#include "ResourceManager.h" #include "Matrix4x4.h" #include "Geometry.h" #include "SceneEntity.h" #include "Material.h" #include "Texture.h" #include "gzstream.h" #include "Matrix4x4.h" #include "Vector3.h" #include "Transform3.h" #include "Shape.h" #include "LODInfo.h" #include "RenderState.h" #include "ShaderProgram.h" #include #include #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 { ///////// //-- cg stuff static CGcontext sCgContext = NULL; static CGprofile sCgFragmentProfile; static CGprofile sCgVertexProfile; static ShaderProgram *sTreeAnimation; // only instance of the resource manager ResourceManager *ResourceManager::sResourceManager = NULL; static void cgErrorCallback() { CGerror lastError = cgGetError(); if(lastError) { printf("%s\n\n", cgGetErrorString(lastError)); printf("%s\n", cgGetLastListing(sCgContext)); printf("Cg error, exiting...\n"); exit(0); } } ResourceManager::ResourceManager() { InitCg(); } ResourceManager::~ResourceManager() { // delete all resources. CLEAR_CONTAINER(mSceneEntities); CLEAR_CONTAINER(mGeometry); CLEAR_CONTAINER(mMaterials); CLEAR_CONTAINER(mTextures); CLEAR_CONTAINER(mTrafos); CLEAR_CONTAINER(mShapes); CLEAR_CONTAINER(mLODs); CLEAR_CONTAINER(mGPUParameters); CLEAR_CONTAINER(mShaders); if (sCgContext) cgDestroyContext(sCgContext); } SceneEntity *ResourceManager::LoadSceneEntity(igzstream &str) { bool hasTrafo; str.read(reinterpret_cast(&hasTrafo), sizeof(bool)); SceneEntity *sceneGeom; Transform3 *trafo; if (!hasTrafo) { // identity trafo = new Transform3(); } 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) { float dist; str.read(reinterpret_cast(&dist), sizeof(float)); int numShapes; str.read(reinterpret_cast(&numShapes), sizeof(int)); LODLevel *lodLevel = new 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, sceneGeom); mShapes.push_back(shape); sceneGeom->AddShape(shape); lodLevel->AddShape(shape); } mLODs.push_back(lodLevel); sceneGeom->AddLODLevel(lodLevel); } /////////// //-- hack: tree animation if (numLODs > 1) { for (int i = 0; i < min(numLODs, 2); ++ i) { ShapeContainer::iterator sstart, send; 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 < 2; ++ i) { Technique *tech = mat->GetTechnique(i); tech->SetVertexProgram(sTreeAnimation); GPUProgramParameters *vtxParams = tech->GetVertexProgramParameters(); 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; } void 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; } cout << "loaded " << (int)mTextureTable.size() << " textures" << endl; } void 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); } cout << "loaded " << (int)mGeometryTable.size() << " shapes" << endl; } 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)); } /////////////// //-- add technique for deferred shading Technique *deferred = new Technique(*tech); if (deferred->GetTexture()) { deferred->SetFragmentProgram(mMrtDefaultFragmentTexProgram); deferred->GetFragmentProgramParameters()->SetViewMatrixParam(0); deferred->GetFragmentProgramParameters()->SetTexture(1, tech->GetTexture()->GetId()); } else { deferred->SetFragmentProgram(mMrtDefaultFragmentProgram); deferred->GetFragmentProgramParameters()->SetViewMatrixParam(0); } deferred->SetVertexProgram(mMrtDefaultVertexProgram); mat->AddTechnique(deferred); 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; //cout << "vertexcount: " << vertexCount << endl; vertices = new Vector3[vertexCount]; str.read(reinterpret_cast(vertices), sizeof(Vector3) * vertexCount); normals = new Vector3[vertexCount]; str.read(reinterpret_cast(normals), sizeof(Vector3) * vertexCount); 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; } return new Geometry(vertices, normals, texcoords, vertexCount, true); //return new Geometry(vertices, normals, texcoords, vertexCount, false); } void 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); } cout << "loaded " << entityCount << " scene entities" << endl; } bool ResourceManager::Load(const std::string &filename, SceneEntityContainer &entities) { igzstream istr(filename.c_str()); if (!istr.is_open()) return false; cout << "loading textures" << endl; // load the texture table LoadTextures(istr); cout << "loading shapes (geometry + materials)" << endl; // load the shapees LoadShapes(istr); cout << "loading scene entites" << endl; LoadSceneEntities(istr, entities); cout << "bin loading finished" << endl; // clean up mTextureTable.clear(); mGeometryTable.clear(); mMaterialTable.clear(); return true; } ShaderProgram *ResourceManager::CreateFragmentProgram(const std::string &filename, const std::string &funcName) { const string fullName = "src/shaders/" + filename + ".cg"; ShaderProgram *p = new ShaderProgram(sCgContext, fullName, sCgFragmentProfile, funcName); mShaders.push_back(p); if (!p->IsValid()) { DEL_PTR(p); cerr << "Program " << funcName << " in " << fullName << " failed to load" << endl; } cout << "Program " << funcName << " in " << fullName << " loaded" << endl; return p; } ShaderProgram *ResourceManager::CreateVertexProgram(const std::string &filename, const std::string &funcName) { const string fullName = "src/shaders/" + filename + ".cg"; ShaderProgram *p = new ShaderProgram(sCgContext, fullName, sCgVertexProfile, funcName); mShaders.push_back(p); if (!p->IsValid()) { DEL_PTR(p); cerr << "Program " << funcName << " in " << fullName << " failed to load" << endl; } cout << "Program " << funcName << " in " << fullName << " loaded" << endl; return p; } void ResourceManager::InitCg() { // setup cg cgSetErrorCallback(cgErrorCallback); // create context. sCgContext = cgCreateContext(); // get the optimal fragment profile sCgFragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT); cgGLSetOptimalOptions(sCgFragmentProfile); // get the optimal vertex profile sCgVertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX); cgGLSetOptimalOptions(sCgVertexProfile); // set textures to auto load cgGLSetManageTextureParameters(sCgContext, false); mMrtDefaultVertexProgram = CreateVertexProgram("mrt", "vtx"); mMrtDefaultFragmentProgram = CreateFragmentProgram("mrt", "frag"); mMrtDefaultFragmentTexProgram = CreateFragmentProgram("mrt", "fragtex"); // provide the current view matrix mMrtDefaultFragmentProgram->AddParameter("viewMatrix", 0); mMrtDefaultFragmentTexProgram->AddParameter("viewMatrix", 0); // add a texture parameter mMrtDefaultFragmentTexProgram->AddParameter("tex", 1); sTreeAnimation = CreateVertexProgram("treeanimation", "animateVtxMrt"); sTreeAnimation->AddParameter("timer", 0); sTreeAnimation->AddParameter("windDir", 1); sTreeAnimation->AddParameter("windStrength", 2); sTreeAnimation->AddParameter("minMaxPos", 3); sTreeAnimation->AddParameter("frequency", 4); cout << "cg initialization successful" << endl; } void ResourceManager::EnableFragmentProfile() { cgGLEnableProfile(sCgFragmentProfile); } void ResourceManager::EnableVertexProfile() { cgGLEnableProfile(sCgVertexProfile); } void ResourceManager::DisableFragmentProfile() { cgGLDisableProfile(sCgFragmentProfile); } void ResourceManager::DisableVertexProfile() { cgGLDisableProfile(sCgVertexProfile); } }