Subversion Repositories spacemission

Rev

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