很早实现的了,也就是针对CAMERA的运动做出相应的运动而已,难度不大,代码如下:
Type
PVRBillBoardVertexInfo = ^TVRBillBoardVertexInfo;
TVRBillBoard = class( TInterfacedObject,IVRBillBoard )
private
Model : IVRModelObject;
VertexInfo :array[0..3] of TVRBillBoardVertexInfo;
Width,Height : Single;
Position : TPoint3;//位置
Camera : IVRCamera;
N : TD3DVector;
Matrix : TD3DMatrix;
procedure InitVertex; //初步是对于Y轴垂直,并且以Z轴负方向为N坐标
procedure Update;//根据CAMERA来判断方向,是否要对应
public
function Init(const Info : TVRBillBoardInfo;const Camera : IVRCamera) : Boolean;
procedure UnInit;
function GetTexture(): IVRTexture;
procedure Render;
Constructor Create;
Destructor Destroy();override;
end;
implementation
{ TVRBillBoard }
constructor TVRBillBoard.Create;
begin
end;
destructor TVRBillBoard.Destroy;
begin
UnInit;
inherited;
end;
function TVRBillBoard.GetTexture: IVRTexture;
begin
Result := Model.GetTexture(0);
end;
function TVRBillBoard.Init(const Info: TVRBillBoardInfo;const Camera : IVRCamera): Boolean;
var
Buf : Pchar;
Material : IVRMaterial;
Texture : IVRTexture; //暂时只支持一重纹理
begin
result := false;
if Camera = nil then exit;
Model := TVRModelObject.Create;
Texture := TVRTexture.Create;
//模型文件初始化
if Model.Init(2,4,BillBoardFVF) = false then exit;
if Texture.Init( Info.TextureInfo ) = false then exit;
Position:=Info.Position;
Width := Info.Width;
Height := Info.Height;
Self.Camera := Camera;
InitVertex; //初始化各顶点
Buf := Model.LockVertexBuffer;
if Buf = nil then exit;
PVRBillBoardVertexInfo(buf)^:= VertexInfo[0];
PVRBillBoardVertexInfo(buf+sizeof(TVRBillBoardVertexInfo))^:=VertexInfo[1];
PVRBillBoardVertexInfo(buf+sizeof(TVRBillBoardVertexInfo)*2)^:=VertexInfo[2];
PVRBillBoardVertexInfo(buf+sizeof(TVRBillBoardVertexInfo)*3)^:=VertexInfo[3];
Model.UnLockVertexBuffer;
Buf := Pchar( Model.LockIndexBuffer );
if Buf = nil then exit;
PWord(Buf)^:=0;
PWord(Buf + sizeof(Word))^:=3;
PWord(Buf+ sizeof(Word)*2)^:=1;
PWord(Buf+ sizeof(Word)*3)^:=3;
PWord(Buf+ sizeof(Word)*4)^:=2;
PWord(Buf+ sizeof(Word)*5)^:=1;
Model.UnLockIndexBuffer;
buf:=Pchar( Model.LockAttriBuffer );
if buf = nil then exit;
PDWord(Buf)^:=0;
PDWord(Buf + sizeof(DWORD))^:=0;
Model.UnLockAttriBuffer;
Model.optimizeInPlace;
Material := TVRMaterial.Create;
Model.AddMaterial(0,Material);//肯定就一个纹理
Material := nil;
//======================================
Model.AddTexture(0,Texture);
Texture := nil;
Result := true;
end;
procedure TVRBillBoard.InitVertex;
var
L,T : Single;
begin
// D3DX9.D3DXPlaneFromPointNormal( )
L := Width / 2;
T := Height / 2 ;
VertexInfo[0].Vertex := Point3( Position.x - L, Position.y + T,Position.z );
VertexInfo[1].Vertex := Point3( Position.x - L, Position.y - T,Position.z );
VertexInfo[2].Vertex := Point3( Position.x + L, Position.y - T,Position.z );
VertexInfo[3].Vertex := Point3( Position.x + L, Position.y + T,Position.z );
VertexInfo[0].Texture := Point2( 0.0,0.0 );
VertexInfo[1].Texture := Point2(0.0,1.0);
VertexInfo[2].Texture := Point2(1.0,1.0);
VertexInfo[3].Texture := Point2(1.0,0.0);
N:=D3DX9.D3DXVector3(0,0,-1);//暂时这样
end;
procedure TVRBillBoard.Render;
begin
if Model <> nil then
begin
Update;
Model.Render;
end;
end;
procedure TVRBillBoard.UnInit;
begin
Model := nil;
Camera := nil;
end;
procedure TVRBillBoard.Update;
var
Cross,Default : TD3DVector;
Angle : Single;
m : TD3DMatrix;
begin
if Camera = nil then exit;
if Model = nil then exit;
Cross := Camera.GetUpRightCross;
N.x := -Cross.x;
N.y := -Cross.y;
N.z := -Cross.z;
Default := D3DX9.D3DXVector3(0,0,-1); //暂时这样
D3DX9.D3DXMatrixIdentity(Matrix);
Angle:=D3DX9.D3DXVec3Dot(N,Default);
//if Angle <= 0 then exit;
Angle:=Math.ArcCos(Angle);
D3DX9.D3DXVec3Cross(Cross,Default,N);
if (Cross.x*Camera.getUp.x>=0) and (Cross.y*Camera.getUp.y>=0) and (Cross.z*Camera.getUp.z>=0) then
begin
D3DX9.D3DXMatrixRotationAxis( Matrix,VRCommon.Point3ToVector(Camera.getUp),Angle);
end
else
begin
D3DX9.D3DXMatrixRotationAxis( Matrix,VRCommon.Point3ToVector(Camera.getUp),-Angle);
end;
D3DX9.D3DXMatrixTranslation(m,Position.x,Position.y,Position.z);
D3DX9.D3DXMatrixMultiply(Matrix,Matrix,m);
Model.SetMatrix(Matrix);
end;