画像を歪ませたいんですが・・

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
匿名

画像を歪ませたいんですが・・

#1

投稿記事 by 匿名 » 16年前

画像をグニャグニャさせるサンプルとかを見たんですが、画像の一部だけをグニャグニャするにはどうしたらいいでしょうか?そのままやると境目が目立ってしまうんです。最終的には背景に水面に石を落した時のような変化をつけてみたいんですが・・

朽木

Re:画像を歪ませたいんですが・・

#2

投稿記事 by 朽木 » 16年前

>水面に石を落した時のような―

ググってみると、参考になりそうなサイトがいくつかあったので、そちらを見てみてはいかがでしょうか。

下に、私が検索して「関係ありそうだなー」って思ったページを挙げてみました。

1.JavaApplet
ttp://oshiete1.goo.ne.jp/qa2551462.html
で、単純(私は理解できなかったけど@@;)な方法で解決しようとしている書き込みがあります。

2.ActionScript
ttp://sakeprog.cocolog-nifty.com/sake/2008/06/post_296b.html

3.C++(Direct3D)
ttp://www.shader.jp/xoops/html/modules/wordpress/index.php?p=97
ttp://www.shader.jp/xoops/html/modules/wordpress/index.php?p=208
Shader.jpを検索してみたら面白そうなものがありました。これが一番参考になるのではないでしょうか。

(※ごめんなさい、画像変形サンプルあるし、一部だけってのを全然読んでませんでした。)

匿名

Re:画像を歪ませたいんですが・・

#3

投稿記事 by 匿名 » 16年前

ありがとうございます。
さっそく見てみます。

匿名

Re:画像を歪ませたいんですが・・

#4

投稿記事 by 匿名 » 16年前

・・さて、見てみたのですが。
やはりこれは一筋縄ではいかないようですね。
Cで書かれているサンプルがあまりないようですし・・
さてどうすれば・・
少し考える必要がありますね・・

Justy

Re:画像を歪ませたいんですが・・

#5

投稿記事 by Justy » 16年前

 環境もそうですし、どのサンプルの話なのかもわからないので、
何とも答えようがないのですが。



>画像をグニャグニャさせるサンプルとかを見たんですが、
>画像の一部だけをグニャグニャするにはどうしたらいいでしょうか

 そのサンプルを改良して影響範囲を制限するだけでできるのでは?

匿名

Re:画像を歪ませたいんですが・・

#6

投稿記事 by 匿名 » 16年前

う~ん、まあそうなんですけど。
DXライブラリのサンプルとかならいいんですが。
さすがに言語が違うと理解できないので改良できないんですよね・・

Justy

Re:画像を歪ませたいんですが・・

#7

投稿記事 by Justy » 16年前

 DXライブラリということなら、いくつか手はありますが、
図のように絵を細かく分割して頂点を増やし、必要な頂点をぐにゃぐにゃ操作して、
DrawPolygonBase()で一気に描画というのがオーソドックスな方法ではないかと思います。

 別解としては、管理人さん作のサンプル
ttp://dixq.net/sm/d5.html
のような方法もあります。

匿名

Re:画像を歪ませたいんですが・・

#8

投稿記事 by 匿名 » 16年前

これは良いですね、まさにこんな風に歪ませたかったんですよ。
サンプルがあったら見せてください。
ところでDrawPolygonBase関数ってどんな関数ですか?
検索しても見つからなかったんですが・・

Dixq (管理人)

Re:画像を歪ませたいんですが・・

#9

投稿記事 by Dixq (管理人) » 16年前

DXライブラリは非公開関数が結構多いです。
DXライブラリで使っている関数はヘッダファイルにかいてあるもので全てですから、
公開されていないファイルはヘッダファイルで検索してみて下さい。

匿名

Re:画像を歪ませたいんですが・・

#10

投稿記事 by 匿名 » 16年前

確かにヘッダファイルにありましたね、DrawPolygonBase関数

DrawPolygonBase( VERTEX *Vertex, int VertexNum, int PrimitiveType, int GrHandle, int TransFlag ) ;

注釈には2Dポリゴンを描画すると書かれていますね。
Justyさんの画像を見ると確かに2Dポリゴンぽいですが、これはどうやって使えばいいのでしょうか?
引数から推測すると3Dポリゴンの様にVERTEX *Vertexは頂点・・ですかね。
VertexNumはポリゴンの数、PrimitiveTypeはポリゴンを敷き詰めるパターン・・かな?
GrHandleはポリゴンに使う画像、TransFlagは透過フラグってところですかね?
この関数は結構使えそうなのでぜひとも使い方を教えてください。
あとどこかでサンプルプログラムとかが公開されていたら教えてください。

SCI

Re:画像を歪ませたいんですが・・

#11

投稿記事 by SCI » 16年前

同ヘッダ内でVERTEX構造体が定義されていますね。検索すると見つかりますよ。

匿名

Re:画像を歪ませたいんですが・・

#12

投稿記事 by 匿名 » 16年前

えーと、それっぽいのがありました。

// 主に2D描画に使用する頂点データ型(公開用)
typedef struct tagVERTEX
{
float x, y ;
float u, v ;
unsigned char b, g, r, a ;
} VERTEX ;

3Dポリゴンの時のようにポリゴンの数×3個、配列で用意すればOK・・かな?
変数名は3Dと同じようなので、yは下が0となるのでしょうか?
uとvは画像の使う場所のようですが、絵を細かく分割しますから(0,0),(0,1),(1,0),(0,1),(1,0),(1,1)みたいな順番で代入していくんでしょうか?
そういえばGrHandleは多分画像ハンドルだと思うのですが、絵は分割されてますから複数になりますよね・・画像ハンドルを渡すと関数内で分割してくれるんでしょうか?

飲み込みが悪くてすいませんが、長い目で見てください。

SCI

Re:画像を歪ませたいんですが・・

#13

投稿記事 by SCI » 16年前

