/** ****************************************************************************** @file /gui/model/DrawModel.cpp @brief Vykreslovani modelu Makro DRAW_DEBUG aktivuje vykreslovani jako smerovych gizm. Makro SIMPLE_SHADOWS aktivuje modifikaci stencil bufferu pro jednoduche stiny. Makro SHADOWMAPPING aktivuje vykreslovani pro pouziti shadowmappingu. @author Vajicek @version 0.1 ******************************************************************************/ #ifdef SHADOWMAPPING #include "external/extgl.h" #endif #include #include #include "gui/model/DrawModel.h" #include "gui/common/init_env.h" namespace gui{ void Sphere(){ static GLUquadricObj* sp = gluNewQuadric(); gluSphere( sp, 3, 20, 20); } /*****************************************************************************/ void SetMaterial_v0(){ float ambient[] = {0.1f,0.1f,0.1f,1}; float diffuse[] = {0.1f,0.1f,0.1f,1}; float specular[] = {0.1f,0.1f,0.1f,1}; glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ambient); glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse); glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR,specular); } int SetMaterial_v2(TModel* m, int material, int submaterial, int flags){ int retval = 0; PMaterial mat = m->matr[material]; if( (submaterial != NOMATERIAL) && (submaterial < mat->submat_c) ){ mat = mat->submat + submaterial; } glMaterialfv(GL_FRONT, GL_AMBIENT, mat->ambient.p); glMaterialfv(GL_FRONT, GL_DIFFUSE, mat->diffuse.p); glMaterialfv(GL_FRONT, GL_SPECULAR,mat->specular.p); glMaterialf(GL_FRONT, GL_SHININESS,mat->shininess); if(flags & DRAW_MATERIAL_TEXTURE) { for(int i = 0; i < mat->mmap_c; i++){ if(mat->mmap[i].bitmap_file){ //najdi texturu v texture_bufferu + nabinduje ji glBindTexture(GL_TEXTURE_2D, mat->mmap[i].id); retval = retval | DRAW_MATERIAL_TEXTURE; break; } }//for map } return retval; } int SetMaterial_v1(TModel* m, int i, int flags){ int retval = 0; PMaterial mat = m->matr[i]; glMaterialfv(GL_FRONT, GL_AMBIENT, mat->ambient.p); glMaterialfv(GL_FRONT, GL_DIFFUSE, mat->diffuse.p); glMaterialfv(GL_FRONT, GL_SPECULAR,mat->specular.p); glMaterialf(GL_FRONT, GL_SHININESS,mat->shininess); if(flags & DRAW_MATERIAL_TEXTURE) { for(int i = 0; i < mat->mmap_c; i++){ if(mat->mmap[i].bitmap_file){ //najdi texturu v texture_bufferu + nabinduje ji glBindTexture(GL_TEXTURE_2D, mat->mmap[i].id); retval = retval | DRAW_MATERIAL_TEXTURE; break; } }//for map } return retval; } /*****************************************************************************/ void DrawModel_v1(TModel* m, int flags){ std::vector::iterator it; P3DObject obj; PMesh mesh; PVertex vert; int vc; int mat; for( it = m->data.begin(); it != m->data.end(); it++) { obj = *it; for(int i = 0; i < obj->mesh_c; i++) { mesh = &(obj->mesh[i]); //pointry a indexy na geometrii vc = obj->poly[mesh->first].first; vert = obj->vert + vc; vc = obj->poly[mesh->last].last - vc + 1; glVertexPointer(3,GL_FLOAT,sizeof(TVertex), vert ); glNormalPointer(GL_FLOAT,sizeof(TVertex),&(vert->normal)); glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); //material if( (mesh->mat != NOMATERIAL) && !(flags & DRAW_NOMATERIAL) ){ glDisable(GL_COLOR_MATERIAL); glDisableClientState(GL_COLOR_ARRAY); mat = SetMaterial_v1(m, mesh->mat, DRAW_MATERIAL_TEXTURE); // if( !(flags & DRAW_NOMATERIAL) && (mat & DRAW_MATERIAL_TEXTURE) ){ glTexCoordPointer(2,GL_FLOAT,sizeof(TVertex),&(vert->texture)); glEnableClientState(GL_TEXTURE_COORD_ARRAY); }else{ glDisableClientState(GL_TEXTURE_COORD_ARRAY); } } //barva else{ glEnable(GL_COLOR_MATERIAL); glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE); // glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(TVertex), &(vert->color)); glEnableClientState(GL_COLOR_ARRAY); // glDisableClientState(GL_TEXTURE_COORD_ARRAY); } //lets draw if(flags & DRAW_WIRE) glDrawArrays(GL_LINE_LOOP,0,vc); else glDrawArrays(GL_TRIANGLES,0,vc); }//for obj->mesh }//for m->data } void DrawModel_v2(TModel* m, int flags){ std::vector::iterator it; P3DObject obj; PMesh mesh; PPolygon pol, lastpol; PVertex vert, last; int mat; //objekty for( it = m->data.begin(); it != m->data.end(); it++) { obj = *it; //meshe for(int i = 0; i < obj->mesh_c; i++) { mesh = &(obj->mesh[i]); //volba materialu if( (mesh->mat != NOMATERIAL) && !(flags & DRAW_NOMATERIAL) ){ mat = 1; glDisable(GL_COLOR_MATERIAL); SetMaterial_v2(m, mesh->mat, NOMATERIAL,DRAW_MATERIAL_TEXTURE); } //nastaveni barvy else { mat = 0; glEnable(GL_COLOR_MATERIAL); glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE); } //polygony pol = obj->poly + mesh->first; lastpol = obj->poly + mesh->last; //rezim kreslani if(flags & DRAW_WIRE) glBegin(GL_LINE_LOOP); else glBegin(GL_TRIANGLES); //vykresli while(pol <= lastpol){ if( mat && !(flags & DRAW_NOSUBMATERIAL) && (pol->submat != NOMATERIAL)){ SetMaterial_v2(m, mesh->mat, pol->submat,DRAW_MATERIAL_TEXTURE); } //vrcholy vert = obj->vert + pol->first; last = obj->vert + pol->last; while( vert <= last ){ glNormal3fv( vert->normal.p); glColor3bv ( (GLbyte*)&vert->color); glTexCoord2fv( vert->texture.p); glVertex3fv( vert->position.p); vert++; } pol ++; } glEnd(); /**/ }//for obj->mesh }//for m->data } void DrawMeshNode(TModel* m, TMeshNode* mn, int flags){ P3DObject obj = mn->obj; PMesh mesh = obj->mesh + mn->mesh; PVertex vert; int vc; int mat; //transformace do lokalnich souradnic glPushMatrix(); #ifdef DRAW_DEBUG DrawAxis(); #endif //animacni transformace if( flags & RIGID_TRANSFORM ){ glTranslatef(mn->translate.x, mn->translate.y, mn->translate.z); glRotatef(mn->rotate.ang, mn->rotate.ax.x, mn->rotate.ax.y, mn->rotate.ax.z); glScalef(mn->scale.x, mn->scale.y, mn->scale.z); } #ifdef DRAW_DEBUG DrawAxis(); #endif if(!ISHELPER(mn) || (flags & DRAW_HELPER) ) { //pointry a indexy na geometrii vc = obj->poly[mesh->first].first; vert = obj->vert + vc; vc = obj->poly[mesh->last].last - vc + 1; glVertexPointer(3,GL_FLOAT,sizeof(TVertex), vert ); glNormalPointer(GL_FLOAT,sizeof(TVertex),&(vert->normal)); glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); //material a textura if( (mesh->mat != NOMATERIAL) && (flags & DRAW_MATERIAL_TEXTURE) ){ glDisable(GL_COLOR_MATERIAL); glDisableClientState(GL_COLOR_ARRAY); mat = SetMaterial_v1(m, mesh->mat, DRAW_MATERIAL_TEXTURE); //textura if( !(flags & DRAW_NOMATERIAL) && (mat & DRAW_MATERIAL_TEXTURE) ){ glTexCoordPointer(2,GL_FLOAT,sizeof(TVertex),&(vert->texture)); glEnableClientState(GL_TEXTURE_COORD_ARRAY); }else{ glDisableClientState(GL_TEXTURE_COORD_ARRAY); } } //barva else if( (flags & DRAW_COLOR_MATERIAL) ) { glEnable(GL_COLOR_MATERIAL); glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE); // glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(TVertex), &(vert->color)); glEnableClientState(GL_COLOR_ARRAY); // glDisableClientState(GL_TEXTURE_COORD_ARRAY); } //draw if(flags & DRAW_WIRE) glDrawArrays(GL_LINE_LOOP,0,vc); else glDrawArrays(GL_TRIANGLES,0,vc); //disable material if( (mesh->mat != NOMATERIAL) && (flags & DRAW_MATERIAL_TEXTURE) ){ glBindTexture(GL_TEXTURE_2D, 0); } } //draw childs for(int j = 0; j < mn -> childs_c; j++) DrawMeshNode(m, mn -> childs[j], flags); //transform back - transforace rodice se projevi i na potomcich glPopMatrix(); } void DrawModel_v3(TModel* m, int flags){ TMeshNode* mn; for(int i = 0; i < m->hierarchy_c; i++){ // mn = m->hierarchy[i]; //draw node DrawMeshNode(m, mn, flags); } } void DrawModel_v3(TModelInstance* inst, int flags) { TMeshNode* mn; #ifdef SIMPLE_SHADOWS //prijemce stinu if(flags&DRAW_SHADOWRECEIVER){ //zapis jednicku glStencilFunc(GL_ALWAYS, 1, 0xFFFFFFFF); glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); } else{ glStencilFunc(GL_ALWAYS, 0, 0xFFFFFFFF); glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); } #endif for(int i = 0; i < inst->hierarchy_c; i++){ // mn = inst->hierarchy[i]; //draw node DrawMeshNode(inst->model_class, mn, flags); } } void DrawModel_v4(TModelInstance* inst, int flags) { //zasobnik TMeshNode* mns[30]; TMeshNode* mn = NULL; int mnc = 0; P3DObject obj = NULL; PMesh mesh = NULL; PVertex vert = NULL; PMaterial mat = NULL; int vc; #ifdef SIMPLE_SHADOWS //prijemce stinu if(flags&DRAW_SHADOWRECEIVER){ //zapis jednicku glStencilFunc(GL_ALWAYS, 1, 0xFFFFFFFF); glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); } else{ glStencilFunc(GL_ALWAYS, 0, 0xFFFFFFFF); glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); } #endif //koreny v obracnem poradi(vykreslovani jako na zasobniku); for(int i = 0; i < inst->hierarchy_c; i++){ mns[mnc++] = inst->hierarchy[i]; while(mnc){ //pop mn = mns[--mnc]; //pop matrix if(!mn){ glPopMatrix(); continue; } obj = mn->obj; mesh = obj->mesh + mn->mesh; //push matrix glPushMatrix(); //animacni transformace if( flags & RIGID_TRANSFORM ){ glTranslatef(mn->translate.x, mn->translate.y, mn->translate.z); glRotatef(mn->rotate.ang, mn->rotate.ax.x, mn->rotate.ax.y, mn->rotate.ax.z); glScalef(mn->scale.x, mn->scale.y, mn->scale.z); } if(!ISHELPER(mn) || (flags & DRAW_HELPER) ) { //pointry a indexy na geometrii vc = obj->poly[mesh->first].first; vert = obj->vert + vc; vc = obj->poly[mesh->last].last - vc + 1; glVertexPointer(3,GL_FLOAT,sizeof(TVertex), vert ); glNormalPointer(GL_FLOAT,sizeof(TVertex),&(vert->normal)); glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); //--- #ifndef SHADOWMAPPING //material a textura if( (mesh->mat != NOMATERIAL) && (flags & DRAW_MATERIAL_TEXTURE) ) { glDisable(GL_COLOR_MATERIAL); glDisableClientState(GL_COLOR_ARRAY); //=== PMaterial mat = inst->model_class->matr[mesh->mat]; glMaterialfv(GL_FRONT, GL_AMBIENT, mat->ambient.p); glMaterialfv(GL_FRONT, GL_DIFFUSE, mat->diffuse.p); glMaterialfv(GL_FRONT, GL_SPECULAR,mat->specular.p); glMaterialf(GL_FRONT, GL_SHININESS,mat->shininess); // if (mat->mmap!=NULL) // may not be necessary if(mat->mmap[0].bitmap_file) glBindTexture(GL_TEXTURE_2D, mat->mmap[0].id); //textura glTexCoordPointer(2,GL_FLOAT,sizeof(TVertex),&(vert->texture)); glEnableClientState(GL_TEXTURE_COORD_ARRAY); //=== glDrawArrays(GL_TRIANGLES,0,vc); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glBindTexture(GL_TEXTURE_2D, 0); } //barva else if( (flags & DRAW_COLOR_MATERIAL) ) { glEnable(GL_COLOR_MATERIAL); glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE); // glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(TVertex), &(vert->color)); glEnableClientState(GL_COLOR_ARRAY); glDrawArrays(GL_TRIANGLES,0,vc); glDisableClientState(GL_COLOR_ARRAY); } else #endif { glColor4f(1,1,1,1); glDrawArrays(GL_TRIANGLES,0,vc); } //--- glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_NORMAL_ARRAY); } //pop matrix mns[mnc++] = NULL; //push draw for(int j = mn->childs_c-1; j >= 0 ; j--) { mns[mnc++] = mn -> childs[j]; } }//while }//for } }//namespace /*****************************************************************************/