source: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/ResourceManager.cpp @ 3050

Revision 3050, 13.1 KB checked in by mattausch, 16 years ago (diff)
Line 
1#include "ResourceManager.h"
2#include "Matrix4x4.h"
3#include "Geometry.h"
4#include "SceneEntity.h"
5#include "Material.h"
6#include "Texture.h"
7#include "gzstream.h"
8#include "Matrix4x4.h"
9#include "Vector3.h"
10#include "Transform3.h"
11#include "Shape.h"
12#include "LODInfo.h"
13#include "RenderState.h"
14#include "ShaderProgram.h"
15#include <Cg/cg.h>
16#include <Cg/cgGL.h>
17
18
19#ifdef _CRT_SET
20        #define _CRTDBG_MAP_ALLOC
21        #include <stdlib.h>
22        #include <crtdbg.h>
23
24        // redefine new operator
25        #define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__)
26        #define new DEBUG_NEW
27#endif
28
29
30using namespace std;
31
32
33namespace CHCDemoEngine
34{
35
36
37/////////
38//-- cg stuff
39
40static CGcontext sCgContext = NULL;
41
42static CGprofile sCgFragmentProfile;
43static CGprofile sCgVertexProfile;
44
45static ShaderProgram *sTreeAnimationProgramMrt;
46static ShaderProgram *sTreeAnimationProgram;
47
48
49// only instance of the resource manager
50ResourceManager *ResourceManager::sResourceManager = NULL;
51
52
53static void cgErrorCallback()
54{
55        CGerror lastError = cgGetError();
56
57        if(lastError)
58        {
59                printf("%s\n\n", cgGetErrorString(lastError));
60                printf("%s\n", cgGetLastListing(sCgContext));
61               
62                printf("Cg error, exiting...\n");
63
64                exit(0);
65        }
66}
67
68
69ResourceManager::ResourceManager()
70{
71        InitCg();
72}
73
74
75ResourceManager::~ResourceManager()
76{
77        // delete all resources.
78        CLEAR_CONTAINER(mSceneEntities);
79        CLEAR_CONTAINER(mGeometry);
80        CLEAR_CONTAINER(mMaterials);
81        CLEAR_CONTAINER(mTextures);
82        CLEAR_CONTAINER(mTrafos);
83        CLEAR_CONTAINER(mShapes);
84        CLEAR_CONTAINER(mLODs);
85        CLEAR_CONTAINER(mGPUParameters);
86        CLEAR_CONTAINER(mShaders);
87       
88        if (sCgContext)
89                cgDestroyContext(sCgContext);
90}
91
92
93SceneEntity *ResourceManager::LoadSceneEntity(igzstream &str)
94{       
95        bool hasTrafo;
96        str.read(reinterpret_cast<char *>(&hasTrafo), sizeof(bool));
97       
98        SceneEntity *sceneGeom;
99        Transform3 *trafo;
100
101        if (!hasTrafo)
102        {
103                // identity
104                trafo = new Transform3();
105        }
106        else
107        {
108                Matrix4x4 m;
109                str.read(reinterpret_cast<char *>(m.x), sizeof(Matrix4x4));
110               
111                trafo = new Transform3(m);
112        }
113
114        mTrafos.push_back(trafo);
115
116        sceneGeom = new SceneEntity(trafo);
117
118
119        ///////////////
120        //-- load LOD levels
121
122        // note: lods must be ordered from smallest distance to largest
123        int numLODs;
124        str.read(reinterpret_cast<char *>(&numLODs), sizeof(int));
125
126        for (int i = 0; i < numLODs; ++ i)
127        {
128                // the distance until the next LOD level is used
129                float dist;
130                str.read(reinterpret_cast<char *>(&dist), sizeof(float));
131
132                int numShapes;
133                str.read(reinterpret_cast<char *>(&numShapes), sizeof(int));
134
135                LODLevel *lodLevel = new LODLevel(dist);
136
137                for (int j = 0; j < numShapes; ++ j)
138                {
139                        int shapeId;
140                        str.read(reinterpret_cast<char *>(&shapeId), sizeof(int));
141
142                        Geometry *geom = mGeometryTable[shapeId];
143                        Material *mat = mMaterialTable[shapeId];
144
145                        // create shape
146                        Shape *shape = new Shape(geom, mat, sceneGeom);
147
148                        mShapes.push_back(shape);
149
150                        sceneGeom->AddShape(shape);
151                        lodLevel->AddShape(shape);
152                }
153
154                mLODs.push_back(lodLevel);
155                sceneGeom->AddLODLevel(lodLevel);
156        }
157
158        ///////////
159        //-- hack: add tree animation (should be done per material script!)
160
161        if (numLODs > 1)
162        {
163                ShapeContainer::iterator sstart, send;
164
165                // only use shader for the first two lod levels (the non-billboards)
166                for (int i = 0; i < min(numLODs, 2); ++ i)
167                //for (int i = 0; i < numLODs; ++ i)
168                {
169                        sceneGeom->GetLODLevel(i, sstart, send);
170
171                        for (ShapeContainer::iterator it = sstart; it != send; ++ it)
172                        {
173                                Shape *shape = *it;
174
175                                Material *mat = shape->GetMaterial();
176
177                                // add the vertex animation program
178                                for (int i = 0; i < 3; ++ i)
179                                {
180                                        Technique *tech = mat->GetTechnique(i);
181
182                                        GPUProgramParameters *vtxParams = tech->GetVertexProgramParameters();
183
184                                        if (i == 0)
185                                        {
186                                                tech->SetVertexProgram(sTreeAnimationProgram);
187                                                vtxParams->SetLightDirParam(5);
188                                        }
189                                        else
190                                        {
191                                                tech->SetVertexProgram(sTreeAnimationProgramMrt);
192                                        }
193
194                                        /// use a timer to simulate the moving of the tree in the wind
195                                        vtxParams->SetTimerParam(0);
196                                        // wind direction
197                                        static Vector3 windDir = Normalize(Vector3(0.8f, 0.2f, 0.0f));
198                                        vtxParams->SetValue3f(1, windDir.x, windDir.y, windDir.z);
199                                        // amplitude
200                                        vtxParams->SetValue1f(2, 0.3f);
201
202                                        AxisAlignedBox3 box = sceneGeom->GetBoundingBox();
203                                        vtxParams->SetValue2f(3, box.Min().z, box.Max().z);
204                                        // frequency
205                                        vtxParams->SetValue1f(4, 0.1f);
206                                }
207                        }
208                }
209        }
210
211        return sceneGeom;
212}
213
214
215void ResourceManager::LoadTextures(igzstream &str)
216{
217        int numTextures;
218        str.read(reinterpret_cast<char *>(&numTextures), sizeof(int));
219       
220        for (int i = 0; i < numTextures; ++ i)
221        {
222                // load texture name
223                int texnameSize;
224                str.read(reinterpret_cast<char *>(&texnameSize), sizeof(int));
225
226                char *texname = new char[texnameSize];
227                str.read(texname, sizeof(char) * texnameSize);
228
229                Texture *tex = new Texture(model_path + texname);
230
231                int boundS, boundT;
232
233                str.read(reinterpret_cast<char *>(&boundS), sizeof(int));
234                str.read(reinterpret_cast<char *>(&boundT), sizeof(int));
235
236                tex->SetBoundaryModeS(boundS);
237                tex->SetBoundaryModeT(boundT);
238
239                tex->Create();
240
241                mTextureTable[i] = tex;
242                mTextures.push_back(tex);
243
244                delete [] texname;
245        }
246
247        cout << "loaded " << (int)mTextureTable.size() << " textures" << endl;
248}
249
250
251void ResourceManager::LoadShapes(igzstream &str)
252{
253        int numShapes;
254        str.read(reinterpret_cast<char *>(&numShapes), sizeof(int));
255
256        for (int i = 0; i < numShapes; ++ i)
257        {
258                Geometry *geom = LoadGeometry(str);
259                Material *mat = LoadMaterial(str);
260
261                mGeometryTable[i] = geom;
262                mMaterialTable[i] = mat;               
263
264                mGeometry.push_back(geom);
265                mMaterials.push_back(mat);
266        }
267
268        cout << "loaded " << (int)mGeometryTable.size() << " shapes" << endl;
269}
270
271
272Material *ResourceManager::LoadMaterial(igzstream &str)
273{
274        // default material
275        Material *mat = new Material();
276       
277        // set default fragment + vertex programs
278        Technique *tech = mat->GetDefaultTechnique();
279
280        // texture
281        int texId;
282        str.read(reinterpret_cast<char *>(&texId), sizeof(int));
283
284        if (texId >= 0)
285                tech->SetTexture(mTextureTable[texId]);
286       
287        str.read(reinterpret_cast<char *>(&tech->mAlphaTestEnabled), sizeof(bool));
288        str.read(reinterpret_cast<char *>(&tech->mCullFaceEnabled), sizeof(bool));
289
290        // gl material
291        bool hasGlMaterial;
292        str.read(reinterpret_cast<char *>(&hasGlMaterial), sizeof(bool));
293
294        if (hasGlMaterial)
295        {
296                // only write rgb part of the material
297                str.read(reinterpret_cast<char *>(&tech->mAmbientColor), sizeof(Vector3));
298                str.read(reinterpret_cast<char *>(&tech->mDiffuseColor), sizeof(Vector3));
299                str.read(reinterpret_cast<char *>(&tech->mEmmisiveColor), sizeof(Vector3));
300                str.read(reinterpret_cast<char *>(&tech->mSpecularColor), sizeof(Vector3));
301        }
302
303
304        ///////////////
305        //-- add technique for deferred shading
306
307        Technique *deferred = new Technique(*tech);
308
309        if (deferred->GetTexture())
310        {
311                deferred->SetFragmentProgram(mMrtDefaultFragmentTexProgram);
312                deferred->GetFragmentProgramParameters()->SetViewMatrixParam(0);
313                deferred->GetFragmentProgramParameters()->SetTexture(1, tech->GetTexture()->GetId());
314        }       
315        else
316        {
317                deferred->SetFragmentProgram(mMrtDefaultFragmentProgram);
318                deferred->GetFragmentProgramParameters()->SetViewMatrixParam(0);
319        }
320
321        deferred->SetVertexProgram(mMrtDefaultVertexProgram);
322        mat->AddTechnique(deferred);
323       
324
325        ///////////
326        //-- add depth pass
327
328        Technique *depthPass = new Technique(*tech);
329        depthPass->SetColorWriteEnabled(false);
330        depthPass->SetLightingEnabled(false);
331        mat->AddTechnique(depthPass);
332
333        return mat;
334}
335
336
337Geometry *ResourceManager::LoadGeometry(igzstream &str)
338{
339        Vector3 *vertices;
340        Vector3 *normals;
341        Texcoord2 *texcoords;
342
343
344        //////////////
345        //-- read in vertices
346
347        int vertexCount;
348        str.read(reinterpret_cast<char *>(&vertexCount), sizeof(int));
349       
350        // end of file reached
351        if (str.eof()) return NULL;
352
353        //cout << "vertexcount: " << vertexCount << endl;
354
355        vertices = new Vector3[vertexCount];
356    str.read(reinterpret_cast<char *>(vertices), sizeof(Vector3) * vertexCount);
357       
358        normals = new Vector3[vertexCount];
359        str.read(reinterpret_cast<char *>(normals), sizeof(Vector3) * vertexCount);
360
361        int texCoordCount;
362        str.read(reinterpret_cast<char *>(&texCoordCount), sizeof(int));
363
364        if (texCoordCount)
365        {
366                texcoords = new Texcoord2[texCoordCount];
367                str.read(reinterpret_cast<char *>(texcoords), sizeof(Texcoord2) * texCoordCount);
368        }
369        else
370        {
371                texcoords = NULL;
372        }
373
374        return new Geometry(vertices, normals, texcoords, vertexCount, true);
375        //return new Geometry(vertices, normals, texcoords, vertexCount, false);
376}
377
378
379void ResourceManager::LoadSceneEntities(igzstream &str,
380                                                                                SceneEntityContainer &entities)
381{
382        int entityCount;
383        str.read(reinterpret_cast<char *>(&entityCount), sizeof(int));
384
385        entities.reserve(entityCount);
386
387        for (int i = 0; i < entityCount; ++ i)
388        {
389                SceneEntity *ent = LoadSceneEntity(str);
390
391                // return loaded entities
392                entities.push_back(ent);
393                // also store internally
394                mSceneEntities.push_back(ent);
395        }
396
397        cout << "loaded " << entityCount << " scene entities" << endl;
398}
399
400
401bool ResourceManager::Load(const std::string &filename,
402                                                   SceneEntityContainer &entities)
403{
404        igzstream istr(filename.c_str());
405       
406        if (!istr.is_open())
407                return false;
408
409        cout << "loading textures" << endl;
410       
411        // load the texture table
412        LoadTextures(istr);
413
414        cout << "loading shapes (geometry + materials)" << endl;
415
416        // load the shapees
417        LoadShapes(istr);
418
419        cout << "loading scene entites" << endl;
420        LoadSceneEntities(istr, entities);
421       
422        cout << "bin loading finished" << endl;
423
424        // clean up
425        mTextureTable.clear();
426        mGeometryTable.clear();
427        mMaterialTable.clear();
428
429        return true;
430}
431
432
433
434ShaderProgram *ResourceManager::CreateFragmentProgram(const std::string &filename,
435                                                                                                          const std::string &funcName)
436{
437        const string fullName = "src/shaders/" + filename + ".cg";
438
439        ShaderProgram *p = new ShaderProgram(sCgContext, fullName, sCgFragmentProfile, funcName);
440
441        mShaders.push_back(p);
442
443        if (!p->IsValid())
444        {
445                DEL_PTR(p);
446                cerr << "Program " << funcName << " in " << fullName << " failed to load" << endl;
447        }
448       
449        cout << "Program " << funcName << " in " << fullName << " loaded" << endl;
450
451        return p;
452}
453
454
455ShaderProgram *ResourceManager::CreateVertexProgram(const std::string &filename, const std::string &funcName)
456{
457        const string fullName = "src/shaders/" + filename + ".cg";
458       
459        ShaderProgram *p = new ShaderProgram(sCgContext, fullName, sCgVertexProfile, funcName);
460        mShaders.push_back(p);
461
462        if (!p->IsValid())
463        {
464                DEL_PTR(p);
465                cerr << "Program " << funcName << " in " << fullName << " failed to load" << endl;
466        }
467       
468        cout << "Program " << funcName << " in " << fullName << " loaded" << endl;
469
470        return p;
471}
472
473
474void ResourceManager::InitCg()
475{
476        // setup cg
477        cgSetErrorCallback(cgErrorCallback);
478        // create context.
479        sCgContext = cgCreateContext();
480        // get the optimal fragment profile
481        sCgFragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);
482        cgGLSetOptimalOptions(sCgFragmentProfile);
483        // get the optimal vertex profile
484        sCgVertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);
485        cgGLSetOptimalOptions(sCgVertexProfile);
486
487        // set textures to auto load
488        cgGLSetManageTextureParameters(sCgContext, false);
489
490        mMrtDefaultVertexProgram = CreateVertexProgram("mrt", "vtx");
491        mMrtDefaultFragmentProgram = CreateFragmentProgram("mrt", "frag");
492        mMrtDefaultFragmentTexProgram = CreateFragmentProgram("mrt", "fragtex");
493
494        // provide the current view matrix
495        mMrtDefaultFragmentProgram->AddParameter("viewMatrix", 0);
496        mMrtDefaultFragmentTexProgram->AddParameter("viewMatrix", 0);
497        // add a texture parameter
498        mMrtDefaultFragmentTexProgram->AddParameter("tex", 1);
499
500
501        ////////////
502        //-- hack: apply hardcoded tree animation (should be provided with a material script!)
503
504        sTreeAnimationProgram = CreateVertexProgram("treeanimation", "animateVtx");
505        sTreeAnimationProgramMrt = CreateVertexProgram("treeanimation", "animateVtxMrt");
506
507        sTreeAnimationProgram->AddParameter("timer", 0);
508        sTreeAnimationProgram->AddParameter("windDir", 1);
509        sTreeAnimationProgram->AddParameter("windStrength", 2);
510        sTreeAnimationProgram->AddParameter("minMaxPos", 3);
511        sTreeAnimationProgram->AddParameter("frequency", 4);
512        sTreeAnimationProgram->AddParameter("lightDir", 5);
513
514        sTreeAnimationProgramMrt->AddParameter("timer", 0);
515        sTreeAnimationProgramMrt->AddParameter("windDir", 1);
516        sTreeAnimationProgramMrt->AddParameter("windStrength", 2);
517        sTreeAnimationProgramMrt->AddParameter("minMaxPos", 3);
518        sTreeAnimationProgramMrt->AddParameter("frequency", 4);
519
520        cout << "cg initialization successful" << endl;
521}
522
523
524void ResourceManager::EnableFragmentProfile()
525{
526        cgGLEnableProfile(sCgFragmentProfile);
527}
528
529
530void ResourceManager::EnableVertexProfile()
531{
532        cgGLEnableProfile(sCgVertexProfile);
533}
534
535
536void ResourceManager::DisableFragmentProfile()
537{
538        cgGLDisableProfile(sCgFragmentProfile);
539}
540
541
542void ResourceManager::DisableVertexProfile()
543{
544        cgGLDisableProfile(sCgVertexProfile);
545       
546}
547
548
549}
550
Note: See TracBrowser for help on using the repository browser.