Subversion Repositories spacemission

Rev

Blame | Last modification | View Log | RSS feed

  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.  
  3140.