実際にコードを打ってテストするのが一番早いのですが(笑)
私はこの関数を使ったことはありませんが、ほとんどDirectXに渡すデータそのものの感じがします。
uvはテクスチャ座標です。
GrHandleはテクスチャに使う画像ハンドルでしょう。
分割とか複数とかが何を言いたいのか分かりませんが、普通にuvで指定した範囲をポリゴンのテクスチャとして設定するものかと思いますよ。
何より、実際にプログラムを作ってみてください(私が作ってもいいのだけれど・・・

匿名

Re:画像を歪ませたいんですが・・

#14

投稿記事 by 匿名 » 16年前

そうなんですけど引数の意味がわからないとプログラムの作りようが・・

分割とか複数とかは、

>>図のように絵を細かく分割して頂点を増やし、必要な頂点をぐにゃぐにゃ操作して、
>>DrawPolygonBase()で一気に描画というのがオーソドックスな方法ではないかと思います。

と言うわけでDrawPolygonBase関数にグラフィックハンドルを渡せば関数内で分割して描画してくれる・・ならいいんですが、そうでない場合グラフィックハンドルは一枚ずつ渡さないといけないのかなって事です。
まあ一気に描画って言うぐらいだから関数内で分割してくれるのかな?

Justy

Re:画像を歪ませたいんですが・・

#15

投稿記事 by Justy » 16年前


>サンプルプログラムとかが公開されていたら教えてください

 さわりだけ。

[color=#d0d0ff" face="monospace]
int image = LoadGraph("xxxx.png");
VERTEX v[/url] =
{
{ 0, 0, 0, 0, 255, 0, 255, 255 },
{ 0, 300, 0, 1, 255, 0, 255, 255 },
{ 300, 0, 0.5f, 0, 255, 255, 255, 255 },
{ 300, 300, 0.5f, 1, 255, 255, 255, 255 },
{ 500, 0, 1, 0, 0, 255, 255, 255 },
{ 500, 300, 1, 1, 0, 255, 255, 255 },
};
DrawPolygonBase(v, 6, DX_PRIMTYPE_TRIANGLESTRIP, image, 0);
[/color]



>まあ一気に描画って言うぐらいだから関数内で分割してくれるのかな?

 そのための u, vです。

 あぁ、1点修正が。
 一気に、とは書きましたが、実際にはすべてをストリップにつなげるのは
ちょっと厄介なので、何回~何十回か呼ぶ必要がありそうです。

匿名

Re:画像を歪ませたいんですが・・

#16

投稿記事 by 匿名 » 16年前

ああなるほど、渡したグラフィックハンドルのどの部分を使うかをu, vで座標ごとに指定しているわけですね。
後わからない所は・・DX_PRIMTYPE_TRIANGLESTRIPの意味がわからないです。

Justy

Re:画像を歪ませたいんですが・・

#17

投稿記事 by Justy » 16年前

 DXライブラリではないですが。

プリミティブタイプ Mi-ko's FriendlySpace
ttp://mi-ko.cocoa.cx/programming/directx/directgraphics/FVF/directgraphics_01.html

SCI

Re:画像を歪ませたいんですが・・

#18

投稿記事 by SCI » 16年前

とりあえず、簡単にテスト用として。
頂点の数だけVERTEXを用意します。
頂点の位置、uv座標をいろいろ変えると、いわゆる「変形」になりますね。
頂点カラーはテクスチャカラーと乗算です。
プリミティブタイプはJustyさんの言うとおりで、DirectXで調べるといいですね。

匿名

Re:画像を歪ませたいんですが・・

#19

投稿記事 by 匿名 » 16年前

トライアングルストリップですか、
意味は・・テクスチャに隙間ができないようにするんでしょうか?
後は変形ですけど・・座標を手打ちで入力するわけにはいかないし、そもそもどう変えればいいのかもわからないし、やっぱり何か物理学的な式とかで計算しないといけないんでしょうか?

匿名

Re:画像を歪ませたいんですが・・

#20

投稿記事 by 匿名 » 16年前

Justyさんの画像から察すると、中心に近いほど大きく、外側に行くほど小さく変形すればいいみたいですね。
それを表現する計算式は・・ちょっと思いつかないですね。

SCI

Re:画像を歪ませたいんですが・・

#21

投稿記事 by SCI » 16年前

適当に作ってみましたが、こんな感じですか?
これは、xy平面上の0~10の正方形の中に、0.1刻みで点を用意し、一部を半球面(Justyさんの画像)っぽく変換を施してプロットしたものです。
速度やアルゴリズムを最適化するにはそれなりの学術的知識が必要になるのでしょうが、なんとなくそれっぽくでもこんな感じになりますね。

Justy

Re:画像を歪ませたいんですが・・

#22

投稿記事 by Justy » 16年前


>座標を手打ちで入力するわけにはいかないし

 まずは普通に規則正しく座標が並んだデフォルトの座標を求めるので、
x軸、y軸の for二重ループで計算できます。



>そもそもどう変えればいいのかもわからないし

 いろいろやり方があり、処理内容によって微妙に異なりますが、おおむね

1デフォルトの座標・UV座標を計算する
2デフォルトの座標・UV座標からのオフセット(何らかの計算)で歪ませる
3トライアングルストリップ構築~描画

 という流れでいいかと思います。

 1は最初の1回のみで、後は2と3を毎フレーム繰り返すことになります。

匿名

Re:画像を歪ませたいんですが・・

#23

投稿記事 by 匿名 » 16年前

SCIさんの画像は確かにそれっぽく見えますね。
変換する時の点の座標はどうやって求めたんですか?
そういえばJustyさんの画像も綺麗に歪んでいますけど、あれはどうやったんでしょうか?

SCI

Re:画像を歪ませたいんですが・・

#24

投稿記事 by SCI » 16年前

イメージとしては「平面の上に半球を置き、平面を引き伸ばして半球の内側にくっつける」です。「魚眼レンズ」が一番近いですね。
つまり、半径の上の中点は半球に沿った半円周上でも中点です。
それを、中心から対象の点に向かうベクトル方向に対して考えて、平面上に正射影したと考えればいいかと。
射影変換だったか、アフィン変換だったか・・・よく分かりませんが・・・
r↑ = (x - x0, y - y0)
θ = (π/2) * (|r↑|/R)
r' = Rsinθ
x' = r'cosφ + x0
y' = r'sinφ + y0
(φ = arg(r↑))
ホントにこれでいいのかは知りませんが。
これが半楕円面やその他の曲線に対する変換(波紋とか)だと、より一般的な変換を考えなければなりません。

この画像では格子点数(ポリゴンの頂点に相当)がかなり多いので境界がはっきりしていますが、ポリゴンの数を荒くすればJustyさんの画像に近づくと思います。

匿名

Re:画像を歪ませたいんですが・・

#25

投稿記事 by 匿名 » 16年前

お、おお・・やはり複雑な式が必要みたいですね。
でも一度数値を代入してしまえば、ループの中でDrawPolygonBase関数を呼ぶだけですから、できない事も無さそうですね。
しかし数学は苦手なので、ちょっと式の文字の意味がわからないですね・・
これをプログラムでやるとすると、どういう風に書けばいいんでしょうか?

SCI

Re:画像を歪ませたいんですが・・

#26

投稿記事 by SCI » 16年前

あまりいいコードではありませんが・・・
#include <stdio.h>
#include <math.h>

int main(void)
{
	//中心と半径
	const double cx = 5.0, cy = 5.0, r = 3.0;
	
	//元座標
	double x, y;
	
	//変換後の、中心からの距離と座標
	double r1, x1, y1;
	
	//中心からの距離(の平方)、偏角
	double d, ang;
	
	FILE *fp = fopen("data.txt", "w");
	
	for (x = 0.0; x < 10.0; x += 0.5)
	{
		for (y = 0.0; y < 10.0; y += 0.5)
		{
			d = (x - cx) * (x - cx) + (y - cy) * (y - cy);
			if (d < r * r && y - cy != 0.0 && x - cx != 0.0)
			{
				ang = atan2(y - cy, x - cx);
				r1 = r * sin(M_PI * sqrt(d) / (2.0 * r));
				x1 = cx + r1 * cos(ang);
				y1 = cy + r1 * sin(ang);
			}
			else
			{
				x1 = x;
				y1 = y;
			}
			fprintf(fp, "%.8f %.8f\n", x1, y1);
		}
	}
	fclose(fp);
	return 0;
}
上のプロットを生成するために使ったコードを、少し修正したものです。
当たり半径を半球の範囲より小さくすると、膨張を浅くすることができますね。
ただ、この方法をゲーム(に限らず)の描画処理に速度的に使えるかどうかは分かりません。

数式についてはかなり簡単な部類だと思いますよ。
今回は画像処理ではなく、比較的簡単な図形を幾何学的に点を移動させているだけなので。

それはそうと、今更ですが
>そのままやると境目が目立ってしまうんです。
これをちょっと見てみたいのですが・・・

匿名

Re:画像を歪ませたいんですが・・

#27

投稿記事 by 匿名 » 16年前

こんな感じでしょうかね、境目が目立ってすごい事になってます。

プログラムは
#include "DxLib.h"

#include <math.h>

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){
ChangeWindowMode(TRUE);SetOutApplicationLogValidFlag( FALSE );
if(DxLib_Init() == -1 || SetDrawScreen( DX_SCREEN_BACK )!=0) return -1;//初期化と裏画面化

int img = LoadGraph("aa.png");//画像をロード

DrawGraph( 0 , 0 , img , FALSE ) ;//画像を描画

	for( int i=0;i<200;i++ ){

	SetDrawArea( 50 , 100+i , 250 , 101+i );//描画可能領域のセット

	DrawGraph( sin((float)i/20)*50 , 0 , img , FALSE ) ;//sin波で左右に揺らしながら一列づつ画像を描画

	}

ScreenFlip();//表画面に反映

WaitKey();//キーの入力待ち

DxLib_End();
return 0;

}
こんな感じです。

ところでSCIさんのサンプルですが

Error: 外部シンボル 'WinMain' が未解決(C:\BORLAND\BCC55\LIB\C0W32.OBJ が参照)

が出るので、少し変えて実行してみたら、見事に数値が出力されました。
しかし・・fwrite関数とかは使えるようになったんですが
fprintf関数とかはまだ使い方を覚えてないんですよね・・
だからこのままだと求めた数値を有効利用できないので
すみませんがファイルを使わないで
VERTEX構造体に直接座標を代入して描画するようなサンプルを作っていただけないでしょうか?

SCI

Re:画像を歪ませたいんですが・・

#28

投稿記事 by SCI » 16年前

なるほど、1列ずつずらしながら描画していますね。

>Error: 外部シンボル 'WinMain' が未解決(C:\BORLAND\BCC55\LIB\C0W32.OBJ が参照)
あのコードは座標の数値を出力するだけの「コンソールアプリ」なので、設定を「コンソールアプリケーション」にするとコンパイルできます。

>だからこのままだと求めた数値を有効利用できないので
あのサンプルでは、出力した数値を別のグラフソフト(gnuplot)でプロットしました。

頂点データを使ったものも作ってみました。
コードは修正してから載せるのでちょっと待っててください(汗

SCI

Re:画像を歪ませたいんですが・・

#29

投稿記事 by SCI » 16年前

それから、DxLibの3D機能を使えば、座標変換が少し簡単になります。
正射影の部分はDxLibの3Dポリゴン処理で勝手にやってくれるので(笑

匿名

Re:画像を歪ませたいんですが・・

#30

投稿記事 by 匿名 » 16年前

そういえばそうでしたね。
設定と言う機能があったのを忘れていました・・

SCI

Re:画像を歪ませたいんですが・・

#31

投稿記事 by SCI » 16年前

うーん、微妙・・・

射影変換をDxLib(というかDirectX)に任せると、デフォルトでは画面中心に向くので、膨らみの角度もそれに伴って変わりますね。

奥行きの歪みじゃなくて、上の横波のような歪みを滑らかに作るには、また別の変換式を考えなければなりません。
DirectXならシェーダを使うとか(全然知らないけど)ありますが・・・

匿名

Re:画像を歪ませたいんですが・・

#32

投稿記事 by 匿名 » 16年前

上の画像は境目がどんな感じで目立つかを見せるための物ですから
実際はJustyさんとSCIさんの画像のように歪めばいいんですけど
確かに普通に描画すると画面中心によってしまいますよね。
私も以前それで失敗した事があります。
デフォルトではって事は何か変える方法があるのでしょうか?

SCI

Re:画像を歪ませたいんですが・・

#33

投稿記事 by SCI » 16年前

>確かに普通に描画すると画面中心によってしまいますよね。
>私も以前それで失敗した事があります。
>デフォルトではって事は何か変える方法があるのでしょうか?

ん、何か勘違いしていませんか?
「中心に向く」というのは、無限遠点が画面中心にあるということです。
この辺は、3Dグラフィックスのビュー変換、透視変換に関する話です。これが原因の失敗というのが思いつかないのですが・・・

DrawPolygon3Dではなく、DrawPolygonBaseで2D座標のみを扱う場合、正射影も自分で計算します。
その場合、無限遠点は「画面平面の法線」方向なので、膨らみは単純に平行移動します。イメージしづらいとは思いますが・・・
とは言え、この2つの違いは処理速度くらいの差しかないので、表現上は気にしなくてもいいでしょう。

匿名

Re:画像を歪ませたいんですが・・

#34

投稿記事 by 匿名 » 16年前

そうなんですか、無限遠点が画面中心にあると言うのは理解していましたが
2Dもそうなのかと勘違いしてしまいました。
ちなみにどんな失敗をしたかと言うと3Dポリゴンで階段を描画しようとしたら
画面の右の方はスコアボードがあるので階段の中心が画面中心からずれてしまうので
左右の拡大率に差が出てしまったんですよね・・

SCI

Re:画像を歪ませたいんですが・・

#35

投稿記事 by SCI » 16年前

なるほど、そういうことでしたか。

匿名

Re:画像を歪ませたいんですが・・

#36

投稿記事 by 匿名 » 16年前

でも、四聖龍神録とかだと真っ直ぐに描画されているんですよね。
あれも3Dポリゴンだと思いますけど、何か無限遠点の位置を変更する方法でもあるのかな?

Justy

Re:画像を歪ませたいんですが・・

#37

投稿記事 by Justy » 16年前

ビューポートの指定をしているからじゃないでしょうか。
そういう関数もあったはずですから。

SCI

Re:画像を歪ませたいんですが・・

#38

投稿記事 by SCI » 16年前

>匿名さん
なんか「真っ直ぐ」の認識が食い違っていますね(笑
3Dについては透視点とか射影変換を復習してみてください。
座標変換を自前でやる場合、そこに3Dの概念は存在しないので、ビュー変換自体が意味を持ちません。
立体の絵を平面に手描きする感じです。透視点を意識して描かない限り、一貫した消失点が存在している必要はありません。

本題に戻りますが、歪みの件は方向性が見えてきましたか?

匿名

Re:画像を歪ませたいんですが・・

#39

投稿記事 by 匿名 » 16年前

そうですね、真っ直ぐじゃなくて左右対称ですね。

歪みの件ですがDrawPolygonBase関数の使い方は大体わかってきました。
しかし色々な数値をうまく代入していくのが難しいですね。
SCIさんに教えてもらった変形の式はちょっと理解に手こずっています。
画像のどの部分と対応しているかはわかりますが、うまくDrawPolygonBase関数に値を渡せません。

SCI

Re:画像を歪ませたいんですが・・

#40

投稿記事 by SCI » 16年前

>しかし色々な数値をうまく代入していくのが難しいですね。
どのような順序で頂点をつなぐかにも寄りますが、うまく数列の一般項を定めれば多少まとまりますね。
ちなみにNo:31148の画像はDrawPolygon3Dを使ってます。
膨張も、すべて座標変換するのではなく、高さを計算してz座標を変化させています。

>SCIさんに教えてもらった変形の式はちょっと理解に手こずっています。
三角関数とベクトルで考えるしか(笑
あ、作図しないとイメージは難しいかも知れません。

匿名

Re:画像を歪ませたいんですが・・

#41

投稿記事 by 匿名 » 16年前

まあ、式の意味がわからなくてもできない事はないと思いますが・・
ちなみにSCIさんのサンプルで出した値を構造体に代入して描画するプログラムを作っては見たんですが、
実行結果が↑です。完全に迷走状態ですね、何で背景が消えてるんだろう・・

プログラムはこんな感じです。
即席ですのでちょっと雑・・
#include "DxLib.h"

#include <math.h>

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){
ChangeWindowMode(TRUE);SetOutApplicationLogValidFlag( FALSE );
if(DxLib_Init() == -1 || SetDrawScreen( DX_SCREEN_BACK )!=0) return -1;//初期化と裏画面化

int img = LoadGraph("aa.png");//画像をロード

int GHandle = MakeGraph( 300 , 300 );//空のグラフィックを作成

int X=200,Y=240;//描画する中心をセット

VERTEX v[400];//構造体の宣言

	//中心と半径
	const double cx = 5.0, cy = 5.0, r = 3.0;
	
	//元座標
	double x, y;
	
	//変換後の、中心からの距離と座標
	double r1, x1, y1;
	
	//中心からの距離(の平方)、偏角
	double d, ang;

DrawGraph( 0 , 0 , img , FALSE ) ;//背景を描画

GetDrawScreenGraph( X-150 , Y-150 , X+150 , Y+150 , GHandle );//背景の一部をキャプチャ

	for (x = 0.0; x < 10.0; x += 0.5)
	{
		for (y = 0.0; y < 10.0; y += 0.5)
		{
			d = (x - cx) * (x - cx) + (y - cy) * (y - cy);
			if (d < r * r && y - cy != 0.0 && x - cx != 0.0)
			{
				ang = atan2(y - cy, x - cx);
				r1 = r * sin(M_PI * sqrt(d) / (2.0 * r));
				x1 = cx + r1 * cos(ang);
				y1 = cy + r1 * sin(ang);
			}
			else
			{
				x1 = x;
				y1 = y;
			}

			v[(int)(x*2)*20+(int)(y*2)].x=X-150+300/19*(x1*2);
			v[(int)(x*2)*20+(int)(y*2)].y=Y-150+300/19*(y1*2);
			v[(int)(x*2)*20+(int)(y*2)].u=x/10;
			v[(int)(x*2)*20+(int)(y*2)].v=y/10;
			v[(int)(x*2)*20+(int)(y*2)].b=255;
			v[(int)(x*2)*20+(int)(y*2)].g=255;
			v[(int)(x*2)*20+(int)(y*2)].r=255;
			v[(int)(x*2)*20+(int)(y*2)].a=255;

		}

	DrawPolygonBase(v, 400, DX_PRIMTYPE_TRIANGLESTRIP, GHandle, 0);//画像を描画

	}

ScreenFlip();//表画面に反映

WaitKey();//キーの入力待ち

DxLib_End();
return 0;

}

Mist

Re:画像を歪ませたいんですが・・

#42

投稿記事 by Mist » 16年前

歪みとは関係ないけど

> if(DxLib_Init() == -1 || SetDrawScreen( DX_SCREEN_BACK )!=0) return -1;//初期化と裏画面化

これはダメです。
DxLib_Initで成功して、SetDrawScreenに失敗した場合にDxLib_Endしないで終了してしまいます。

Justy

Re:画像を歪ませたいんですが・・

#43

投稿記事 by Justy » 16年前


>プログラムはこんな感じです

 以前書いた[url]http://www.play21.jp/board/formz.cgi?action=res&resno=30740&page=&id=dixq&rln=31274#31099回答[/url]の手順のうち、1と2は行っていますが、
3の前半「トライアングルストリップ」の構築ができていません。

 トライアングルストリップはどういうものなのか(どういう順番で座標リストを作るのか)、
図を引いたりしてもう一度見直してみた方がいいかと思います。

SCI

Re:画像を歪ませたいんですが・・

#44

投稿記事 by SCI » 16年前

>まあ、式の意味がわからなくてもできない事はないと思いますが・・
できるのなら、私はもう何も言えませんね。

匿名

Re:画像を歪ませたいんですが・・

#45

投稿記事 by 匿名 » 16年前

しかし、やはり難しいようですね。
for (x = 0.0; x < 10.0; x += 0.5)
{
	for (y = 0.0; y < 10.0; y += 0.5)}
から縦横20個に分けていると解釈して構造体を20×20で400個用意して、
for文の値から画像のどの点に対応しているか代入したつもりですが、
よく考えたらトライアングルストリップの説明に「三角形を並べて図形を作る」って書いてあったような・・
このプログラムだと座標を格子状に並べていますから、こうなるのも当然かも、全然三角形を作ってないし・・

すみません、やっぱり自分一人じゃ無理です・・

Justy

Re:画像を歪ませたいんですが・・

#46

投稿記事 by Justy » 16年前


>やはり難しいようですね

 慣れてしまえばそれほど難しいものではないのですが,
まずは単純な3つか4つくらいの頂点のトライアングルストリップを
作っていろいろいじって慣れてください。

 それからでないと、いきなりグリッド状のストリップを作るのは
難しいかもしれません。



>構造体を20×20で400個用意して、
>for文の値から画像のどの点に対応しているか代入

したのなら、あとはその情報を元にトライアングルストリップを構築するだけです。

 まずは添付の図のような順番で横方向に頂点情報を作ります。
 横一列分の頂点リストができあがったのなら、そのリストを DrawPolygonBase()に
流し込みます。
 それが終わったら次の列を処理します。

 それを縦の列の数の分だけ繰り返せば、完了です。


 あと、

[color=#d0d0ff" face="monospace]
for (x = 0.0; x < 10.0; x += 0.5) // 座標でループ
{
for (y = 0.0; y < 10.0; y += 0.5)}
[/color]

 こういう浮動小数点数を使ったループではなく、
きちんと分割数を定義して
[color=#d0d0ff" face="monospace]
for(int y=0; y<=NumY; ++y) // 分割数でループ
{
for(int x=0; x<=NumX; ++x)
[/color]

 のようなループとした方が、配列の参照するインデックスを求めたりするのは勿論、
UV値を求めるとき等、計算しやすくなるかと思います。

匿名

Re:画像を歪ませたいんですが・・

#47

投稿記事 by 匿名 » 16年前

確かに図にするとわかりやすいですね。
こんな風に頂点をジグザグに配置していけばいいんですか、私完全に直線状に配置してました・・

匿名

Re:画像を歪ませたいんですが・・

#48

投稿記事 by 匿名 » 16年前

・・でもよく考えたらSCIさんのサンプルは二重ループですから、やはり式の意味を理解しないとトライアングルストリップを構築できませんね・・

匿名

Re:画像を歪ませたいんですが・・

#49

投稿記事 by 匿名 » 16年前

ちょっと一筋縄では行かないので、トライアングルストリップの練習をしてみました。
#include "DxLib.h"

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){
ChangeWindowMode(TRUE);SetOutApplicationLogValidFlag( FALSE );
if(DxLib_Init() == -1 || SetDrawScreen( DX_SCREEN_BACK )!=0) return -1;//初期化と裏画面化

int GHandle = LoadGraph("aa.png");//画像をロード

VERTEX v[3];//構造体の宣言

	v[0].x=100;
	v[0].y=100;
	v[0].u=0;
	v[0].v=0;
	v[0].b=255;
	v[0].g=255;
	v[0].r=255;
	v[0].a=255;

	v[1].x=200;
	v[1].y=100;
	v[1].u=1;
	v[1].v=0;
	v[1].b=255;
	v[1].g=255;
	v[1].r=255;
	v[1].a=255;

	v[2].x=200;
	v[2].y=200;
	v[2].u=1;
	v[2].v=1;
	v[2].b=255;
	v[2].g=255;
	v[2].r=255;
	v[2].a=255;

DrawPolygonBase(v, 3, DX_PRIMTYPE_TRIANGLESTRIP, GHandle, 0);//画像を描画

ScreenFlip();//表画面に反映

WaitKey();//キーの入力待ち

DxLib_End();
return 0;

}
よく考えたらトライアングルストリップなんだから頂点は三個一組で用意するべきでしたね・・
3Dポリゴンの時のように「画像は2の乗数サイズしか使用出来ない」とか「取り込んだ画像は正常に描画されない」みたいな心配もありますが、一応うまく描画されました。
ここからフィールドを構築・・できるだろうか?

匿名

Re:画像を歪ませたいんですが・・

#50

投稿記事 by 匿名 » 16年前

とりあえず描画はできましたが、上下左右の端が不自然になってしまいました。
このままだと無駄な処理が多すぎるので、何とか簡略化したいんですが・・
<#include "DxLib.h"

#include <math.h>

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){
ChangeWindowMode(TRUE);SetOutApplicationLogValidFlag( FALSE );
if(DxLib_Init() == -1 || SetDrawScreen( DX_SCREEN_BACK )!=0) return -1;//初期化と裏画面化

	int img = LoadGraph("aa.png");//画像をロード

	VERTEX v[40];//構造体の宣言

	//中心と半径
	const double cx = 5.0, cy = 5.0, r = 3.0;

	//元座標
	double x, y;

	//変換後の、中心からの距離と座標
	double r1, x1, y1;

	//中心からの距離(の平方)、偏角
	double d, ang;

	for (x = 0.0; x < 10.0; x += 0.5){

		for (y = 0.0; y < 10.0; y += 0.5){

			d = (x - cx) * (x - cx) + (y - cy) * (y - cy);

			if (d < r * r && y - cy != 0.0 && x - cx != 0.0){

				ang = atan2(y - cy, x - cx);
				r1 = r * sin(M_PI * sqrt(d) / (2.0 * r));
				x1 = cx + r1 * cos(ang);
				y1 = cy + r1 * sin(ang);
			}

			else{
				x1 = x;
				y1 = y;
			}

			v[(int)(y*4)].x=x1*50;
			v[(int)(y*4)].y=y1*50;
			v[(int)(y*4)].u=x/10;
			v[(int)(y*4)].v=y/10;
			v[(int)(y*4)].b=255;
			v[(int)(y*4)].g=255;
			v[(int)(y*4)].r=255;
			v[(int)(y*4)].a=255;

			x+=0.5;

			d = (x - cx) * (x - cx) + (y - cy) * (y - cy);

			if (d < r * r && y - cy != 0.0 && x - cx != 0.0){

				ang = atan2(y - cy, x - cx);
				r1 = r * sin(M_PI * sqrt(d) / (2.0 * r));
				x1 = cx + r1 * cos(ang);
				y1 = cy + r1 * sin(ang);
			}

			else{
				x1 = x;
				y1 = y;
			}

			v[(int)(y*4)+1].x=x1*50;
			v[(int)(y*4)+1].y=y1*50;
			v[(int)(y*4)+1].u=x/10;
			v[(int)(y*4)+1].v=y/10;
			v[(int)(y*4)+1].b=255;
			v[(int)(y*4)+1].g=255;
			v[(int)(y*4)+1].r=255;
			v[(int)(y*4)+1].a=255;

			x-=0.5;

		}

	DrawPolygonBase(v, 40, DX_PRIMTYPE_TRIANGLESTRIP, img, 0);//画像を描画

	}

ScreenFlip();//表画面に反映

WaitKey();//キーの入力待ち

DxLib_End();
return 0;

}
あと、2Dポリゴンでも画像は2の乗数サイズしか使用出来ないようですね・・

匿名

Re:画像を歪ませたいんですが・・

#51

投稿記事 by 匿名 » 16年前

上のプログラムを少し改良してみました。
その結果、歪んでいる部分が画面からはみ出ると描画できなくなるという問題が出てきました。
これはどうやったら解決できるか分からないので、何か方法があったら教えてください。
あと、静止画だと分かりにくいのでちょっと適当な画像で実行してみてください。
#include "DxLib.h"

#include <math.h>



int count=0;

void wait_fanc(){
    int term;
    static int t=0;
    term = GetNowCount()-t;
    if(16-term>0)
            Sleep(16-term);
    t=GetNowCount();
    return;
}



void fps(){
    int i;
    static int t=0,ave=0,f[60];

    f[count%60]=GetNowCount()-t;
    t=GetNowCount();
    if(count%60==59){
        ave=0;
        for(i=0;i<60;i++)
            ave+=f;
        ave/=60;
    }
    if(ave!=0){
        DrawFormatString(350,250,GetColor(255,255,255),"%.1fFPS",1000.0/(double)ave);
    }
    return;
}



int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){
ChangeWindowMode(TRUE);SetOutApplicationLogValidFlag( FALSE );
if(DxLib_Init() == -1 || SetDrawScreen( DX_SCREEN_BACK )!=0) return -1;//初期化と裏画面化

	int img = LoadGraph("aa.png");//画像をロード

	int GHandle = MakeGraph( 256 , 256 );//空のグラフィックを作成

	int X=100,Y=100;

	float Count=0,CountX=0,CountY=0;

	VERTEX v[40];//構造体の宣言

	//中心と半径
	const double cx = 5.0, cy = 5.0, r = 5.0;

	//元座標
	double x, y;

	//変換後の、中心からの距離と座標
	double r1, x1, y1;

	//中心からの距離(の平方)、偏角
	double d, ang;

	char Key[256];

	while(!ProcessMessage() && !ClearDrawScreen() && !GetHitKeyStateAll( Key ) && !Key[KEY_INPUT_ESCAPE]){

		DrawGraph( 0 , 0 , img , FALSE ) ;//背景を描画

		fps();

		GetDrawScreenGraph( X , Y , X+256 , Y+256 , GHandle );//背景の一部をキャプチャ

		CountX=0;

		for (x = 0.0; x < 10.0; x += 0.5){

			CountY=0;

			for (y = 0.0; y < 10.0; y += 0.5){

				d = (x - cx) * (x - cx) + (y - cy) * (y - cy);

				if ( d < r * r && ( y - cy != 0.0 || x - cx != 0.0 ) ){

					ang = atan2(y - cy, x - cx);
					r1 = r * sin(M_PI * sqrt(d) / (2.0 * r));
					x1 = cx + r1 * cos(ang);
					y1 = cy + r1 * sin(ang);
				}

				else{
					x1 = x;
					y1 = y;
				}

				v[(int)(y*4)].x=X+x1*25.6;
				v[(int)(y*4)].y=Y+y1*25.6;

				if ( d < r * r ){
				v[(int)(y*4)].u=x/10+cos(Count+CountX)/80;
				v[(int)(y*4)].v=y/10+sin(Count+CountY)/80;
				v[(int)(y*4)].b=255-(50-d)*2;
				v[(int)(y*4)].g=255-(50-d)*2;
				}

				else{
				v[(int)(y*4)].u=x/10;
				v[(int)(y*4)].v=y/10;
				v[(int)(y*4)].b=255;
				v[(int)(y*4)].g=255;
				}

				v[(int)(y*4)].r=255;
				v[(int)(y*4)].a=255;

				x+=0.5;

				d = (x - cx) * (x - cx) + (y - cy) * (y - cy);

				if ( d < r * r && ( y - cy != 0.0 || x - cx != 0.0 ) ){

					ang = atan2(y - cy, x - cx);
					r1 = r * sin(M_PI * sqrt(d) / (2.0 * r));
					x1 = cx + r1 * cos(ang);
					y1 = cy + r1 * sin(ang);
				}

				else{
					x1 = x;
					y1 = y;
				}

				v[(int)(y*4)+1].x=X+x1*25.6;
				v[(int)(y*4)+1].y=Y+y1*25.6;

				if ( d < r * r ){
				v[(int)(y*4)+1].u=x/10+cos(Count+CountX)/80;
				v[(int)(y*4)+1].v=y/10+sin(Count+CountY)/80;
				v[(int)(y*4)+1].b=255-(50-d)*2;
				v[(int)(y*4)+1].g=255-(50-d)*2;
				}

				else{
				v[(int)(y*4)+1].u=x/10;
				v[(int)(y*4)+1].v=y/10;
				v[(int)(y*4)+1].b=255;
				v[(int)(y*4)+1].g=255;
				}

				v[(int)(y*4)+1].r=255;
				v[(int)(y*4)+1].a=255;

				x-=0.5;

				CountY+=0.5;

			}

		DrawPolygonBase(v, 40, DX_PRIMTYPE_TRIANGLESTRIP, GHandle, 0);//画像を描画

		CountX+=0.5;

		}

		count++;
		ScreenFlip();
		wait_fanc();

		if( Key[ KEY_INPUT_UP     ]  == 1 )Y-=3;
		if( Key[ KEY_INPUT_LEFT   ]  == 1 )X-=3;
		if( Key[ KEY_INPUT_DOWN   ]  == 1 )Y+=3;
		if( Key[ KEY_INPUT_RIGHT  ]  == 1 )X+=3;

//		if( X<0   )X=0;
//		if( X>384 )X=384;
//		if( Y<0   )Y=0;
//		if( Y>223 )Y=223;

		Count+=0.05;

	}

DxLib_End();
return 0;

}

Justy

Re:画像を歪ませたいんですが・・

#52

投稿記事 by Justy » 16年前


>歪んでいる部分が画面からはみ出ると描画できなくなるという

 それはそうです。
 GetDrawScreenGraph()で指定した範囲に画面の外が含まれていると
自動的に補正され画面外を含まない範囲になるよう補正されます。

 その為、得られたグラフィックスは望んだものとは異なるものとなるので
挙動がおかしくなるのではないでしょうか。

 試しに、DrawPolygonBase()をやめて、普通に DrawGraph()で GHandleを
表示してみてください。

匿名

Re:画像を歪ませたいんですが・・

#53

投稿記事 by 匿名 » 16年前

確かに普通に描画するとよくわかります。
どうやら補正されているというより取り込まれて無いみたいですね。
でも歪んでいる部分が画面からはみ出るパターンも作りたいんですよね・・
何か方法はないでしょうか?

SCI

Re:画像を歪ませたいんですが・・

#54

投稿記事 by SCI » 16年前

コードを試してないんでよく分かってませんが、こういう状態でしょうか。
歪んだ部分は左の画面外に出ています。

Justy

Re:画像を歪ませたいんですが・・

#55

投稿記事 by Justy » 16年前


>取り込まれて無いみたいですね

 あー、エラーになって更新されないわけですね。



>でも歪んでいる部分が画面からはみ出るパターンも作りたいんですよね・

 今の方法って、何かしらの背景を表示したら、GetDrawScreenGraph()で必要な部分を切り取って
動かない部分はDrawGraphで、動く部分は DrawPolygonBase()で行っているわけですよね?

 画面から切り取るときの座標を必ず画面内におさまるよう調整してあげれば
できなくもないですが、手っ取り早いのは画面全体をとりこんで、そのすべてをグリッド化、
必要なとこだけ頂点情報をいじって表示すればいいんじゃないでしょうか。

ttp://www.play21.jp/board/formz.cgi?action=res&resno=30740&page=&id=dixq&lognum=#30796
みたいに。

匿名

Re:画像を歪ませたいんですが・・

#56

投稿記事 by 匿名 » 16年前

あれ?動かない部分は頂点を動かしてないだけで背景の時しかDrawGraphは使ってないと思いますけど?

画面全体を取り込んで必要なとこだけ頂点をいじるのは使えそうですね。
ちょっとやってみます。

ところでSCIさんの画像ですが、確かにそんな感じですが、その画像はどうやって作ったんですか?

匿名

Re:画像を歪ませたいんですが・・

#57

投稿記事 by 匿名 » 16年前

と思ったんですが、画面全体のグリッド化はやってみると意外に難しかったです。
これはちょっと時間かかりそうですね・・
あと今の方法だと歪んでいる所と歪んでいない所の境目が目立ってしまうんですよね。
SCIさんの画像みたいに目立たなくするにはどうしたらいいでしょうか?

SCI

Re:画像を歪ませたいんですが・・

#58

投稿記事 by SCI » 16年前

いや、方法は同じはずなので、境界は変わらないと思いますよ。
多分、使う画像によって目立つ場合があるのでは?

匿名

Re:画像を歪ませたいんですが・・

#59

投稿記事 by 匿名 » 16年前

うーん、結構画像に関係なく目立ってます。

とりあえず、画面全体のグリッド化をやってみました。何か表示サイズがおかしいですが、それはともかく
歪んでいる部分が画面の外に出ると画像の端がめくれて元の背景が見えるという問題が発生しました・・
これは・・どうすればいいでしょうか?
#include "DxLib.h"

#include <math.h>

int count=0;

void wait_fanc(){
    int term;
    static int t=0;
    term = GetNowCount()-t;
    if(16-term>0)
            Sleep(16-term);
    t=GetNowCount();
    return;
}

void fps(){
    int i;
    static int t=0,ave=0,f[60];

    f[count%60]=GetNowCount()-t;
    t=GetNowCount();
    if(count%60==59){
        ave=0;
        for(i=0;i<60;i++)
            ave+=f;
        ave/=60;
    }
    if(ave!=0){
        DrawFormatString(577,465,GetColor(255,255,255),"%.1fFPS",1000.0/(double)ave);
    }
    return;
}

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){
ChangeWindowMode(TRUE);SetOutApplicationLogValidFlag( FALSE );
if(DxLib_Init() == -1 || SetDrawScreen( DX_SCREEN_BACK )!=0) return -1;//初期化と裏画面化

	int image = LoadGraph("背景.png"),board = LoadGraph("枠.png");//画像をロード

	int GHandle = MakeGraph( 384 , 448 );//空のグラフィックを作成

	VERTEX v[50];//構造体の宣言

	int X,Y;

	int i;

	//中心と半径
	double cx = 244, cy = 240, r = 100;

	//元座標
	double x, y;

	//変換後の、中心からの距離と座標
	double r1, x1, y1;

	//中心からの距離(の平方)、偏角
	double d, ang;

	char Key[256];

	while(!ProcessMessage() && !ClearDrawScreen() && !GetHitKeyStateAll( Key ) && !Key[KEY_INPUT_ESCAPE]){

		SetDrawArea( 32 , 16 , 416 , 464 );//描画可能領域のセット

		DrawGraph( 32 , 16+count%700 , image , FALSE ) ;//背景を描画

		DrawGraph( 32 , 16+(count%700)-700 , image , FALSE ) ;//背景を描画

		GetDrawScreenGraph( 32 , 16 , 416 , 464 , GHandle );//背景の一部をキャプチャ

		for (y = 16; y < 464; y += 16){



			for (x = 32; x <= 416; x += 16){



				for ( i = 0; i < 2; i++ ){



					y+=16*i;

					d = (x - cx) * (x - cx) + (y - cy) * (y - cy);

					if ( d < r * r && ( y - cy != 0.0 || x - cx != 0.0 ) ){

						ang = atan2(y - cy, x - cx);
						r1 = r * sin(M_PI * sqrt(d) / (2.0 * r));
						x1 = cx + r1 * cos(ang);
						y1 = cy + r1 * sin(ang);
					}

					else{
						x1 = x;
						y1 = y;
					}

					v[(int)(x-32)/8+i].x=x1;
					v[(int)(x-32)/8+i].y=y1;

					if ( d < r * r ){
					v[(int)(x-32)/8+i].u=(x-32)/384;
					v[(int)(x-32)/8+i].v=(y-16)/448;
					}

					else{
					v[(int)(x-32)/8+i].u=(x-32)/384;
					v[(int)(x-32)/8+i].v=(y-16)/448;
					}

					v[(int)(x-32)/8+i].b=255;
					v[(int)(x-32)/8+i].g=255;
					v[(int)(x-32)/8+i].r=255;
					v[(int)(x-32)/8+i].a=255;

					y-=16*i;

				}

			}

		DrawPolygonBase(v, 50, DX_PRIMTYPE_TRIANGLESTRIP, GHandle, 0);//画像を描画

		}

		SetDrawArea( 0 , 0 , 640 , 480 );//描画可能領域のセット

		DrawGraph( 0 , 0 , board , TRUE ) ;//枠を描画

		fps();
		count++;
		ScreenFlip();
		wait_fanc();

		if( Key[ KEY_INPUT_UP     ]  == 1 )cy-=3;
		if( Key[ KEY_INPUT_LEFT   ]  == 1 )cx-=3;
		if( Key[ KEY_INPUT_DOWN   ]  == 1 )cy+=3;
		if( Key[ KEY_INPUT_RIGHT  ]  == 1 )cx+=3;

	}

DxLib_End();
return 0;

}

SCI

Re:画像を歪ませたいんですが・・

#60

投稿記事 by SCI » 16年前

>うーん、結構画像に関係なく目立ってます。
まず「目立つ」の認識が食い違っていますね。私には目立っている(私のものと差がある)ようには見えませんが・・・

>歪んでいる部分が画面の外に出ると画像の端がめくれて元の背景が見える
自身でそのようにプログラムしているので当然の結果です。
何がしたいかにもよるので、一概に「こうすればいい」というのはありませんね。

Justy

Re:画像を歪ませたいんですが・・

#61

投稿記事 by Justy » 16年前


>動かない部分は頂点を動かしてないだけで背景の時しかDrawGraphは使ってないと思いますけど?

 あー、まぁその背景の時の描画がそのまま残っている、ということです。



>あと今の方法だと歪んでいる所と歪んでいない所の境目が目立ってしまうんですよね

 うっすらとしか見えないのですが、四角い境目のことですか?
 ひょっとしたら x, y座標ともに 0.5を引いたら一致するかもしれませんね。



>元の背景が見えるという問題が発生しました・

 元々背景を残したまま、上から DrawPolygonBase()で描画しているので、

・ GetDrawScreenGraph()の直後で ClearDrawScreen()を呼んで表示用の画面をクリアする
・ 表示用の画面ではなく一時的なテクスチャに対して背景をレンダリングする

 のどちらかでとりあえず背景は見えなくなります。

匿名

Re:画像を歪ませたいんですが・・

#62

投稿記事 by 匿名 » 16年前

確かにそれほど差があるわけでもないですね。
動かすことで強調されていたようです。

とりあえず背景は置いといて正しいサイズで描画できるように改良してみます。

匿名

Re:画像を歪ませたいんですが・・

#63

投稿記事 by 匿名 » 16年前

ところでSCIさんの画像は端がめくれていませんが、SCIさんはどのような方法で描画しているんですか?

閉鎖

“C言語何でも質問掲示板” へ戻る