// Note that we only need one of these. We don't need to re-create it for every model. //----------------------------------------------------------------------------- void CPUTModelDX11::CreateBoundingBoxMesh() { CPUTResult result = CPUT_SUCCESS; float3 pVertices[8] = { float3( 1.0f, 1.0f, 1.0f ), // 0 float3( 1.0f, 1.0f, -1.0f ), // 1 float3( -1.0f, 1.0f, 1.0f ), // 2 float3( -1.0f, 1.0f, -1.0f ), // 3 float3( 1.0f, -1.0f, 1.0f ), // 4 float3( 1.0f, -1.0f, -1.0f ), // 5 float3( -1.0f, -1.0f, 1.0f ), // 6 float3( -1.0f, -1.0f, -1.0f ) // 7 }; USHORT pIndices[24] = { 0,1, 1,3, 3,2, 2,0, // Top 4,5, 5,7, 7,6, 6,4, // Bottom 0,4, 1,5, 2,6, 3,7 // Verticals }; CPUTVertexElementDesc pVertexElements[] = { { CPUT_VERTEX_ELEMENT_POSITON, tFLOAT, 12, 0 }, }; CPUTMesh *pMesh = mpBoundingBoxMesh = new CPUTMeshDX11(); pMesh->SetMeshTopology(CPUT_TOPOLOGY_INDEXED_LINE_LIST); CPUTBufferInfo vertexElementInfo; vertexElementInfo.mpSemanticName = "POSITION"; vertexElementInfo.mSemanticIndex = 0; vertexElementInfo.mElementType = CPUT_F32; vertexElementInfo.mElementComponentCount = 3; vertexElementInfo.mElementSizeInBytes = 12; vertexElementInfo.mElementCount = 8; vertexElementInfo.mOffset = 0; CPUTBufferInfo indexDataInfo; indexDataInfo.mElementType = CPUT_U16; indexDataInfo.mElementComponentCount = 1; indexDataInfo.mElementSizeInBytes = sizeof(UINT16); indexDataInfo.mElementCount = 24; // 12 lines, 2 verts each indexDataInfo.mOffset = 0; indexDataInfo.mSemanticIndex = 0; indexDataInfo.mpSemanticName = NULL; result = pMesh->CreateNativeResources( this, -1, 1, // vertexFormatDesc.mFormatDescriptorCount, &vertexElementInfo, pVertices, // (void*)vertexFormatDesc.mpVertices, &indexDataInfo, pIndices // &vertexFormatDesc.mpIndices[0] ); ASSERT( CPUTSUCCESS(result), _L("Failed building bounding box mesh") ); cString modelSuffix = ptoc(this); UINT index = mpSubMaterialCount[0] + CPUT_MATERIAL_INDEX_BOUNDING_BOX; CPUTMaterialDX11 *pMaterial = (CPUTMaterialDX11*)(mpMaterial[0][index]); ((CPUTMeshDX11*)pMesh)->BindVertexShaderLayout( pMaterial, &mpInputLayout[0][index] ); }
//----------------------------------------------------------------------------- void CPUTAssetSet::RenderRecursive(CPUTRenderParameters &renderParams, int materialIndex) { if (!IsEnabled) return; CPUTMaterial* pCurrentMaterial = NULL; CPUTRenderStateBlock* pCurrentRenderState = NULL; CPUTRenderNode* pCurrent = mpRootNode; CPUTInputLayoutCache* pInputLayoutCache = CPUTInputLayoutCache::GetInputLayoutCache(); while (pCurrent) { if (pCurrent->GetNodeType() == CPUTRenderNode::CPUT_NODE_MODEL) { CPUTModel* pModel = (CPUTModel*)pCurrent; pModel->UpdateShaderConstants(renderParams); int meshCount = pModel->GetMeshCount(); for (int mesh = 0; mesh < meshCount; mesh++) { CPUTMaterial* pMaterial = pModel->GetMaterial(mesh, materialIndex); if (pMaterial != NULL) { CPUTRenderStateBlock* pRenderStateBlock = pMaterial->GetRenderStateBlock(); CPUTMesh* pMesh = pModel->GetMesh(mesh); SetMaterialStates(pMaterial, pCurrentMaterial); SetRenderStateBlock(pRenderStateBlock, pCurrentRenderState); pInputLayoutCache->Apply(pMesh, pMaterial); pMesh->Draw(); SAFE_RELEASE(pCurrentMaterial); pCurrentMaterial = pMaterial; SAFE_RELEASE(pCurrentRenderState) pCurrentRenderState = pRenderStateBlock; } } } CPUTRenderNode* pNext = pCurrent->GetChild(); if (pNext == NULL) { pNext = pCurrent->GetSibling(); if (pNext == NULL) { pNext = pCurrent->GetParent(); if (pNext != NULL) { pNext = pNext->GetSibling(); } } } pCurrent = pNext; } SAFE_RELEASE(pCurrentMaterial); SAFE_RELEASE(pCurrentRenderState); }
//----------------------------------------------------------------------------- CPUTResult CPUTModel::LoadModelPayload(const cString &File) { CPUTResult result = CPUT_SUCCESS; std::ifstream file(File.c_str(), std::ios::in | std::ios::binary); ASSERT( !file.fail(), _L("CPUTModelDX11::LoadModelPayload() - Could not find binary model file: ") + File ); // set up for mesh creation loop UINT meshIndex = 0; while(file.good() && !file.eof()) { // TODO: rearrange while() to avoid if(eof). Should perform only one branch per loop iteration, not two CPUTRawMeshData vertexFormatDesc; vertexFormatDesc.Read(file); if(file.eof()) { // TODO: Wtf? Why would we get here? We check eof at the top of loop. If it isn't eof there, why is it eof here? break; } ASSERT( meshIndex < mMeshCount, _L("Actual mesh count doesn't match stated mesh count")); // create the mesh. CPUTMesh *pMesh = mpMesh[meshIndex]; // always a triangle list (at this point) pMesh->SetMeshTopology(CPUT_TOPOLOGY_INDEXED_TRIANGLE_LIST); // get number of data blocks in the vertex element (pos,norm,uv,etc) // YUCK! TODO: Use fixed-size array of elements CPUTBufferInfo *pVertexElementInfo = new CPUTBufferInfo[vertexFormatDesc.mFormatDescriptorCount]; // pMesh->SetBounds(vertexFormatDesc.mBboxCenter, vertexFormatDesc.mBboxHalf); // running count of each type of element int positionStreamCount=0; int normalStreamCount=0; int texCoordStreamCount=0; int tangentStreamCount=0; int binormalStreamCount=0; int colorStreamCount=0; int RunningOffset = 0; for(UINT ii=0; ii<vertexFormatDesc.mFormatDescriptorCount; ii++) { // lookup the CPUT data type equivalent pVertexElementInfo[ii].mElementType = CPUT_FILE_ELEMENT_TYPE_TO_CPUT_TYPE_CONVERT[vertexFormatDesc.mpElements[ii].mVertexElementType]; ASSERT((pVertexElementInfo[ii].mElementType !=CPUT_UNKNOWN ) , _L(".MDL file load error. This model file has an unknown data type in it's model data.")); // calculate the number of elements in this stream block (i.e. F32F32F32 = 3xF32) pVertexElementInfo[ii].mElementComponentCount = vertexFormatDesc.mpElements[ii].mElementSizeInBytes/CPUT_DATA_FORMAT_SIZE[pVertexElementInfo[ii].mElementType]; // store the size of each element type in bytes (i.e. 3xF32, each element = F32 = 4 bytes) pVertexElementInfo[ii].mElementSizeInBytes = vertexFormatDesc.mpElements[ii].mElementSizeInBytes; // store the number of elements (i.e. 3xF32, 3 elements) pVertexElementInfo[ii].mElementCount = vertexFormatDesc.mVertexCount; // calculate the offset from the first element of the stream - assumes all blocks appear in the vertex stream as the order that appears here pVertexElementInfo[ii].mOffset = RunningOffset; RunningOffset = RunningOffset + pVertexElementInfo[ii].mElementSizeInBytes; // extract the name of stream pVertexElementInfo[ii].mpSemanticName = CPUT_VERTEX_ELEMENT_SEMANTIC_AS_STRING[ii]; switch(vertexFormatDesc.mpElements[ii].mVertexElementSemantic) { case CPUT_VERTEX_ELEMENT_POSITON: pVertexElementInfo[ii].mpSemanticName = "POSITION"; pVertexElementInfo[ii].mSemanticIndex = positionStreamCount++; break; case CPUT_VERTEX_ELEMENT_NORMAL: pVertexElementInfo[ii].mpSemanticName = "NORMAL"; pVertexElementInfo[ii].mSemanticIndex = normalStreamCount++; break; case CPUT_VERTEX_ELEMENT_TEXTURECOORD: pVertexElementInfo[ii].mpSemanticName = "TEXCOORD"; pVertexElementInfo[ii].mSemanticIndex = texCoordStreamCount++; break; case CPUT_VERTEX_ELEMENT_TANGENT: pVertexElementInfo[ii].mpSemanticName = "TANGENT"; pVertexElementInfo[ii].mSemanticIndex = tangentStreamCount++; break; case CPUT_VERTEX_ELEMENT_BINORMAL: pVertexElementInfo[ii].mpSemanticName = "BINORMAL"; pVertexElementInfo[ii].mSemanticIndex = binormalStreamCount++; break; case CPUT_VERTEX_ELEMENT_VERTEXCOLOR: pVertexElementInfo[ii].mpSemanticName = "COLOR"; pVertexElementInfo[ii].mSemanticIndex = colorStreamCount++; break; default: cString errorString = _L("Invalid vertex semantic in: '")+File+_L("'\n"); TRACE(errorString.c_str()); ASSERT(0, errorString); } } // Index buffer CPUTBufferInfo indexDataInfo; indexDataInfo.mElementType = (vertexFormatDesc.mIndexType == tUINT32) ? CPUT_U32 : CPUT_U16; indexDataInfo.mElementComponentCount = 1; indexDataInfo.mElementSizeInBytes = (vertexFormatDesc.mIndexType == tUINT32) ? sizeof(UINT32) : sizeof(UINT16); indexDataInfo.mElementCount = vertexFormatDesc.mIndexCount; indexDataInfo.mOffset = 0; indexDataInfo.mSemanticIndex = 0; indexDataInfo.mpSemanticName = NULL; if( pVertexElementInfo->mElementCount && indexDataInfo.mElementCount ) { result = pMesh->CreateNativeResources( this, meshIndex, vertexFormatDesc.mFormatDescriptorCount, pVertexElementInfo, (void*)vertexFormatDesc.mpVertices, &indexDataInfo, &vertexFormatDesc.mpIndices[0] ); if(CPUTFAILED(result)) { return result; } // CC added result = pMesh->ExtractVerticesandIndices(); if(CPUTFAILED(result)) { return result; } // CC added ends } delete [] pVertexElementInfo; pVertexElementInfo = NULL; ++meshIndex; } ASSERT( file.eof(), _L("") ); // close file file.close(); return result; }
//----------------------------------------------------------------------------- CPUTResult CPUTModel::LoadModelPayload(const cString &FileName) { CPUTResult result = CPUT_SUCCESS; CPUTFileSystem::CPUTOSifstream file(FileName, std::ios::in | std::ios::binary); ASSERT( !file.fail(), _L("CPUTModel::LoadModelPayload() - Could not find binary model file: ") + FileName ); // set up for mesh creation loop UINT meshIndex = 0; while(file.good() && !file.eof()) { // TODO: rearrange while() to avoid if(eof). Should perform only one branch per loop iteration, not two CPUTRawMeshData vertexFormatDesc; vertexFormatDesc.Read(file); if(file.eof()) { // TODO: Wtf? Why would we get here? We check eof at the top of loop. If it isn't eof there, why is it eof here? break; } ASSERT( meshIndex < mMeshCount, _L("Actual mesh count doesn't match stated mesh count")); // create the mesh. CPUTMesh *pMesh = mpMesh[meshIndex]; // always a triangle list (at this point) pMesh->SetMeshTopology(CPUT_TOPOLOGY_INDEXED_TRIANGLE_LIST); // get number of data blocks in the vertex element (pos,norm,uv,etc) CPUTBufferElementInfo *pVertexElementInfo = new CPUTBufferElementInfo[vertexFormatDesc.mFormatDescriptorCount]; // running count of each type of element int positionStreamCount=0; int normalStreamCount=0; int texCoordStreamCount=0; int tangentStreamCount=0; int binormalStreamCount=0; int colorStreamCount=0; int blendWeightStreamCount = 0; int blendIndexStreamCount = 0; int runningOffset = 0; for(UINT ii=0; ii<vertexFormatDesc.mFormatDescriptorCount; ii++) { // lookup the CPUT data type equivalent pVertexElementInfo[ii].mElementType = CPUT_FILE_ELEMENT_TYPE_TO_CPUT_TYPE_CONVERT(vertexFormatDesc.mpElements[ii].mVertexElementType); ASSERT((pVertexElementInfo[ii].mElementType !=CPUT_UNKNOWN ) , _L(".MDL file load error. This model file has an unknown data type in it's model data.")); // calculate the number of elements in this stream block (i.e. F32F32F32 = 3xF32) pVertexElementInfo[ii].mElementComponentCount = vertexFormatDesc.mpElements[ii].mElementSizeInBytes/CPUT_DATA_FORMAT_SIZE[pVertexElementInfo[ii].mElementType]; // store the size of each element type in bytes (i.e. 3xF32, each element = F32 = 4 bytes) pVertexElementInfo[ii].mElementSizeInBytes = vertexFormatDesc.mpElements[ii].mElementSizeInBytes; // store the number of elements (i.e. 3xF32, 3 elements) // calculate the offset from the first element of the stream - assumes all blocks appear in the vertex stream as the order that appears here pVertexElementInfo[ii].mOffset = runningOffset; runningOffset = runningOffset + pVertexElementInfo[ii].mElementSizeInBytes; // extract the name of stream pVertexElementInfo[ii].mpSemanticName = CPUT_VERTEX_ELEMENT_SEMANTIC_AS_STRING[ii]; //TODO: Calculate Opengl semantic index elsewhere switch(vertexFormatDesc.mpElements[ii].mVertexElementSemantic) { //FIXME - this isn't right, and needs to change for DX and OpenGL //Probably just need to move semantic bind point into OpenGL, or something. //Currently, TEXCOORD is the only semantic with multiples in common use. Adding //semantic index works provided addtional attributes (e.g. vertex color) are not //present case eCPUT_VERTEX_ELEMENT_SEMANTIC::CPUT_VERTEX_ELEMENT_POSITON: pVertexElementInfo[ii].mpSemanticName = "POSITION"; pVertexElementInfo[ii].mSemanticIndex = positionStreamCount++; pVertexElementInfo[ii].mBindPoint = CPUTSemanticBindPoint::POSITION; break; case eCPUT_VERTEX_ELEMENT_SEMANTIC::CPUT_VERTEX_ELEMENT_NORMAL: pVertexElementInfo[ii].mpSemanticName = "NORMAL"; pVertexElementInfo[ii].mSemanticIndex = normalStreamCount++; pVertexElementInfo[ii].mBindPoint = CPUTSemanticBindPoint::NORMAL; break; case eCPUT_VERTEX_ELEMENT_SEMANTIC::CPUT_VERTEX_ELEMENT_TEXTURECOORD: pVertexElementInfo[ii].mpSemanticName = "TEXCOORD"; pVertexElementInfo[ii].mSemanticIndex = texCoordStreamCount++; pVertexElementInfo[ii].mBindPoint = CPUTSemanticBindPoint::TEXCOORD + pVertexElementInfo[ii].mSemanticIndex; break; case eCPUT_VERTEX_ELEMENT_SEMANTIC::CPUT_VERTEX_ELEMENT_TANGENT: pVertexElementInfo[ii].mpSemanticName = "TANGENT"; pVertexElementInfo[ii].mSemanticIndex = tangentStreamCount++; pVertexElementInfo[ii].mBindPoint = CPUTSemanticBindPoint::TANGENT; break; case eCPUT_VERTEX_ELEMENT_SEMANTIC::CPUT_VERTEX_ELEMENT_BINORMAL: pVertexElementInfo[ii].mpSemanticName = "BINORMAL"; pVertexElementInfo[ii].mSemanticIndex = binormalStreamCount++; pVertexElementInfo[ii].mBindPoint = CPUTSemanticBindPoint::BINORMAL; break; case eCPUT_VERTEX_ELEMENT_SEMANTIC::CPUT_VERTEX_ELEMENT_VERTEXCOLOR: pVertexElementInfo[ii].mpSemanticName = "COLOR"; pVertexElementInfo[ii].mSemanticIndex = colorStreamCount++; pVertexElementInfo[ii].mBindPoint = CPUTSemanticBindPoint::COLOR; break; default: cString errorString = _L("Invalid vertex semantic in: '")+FileName+_L("'\n"); TRACE(errorString.c_str()); ASSERT(0, errorString); } } // Index buffer CPUTBufferElementInfo indexDataInfo; indexDataInfo.mElementType = (vertexFormatDesc.mIndexType == eCPUT_VERTEX_ELEMENT_TYPE::tUINT32) ? CPUT_U32 : CPUT_U16; indexDataInfo.mElementComponentCount = 1; indexDataInfo.mElementSizeInBytes = (vertexFormatDesc.mIndexType == eCPUT_VERTEX_ELEMENT_TYPE::tUINT32) ? sizeof(uint32_t) : sizeof(uint16_t); indexDataInfo.mOffset = 0; indexDataInfo.mSemanticIndex = 0; indexDataInfo.mpSemanticName = NULL; if( vertexFormatDesc.mVertexCount && vertexFormatDesc.mIndexCount ) { result = pMesh->CreateNativeResources( this, meshIndex, vertexFormatDesc.mFormatDescriptorCount, pVertexElementInfo, vertexFormatDesc.mVertexCount, (void*)vertexFormatDesc.mpVertices, &indexDataInfo, vertexFormatDesc.mIndexCount, vertexFormatDesc.mpIndices ); if(CPUTFAILED(result)) { return result; } } delete [] pVertexElementInfo; pVertexElementInfo = NULL; ++meshIndex; } ASSERT( file.eof(), _L("") ); // close file file.close(); return result; }
void CPUTModel_CPRT::CreateModelLayer(ID3D11Device* pd3dDevice, ID3D11DeviceContext* pImmediateContext, ID3D10Blob* pVertexShaderBlob, LayerInitialization layerType) { CPUTMesh* pMesh = new CPUTMesh(); float* layer = NULL; switch(layerType) { case NORMAL_LAYER: if(normals.size() < 1) return; normalOverlays.push_back(pMesh); layer = normals.front(); break; case TANGENT_LAYER: if(tangents.size() < 1) return; tangentOverlays.push_back(pMesh); layer = tangents.front(); break; } float* vertsToSubmit = new float[vertexCount.front()*3*2]; float* uvsToSubmit = new float[vertexCount.front()*3*2]; unsigned int vertIndexToSubmit = 0, uvIndexToSubmit=0; for(unsigned int i = 0; i < vertexCount.front()*3; ++i,vertIndexToSubmit+=3,uvIndexToSubmit+=2)//Going to process the vertex/normal information to create a bunch of lines { vertsToSubmit[vertIndexToSubmit] = vertices.front()[i]; uvsToSubmit[uvIndexToSubmit] = 0.0f; vertsToSubmit[vertIndexToSubmit+3] = vertices.front()[i]+0.2f*layer[i]; uvsToSubmit[uvIndexToSubmit+2] = 1.0f; ++i,++vertIndexToSubmit;++uvIndexToSubmit; vertsToSubmit[vertIndexToSubmit] = vertices.front()[i]; uvsToSubmit[uvIndexToSubmit] = 0.0f; vertsToSubmit[vertIndexToSubmit+3] = vertices.front()[i]+0.2f*layer[i]; uvsToSubmit[uvIndexToSubmit+2] = 1.0f; ++i,++vertIndexToSubmit;++uvIndexToSubmit; vertsToSubmit[vertIndexToSubmit] = vertices.front()[i]; vertsToSubmit[vertIndexToSubmit+3] = vertices.front()[i]+0.2f*layer[i]; ++vertIndexToSubmit; } delete layer; // set the topology pMesh->SetMeshTopology( CPUT_TOPOLOGY_LINE_LIST ); CPUTMeshStreamUniform* meshStream = new CPUTMeshStreamUniform(); // position stream CPUTMeshStreamInfoBlock* infoBlock = new CPUTMeshStreamInfoBlock(); meshStream->SetName("POSITION"); meshStream->SetData(vertsToSubmit); infoBlock->m_StreamBufferType = CPUT_STREAM_TYPE_VERTEX; infoBlock->m_StreamComponentsLayoutType = CPUT_STREAM_ELEMENT_LAYOUT_UNIFORM; infoBlock->m_DataFormatElementType = CPUT_F32; infoBlock->m_NumberDataFormatElements = 3; // 3xF32 infoBlock->m_DataElementBlockSize = sizeof(float)*3; // 12 bytes = size of CPUT_F32_F32_F32 element infoBlock->m_NumberVerticies = vertexCount.front()*2; meshStream->SetStreamInfo(infoBlock); pMesh->AddVertexStream(meshStream); // UV stream meshStream = new CPUTMeshStreamUniform(); infoBlock = new CPUTMeshStreamInfoBlock(); meshStream->SetName("TEXCOORD"); meshStream->SetData(uvsToSubmit); infoBlock->m_StreamBufferType = CPUT_STREAM_TYPE_VERTEX; infoBlock->m_StreamComponentsLayoutType = CPUT_STREAM_ELEMENT_LAYOUT_UNIFORM; infoBlock->m_DataFormatElementType = CPUT_F32; infoBlock->m_NumberDataFormatElements = 2; // 3xF32 infoBlock->m_DataElementBlockSize = sizeof(float)*3; // 12 bytes = size of CPUT_F32_F32_F32 element infoBlock->m_NumberVerticies = vertexCount.front()*2; meshStream->SetStreamInfo(infoBlock); pMesh->AddVertexStream(meshStream); CPUTMaterialPhong* pMaterialPhong = new CPUTMaterialPhong(); switch(layerType) { case NORMAL_LAYER: pMaterialPhong->SetTexture( CPUT_PHONG_MATERIAL_PROPERTY_DIFFUSE_TEXTURE, pd3dDevice, "../media/normals.png" ); break; case TANGENT_LAYER: pMaterialPhong->SetTexture( CPUT_PHONG_MATERIAL_PROPERTY_DIFFUSE_TEXTURE, pd3dDevice, "../media/tangents.png" ); break; } pMesh->SetMaterial((CPUTMaterialBase*)pMaterialPhong); int currentNumMeshes = AddMesh(pMesh); D3D11_INPUT_ELEMENT_DESC* layout = NULL; ID3D11InputLayout* pVertexLayout = NULL; pMesh = (CPUTMesh*) GetMesh(currentNumMeshes-1); layerIndices.push_back(currentNumMeshes-1); // register each mesh with the current graphics device pMesh->Register(pd3dDevice, &layout); // Create the input layout (TODO: should this be left to user to do?) int numInputLayoutElements; pMesh->GetNumberOfInputLayoutElements(numInputLayoutElements); int numElements = pMesh->GetVertexStreamCount(); pd3dDevice->CreateInputLayout( layout, numInputLayoutElements, pVertexShaderBlob->GetBufferPointer(), pVertexShaderBlob->GetBufferSize(), &pVertexLayout ); pMesh->SetDXLayout(pVertexLayout); delete vertsToSubmit; delete uvsToSubmit; switch(layerType) { case NORMAL_LAYER: normals.erase(normals.begin()); break; case TANGENT_LAYER: tangents.erase(tangents.begin()); break; } }