#include "ResourceManager.h" #include "Matrix4x4.h" #include "Geometry.h" #include "SceneEntity.h" #include "Material.h" #include "Texture.h" #include "gzstream.h" #include "Vector3.h" #include "Transform3.h" #include "Shape.h" #include "LODInfo.h" #include "RenderState.h" #include "ShaderProgram.h" #include "ShaderManager.h" #ifdef _CRT_SET #define _CRTDBG_MAP_ALLOC #include #include // redefine new operator #define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__) #define new DEBUG_NEW #endif using namespace std; namespace CHCDemoEngine { // only instance of the resource manager ResourceManager *ResourceManager::sResourceManager = NULL; ResourceManager::ResourceManager() { mUseNormalMapping = false; mUseSpecialColors = false; } ResourceManager::~ResourceManager() { // delete all resources. CLEAR_CONTAINER(mSceneEntities); CLEAR_CONTAINER(mGeometry); CLEAR_CONTAINER(mMaterials); CLEAR_CONTAINER(mTextures); CLEAR_CONTAINER(mTrafos); CLEAR_CONTAINER(mShapes); } void ResourceManager::DelSingleton() { DEL_PTR(sResourceManager); } SceneEntity *ResourceManager::LoadSceneEntity(igzstream &str) { bool hasTrafo; str.read(reinterpret_cast(&hasTrafo), sizeof(bool)); SceneEntity *sceneGeom; Transform3 *trafo; if (!hasTrafo) { trafo = new Transform3(); // identity } else { Matrix4x4 m; str.read(reinterpret_cast(m.x), sizeof(Matrix4x4)); trafo = new Transform3(m); } mTrafos.push_back(trafo); sceneGeom = new SceneEntity(trafo); /////////////// //-- load LOD levels // note: lods must be ordered from smallest distance to largest int numLODs; str.read(reinterpret_cast(&numLODs), sizeof(int)); for (int i = 0; i < numLODs; ++ i) { // the distance until the next LOD level is used float dist; str.read(reinterpret_cast(&dist), sizeof(float)); int numShapes; str.read(reinterpret_cast(&numShapes), sizeof(int)); //LODLevel *lodLevel = new LODLevel(dist); LODLevel lodLevel(dist); for (int j = 0; j < numShapes; ++ j) { int shapeId; str.read(reinterpret_cast(&shapeId), sizeof(int)); Geometry *geom = mGeometryTable[shapeId]; Material *mat = mMaterialTable[shapeId]; // create shape Shape *shape = new Shape(geom, mat); mShapes.push_back(shape); sceneGeom->AddShape(shape); lodLevel.AddShape(shape); } //mLODs.push_back(lodLevel); sceneGeom->AddLODLevel(lodLevel); } static ShaderProgram *sTreeAnimationProgram = ShaderManager::GetSingleton()->GetShaderProgram("treeAnimation"); static ShaderProgram *sTreeAnimationProgramMrt = ShaderManager::GetSingleton()->GetShaderProgram("treeAnimationMrt"); /////////// //-- hack: add tree animation (should be done per material script!) if (numLODs > 1) { ShapeContainer::iterator sstart, send; // only use shader for the first two lod levels (the non-billboards) for (int i = 0; i < min(numLODs, 2); ++ i) //for (int i = 0; i < numLODs; ++ i) { sceneGeom->GetLODLevel(i, sstart, send); for (ShapeContainer::iterator it = sstart; it != send; ++ it) { Shape *shape = *it; Material *mat = shape->GetMaterial(); // add the vertex animation program for (int i = 0; i < 3; ++ i) { Technique *tech = mat->GetTechnique(i); GPUProgramParameters *vtxParams = tech->GetVertexProgramParameters(); if (i == 0) { tech->SetVertexProgram(sTreeAnimationProgram); vtxParams->SetLightDirParam(5); } else { tech->SetVertexProgram(sTreeAnimationProgramMrt); vtxParams->SetOldTimerParam(5); } /// use a timer to simulate the moving of the tree in the wind vtxParams->SetTimerParam(0); // wind direction static Vector3 windDir = Normalize(Vector3(0.8f, 0.2f, 0.0f)); vtxParams->SetValue3f(1, windDir.x, windDir.y, windDir.z); // amplitude vtxParams->SetValue1f(2, 0.3f); AxisAlignedBox3 box = sceneGeom->GetBoundingBox(); vtxParams->SetValue2f(3, box.Min().z, box.Max().z); // frequency vtxParams->SetValue1f(4, 0.1f); } } } } return sceneGeom; } int ResourceManager::LoadTextures(igzstream &str) { int numTextures; str.read(reinterpret_cast(&numTextures), sizeof(int)); for (int i = 0; i < numTextures; ++ i) { // load texture name int texnameSize; str.read(reinterpret_cast(&texnameSize), sizeof(int)); char *texname = new char[texnameSize]; str.read(texname, sizeof(char) * texnameSize); Texture *tex = new Texture(model_path + texname); int boundS, boundT; str.read(reinterpret_cast(&boundS), sizeof(int)); str.read(reinterpret_cast(&boundT), sizeof(int)); tex->SetBoundaryModeS(boundS); tex->SetBoundaryModeT(boundT); tex->Create(); mTextureTable[i] = tex; mTextures.push_back(tex); delete [] texname; } return numTextures; } // todo: split up geometry and materials!! int ResourceManager::LoadShapes(igzstream &str) { int numShapes; str.read(reinterpret_cast(&numShapes), sizeof(int)); for (int i = 0; i < numShapes; ++ i) { Geometry *geom = LoadGeometry(str); Material *mat = LoadMaterial(str); mGeometryTable[i] = geom; mMaterialTable[i] = mat; mGeometry.push_back(geom); mMaterials.push_back(mat); } return numShapes; } Material *ResourceManager::LoadMaterial(igzstream &str) { // default material Material *mat = new Material(); // set default fragment + vertex programs Technique *tech = mat->GetDefaultTechnique(); // texture int texId; str.read(reinterpret_cast(&texId), sizeof(int)); if (texId >= 0) tech->SetTexture(mTextureTable[texId]); str.read(reinterpret_cast(&tech->mAlphaTestEnabled), sizeof(bool)); str.read(reinterpret_cast(&tech->mCullFaceEnabled), sizeof(bool)); // gl material bool hasGlMaterial; str.read(reinterpret_cast(&hasGlMaterial), sizeof(bool)); if (hasGlMaterial) { // only write rgb part of the material str.read(reinterpret_cast(&tech->mAmbientColor), sizeof(Vector3)); str.read(reinterpret_cast(&tech->mDiffuseColor), sizeof(Vector3)); str.read(reinterpret_cast(&tech->mEmmisiveColor), sizeof(Vector3)); str.read(reinterpret_cast(&tech->mSpecularColor), sizeof(Vector3)); } if (mUseSpecialColors) { tech->mAmbientColor.r = tech->mAmbientColor.g = tech->mAmbientColor.b = 0.2f; tech->mDiffuseColor.r = 0.7f; tech->mDiffuseColor.g = 0.5f; tech->mDiffuseColor.b = 0.2f; } /////////////// //-- add technique for deferred shading static ShaderProgram *sDefaultFragmentProgramMrt = ShaderManager::GetSingleton()->GetShaderProgram("defaultFragmentMrt"); static ShaderProgram *sDefaultFragmentTexProgramMrt = ShaderManager::GetSingleton()->GetShaderProgram("defaultFragmentTexMrt"); static ShaderProgram *sDefaultVertexProgramMrt = ShaderManager::GetSingleton()->GetShaderProgram("defaultVertexMrt"); static ShaderProgram *sNormalMappingVertexProgramMrt = ShaderManager::GetSingleton()->GetShaderProgram("normalMappingVertexMrt"); static ShaderProgram *sNormalMappingFragmentProgramMrt = ShaderManager::GetSingleton()->GetShaderProgram("normalMappingFragmentMrt"); Technique *deferred = new Technique(*tech); if (mUseNormalMapping) { deferred->SetFragmentProgram(sNormalMappingFragmentProgramMrt); deferred->SetVertexProgram(sNormalMappingVertexProgramMrt); } else { if (deferred->GetTexture()) deferred->SetFragmentProgram(sDefaultFragmentTexProgramMrt); else deferred->SetFragmentProgram(sDefaultFragmentProgramMrt); deferred->SetVertexProgram(sDefaultVertexProgramMrt); } deferred->GetFragmentProgramParameters()->SetViewMatrixParam(0); deferred->GetVertexProgramParameters()->SetModelMatrixParam(1); deferred->GetVertexProgramParameters()->SetOldModelMatrixParam(2); mat->AddTechnique(deferred); /////////// //-- add depth pass Technique *depthPass = new Technique(*tech); depthPass->SetColorWriteEnabled(false); depthPass->SetLightingEnabled(false); mat->AddTechnique(depthPass); return mat; } Geometry *ResourceManager::LoadGeometry(igzstream &str) { Vector3 *vertices; Vector3 *normals; Texcoord2 *texcoords; ////////////// //-- read in vertices int vertexCount; str.read(reinterpret_cast(&vertexCount), sizeof(int)); // end of file reached if (str.eof()) return NULL; vertices = new Vector3[vertexCount]; str.read(reinterpret_cast(vertices), sizeof(Vector3) * vertexCount); normals = new Vector3[vertexCount]; str.read(reinterpret_cast(normals), sizeof(Vector3) * vertexCount); Vector3 *tangents; if (mUseNormalMapping) { tangents = new Vector3[vertexCount]; str.read(reinterpret_cast(tangents), sizeof(Vector3) * vertexCount); } else { tangents = NULL; } int texCoordCount; str.read(reinterpret_cast(&texCoordCount), sizeof(int)); if (texCoordCount) { texcoords = new Texcoord2[texCoordCount]; str.read(reinterpret_cast(texcoords), sizeof(Texcoord2) * texCoordCount); } else { texcoords = NULL; } const bool delGeometry = true; //const bool delGeometry = false; return new Geometry(vertices, normals, texcoords, vertexCount, delGeometry, NULL);//tangents); } int ResourceManager::LoadSceneEntities(igzstream &str, SceneEntityContainer &entities) { int entityCount; str.read(reinterpret_cast(&entityCount), sizeof(int)); entities.reserve(entityCount); for (int i = 0; i < entityCount; ++ i) { SceneEntity *ent = LoadSceneEntity(str); // return loaded entities entities.push_back(ent); // also store internally mSceneEntities.push_back(ent); } return entityCount; } int ResourceManager::Load(const std::string &filename, SceneEntityContainer &entities) { igzstream istr(filename.c_str()); if (!istr.is_open()) return 0; cout << "loading textures" << endl; // load the texture table int numTextures = LoadTextures(istr); cout << "loaded " << numTextures << " textures" << endl; cout << "loading shapes (geometry + materials)" << endl; // load the shapees int numShapes = LoadShapes(istr); cout << "loaded " << (int)mGeometryTable.size() << " shapes" << endl; cout << "loading scene entites" << endl; int numEntities = LoadSceneEntities(istr, entities); cout << "loaded " << numEntities << " scene entities" << endl; cout << "bin loading finished" << endl; // clean up temporary tables mTextureTable.clear(); mGeometryTable.clear(); mMaterialTable.clear(); return numEntities; } void ResourceManager::AddSceneEntity(SceneEntity *ent) { mSceneEntities.push_back(ent); } Transform3 *ResourceManager::CreateTransform(const Matrix4x4 &m) { Transform3 *t = new Transform3(m); mTrafos.push_back(t); return t; } Material *ResourceManager::CreateMaterial() { Material *mat = new Material(); mMaterials.push_back(mat); return mat; } }