11#include " CilindricalBillboard.hpp"
22#include " Plane.hpp"
33#include " ../IGraphicsCommandList.hpp"
4+ #include " ../IShaderCompiler.hpp"
5+ #include " ../../Logging/Exception.hpp"
46
57using namespace Engine3DRadSpace ;
68using namespace Engine3DRadSpace ::Graphics;
@@ -13,50 +15,76 @@ CilindricalBillboard::CilindricalBillboard(IGraphicsDevice *device) :
1315{
1416 auto vertices = CreateVertices ();
1517 _vertices = device->CreateVertexBuffer <VertexPositionUV>(vertices, BufferUsage::ReadOnlyGPU);
16-
17- auto indices = Plane:: CreateIndices ();
18+
19+ auto indices = CreateIndices ();
1820 _indices = device->CreateIndexBuffer (indices);
21+
22+ ShaderDescFile vtx (" Data\\ Shaders\\ PositionUV.hlsl" , " VS_Main" , ShaderType::Vertex);
23+ ShaderDescFile frg (" Data\\ Shaders\\ PositionUV.hlsl" , " PS_Main" , ShaderType::Fragment);
24+
25+ std::array<ShaderDesc*, 2 > shaders = { &vtx, &frg };
26+
27+ auto effect = device->ShaderCompiler ()->CompileEffect (shaders);
28+ if (effect.first )
29+ {
30+ _shader = effect.first ;
31+ }
32+ else
33+ {
34+ throw Logging::Exception (std::format (" Failed to compile effect for CilindricalBillboard: {}" , effect.second .Log ));
35+ }
1936}
2037
2138Matrix4x4 CilindricalBillboard::_mvp () const noexcept
2239{
2340 auto v = View;
41+ auto v_inv = v;
42+ v_inv.Invert ();
2443
25- Vector3 cam_pos (v .M41 , v .M42 , v .M43 );
44+ Vector3 cam_pos (v_inv .M41 , v_inv .M42 , v_inv .M43 );
2645 Vector3 x_axis (v.M11 , v.M21 , v.M31 );
27- Vector3 y_axis (v.M11 , v.M21 , v.M31 );
28- Vector3 z_axis (v.M11 , v.M21 , v.M31 );
29-
30- Vector3 fwd = cam_pos + z_axis;
46+ Vector3 y_axis (v.M12 , v.M22 , v.M32 );
47+ Vector3 z_axis (v.M13 , v.M23 , v.M33 );
48+
3149 Vector3 up = cam_pos + y_axis;
32- Vector3 right = cam_pos + x_axis ;
50+ Vector3 fwd = cam_pos - z_axis ;
3351
34- auto model = Matrix4x4::CreateCylindricalBillboard (Position, cam_pos, up, fwd, Axis, std::nullopt );
35- return model * View * Projection;
52+ // Use Position field if set, otherwise extract from Transform
53+ Vector3 objectPos = (Position != Vector3::Zero ()) ? Position : Vector3 (Transform.M41 , Transform.M42 , Transform.M43 );
54+ auto model = Matrix4x4::CreateCylindricalBillboard (objectPos, cam_pos, up, fwd, Axis, std::nullopt );
55+ return model * v * Projection;
3656}
3757
3858std::array<VertexPositionUV, 4 > CilindricalBillboard::CreateVertices ()
3959{
4060 std::array<VertexPositionUV, 4 > plane;
4161
42- Vector2 s (0 .5f );
62+ Vector2 s (0 .5f , 0 . 5f );
4363
44- // See Plane.cpp
45- plane[0 ] = VertexPositionUV (Vector3 (-s.X , 0 , -s.Y ), Vector2 (0 ,1 ));
46- plane[1 ] = VertexPositionUV (Vector3 (-s.X , 0 , +s.Y ), Vector2 (0 ,0 ));
47- plane[2 ] = VertexPositionUV (Vector3 (+s.X , 0 , +s.Y ), Vector2 (0 , 1 ));
48- plane[3 ] = VertexPositionUV (Vector3 (+s.X , 0 , -s.Y ), Vector2 (1 ,1 ));
64+ // Billboard in XY plane, will be rotated by cylindrical billboard matrix
65+ plane[0 ] = VertexPositionUV (Vector3 (-s.X , -s.Y , 0 ), Vector2 (0 , 1 ));
66+ plane[1 ] = VertexPositionUV (Vector3 (-s.X , +s.Y , 0 ), Vector2 (0 , 0 ));
67+ plane[2 ] = VertexPositionUV (Vector3 (+s.X , +s.Y , 0 ), Vector2 (1 , 0 ));
68+ plane[3 ] = VertexPositionUV (Vector3 (+s.X , -s.Y , 0 ), Vector2 (1 , 1 ));
4969
5070 return plane;
5171}
5272
73+ std::array<unsigned , 6 > CilindricalBillboard::CreateIndices ()
74+ {
75+ // Counter-clockwise winding for camera-facing billboard (reversed from Plane for proper facing).
76+ return { 0 , 2 , 1 , 0 , 3 , 2 };
77+ }
78+
5379void CilindricalBillboard::Draw3D ()
5480{
5581 auto mat = _mvp ();
5682
5783 _shader->SetAll ();
5884 _shader->operator [](0 )->SetData (0 , &mat, sizeof (mat));
5985 _shader->operator [](1 )->SetTexture (0 , Texture);
60- _device->ImmediateContext ()->DrawVertexBufferWithindices (_vertices.get (), _indices.get ());
86+ auto cmdList = _device->ImmediateContext ();
87+ cmdList->SetTopology (VertexTopology::TriangleList);
88+ cmdList->DrawVertexBufferWithindices (_vertices.get (), _indices.get ());
6189}
6290
0 commit comments