void TaxiPathGraph::Initialize() { if (GetVertexCount() > 0) return; std::vector<std::pair<edge, EdgeCost>> edges; // Initialize here for (TaxiPathEntry const* path : sTaxiPathStore) { TaxiNodesEntry const* from = sTaxiNodesStore.LookupEntry(path->From); TaxiNodesEntry const* to = sTaxiNodesStore.LookupEntry(path->To); if (from && to && from->Flags & (TAXI_NODE_FLAG_ALLIANCE | TAXI_NODE_FLAG_HORDE) && to->Flags & (TAXI_NODE_FLAG_ALLIANCE | TAXI_NODE_FLAG_HORDE)) AddVerticeAndEdgeFromNodeInfo(from, to, path->ID, edges); } // create graph m_graph = Graph(GetVertexCount()); WeightMap weightmap = boost::get(boost::edge_weight, m_graph); for (std::size_t j = 0; j < edges.size(); ++j) { edge_descriptor e = boost::add_edge(edges[j].first.first, edges[j].first.second, m_graph).first; weightmap[e] = edges[j].second; } }
void AasRenderer::RenderGeometryShadow(gfx::AnimatedModel * model, const gfx::AnimatedModelParams & params, const gfx::Light3d & globalLight, float alpha) { // Find or create render caching data for the submesh auto &renderData = mRenderDataCache[model->GetHandle()]; if (!renderData) { renderData = std::make_unique<AasRenderData>(); } mDevice.SetMaterial(mGeometryShadowMaterial); auto d3d = mDevice.GetDevice(); d3d->SetVertexShaderConstantF(0, &mDevice.GetCamera().GetViewProj()._11, 4); d3d->SetVertexShaderConstantF(4, &globalLight.dir.x, 1); XMFLOAT4 floats{ params.offsetZ, 0, 0, 0 }; d3d->SetVertexShaderConstantF(5, &floats.x, 1); floats.x = alpha; d3d->SetVertexShaderConstantF(6, &floats.x, 1); auto materialIds(model->GetSubmeshes()); for (size_t i = 0; i < materialIds.size(); ++i) { auto submesh(model->GetSubmesh(params, i)); auto &submeshData = GetSubmeshData(*renderData, i, *submesh); submeshData.binding.Bind(); d3d->SetIndices(submeshData.idxBuffer->GetBuffer()); D3DLOG(d3d->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, submesh->GetVertexCount(), 0, submesh->GetPrimitiveCount())); } }
unsigned int NzSubMesh::GetTriangleCount() const { const NzIndexBuffer* indexBuffer = GetIndexBuffer(); unsigned int indexCount; if (indexBuffer) indexCount = indexBuffer->GetIndexCount(); else indexCount = GetVertexCount(); switch (m_primitiveMode) { case nzPrimitiveMode_LineList: case nzPrimitiveMode_LineStrip: case nzPrimitiveMode_PointList: return 0; case nzPrimitiveMode_TriangleFan: return (indexCount - 1) / 2; case nzPrimitiveMode_TriangleList: return indexCount / 3; case nzPrimitiveMode_TriangleStrip: return indexCount - 2; } NazaraError("Primitive mode not handled (0x" + NzString::Number(m_primitiveMode, 16) + ')'); return 0; }
// TODO: exploit a better algorithm, use vertex hash table/map. // void mxRenderMesh::WeldVertices() { TArray< mxVertex > newVerts; newVerts.Resize( GetVertexCount() ); for ( u32 triIdx = 0; triIdx < GetTriangleCount(); triIdx++ ) { IndexTriple & rTri = Triangles[ triIdx ]; for ( TIndex i = 0; i < 3; i++ ) { const mxVertex & rCurrVertex = Vertices[ rTri[i] ]; s32 iExistingVertex = -1; for ( TIndex iVtx = 0; iVtx < newVerts.Num(); iVtx++ ) { if ( VectorsEqual( newVerts[ iVtx ].Pos, rCurrVertex.Pos ) ) { iExistingVertex = iVtx; break; } } if ( iExistingVertex != -1 ) { rTri[ i ] = iExistingVertex; } else { rTri[ i ] = newVerts.Append( mxVertex( rCurrVertex ) ); } } } Vertices = newVerts; }
void mxRenderMesh::TransformVertices( const TMatrix4& matrix ) { for ( u32 i = 0; i < GetVertexCount(); ++i ) { matrix.transformVect( Vertices[ i ].Pos ); } }
void mxRenderMesh::ScaleVertices( const Vec3D& value ) { for ( u32 i = 0; i < GetVertexCount(); ++i ) { Vertices[ i ].Pos *= value; } }
void mxRenderMesh::ScaleTextureCoordinates( const f32 factorU, const f32 factorV ) { for ( u32 i = 0; i < GetVertexCount(); ++i ) { Vertices[ i ].U *= factorU; Vertices[ i ].V *= factorV; } }
void dgCollisionBVH::GetVertexListIndexList (const dgVector& p0, const dgVector& p1, dgGetVertexListIndexList &data) const { ForAllSectors (p0, p1, CollectVertexListIndexList, &data); data.m_veterxArray = GetLocalVertexPool(); data.m_vertexCount = GetVertexCount(); data.m_vertexStrideInBytes = GetStrideInBytes(); }
void mxRenderMesh::ComputeBoundingBox( AABB &bbox ) const { bbox.reset( 0.0f, 0.0f, 0.0f ); for ( u32 i = 0; i < GetVertexCount(); i++ ) { bbox.addInternalPoint( GetPos( i ) ); } }
void dgCollisionBVH::GetVertexListIndexList (const dgVector& p0, const dgVector& p1, dgMeshVertexListIndexList &data) const { dgFastAABBInfo box (p0, p1); ForAllSectors (box, dgVector (dgFloat32 (0.0f)), dgFloat32 (1.0f), CollectVertexListIndexList, &data); data.m_veterxArray = GetLocalVertexPool(); data.m_vertexCount = GetVertexCount(); data.m_vertexStrideInBytes = GetStrideInBytes(); }
void CSceneObject::OnFrame() { inherited::OnFrame(); if (!m_pReference) return; if (m_pReference) m_pReference->OnFrame(); if (psDeviceFlags.is(rsStatistic)){ if (IsStatic()||IsMUStatic()||Selected()){ Device.Statistic->dwLevelSelFaceCount += GetFaceCount(); Device.Statistic->dwLevelSelVertexCount += GetVertexCount(); } } }
inline void ParametricSurface::GenerateVertices(vector<float>& vertices, unsigned char flags) const { int floatsPerVertex = 3; if (flags & VertexFlagsNormals) floatsPerVertex += 3; if (flags & VertexFlagsTexCoords) floatsPerVertex += 2; vertices.resize(GetVertexCount() * floatsPerVertex); float* attribute = &vertices[0]; for (int j = 0; j < m_divisions.y; j++) { for (int i = 0; i < m_divisions.x; i++) { // Compute Position vec2 domain = ComputeDomain(i, j); vec3 range = Evaluate(domain); attribute = range.Write(attribute); // Compute Normal if (flags & VertexFlagsNormals) { float s = i, t = j; // Nudge the point if the normal is indeterminate. if (i == 0) s += 0.01f; if (i == m_divisions.x - 1) s -= 0.01f; if (j == 0) t += 0.01f; if (j == m_divisions.y - 1) t -= 0.01f; // Compute the tangents and their cross product. vec3 p = Evaluate(ComputeDomain(s, t)); vec3 u = Evaluate(ComputeDomain(s + 0.01f, t)) - p; vec3 v = Evaluate(ComputeDomain(s, t + 0.01f)) - p; vec3 normal = u.Cross(v).Normalized(); if (InvertNormal(domain)) normal = -normal; attribute = normal.Write(attribute); } // Compute Texture Coordinates if (flags & VertexFlagsTexCoords) { float s = m_textureCount.x * i / m_slices.x; float t = m_textureCount.y * j / m_slices.y; attribute = vec2(s, t).Write(attribute); } } } }
bool OGLRenderSystem::DrawPrimitiveUP( PrimitiveType::PrimitiveType type, int count, void* data, int stride ) { if( !ApplyVertexDeclaration( stride, (char*)data ) ) return false; glDrawArrays( type, 0, GetVertexCount( type, count ) ); ResetClientState( ); ++mBatchCount; mPrimCount += count; return true; };
//-------------------------------------------------------------------------------- void VertexBuffer_DX11::Init(const void* in_pData) { //If buffer is constant, it needs to be initialized with data. AssertMsg(!(m_uiBufferType & eUT_Constant && in_pData == nullptr), L("Constant Buffers need to be initialized with data.")); AssertMsg(!(m_uiBufferType & eUT_Constant && m_uiVertexCount == 0), L("Constant Buffers need to be initialized with data.")); //If buffer is not CPU writable, it needs to be initialized with data. (at least until GPU write support/use) AssertMsg(!(!(m_uiBufferType & eUT_CPU_Writable) && in_pData == nullptr), L("Non-CPU Writable Buffers need to be initialized with data.")); AssertMsg(!(!(m_uiBufferType & eUT_CPU_Writable) && m_uiVertexCount == 0), L("Non-CPU Writable Buffers need to be initialized with data.")); if (GetVertexCount() == 0) return; Renderer_DX11* pDX11Renderer = (Renderer_DX11*)GetOwner(); D3D11_BUFFER_DESC vertexBufferDesc; vertexBufferDesc.ByteWidth = GetVertexCount() * GetVertexSize(); vertexBufferDesc.Usage = GetD3D11Usage(m_uiBufferType); vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; vertexBufferDesc.CPUAccessFlags = GetCPUAccessFlags(m_uiBufferType); vertexBufferDesc.MiscFlags = 0; vertexBufferDesc.StructureByteStride = 0; D3D11_SUBRESOURCE_DATA vertexBufferInitData; vertexBufferInitData.pSysMem = in_pData; vertexBufferInitData.SysMemPitch = 0; vertexBufferInitData.SysMemSlicePitch = 0; SAFE_RELEASE(m_pD3D11VertexBuffer); if(in_pData == nullptr) HResult hr = pDX11Renderer->GetDevice()->CreateBuffer(&vertexBufferDesc, nullptr, &m_pD3D11VertexBuffer); else HResult hr = pDX11Renderer->GetDevice()->CreateBuffer(&vertexBufferDesc, &vertexBufferInitData, &m_pD3D11VertexBuffer); SET_D3D11_OBJECT_NAME(m_pD3D11VertexBuffer); }
//---------------------------------------------------------------------------- // Skeleton functions //---------------------------------------------------------------------------- bool CEditableObject::ImportMAXSkeleton(CExporter* E) { bool bResult = true; CEditableMesh* MESH = xr_new<CEditableMesh>(this); m_Meshes.push_back(MESH); // import mesh if (!MESH->Convert(E)) return FALSE; // BONES m_Bones.reserve(E->m_Bones.size()); for (int B=0; B!=E->m_Bones.size(); B++){ m_Bones.push_back(xr_new<CBone>()); CBone* BONE = m_Bones.back(); CBoneDef* bone = E->m_Bones[B]; CBoneDef* parent_bone = bone->parent; Fvector offset,rotate; float length= 0.1f; Fmatrix m; if (parent_bone) m.mul(parent_bone->matOffset,bone->matInit); else m.set(bone->matInit); m.getXYZi (rotate); offset.set (m.c); BONE->SetWMap (bone->name.c_str()); BONE->SetName (bone->name.c_str()); BONE->SetParentName (Helper::ConvertSpace(string(bone->pBone->GetParentNode()->GetName())).c_str()); BONE->SetRestParams (length,offset,rotate); } // DEFAULT BONE PART m_BoneParts.push_back(SBonePart()); SBonePart& BP = m_BoneParts.back(); BP.alias = "default"; for (int b_i=0; b_i<(int)m_Bones.size(); b_i++) BP.bones.push_back(Bones()[b_i]->Name()); m_objectFlags.set(CEditableObject::eoDynamic,TRUE); if ((0==GetVertexCount())||(0==GetFaceCount())){ bResult = false; }else{ ELog.Msg(mtInformation,"Model '%s' contains: %d points, %d faces, %d bones", E->m_MeshNode->GetName(), GetVertexCount(), GetFaceCount(), Bones().size()); } return bResult; }
void ProceduralQuad::GetNormals(void * data_start, unsigned int byte_stride) { Eigen::Vector3f normal = (corners[1]-corners[0]).cross(corners[2]-corners[0]); normal.normalize(); float * dest = (float *) data_start; unsigned int vertex_count = GetVertexCount(); for (unsigned int i = 0; i < vertex_count; ++i) { dest[0] = normal[0]; dest[1] = normal[1]; dest[2] = normal[2]; dest = (float *) ((char *) dest + byte_stride); } }
bool OGLRenderSystem::DrawPrimitive( PrimitiveType::PrimitiveType type, int start, int count ) { glBindBuffer( GL_ARRAY_BUFFER, mRenderState.mVertexBuffer ); if( !ApplyVertexDeclaration( mRenderState.mVDeclaration->GetStride( 0 ) ) ) return false; glDrawArrays( type, 0, GetVertexCount( type, count ) ); ResetClientState( ); ++mBatchCount; mPrimCount += count; return true; };
bool OGLRenderSystem::DrawIndexedPrimitive( PrimitiveType::PrimitiveType type, int vstart, int istart, int vcount, int count ) { glBindBuffer( GL_ARRAY_BUFFER, mRenderState.mVertexBuffer ); int stride = mRenderState.mVDeclaration->GetStride( 0 ); if( !ApplyVertexDeclaration( stride, (char*)(vstart * stride) ) ) return false; glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, mRenderState.mIndexBuffer ); glDrawElements( type, GetVertexCount( type, count ), GL_UNSIGNED_SHORT, 0 ); ResetClientState( ); ++mBatchCount; mPrimCount += count; return true; };
void dgCollisionBVH::GetCollisionInfo(dgCollisionInfo* const info) const { dgCollision::GetCollisionInfo(info); dgMeshVertexListIndexList data; data.m_indexList = NULL; data.m_userDataList = NULL; data.m_maxIndexCount = 1000000000; data.m_triangleCount = 0; // dgVector p0 (-1.0e10f, -1.0e10f, -1.0e10f, 1.0f); // dgVector p1 ( 1.0e10f, 1.0e10f, 1.0e10f, 1.0f); dgVector zero (dgFloat32 (0.0f)); dgFastAABBInfo box (dgGetIdentityMatrix(), dgVector (dgFloat32 (1.0e15f))); ForAllSectors (box, zero, dgFloat32 (1.0f), GetTriangleCount, &data); info->m_bvhCollision.m_vertexCount = GetVertexCount(); info->m_bvhCollision.m_indexCount = data.m_triangleCount * 3; }
void dgCollisionBVH::GetCollisionInfo(dgCollisionInfo* info) const { dgCollision::GetCollisionInfo(info); info->m_offsetMatrix = GetOffsetMatrix(); info->m_collisionType = m_collsionId; dgGetVertexListIndexList data; data.m_indexList = NULL; data.m_userDataList = NULL; data.m_maxIndexCount = 1000000000; data.m_triangleCount = 0; dgVector p0 (-1.0e10f, -1.0e10f, -1.0e10f, 1.0f); dgVector p1 ( 1.0e10f, 1.0e10f, 1.0e10f, 1.0f); ForAllSectors (p0, p1, GetTriangleCount, &data); info->m_bvhCollision.m_vertexCount = GetVertexCount(); info->m_bvhCollision.m_indexCount = data.m_triangleCount * 3; }
void AasRenderer::RenderWithoutMaterial(gfx::AnimatedModel *model, const gfx::AnimatedModelParams& params) { // Find or create render caching data for the model auto &renderData = mRenderDataCache[model->GetHandle()]; if (!renderData) { renderData = std::make_unique<AasRenderData>(); } auto materialIds(model->GetSubmeshes()); for (size_t i = 0; i < materialIds.size(); ++i) { auto submesh(model->GetSubmesh(params, i)); auto &submeshData = GetSubmeshData(*renderData, i, *submesh); submeshData.binding.Bind(); auto d3d = mDevice.GetDevice(); d3d->SetIndices(submeshData.idxBuffer->GetBuffer()); D3DLOG(d3d->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, submesh->GetVertexCount(), 0, submesh->GetPrimitiveCount())); } }
bool IShape::ContainsPoint(const glm::vec2& point) { // For each triangle. for (unsigned int t = 0; t < GetVertexCount() / 3; ++t) { // Index for the first vertex that composes triangle. const unsigned int triangleStartIndex = t * 3; // Get the viewport coordinates of the three vertices that // compose the triangle. glm::vec2 A = TransformPoint(GetVertexPosition(triangleStartIndex)); glm::vec2 B = TransformPoint(GetVertexPosition(triangleStartIndex + 1)); glm::vec2 C = TransformPoint(GetVertexPosition(triangleStartIndex + 2)); // Compute barycentric coordinates for the specified point with // respect to the triangle ABC. const glm::vec2 v0(C - A); const glm::vec2 v1(B - A); const glm::vec2 v2(point - A); float dot00 = glm::dot(v0, v0); float dot01 = glm::dot(v0, v1); float dot02 = glm::dot(v0, v2); float dot11 = glm::dot(v1, v1); float dot12 = glm::dot(v1, v2); float recipDenom = 1.0f / (dot00 * dot11 - dot01 * dot01); float u = (dot11 * dot02 - dot01 * dot12) * recipDenom; float v = (dot00 * dot12 - dot01 * dot02) * recipDenom; // Return true if the point is inside of the triangle. if (u >= 0.0f && v >= 0.0f && (u + v) < 1.0f) return true; } // The point was not contained by any of the triangles that compose // the shape. return false; }
//-------------------------------------------------------------------------------- void GeometryDX11::LoadToBuffers( ID3D11Device* pDevice ) { // Check the size of the assembled vertices CalculateVertexSize(); // Load the vertex buffer first by calculating the required size unsigned int vertices_length = GetVertexSize() * GetVertexCount(); char* pBytes = new char[vertices_length]; for ( int j = 0; j < m_iVertexCount; j++ ) { int iElemOffset = 0; for ( int i = 0; i < m_vElements.count(); i++ ) { memcpy( pBytes + j * m_iVertexSize + iElemOffset, m_vElements[i]->GetPtr(j), m_vElements[i]->SizeInBytes() ); iElemOffset += m_vElements[i]->SizeInBytes(); } } D3D11_SUBRESOURCE_DATA data; data.pSysMem = reinterpret_cast<void*>( pBytes ); data.SysMemPitch = 0; data.SysMemSlicePitch = 0; D3D11_BUFFER_DESC vbuffer; vbuffer.ByteWidth = vertices_length; vbuffer.BindFlags = D3D11_BIND_VERTEX_BUFFER; vbuffer.MiscFlags = 0; vbuffer.StructureByteStride = 0; vbuffer.Usage = D3D11_USAGE_IMMUTABLE; vbuffer.CPUAccessFlags = 0; vbuffer.StructureByteStride = 0; pDevice->CreateBuffer( &vbuffer, &data, &m_pVertexBuffer ); delete [] pBytes; // TODO: add error checking here! // Load the index buffer by calculating the required size // based on the number of indices. data.pSysMem = reinterpret_cast<void*>( &m_vIndices[0] ); data.SysMemPitch = 0; data.SysMemSlicePitch = 0; D3D11_BUFFER_DESC ibuffer; ibuffer.ByteWidth = sizeof( unsigned int ) * GetIndexCount(); ibuffer.BindFlags = D3D11_BIND_INDEX_BUFFER; ibuffer.MiscFlags = 0; ibuffer.StructureByteStride = 0; ibuffer.Usage = D3D11_USAGE_IMMUTABLE; ibuffer.CPUAccessFlags = 0; ibuffer.StructureByteStride = 0; pDevice->CreateBuffer( &ibuffer, &data, &m_pIndexBuffer ); //m_iIB = RendererDX11::Get()->CreateIndexBuffer( &ibuffer, &data ); }
UInt TriangleStripMesh::GetTriangleCount() const { if ( m_pIB == NULL ) return ( GetVertexCount() - 2 ); return ( GetIndexCount() - 2 ); }
void ModelDefinition::Serialize(Serializer &serializer) const { BasicSerializer intermediarySerializer; ///////////////////////////////////// // Bones intermediarySerializer.Write(static_cast<uint32_t>(m_bones.count)); // Local information. for (size_t iBone = 0; iBone < m_bones.count; ++iBone) { auto bone = m_bones[iBone]; assert(bone != nullptr); { // Name. intermediarySerializer.WriteString(bone->GetName()); // Relative transformation. intermediarySerializer.Write(bone->GetPosition()); intermediarySerializer.Write(bone->GetRotation()); intermediarySerializer.Write(bone->GetScale()); // 4x4 offset matrix. intermediarySerializer.Write(bone->GetOffsetMatrix()); } } // Parents. -1 for bones without parents. for (size_t iBone = 0; iBone < m_bones.count; ++iBone) { auto bone = m_bones[iBone]; assert(bone != nullptr); { auto parentBone = bone->GetParent(); if (parentBone != nullptr) { size_t parentBoneIndex; if (!this->FindBoneIndex(parentBone, parentBoneIndex)) { assert(false); } intermediarySerializer.Write(static_cast<uint32_t>(parentBoneIndex)); } else { intermediarySerializer.Write(static_cast<uint32_t>(-1)); } } } Serialization::ChunkHeader header; header.id = Serialization::ChunkID_Model_Bones; header.version = 1; header.sizeInBytes = intermediarySerializer.GetBufferSizeInBytes(); serializer.Write(header); serializer.Write(intermediarySerializer.GetBuffer(), header.sizeInBytes); ///////////////////////////////////// // Meshes // // Vertex data is always saved in P3T2N3T3B3 format. Bones are referenced using an integer to index into the list of bones defined above. intermediarySerializer.Clear(); intermediarySerializer.Write(static_cast<uint32_t>(this->meshes.count)); for (size_t iMesh = 0; iMesh < this->meshes.count; ++iMesh) { // Name. intermediarySerializer.WriteString(this->meshes[iMesh].name); // Material. intermediarySerializer.WriteString(this->meshes[iMesh].material->GetDefinition().relativePath); // Vertices. auto vertexArray = this->meshes[iMesh].geometry; assert(vertexArray != nullptr); { // Vertex Format. vertexArray->GetFormat().Serialize(intermediarySerializer); // Vertices. intermediarySerializer.Write(static_cast<uint32_t>(vertexArray->GetVertexCount())); if (vertexArray->GetVertexCount() > 0) { intermediarySerializer.Write(vertexArray->GetVertexDataPtr(), vertexArray->GetFormat().GetSizeInBytes() * vertexArray->GetVertexCount()); } // Indices. intermediarySerializer.Write(static_cast<uint32_t>(vertexArray->GetIndexCount())); if (vertexArray->GetIndexCount() > 0) { intermediarySerializer.Write(vertexArray->GetIndexDataPtr(), sizeof(uint32_t) * vertexArray->GetIndexCount()); } // Skinning Vertex Attributes. if (this->meshes[iMesh].skinningVertexAttributes != nullptr) { intermediarySerializer.Write(static_cast<uint32_t>(vertexArray->GetVertexCount())); if (vertexArray->GetVertexCount() > 0) { uint32_t totalBoneWeights = 0; // Bone Counts. for (size_t iVertex = 0; iVertex < vertexArray->GetVertexCount(); ++iVertex) { uint16_t count = static_cast<uint16_t>(this->meshes[iMesh].skinningVertexAttributes[iVertex].bones.count); intermediarySerializer.Write(count); totalBoneWeights += count; } // Bone/Weight Pairs. intermediarySerializer.Write(totalBoneWeights); for (size_t iVertex = 0; iVertex < vertexArray->GetVertexCount(); ++iVertex) { auto &bones = this->meshes[iMesh].skinningVertexAttributes[iVertex].bones; { for (size_t iBone = 0; iBone < bones.count; ++iBone) { auto &bone = bones[iBone]; intermediarySerializer.Write(static_cast<uint32_t>(bone.boneIndex)); intermediarySerializer.Write(static_cast<float >(bone.weight)); } } } } } else { intermediarySerializer.Write(static_cast<uint32_t>(0)); } // Default uniforms. this->meshes[iMesh].defaultUniforms.Serialize(intermediarySerializer); } } header.id = Serialization::ChunkID_Model_Meshes; header.version = 1; header.sizeInBytes = intermediarySerializer.GetBufferSizeInBytes(); serializer.Write(header); serializer.Write(intermediarySerializer.GetBuffer(), header.sizeInBytes); ///////////////////////////////////// // Animation intermediarySerializer.Clear(); intermediarySerializer.Write(static_cast<uint32_t>(m_animation.GetKeyFrameCount())); for (uint32_t iKeyFrame = 0; iKeyFrame < m_animation.GetKeyFrameCount(); ++iKeyFrame) { // Time. intermediarySerializer.Write(static_cast<float>(m_animation.GetKeyFrameTimeByIndex(iKeyFrame))); // Channels. intermediarySerializer.Write(static_cast<uint32_t>(this->animationChannelBones.count)); for (size_t iChannel = 0; iChannel < this->animationChannelBones.count; ++iChannel) { auto channel = this->animationChannelBones.buffer[iChannel]->value; auto bone = this->animationChannelBones.buffer[iChannel]->key; assert(channel != nullptr); assert(bone != nullptr); { // Bone Index. size_t boneIndex; this->FindBoneIndex(bone, boneIndex); intermediarySerializer.Write(static_cast<uint32_t>(boneIndex)); // Bone Transformation. glm::vec3 position; glm::quat rotation; glm::vec3 scale; auto key = static_cast<TransformAnimationKey*>(channel->GetKey(iKeyFrame)); if (key != nullptr) { position = key->position; rotation = key->rotation; scale = key->scale; } else { // We should never actually get here, but for completeness we'll just write identities. position = bone->GetPosition(); rotation = bone->GetRotation(); scale = bone->GetScale(); } intermediarySerializer.Write(position); intermediarySerializer.Write(rotation); intermediarySerializer.Write(scale); } } } intermediarySerializer.Write(this->animationAABBPadding); header.id = Serialization::ChunkID_Model_Animation; header.version = 1; header.sizeInBytes = intermediarySerializer.GetBufferSizeInBytes(); serializer.Write(header); serializer.Write(intermediarySerializer.GetBuffer(), header.sizeInBytes); ///////////////////////////////////// // Animation Segments intermediarySerializer.Clear(); intermediarySerializer.Write(static_cast<uint32_t>(m_animation.GetNamedSegmentCount())); for (size_t iSegment = 0; iSegment < m_animation.GetNamedSegmentCount(); ++iSegment) { auto segment = m_animation.GetNamedSegmentByIndex(iSegment); assert(segment != nullptr); { intermediarySerializer.WriteString(segment->name); intermediarySerializer.Write(static_cast<uint32_t>(segment->startKeyFrame)); intermediarySerializer.Write(static_cast<uint32_t>(segment->endKeyFrame)); } } header.id = Serialization::ChunkID_Model_AnimationSegments; header.version = 1; header.sizeInBytes = intermediarySerializer.GetBufferSizeInBytes(); serializer.Write(header); serializer.Write(intermediarySerializer.GetBuffer(), header.sizeInBytes); ///////////////////////////////////// // Animation Sequences /* intermediarySerializer.Clear(); intermediarySerializer.Write(static_cast<uint32_t>(this->animationSequences.count)); for (size_t iSequence = 0; iSequence < this->animationSequences.count; ++iSequence) { } header.id = Serialization::ChunkID_Model_AnimationSequences; header.version = 1; header.sizeInBytes = intermediarySerializer.GetBufferSizeInBytes(); serializer.Write(header); serializer.Write(intermediarySerializer.GetBuffer(), header.sizeInBytes); */ ///////////////////////////////////// // Convex Hulls intermediarySerializer.Clear(); intermediarySerializer.Write(static_cast<uint32_t>(m_convexHulls.count)); Vector<uint32_t> vertexCounts(m_convexHulls.count); Vector<uint32_t> indexCounts( m_convexHulls.count); Vector<float> vertices; Vector<uint32_t> indices; for (size_t iConvexHull = 0; iConvexHull < m_convexHulls.count; ++iConvexHull) { auto convexHull = m_convexHulls[iConvexHull]; assert(convexHull != nullptr); { uint32_t vertexCount = static_cast<uint32_t>(convexHull->GetVertexCount()); uint32_t indexCount = static_cast<uint32_t>(convexHull->GetIndexCount()); vertexCounts.PushBack(vertexCount); indexCounts.PushBack( indexCount); for (uint32_t iVertex = 0; iVertex < vertexCount; ++iVertex) { vertices.PushBack(convexHull->GetVertices()[iVertex * 3 + 0]); vertices.PushBack(convexHull->GetVertices()[iVertex * 3 + 1]); vertices.PushBack(convexHull->GetVertices()[iVertex * 3 + 2]); } for (uint32_t iIndex = 0; iIndex < indexCount; ++iIndex) { indices.PushBack(convexHull->GetIndices()[iIndex]); } } } intermediarySerializer.Write(vertexCounts.buffer, vertexCounts.count * 4); intermediarySerializer.Write(indexCounts.buffer, indexCounts.count * 4); intermediarySerializer.Write(static_cast<uint32_t>(vertices.count)); intermediarySerializer.Write(static_cast<uint32_t>(indices.count)); intermediarySerializer.Write(vertices.buffer, vertices.count * 4); intermediarySerializer.Write(indices.buffer, indices.count * 4); intermediarySerializer.Write(this->convexHullBuildSettings); header.id = Serialization::ChunkID_Model_ConvexHulls; header.version = 1; header.sizeInBytes = intermediarySerializer.GetBufferSizeInBytes(); serializer.Write(header); serializer.Write(intermediarySerializer.GetBuffer(), header.sizeInBytes); ///////////////////////////////////// // Null Chunk header.id = Serialization::ChunkID_Null; header.version = 1; header.sizeInBytes = 0; serializer.Write(header); }
BYTE* D3DXMeshVertexEnumer::GetVertexByteHead( UINT uIndex ) { _ASSERTE(IsValid()); _ASSERTE(uIndex < GetVertexCount()); return m_pBuffer + m_dwNumBytePerVertex * uIndex; }
bool CEditableMesh::Convert( INode *node ) { // prepares & checks BOOL bDeleteObj; bool bResult = true; TriObject *obj = ExtractTriObject( node, bDeleteObj ); if( !obj ){ ELog.Msg(mtError,"%s -> Can't convert to TriObject", node->GetName() ); return false; } if( obj->mesh.getNumFaces() <=0 ){ ELog.Msg(mtError,"%s -> There are no faces ?", node->GetName() ); if (bDeleteObj) delete (obj); return false; } Mtl *pMtlMain = node->GetMtl(); DWORD cSubMaterials=0; if (pMtlMain){ // There is at least one material. We're in case 1) or 2) cSubMaterials = pMtlMain->NumSubMtls(); if (cSubMaterials < 1){ // Count the material itself as a submaterial. cSubMaterials = 1; } } // build normals obj->mesh.buildRenderNormals(); // vertices m_VertCount = obj->mesh.getNumVerts(); m_Vertices = xr_alloc<Fvector>(m_VertCount); for (int v_i=0; v_i<m_VertCount; v_i++){ Point3* p = obj->mesh.verts+v_i; m_Vertices[v_i].set(p->x,p->y,p->z); } // set smooth group MAX type m_Flags.set(flSGMask,TRUE); // faces m_FaceCount = obj->mesh.getNumFaces(); m_Faces = xr_alloc<st_Face> (m_FaceCount); m_SmoothGroups = xr_alloc<u32> (m_FaceCount); m_VMRefs.reserve(m_FaceCount*3); if (0==obj->mesh.mapFaces(1)) { bResult = false; ELog.Msg(mtError,"'%s' hasn't UV mapping!", node->GetName()); } if (bResult) { CSurface* surf=0; for (int f_i=0; f_i<m_FaceCount; ++f_i) { Face* vf = obj->mesh.faces+f_i; TVFace* tf = obj->mesh.mapFaces(1) + f_i; if (!tf) { bResult = false; ELog.Msg(mtError,"'%s' hasn't UV mapping!", node->GetName()); break; } m_SmoothGroups[f_i] = vf->getSmGroup(); for (int k=0; k<3; ++k) { m_Faces[f_i].pv[k].pindex = vf->v[k]; m_VMRefs.push_back(st_VMapPtLst()); st_VMapPtLst& vm_lst = m_VMRefs.back(); vm_lst.count = 1; vm_lst.pts = xr_alloc<st_VMapPt>(vm_lst.count); for (DWORD vm_i=0; vm_i<vm_lst.count; ++vm_i) { vm_lst.pts[vm_i].vmap_index = 0; vm_lst.pts[vm_i].index = tf->t[k]; } m_Faces[f_i].pv[k].vmref = m_VMRefs.size()-1; if (!bResult) break; } if (pMtlMain) { int m_id = obj->mesh.getFaceMtlIndex(f_i); if (cSubMaterials == 1) { m_id = 0; }else { // SDK recommends mod'ing the material ID by the valid # of materials, // as sometimes a material number that's too high is returned. m_id %= cSubMaterials; } surf = m_Parent->CreateSurface(pMtlMain,m_id); if (!surf) bResult = false; } if (!bResult) break; m_SurfFaces[surf].push_back(f_i); } } // vmaps if( bResult ){ int vm_cnt = obj->mesh.getNumTVerts(); m_VMaps.resize(1); st_VMap*& VM = m_VMaps.back(); VM = xr_new<st_VMap>("Texture",vmtUV,false); for (int tx_i=0; tx_i<vm_cnt; tx_i++){ UVVert* tv = obj->mesh.tVerts + tx_i; VM->appendUV(tv->x,1-tv->y); } } if ((GetVertexCount()<4)||(GetFaceCount()<2)) { ELog.Msg(mtError,"Invalid mesh: '%s'. Faces<2 or Verts<4"); bResult = false; } if (bResult ){ ELog.Msg(mtInformation,"Model '%s' contains: %d points, %d faces", node->GetName(), m_VertCount, m_FaceCount); } if (bResult) { RecomputeBBox (); OptimizeMesh (false); RebuildVMaps (); ELog.Msg(mtInformation,"Model '%s' converted: %d points, %d faces", node->GetName(), GetVertexCount(), GetFaceCount()); } if (bDeleteObj) delete (obj); return bResult; }
bool CEditableMesh::Convert(CExporter* E) { bool bResult = true; m_Name = E->m_MeshNode->GetName(); // maps // Weight maps m_VMaps.resize(E->m_Bones.size()+1); for (DWORD b_i=0; b_i<E->m_Bones.size(); b_i++) m_VMaps[b_i] = xr_new<st_VMap>(E->m_Bones[b_i]->name.c_str(),vmtWeight,false);; // UV map int VM_UV_idx = m_VMaps.size()-1; st_VMap*& VM_UV = m_VMaps[VM_UV_idx]; VM_UV = xr_new<st_VMap>("texture",vmtUV,false); // points { m_VertCount = E->m_ExpVertices.size(); m_Vertices = xr_alloc<Fvector>(m_VertCount); Fvector* p_it = m_Vertices; for (ExpVertIt ev_it=E->m_ExpVertices.begin(); ev_it!=E->m_ExpVertices.end(); ev_it++,p_it++){ p_it->set ((*ev_it)->P); VM_UV->appendUV ((*ev_it)->uv.x,(*ev_it)->uv.y); } } // faces { // set smooth group MAX type m_Flags.set(flSGMask,TRUE); // reserve space for faces and references m_FaceCount = E->m_ExpFaces.size(); m_Faces = xr_alloc<st_Face> (m_FaceCount); m_SmoothGroups = xr_alloc<u32> (m_FaceCount); m_VMRefs.resize (m_VertCount); int f_id=0; for (ExpFaceIt ef_it=E->m_ExpFaces.begin(); ef_it!=E->m_ExpFaces.end(); ef_it++,f_id++){ // FACES m_SmoothGroups[f_id] = (*ef_it)->sm_group; st_Face& F = m_Faces[f_id]; for (int k=0; k<3; ++k) { int v_idx = (*ef_it)->v[k]; st_FaceVert& vt = F.pv[k]; st_VERT* V = E->m_ExpVertices[v_idx]; vt.pindex = v_idx; st_VMapPtLst& vm_lst= m_VMRefs[vt.pindex]; vm_lst.count = V->data.size()+1; vm_lst.pts = xr_alloc<st_VMapPt>(vm_lst.count); vm_lst.pts[0].vmap_index= VM_UV_idx; vm_lst.pts[0].index = vt.pindex; for (VDIt vd_it=V->data.begin(); vd_it!=V->data.end(); vd_it++){ DWORD idx = vd_it-V->data.begin()+1; st_VMap* vm = m_VMaps[vd_it->bone]; vm->appendW (vd_it->weight); vm_lst.pts[idx].vmap_index = vd_it->bone; vm_lst.pts[idx].index = vm->size()-1; } vt.vmref = vt.pindex; } CSurface* surf = m_Parent->CreateSurface(E->m_MtlMain,(*ef_it)->m_id); if (!surf){ bResult = FALSE; break; } m_SurfFaces[surf].push_back(f_id); } } if ((GetVertexCount()<4)||(GetFaceCount()<2)) { Log("!Invalid mesh: '%s'. Faces<2 or Verts<4",*Name()); bResult = false; } if (bResult) { RecomputeBBox (); OptimizeMesh (true);//false); RebuildVMaps (); } return bResult; }
void SS3OPiece::SetVertexTangents() { if (isEmpty || primitiveType == S3O_PRIMTYPE_QUADS) { return; } sTangents.resize(GetVertexCount(), ZeroVector); tTangents.resize(GetVertexCount(), ZeroVector); unsigned stride = 0; switch (primitiveType) { case S3O_PRIMTYPE_TRIANGLES: { stride = 3; } break; case S3O_PRIMTYPE_TRIANGLE_STRIP: { stride = 1; } break; } // for triangle strips, the piece vertex _indices_ are defined // by the draw order of the vertices numbered <v, v + 1, v + 2> // for v in [0, n - 2] const unsigned vrtMaxNr = (stride == 1)? vertexDrawOrder.size() - 2: vertexDrawOrder.size(); // set the triangle-level S- and T-tangents for (unsigned vrtNr = 0; vrtNr < vrtMaxNr; vrtNr += stride) { bool flipWinding = false; if (primitiveType == S3O_PRIMTYPE_TRIANGLE_STRIP) { flipWinding = ((vrtNr & 1) == 1); } const int v0idx = vertexDrawOrder[vrtNr ]; const int v1idx = vertexDrawOrder[vrtNr + (flipWinding? 2: 1)]; const int v2idx = vertexDrawOrder[vrtNr + (flipWinding? 1: 2)]; if (v1idx == -1 || v2idx == -1) { // not a valid triangle, skip // to start of next tri-strip vrtNr += 3; continue; } const SS3OVertex* vrt0 = &vertices[v0idx]; const SS3OVertex* vrt1 = &vertices[v1idx]; const SS3OVertex* vrt2 = &vertices[v2idx]; const float3& p0 = vrt0->pos; const float3& p1 = vrt1->pos; const float3& p2 = vrt2->pos; const float2 tc0(vrt0->textureX, vrt0->textureY); const float2 tc1(vrt1->textureX, vrt1->textureY); const float2 tc2(vrt2->textureX, vrt2->textureY); const float x1x0 = p1.x - p0.x, x2x0 = p2.x - p0.x; const float y1y0 = p1.y - p0.y, y2y0 = p2.y - p0.y; const float z1z0 = p1.z - p0.z, z2z0 = p2.z - p0.z; const float s1 = tc1.x - tc0.x, s2 = tc2.x - tc0.x; const float t1 = tc1.y - tc0.y, t2 = tc2.y - tc0.y; // if d is 0, texcoors are degenerate const float d = (s1 * t2 - s2 * t1); const bool b = (d > -0.0001f && d < 0.0001f); const float r = b? 1.0f: 1.0f / d; // note: not necessarily orthogonal to each other // or to vertex normal (only to the triangle plane) const float3 sdir((t2 * x1x0 - t1 * x2x0) * r, (t2 * y1y0 - t1 * y2y0) * r, (t2 * z1z0 - t1 * z2z0) * r); const float3 tdir((s1 * x2x0 - s2 * x1x0) * r, (s1 * y2y0 - s2 * y1y0) * r, (s1 * z2z0 - s2 * z1z0) * r); sTangents[v0idx] += sdir; sTangents[v1idx] += sdir; sTangents[v2idx] += sdir; tTangents[v0idx] += tdir; tTangents[v1idx] += tdir; tTangents[v2idx] += tdir; } // set the smoothed per-vertex tangents for (int vrtIdx = vertices.size() - 1; vrtIdx >= 0; vrtIdx--) { float3& n = vertices[vrtIdx].normal; float3& s = sTangents[vrtIdx]; float3& t = tTangents[vrtIdx]; int h = 1; if (math::isnan(n.x) || math::isnan(n.y) || math::isnan(n.z)) { n = float3(0.0f, 0.0f, 1.0f); } if (s == ZeroVector) { s = float3(1.0f, 0.0f, 0.0f); } if (t == ZeroVector) { t = float3(0.0f, 1.0f, 0.0f); } h = ((n.cross(s)).dot(t) < 0.0f)? -1: 1; s = (s - n * n.dot(s)); s = s.SafeANormalize(); t = (s.cross(n)) * h; // t = (s.cross(n)); // h = ((s.cross(t)).dot(n) >= 0.0f)? 1: -1; // t = t * h; } }
void AasRenderer::Render(gfx::AnimatedModel *model, const gfx::AnimatedModelParams& params, gsl::span<Light3d> lights, const MdfRenderOverrides *materialOverrides) { // Find or create render caching data for the model auto &renderData = mRenderDataCache[model->GetHandle()]; if (!renderData) { renderData = std::make_unique<AasRenderData>(); } auto materialIds(model->GetSubmeshes()); for (size_t i = 0; i < materialIds.size(); ++i) { auto materialId = materialIds[i]; auto submesh(model->GetSubmesh(params, i)); // Remove special material marker in the upper byte and only // use the actual shader registration id materialId &= 0x00FFFFFF; // Usually this should not happen, since it means there's // an unbound replacement material if (materialId == 0) { continue; } // if material was not found if (materialId == 0x00FFFFFF) { continue; } auto material = mMdfFactory.GetById(materialId); if (!material) { logger->error("Legacy shader with id {} wasn't found.", materialId); continue; } material->Bind(mDevice, lights, materialOverrides); // Do we have to recalculate the normals? if (material->GetSpec()->recalculateNormals) { RecalcNormals( submesh->GetVertexCount(), submesh->GetPositions().data(), submesh->GetNormals().data(), submesh->GetPrimitiveCount(), submesh->GetIndices().data() ); } auto &submeshData = GetSubmeshData(*renderData, i, *submesh); submeshData.binding.Bind(); auto d3d = mDevice.GetDevice(); d3d->SetIndices(submeshData.idxBuffer->GetBuffer()); D3DLOG(d3d->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, submesh->GetVertexCount(), 0, submesh->GetPrimitiveCount())); } }