#include "Mesh.h" #include "imgui/imgui.h" // Mesh Mesh::Mesh( Graphics& gfx,std::vector> bindPtrs ) { if( !IsStaticInitialized() ) { AddStaticBind( std::make_unique( gfx,D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST ) ); } for( auto& pb : bindPtrs ) { if( auto pi = dynamic_cast(pb.get()) ) { AddIndexBuffer( std::unique_ptr{ pi } ); pb.release(); } else { AddBind( std::move( pb ) ); } } AddBind( std::make_unique( gfx,*this ) ); } void Mesh::Draw( Graphics& gfx,DirectX::FXMMATRIX accumulatedTransform ) const noxnd { DirectX::XMStoreFloat4x4( &transform,accumulatedTransform ); Drawable::Draw( gfx ); } DirectX::XMMATRIX Mesh::GetTransformXM() const noexcept { return DirectX::XMLoadFloat4x4( &transform ); } // Node Node::Node( const std::string& name,std::vector meshPtrs,const DirectX::XMMATRIX& transform ) noxnd : meshPtrs( std::move( meshPtrs ) ), name( name ) { DirectX::XMStoreFloat4x4( &this->transform,transform ); } void Node::Draw( Graphics& gfx,DirectX::FXMMATRIX accumulatedTransform ) const noxnd { const auto built = DirectX::XMLoadFloat4x4( &transform ) * accumulatedTransform; for( const auto pm : meshPtrs ) { pm->Draw( gfx,built ); } for( const auto& pc : childPtrs ) { pc->Draw( gfx,built ); } } void Node::AddChild( std::unique_ptr pChild ) noxnd { assert( pChild ); childPtrs.push_back( std::move( pChild ) ); } void Node::RenderTree() const noexcept { // if tree node expanded, recursively render all children if( ImGui::TreeNode( name.c_str() ) ) { for( const auto& pChild : childPtrs ) { pChild->RenderTree(); } ImGui::TreePop(); } } // Model Model::Model( Graphics& gfx,const std::string fileName ) { Assimp::Importer imp; const auto pScene = imp.ReadFile( fileName.c_str(), aiProcess_Triangulate | aiProcess_JoinIdenticalVertices ); for( size_t i = 0; i < pScene->mNumMeshes; i++ ) { meshPtrs.push_back( ParseMesh( gfx,*pScene->mMeshes[i] ) ); } pRoot = ParseNode( *pScene->mRootNode ); } void Model::Draw( Graphics& gfx ) const noxnd { const auto transform = DirectX::XMMatrixRotationRollPitchYaw( pos.roll,pos.pitch,pos.yaw ) * DirectX::XMMatrixTranslation( pos.x,pos.y,pos.z ); pRoot->Draw( gfx,transform ); } void Model::ShowWindow( const char* windowName ) noexcept { windowName = windowName ? windowName : "Model"; if( ImGui::Begin( windowName ) ) { ImGui::Columns( 2,nullptr,true ); pRoot->RenderTree(); ImGui::NextColumn(); ImGui::Text( "Orientation" ); ImGui::SliderAngle( "Roll",&pos.roll,-180.0f,180.0f ); ImGui::SliderAngle( "Pitch",&pos.pitch,-180.0f,180.0f ); ImGui::SliderAngle( "Yaw",&pos.yaw,-180.0f,180.0f ); ImGui::Text( "Position" ); ImGui::SliderFloat( "X",&pos.x,-20.0f,20.0f ); ImGui::SliderFloat( "Y",&pos.y,-20.0f,20.0f ); ImGui::SliderFloat( "Z",&pos.z,-20.0f,20.0f ); } ImGui::End(); } std::unique_ptr Model::ParseMesh( Graphics& gfx,const aiMesh& mesh ) { namespace dx = DirectX; using Dvtx::VertexLayout; Dvtx::VertexBuffer vbuf( std::move( VertexLayout{} .Append( VertexLayout::Position3D ) .Append( VertexLayout::Normal ) ) ); for( unsigned int i = 0; i < mesh.mNumVertices; i++ ) { vbuf.EmplaceBack( *reinterpret_cast(&mesh.mVertices[i]), *reinterpret_cast(&mesh.mNormals[i]) ); } std::vector indices; indices.reserve( mesh.mNumFaces * 3 ); for( unsigned int i = 0; i < mesh.mNumFaces; i++ ) { const auto& face = mesh.mFaces[i]; assert( face.mNumIndices == 3 ); indices.push_back( face.mIndices[0] ); indices.push_back( face.mIndices[1] ); indices.push_back( face.mIndices[2] ); } std::vector> bindablePtrs; bindablePtrs.push_back( std::make_unique( gfx,vbuf ) ); bindablePtrs.push_back( std::make_unique( gfx,indices ) ); auto pvs = std::make_unique( gfx,L"PhongVS.cso" ); auto pvsbc = pvs->GetBytecode(); bindablePtrs.push_back( std::move( pvs ) ); bindablePtrs.push_back( std::make_unique( gfx,L"PhongPS.cso" ) ); bindablePtrs.push_back( std::make_unique( gfx,vbuf.GetLayout().GetD3DLayout(),pvsbc ) ); struct PSMaterialConstant { DirectX::XMFLOAT3 color = { 0.6f,0.6f,0.8f }; float specularIntensity = 0.6f; float specularPower = 30.0f; float padding[3]; } pmc; bindablePtrs.push_back( std::make_unique>( gfx,pmc,1u ) ); return std::make_unique( gfx,std::move( bindablePtrs ) ); } std::unique_ptr Model::ParseNode( const aiNode& node ) noexcept { namespace dx = DirectX; const auto transform = dx::XMMatrixTranspose( dx::XMLoadFloat4x4( reinterpret_cast(&node.mTransformation) ) ); std::vector curMeshPtrs; curMeshPtrs.reserve( node.mNumMeshes ); for( size_t i = 0; i < node.mNumMeshes; i++ ) { const auto meshIdx = node.mMeshes[i]; curMeshPtrs.push_back( meshPtrs.at( meshIdx ).get() ); } auto pNode = std::make_unique( node.mName.C_Str(),std::move( curMeshPtrs ),transform ); for( size_t i = 0; i < node.mNumChildren; i++ ) { pNode->AddChild( ParseNode( *node.mChildren[i] ) ); } return pNode; }