Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
16 | daniel-mar | 1 | unit SXlib; |
2 | |||
3 | //Simplified X handling routine |
||
4 | |||
5 | interface |
||
6 | {$INCLUDE DelphiXcfg.inc} |
||
7 | uses |
||
8 | Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, |
||
9 | {$IFDEF QDA_SUPPORT}QDArc,{$ENDIF} |
||
10 | DXDraws, DirectX, D3DUtils, DXClass; |
||
11 | |||
12 | (* SXF形式について |
||
13 | |||
14 | name | ofs | length | comment |
||
15 | ---------------------------------------------------------------------------------------------------- |
||
16 | Signature | 0 | 16 | 'Simplified_X01 ' |
||
17 | nVextices | 16 | 2 | number of vertices |
||
18 | nIndices | 18 | 2 | number of indices for vertices |
||
19 | dwFVF | 20 | 4 | flags for flexible vertex format |
||
20 | VertexSize| 24 | 4 | required bytes per vertex |
||
21 | |||
22 | Vertices | 256 | VertexSize * nVertices | vertices |
||
23 | Indices | 256+Vertices | 2 * nIndices | indices for vertices |
||
24 | |||
25 | *) |
||
26 | |||
27 | (* SX形式について(古い) |
||
28 | |||
29 | name | ofs | length | comment |
||
30 | ---------------------------------------------------------------------------- |
||
31 | Signature | 0 | 16 | 'Simplified_X00 ' |
||
32 | nVextices | 16 | 2 | number of vertices |
||
33 | nIndices | 18 | 2 | number of indices for vertices |
||
34 | |||
35 | Vertices | 256 | 40 * nVertices | vertices(TSXVertex) |
||
36 | Indices | 256+Vertices | 2 * nIndices | indices for vertices |
||
37 | |||
38 | *) |
||
39 | |||
40 | const |
||
41 | |||
42 | //SXファイル識別子 |
||
43 | //SX file identifier |
||
44 | SX_SIGNATURE: string[16] = 'Simplified_X00 '; //SXFlexible |
||
45 | SXF_SIGNATURE: string[16] = 'Simplified_X01 '; //古いSX |
||
46 | |||
47 | //メッシュを描画するときに一度にDirect3Dに流し込む頂点の最大数(必ず3の倍数) |
||
48 | //One at a time when drawing the flow into the maximum number of vertices Direct3D mesh (must be a multiple of 3) |
||
49 | DIV_VERTICES: Word = $FFFF; |
||
50 | |||
51 | |||
52 | |||
53 | //TSXVertex用、FVFフラグ |
||
54 | FVF_SXVERTEX: DWord = (D3DFVF_VERTEX or D3DFVF_DIFFUSE or D3DFVF_SPECULAR); |
||
55 | |||
56 | //TSXVertexMT用 |
||
57 | FVF_SXVERTEXMT: DWord = (D3DFVF_XYZ or D3DFVF_NORMAL or D3DFVF_DIFFUSE or D3DFVF_SPECULAR or D3DFVF_TEX2); |
||
58 | |||
59 | type |
||
60 | TSXMesh = class; |
||
61 | TSXFrame = class; |
||
62 | TSXFrameList = class; |
||
63 | TSXScene = class; |
||
64 | TSXRenderingQueue = class; |
||
65 | |||
66 | //SX形式のための頂点データ |
||
67 | //Vertex data for the SX-style |
||
68 | TSXVertex = packed record |
||
69 | |||
70 | case Integer of |
||
71 | 0: ( |
||
72 | x, y, z: Single; //頂点 |
||
73 | nx, ny, nz: Single; //法線 |
||
74 | diffuse: TD3DCOLOR; //ディフューズ |
||
75 | specular: TD3DCOLOR; //スペキュラ |
||
76 | tu, tv: Single; //テクスチャ座標 ** Texture coordinates |
||
77 | ); |
||
78 | 1: ( |
||
79 | pos: TD3DVector; |
||
80 | normal: TD3DVector; |
||
81 | ); |
||
82 | end; |
||
83 | |||
84 | PSXVertex = ^TSXVertex; |
||
85 | |||
86 | TSXVertexArray = array[0..$FFFFFF] of TSXVertex; |
||
87 | PSXVertexArray = ^TSXVertexArray; |
||
88 | |||
89 | //マルチテクスチャ対応SXVertex |
||
90 | //SXVertex multi-texture support |
||
91 | TSXVertexMT = packed record |
||
92 | case Integer of |
||
93 | 0: ( |
||
94 | x, y, z: Single; //頂点 |
||
95 | nx, ny, nz: Single; //法線 |
||
96 | diffuse: TD3DCOLOR; //ディフューズ |
||
97 | specular: TD3DCOLOR; //スペキュラ |
||
98 | tu0, tv0: Single; //テクスチャ座標 |
||
99 | tu1, tv1: Single; //テクスチャ座標(2) |
||
100 | ); |
||
101 | 1: ( |
||
102 | pos: TD3DVector; |
||
103 | normal: TD3DVector; |
||
104 | ); |
||
105 | end; |
||
106 | |||
107 | PSXVertexMT = ^TSXVertexMT; |
||
108 | |||
109 | TSXVertexArrayMT = array[0..$FFFFFF] of TSXVertexMT; |
||
110 | PSXVertexArrayMT = ^TSXVertexArrayMT; |
||
111 | |||
112 | //ビルボードのための頂点情報 |
||
113 | //Billboard top information for |
||
114 | TSXVertexBB = record |
||
115 | case Integer of |
||
116 | 0: ( |
||
117 | //視点からの距離1の時の、中心からの相対座標 |
||
118 | //At a distance from the viewpoint of the relative coordinate from the center |
||
119 | dx, dy: Single; |
||
120 | color: TD3DCOLOR; //色 |
||
121 | tu, tv: Single; //テクスチャ座標 |
||
122 | ); |
||
123 | 1: ( |
||
124 | size: TSngPoint; |
||
125 | ); |
||
126 | end; |
||
127 | |||
128 | //イベントハンドラ |
||
129 | //Event handler |
||
130 | TSXRenderMeshEvent = procedure(Sender: TSXFrame) of object; |
||
131 | |||
132 | //ブレンドモード |
||
133 | //Blend |
||
134 | // TSXBlendMode = ( |
||
135 | // sxbDefault, //普通、透けない |
||
136 | // sxbAdd, //加算合成 |
||
137 | // sxbAlpha, //半透明 |
||
138 | // sxbSub //減算合成 |
||
139 | // ); |
||
140 | |||
141 | //可視属性 |
||
142 | //Visible attribute |
||
143 | TSXVisibility = ( |
||
144 | sxvShow, //見える |
||
145 | sxvHide, //隠れる。子フレームも含めて |
||
146 | sxvHideMyself //隠れる。子フレームは隠れない。 |
||
147 | ); |
||
148 | |||
149 | //クラス群 |
||
150 | //Classes |
||
151 | |||
152 | //メッシュ用クラス |
||
153 | //The Mesh Class |
||
154 | TSXMesh = class |
||
155 | private |
||
156 | procedure SetVertexSize(const Value: DWord); |
||
157 | protected |
||
158 | FOwner: TDXDraw; //色々お世話になるDDDDオブジェクト |
||
159 | FVBuf: IDirect3DVertexBuffer7; //VertexBuffer |
||
160 | FIndexCount: Word; //頂点インデクスの数 |
||
161 | FVertexCount: Word; //頂点の数 |
||
162 | FFaceCount: Word; //面の数、常に頂点数/3 |
||
163 | FVertexSize: DWord; //1個の頂点あたりのサイズ |
||
164 | FVFFlags: DWord; //描画させるときのフラグ |
||
165 | VertexKeepBuf: Pointer; //頂点の配列を入れる。Keep用のバッファとして使う |
||
166 | FIndices: array of Word; //頂点インデクス |
||
167 | FLocked: Boolean; //ロック中? |
||
168 | FPVertex: Pointer; //頂点バッファへのポインタ |
||
169 | FRecovery: Boolean; //リカバリ中? |
||
170 | function GetIndex(idx: Word): Word; |
||
171 | function GetVertex(idx: Word): Pointer; |
||
172 | procedure SetIndex(idx: Word; const Value: Word); |
||
173 | procedure SetVertex(idx: Word; const Value: Pointer); |
||
174 | public |
||
175 | constructor Create(AOwner: TDXDraw); |
||
176 | destructor Destroy; override; |
||
177 | procedure KeepVB; //画面が初期化される時の事を考えて、現在のVBの状態を保持 |
||
178 | procedure RecoverVB; //保持したVBを復元 |
||
179 | property VertexBuffer: IDirect3DVertexBuffer7 read FVBuf; //VertexBuffer |
||
180 | property IndexCount: Word read FIndexCount; //頂点インデクスの数 |
||
181 | property VertexCount: Word read FVertexCount; //頂点の数 |
||
182 | property FaceCount: Word read FFaceCount; //面の数(頂点の数 / 3 |
||
183 | property Vertex[idx: Word]: Pointer read GetVertex write SetVertex; //頂点への参照 |
||
184 | property Index[idx: Word]: Word read GetIndex write SetIndex; //頂点インデクス |
||
185 | property FVF: DWord read FVFFlags write FVFFlags; //FlexibleVertexFormatに関するフラグ |
||
186 | property VertexSize: DWord read FVertexSize write SetVertexSize; |
||
187 | procedure Draw(dwFlags: DWord); //DrawIndexedPrimitiveVBで全部描画 |
||
188 | procedure DrawPartial(start: Word; count: Word; dwFlags: DWord); //DrawIndexedPrimitiveVBで部分描画 |
||
189 | procedure LoadFromStream(s: TStream); |
||
190 | procedure LoadFromFile(fileName: string); |
||
191 | {$IFDEF QDA_SUPPORT} |
||
192 | procedure LoadFromQDA(QDAName, QDAID: string); |
||
193 | {$ENDIF} |
||
194 | function Lock: Pointer; |
||
195 | procedure Unlock; |
||
196 | procedure SetSize(newVertexCount, newIndexCount: Word); //バッファの大きさを再設定する、中身は消える |
||
197 | procedure Optimize; |
||
198 | end; |
||
199 | |||
200 | { |
||
201 | TSXMesh = class(TSXGenMesh) |
||
202 | private |
||
203 | function GetVertex(idx: Word): TSXVertex; override; |
||
204 | procedure SetVertex(idx: Word; const Value: TSXVertex); override; |
||
205 | public |
||
206 | |||
207 | property Vertex[idx:Word]:TSXVertex read GetVertex write SetVertex; //頂点 |
||
208 | function Lock:PSXVertexArray; |
||
209 | end; |
||
210 | } |
||
211 | |||
212 | //フレーム |
||
213 | //The Frame |
||
214 | TSXFrame = class |
||
215 | private |
||
216 | FMatrix: TD3DMATRIX; //変換行列(自分の座標系→親座標系) |
||
217 | FMeshMatrix: TD3DMATRIX; //メッシュ描画時の変換行列…メッシュ座標→自分座標 |
||
218 | |||
219 | FAncestors: TSXFrameList; //祖先フレーム達 |
||
220 | FChildren: TSXFrameList; //子フレーム達 |
||
221 | FParent: TSXFrame; //親フレーム(Ancestors[Ancestors.Count-1]と同) |
||
222 | FVisibility: TSXVisibility; //可視属性 |
||
223 | FBindRenderState: Boolean; //自分の子孫のレンダリングステートを、強制的に自分のにする |
||
224 | FBindTexture: Boolean; //自分の子孫のテクスチャを、強制的に自分のにする |
||
225 | FBindMaterial: Boolean; //自分の子孫のマテリアルを、強制的に自分のにする |
||
226 | |||
227 | RenderedMatrix: TD3DMATRIX; //最後にレンダリングされたときのワールド行列(ビルボードの描画に使用) |
||
228 | BBAttached: Boolean; //ビルボードがくっついてる? |
||
229 | |||
230 | function GetWorldMatrix: TD3DMATRIX; |
||
231 | procedure SetParent(const Value: TSXFrame); |
||
232 | |||
233 | public |
||
234 | |||
235 | //中身 |
||
236 | Texture: TDirect3DTexture2; //メッシュに貼り付けるテクスチャ |
||
237 | Mesh: TSXMesh; //書き込むメッシュ |
||
238 | Material: TD3DMATERIAL7; //マテリアル |
||
239 | |||
240 | //レンダリングステートの制御 |
||
241 | Lighting: Boolean; //True:ライティングをする, False:頂点の色をそのまま使う |
||
242 | Specular: Boolean; //スペキュラハイライトをつける |
||
243 | BlendMode: TRenderType; //描画時のブレンドモード |
||
244 | |||
245 | //イベントハンドラ |
||
246 | OnRenderMesh: TSXRenderMeshEvent; //メッシュをこれから書きますですイベント |
||
247 | |||
248 | //いろいろ |
||
249 | Tag: DWord; //整数値、なんにでも使って |
||
250 | RenderAttr: Integer; //整数値、OnRenderMeshで、マテリアル番号代わりにどうぞ |
||
251 | |||
252 | //コンストラクタ・デストラクタ |
||
253 | constructor Create(parentFrame: TSXFrame); |
||
254 | destructor Destroy; override; |
||
255 | |||
256 | //親子関係 |
||
257 | property Ancestors: TSXFrameList read FAncestors; |
||
258 | property Children: TSXFrameList read FChildren; |
||
259 | property Parent: TSXFrame read FParent write SetParent; |
||
260 | property BindRenderState: Boolean read FBindRenderState write FBindRenderState; |
||
261 | property BindTexture: Boolean read FBindTexture write FBindTexture; |
||
262 | property BindMaterial: Boolean read FBindMaterial write FBindMaterial; |
||
263 | |||
264 | //可視属性 |
||
265 | property Visibility: TSXVisibility read FVisibility write FVisibility; |
||
266 | |||
267 | //座標変換関係 |
||
268 | property Matrix: TD3DMATRIX read FMatrix write FMatrix; |
||
269 | property WorldMatrix: TD3DMATRIX read GetWorldMatrix; //自分座標→ワールド座標の変換行列 |
||
270 | property MeshMatrix: TD3DMATRIX read FMeshMatrix write FMeshMatrix; //メッシュ描画時の変換行列…メッシュ座標→自分座標 |
||
271 | |||
272 | procedure SetTransform(ref: TSXFrame; const mat: TD3DMATRIX); |
||
273 | function GetTransform(ref: TSXFrame): TD3DMATRIX; |
||
274 | |||
275 | function LocalToWorld(vec: TD3DVector): TD3DVector; //フレーム内での座標を、ワールド座標に変換する |
||
276 | function WorldToLocal(vec: TD3DVector): TD3DVector; //ワールド座標内の座標をフレーム内の座標に変換する |
||
277 | |||
278 | //位置 |
||
279 | procedure SetTranslation(ref: TSXFrame; const pos: TD3Dvector); |
||
280 | function GetTranslation(ref: TSXFrame): TD3DVector; |
||
281 | |||
282 | //姿勢 |
||
283 | //…軸ベクトルで設定・取得 |
||
284 | procedure SetOrientation(ref: TSXFrame; const vecZ: TD3DVector; const vecY: TD3DVector); |
||
285 | procedure GetOrientation(ref: TSXFrame; var vecZ: TD3DVector; var vecY: TD3DVector); |
||
286 | //…マトリクスを与えて姿勢だけ設定 |
||
287 | procedure SetOrientationMatrix(ref: TSXFrame; const mat: TD3DMATRIX); |
||
288 | |||
289 | //お便利 |
||
290 | //…Z軸をtargetフレーム内の座標posを向ける。Y軸はworldフレーム内のY軸に向け。Y軸の傾きをbank度とする |
||
291 | procedure LookAt(target: TSXFrame; const pos: TD3DVector; world: TSXFrame; const bank: Integer); |
||
292 | function ViewMatrix: TD3DMatrix; //このフレームをカメラにした場合のビュー行列を生成 |
||
293 | end; |
||
294 | |||
295 | //フレームのリスト |
||
296 | //List of frames |
||
297 | TSXFrameList = class(TList) |
||
298 | private |
||
299 | function GetFrame(idx: Integer): TSXFrame; |
||
300 | procedure SetFrame(idx: Integer; const Value: TSXFrame); |
||
301 | public |
||
302 | property Frames[idx: Integer]: TSXFrame read GetFrame write SetFrame; default; |
||
303 | constructor Create; |
||
304 | destructor Destroy; override; |
||
305 | procedure Assign(source: TSXFrameList); |
||
306 | end; |
||
307 | |||
308 | //シーン全体 |
||
309 | TSXScene = class |
||
310 | private |
||
311 | FCamera: TSXFrame; |
||
312 | FOwner: TDXDraw; |
||
313 | |||
314 | FProjectionMatrix: TD3DMATRIX; |
||
315 | FVP: TD3DVIEWPORT7; |
||
316 | |||
317 | OpaqueQueue: TSXRenderingQueue; //不透明体用のキュー |
||
318 | AlphaQueue: TSXRenderingQueue; //半透明透明体用のキュー |
||
319 | AddQueue: TSXRenderingQueue; //加算半透明体用のキュー |
||
320 | SubQueue: TSXRenderingQueue; //減算半透明体用のキュー |
||
321 | |||
322 | //ProcessVertices用 |
||
323 | //MeshProcessor:TSXMesh; //Lightingをしないとき・環境マップする時用 |
||
324 | //MeshProcessorMT:TSXMesh; //同上、ただしマルチテクスチャ(2ステージ)版 |
||
325 | public |
||
326 | constructor Create(DDCompo: TDXDraw); |
||
327 | destructor Destroy; override; |
||
328 | |||
329 | property CameraFrame: TSXFrame read FCamera write FCamera; //視点を置くフレーム |
||
330 | |||
331 | procedure Render(rootFrame: TSXFrame); //rootFrame以下を描画 |
||
332 | procedure Clear(dwFlags: DWord; color: DWORD; z: Single; stencil: DWord); //バックバッファのクリア |
||
333 | |||
334 | procedure SetProjection(fov, aspect, nearZ, farZ: Single); //透視変換の設定 |
||
335 | procedure SetViewPort(left, top, right, bottom: DWord); //ビューポート |
||
336 | |||
337 | procedure Recover; //ビューポートなどの状態をリストア |
||
338 | |||
339 | procedure PushBillboard(blendMode: TRenderType; ref: TSXFrame; pos: TD3DVector; points: array of TSXVertexBB; tex: TDirect3DTexture2); |
||
340 | function SphereVisibility(ref: TSXFrame; pos: TD3DVector; radius: Single; depth: Single): Boolean; //refフレーム内にある、中心pos、半径radiusの球は見えるか、但し、距離がdepth以上なら見えないものとする |
||
341 | end; |
||
342 | |||
343 | //ライト |
||
344 | TSXLight = class |
||
345 | private |
||
346 | FOwner: TDXDraw; |
||
347 | FIndex: DWord; //SetLightに渡す、インデクス |
||
348 | FEnabled: Boolean; |
||
349 | FUpdate: Boolean; //パラメータの変更を、即反映 |
||
350 | procedure SetEnabled(const Value: Boolean); |
||
351 | public |
||
352 | Params: TD3DLIGHT7; |
||
353 | |||
354 | constructor Create(DDCompo: TDXDraw; index: DWord); |
||
355 | destructor Destroy; override; |
||
356 | |||
357 | procedure BeginUpdate; //Paramsの内容を、Direct3Dに伝えなくする |
||
358 | procedure EndUpdate; //Paramsの内容を、Direct3Dに伝えなくした状態を解除 |
||
359 | |||
360 | property Enabled: Boolean read FEnabled write SetEnabled; |
||
361 | |||
362 | //お便利ルーチン |
||
363 | procedure SetupDiffuse(_R, _G, _B: Single); |
||
364 | procedure SetupSpecular(_R, _G, _B: Single); |
||
365 | procedure SetupAmbient(_R, _G, _B: Single); |
||
366 | |||
367 | procedure SetupColors(difR, difG, difB, specR, specG, specB, ambR, ambG, ambB: Single); |
||
368 | procedure SetupRanges(range, att0, att1, att2: Single); |
||
369 | |||
370 | procedure SetupDirectional(dir: TD3DVector); |
||
371 | procedure SetupPoint(pos: TD3DVector); |
||
372 | procedure SetupSpot(pos, dir: TD3DVector; theta, phi, falloff: Single); |
||
373 | |||
374 | procedure FitFrame(target: TSXFrame); //フレームの位置・向きにセットする |
||
375 | end; |
||
376 | |||
377 | //複数のライトを管理するオブジェクト |
||
378 | TSXLightGroup = class(TList) |
||
379 | private |
||
380 | FOwner: TDXDraw; |
||
381 | FCapacity: DWord; //管理するライトの数 |
||
382 | FLights: array of TSXLight; |
||
383 | //FSpecularPower:Single; //スペキュラ強度 |
||
384 | function GetLights(idx: DWord): TSXLight; |
||
385 | function GetUnusedLight: TSXLight; |
||
386 | // procedure SetSpecularPower(const Value: Single); |
||
387 | public |
||
388 | constructor Create(DDCompo: TDXDraw; capacity: DWord); |
||
389 | destructor Destroy; override; |
||
390 | |||
391 | property Lights[idx: DWord]: TSXLight read GetLights; default; |
||
392 | property UnusedLight: TSXLight read GetUnusedLight; //Enabledになってない、最初のライトを返す |
||
393 | //property SpecularPower:Single read FSpecularPower write SetSpecularPower; |
||
394 | |||
395 | procedure EnableAll; //全部点ける |
||
396 | procedure DisableAll; //全部消す |
||
397 | |||
398 | procedure Recover; //解像度を変えた後などのリカバリ |
||
399 | end; |
||
400 | |||
401 | TSXMaterial = class |
||
402 | private |
||
403 | FOwner: TDXDraw; |
||
404 | FUpdate: Boolean; |
||
405 | public |
||
406 | Params: TD3DMATERIAL7; |
||
407 | constructor Create(DDCompo: TDXDraw); |
||
408 | |||
409 | procedure BeginUpdate; //Paramsの内容を、Direct3Dに伝えなくする |
||
410 | procedure EndUpdate; //Paramsの内容を、Direct3Dに伝えなくした状態を解除 |
||
411 | |||
412 | procedure SetupDiffuse(_R, _G, _B: Single); |
||
413 | procedure SetupSpecular(_R, _G, _B: Single); |
||
414 | procedure SetupAmbient(_R, _G, _B: Single); |
||
415 | procedure SetupEmissive(_R, _G, _B: Single); |
||
416 | procedure SetupSpecularPower(pow: Single); |
||
417 | |||
418 | procedure SetupColors(difR, difG, difB, specR, specG, specB, ambR, ambG, ambB, emsR, emsG, emsB, pow: Single); |
||
419 | end; |
||
420 | |||
421 | //メッシュ描画キューに入れる情報 |
||
422 | TSXMeshInfo = record |
||
423 | frame: TSXFrame; //そのメッシュを描こうとしたフレームはどれ? |
||
424 | mesh: TSXMesh; //メッシュ |
||
425 | mat: TD3DMatrix; //変換行列 |
||
426 | tex: TDirect3DTexture2; //テクスチャ |
||
427 | mtrl: TD3DMATERIAL7; //マテリアル |
||
428 | lighting: Boolean; //光源計算する/しない |
||
429 | OnRender: TSXRenderMeshEvent; |
||
430 | end; |
||
431 | |||
432 | //ビルボード描画キューに入れる情報 |
||
433 | TSXBillboardInfo = record |
||
434 | ref: TSXFrame; //基準フレーム |
||
435 | pos: TD3DVector; //基準フレーム内での位置 |
||
436 | tex: TDirect3DTexture2; //テクスチャ |
||
437 | pts: array[0..3] of TSXVertexBB; //頂点データ |
||
438 | end; |
||
439 | |||
440 | //レンダリングの順序を保つためのバッファ、透明体かそうでないかで順序を変える。 |
||
441 | //Render order to maintain the buffer, or not change the order in a transparent body. |
||
442 | TSXRenderingQueue = class |
||
443 | private |
||
444 | FOwner: TDXDraw; //色々お世話になるDDDDオブジェクト |
||
445 | Scene: TSXScene; //この |
||
446 | |||
447 | MeshQueue: array of TSXMeshInfo; |
||
448 | BillboardQueue: array of TSXBillboardInfo; |
||
449 | |||
450 | FMeshCapacity: Integer; //メッシュを情報蓄える容量 |
||
451 | FBillboardCapacity: Integer; |
||
452 | |||
453 | FMeshCount: Integer; //キューに入ってる数 |
||
454 | FBillboardCount: Integer; |
||
455 | |||
456 | procedure SetBillBoardCapacity(const Value: Integer); |
||
457 | procedure SetMeshCapacity(const Value: Integer); //ビルボードについての情報を蓄える容量 |
||
458 | public |
||
459 | constructor Create(AOwner: TDXDraw; _Scene: TSXScene); |
||
460 | destructor Destroy; override; |
||
461 | procedure PushMesh(mesh: TSXMesh; frame: TSXFrame; mat: TD3DMatrix; tex: TDirect3DTexture2; mtrl: TD3DMATERIAL7; event: TSXRenderMeshEvent); //メッシュ |
||
462 | procedure PushBillboard(ref: TSXFrame; pos: TD3DVector; tex: TDirect3DTexture2; pts: array of TSXVertexBB); //ビルボード |
||
463 | procedure Render(viewMat: TD3DMATRIX; viewParam: TD3DVIEWPORT7); //レンダリング |
||
464 | procedure Flush; //レンダリングせず、バッファの中を空に **Without rendering the buffer to empty |
||
465 | |||
466 | property MeshCapacity: Integer read FMeshCapacity write SetMeshCapacity; |
||
467 | property BillboardCapacity: Integer read FBillboardCapacity write SetBillBoardCapacity; |
||
468 | property MeshCount: Integer read FMeshCount; |
||
469 | property BillboardCount: Integer read FBillboardCount; |
||
470 | end; |
||
471 | |||
472 | {Renderer of the primitive} |
||
473 | |||
474 | TSXPrimitiveRec = packed record |
||
475 | Texture: TDirect3DTexture2; //テクスチャ |
||
476 | Bound: array[0..3] of TD3DTLVertex; //四角形 |
||
477 | ZOrder: Integer; //Zオーダ |
||
478 | BlendMode: TRenderType; //ブレンドモード |
||
479 | end; |
||
480 | PPrimitive = ^TSXPrimitiveRec; |
||
481 | |||
482 | TSXTextureCoordRec = packed record |
||
483 | Texture: TDirect3DTexture2; |
||
484 | Top, Left, Bottom, Right: Single; //テクスチャ座標 |
||
485 | end; |
||
486 | PTextureCoord = ^TSXTextureCoordRec; |
||
487 | |||
488 | TSingleRect = packed record |
||
489 | Left, Top, Right, Bottom: Single; |
||
490 | end; |
||
491 | |||
492 | TSXPrimitiveRenderer = class |
||
493 | private |
||
494 | FDXDraw: TDXDraw; |
||
495 | FZMax: Integer; //Zオーダの最大値 |
||
496 | FMaxPrimitives: Integer; //格納できるTLVの最大値 |
||
497 | |||
498 | ZSortBuf: ^Integer; //Zソート用バッファ |
||
499 | ZSortCount: ^Integer; //Zソート用カウンタ |
||
500 | PrimBuf: PPrimitive; //プリミティブ入れ |
||
501 | PrimCount: Integer; //現在PrimBufに入ってるプリミティブの数 |
||
502 | Patterns: PTextureCoord; //テクスチャパターン |
||
503 | FNPrims: Integer; //最後にUpdateメソッドを発行した際の、プリミティブの数 |
||
504 | FColorKey: Boolean; //カラーキーによる抜き色を行う? |
||
505 | procedure setZMax(v: Integer); |
||
506 | public |
||
507 | constructor Create(DDCompo: TDXDraw; PrimitiveCount: Integer; PatternCount: Integer); |
||
508 | destructor Destroy; override; |
||
509 | property ZMax: Integer read FZMax write setZMax; |
||
510 | |||
511 | procedure SetPattern(idx: Integer; Tex: TDirect3DTexture2; Coord: TRect); //パターンとしてTexのCoordで示される範囲を登録 |
||
512 | |||
513 | procedure Push(Tex: TDirect3DTexture2; p1, p2, p3, p4: TD3DTLVertex; Z: Integer; blend: TRenderType); //TLVertexで四角形を入れる |
||
514 | procedure Push2D(Tex: TDirect3DTexture2; p1, p2, p3, p4: TD2DVector; Z: Integer; blend: TRenderType; col: DWord); //2D的な四角形 |
||
515 | |||
516 | procedure PushPattern(iPat: Integer; p1, p2, p3, p4: TD3DHVector; Z: Integer; blend: TRenderType; col: DWord); //パターンをプッシュ(3次元) |
||
517 | procedure PushPattern2D(iPat: Integer; p1, p2, p3, p4: TD2DVector; Z: Integer; blend: TRenderType; col: DWord); //パターンをプッシュする |
||
518 | procedure PushPatternRect(iPat: Integer; rect: TSingleRect; Z: Integer; blend: TRenderType; col: DWord); //パターンをプッシュする(矩形) |
||
519 | |||
520 | procedure BeginRender; //Z値にしたがってソート |
||
521 | procedure RenderOneLayer(Z: Integer); //単一のZ値を持つ集合だけ描画 |
||
522 | procedure EndRender; //スタックを空に |
||
523 | procedure Render; //全部描画(BeginRender~RenderOneLayer~EndRender) |
||
524 | |||
525 | property nPrims: Integer read FNPrims; |
||
526 | property ColorKey: Boolean read FColorKey write FColorKey; |
||
527 | |||
528 | class function SingleRect(x1, y1, x2, y2: Single): TSingleRect; |
||
529 | end; |
||
530 | |||
531 | //SXVertex作成 |
||
532 | function SXVertex(x, y, z, nx, ny, nz: Single; dif, spec: TD3DCOLOR; tu, tv: Single): TSXVertex; |
||
533 | |||
534 | //SXVertexBB作成 |
||
535 | function SXVertexBB(dx, dy: Single; col: TD3DCOLOR; tu, tv: Single): TSXVertexBB; |
||
536 | |||
537 | //マテリアル設定の便宜を図る関数 |
||
538 | //Convenience function for setting material |
||
539 | function MakeMaterial(difR, difG, difB, specR, specG, specB, ambR, ambG, ambB, emsR, emsG, emsB, pow: Single): TD3DMATERIAL7; |
||
540 | |||
541 | implementation |
||
542 | |||
543 | type |
||
544 | TSXTLVertexMT = packed record |
||
545 | case Integer of |
||
546 | 0: ( |
||
547 | x, y, z, rhw: Single; //頂点 |
||
548 | diffuse: TD3DCOLOR; //ディフューズ |
||
549 | specular: TD3DCOLOR; //スペキュラ |
||
550 | tu0, tv0: Single; //テクスチャ座標 |
||
551 | tu1, tv1: Single; //テクスチャ座標2 |
||
552 | ); |
||
553 | 1: ( |
||
554 | pos: TD3DVector; |
||
555 | ); |
||
556 | 2: ( |
||
557 | hgPos: TD3DHVector; |
||
558 | ); |
||
559 | end; |
||
560 | |||
561 | const |
||
562 | FVF_SXTLVertexMT: DWord = (D3DFVF_XYZRHW or D3DFVF_DIFFUSE or D3DFVF_SPECULAR or D3DFVF_TEX2); |
||
563 | |||
564 | { Helper functions } |
||
565 | |||
566 | function SXVertex(x, y, z, nx, ny, nz: Single; dif, spec: TD3DCOLOR; tu, tv: Single): TSXVertex; |
||
567 | begin |
||
568 | result.x := x; |
||
569 | result.y := y; |
||
570 | result.z := z; |
||
571 | result.nx := nx; |
||
572 | result.ny := ny; |
||
573 | result.nz := nz; |
||
574 | |||
575 | result.diffuse := dif; |
||
576 | result.specular := spec; |
||
577 | |||
578 | result.tu := tu; |
||
579 | result.tv := tv; |
||
580 | |||
581 | end; |
||
582 | |||
583 | function SXVertexBB(dx, dy: Single; col: TD3DCOLOR; tu, tv: Single): TSXVertexBB; |
||
584 | begin |
||
585 | result.dx := dx; |
||
586 | result.dy := dy; |
||
587 | |||
588 | result.color := col; |
||
589 | |||
590 | result.tu := tu; |
||
591 | result.tv := tv; |
||
592 | end; |
||
593 | |||
594 | { TSXMesh } |
||
595 | |||
596 | //コンストラクタ |
||
597 | //Constructor |
||
598 | |||
599 | constructor TSXMesh.Create(AOwner: TDXDraw); |
||
600 | begin |
||
601 | inherited Create; |
||
602 | |||
603 | FOwner := AOwner; |
||
604 | FVBuf := nil; |
||
605 | SetLength(FIndices, 0); |
||
606 | FIndexCount := 0; |
||
607 | FFaceCount := 0; |
||
608 | FVertexCount := 0; |
||
609 | VertexKeepBuf := nil; |
||
610 | |||
611 | FVertexSize := sizeof(TSXVertex); |
||
612 | FVFFlags := FVF_SXVERTEX; |
||
613 | |||
614 | FLocked := False; |
||
615 | FRecovery := False; |
||
616 | |||
617 | end; |
||
618 | |||
619 | //デストラクタ |
||
620 | //Destructor |
||
621 | |||
622 | destructor TSXMesh.Destroy; |
||
623 | begin |
||
624 | if FVBuf <> nil then |
||
625 | FVBuf := nil; //._Release; |
||
626 | |||
627 | if VertexKeepBuf <> nil then |
||
628 | FreeMem(VertexKeepBuf); |
||
629 | |||
630 | FIndices := nil; |
||
631 | |||
632 | inherited; |
||
633 | end; |
||
634 | |||
635 | //現在のVertexBufferの状態を保持 |
||
636 | //Currently holds the state of VertexBuffer |
||
637 | |||
638 | procedure TSXMesh.KeepVB; |
||
639 | begin |
||
640 | if FVBuf <> nil then |
||
641 | begin |
||
642 | //バッファサイズの変更 |
||
643 | //Resizing of the buffer |
||
644 | if VertexKeepBuf <> nil then |
||
645 | FreeMem(VertexKeepBuf); |
||
646 | VertexKeepBuf := AllocMem(VertexSize * FVertexCount); |
||
647 | |||
648 | Self.Lock; |
||
649 | Move(FPVertex^, VertexKeepBuf^, VertexSize * FVertexCount); |
||
650 | Self.Unlock; |
||
651 | end; |
||
652 | end; |
||
653 | |||
654 | //保存したVertexBufferの状態を復元 |
||
655 | //Restore the state saved VertexBuffer |
||
656 | |||
657 | |||
658 | procedure TSXMesh.RecoverVB; |
||
659 | begin |
||
660 | |||
661 | if FVBuf <> nil then |
||
662 | begin |
||
663 | //リカバリ期間・開始 |
||
664 | //Recovery period begins |
||
665 | FRecovery := True; |
||
666 | FVBuf := nil; |
||
667 | |||
668 | SetSize(FVertexCount, FIndexCount); |
||
669 | |||
670 | Self.Lock; |
||
671 | Move(VertexKeepBuf^, FPVertex^, VertexSize * FVertexCount); |
||
672 | Self.Unlock; |
||
673 | |||
674 | FreeMem(VertexKeepBuf); |
||
675 | VertexKeepBuf := nil; |
||
676 | FRecovery := False; |
||
677 | //リカバリ期間・終了 |
||
678 | //Recovery period ends |
||
679 | end; |
||
680 | end; |
||
681 | |||
682 | //DPで描画 |
||
683 | //Simple DP draw |
||
684 | |||
685 | procedure TSXMesh.Draw(dwFlags: DWord); |
||
686 | var |
||
687 | ofs: Word; |
||
688 | nIs: Word; |
||
689 | begin |
||
690 | ofs := 0; |
||
691 | while ofs < FIndexCount do |
||
692 | begin |
||
693 | |||
694 | nIs := FIndexCount - ofs; |
||
695 | if nIs > DIV_VERTICES then |
||
696 | nIs := DIV_VERTICES; |
||
697 | |||
698 | FOwner.D3DDevice7.DrawIndexedPrimitiveVB( |
||
699 | D3DPT_TRIANGLELIST, FVBuf, 0, FVertexCount, FIndices[ofs], nIs, dwFlags); |
||
700 | |||
701 | Inc(ofs, nIs); |
||
702 | end; |
||
703 | end; |
||
704 | |||
705 | //DPで描画 |
||
706 | //Draw DP strem of primitives |
||
707 | |||
708 | procedure TSXMesh.DrawPartial(start: Word; count: Word; dwFlags: DWord); |
||
709 | begin |
||
710 | FOwner.D3DDevice7.DrawIndexedPrimitiveVB( |
||
711 | D3DPT_TRIANGLELIST, FVBuf, 0, FVertexCount, FIndices[start], count, dwFlags); |
||
712 | end; |
||
713 | |||
714 | //インデクス操作 |
||
715 | //Check index |
||
716 | |||
717 | function TSXMesh.GetIndex(idx: Word): Word; |
||
718 | begin |
||
719 | if idx >= FIndexCount then |
||
720 | begin |
||
721 | //DDDD_PutDebugMessage('SXLib: 範囲外の頂点インデクスを参照しようとしました'); |
||
722 | result := 0; |
||
723 | exit; |
||
724 | end; |
||
725 | |||
726 | result := FIndices[idx]; |
||
727 | end; |
||
728 | |||
729 | procedure TSXMesh.SetIndex(idx: Word; const Value: Word); |
||
730 | begin |
||
731 | if idx >= FIndexCount then |
||
732 | begin |
||
733 | //DDDD_PutDebugMessage('SXLib: 範囲外の頂点インデクスを設定しようとしました'); |
||
734 | exit; |
||
735 | end; |
||
736 | |||
737 | FIndices[idx] := Value; |
||
738 | end; |
||
739 | |||
740 | //頂点操作 |
||
741 | //Operation on Vertex |
||
742 | |||
743 | function TSXMesh.GetVertex(idx: Word): Pointer; |
||
744 | var |
||
745 | pV: Pointer; |
||
746 | ofs: DWord; |
||
747 | lpdwSize: Cardinal; |
||
748 | begin |
||
749 | //範囲チェック |
||
750 | //check range |
||
751 | if idx >= FVertexCount then |
||
752 | begin |
||
753 | //DDDD_PutDebugMessage('SXLib: 範囲外の頂点を参照しようとしました'); |
||
754 | result := nil; |
||
755 | exit; |
||
756 | end; |
||
757 | |||
758 | //ロックされていないなら、ロック。ロックされてるなら、前に得たポインタをゲット |
||
759 | //when is unlocked, then lock there |
||
760 | if not FLocked then |
||
761 | begin |
||
762 | if FVBuf.Lock(DDLOCK_READONLY or DDLOCK_WAIT, pV, lpdwSize) <> DD_OK then |
||
763 | begin |
||
764 | //DDDD_PutDebugMessage('SXLib: VertexBufferがロックできません'); |
||
765 | Halt; |
||
766 | end; |
||
767 | end |
||
768 | else |
||
769 | pV := FPVertex; |
||
770 | |||
771 | //返り値に格納 |
||
772 | //calc place of vertices |
||
773 | ofs := idx * VertexSize; |
||
774 | asm |
||
775 | mov eax,ofs; |
||
776 | add pV,eax; |
||
777 | end; |
||
778 | result := pV; |
||
779 | |||
780 | //アンロック |
||
781 | //unlock |
||
782 | if not FLocked then |
||
783 | begin |
||
784 | if FVBuf.Unlock <> DD_OK then |
||
785 | begin |
||
786 | //DDDD_PutDebugMessage('SXLib: VertexBufferがアンロックできません'); |
||
787 | Halt; |
||
788 | end; |
||
789 | end; |
||
790 | |||
791 | end; |
||
792 | |||
793 | procedure TSXMesh.SetVertex(idx: Word; const Value: Pointer); |
||
794 | var |
||
795 | ofs: DWord; |
||
796 | pV: ^TSXVertex; |
||
797 | lpdwSize: Cardinal; |
||
798 | begin |
||
799 | //範囲チェック |
||
800 | //check range |
||
801 | if idx >= FVertexCount then |
||
802 | begin |
||
803 | //DDDD_PutDebugMessage('SXLib: 範囲外の頂点を変更しようとしました'); |
||
804 | exit; |
||
805 | end; |
||
806 | |||
807 | //ロックされていないなら、ロック。ロックされてるなら、前に得たポインタをゲット |
||
808 | //Test when unlocked, and after test lock |
||
809 | if not FLocked then |
||
810 | begin |
||
811 | if FVBuf.Lock(DDLOCK_WRITEONLY or DDLOCK_WAIT, Pointer(pV), lpdwSize) <> DD_OK then |
||
812 | begin |
||
813 | //DDDD_PutDebugMessage('SXLib: VertexBufferがロックできません'); |
||
814 | Halt; |
||
815 | end; |
||
816 | end |
||
817 | else |
||
818 | pV := FPVertex; |
||
819 | |||
820 | //格納するっす |
||
821 | //physic size of vertices stream |
||
822 | ofs := idx * VertexSize; |
||
823 | asm |
||
824 | mov eax,ofs; |
||
825 | add pV,eax; |
||
826 | end; |
||
827 | Move(Value^, pV^, VertexSize); |
||
828 | |||
829 | //Unlock |
||
830 | if not FLocked then |
||
831 | begin |
||
832 | if FVBuf.Unlock <> DD_OK then |
||
833 | begin |
||
834 | //DDDD_PutDebugMessage('SXLib: VertexBufferがアンロックできません'); |
||
835 | Halt; |
||
836 | end; |
||
837 | end; |
||
838 | end; |
||
839 | |||
840 | //1Vertexあたりのサイズを変更 |
||
841 | //Set size for all Vertexes |
||
842 | procedure TSXMesh.SetVertexSize(const Value: DWord); |
||
843 | begin |
||
844 | FVertexSize := Value; |
||
845 | SetSize(FVertexCount, FIndexCount); |
||
846 | end; |
||
847 | |||
848 | //ストリームから読み込み |
||
849 | //Reading from strem |
||
850 | |||
851 | procedure TSXMesh.LoadFromStream(s: TStream); |
||
852 | var |
||
853 | sign: array[0..16] of AnsiChar; |
||
854 | nVertices, nIndices: Word; |
||
855 | StartPos: Integer; |
||
856 | begin |
||
857 | |||
858 | StartPos := s.Position; |
||
859 | |||
860 | //シグネチャの確認 |
||
861 | //Check of the signature |
||
862 | sign[16] := Chr(0); |
||
863 | s.ReadBuffer(sign, 16); |
||
864 | |||
865 | if StrPas(sign) = SX_SIGNATURE then |
||
866 | begin |
||
867 | //SX形式 |
||
868 | FVertexSize := Sizeof(TSXVertex); |
||
869 | FVFFlags := FVF_SXVERTEX; |
||
870 | //頂点数・頂点インデクス数の設定 |
||
871 | //Setting the number of vertices of vertex indices |
||
872 | s.ReadBuffer(nVertices, Sizeof(Word)); |
||
873 | s.ReadBuffer(nIndices, Sizeof(Word)); |
||
874 | end |
||
875 | else |
||
876 | if StrPas(sign) = SXF_SIGNATURE then |
||
877 | begin |
||
878 | //頂点数・頂点インデクス数の設定 |
||
879 | //Setting the number of vertices of vertex indices |
||
880 | s.ReadBuffer(nVertices, Sizeof(Word)); |
||
881 | s.ReadBuffer(nIndices, Sizeof(Word)); |
||
882 | //SXFlexible format |
||
883 | s.ReadBuffer(FVFFlags, Sizeof(DWord)); |
||
884 | s.ReadBuffer(FVertexSize, Sizeof(DWord)); |
||
885 | end |
||
886 | else |
||
887 | begin |
||
888 | //DDDD_PutDebugMessage('SXLib: 不正なSXファイルです'); |
||
889 | Halt; |
||
890 | end; |
||
891 | |||
892 | SetSize(nVertices, nIndices); |
||
893 | |||
894 | //ヘッダのスキップ |
||
895 | //Skip header |
||
896 | s.Position := StartPos + 256; |
||
897 | |||
898 | try |
||
899 | //頂点のロード |
||
900 | //Peak load |
||
901 | Lock; |
||
902 | s.ReadBuffer(FPVertex^, VertexSize * nVertices); |
||
903 | Unlock; |
||
904 | |||
905 | //頂点インデクスのロード |
||
906 | //Load indexes |
||
907 | s.ReadBuffer(FIndices[0], Sizeof(Word) * nIndices); |
||
908 | except |
||
909 | //DDDD_PutDebugMessage('SXLib: ストリームからの読み込み中にエラーが発生しました'); |
||
910 | Halt; |
||
911 | end; |
||
912 | |||
913 | end; |
||
914 | |||
915 | //ファイルから読み込み |
||
916 | //Load from file by name |
||
917 | |||
918 | procedure TSXMesh.LoadFromFile(fileName: string); |
||
919 | var |
||
920 | fs: TFileStream; |
||
921 | begin |
||
922 | fs := nil; |
||
923 | |||
924 | try |
||
925 | fs := TFileStream.Create(filename, fmOpenRead); |
||
926 | except |
||
927 | //DDDD_PutDebugMessage('SXLib: ' + filename + ' が、開けません'); |
||
928 | Halt; |
||
929 | end; |
||
930 | |||
931 | LoadFromStream(fs); |
||
932 | fs.Free; |
||
933 | end; |
||
934 | |||
935 | {$IFDEF QDA_SUPPORT} |
||
936 | //QDAから読み込み |
||
937 | procedure TSXMesh.LoadFromQDA(QDAName, QDAID: string); |
||
938 | var |
||
939 | ms: TMemoryStream; |
||
940 | begin |
||
941 | ms := nil; |
||
942 | |||
943 | try |
||
944 | ms := ExtractFromQDAFile(QDAName, QDAID); |
||
945 | except |
||
946 | //DDDD_PutDebugMessage('SXLib: ' + QDAname + ' 内の、' + QDAID + 'が抽出できません'); |
||
947 | Halt; |
||
948 | end; |
||
949 | |||
950 | LoadFromStream(ms); |
||
951 | ms.Free; |
||
952 | end; |
||
953 | {$ENDIF} |
||
954 | |||
955 | //VertexBuffer Lock |
||
956 | |||
957 | function TSXMesh.Lock: Pointer; |
||
958 | var lpdwSize: Cardinal; |
||
959 | begin |
||
960 | if FVBuf.Lock(DDLOCK_WAIT, Pointer(FPVertex), lpdwSize) <> DD_OK then |
||
961 | begin |
||
962 | //DDDD_PutDebugMessage('SXLib: VertexBufferがロックできません'); |
||
963 | Halt; |
||
964 | end; |
||
965 | |||
966 | result := FPVertex; |
||
967 | FLocked := True; |
||
968 | end; |
||
969 | |||
970 | //VertexBuffer unlock |
||
971 | |||
972 | procedure TSXMesh.Unlock; |
||
973 | begin |
||
974 | if FVBuf.Unlock <> DD_OK then |
||
975 | begin |
||
976 | //DDDD_PutDebugMessage('SXLib: VertexBufferがアンロックできません'); |
||
977 | Halt; |
||
978 | end; |
||
979 | |||
980 | FLocked := False; |
||
981 | end; |
||
982 | |||
983 | //頂点配列とインデクス配列のサイズを再設定 |
||
984 | //Reconfigure the size of the array and vertex array indices |
||
985 | |||
986 | procedure TSXMesh.SetSize(newVertexCount, newIndexCount: Word); |
||
987 | var |
||
988 | vbdesc: TD3DVERTEXBUFFERDESC; |
||
989 | begin |
||
990 | FVertexCount := newVertexCount; |
||
991 | FIndexCount := newIndexCount; |
||
992 | FFaceCount := newIndexCount div 3; |
||
993 | |||
994 | //まず、既存のVertexBufferの解放 |
||
995 | //When exist VertexBuffer, release it |
||
996 | if FVBuf <> nil then |
||
997 | FVBuf := nil; //.Release; |
||
998 | |||
999 | //VertexBufferの生成 |
||
1000 | //Generate VertexBuffer |
||
1001 | ZeroMemory(@vbdesc, Sizeof(vbdesc)); |
||
1002 | with vbdesc do |
||
1003 | begin |
||
1004 | dwSize := Sizeof(vbdesc); |
||
1005 | {$IFNDEF D3D_deprecated} |
||
1006 | if not (dtTnLHAL in FOwner.D3DDeviceTypeSet) then |
||
1007 | dwCaps := D3DVBCAPS_SYSTEMMEMORY |
||
1008 | else |
||
1009 | {$ENDIF} |
||
1010 | dwCaps := 0; |
||
1011 | |||
1012 | dwFVF := FVFFlags; |
||
1013 | dwNumVertices := newVertexCount; |
||
1014 | end; |
||
1015 | FOwner.D3D7.CreateVertexBuffer(vbdesc, FVBuf, 0); |
||
1016 | |||
1017 | //頂点インデクス配列の設定 |
||
1018 | //Vertex set of the array index |
||
1019 | |||
1020 | if not FRecovery then |
||
1021 | SetLength(FIndices, newIndexCount); |
||
1022 | |||
1023 | end; |
||
1024 | |||
1025 | //最適かするっ。ロックとかはできなくなるよ |
||
1026 | //Optimize, cannot be locked |
||
1027 | procedure TSXMesh.Optimize; |
||
1028 | begin |
||
1029 | FVBuf.Optimize(FOwner.D3DDevice7, 0); |
||
1030 | end; |
||
1031 | |||
1032 | { TSXFrame } |
||
1033 | |||
1034 | constructor TSXFrame.Create(parentFrame: TSXFrame); |
||
1035 | begin |
||
1036 | inherited Create; |
||
1037 | |||
1038 | //親子関係の初期化 |
||
1039 | //Initialize parent-child relationship |
||
1040 | FAncestors := TSXFrameList.Create; |
||
1041 | if ParentFrame <> nil then |
||
1042 | begin |
||
1043 | //Ancestral copy of the list |
||
1044 | FAncestors.Assign(parentFrame.Ancestors); //先祖リストのコピー |
||
1045 | //Fathers at the end of the list, put the parent |
||
1046 | FAncestors.Add(parentFrame); //先祖リストの末尾に、親を入れる |
||
1047 | //Parents put their children to the list |
||
1048 | ParentFrame.Children.Add(Self); //親の子リストに自分をつける |
||
1049 | end; |
||
1050 | |||
1051 | FChildren := TSXFrameList.Create; |
||
1052 | FParent := parentFrame; |
||
1053 | |||
1054 | FBindMaterial := False; |
||
1055 | FBindRenderState := False; |
||
1056 | FBindTexture := False; |
||
1057 | |||
1058 | |||
1059 | //変数とかの初期化 |
||
1060 | //Variable Or First Initialization |
||
1061 | |||
1062 | FMatrix := D3DUtil_SetIdentityMatrix; |
||
1063 | FMeshMatrix := D3DUtil_SetIdentityMatrix; |
||
1064 | |||
1065 | BlendMode := rtDraw; |
||
1066 | Material := MakeMaterial(1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 10.0); |
||
1067 | |||
1068 | Visibility := sxvShow; |
||
1069 | Lighting := True; |
||
1070 | Specular := True; |
||
1071 | |||
1072 | |||
1073 | OnRenderMesh := nil; |
||
1074 | Mesh := nil; |
||
1075 | Texture := nil; |
||
1076 | |||
1077 | end; |
||
1078 | |||
1079 | destructor TSXFrame.Destroy; |
||
1080 | begin |
||
1081 | inherited; |
||
1082 | |||
1083 | while Children.Count > 0 do |
||
1084 | begin //This child frame is recursively Freed |
||
1085 | Children[0].Free; //これで、再帰的に子フレームがFreeされる |
||
1086 | end; |
||
1087 | |||
1088 | //リストオブジェクトの解放 |
||
1089 | //Object free list |
||
1090 | |||
1091 | FChildren.Free; |
||
1092 | FAncestors.Free; |
||
1093 | |||
1094 | //親のリストから自分をはずす |
||
1095 | //Remove yourself from the list of parents |
||
1096 | |||
1097 | if Parent <> nil then |
||
1098 | Parent.Children.Delete(Parent.Children.IndexOf(Self)); |
||
1099 | |||
1100 | end; |
||
1101 | |||
1102 | //自分の座標→ワールド座標 のための変換行列を得る |
||
1103 | //To obtain the world coordinate transformation matrix → coordinate their |
||
1104 | |||
1105 | function TSXFrame.GetWorldMatrix: TD3DMATRIX; |
||
1106 | var |
||
1107 | mat: TD3DMATRIX; |
||
1108 | i: Integer; |
||
1109 | begin |
||
1110 | |||
1111 | mat := FMatrix; |
||
1112 | |||
1113 | //祖先のマトリクスを 親→祖父… の順に乗じていく。 |
||
1114 | //Ancestors[0] はNilであり、途中にNilは入らないという前提の下に計算 |
||
1115 | // Parent → grandfather ... we multiply the matrix of the ancestral order. |
||
1116 | // Ancestors [0] is not Nil, Nil way under the assumption that the fit is calculated |
||
1117 | |||
1118 | for i := Ancestors.Count - 1 downto 1 do |
||
1119 | begin |
||
1120 | {$IFDEF USE_S_MATHPACK} |
||
1121 | mat := NowCompositeMatrix(mat, Ancestors[i].FMatrix); |
||
1122 | {$ELSE} |
||
1123 | D3DMath_MatrixMultiply(mat, FMatrix, Ancestors[i].FMatrix) |
||
1124 | {$ENDIF} |
||
1125 | end; |
||
1126 | |||
1127 | result := mat; |
||
1128 | end; |
||
1129 | |||
1130 | //…Z軸をtargetフレーム内の座標posを向ける。worldフレームのY軸をupベクトルに指定し、Y軸のZ軸回りの傾きをbank度とする |
||
1131 | // Z axis toward the target coordinates in the frame pos. Y-axis of world frame specified in the up vector, Y and Z axis tilt of the axis around which at bank |
||
1132 | |||
1133 | procedure TSXFrame.LookAt(target: TSXFrame; const pos: TD3DVector; world: TSXFrame; const bank: Integer); |
||
1134 | var |
||
1135 | vRel: TD3DVECTOR; //Targetとの相対座標 //Target coordinates to relative |
||
1136 | vecCeil: TD3Dvector; //天井のベクトル //Vector Ceiling |
||
1137 | vecX, vecY, vecZ: TD3DVECTOR; |
||
1138 | normX: Single; //X軸の長さ(天井とZが平行かどうかのチェック用) |
||
1139 | //The length of the X-axis (Z and for checking whether the ceiling parallel) |
||
1140 | begin |
||
1141 | |||
1142 | { |
||
1143 | //targetのposは、自分の座標系でどこなのか |
||
1144 | vRel:=WorldToLocal(target.LocalToWorld(pos)); |
||
1145 | |||
1146 | //向き = Z軸ベクトル |
||
1147 | vecZ:=NowNormalize(vRel); |
||
1148 | |||
1149 | //YZ平面にvRelを射影して、X軸と外積を取って新しいY軸を得る |
||
1150 | vecY:=NowCrossProduct(Vector(0,vecZ.Y,vecZ.Z), Vector(1,0,0)); |
||
1151 | |||
1152 | vecY:=NowNormalize(vecY); |
||
1153 | |||
1154 | SetOrientation(Self, vecZ, vecY); |
||
1155 | } |
||
1156 | |||
1157 | |||
1158 | //targetのposは、自分の座標系でどこなのか |
||
1159 | //pos of target, or a coordinate system where one |
||
1160 | |||
1161 | vRel := WorldToLocal(target.LocalToWorld(pos)); |
||
1162 | |||
1163 | //向き = Z軸ベクトル |
||
1164 | //Direction = Z axis vector |
||
1165 | |||
1166 | {$IFDEF USE_S_MATHPACK} |
||
1167 | vecZ := NowNormalize(vRel); |
||
1168 | {$ELSE} |
||
1169 | vecZ := D3DMath_VecNormalize(vRel); |
||
1170 | {$ENDIF} |
||
1171 | //天井の向き = worldのY軸 |
||
1172 | //Ceiling Direction = World of the Y-axis |
||
1173 | |||
1174 | {$IFDEF USE_S_MATHPACK} |
||
1175 | vecCeil := NowSub(WorldToLocal(world.LocalToWorld(Vector(0, 1, 0))), WorldToLocal(world.LocalToWorld(Vector(0, 0, 0)))); |
||
1176 | vecCeil := NowNormalize(vecCeil); |
||
1177 | {$ELSE} |
||
1178 | vecCeil := D3DMath_Vec3Subtract(WorldToLocal(world.LocalToWorld(MakeD3DVector(0, 1, 0))), WorldToLocal(world.LocalToWorld(MakeD3DVector(0, 0, 0)))); |
||
1179 | vecCeil := D3DMath_VecNormalize(vecCeil); |
||
1180 | {$ENDIF} |
||
1181 | |||
1182 | //天井とZで外積を取って、Xの向きとする |
||
1183 | //Taking the cross product in the ceiling and Z and the direction of the X |
||
1184 | |||
1185 | {$IFDEF USE_S_MATHPACK} |
||
1186 | vecX := NowCrossProduct(vecCeil, vecZ); |
||
1187 | {$ELSE} |
||
1188 | vecX := D3DMath_Vec3Cross(vecCeil, vecZ); |
||
1189 | {$ENDIF} |
||
1190 | |||
1191 | //天井とZが平行な場合、右耳の方向をworldのX軸にする |
||
1192 | //And Z is parallel to the ceiling, the direction of the X-axis of the world right ear |
||
1193 | {$IFDEF USE_S_MATHPACK} |
||
1194 | normX := NowLength(vecX); |
||
1195 | {$ELSE} |
||
1196 | normX := D3DMath_Vec3Length(vecX); |
||
1197 | {$ENDIF} |
||
1198 | if normX < 0.0001 then |
||
1199 | {$IFDEF USE_S_MATHPACK} |
||
1200 | vecX := NowSub(WorldToLocal(world.LocalToWorld(Vector(1, 0, 0))), WorldToLocal(world.LocalToWorld(Vector(0, 0, 0)))); |
||
1201 | {$ELSE} |
||
1202 | vecX := D3DMath_Vec3Subtract(WorldToLocal(world.LocalToWorld(MakeD3DVector(1, 0, 0))), WorldToLocal(world.LocalToWorld(MakeD3DVector(0, 0, 0)))); |
||
1203 | {$ENDIF} |
||
1204 | |||
1205 | {$IFDEF USE_S_MATHPACK} |
||
1206 | vecX := NowNormalize(vecX); |
||
1207 | {$ELSE} |
||
1208 | vecX := D3DMath_VecNormalize(vecX); |
||
1209 | {$ENDIF} |
||
1210 | |||
1211 | //XとZで外積を取って、Yの向きとする |
||
1212 | //Taking the cross product in X and Z direction and the Y |
||
1213 | |||
1214 | {$IFDEF USE_S_MATHPACK} |
||
1215 | vecY := NowNormalize(NowCrossProduct(vecZ, vecX)); |
||
1216 | {$ELSE} |
||
1217 | vecY := D3DMath_VecNormalize(D3DMath_Vec3Cross(vecZ, vecX)); |
||
1218 | {$ENDIF} |
||
1219 | |||
1220 | //以上で姿勢の計算完了~セット |
||
1221 | //Complete set - at least calculate the position |
||
1222 | |||
1223 | SetOrientation(Self, vecZ, vecY); |
||
1224 | |||
1225 | //バンク |
||
1226 | //Bank |
||
1227 | if bank <> 0 then |
||
1228 | {$IFDEF USE_S_MATHPACK} |
||
1229 | SetTransform(Self, NowRotZMatrix(bank)); |
||
1230 | {$ELSE} |
||
1231 | begin |
||
1232 | SetTransform(Self, D3DUtil_SetRotateZMatrix(bank)); |
||
1233 | end; |
||
1234 | {$ENDIF} |
||
1235 | end; |
||
1236 | |||
1237 | //refに対する変換行列の設定 |
||
1238 | |||
1239 | procedure TSXFrame.SetTransform(ref: TSXFrame; const mat: TD3DMATRIX); |
||
1240 | begin |
||
1241 | |||
1242 | if ref = Self then |
||
1243 | begin |
||
1244 | //自分への変換行列 |
||
1245 | {$IFDEF USE_S_MATHPACK} |
||
1246 | FMatrix := NowCompositeMatrix(mat, FMatrix); |
||
1247 | {$ELSE} |
||
1248 | FMatrix := D3DMath_MatrixMultiply(mat, FMatrix) |
||
1249 | {$ENDIF} |
||
1250 | |||
1251 | |||
1252 | end |
||
1253 | else |
||
1254 | if ref = Parent then |
||
1255 | begin |
||
1256 | //親への変換行列 |
||
1257 | //Transformation matrix to the parent |
||
1258 | FMatrix := mat; |
||
1259 | |||
1260 | end |
||
1261 | else |
||
1262 | begin |
||
1263 | |||
1264 | //自分→ref→ワールド→親 |
||
1265 | //Ones to ref to World to Parent |
||
1266 | if Parent <> nil then |
||
1267 | begin |
||
1268 | if ref <> nil then |
||
1269 | {$IFDEF USE_S_MATHPACK} |
||
1270 | FMatrix := NowCompositeMatrix( |
||
1271 | NowCompositeMatrix(mat, ref.WorldMatrix), |
||
1272 | NowInvMatrix(Parent.WorldMatrix) |
||
1273 | ) |
||
1274 | {$ELSE} |
||
1275 | begin |
||
1276 | FMatrix := D3DMath_MatrixMultiply(D3DMath_MatrixMultiply(mat, WorldMatrix), D3DMath_MatrixInvert(Parent.WorldMatrix)) |
||
1277 | end |
||
1278 | {$ENDIF} |
||
1279 | else |
||
1280 | {$IFDEF USE_S_MATHPACK} |
||
1281 | FMatrix := NowCompositeMatrix(mat, NowInvMatrix(Parent.WorldMatrix)); |
||
1282 | {$ELSE} |
||
1283 | begin |
||
1284 | FMatrix := D3DMath_MatrixMultiply(mat, D3DMath_MatrixInvert(Parent.WorldMatrix)); |
||
1285 | end |
||
1286 | {$ENDIF} |
||
1287 | end |
||
1288 | else |
||
1289 | begin |
||
1290 | if ref <> nil then |
||
1291 | {$IFDEF USE_S_MATHPACK} |
||
1292 | FMatrix := NowCompositeMatrix(mat, ref.WorldMatrix) |
||
1293 | {$ELSE} |
||
1294 | begin |
||
1295 | FMatrix := D3DMath_MatrixMultiply(mat, ref.WorldMatrix) |
||
1296 | end |
||
1297 | {$ENDIF} |
||
1298 | else |
||
1299 | FMatrix := mat; |
||
1300 | end; |
||
1301 | end; |
||
1302 | end; |
||
1303 | |||
1304 | //refに対する変換行列の取得 |
||
1305 | //ref to get the transformation matrix |
||
1306 | |||
1307 | function TSXFrame.GetTransform(ref: TSXFrame): TD3DMATRIX; |
||
1308 | begin |
||
1309 | |||
1310 | if ref = Self then |
||
1311 | begin |
||
1312 | //自分への変換を得る…単位行列に決まってる。 |
||
1313 | //Their conversion to get ... I decided the matrix. |
||
1314 | |||
1315 | result := D3DUtil_SetIdentityMatrix; |
||
1316 | |||
1317 | end |
||
1318 | else |
||
1319 | if ref = Parent then |
||
1320 | begin |
||
1321 | |||
1322 | //親へのオリエンテーションを得る |
||
1323 | //Get to the parent orientation |
||
1324 | |||
1325 | result := FMatrix; |
||
1326 | |||
1327 | end |
||
1328 | else |
||
1329 | begin |
||
1330 | |||
1331 | //自分→ワールド→ref |
||
1332 | //Ones to World to Ref |
||
1333 | if ref <> nil then |
||
1334 | {$IFDEF USE_S_MATHPACK} |
||
1335 | result := NowCompositeMatrix(WorldMatrix, NowInvMatrix(ref.WorldMatrix)) |
||
1336 | {$ELSE} |
||
1337 | begin |
||
1338 | Result := D3DMath_MatrixMultiply(WorldMatrix, D3DMath_MatrixInvert(Parent.WorldMatrix)); |
||
1339 | end |
||
1340 | {$ENDIF} |
||
1341 | else |
||
1342 | result := WorldMatrix; |
||
1343 | end; |
||
1344 | end; |
||
1345 | |||
1346 | //姿勢の設定 |
||
1347 | //Setting position |
||
1348 | |||
1349 | procedure TSXFrame.SetOrientation(ref: TSXFrame; const vecZ: TD3DVector; |
||
1350 | const vecY: TD3DVector); |
||
1351 | var |
||
1352 | tmpMat: TD3DMATRIX; //refフレームとの相対変換行列 //relative to ref frame transformation matrix |
||
1353 | vTrans: array[0..3] of Single; //平行移動成分の保存用 //Translation component storage |
||
1354 | vecX: TD3DVECTOR; |
||
1355 | begin |
||
1356 | {$IFDEF USE_S_MATHPACK} |
||
1357 | vecX := NowNormalize(NowCrossProduct(vecY, vecZ)); |
||
1358 | {$ELSE} |
||
1359 | vecX := D3DMath_VecNormalize(D3DMath_Vec3Cross(vecY, vecZ)); |
||
1360 | {$ENDIF} |
||
1361 | if ref = Parent then |
||
1362 | begin |
||
1363 | |||
1364 | //親への姿勢を作るだけなら、簡単 |
||
1365 | //If you just make a commitment to parents, simply |
||
1366 | |||
1367 | with FMatrix do |
||
1368 | begin |
||
1369 | _11 := vecX.X; _12 := vecX.Y; _13 := vecX.Z; |
||
1370 | _21 := vecY.X; _22 := vecY.Y; _23 := vecY.Z; |
||
1371 | _31 := vecZ.X; _32 := vecZ.Y; _33 := vecZ.Z; |
||
1372 | end; |
||
1373 | |||
1374 | end |
||
1375 | else |
||
1376 | begin |
||
1377 | |||
1378 | //平行移動成分の保存 |
||
1379 | //Save the translation component |
||
1380 | |||
1381 | vTrans[0] := FMatrix._41; |
||
1382 | vTrans[1] := FMatrix._42; |
||
1383 | vTrans[2] := FMatrix._43; |
||
1384 | |||
1385 | //変換 |
||
1386 | //transformation |
||
1387 | with tmpMat do |
||
1388 | begin |
||
1389 | _11 := vecX.X; _12 := vecX.Y; _13 := vecX.Z; _14 := 0; |
||
1390 | _21 := vecY.X; _22 := vecY.Y; _23 := vecY.Z; _24 := 0; |
||
1391 | _31 := vecZ.X; _32 := vecZ.Y; _33 := vecZ.Z; _34 := 0; |
||
1392 | _41 := vTrans[0]; _42 := vTrans[1]; _43 := vTrans[2]; _44 := 1; |
||
1393 | end; |
||
1394 | |||
1395 | SetTransform(ref, tmpMat); |
||
1396 | |||
1397 | //Restoring the translation component |
||
1398 | |||
1399 | with FMatrix do |
||
1400 | begin |
||
1401 | _41 := vTrans[0]; _42 := vTrans[1]; _43 := vTrans[2]; |
||
1402 | end; |
||
1403 | |||
1404 | end; |
||
1405 | |||
1406 | end; |
||
1407 | |||
1408 | //位置の設定 |
||
1409 | //Set Position |
||
1410 | |||
1411 | procedure TSXFrame.SetTranslation(ref: TSXFrame; const pos: TD3Dvector); |
||
1412 | var |
||
1413 | tmpMat: TD3DMATRIX; //refフレームとの相対変換行列 //relative to ref frame transformation matrix |
||
1414 | origMat: TD3DMATRIX; //For postural |
||
1415 | |||
1416 | begin |
||
1417 | |||
1418 | if ref = Parent then |
||
1419 | begin |
||
1420 | |||
1421 | //親へのトランスレーションを作るだけなら、簡単 |
||
1422 | //If you only make the translation to the parent easily |
||
1423 | |||
1424 | with FMatrix do |
||
1425 | begin |
||
1426 | _41 := pos.X; _42 := pos.Y; _43 := pos.Z; |
||
1427 | end; |
||
1428 | |||
1429 | end |
||
1430 | else |
||
1431 | begin |
||
1432 | |||
1433 | origMat := FMatrix; |
||
1434 | tmpMat := FMatrix; |
||
1435 | |||
1436 | with tmpMat do |
||
1437 | begin |
||
1438 | _41 := pos.X; _42 := pos.Y; _43 := pos.Z; |
||
1439 | end; |
||
1440 | |||
1441 | SetTransform(ref, tmpMat); |
||
1442 | |||
1443 | with FMatrix do |
||
1444 | begin |
||
1445 | _11 := OrigMat._11; _12 := OrigMat._12; _13 := OrigMat._13; |
||
1446 | _21 := OrigMat._21; _22 := OrigMat._22; _23 := OrigMat._23; |
||
1447 | _31 := OrigMat._31; _32 := OrigMat._32; _33 := OrigMat._33; |
||
1448 | end; |
||
1449 | end; |
||
1450 | end; |
||
1451 | |||
1452 | procedure TSXFrame.GetOrientation(ref: TSXFrame; var vecZ, |
||
1453 | vecY: TD3DVector); |
||
1454 | var |
||
1455 | tmpMat: TD3DMATRIX; //Results calculated buffer |
||
1456 | begin |
||
1457 | |||
1458 | tmpMat := GetTransform(ref); |
||
1459 | |||
1460 | with vecY, tmpMat do |
||
1461 | begin |
||
1462 | X := _21; Y := _22; Z := _23; |
||
1463 | end; |
||
1464 | |||
1465 | with vecZ, tmpMat do |
||
1466 | begin |
||
1467 | X := _31; Y := _32; Z := _33; |
||
1468 | end; |
||
1469 | end; |
||
1470 | |||
1471 | //姿勢だけをマトリクスで与える |
||
1472 | //Just give the attitude matrix |
||
1473 | |||
1474 | procedure TSXFrame.SetOrientationMatrix(ref: TSXFrame; |
||
1475 | const mat: TD3DMATRIX); |
||
1476 | var |
||
1477 | pushedV: TD3DVector; //平行移動分保存用 //Save Translates for minutes |
||
1478 | begin |
||
1479 | |||
1480 | //保存 |
||
1481 | //Save |
||
1482 | with pushedV do |
||
1483 | begin |
||
1484 | x := FMatrix._41; y := FMatrix._42; z := FMatrix._43; |
||
1485 | end; |
||
1486 | |||
1487 | if ref = Self then |
||
1488 | begin |
||
1489 | //自分への変換行列 |
||
1490 | //His conversion matrix |
||
1491 | |||
1492 | {$IFDEF USE_S_MATHPACK} |
||
1493 | FMatrix := NowCompositeMatrix(mat, FMatrix); |
||
1494 | {$ELSE} |
||
1495 | FMatrix := D3DMath_MatrixMultiply(mat, FMatrix) |
||
1496 | {$ENDIF} |
||
1497 | |||
1498 | end |
||
1499 | else |
||
1500 | if ref = Parent then |
||
1501 | begin |
||
1502 | //親への変換行列 |
||
1503 | //Transformation matrix to the parent |
||
1504 | |||
1505 | FMatrix := mat; |
||
1506 | |||
1507 | end |
||
1508 | else |
||
1509 | begin |
||
1510 | |||
1511 | //自分→ref→ワールド→親 |
||
1512 | //My→ref →World →Parent |
||
1513 | |||
1514 | if Parent <> nil then |
||
1515 | begin |
||
1516 | if ref <> nil then |
||
1517 | {$IFDEF USE_S_MATHPACK} |
||
1518 | FMatrix := NowCompositeMatrix( |
||
1519 | NowCompositeMatrix(mat, ref.WorldMatrix), |
||
1520 | NowInvMatrix(Parent.WorldMatrix)) |
||
1521 | {$ELSE} |
||
1522 | begin |
||
1523 | FMatrix := D3DMath_MatrixMultiply(D3DMath_MatrixMultiply(mat, ref.WorldMatrix), D3DMath_MatrixInvert(Parent.WorldMatrix)) |
||
1524 | end |
||
1525 | {$ENDIF} |
||
1526 | else |
||
1527 | {$IFDEF USE_S_MATHPACK} |
||
1528 | FMatrix := NowCompositeMatrix(mat, NowInvMatrix(Parent.WorldMatrix)); |
||
1529 | {$ELSE} |
||
1530 | begin |
||
1531 | FMatrix := D3DMath_MatrixMultiply(mat, D3DMath_MatrixInvert(Parent.WorldMatrix)); |
||
1532 | end |
||
1533 | {$ENDIF} |
||
1534 | end |
||
1535 | else |
||
1536 | begin |
||
1537 | if ref <> nil then |
||
1538 | {$IFDEF USE_S_MATHPACK} |
||
1539 | FMatrix := NowCompositeMatrix(mat, ref.WorldMatrix) |
||
1540 | {$ELSE} |
||
1541 | begin |
||
1542 | FMatrix := D3DMath_MatrixMultiply(mat, ref.WorldMatrix) |
||
1543 | end |
||
1544 | {$ENDIF} |
||
1545 | else |
||
1546 | FMatrix := mat; |
||
1547 | end; |
||
1548 | |||
1549 | end; |
||
1550 | |||
1551 | //復元 |
||
1552 | //Restore |
||
1553 | with pushedV do |
||
1554 | begin |
||
1555 | FMatrix._41 := x; FMatrix._42 := y; FMatrix._43 := z; |
||
1556 | end; |
||
1557 | end; |
||
1558 | |||
1559 | |||
1560 | function TSXFrame.GetTranslation(ref: TSXFrame): TD3DVECTOR; |
||
1561 | var |
||
1562 | tmpMat: TD3DMATRIX; //結果算出用バッファ Results calculated buffer |
||
1563 | begin |
||
1564 | |||
1565 | if ref = Parent then |
||
1566 | begin |
||
1567 | result.X := FMatrix._41; |
||
1568 | result.Y := FMatrix._42; |
||
1569 | result.Z := FMatrix._43; |
||
1570 | end |
||
1571 | else |
||
1572 | begin |
||
1573 | tmpMat := GetTransform(ref); |
||
1574 | result.X := tmpMat._41; |
||
1575 | result.Y := tmpMat._42; |
||
1576 | result.Z := tmpMat._43; |
||
1577 | end; |
||
1578 | |||
1579 | end; |
||
1580 | |||
1581 | //フレーム内の座標→ワールド座標 |
||
1582 | //Coordinates in world coordinate frame |
||
1583 | |||
1584 | function TSXFrame.LocalToWorld(vec: TD3DVector): TD3DVector; |
||
1585 | begin |
||
1586 | {$IFDEF USE_S_MATHPACK} |
||
1587 | Result := NowHeteroginize(NowTransform(NowHomoginize(vec), WorldMatrix)); |
||
1588 | {$ELSE} |
||
1589 | Result := D3DMath_VecHeterogenize(D3DMath_VecTransform(D3DMath_VecHomogenize(vec), WorldMatrix)) |
||
1590 | {$ENDIF} |
||
1591 | end; |
||
1592 | |||
1593 | //ワールド座標→フレーム内の座標 |
||
1594 | //Coordinates in world coordinate frame |
||
1595 | |||
1596 | function TSXFrame.WorldToLocal(vec: TD3DVector): TD3DVector; |
||
1597 | begin |
||
1598 | {$IFDEF USE_S_MATHPACK} |
||
1599 | Result := NowHeteroginize(NowTransform(NowHomoginize(vec), NowInvMatrix(WorldMatrix))); |
||
1600 | {$ELSE} |
||
1601 | Result := D3DMath_VecHeterogenize(D3DMath_VecTransform(D3DMath_VecHomogenize(vec), D3DMath_MatrixInvert(WorldMatrix))); |
||
1602 | {$ENDIF} |
||
1603 | end; |
||
1604 | |||
1605 | //親フレームの変更 |
||
1606 | //Changing the parent frame |
||
1607 | |||
1608 | procedure TSXFrame.SetParent(const Value: TSXFrame); |
||
1609 | |||
1610 | //先祖リストを再帰的に修正する |
||
1611 | //Fix recursive ancestor list |
||
1612 | |||
1613 | procedure RebuildAncestors(me: TSXFrame); |
||
1614 | var |
||
1615 | i: Integer; |
||
1616 | begin |
||
1617 | for i := 0 to me.Children.Count - 1 do |
||
1618 | begin |
||
1619 | //ヲレの先祖を先祖と崇めなさい |
||
1620 | //Ancestor worship ancestors and record your Wo |
||
1621 | |||
1622 | me.Children[i].Ancestors.Assign(me.Ancestors); |
||
1623 | //ヲレを親と崇めなさい |
||
1624 | //Users report your parents to revere |
||
1625 | |||
1626 | me.Children[i].Ancestors.Add(me); |
||
1627 | //子々孫々に渡ってそうしたまへ |
||
1628 | //Sometimes we do that across to our children grandchildren |
||
1629 | |||
1630 | RebuildAncestors(me.Children[i]); |
||
1631 | end; |
||
1632 | end; |
||
1633 | |||
1634 | begin |
||
1635 | //元の親のリストから外す |
||
1636 | //Removed from the list of the original parent |
||
1637 | |||
1638 | if FParent <> nil then |
||
1639 | FParent.Children.Delete(FParent.Children.IndexOf(Self)); |
||
1640 | |||
1641 | |||
1642 | if Value <> nil then |
||
1643 | begin |
||
1644 | //新しい親のリストに加える |
||
1645 | //Add to the list of new parent |
||
1646 | |||
1647 | Value.Children.Add(Self); |
||
1648 | //先祖リストを変える |
||
1649 | //Changing the list of ancestors |
||
1650 | |||
1651 | Ancestors.Assign(Value.Ancestors); |
||
1652 | Ancestors.Add(Value); |
||
1653 | end |
||
1654 | else |
||
1655 | begin |
||
1656 | Ancestors.Clear; |
||
1657 | end; |
||
1658 | |||
1659 | //自分に子供がいるなら、それらの先祖リストも変える |
||
1660 | //If you have children yourself, they also change the list of ancestors |
||
1661 | |||
1662 | RebuildAncestors(Self); |
||
1663 | |||
1664 | FParent := Value; |
||
1665 | end; |
||
1666 | |||
1667 | //このフレームをカメラにした場合のビュー行列を計算 |
||
1668 | //When calculating the view matrix of the camera frame |
||
1669 | |||
1670 | function TSXFrame.ViewMatrix: TD3DMatrix; |
||
1671 | begin |
||
1672 | {$IFDEF USE_S_MATHPACK} |
||
1673 | Result := NowInvMatrix(WorldMatrix); |
||
1674 | {$ELSE} |
||
1675 | Result := D3DMath_MatrixInvert(WorldMatrix) |
||
1676 | {$ENDIF} |
||
1677 | end; |
||
1678 | |||
1679 | { TSXFrameList } |
||
1680 | |||
1681 | //コピー |
||
1682 | //Copy |
||
1683 | |||
1684 | procedure TSXFrameList.Assign(source: TSXFrameList); |
||
1685 | var |
||
1686 | i: Integer; |
||
1687 | begin |
||
1688 | Self.Clear; |
||
1689 | |||
1690 | for i := 0 to source.Count - 1 do |
||
1691 | begin |
||
1692 | Self.Add(Pointer(source.Frames[i])); |
||
1693 | end; |
||
1694 | end; |
||
1695 | |||
1696 | constructor TSXFrameList.Create; |
||
1697 | begin |
||
1698 | inherited; |
||
1699 | end; |
||
1700 | |||
1701 | destructor TSXFrameList.Destroy; |
||
1702 | begin |
||
1703 | inherited; |
||
1704 | end; |
||
1705 | |||
1706 | function TSXFrameList.GetFrame(idx: Integer): TSXFrame; |
||
1707 | begin |
||
1708 | result := Items[idx]; |
||
1709 | end; |
||
1710 | |||
1711 | procedure TSXFrameList.SetFrame(idx: Integer; const Value: TSXFrame); |
||
1712 | begin |
||
1713 | Items[idx] := Pointer(Value); |
||
1714 | end; |
||
1715 | |||
1716 | { TSXScene } |
||
1717 | |||
1718 | constructor TSXScene.Create(DDCompo: TDXDRaw); |
||
1719 | begin |
||
1720 | inherited Create; |
||
1721 | |||
1722 | AlphaQueue := TSXRenderingQueue.Create(DDCompo, Self); |
||
1723 | OpaqueQueue := TSXRenderingQueue.Create(DDCompo, Self); |
||
1724 | AddQueue := TSXRenderingQueue.Create(DDCompo, Self); |
||
1725 | SubQueue := TSXRenderingQueue.Create(DDCompo, Self); |
||
1726 | |||
1727 | { |
||
1728 | MeshProcessor:=TSXMesh.Create(DDCompo); |
||
1729 | MeshProcessor.VertexSize:=Sizeof(D3DTLVERTEX); |
||
1730 | MeshProcessor.FVF:=D3DFVF_TLVERTEX; |
||
1731 | MeshProcessor.SetSize(65535,65535); //(^^;) |
||
1732 | |||
1733 | MeshProcessorMT:=TSXMesh.Create(DDCompo); |
||
1734 | MeshProcessorMT.VertexSize:=Sizeof(TSXTLVertexMT); |
||
1735 | MeshProcessorMT.FVF:=FVF_SXTLVertexMT; |
||
1736 | MeshProcessorMT.SetSize(65535,65535); |
||
1737 | } |
||
1738 | |||
1739 | FCamera := nil; |
||
1740 | FOwner := DDCompo; |
||
1741 | end; |
||
1742 | |||
1743 | destructor TSXScene.Destroy; |
||
1744 | begin |
||
1745 | |||
1746 | AlphaQueue.Free; |
||
1747 | OpaqueQueue.Free; |
||
1748 | AddQueue.Free; |
||
1749 | SubQueue.Free; |
||
1750 | |||
1751 | //MeshProcessor.Free; |
||
1752 | //MeshProcessorMT.Free; |
||
1753 | |||
1754 | inherited; |
||
1755 | end; |
||
1756 | |||
1757 | //描画 |
||
1758 | |||
1759 | procedure TSXScene.Render(rootFrame: TSXFrame); |
||
1760 | var |
||
1761 | viewMat: TD3DMATRIX; |
||
1762 | curTexture: TDirect3DTexture2; |
||
1763 | curMaterial: TD3DMATERIAL7; |
||
1764 | curBlendMode: TRenderType; |
||
1765 | |||
1766 | procedure QueingFrame(frame: TSXFrame; const mat: TD3DMATRIX; RSBind, TexBind, MatBind: Boolean); |
||
1767 | var |
||
1768 | i: Integer; |
||
1769 | meshM: TD3DMATRIX; |
||
1770 | begin |
||
1771 | |||
1772 | //子フレーム無し、かつ、描画するメッシュなしなら、何もしない |
||
1773 | //Visibilityが「子供もひっくるめて隠す」でも何もしない |
||
1774 | //ただし、ビルボードがくっついてる時は、マトリクスの合成だけ行う |
||
1775 | if (not frame.BBAttached) then |
||
1776 | if ((frame.Children.Count = 0) and (frame.Mesh = nil)) or (frame.Visibility = sxvHide) then |
||
1777 | exit; |
||
1778 | |||
1779 | //変換行列の計算 |
||
1780 | {$IFDEF USE_S_MATHPACK} |
||
1781 | frame.RenderedMatrix := NowCompositeMatrix(frame.Matrix, mat); |
||
1782 | {$ELSE} |
||
1783 | frame.RenderedMatrix := D3DMath_MatrixMultiply(frame.Matrix, mat); |
||
1784 | {$ENDIF} |
||
1785 | |||
1786 | |||
1787 | //メッシュの描画 |
||
1788 | if frame.Mesh <> nil then |
||
1789 | begin |
||
1790 | {$IFDEF USE_S_MATHPACK} |
||
1791 | meshM := NowCompositeMatrix(frame.MeshMatrix, frame.RenderedMatrix); |
||
1792 | {$ELSE} |
||
1793 | meshM := D3DMath_MatrixMultiply(frame.MeshMatrix, frame.RenderedMatrix); |
||
1794 | {$ENDIF} |
||
1795 | //テクスチャがあるなら、貼り付ける。「親のテクスチャ使用」を強制されてないなら |
||
1796 | if not TexBind then |
||
1797 | curTexture := frame.Texture; |
||
1798 | |||
1799 | //マテリアルを設定する |
||
1800 | if not MatBind then |
||
1801 | curMaterial := frame.Material; |
||
1802 | |||
1803 | //レンダリングステートの設定 |
||
1804 | if not RSBind then |
||
1805 | curBlendMode := frame.BlendMode; |
||
1806 | |||
1807 | //キューに放り込む |
||
1808 | if frame.Visibility = sxvShow then |
||
1809 | begin |
||
1810 | case curBlendMode of |
||
1811 | rtAdd: AddQueue.PushMesh(frame.Mesh, frame, meshM, curTexture, curMaterial, frame.OnRenderMesh); |
||
1812 | rtBlend: AlphaQueue.PushMesh(frame.Mesh, frame, meshM, curTexture, curMaterial, frame.OnRenderMesh); |
||
1813 | rtDraw: OpaqueQueue.PushMesh(frame.Mesh, frame, meshM, curTexture, curMaterial, frame.OnRenderMesh); |
||
1814 | rtSub: SubQueue.PushMesh(frame.Mesh, frame, meshM, curTexture, curMaterial, frame.OnRenderMesh); |
||
1815 | end; |
||
1816 | end; |
||
1817 | end; |
||
1818 | |||
1819 | //子供の描画 |
||
1820 | for i := 0 to frame.Children.Count - 1 do |
||
1821 | begin |
||
1822 | QueingFrame(frame.Children[i], frame.RenderedMatrix, RSBind or frame.BindRenderState, TexBind or frame.BindTexture, MatBind or frame.BindMaterial); |
||
1823 | end; |
||
1824 | end; |
||
1825 | |||
1826 | begin |
||
1827 | |||
1828 | if FCamera = nil then |
||
1829 | begin |
||
1830 | //DDDD_PutDebugMessage('SXLib: カメラフレームが設定されていません'); |
||
1831 | exit; |
||
1832 | end; |
||
1833 | |||
1834 | //ビュー行列の作成…(ワールド座標系でのカメラフレームの姿勢)の逆 |
||
1835 | //Create a view matrix (camera position in world coordinate frame), the inverse |
||
1836 | |||
1837 | viewMat := CameraFrame.ViewMatrix; |
||
1838 | |||
1839 | FOwner.D3DDevice7.SetTransform(D3DTRANSFORMSTATE_VIEW, viewMat); |
||
1840 | |||
1841 | //再帰的にキューに入れる |
||
1842 | //Recursively queued |
||
1843 | |||
1844 | if rootFrame.Parent = nil then |
||
1845 | QueingFrame(rootFrame, D3DUtil_SetIdentityMatrix, false, false, false) |
||
1846 | else |
||
1847 | QueingFrame(rootFrame, rootFrame.Parent.WorldMatrix, false, false, false); |
||
1848 | |||
1849 | { キューに入ってる物体を描く } |
||
1850 | { I draw the object in the queue } |
||
1851 | |||
1852 | /////不透明体 |
||
1853 | //Opaque |
||
1854 | FOwner.D3DDevice7.SetRenderState(D3DRENDERSTATE_ZENABLE, 1); //Z比較あり |
||
1855 | FOwner.D3DDevice7.SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, 1); //Z書き込みあり |
||
1856 | |||
1857 | //ブレンドなし |
||
1858 | //No Blending |
||
1859 | FOwner.D3DDevice7.SetRenderState(D3DRENDERSTATE_BLENDENABLE, 0); |
||
1860 | |||
1861 | OpaqueQueue.Render(viewMat, FVP); |
||
1862 | |||
1863 | /////加算合成体 |
||
1864 | //Body additive synthesis |
||
1865 | FOwner.D3DDevice7.SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, 0); //Z書き込みなし |
||
1866 | |||
1867 | //ブレンドの設定 |
||
1868 | //Set of Blend |
||
1869 | FOwner.D3DDevice7.SetRenderState(D3DRENDERSTATE_BLENDENABLE, 1); |
||
1870 | |||
1871 | FOwner.D3DDevice7.SetTextureStageState(0, D3DTSS_COLORARG1, DWord(D3DTA_TEXTURE)); |
||
1872 | FOwner.D3DDevice7.SetTextureStageState(0, D3DTSS_COLORARG2, DWord(D3DTA_DIFFUSE)); |
||
1873 | FOwner.D3DDevice7.SetTextureStageState(0, D3DTSS_COLOROP, DWord(D3DTOP_MODULATE)); |
||
1874 | |||
1875 | FOwner.D3DDevice7.SetTextureStageState(0, D3DTSS_ALPHAARG1, DWord(D3DTA_TEXTURE)); |
||
1876 | FOwner.D3DDevice7.SetTextureStageState(0, D3DTSS_ALPHAARG2, DWord(D3DTA_DIFFUSE)); |
||
1877 | FOwner.D3DDevice7.SetTextureStageState(0, D3DTSS_ALPHAOP, DWord(D3DTOP_MODULATE)); |
||
1878 | |||
1879 | FOwner.D3DDevice7.SetRenderState(D3DRENDERSTATE_SRCBLEND, DWord(D3DBLEND_ONE)); |
||
1880 | FOwner.D3DDevice7.SetRenderState(D3DRENDERSTATE_DESTBLEND, DWord(D3DBLEND_ONE)); |
||
1881 | |||
1882 | AddQueue.Render(viewMat, FVP); |
||
1883 | |||
1884 | //半透明体 |
||
1885 | FOwner.D3DDevice7.SetRenderState(D3DRENDERSTATE_SRCBLEND, DWord(D3DBLEND_SRCALPHA)); |
||
1886 | FOwner.D3DDevice7.SetRenderState(D3DRENDERSTATE_DESTBLEND, DWord(D3DBLEND_INVSRCALPHA)); |
||
1887 | |||
1888 | AlphaQueue.Render(viewMat, FVP); |
||
1889 | |||
1890 | //減算合成体…減算はニセ減算だけど(^^;) |
||
1891 | FOwner.D3DDevice7.SetRenderState(D3DRENDERSTATE_SRCBLEND, DWord(D3DBLEND_ZERO)); |
||
1892 | FOwner.D3DDevice7.SetRenderState(D3DRENDERSTATE_DESTBLEND, DWord(D3DBLEND_INVSRCCOLOR)); |
||
1893 | |||
1894 | SubQueue.Render(viewMat, FVP); |
||
1895 | |||
1896 | //テクスチャに何も指定しない状態で、一連のレンダリングを終える |
||
1897 | FOwner.D3DDevice7.SetTexture(0, nil); |
||
1898 | end; |
||
1899 | |||
1900 | procedure TSXScene.Clear(dwFlags: DWord; color: DWORD; z: Single; stencil: DWord); |
||
1901 | var |
||
1902 | r: TD3DRect; |
||
1903 | begin |
||
1904 | with r do |
||
1905 | begin |
||
1906 | x1 := FVP.dwX; |
||
1907 | y1 := FVP.dwY; |
||
1908 | x2 := FVP.dwX + FVP.dwWidth; |
||
1909 | y2 := FVP.dwY + FVP.dwHeight; |
||
1910 | end; |
||
1911 | |||
1912 | FOwner.D3DDevice7.Clear(1, @r, dwFlags, color, z, stencil); |
||
1913 | end; |
||
1914 | |||
1915 | //透視変換の設定 |
||
1916 | |||
1917 | procedure TSXScene.SetProjection(fov, aspect, nearZ, farZ: Single); //透視変換の設定 |
||
1918 | var |
||
1919 | q, w, h: Single; |
||
1920 | begin |
||
1921 | |||
1922 | q := farZ / (farZ - nearZ); |
||
1923 | w := aspect * Cos(fov * 0.5) / Sin(fov * 0.5); |
||
1924 | h := Cos(fov * 0.5) / Sin(fov * 0.5); |
||
1925 | |||
1926 | FProjectionMatrix := D3DUtil_SetIdentityMatrix; |
||
1927 | |||
1928 | FProjectionMatrix._11 := w; // |
||
1929 | FProjectionMatrix._22 := h; // |
||
1930 | FProjectionMatrix._33 := q; // Q = Zf / (Zf-Zn) |
||
1931 | FProjectionMatrix._34 := 1.0; |
||
1932 | FProjectionMatrix._43 := -q * nearZ; // -QZn |
||
1933 | FProjectionMatrix._44 := 0.0; |
||
1934 | |||
1935 | FOwner.D3DDevice7.SetTransform(D3DTRANSFORMSTATE_PROJECTION, FProjectionMatrix); |
||
1936 | end; |
||
1937 | |||
1938 | procedure TSXScene.SetViewPort(left, top, right, bottom: DWord); |
||
1939 | begin |
||
1940 | ZeroMemory(@FVP, sizeof(FVP)); |
||
1941 | |||
1942 | with FVP do |
||
1943 | begin |
||
1944 | dwX := left; |
||
1945 | dwY := top; |
||
1946 | dwWidth := right - left; |
||
1947 | dwHeight := bottom - top; |
||
1948 | dvMinZ := 0; |
||
1949 | dvMaxZ := 1.0; |
||
1950 | end; |
||
1951 | |||
1952 | FOwner.D3DDevice7.SetViewport(FVP); |
||
1953 | end; |
||
1954 | |||
1955 | //D3D解放(解像度変更)からのリカバリ |
||
1956 | |||
1957 | procedure TSXScene.Recover; |
||
1958 | begin |
||
1959 | FOwner.D3DDevice7.SetViewport(FVP); |
||
1960 | FOwner.D3DDevice7.SetTransform(D3DTRANSFORMSTATE_PROJECTION, FProjectionMatrix); |
||
1961 | end; |
||
1962 | |||
1963 | //ビルボードを押し込む |
||
1964 | |||
1965 | procedure TSXScene.PushBillboard(blendMode: TRenderType; ref: TSXFrame; |
||
1966 | pos: TD3DVector; points: array of TSXVertexBB; tex: TDirect3DTexture2); |
||
1967 | begin |
||
1968 | case blendMode of |
||
1969 | rtAdd: AddQueue.PushBillboard(ref, pos, tex, points); |
||
1970 | rtBlend: AlphaQueue.PushBillboard(ref, pos, tex, points); |
||
1971 | rtDraw: OpaqueQueue.PushBillboard(ref, pos, tex, points); |
||
1972 | rtSub: SubQueue.PushBillboard(ref, pos, tex, points); |
||
1973 | end; |
||
1974 | //フラグを立てる |
||
1975 | ref.BBAttached := True; |
||
1976 | |||
1977 | end; |
||
1978 | |||
1979 | //球体の可視判定 |
||
1980 | |||
1981 | function TSXScene.SphereVisibility(ref: TSXFrame; pos: TD3DVector; |
||
1982 | radius: Single; depth: Single): Boolean; |
||
1983 | var |
||
1984 | viewM: TD3DMATRIX; //ref.posを視野座標系に変換する行列 |
||
1985 | projM: TD3DMATRIX; //透視変換行列(画角ゲット用) |
||
1986 | |||
1987 | p: TD3DVector; |
||
1988 | fovH, fovV: Single; //画角 |
||
1989 | cosFovH, sinFovH, cosFovV, sinFovV: Single; |
||
1990 | begin |
||
1991 | //まず、視野座標系に変換する |
||
1992 | {$IFDEF USE_S_MATHPACK} |
||
1993 | viewM := NowCompositeMatrix(ref.WorldMatrix, NowInvMatrix(CameraFrame.WorldMatrix)); |
||
1994 | p := NowHeteroginize(NowTransform(NowHomoginize(pos), viewM)); |
||
1995 | {$ELSE} |
||
1996 | viewM := D3DMath_MatrixMultiply(ref.WorldMatrix, D3DMath_MatrixInvert(CameraFrame.WorldMatrix)); |
||
1997 | p := D3DMath_VecHeterogenize(D3DMath_VecTransform(D3DMath_VecHomogenize(pos), viewM)); |
||
1998 | {$ENDIF} |
||
1999 | |||
2000 | //視界の後方や、depthより遠くにあるってのは論外 |
||
2001 | if (p.z < -radius) or (p.z > depth + radius) then |
||
2002 | begin |
||
2003 | Result := False; |
||
2004 | Exit; |
||
2005 | end; |
||
2006 | |||
2007 | //縦・横の画角を求める |
||
2008 | FOwner.D3DDevice7.GetTransform(D3DTRANSFORMSTATE_PROJECTION, projM); |
||
2009 | fovH := ArcTan(1.0 / projM._11); |
||
2010 | fovV := ArcTan(1.0 / projM._22); |
||
2011 | |||
2012 | //画角のSin,Cosを出しておく |
||
2013 | SinFovH := Sin(fovH); CosFovH := Cos(fovH); |
||
2014 | SinFovV := Sin(fovV); CosFovV := Cos(fovV); |
||
2015 | |||
2016 | //XZ平面での判定…画角分だけ球の中心を回転させた時、コーンの中心から球の中心までが、球の半径の値以下になるかを見る |
||
2017 | if ((p.x * CosFovH - p.z * SinFovH) > radius) or ((p.x * CosFovH + p.z * SinFovH) < -radius) then |
||
2018 | begin |
||
2019 | Result := False; |
||
2020 | Exit; |
||
2021 | end; |
||
2022 | |||
2023 | //YZ平面での判定 |
||
2024 | if ((p.y * CosfovV - p.z * SinfovV) > radius) or ((p.y * CosfovV + p.z * SinfovV) < -radius) then |
||
2025 | begin |
||
2026 | Result := False; |
||
2027 | Exit; |
||
2028 | end; |
||
2029 | |||
2030 | Result := True; |
||
2031 | end; |
||
2032 | |||
2033 | { TSXLight } |
||
2034 | |||
2035 | constructor TSXLight.Create(DDCompo: TDXDraw; index: DWord); |
||
2036 | begin |
||
2037 | inherited Create; |
||
2038 | |||
2039 | FOwner := DDCompo; |
||
2040 | FIndex := index; |
||
2041 | FEnabled := False; |
||
2042 | FUpdate := True; |
||
2043 | |||
2044 | //デフォ値の設定 |
||
2045 | ZeroMemory(@Params, Sizeof(Params)); |
||
2046 | with Params do |
||
2047 | begin |
||
2048 | dltType := D3DLIGHT_DIRECTIONAL; |
||
2049 | |||
2050 | dcvDiffuse.r := 1.0; |
||
2051 | dcvDiffuse.g := 1.0; |
||
2052 | dcvDiffuse.b := 1.0; |
||
2053 | {$IFDEF USE_S_MATHPACK} |
||
2054 | dvDirection := Vector(0, 0, 1); |
||
2055 | {$ELSE} |
||
2056 | dvDirection := MakeD3DVector(0, 0, 1); |
||
2057 | {$ENDIF} |
||
2058 | end; |
||
2059 | end; |
||
2060 | |||
2061 | destructor TSXLight.Destroy; |
||
2062 | begin |
||
2063 | inherited; |
||
2064 | end; |
||
2065 | |||
2066 | //D3Dにライトを登録 |
||
2067 | |||
2068 | procedure TSXLight.SetEnabled(const Value: Boolean); |
||
2069 | begin |
||
2070 | FEnabled := Value; |
||
2071 | |||
2072 | FOwner.D3DDevice7.SetLight(FIndex, Params); |
||
2073 | FOwner.D3DDevice7.LightEnable(FIndex, FEnabled); |
||
2074 | |||
2075 | end; |
||
2076 | |||
2077 | //お便利るーちんず |
||
2078 | |||
2079 | procedure TSXLight.SetupDiffuse(_R, _G, _B: Single); |
||
2080 | begin |
||
2081 | with Params.dcvDiffuse do |
||
2082 | begin |
||
2083 | dvR := _R; |
||
2084 | dvG := _G; |
||
2085 | dvB := _B; |
||
2086 | end; |
||
2087 | |||
2088 | if FUpdate then |
||
2089 | FOwner.D3DDevice7.SetLight(FIndex, Params); |
||
2090 | end; |
||
2091 | |||
2092 | procedure TSXLight.SetupSpecular(_R, _G, _B: Single); |
||
2093 | begin |
||
2094 | with Params.dcvSpecular do |
||
2095 | begin |
||
2096 | dvR := _R; |
||
2097 | dvG := _G; |
||
2098 | dvB := _B; |
||
2099 | end; |
||
2100 | |||
2101 | if FUpdate then |
||
2102 | FOwner.D3DDevice7.SetLight(FIndex, Params); |
||
2103 | end; |
||
2104 | |||
2105 | procedure TSXLight.SetupAmbient(_R, _G, _B: Single); |
||
2106 | begin |
||
2107 | with Params.dcvAmbient do |
||
2108 | begin |
||
2109 | dvR := _R; |
||
2110 | dvG := _G; |
||
2111 | dvB := _B; |
||
2112 | end; |
||
2113 | |||
2114 | if FUpdate then |
||
2115 | FOwner.D3DDevice7.SetLight(FIndex, Params); |
||
2116 | end; |
||
2117 | |||
2118 | procedure TSXLight.SetupColors(difR, difG, difB, specR, specG, specB, ambR, |
||
2119 | ambG, ambB: Single); |
||
2120 | begin |
||
2121 | with Params.dcvDiffuse do |
||
2122 | begin |
||
2123 | dvR := difR; |
||
2124 | dvG := difG; |
||
2125 | dvB := difB; |
||
2126 | end; |
||
2127 | with Params.dcvSpecular do |
||
2128 | begin |
||
2129 | dvR := specR; |
||
2130 | dvG := specG; |
||
2131 | dvB := specB; |
||
2132 | end; |
||
2133 | with Params.dcvAmbient do |
||
2134 | begin |
||
2135 | dvR := ambR; |
||
2136 | dvG := ambG; |
||
2137 | dvB := ambB; |
||
2138 | end; |
||
2139 | |||
2140 | if FUpdate then |
||
2141 | FOwner.D3DDevice7.SetLight(FIndex, Params); |
||
2142 | end; |
||
2143 | |||
2144 | procedure TSXLight.SetupRanges(range, att0, att1, att2: Single); |
||
2145 | begin |
||
2146 | with Params do |
||
2147 | begin |
||
2148 | dvRange := range; |
||
2149 | dvAttenuation0 := att0; |
||
2150 | dvAttenuation1 := att1; |
||
2151 | dvAttenuation2 := att2; |
||
2152 | end; |
||
2153 | |||
2154 | if FUpdate then |
||
2155 | FOwner.D3DDevice7.SetLight(FIndex, Params); |
||
2156 | end; |
||
2157 | |||
2158 | procedure TSXLight.SetupDirectional(dir: TD3DVector); |
||
2159 | begin |
||
2160 | Params.dltType := D3DLIGHT_DIRECTIONAL; |
||
2161 | Params.dvDirection := dir; |
||
2162 | |||
2163 | if FUpdate then |
||
2164 | FOwner.D3DDevice7.SetLight(FIndex, Params); |
||
2165 | end; |
||
2166 | |||
2167 | procedure TSXLight.SetupPoint(pos: TD3DVector); |
||
2168 | begin |
||
2169 | Params.dltType := D3DLIGHT_POINT; |
||
2170 | Params.dvPosition := pos; |
||
2171 | |||
2172 | if FUpdate then |
||
2173 | FOwner.D3DDevice7.SetLight(FIndex, Params); |
||
2174 | end; |
||
2175 | |||
2176 | procedure TSXLight.SetupSpot(pos, dir: TD3DVector; theta, phi, |
||
2177 | falloff: Single); |
||
2178 | begin |
||
2179 | Params.dltType := D3DLIGHT_SPOT; |
||
2180 | Params.dvDirection := dir; |
||
2181 | |||
2182 | Params.dvTheta := theta; |
||
2183 | Params.dvPhi := phi; |
||
2184 | Params.dvFalloff := falloff; |
||
2185 | |||
2186 | if FUpdate then |
||
2187 | FOwner.D3DDevice7.SetLight(FIndex, Params); |
||
2188 | end; |
||
2189 | |||
2190 | //フレームの位置・向きにセット |
||
2191 | |||
2192 | procedure TSXLight.FitFrame(target: TSXFrame); |
||
2193 | var |
||
2194 | mat: TD3DMATRIX; |
||
2195 | begin |
||
2196 | |||
2197 | if target = nil then |
||
2198 | mat := D3DUtil_SetIdentityMatrix |
||
2199 | else |
||
2200 | mat := target.WorldMatrix; |
||
2201 | {$IFDEF USE_S_MATHPACK} |
||
2202 | Params.dvDirection := Vector(mat._31, mat._32, mat._33); |
||
2203 | Params.dvPosition := Vector(mat._41, mat._42, mat._43); |
||
2204 | {$ELSE} |
||
2205 | Params.dvDirection := MakeD3DVector(mat._31, mat._32, mat._33); |
||
2206 | Params.dvPosition := MakeD3DVector(mat._41, mat._42, mat._43); |
||
2207 | {$ENDIF} |
||
2208 | if FUpdate then |
||
2209 | FOwner.D3DDevice7.SetLight(FIndex, Params); |
||
2210 | end; |
||
2211 | |||
2212 | procedure TSXLight.BeginUpdate; |
||
2213 | begin |
||
2214 | FUpdate := False; |
||
2215 | end; |
||
2216 | |||
2217 | procedure TSXLight.EndUpdate; |
||
2218 | begin |
||
2219 | FUpdate := True; |
||
2220 | FOwner.D3DDevice7.SetLight(FIndex, Params); |
||
2221 | end; |
||
2222 | |||
2223 | { TSXLightGroup } |
||
2224 | |||
2225 | constructor TSXLightGroup.Create(DDCompo: TDXDraw; capacity: DWord); |
||
2226 | var |
||
2227 | i: Integer; |
||
2228 | begin |
||
2229 | inherited Create; |
||
2230 | |||
2231 | FOwner := DDCompo; |
||
2232 | FCapacity := capacity; |
||
2233 | SetLength(FLights, capacity); |
||
2234 | |||
2235 | for i := 0 to capacity - 1 do |
||
2236 | begin |
||
2237 | FLights[i] := TSXLight.Create(FOwner, i); |
||
2238 | end; |
||
2239 | end; |
||
2240 | |||
2241 | destructor TSXLightGroup.Destroy; |
||
2242 | var |
||
2243 | i: Integer; |
||
2244 | begin |
||
2245 | |||
2246 | for i := 0 to FCapacity - 1 do |
||
2247 | begin |
||
2248 | FLights[i].Free; |
||
2249 | end; |
||
2250 | |||
2251 | FLights := nil; |
||
2252 | |||
2253 | inherited; |
||
2254 | end; |
||
2255 | |||
2256 | procedure TSXLightGroup.DisableAll; |
||
2257 | var |
||
2258 | i: Integer; |
||
2259 | begin |
||
2260 | for i := 0 to FCapacity - 1 do |
||
2261 | begin |
||
2262 | FLights[i].Enabled := True; |
||
2263 | end; |
||
2264 | end; |
||
2265 | |||
2266 | procedure TSXLightGroup.EnableAll; |
||
2267 | var |
||
2268 | i: Integer; |
||
2269 | begin |
||
2270 | for i := 0 to FCapacity - 1 do |
||
2271 | begin |
||
2272 | FLights[i].Enabled := False; |
||
2273 | end; |
||
2274 | end; |
||
2275 | |||
2276 | function TSXLightGroup.GetLights(idx: DWord): TSXLight; |
||
2277 | begin |
||
2278 | //範囲チェック |
||
2279 | if idx >= FCapacity then |
||
2280 | begin |
||
2281 | //DDDD_PutDebugMessage('TSXLightGroup @ SXLib: 範囲外のライトを参照しようとしました'); |
||
2282 | result := nil; |
||
2283 | exit; |
||
2284 | end; |
||
2285 | |||
2286 | result := FLights[idx]; |
||
2287 | end; |
||
2288 | |||
2289 | |||
2290 | //Enabledじゃないライトを探索 |
||
2291 | |||
2292 | function TSXLightGroup.GetUnusedLight: TSXLight; |
||
2293 | var |
||
2294 | i: Integer; |
||
2295 | begin |
||
2296 | |||
2297 | for i := 0 to FCapacity - 1 do |
||
2298 | begin |
||
2299 | if not FLights[i].Enabled then |
||
2300 | begin |
||
2301 | result := FLights[i]; |
||
2302 | exit; |
||
2303 | end; |
||
2304 | end; |
||
2305 | |||
2306 | result := nil; |
||
2307 | end; |
||
2308 | |||
2309 | //スペキュラ強度の設定 |
||
2310 | { |
||
2311 | procedure TSXLightGroup.SetSpecularPower(const Value: Single); |
||
2312 | var |
||
2313 | mtrl:D3DMATERIAL7; |
||
2314 | begin |
||
2315 | FSpecularPower := Value; |
||
2316 | |||
2317 | ZeroMemory(@mtrl, Sizeof(mtrl)); |
||
2318 | mtrl.power:=FSpecularPower; |
||
2319 | |||
2320 | FOwner.D3DDevice.SetMaterial(@mtrl); |
||
2321 | end; |
||
2322 | } |
||
2323 | |||
2324 | procedure TSXLightGroup.Recover; |
||
2325 | var |
||
2326 | i: Integer; |
||
2327 | begin |
||
2328 | |||
2329 | for i := 0 to FCapacity - 1 do |
||
2330 | begin |
||
2331 | if FLights[i].Enabled then |
||
2332 | FLights[i].Enabled := True; |
||
2333 | end; |
||
2334 | |||
2335 | // SpecularPower:=FSpecularPower; |
||
2336 | end; |
||
2337 | |||
2338 | { TSXMatetial } |
||
2339 | |||
2340 | constructor TSXMaterial.Create(DDCompo: TDXDraw); |
||
2341 | begin |
||
2342 | ZeroMemory(@Params, Sizeof(Params)); |
||
2343 | FOwner := DDCompo; |
||
2344 | FUpdate := True; |
||
2345 | end; |
||
2346 | |||
2347 | procedure TSXMaterial.SetupAmbient(_R, _G, _B: Single); |
||
2348 | begin |
||
2349 | with Params.dcvAmbient do |
||
2350 | begin |
||
2351 | R := _R; G := _G; B := _B; |
||
2352 | end; |
||
2353 | |||
2354 | if FUpdate then |
||
2355 | FOwner.D3DDevice7.SetMaterial(Params); |
||
2356 | end; |
||
2357 | |||
2358 | procedure TSXMaterial.SetupDiffuse(_R, _G, _B: Single); |
||
2359 | begin |
||
2360 | with Params.dcvDiffuse do |
||
2361 | begin |
||
2362 | R := _R; G := _G; B := _B; |
||
2363 | end; |
||
2364 | |||
2365 | if FUpdate then |
||
2366 | FOwner.D3DDevice7.SetMaterial(Params); |
||
2367 | end; |
||
2368 | |||
2369 | procedure TSXMaterial.SetupEmissive(_R, _G, _B: Single); |
||
2370 | begin |
||
2371 | with Params.dcvEmissive do |
||
2372 | begin |
||
2373 | R := _R; G := _G; B := _B; |
||
2374 | end; |
||
2375 | |||
2376 | if FUpdate then |
||
2377 | FOwner.D3DDevice7.SetMaterial(Params); |
||
2378 | end; |
||
2379 | |||
2380 | procedure TSXMaterial.SetupSpecular(_R, _G, _B: Single); |
||
2381 | begin |
||
2382 | with Params.dcvSpecular do |
||
2383 | begin |
||
2384 | R := _R; G := _G; B := _B; |
||
2385 | end; |
||
2386 | |||
2387 | if FUpdate then |
||
2388 | FOwner.D3DDevice7.SetMaterial(Params); |
||
2389 | end; |
||
2390 | |||
2391 | procedure TSXMaterial.SetupSpecularPower(pow: Single); |
||
2392 | begin |
||
2393 | with Params do |
||
2394 | begin |
||
2395 | dvPower := pow; |
||
2396 | end; |
||
2397 | |||
2398 | if FUpdate then |
||
2399 | FOwner.D3DDevice7.SetMaterial(Params); |
||
2400 | end; |
||
2401 | |||
2402 | |||
2403 | procedure TSXMaterial.SetupColors(difR, difG, difB, specR, specG, specB, |
||
2404 | ambR, ambG, ambB, emsR, emsG, emsB, pow: Single); |
||
2405 | begin |
||
2406 | |||
2407 | with Params.dcvDiffuse do |
||
2408 | begin |
||
2409 | dvR := difR; |
||
2410 | dvG := difG; |
||
2411 | dvB := difB; |
||
2412 | end; |
||
2413 | with Params.dcvSpecular do |
||
2414 | begin |
||
2415 | dvR := specR; |
||
2416 | dvG := specG; |
||
2417 | dvB := specB; |
||
2418 | end; |
||
2419 | with Params.dcvAmbient do |
||
2420 | begin |
||
2421 | dvR := ambR; |
||
2422 | dvG := ambG; |
||
2423 | dvB := ambB; |
||
2424 | end; |
||
2425 | with Params.dcvEmissive do |
||
2426 | begin |
||
2427 | dvR := emsR; |
||
2428 | dvG := emsG; |
||
2429 | dvB := emsB; |
||
2430 | end; |
||
2431 | |||
2432 | Params.dvPower := pow; |
||
2433 | |||
2434 | if FUpdate then |
||
2435 | FOwner.D3DDevice7.SetMaterial(Params); |
||
2436 | |||
2437 | end; |
||
2438 | |||
2439 | procedure TSXMaterial.BeginUpdate; |
||
2440 | begin |
||
2441 | FUpdate := False; |
||
2442 | end; |
||
2443 | |||
2444 | procedure TSXMaterial.EndUpdate; |
||
2445 | begin |
||
2446 | FUpdate := True; |
||
2447 | FOwner.D3DDevice7.SetMaterial(Params); |
||
2448 | end; |
||
2449 | |||
2450 | { ヘルパー関数 } |
||
2451 | |||
2452 | function MakeMaterial(difR, difG, difB, specR, specG, specB, ambR, ambG, ambB, emsR, emsG, emsB, pow: Single): TD3DMATERIAL7; |
||
2453 | begin |
||
2454 | with Result.dcvDiffuse do |
||
2455 | begin |
||
2456 | dvR := difR; |
||
2457 | dvG := difG; |
||
2458 | dvB := difB; |
||
2459 | dvA := 1.0; |
||
2460 | end; |
||
2461 | with Result.dcvSpecular do |
||
2462 | begin |
||
2463 | dvR := specR; |
||
2464 | dvG := specG; |
||
2465 | dvB := specB; |
||
2466 | dvA := 1.0; |
||
2467 | end; |
||
2468 | with Result.dcvAmbient do |
||
2469 | begin |
||
2470 | dvR := ambR; |
||
2471 | dvG := ambG; |
||
2472 | dvB := ambB; |
||
2473 | dvA := 1.0; |
||
2474 | end; |
||
2475 | with Result.dcvEmissive do |
||
2476 | begin |
||
2477 | dvR := emsR; |
||
2478 | dvG := emsG; |
||
2479 | dvB := emsB; |
||
2480 | dvA := 1.0; |
||
2481 | end; |
||
2482 | |||
2483 | Result.dvPower := pow; |
||
2484 | end; |
||
2485 | |||
2486 | { TSXRenderingQueue } |
||
2487 | |||
2488 | //コンストラクタ |
||
2489 | |||
2490 | constructor TSXRenderingQueue.Create(AOwner: TDXDraw; _Scene: TSXScene); |
||
2491 | begin |
||
2492 | inherited create; |
||
2493 | |||
2494 | FOwner := AOwner; |
||
2495 | Scene := _Scene; |
||
2496 | |||
2497 | //デフォ値の代入 |
||
2498 | BillboardCapacity := 32; |
||
2499 | MeshCapacity := 32; |
||
2500 | |||
2501 | FBillboardCount := 0; |
||
2502 | FMeshCount := 0; |
||
2503 | end; |
||
2504 | |||
2505 | //デストラクタ |
||
2506 | |||
2507 | destructor TSXRenderingQueue.Destroy; |
||
2508 | begin |
||
2509 | BillboardQueue := nil; |
||
2510 | MeshQueue := nil; |
||
2511 | |||
2512 | inherited; |
||
2513 | end; |
||
2514 | |||
2515 | //何もせずに、中身だけ消す |
||
2516 | |||
2517 | procedure TSXRenderingQueue.Flush; |
||
2518 | begin |
||
2519 | FBillboardCount := 0; |
||
2520 | FMeshCount := 0; |
||
2521 | end; |
||
2522 | |||
2523 | //ビルボードを入れる |
||
2524 | |||
2525 | procedure TSXRenderingQueue.PushBillboard(ref: TSXFrame; pos: TD3DVector; |
||
2526 | tex: TDirect3DTexture2; pts: array of TSXVertexBB); //ビルボード |
||
2527 | begin |
||
2528 | //必要なら拡張する |
||
2529 | if BillboardCount >= BillboardCapacity then |
||
2530 | BillboardCapacity := BillboardCapacity * 2; |
||
2531 | |||
2532 | |||
2533 | BillboardQueue[FBillboardCount].tex := tex; |
||
2534 | BillboardQueue[FBillboardCount].ref := ref; |
||
2535 | BillboardQueue[FBillboardCount].pos := pos; |
||
2536 | Move(pts, BillboardQueue[FBillboardCount].Pts, Sizeof(TSXVertexBB) * 4); //4頂点分コピー |
||
2537 | |||
2538 | Inc(FBillboardCount); |
||
2539 | end; |
||
2540 | |||
2541 | //メッシュを入れる |
||
2542 | |||
2543 | procedure TSXRenderingQueue.PushMesh(mesh: TSXMesh; frame: TSXFrame; mat: TD3DMatrix; |
||
2544 | tex: TDirect3DTexture2; mtrl: TD3DMATERIAL7; event: TSXRenderMeshEvent); |
||
2545 | begin |
||
2546 | //必要なら拡張する |
||
2547 | if MeshCount >= MeshCapacity then |
||
2548 | MeshCapacity := MeshCapacity * 2; |
||
2549 | |||
2550 | MeshQueue[FmeshCount].mat := mat; |
||
2551 | MeshQueue[FmeshCount].mesh := mesh; |
||
2552 | MeshQueue[FmeshCount].mtrl := mtrl; |
||
2553 | MeshQueue[FmeshCount].tex := tex; |
||
2554 | MeshQueue[FmeshCount].OnRender := event; |
||
2555 | MeshQueue[FMeshCount].frame := frame; |
||
2556 | |||
2557 | Inc(FMeshCount); |
||
2558 | end; |
||
2559 | |||
2560 | //ビルボード用の情報入れをサイズを変える |
||
2561 | |||
2562 | procedure TSXRenderingQueue.SetBillBoardCapacity(const Value: Integer); |
||
2563 | begin |
||
2564 | FBillboardCapacity := Value; |
||
2565 | SetLength(BillboardQueue, Value); |
||
2566 | end; |
||
2567 | |||
2568 | //メッシュ用の情報入れをサイズを変える |
||
2569 | |||
2570 | procedure TSXRenderingQueue.SetMeshCapacity(const Value: Integer); |
||
2571 | begin |
||
2572 | FMeshCapacity := Value; |
||
2573 | SetLength(MeshQueue, Value); |
||
2574 | end; |
||
2575 | |||
2576 | //描画 |
||
2577 | |||
2578 | procedure TSXRenderingQueue.Render(viewMat: TD3DMATRIX; viewParam: TD3DVIEWPORT7); |
||
2579 | var |
||
2580 | i, j: Integer; |
||
2581 | prevTex: TDirect3DTexture2; //前回使ったテクスチャへの参照 //With reference to the previous texture |
||
2582 | prevSpec: Boolean; //前回描画したものは、スペキュラを計算したか //The last drawing was either calculated specular |
||
2583 | prevLit: Boolean; //前回描画したものは、ライティングの計算をしたか //Was drawn last, or the lighting calculations |
||
2584 | prevFrame: TSXFrame; //直前に描画したビルボードの入ってたフレーム //I was drawn into the frame just before the billboard |
||
2585 | center: {$IFDEF USE_S_MATHPACK}THgVector{$ELSE}TD3DHVector{$ENDIF}; |
||
2586 | pts: array[0..3] of TD3DTLVERTEX; |
||
2587 | m: TD3DMATRIX; |
||
2588 | projM, screenM, viewProjScreenM: TD3DMATRIX; |
||
2589 | begin |
||
2590 | |||
2591 | //メッシュの描画 |
||
2592 | |||
2593 | prevTex := nil; |
||
2594 | FOwner.D3DDevice7.SetTexture(0, nil); |
||
2595 | |||
2596 | prevSpec := True; |
||
2597 | FOwner.D3DDevice7.SetRenderState(D3DRENDERSTATE_SPECULARENABLE, DWord(True)); |
||
2598 | |||
2599 | prevLit := True; |
||
2600 | FOwner.D3DDevice7.SetRenderState(D3DRENDERSTATE_LIGHTING, DWord(True)); |
||
2601 | |||
2602 | for i := 0 to MeshCount - 1 do |
||
2603 | begin |
||
2604 | |||
2605 | //ライティング |
||
2606 | if prevLit <> MeshQueue[i].Frame.Lighting then |
||
2607 | begin |
||
2608 | FOwner.D3DDevice7.SetRenderState(D3DRENDERSTATE_LIGHTING, DWord(MeshQueue[i].Frame.Lighting)); |
||
2609 | prevLit := MeshQueue[i].Frame.Lighting; |
||
2610 | end; |
||
2611 | |||
2612 | //スペキュラつける? |
||
2613 | if prevSpec <> MeshQueue[i].Frame.Specular then |
||
2614 | begin |
||
2615 | FOwner.D3DDevice7.SetRenderState(D3DRENDERSTATE_SPECULARENABLE, DWord(MeshQueue[i].Frame.Specular)); |
||
2616 | prevSpec := MeshQueue[i].Frame.Specular; |
||
2617 | end; |
||
2618 | |||
2619 | //行列の設定 |
||
2620 | FOwner.D3DDevice7.SetTransform(D3DTRANSFORMSTATE_WORLD, (MeshQueue[i].mat)); |
||
2621 | |||
2622 | //マテリアルの設定 |
||
2623 | FOwner.D3DDevice7.SetMaterial((MeshQueue[i].Mtrl)); |
||
2624 | |||
2625 | //テクスチャがあるなら、貼り付ける。 |
||
2626 | if MeshQueue[i].tex <> prevTex then |
||
2627 | begin |
||
2628 | if MeshQueue[i].tex <> nil then |
||
2629 | FOwner.D3DDevice7.SetTexture(0, MeshQueue[i].tex.Surface.IDDSurface7) |
||
2630 | else |
||
2631 | FOwner.D3DDevice7.SetTexture(0, nil); |
||
2632 | end; |
||
2633 | |||
2634 | prevTex := MeshQueue[i].tex; |
||
2635 | |||
2636 | //イベントハンドラを呼ぶ |
||
2637 | if Assigned(MeshQueue[i].OnRender) then |
||
2638 | MeshQueue[i].OnRender(MeshQueue[i].Frame); |
||
2639 | |||
2640 | //描画 |
||
2641 | MeshQueue[i].Mesh.Draw(0); |
||
2642 | |||
2643 | end; |
||
2644 | |||
2645 | //ビルボードの描画 |
||
2646 | |||
2647 | //ライティングを切る |
||
2648 | FOwner.D3DDevice7.SetRenderState(D3DRENDERSTATE_LIGHTING, DWord(False)); |
||
2649 | |||
2650 | FOwner.D3DDevice7.GetTransform(D3DTRANSFORMSTATE_PROJECTION, projM); |
||
2651 | ScreenM := D3DUtil_SetIdentityMatrix; |
||
2652 | with ScreenM do |
||
2653 | begin |
||
2654 | _11 := viewParam.dwWidth / 2.0; |
||
2655 | _22 := -(viewParam.dwHeight / 2.0); |
||
2656 | _33 := viewParam.dvMaxZ - viewParam.dvMinZ; |
||
2657 | _41 := viewParam.dwX + viewParam.dwWidth / 2.0; |
||
2658 | _42 := viewParam.dwY + viewParam.dwHeight / 2.0; |
||
2659 | _43 := viewParam.dvMinZ; |
||
2660 | end; |
||
2661 | |||
2662 | //視野座標→画面 の変換行列 |
||
2663 | {$IFDEF USE_S_MATHPACK} |
||
2664 | viewProjScreenM := NowCompositeMatrix(viewMat, projM); |
||
2665 | viewProjScreenM := NowCompositeMatrix(viewProjScreenM, ScreenM); |
||
2666 | {$ELSE} |
||
2667 | viewProjScreenM := D3DMath_MatrixMultiply(viewMat, projM); |
||
2668 | viewProjScreenM := D3DMath_MatrixMultiply(viewProjScreenM, ScreenM); |
||
2669 | {$ENDIF} |
||
2670 | prevFrame := nil; |
||
2671 | |||
2672 | for i := 0 to BillboardCount - 1 do |
||
2673 | begin |
||
2674 | |||
2675 | if BillboardQueue[i].ref <> nil then |
||
2676 | begin |
||
2677 | //テクスチャがあるなら、貼り付ける。 |
||
2678 | if BillboardQueue[i].Tex <> prevTex then |
||
2679 | begin |
||
2680 | if BillboardQueue[i].Tex <> nil then |
||
2681 | FOwner.D3DDevice7.SetTexture(0, BillboardQueue[i].Tex.Surface.IDDSurface7) |
||
2682 | else |
||
2683 | FOwner.D3DDevice7.SetTexture(0, nil); |
||
2684 | end; |
||
2685 | prevTex := BillboardQueue[i].Tex; |
||
2686 | |||
2687 | |||
2688 | //ビルボードの中心の視野座標を求める |
||
2689 | if prevFrame <> BillboardQueue[i].ref then |
||
2690 | begin |
||
2691 | {$IFDEF USE_S_MATHPACK} |
||
2692 | m := NowCompositeMatrix(BillboardQueue[i].ref.RenderedMatrix, viewProjScreenM); |
||
2693 | {$ELSE} |
||
2694 | m := D3DMath_MatrixMultiply(BillboardQueue[i].ref.RenderedMatrix, viewProjScreenM); |
||
2695 | {$ENDIF} |
||
2696 | prevFrame := BillboardQueue[i].ref; |
||
2697 | end; |
||
2698 | {$IFDEF USE_S_MATHPACK} |
||
2699 | center := NowHomoginize(BillboardQueue[i].pos); |
||
2700 | center := NowTransform(center, m); |
||
2701 | {$ELSE} |
||
2702 | center := D3DMath_VecHomogenize(BillboardQueue[i].pos); |
||
2703 | center := D3DMath_VecTransform(center, m); |
||
2704 | {$ENDIF} |
||
2705 | //W値が正なら描画 |
||
2706 | //W is positive if the drawing |
||
2707 | if center.W > 0 then |
||
2708 | begin |
||
2709 | //ビルボードの中心の画面での座標を求める |
||
2710 | //Find the coordinates of the center of the screen, billboard |
||
2711 | {$IFDEF USE_S_MATHPACK} |
||
2712 | center := NowViewFrustumToScreen(center); |
||
2713 | {$ELSE} |
||
2714 | center := D3DMath_VecViewScreenize(center); |
||
2715 | {$ENDIF} |
||
2716 | for j := 0 to 3 do |
||
2717 | begin |
||
2718 | with BillboardQueue[i].Pts[j] do |
||
2719 | begin |
||
2720 | Pts[j].sx := center.x + BillboardQueue[i].Pts[j].dx * center.W; |
||
2721 | Pts[j].sy := center.y + BillboardQueue[i].Pts[j].dy * center.W; |
||
2722 | Pts[j].sz := center.z; |
||
2723 | Pts[j].rhw := center.w; |
||
2724 | Pts[j].color := color; |
||
2725 | Pts[j].specular := $FF000000; |
||
2726 | Pts[j].tu := tu; |
||
2727 | Pts[j].tv := tv; |
||
2728 | end; |
||
2729 | end; |
||
2730 | |||
2731 | FOwner.D3DDevice7.DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_TLVERTEX, Pts, 4, 0); |
||
2732 | end; |
||
2733 | |||
2734 | //参照フレームに付いたフラグを消す |
||
2735 | BillboardQueue[i].ref.BBAttached := False; |
||
2736 | end; |
||
2737 | end; |
||
2738 | |||
2739 | //キューを空に |
||
2740 | FMeshCount := 0; |
||
2741 | FBillBoardCount := 0; |
||
2742 | end; |
||
2743 | |||
2744 | {-------------------------------- Primitive Renderer --------------------------} |
||
2745 | |||
2746 | type |
||
2747 | TIntArray = array[0..$0FFFFFFF] of Integer; |
||
2748 | PIntArray = ^TIntArray; |
||
2749 | TPrimArray = array[0..$FFFFF] of TSXPrimitiveRec; |
||
2750 | PPrimArray = ^TPrimArray; |
||
2751 | TTextureCoordArray = array[0..$FFFFF] of TSXTextureCoordRec; |
||
2752 | PTextureCoordArray = ^TTextureCoordArray; |
||
2753 | |||
2754 | class function TSXPrimitiveRenderer.SingleRect(x1, y1, x2, y2: Single): TSingleRect; |
||
2755 | begin |
||
2756 | with result do |
||
2757 | begin |
||
2758 | Left := x1; |
||
2759 | Top := y1; |
||
2760 | Right := x2; |
||
2761 | Bottom := y2; |
||
2762 | end; |
||
2763 | end; |
||
2764 | |||
2765 | constructor TSXPrimitiveRenderer.Create(DDCompo: TDXDraw; PrimitiveCount: Integer; PatternCount: Integer); |
||
2766 | begin |
||
2767 | FDXDraw := DDCompo; |
||
2768 | FMaxPrimitives := PrimitiveCount; |
||
2769 | ZSortBuf := nil; |
||
2770 | ZSortCount := nil; |
||
2771 | PrimCount := 0; |
||
2772 | |||
2773 | GetMem(PrimBuf, Sizeof(TSXPrimitiveRec) * PrimitiveCount); |
||
2774 | GetMem(Patterns, Sizeof(TSXTextureCoordRec) * PatternCount); |
||
2775 | |||
2776 | ZMax := 0; |
||
2777 | ColorKey := True; |
||
2778 | end; |
||
2779 | |||
2780 | destructor TSXPrimitiveRenderer.Destroy; |
||
2781 | begin |
||
2782 | FreeMem(ZSortBuf); |
||
2783 | FreeMem(ZSortCount); |
||
2784 | FreeMem(Patterns); |
||
2785 | FreeMem(PrimBuf); |
||
2786 | |||
2787 | inherited; |
||
2788 | end; |
||
2789 | |||
2790 | procedure TSXPrimitiveRenderer.setZMax(v: Integer); |
||
2791 | begin |
||
2792 | FZmax := v; |
||
2793 | |||
2794 | if ZSortBuf <> nil then |
||
2795 | FreeMem(ZSortBuf); |
||
2796 | if ZSortCount <> nil then |
||
2797 | FreeMem(ZSortCount); |
||
2798 | |||
2799 | GetMem(ZSortBuf, (FZMax + 1) * FMaxPrimitives * sizeof(Integer)); |
||
2800 | GetMem(ZSortCount, (FZMax + 1) * sizeof(Integer)); |
||
2801 | end; |
||
2802 | |||
2803 | //パターンとしてTexのCoordで示される範囲を登録 |
||
2804 | |||
2805 | procedure TSXPrimitiveRenderer.SetPattern(idx: Integer; Tex: TDirect3DTexture2; Coord: TRect); |
||
2806 | var |
||
2807 | pPat: PTextureCoord; |
||
2808 | begin |
||
2809 | pPat := @(PTextureCoordArray(Patterns)^[idx]); |
||
2810 | |||
2811 | with pPat^ do |
||
2812 | begin |
||
2813 | Texture := Tex; |
||
2814 | Top := Coord.Top / Tex.Height; |
||
2815 | Left := Coord.Left / Tex.Width; |
||
2816 | Bottom := Coord.Bottom / Tex.Height; |
||
2817 | Right := Coord.Right / Tex.Width; |
||
2818 | end; |
||
2819 | |||
2820 | end; |
||
2821 | |||
2822 | procedure TSXPrimitiveRenderer.Push(Tex: TDirect3DTexture2; p1, p2, p3, p4: TD3DTLVertex; Z: Integer; blend: TRenderType); //TLVertexで四角形を入れる |
||
2823 | begin |
||
2824 | with PPrimArray(PrimBuf)^[PrimCount] do |
||
2825 | begin |
||
2826 | Texture := Tex; |
||
2827 | |||
2828 | Bound[0] := p1; |
||
2829 | Bound[1] := p2; |
||
2830 | Bound[2] := p3; |
||
2831 | Bound[3] := p4; |
||
2832 | |||
2833 | ZOrder := Z; |
||
2834 | BlendMode := blend; |
||
2835 | end; |
||
2836 | |||
2837 | Inc(PrimCount); |
||
2838 | end; |
||
2839 | |||
2840 | procedure TSXPrimitiveRenderer.Push2D(Tex: TDirect3DTexture2; p1, p2, p3, p4: TD2DVector; Z: Integer; blend: TRenderType; col: DWord); //2D的な四角形 |
||
2841 | begin |
||
2842 | with PPrimArray(PrimBuf)^[PrimCount] do |
||
2843 | begin |
||
2844 | Texture := Tex; |
||
2845 | |||
2846 | Bound[0] := MakeD3DTLVertex(p1.x, p1.y, 2.0, 0.5, col, 0, 0, 0); |
||
2847 | Bound[1] := MakeD3DTLVertex(p2.x, p2.y, 2.0, 0.5, col, 0, 1, 0); |
||
2848 | Bound[2] := MakeD3DTLVertex(p3.x, p3.y, 2.0, 0.5, col, 0, 0, 1); |
||
2849 | Bound[3] := MakeD3DTLVertex(p4.x, p4.y, 2.0, 0.5, col, 0, 1, 1); |
||
2850 | |||
2851 | ZOrder := Z; |
||
2852 | BlendMode := blend; |
||
2853 | end; |
||
2854 | |||
2855 | Inc(PrimCount); |
||
2856 | end; |
||
2857 | |||
2858 | //パターンをプッシュ(3次元) |
||
2859 | |||
2860 | procedure TSXPrimitiveRenderer.PushPattern(iPat: Integer; p1, p2, p3, p4: TD3DHVector; Z: Integer; blend: TRenderType; col: DWord); |
||
2861 | var |
||
2862 | pPat: PTextureCoord; |
||
2863 | begin |
||
2864 | with PPrimArray(PrimBuf)^[PrimCount] do |
||
2865 | begin |
||
2866 | |||
2867 | pPat := @(PTextureCoordArray(Patterns)^[iPat]); |
||
2868 | Texture := pPat^.Texture; |
||
2869 | |||
2870 | Bound[0] := MakeD3DTLVertex(p1.x, p1.y, p1.z, p1.w, col, 0, pPat^.Left, pPat^.Top); |
||
2871 | Bound[1] := MakeD3DTLVertex(p2.x, p2.y, p2.z, p2.w, col, 0, pPat^.Right, pPat^.Top); |
||
2872 | Bound[2] := MakeD3DTLVertex(p3.x, p3.y, p3.z, p3.w, col, 0, pPat^.Left, pPat^.Bottom); |
||
2873 | Bound[3] := MakeD3DTLVertex(p4.x, p4.y, p4.z, p4.w, col, 0, pPat^.Right, pPat^.Bottom); |
||
2874 | |||
2875 | ZOrder := Z; |
||
2876 | BlendMode := blend; |
||
2877 | end; |
||
2878 | |||
2879 | Inc(PrimCount); |
||
2880 | end; |
||
2881 | |||
2882 | procedure TSXPrimitiveRenderer.PushPattern2D(iPat: Integer; p1, p2, p3, p4: TD2DVector; Z: Integer; blend: TRenderType; col: DWord); //パターンをプッシュする |
||
2883 | var |
||
2884 | pPat: PTextureCoord; |
||
2885 | begin |
||
2886 | with PPrimArray(PrimBuf)^[PrimCount] do |
||
2887 | begin |
||
2888 | |||
2889 | pPat := @(PTextureCoordArray(Patterns)^[iPat]); |
||
2890 | Texture := pPat^.Texture; |
||
2891 | |||
2892 | Bound[0] := MakeD3DTLVertex(p1.x, p1.y, 2, 0.5, col, 0, pPat^.Left, pPat^.Top); |
||
2893 | Bound[1] := MakeD3DTLVertex(p2.x, p2.y, 2, 0.5, col, 0, pPat^.Right, pPat^.Top); |
||
2894 | Bound[2] := MakeD3DTLVertex(p3.x, p3.y, 2, 0.5, col, 0, pPat^.Left, pPat^.Bottom); |
||
2895 | Bound[3] := MakeD3DTLVertex(p4.x, p4.y, 2, 0.5, col, 0, pPat^.Right, pPat^.Bottom); |
||
2896 | |||
2897 | ZOrder := Z; |
||
2898 | BlendMode := blend; |
||
2899 | end; |
||
2900 | |||
2901 | Inc(PrimCount); |
||
2902 | end; |
||
2903 | |||
2904 | //パターンをプッシュする(矩形) |
||
2905 | |||
2906 | procedure TSXPrimitiveRenderer.PushPatternRect(iPat: Integer; rect: TSingleRect; Z: Integer; blend: TRenderType; col: DWord); |
||
2907 | var |
||
2908 | pPat: PTextureCoord; |
||
2909 | begin |
||
2910 | with PPrimArray(PrimBuf)^[PrimCount] do |
||
2911 | begin |
||
2912 | |||
2913 | pPat := @(PTextureCoordArray(Patterns)^[iPat]); |
||
2914 | Texture := pPat^.Texture; |
||
2915 | |||
2916 | Bound[0] := MakeD3DTLVertex(rect.Left, rect.Top, 2, 0.5, col, 0, pPat^.Left, pPat^.Top); |
||
2917 | Bound[1] := MakeD3DTLVertex(rect.Right, rect.Top, 2, 0.5, col, 0, pPat^.Right, pPat^.Top); |
||
2918 | Bound[2] := MakeD3DTLVertex(rect.Left, rect.Bottom, 2, 0.5, col, 0, pPat^.Left, pPat^.Bottom); |
||
2919 | Bound[3] := MakeD3DTLVertex(rect.Right, rect.Bottom, 2, 0.5, col, 0, pPat^.Right, pPat^.Bottom); |
||
2920 | |||
2921 | ZOrder := Z; |
||
2922 | BlendMode := blend; |
||
2923 | end; |
||
2924 | |||
2925 | Inc(PrimCount); |
||
2926 | end; |
||
2927 | |||
2928 | //Z値にしたがってソート |
||
2929 | |||
2930 | procedure TSXPrimitiveRenderer.BeginRender; |
||
2931 | var |
||
2932 | i: Integer; |
||
2933 | pCount: ^Integer; //各レイヤに、いくつ物体があるか |
||
2934 | pSort: ^Integer; |
||
2935 | pPrim: PPrimitive; |
||
2936 | begin |
||
2937 | FNPrims := PrimCount; |
||
2938 | |||
2939 | //FSortCountのクリア |
||
2940 | pCount := Pointer(ZSortCount); |
||
2941 | ZeroMemory(pCount, Sizeof(Integer) * (FZMax + 1)); |
||
2942 | |||
2943 | if PrimCount = 0 then |
||
2944 | Exit; |
||
2945 | |||
2946 | //ビンソート |
||
2947 | pPrim := @(PPrimArray(PrimBuf)^[PrimCount - 1]); |
||
2948 | for i := PrimCount - 1 downto 0 do |
||
2949 | begin |
||
2950 | pSort := Pointer(ZSortBuf); |
||
2951 | pCount := Pointer(ZSortCount); |
||
2952 | if pPrim^.ZOrder > FZMax then |
||
2953 | begin |
||
2954 | //DDDD_PutDebugMessage(Format('Primitives: Z=%dは無効です、Z値は0から%dの範囲にしてください',[pPrim^.ZOrder,FZMax])); |
||
2955 | continue; |
||
2956 | end; |
||
2957 | Inc(pCount, pPrim^.ZOrder); |
||
2958 | Inc(pSort, pPrim^.ZOrder * FMaxPrimitives + pCount^); |
||
2959 | pSort^ := i; //FSortBuf[z][FSortCount[z]]:=i |
||
2960 | Inc(pCount^); //FSortCount[z]++ |
||
2961 | |||
2962 | Dec(pPrim); |
||
2963 | end; |
||
2964 | |||
2965 | end; |
||
2966 | |||
2967 | //単一のZ値を持つ集合だけ描画 |
||
2968 | |||
2969 | procedure TSXPrimitiveRenderer.RenderOneLayer(Z: Integer); |
||
2970 | var |
||
2971 | i: Integer; |
||
2972 | pSort: ^Integer; |
||
2973 | pPrim: PPrimitive; |
||
2974 | |||
2975 | prevTexture: TDirect3DTexture2; |
||
2976 | prevBlendMode: TRenderType; |
||
2977 | nPrims: Integer; |
||
2978 | begin |
||
2979 | |||
2980 | asm |
||
2981 | finit; |
||
2982 | end; |
||
2983 | |||
2984 | if Z > FZMax then |
||
2985 | begin |
||
2986 | //DDDD_PutDebugMessage(Format('Render: Z=%dは無効です、Z値は0から%dの範囲にしてください',[Z,FZMax])); |
||
2987 | exit; |
||
2988 | end; |
||
2989 | |||
2990 | nPrims := PIntArray(ZSortCount)^[Z]; |
||
2991 | if nPrims = 0 then |
||
2992 | Exit; |
||
2993 | |||
2994 | //レンダリングステートの設定 |
||
2995 | with FDXDraw.D3DDevice7 do |
||
2996 | begin |
||
2997 | SetTexture(0, nil); |
||
2998 | SetRenderState(D3DRENDERSTATE_ZENABLE, INteger(False)); |
||
2999 | SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, INteger(False)); |
||
3000 | |||
3001 | //SetTextureStageState(0, D3DTSS_MAGFILTER, Integer(D3DTFG_POINT)); |
||
3002 | //SetTextureStageState(0, D3DTSS_MINFILTER, Integer(D3DTFG_POINT)); |
||
3003 | |||
3004 | SetTextureStageState(0, D3DTSS_MAGFILTER, Integer(D3DTFG_LINEAR)); |
||
3005 | SetTextureStageState(0, D3DTSS_MINFILTER, Integer(D3DTFG_LINEAR)); |
||
3006 | |||
3007 | SetRenderState(D3DRENDERSTATE_STIPPLEDALPHA, Integer(False)); |
||
3008 | SetRenderState(D3DRENDERSTATE_DITHERENABLE, Integer(False)); |
||
3009 | SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, Integer(False)); |
||
3010 | SetRenderState(D3DRENDERSTATE_COLORKEYENABLE, Integer(ColorKey)); |
||
3011 | end; |
||
3012 | prevTexture := nil; |
||
3013 | prevBlendMode := rtDraw; |
||
3014 | |||
3015 | pSort := @(PIntArray(ZSortBuf)^[FMaxPrimitives * Z]); |
||
3016 | for i := 0 to nPrims - 1 do |
||
3017 | begin |
||
3018 | pPrim := @(PPrimArray(PrimBuf)^[pSort^]); |
||
3019 | |||
3020 | //テクスチャの変更 |
||
3021 | if pPrim^.Texture <> prevTexture then |
||
3022 | begin |
||
3023 | if pPrim^.Texture = nil then |
||
3024 | FDXDraw.D3DDevice7.SetTexture(0, nil) |
||
3025 | else |
||
3026 | FDXDraw.D3DDevice7.SetTexture(0, pPrim^.Texture.Surface.IDDSurface7); |
||
3027 | prevTexture := pPrim^.Texture; |
||
3028 | end; |
||
3029 | |||
3030 | //ブレンドモードの設定 |
||
3031 | if pPrim^.BlendMode <> prevBlendMode then |
||
3032 | begin |
||
3033 | case pPrim^.BlendMode of |
||
3034 | |||
3035 | rtDraw: |
||
3036 | begin |
||
3037 | //QD.D3DDevice7.SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, Integer(False)); |
||
3038 | FDXDraw.D3DDevice7.SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, 0); |
||
3039 | //QD.D3DDevice7.SetRenderState(D3DRENDERSTATE_FILLMODE, Integer(D3DFILL_SOLID)); |
||
3040 | FDXDraw.D3DDevice7.SetRenderState(D3DRENDERSTATE_COLORKEYENABLE, Integer(True)); |
||
3041 | FDXDraw.D3DDevice7.SetRenderState(D3DRENDERSTATE_SRCBLEND, Integer(D3DBLEND_ONE)); |
||
3042 | end; |
||
3043 | |||
3044 | rtAdd: |
||
3045 | begin |
||
3046 | if prevBlendMode = rtDraw then |
||
3047 | begin |
||
3048 | FDXDraw.D3DDevice7.SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, Integer(True)); |
||
3049 | |||
3050 | FDXDraw.D3DDevice7.SetTextureStageState(0, D3DTSS_COLORARG1, Integer(D3DTA_TEXTURE)); |
||
3051 | FDXDraw.D3DDevice7.SetTextureStageState(0, D3DTSS_COLORARG2, Integer(D3DTA_DIFFUSE)); |
||
3052 | FDXDraw.D3DDevice7.SetTextureStageState(0, D3DTSS_COLOROP, Integer(D3DTOP_MODULATE)); |
||
3053 | |||
3054 | FDXDraw.D3DDevice7.SetTextureStageState(0, D3DTSS_ALPHAARG1, Integer(D3DTA_TEXTURE)); |
||
3055 | FDXDraw.D3DDevice7.SetTextureStageState(0, D3DTSS_ALPHAARG2, Integer(D3DTA_DIFFUSE)); |
||
3056 | FDXDraw.D3DDevice7.SetTextureStageState(0, D3DTSS_ALPHAOP, Integer(D3DTOP_MODULATE)); |
||
3057 | end; |
||
3058 | FDXDraw.D3DDevice7.SetRenderState(D3DRENDERSTATE_SRCBLEND, Integer(D3DBLEND_ONE)); // ソースブレンド設定 |
||
3059 | FDXDraw.D3DDevice7.SetRenderState(D3DRENDERSTATE_DESTBLEND, Integer(D3DBLEND_ONE)); // ディスティネーション設定 |
||
3060 | end; |
||
3061 | |||
3062 | rtBlend: |
||
3063 | begin |
||
3064 | if prevBlendMode = rtDraw then |
||
3065 | begin |
||
3066 | FDXDraw.D3DDevice7.SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, Integer(True)); //αを有効に☆ |
||
3067 | |||
3068 | FDXDraw.D3DDevice7.SetTextureStageState(0, D3DTSS_COLORARG1, Integer(D3DTA_TEXTURE)); |
||
3069 | FDXDraw.D3DDevice7.SetTextureStageState(0, D3DTSS_COLORARG2, Integer(D3DTA_DIFFUSE)); |
||
3070 | FDXDraw.D3DDevice7.SetTextureStageState(0, D3DTSS_COLOROP, Integer(D3DTOP_MODULATE)); |
||
3071 | |||
3072 | FDXDraw.D3DDevice7.SetTextureStageState(0, D3DTSS_ALPHAARG1, Integer(D3DTA_TEXTURE)); |
||
3073 | FDXDraw.D3DDevice7.SetTextureStageState(0, D3DTSS_ALPHAARG2, Integer(D3DTA_DIFFUSE)); |
||
3074 | FDXDraw.D3DDevice7.SetTextureStageState(0, D3DTSS_ALPHAOP, Integer(D3DTOP_MODULATE)); |
||
3075 | end; |
||
3076 | FDXDraw.D3DDevice7.SetRenderState(D3DRENDERSTATE_SRCBLEND, Integer(D3DBLEND_SRCALPHA)); // ソースブレンド設定 |
||
3077 | FDXDraw.D3DDevice7.SetRenderState(D3DRENDERSTATE_DESTBLEND, Integer(D3DBLEND_INVSRCALPHA)); // ディスティネーション設定 |
||
3078 | end; |
||
3079 | |||
3080 | rtSub: |
||
3081 | begin |
||
3082 | if prevBlendMode = rtDraw then |
||
3083 | begin |
||
3084 | FDXDraw.D3DDevice7.SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, Integer(True)); //αを有効に☆ |
||
3085 | |||
3086 | FDXDraw.D3DDevice7.SetTextureStageState(0, D3DTSS_COLORARG1, Integer(D3DTA_TEXTURE)); |
||
3087 | FDXDraw.D3DDevice7.SetTextureStageState(0, D3DTSS_COLORARG2, Integer(D3DTA_DIFFUSE)); |
||
3088 | FDXDraw.D3DDevice7.SetTextureStageState(0, D3DTSS_COLOROP, Integer(D3DTOP_MODULATE)); |
||
3089 | |||
3090 | FDXDraw.D3DDevice7.SetTextureStageState(0, D3DTSS_ALPHAARG1, Integer(D3DTA_TEXTURE)); |
||
3091 | FDXDraw.D3DDevice7.SetTextureStageState(0, D3DTSS_ALPHAARG2, Integer(D3DTA_DIFFUSE)); |
||
3092 | FDXDraw.D3DDevice7.SetTextureStageState(0, D3DTSS_ALPHAOP, Integer(D3DTOP_MODULATE)); |
||
3093 | end; |
||
3094 | FDXDraw.D3DDevice7.SetRenderState(D3DRENDERSTATE_SRCBLEND, Integer(D3DBLEND_DESTCOLOR)); // ソースブレンド設定 |
||
3095 | FDXDraw.D3DDevice7.SetRenderState(D3DRENDERSTATE_DESTBLEND, Integer(D3DBLEND_ZERO)); // ディスティネーション設定 |
||
3096 | end; |
||
3097 | |||
3098 | end; |
||
3099 | prevBlendMode := pPrim^.BlendMode; |
||
3100 | end; |
||
3101 | |||
3102 | try |
||
3103 | asm |
||
3104 | finit; |
||
3105 | end; |
||
3106 | FDXDraw.D3DDevice7.DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_TLVERTEX, pPrim^.Bound, 4, 0); |
||
3107 | asm |
||
3108 | finit; |
||
3109 | end; |
||
3110 | Inc(pSort); |
||
3111 | except |
||
3112 | //DDDD_PutDebugMessage('FP Fault'); |
||
3113 | Halt; |
||
3114 | end; |
||
3115 | end; |
||
3116 | |||
3117 | end; |
||
3118 | |||
3119 | //スタックを空に |
||
3120 | |||
3121 | procedure TSXPrimitiveRenderer.EndRender; |
||
3122 | begin |
||
3123 | PrimCount := 0; |
||
3124 | end; |
||
3125 | |||
3126 | //全部描画 |
||
3127 | |||
3128 | procedure TSXPrimitiveRenderer.Render; |
||
3129 | var |
||
3130 | i: Integer; |
||
3131 | begin |
||
3132 | BeginRender; |
||
3133 | for i := 0 to FZMax do |
||
3134 | RenderOneLayer(i); |
||
3135 | EndRender; |
||
3136 | end; |
||
3137 | |||
3138 | end. |
||
3139 |