SpaceShooter::SpaceShooter() { Renderer::Get().Initialize(); // Create the player's view. Quaternion viewRotation( Vector3::Right, Pi / 2.f ); mCamera = ViewPtr( new View( Vector3( 0.f, 60.f, 0.f ), viewRotation, 1.04719755f, 1920.0f / 1080.0f, 0.1f, 100.f, false ) ); Renderer::Get().SetCamera( mCamera ); // Create the background. MaterialPtr backgroundMaterial = MaterialPtr( new Material( L"Resources\\Shaders\\tangent.hlsl", L"Resources\\Textures\\starfield.dds" ) ); RawMeshPtr backgroundMesh = RawMeshPtr( new RawMesh() ); GenerateQuadVerticies( *backgroundMesh.get(), 90.f, 45.f ); MeshPrimitivePtr background = MeshPrimitivePtr( new MeshPrimitive( backgroundMesh, backgroundMaterial, GetTangentSpaceVertexSource() ) ); mBackground = GameObjectPtr( new GameObject( background ) ); Matrix4 backgroundOffset; backgroundOffset.CreateFromQuaternion( Quaternion( Vector3::Right, Pi / 2.f ) ); mBackground->SetOffset( backgroundOffset ); mBackground->SetTranslation( Vector3( 0.f, -10.f, 0.f ) ); mBackground->Attach(); // Load the player's ship. MaterialPtr playerShipMaterial = MaterialPtr( new Material( L"Resources\\Shaders\\tangent.hlsl", L"Resources\\Textures\\frigate.dds" ) ); RawMeshPtr shipMesh = RawMeshPtr( new RawMesh() ); LoadMeshFromObjFile( "Resources\\Meshes\\frigate_normal.obj", *shipMesh.get() ); CalculateTangents( *shipMesh.get() ); MeshPrimitivePtr player = MeshPrimitivePtr( new MeshPrimitive( shipMesh, playerShipMaterial, GetTangentSpaceVertexSource() ) ); mPlayerObject = PlayerShipPtr( new PlayerShip( player ) ); mPlayerObject->SetScale( 0.3f ); mPlayerObject->SetBounds( 6.5f ); Matrix4 playerOffset; playerOffset.CreateFromQuaternion( Quaternion( Vector3::Up, Pi / 2.f ) ); mPlayerObject->SetOffset( playerOffset ); mPlayerObject->SetFrictionFactor( 0.5f ); mPlayerObject->Attach(); // Load asteroids MaterialPtr asteroidMaterial = MaterialPtr( new Material( L"Resources\\Shaders\\tangent.hlsl", L"Resources\\Textures\\asteroid.dds" ) ); RawMeshPtr asteroidMesh = RawMeshPtr( new RawMesh() ); LoadMeshFromObjFile( "Resources\\Meshes\\asteroid1.obj", *asteroidMesh.get() ); CalculateTangents( *asteroidMesh.get() ); for ( int i = 0; i < 5; i++ ) { MeshPrimitivePtr asteroid = MeshPrimitivePtr( new MeshPrimitive( asteroidMesh, asteroidMaterial, GetTangentSpaceVertexSource() ) ); GameObjectPtr newAsteroid = GameObjectPtr( new Asteroid( asteroid ) ); newAsteroid->SetScale( 1.f ); newAsteroid->SetBounds( 4.f ); newAsteroid->SetTranslation( Vector3( RandomFloat( -40.f, 40.f ), 0.f, RandomFloat( -40.f, 40.f ) ) ); mAsteroids.push_back( newAsteroid ); newAsteroid->Attach(); } // Load the player's jet particles. playerJetParticles = ParticleSystemPtr( new ParticleSystem() ); ParticleSystemLoader loader; loader.LoadFromFile( "Resources\\ParticleSystems\\jet_fuel.part", playerJetParticles ); playerJetParticles->SetEmitterState( false ); // turn the particles off to start with Renderer::Get().AddTranslucentPrimitive( playerJetParticles ); }
void ModelLoader::AddTri(const vector<vector<int>>& data) { ASSERT (m_pCurrentMesh != 0, ""); unsigned int index[3]; for (int i = 0; i < 3; ++i) { index[i] = m_VPNTTData.size(); Vector3 tangent = Vector3(0,0,0); VertexPosNormTanTex vpntt( m_VertexData[data[i][0] - 1], m_NormalData[data[i][2] - 1], tangent, m_TextureData[data[i][1] - 1]); stringstream stream; stream << data[i][0] << "/" << data[i][1] << "/" << data[i][2]; if (m_VPNTTMap.count(stream.str()) == 0) { m_VPNTTData.push_back(vpntt); m_VPNTTMap[stream.str()] = index[i]; } else { index[i] = m_VPNTTMap[stream.str()]; } } m_IndexData.push_back(index[2]); m_IndexData.push_back(index[1]); m_IndexData.push_back(index[0]); CalculateTangents(m_VPNTTData[index[2]], m_VPNTTData[index[1]], m_VPNTTData[index[0]]); }
bool Mesh::load(const std::string& filename) { std::shared_ptr<ObjMesh> mesh = nullptr; if ( !LoadObjMesh(filename, mesh) ) return false; if ( mesh->faces.size() > 0 ) { if ( mesh->faces[0].type != TRIANGLE ) { std::cerr << "[Mesh:load] Error: Only triangle-face Obj files supported." << std::endl; return false; } } this->name = mesh->name; std::vector<Vector3f> normals; std::vector<Vector4f> tangents; std::vector<unsigned int> indices; std::vector<unsigned int> textureIndices; std::vector<unsigned int> normalIndices; //-------------------------------------------------------------------------- // Copy the face indices from the *.obj file to this mesh. //-------------------------------------------------------------------------- indices.resize(mesh->faces.size() * TRIANGLE_EDGE_COUNT); normalIndices.resize(mesh->faces.size() * TRIANGLE_EDGE_COUNT); textureIndices.resize(mesh->faces.size() * TRIANGLE_EDGE_COUNT); unsigned int index = 0; for ( unsigned int i = 0; i < mesh->faces.size(); i++ ) { indices[index] = static_cast<unsigned int>(mesh->faces[i].vertexIndices[A]); indices[index + 1] = static_cast<unsigned int>(mesh->faces[i].vertexIndices[B]); indices[index + 2] = static_cast<unsigned int>(mesh->faces[i].vertexIndices[C]); normalIndices[index] = static_cast<unsigned int>(mesh->faces[i].normalIndices[A]); normalIndices[index + 1] = static_cast<unsigned int>(mesh->faces[i].normalIndices[B]); normalIndices[index + 2] = static_cast<unsigned int>(mesh->faces[i].normalIndices[C]); textureIndices[index] = static_cast<unsigned int>(mesh->faces[i].textureIndices[A]); textureIndices[index + 1] = static_cast<unsigned int>(mesh->faces[i].textureIndices[B]); textureIndices[index + 2] = static_cast<unsigned int>(mesh->faces[i].textureIndices[C]); index += TRIANGLE_EDGE_COUNT; } //-------------------------------------------------------------------------- // Calcualte the vertex normals, tangents, and face normals. //-------------------------------------------------------------------------- //CalculateNormals(indices, mesh->vertices, normals); normals.resize(mesh->normals.size()); for ( unsigned int i = 0; i < mesh->normals.size(); i++ ) { normals[i] = mesh->normals[i]; } Decompress(indices, normalIndices, textureIndices, mesh->vertices, normals, mesh->textureCoordinates, tangents, this->vertices, this->faces); CalculateTangents(this->vertices, this->faces); this->constructOnGPU(); return true; }
void RenderDataManager::InitializeNode(TQuad* q) { assert(!q->renderData); QuadRenderData* rd = q->renderData = Allocate(); // Allocate vertex data space const size_t vertexSize = q->GetVertexSize(); if (static_cast<int>(vertexSize) != rd->vertexSize) { const size_t size = NUM_VERTICES * vertexSize; if (rd->vertexBuffer.GetSize() != size) { rd->vertexBuffer.Init(size); } rd->vertexSize = vertexSize; } // build the vertex buffer Vector3* v = (Vector3*)rd->vertexBuffer.LockData(); uint vda = q->textureSetup->vertexDataReq; // vertex data requirements const Heightmap* hm = roothm->GetLevel(q->depth); // get the right heightmap level for (int y = q->hmPos.y; y <= (q->hmPos.y + QUAD_W); y++) for (int x = q->hmPos.x; x <= (q->hmPos.x + QUAD_W); x++) { *(v++) = Vector3(x * hm->squareSize, hm->atSynced(x, y), y * hm->squareSize); Vector3 tangent, binormal; CalculateTangents(hm, x,y, tangent, binormal); Vector3 normal = binormal.cross(tangent); normal.ANormalize(); if (vda & VRT_Normal) *(v++) = normal; if (vda & VRT_TangentSpaceMatrix) { tangent.ANormalize(); binormal.ANormalize(); // orthonormal matrix, so inverse=transpose // Take the inverse of the tangent space -> world space transformation Vector3* tgs2ws = v; tgs2ws[0] = Vector3(tangent.x, binormal.x, normal.x); tgs2ws[1] = Vector3(tangent.y, binormal.y, normal.y); tgs2ws[2] = Vector3(tangent.z, binormal.z, normal.z); v += 3; } } rd->vertexBuffer.UnlockData(); rd->SetQuad(q); }
void ModelLoader::FlushMesh() { ASSERT(m_pCurrentMesh != 0, ""); // TANGENTS for (unsigned int i = 0; i < m_VPNTTData.size() / 3; ++i) { CalculateTangents(m_VPNTTData[i*3],m_VPNTTData[(i*3)+1],m_VPNTTData[(i*3)+2]); } m_pCurrentMesh->SetVertices(m_VPNTTData); m_pCurrentMesh->SetIndices(m_IndexData); m_VPNTTData.clear(); m_VPNTTMap.clear(); m_pCurrentMesh = 0; m_IndexData.clear(); }
void Heightmap::GenerateNormals () { normalData = SAFE_NEW uchar [3 * w * h]; uchar *cnorm = normalData; for (int y=0;y<h;y++) for (int x=0;x<w;x++) { Vector3 tangent, binormal; CalculateTangents(this, x,y,tangent,binormal); Vector3 normal = binormal.cross(tangent); normal.Normalize (); *(cnorm++) = (uchar)((normal.x * 0.5f + 0.5f) * 255); *(cnorm++) = (uchar)((normal.y * 0.5f + 0.5f) * 255); *(cnorm++) = (uchar)((normal.z * 0.5f + 0.5f) * 255); } }
Mesh::Mesh(int vertNum, Vertex* vert, int indNum, unsigned int* indices, ID3D11Device* deviceObj) { numOfIndices = indNum; CalculateTangents(&verts[0], verts.size(), &indices[0], numOfIndices); // Create vertexBuffers D3D11_BUFFER_DESC vbd; vbd.Usage = D3D11_USAGE_IMMUTABLE; vbd.ByteWidth = sizeof(Vertex) * vertNum; vbd.BindFlags = D3D11_BIND_VERTEX_BUFFER; vbd.CPUAccessFlags = 0; vbd.MiscFlags = 0; vbd.StructureByteStride = 0; // Load Data to Vertex Buffer D3D11_SUBRESOURCE_DATA vertData; vertData.pSysMem = vert; // Create the buffer with the data HR(deviceObj->CreateBuffer(&vbd, &vertData, &vBuffer)); //Create Index Buffer D3D11_BUFFER_DESC ibd; ibd.Usage = D3D11_USAGE_IMMUTABLE; ibd.ByteWidth = sizeof(int) * indNum; ibd.BindFlags = D3D11_BIND_INDEX_BUFFER; ibd.CPUAccessFlags = 0; ibd.MiscFlags = 0; ibd.StructureByteStride = 0; //Load Data to IndexBuffer D3D11_SUBRESOURCE_DATA indData; indData.pSysMem = indices; // Create Index Buffer with the data. HR(deviceObj->CreateBuffer(&ibd, &indData, &iBuffer)); }
Model<VertexPosNormTanTex>* TerrainLoader::Load(ID3D10Device* pDXDevice, const tstring& key) { Model<VertexPosNormTanTex>* ret = 0; if ( m_pAssets->IsAssetPresent(key)) { ret = m_pAssets->GetAsset(key); } else { vector<VertexPosNormTanTex> vertices; vector<DWORD> indices; Texture2D* heightMap = Content->LoadTexture2D(key, true); ID3D10Texture2D* pTex2D = heightMap->GetTextureResource(); vertices.reserve(heightMap->GetWidth() * heightMap->GetHeight()); indices.reserve((heightMap->GetWidth()-1) * (heightMap->GetHeight()-1) * 6); D3D10_MAPPED_TEXTURE2D pMappedTex2D; pTex2D->Map(0, D3D10_MAP_READ, 0, &pMappedTex2D); float heightMult = 1.0f; float planarMult = 1.0f / max(heightMap->GetWidth(), heightMap->GetHeight()); BYTE* pData = static_cast<BYTE*>(pMappedTex2D.pData); for (UINT x = 0; x < heightMap->GetHeight(); ++x) { for (UINT z = 0; z < heightMap->GetWidth(); ++z) { float height = pData[z * 4 + x * pMappedTex2D.RowPitch + 0] / 255.0f; //get red vertices.push_back(VertexPosNormTanTex( static_cast<float>(x) * planarMult, height * heightMult, static_cast<float>(z) * planarMult, 0, 0, 0, 0, 0, 0, static_cast<float>(z) / heightMap->GetWidth(), static_cast<float>(x) / heightMap->GetHeight())); if (z != heightMap->GetWidth() - 1 && x != heightMap->GetHeight() - 1) { indices.push_back(z + x * heightMap->GetWidth()); indices.push_back(z + x * heightMap->GetWidth() + 1); indices.push_back(z + (x + 1) * heightMap->GetWidth()); indices.push_back(z + x * heightMap->GetWidth() + 1); indices.push_back(z + (x + 1) * heightMap->GetWidth() + 1); indices.push_back(z + (x + 1) * heightMap->GetWidth()); } } } pTex2D->Unmap(0); CalculateNormals(vertices, indices); CalculateTangents(vertices, indices); Model<VertexPosNormTanTex>* pModel = new Model<VertexPosNormTanTex>(pDXDevice); ModelMesh<VertexPosNormTanTex>* pMesh = pModel->AddMesh(_T("")); pMesh->SetVertices(vertices); pMesh->SetIndices(indices); m_pAssets->AddAsset(key, pModel); ret = pModel; } return ret; }
void Blendmap::Generate(Heightmap* rootHm, int lodLevel, float hmScale, float hmOffset) { const Heightmap* heightmap = rootHm->GetLevel(-lodLevel); // Allocate the blendmap image AlphaImage* bm = new AlphaImage; bm->Alloc(heightmap->w-1, heightmap->h-1); // texture dimensions have to be power-of-two Blendmap::GeneratorInfo* gi = generatorInfo; // Calculate blend factors using the function parameters and heightmap input: for (int y=0;y<bm->h;y++) { for (int x=0;x<bm->w;x++) { const float h = (heightmap->atSynced(x, y) - hmOffset) / hmScale; float factor=1.0f; if(h < gi->minHeight - gi->minHeightFuzzy) { bm->at(x,y) = 0.0f; continue; } else if (gi->minHeightFuzzy > 0.0f && h < gi->minHeight + gi->minHeightFuzzy) factor = (h - (gi->minHeight - gi->minHeightFuzzy)) / (2.0f * gi->minHeightFuzzy); if(h > gi->maxHeight + gi->maxHeightFuzzy) { bm->at (x,y) = 0.0f; continue; } else if (gi->maxHeightFuzzy > 0.0f && h > gi->maxHeight - gi->maxHeightFuzzy) factor *= ((gi->maxHeight + gi->maxHeightFuzzy) - h) / (2.0f * gi->maxHeightFuzzy); float norm_y = 0.0f; if (heightmap->normalData) { const uchar* cnorm = heightmap->GetNormal(x, y); norm_y = cnorm[1] / 255.0f * 2.0f - 1.0f; if (norm_y > 1.0f) norm_y = 1.0f; } else { Vector3 tangent, binormal; CalculateTangents(heightmap, x,y,tangent,binormal); Vector3 normal = tangent.cross(binormal); normal.ANormalize(); norm_y = normal.y; } // flatness=dotproduct of surface normal with up vector float slope = 1.0f - fabs(norm_y); if (slope < gi->minSlope - gi->minSlopeFuzzy) { bm->at(x,y) = 0.0f; continue; } else if (gi->minSlopeFuzzy > 0.0f && slope < gi->minSlope + gi->minSlopeFuzzy) factor *= (h - (gi->minSlope - gi->minSlopeFuzzy)) / ( 2.0f * gi->minSlopeFuzzy); if (slope > gi->maxSlope + gi->maxSlopeFuzzy) { bm->at(x,y) = 0.0f; continue; } else if (gi->maxSlopeFuzzy > 0.0f && slope > gi->maxSlope - gi->maxSlopeFuzzy) factor *= ((gi->maxSlope + gi->maxSlopeFuzzy) - h) / (2.0f * gi->maxSlopeFuzzy); factor *= gi->coverage; factor *= (rand() < gi->noise * RAND_MAX) ? 0.0f : 1.0f; bm->at(x,y) = factor; } } BlendmapFilter(bm); image = bm; }
int MeshCompiler::Compile( const char* InFilename, const char* OutFilename, bool LongIndices ) { m_StrippedFilename = FileUtil::StripExtensions( FileUtil::StripLeadingFolders( InFilename ) ); TiXmlDocument XMLDoc; XMLDoc.LoadFile( InFilename ); TiXmlElement* RootElement = XMLDoc.FirstChildElement(); // "mesh" // Sanity check if( _stricmp( RootElement->Value(), "mesh" ) ) { PRINTF( "Input file is not a valid XML mesh file.\n" ); return -1; } STATICHASH( BakeAOForDynamicMeshes ); STATICHASH( BakeAOForAnimatedMeshes ); STATICHASH( TraceTriangleBacks ); STATICHASH( DynamicAORadius ); STATICHASH( DynamicAOPushOut ); MAKEHASH( m_StrippedFilename ); ConfigManager::Load( FileStream( "tools.cfg", FileStream::EFM_Read ) ); m_BakeAOForDynamicMeshes = ConfigManager::GetArchetypeBool( sBakeAOForDynamicMeshes, ConfigManager::EmptyContext, false, sm_StrippedFilename ); m_BakeAOForAnimatedMeshes = ConfigManager::GetArchetypeBool( sBakeAOForAnimatedMeshes, ConfigManager::EmptyContext, false, sm_StrippedFilename ); m_TraceTriangleBacks = ConfigManager::GetArchetypeBool( sTraceTriangleBacks, ConfigManager::EmptyContext, false, sm_StrippedFilename ); m_AORadius = ConfigManager::GetArchetypeFloat( sDynamicAORadius, ConfigManager::EmptyContext, 0.1f, sm_StrippedFilename ); m_AOPushOut = ConfigManager::GetArchetypeFloat( sDynamicAOPushOut, ConfigManager::EmptyContext, 0.01f, sm_StrippedFilename ); m_Header.m_LongIndices = LongIndices; // Get armature first, which will make it easier to handle bone references in verts TiXmlElement* Arm = RootElement->FirstChildElement( "armature" ); CompileArmature( Arm ); int NumFaces = 0; for( TiXmlElement* Face = RootElement->FirstChildElement( "face" ); Face; Face = Face->NextSiblingElement( "face" ) ) { CompileFace( Face ); NumFaces++; } for( TiXmlElement* Mat = RootElement->FirstChildElement( "material" ); Mat; Mat = Mat->NextSiblingElement( "material" ) ) { CompileMaterial( Mat ); } m_Header.m_NumVertices = m_Positions.Size(); m_Header.m_NumIndices = m_Indices.Size(); NormalizeWeights(); CalculateAABB(); if( m_Header.m_HasUVs && m_Header.m_HasNormals ) { m_Header.m_HasTangents = true; } PRINTF( "Calculating tangents...\n" ); CalculateTangents(); CalculateAmbientOcclusion(); PRINTF( "Compile successful!\n" ); PRINTF( "Imported %d faces.\n", NumFaces ); Write( FileStream( OutFilename, FileStream::EFM_Write ) ); PRINTF( "Exported %d vertices.\n", m_Header.m_NumVertices ); PRINTF( "Exported %d indices (%d triangles).\n", m_Header.m_NumIndices, m_Header.m_NumIndices / 3 ); if( m_Header.m_HasSkeleton ) { PRINTF( "Exported %d bones.\n", m_Header.m_NumBones ); PRINTF( "Exported %d frames.\n", m_Header.m_NumFrames ); PRINTF( "Exported %d animations.\n", m_Header.m_NumAnims ); } return 0; }
Mesh::Mesh(ID3D11Device* deviceObj, char* filename) { // File input object std::ifstream obj(filename); // <-- Replace filename with your parameter // Check for successful open if (!obj.is_open()) return; // Still good? while (obj.good()) { // Get the line (100 characters should be more than enough) obj.getline(chars, 100); // Check the type of line if (chars[0] == 'v' && chars[1] == 'n') { // Read the 3 numbers directly into an XMFLOAT3 XMFLOAT3 norm; sscanf_s( chars, "vn %f %f %f", &norm.x, &norm.y, &norm.z); // Add to the list of normals normals.push_back(norm); } else if (chars[0] == 'v' && chars[1] == 't') { // Read the 2 numbers directly into an XMFLOAT2 XMFLOAT2 uv; sscanf_s( chars, "vt %f %f", &uv.x, &uv.y); // Add to the list of uv's uvs.push_back(uv); } else if (chars[0] == 'v') { // Read the 3 numbers directly into an XMFLOAT3 XMFLOAT3 pos; sscanf_s( chars, "v %f %f %f", &pos.x, &pos.y, &pos.z); // Add to the positions positions.push_back(pos); } else if (chars[0] == 'f') { // Read the 9 face indices into an array unsigned int i[9]; sscanf_s( chars, "f %d/%d/%d %d/%d/%d %d/%d/%d", &i[0], &i[1], &i[2], &i[3], &i[4], &i[5], &i[6], &i[7], &i[8]); // - Create the verts by looking up // corresponding data from vectors // - OBJ File indices are 1-based, so // they need to be adusted Vertex v1; v1.Position = positions[i[0] - 1]; v1.UV = uvs[i[1] - 1]; v1.Normal = normals[i[2] - 1]; Vertex v2; v2.Position = positions[i[3] - 1]; v2.UV = uvs[i[4] - 1]; v2.Normal = normals[i[5] - 1]; Vertex v3; v3.Position = positions[i[6] - 1]; v3.UV = uvs[i[7] - 1]; v3.Normal = normals[i[8] - 1]; // Flip the UV's since they're probably "upside down" v1.UV.y = 1.0f - v1.UV.y; v2.UV.y = 1.0f - v2.UV.y; v3.UV.y = 1.0f - v3.UV.y; // Add the verts to the vector verts.push_back(v1); verts.push_back(v2); verts.push_back(v3); // Add three more indices indices.push_back(vertCounter++); indices.push_back(vertCounter++); indices.push_back(vertCounter++); } } // Close obj.close(); numOfIndices = indices.size(); CalculateTangents(&verts[0], verts.size(), &indices[0], numOfIndices); // Create vertexBuffers D3D11_BUFFER_DESC vbd; vbd.Usage = D3D11_USAGE_IMMUTABLE; vbd.ByteWidth = sizeof(Vertex) * verts.size(); vbd.BindFlags = D3D11_BIND_VERTEX_BUFFER; vbd.CPUAccessFlags = 0; vbd.MiscFlags = 0; vbd.StructureByteStride = 0; // Load Data to Vertex Buffer D3D11_SUBRESOURCE_DATA vertData; vertData.pSysMem = &verts[0]; // Create the buffer with the data HR(deviceObj->CreateBuffer(&vbd, &vertData, &vBuffer)); //Create Index Buffer D3D11_BUFFER_DESC ibd; ibd.Usage = D3D11_USAGE_IMMUTABLE; ibd.ByteWidth = sizeof(int) * indices.size(); ibd.BindFlags = D3D11_BIND_INDEX_BUFFER; ibd.CPUAccessFlags = 0; ibd.MiscFlags = 0; ibd.StructureByteStride = 0; //Load Data to IndexBuffer D3D11_SUBRESOURCE_DATA indData; indData.pSysMem = &indices[0]; // Create Index Buffer with the data. HR(deviceObj->CreateBuffer(&ibd, &indData, &iBuffer)); }