InstanceMeshes.pas
上传用户:ctlcnc
上传日期:2021-12-10
资源大小:4933k
文件大小:8k
源码类别:

2D图形编程

开发平台:

Delphi

  1. unit InstanceMeshes;
  2. //---------------------------------------------------------------------------
  3. interface
  4. //---------------------------------------------------------------------------
  5. uses
  6.  Windows, Direct3D9, d3dx9, Vectors2, Vectors3, AsphyreUtils, AsphyreMeshes;
  7. //---------------------------------------------------------------------------
  8. // Enable the following option to enable the generation and usage of
  9. // texture coordinates.
  10. //---------------------------------------------------------------------------
  11. {$define IncludeTexCoords}
  12. //---------------------------------------------------------------------------
  13. type
  14.  PInstanceMeshVertex = ^TInstanceMeshVertex;
  15.  TInstanceMeshVertex = packed record
  16.   Position: TVector3;
  17.   Normal  : TVector3;
  18.   {$ifdef IncludeTexCoords}
  19.   TexCoord: TPoint2;
  20.   {$endif}
  21.   Instance: Single;
  22.  end;
  23. //---------------------------------------------------------------------------
  24.  TInstanceMesh = class(TAsphyreCustomMesh)
  25.  private
  26.   FNumCopies: Integer;
  27.   VertexDecl: IDirect3DVertexDeclaration9;
  28.   function CreateBuffers(Faces, Vertices: Integer): Boolean;
  29.   function LockBuffers(Mesh: ID3DXMesh; out CurVertex,
  30.    CurIndex: Pointer): Boolean;
  31.   procedure UnlockBuffers(Mesh: ID3DXMesh);
  32.  public
  33.   property NumCopies: Integer read FNumCopies;
  34.   function Generate(Source: TAsphyreCustomMesh; MaxCopies: Integer): Boolean;
  35.   procedure DrawCopies(Copies: Integer);
  36.   destructor Destroy(); override;
  37.  end;
  38. //---------------------------------------------------------------------------
  39. implementation
  40. //---------------------------------------------------------------------------
  41. const
  42.  {$ifdef IncludeTexCoords}
  43.  VertexElementNo = 5;
  44.  {$else}
  45.  VertexElementNo = 4;
  46.  {$endif}
  47. //---------------------------------------------------------------------------
  48.  VertexElements: array[0..VertexElementNo - 1] of TD3DVertexElement9 =
  49.  (// Position
  50.   (Stream: 0; Offset: 0; _Type: D3DDECLTYPE_FLOAT3;
  51.    Method: D3DDECLMETHOD_DEFAULT; Usage: D3DDECLUSAGE_POSITION; UsageIndex: 0),
  52.   // Normal
  53.   (Stream: 0; Offset: 12; _Type: D3DDECLTYPE_FLOAT3;
  54.    Method: D3DDECLMETHOD_DEFAULT; Usage: D3DDECLUSAGE_NORMAL; UsageIndex: 0),
  55.   {$ifdef IncludeTexCoords}
  56.   // TexCoord
  57.   (Stream: 0; Offset: 24; _Type: D3DDECLTYPE_FLOAT2;
  58.    Method: D3DDECLMETHOD_DEFAULT; Usage: D3DDECLUSAGE_TEXCOORD; UsageIndex: 0),
  59.   // Instance Index
  60.   (Stream: 0; Offset: 32; _Type: D3DDECLTYPE_FLOAT1;
  61.    Method: D3DDECLMETHOD_DEFAULT; Usage: D3DDECLUSAGE_TEXCOORD; UsageIndex: 1),
  62.   {$else}
  63.   // Instance Index
  64.   (Stream: 0; Offset: 24; _Type: D3DDECLTYPE_FLOAT1;
  65.    Method: D3DDECLMETHOD_DEFAULT; Usage: D3DDECLUSAGE_TEXCOORD; UsageIndex: 1),
  66.   {$endif}
  67.   // D3DDECL_END()
  68.   (Stream: $FF; Offset: 0; _Type: D3DDECLTYPE_UNUSED;
  69.    Method: TD3DDeclMethod(0); Usage: TD3DDeclUsage(0); UsageIndex: 0));
  70. //---------------------------------------------------------------------------
  71. type
  72.  PInputVertex = ^TInputVertex;
  73.  TInputVertex = record
  74.   Position: TVector3;
  75.   Normal  : TVector3;
  76.   {$ifdef IncludeTexCoords}
  77.   TexCoord: TPoint2;
  78.   {$endif}
  79.  end;
  80. //---------------------------------------------------------------------------
  81. destructor TInstanceMesh.Destroy();
  82. begin
  83.  if (VertexDecl <> nil) then VertexDecl:= nil;
  84.  inherited;
  85. end;
  86. //---------------------------------------------------------------------------
  87. function TInstanceMesh.CreateBuffers(Faces, Vertices: Integer): Boolean;
  88. begin
  89.  if (VertexDecl <> nil) then VertexDecl:= nil;
  90.  if (FDXMesh <> nil) then FDXMesh:= nil;
  91.  Result:= Succeeded(Device.Dev9.CreateVertexDeclaration(@VertexElements[0],
  92.   VertexDecl));
  93.  if (not Result) then Exit;
  94.  Result:= Succeeded(D3DXCreateMesh(Faces, Vertices, D3DXMESH_MANAGED or
  95.   D3DXMESH_WRITEONLY, @VertexElements[0], Device.Dev9, FDXMesh));
  96. end;
  97. //---------------------------------------------------------------------------
  98. function TInstanceMesh.LockBuffers(Mesh: ID3DXMesh; out CurVertex,
  99.  CurIndex: Pointer): Boolean;
  100. begin
  101.  if (Mesh = nil) then
  102.   begin
  103.    Result:= False;
  104.    Exit;
  105.   end;
  106.  Result:= Succeeded(Mesh.LockVertexBuffer(0, CurVertex));
  107.  if (not Result) then Exit;
  108.  Result:= Succeeded(Mesh.LockIndexBuffer(0, CurIndex));
  109.  if (not Result) then
  110.   begin
  111.    Mesh.UnlockVertexBuffer();
  112.    CurVertex:= nil;
  113.   end;
  114. end;
  115. //---------------------------------------------------------------------------
  116. procedure TInstanceMesh.UnlockBuffers(Mesh: ID3DXMesh);
  117. begin
  118.  if (Mesh <> nil) then
  119.   begin
  120.    Mesh.UnlockIndexBuffer();
  121.    Mesh.UnlockVertexBuffer();
  122.   end;
  123. end;
  124. //---------------------------------------------------------------------------
  125. function TInstanceMesh.Generate(Source: TAsphyreCustomMesh;
  126.  MaxCopies: Integer): Boolean;
  127. var
  128.  NumVertices, NumFaces, CopyNo, VertexNo, FaceNo: Integer;
  129.  CurVertex: PInstanceMeshVertex;
  130.  CurIndex : PWord;
  131.  SrcVertex: PInputVertex;
  132.  SrcIndex : PWord;
  133.  SrcStride: Integer;
  134.  InVertex : PInputVertex;
  135.  InIndex  : PWord;
  136.  IndexAdd : Integer;
  137. begin
  138.  // (1) Calculate new geometry information.
  139.  with Source.DXMesh do
  140.   begin
  141.    FNumCopies := Min2(65536 div GetNumVertices(), MaxCopies);
  142.    NumVertices:= Integer(GetNumVertices()) * FNumCopies;
  143.    NumFaces   := Integer(GetNumFaces()) * FNumCopies;
  144.   end;
  145.  // (2) Create vertex & index buffers.
  146.  Result:= CreateBuffers(NumFaces, NumVertices);
  147.  if (not Result) then Exit;
  148.  // (3) Obtain direct access to new vertex & index buffers.
  149.  Result:= LockBuffers(FDXMesh, Pointer(CurVertex), Pointer(CurIndex));
  150.  if (not Result) then Exit;
  151.  // (4) Obtain direct access to input vertex & index buffers.
  152.  Result:= LockBuffers(Source.DXMesh, Pointer(SrcVertex), Pointer(SrcIndex));
  153.  if (not Result) then
  154.   begin
  155.    UnlockBuffers(FDXMesh);
  156.    Exit;
  157.   end;
  158.  SrcStride:= Source.DXMesh.GetNumBytesPerVertex();
  159.  // (5) Create multiple instances of the same geometry.
  160.  for CopyNo:= 0 to FNumCopies - 1 do
  161.   begin
  162.    InVertex:= SrcVertex;
  163.    InIndex := SrcIndex;
  164.    // -> copy vertices
  165.    for VertexNo:= 0 to Source.DXMesh.GetNumVertices() - 1 do
  166.     begin
  167.      CurVertex.Position:= InVertex.Position;
  168.      CurVertex.Normal  := InVertex.Normal;
  169.      {$ifdef IncludeTexCoords}
  170.      CurVertex.TexCoord:= InVertex.TexCoord;
  171.      {$endif}
  172.      CurVertex.Instance:= CopyNo;
  173.      Inc(CurVertex);
  174.      Inc(Integer(InVertex), SrcStride);
  175.     end;
  176.    // -> copy indices
  177.    IndexAdd:= Integer(Source.DXMesh.GetNumVertices()) * CopyNo;
  178.    for FaceNo:= 0 to Source.DXMesh.GetNumFaces() - 1 do
  179.     begin
  180.      CurIndex^:= InIndex^ + IndexAdd;
  181.      Inc(CurIndex);
  182.      Inc(InIndex);
  183.      CurIndex^:= InIndex^ + IndexAdd;
  184.      Inc(CurIndex);
  185.      Inc(InIndex);
  186.      CurIndex^:= InIndex^ + IndexAdd;
  187.      Inc(CurIndex);
  188.      Inc(InIndex);
  189.     end;
  190.   end;
  191.  UnlockBuffers(Source.DXMesh);
  192.  UnlockBuffers(FDXMesh);
  193. end;
  194. //---------------------------------------------------------------------------
  195. procedure TInstanceMesh.DrawCopies(Copies: Integer);
  196. var
  197.  VertexBuffer: IDirect3DVertexBuffer9;
  198.  IndexBuffer : IDirect3DIndexBuffer9;
  199.  PassNo, NoVertices, NoFaces: Integer;
  200. begin
  201.  FDXMesh.GetVertexBuffer(VertexBuffer);
  202.  FDXMesh.GetIndexBuffer(IndexBuffer);
  203.  NoVertices:= FDXMesh.GetNumVertices();
  204.  NoFaces   := (Integer(FDXMesh.GetNumFaces()) div FNumCopies) * Copies;
  205.  Inc(TotalVerticesNo, NoVertices);
  206.  Inc(TotalFacesNo, NoFaces);
  207.  with Device.Dev9 do
  208.   begin
  209.    SetStreamSource(0, VertexBuffer, 0, FDXMesh.GetNumBytesPerVertex());
  210.    SetIndices(IndexBuffer);
  211.    SetVertexDeclaration(VertexDecl);
  212.    DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, NoVertices, 0, NoFaces);
  213.   end;
  214.  Inc(DrawPrimitiveCalls);
  215.  IndexBuffer:= nil;
  216.  VertexBuffer:= nil;
  217. end;
  218. //---------------------------------------------------------------------------
  219. end.