//#pragma hdrstop #include //Должен стоять до "wx/gl...h" #include #include #include #include "object3d.h" #include "texture.h" #include "mathTools.h" //#include "tools/debug.h" //--------------------------------------------------------------------------- TTriMat::TTriMat() { textureid=0; ColorAmbientRGB.r=0.2f; // 0.2 по умолчанию в OpenGL ColorAmbientRGB.g=0.2f; ColorAmbientRGB.b=0.2f; ColorAmbientRGB.a=1.0f; ColorDiffuseRGB.r=0.8f; // 0.8 по умолчанию в OpenGL ColorDiffuseRGB.g=0.8f; ColorDiffuseRGB.b=0.8f; ColorDiffuseRGB.a=1.0f; ColorSpecularRGB.r=0.0f; // 0.0 по умолчанию в OpenGL ColorSpecularRGB.g=0.0f; ColorSpecularRGB.b=0.0f; ColorSpecularRGB.a=1.0f; USCALE=1.0f; VSCALE=1.0f; } //--------------------------------------------------------------------------- void TTriMat::Release() { //прозрачность glDisable(GL_COLOR_MATERIAL); glEnable(GL_LIGHTING); glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*)&ColorAmbientRGB); glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*)&ColorDiffuseRGB); glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*)&ColorSpecularRGB); glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 100.0f); //яркость источника цвета от 0 до 128 //если текстурированна if(textureid!=0) { glBindTexture(GL_TEXTURE_2D, textureid); glEnable(GL_TEXTURE_2D); //чтобы цвет не воздействовал на текстуру если она есть glEnable(GL_COLOR_MATERIAL); glColor4f(1,1,1,ColorDiffuseRGB.a); glDisable(GL_COLOR_MATERIAL); } else glDisable(GL_TEXTURE_2D); } //--------------------------------------------------------------------------- TTriangles::TTriangles() { del=false; bSmooth=false; CountVertex=0; CountFaces=0; //countMapPoint=0; Vertices=NULL; SmoothNormals=NULL; faces=NULL; TexVertices=NULL; SmoothG=NULL; bInit=false; //разбивка по материалам countMF=0; MatFaces=NULL; //материал (после разбивки) TriMat=NULL; } //------------------------------------------------------------------------------ TTriangles::~TTriangles() { if (Vertices!=NULL) delete[] Vertices; Vertices=NULL; if (SmoothNormals!=NULL) delete[] SmoothNormals; SmoothNormals=NULL; if (faces!=NULL) delete[] faces; faces=NULL; if (TexVertices!=NULL) delete[] TexVertices; TexVertices=NULL; if (SmoothG!=NULL) delete[] SmoothG; SmoothG=NULL; if (bInit) { glDeleteBuffersARB(1,&vbov); glDeleteBuffersARB(1,&vbot); glDeleteBuffersARB(1,&vbon); glDeleteBuffersARB(1,&vbof); } for(unsigned int i=0;ifaces*sizeof(RsFacesABC), &face[0], GL_STATIC_DRAW_ARB); bInit=true; } // vbov,vbon,vbot,vbof :TGLuint; //вершины,нормали,текстура,рёбра glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState( GL_NORMAL_ARRAY ); glEnableClientState( GL_TEXTURE_COORD_ARRAY ); glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbov); glVertexPointer( 3, GL_FLOAT, 0, (char *) NULL ); glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbot); glTexCoordPointer( 2, GL_FLOAT, 0, (char *) NULL ); glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbon); glNormalPointer( GL_FLOAT, 0, (char *) NULL ); glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, vbof); glDrawElements(GL_TRIANGLES, p_object->faces*3 ,GL_UNSIGNED_SHORT, NULL); //биндим нулевой буфер glBindBufferARB(GL_ARRAY_BUFFER_ARB,0); glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB,0); glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_NORMAL_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); /**/ } //------------------------------------------------------------------------------ void TTriangles::CalcMinMaxPoint() { if(CountVertex>0) { MaxPointXYZ.x=Vertices[0].x; MaxPointXYZ.y=Vertices[0].y; MaxPointXYZ.z=Vertices[0].z; MinPointXYZ.x=Vertices[0].x; MinPointXYZ.y=Vertices[0].y; MinPointXYZ.z=Vertices[0].z; } for(unsigned int i=1;iVertices[i].x) MinPointXYZ.x=Vertices[i].x; if(MinPointXYZ.y>Vertices[i].y) MinPointXYZ.y=Vertices[i].y; if(MinPointXYZ.z>Vertices[i].z) MinPointXYZ.z=Vertices[i].z; } PointXYZCenter.x=(MinPointXYZ.x+MaxPointXYZ.x)/2.0f; PointXYZCenter.y=(MinPointXYZ.y+MaxPointXYZ.y)/2.0f; PointXYZCenter.z=(MinPointXYZ.z+MaxPointXYZ.z)/2.0f; /* //DOTO есть такие параметры как сдвиг вращения масштаб я здесь учитываю только масштаб и сдвиг MaxPointXYZ.x=(MaxPointXYZ.x*ScaleXYZ.x)+ShiftXYZ.x; MaxPointXYZ.y=(MaxPointXYZ.y*ScaleXYZ.y)+ShiftXYZ.y; MaxPointXYZ.z=(MaxPointXYZ.z*ScaleXYZ.z)+ShiftXYZ.z; MinPointXYZ.x=(MinPointXYZ.x*ScaleXYZ.x)+ShiftXYZ.x; MinPointXYZ.y=(MinPointXYZ.y*ScaleXYZ.y)+ShiftXYZ.y; MinPointXYZ.z=(MinPointXYZ.z*ScaleXYZ.z)+ShiftXYZ.z; //так как выделяем обьект по попаданию точки в нутырь куба для плоских обьектов немного расширем пространиство MaxPointXYZ.x=MaxPointXYZ.x+0.001; MaxPointXYZ.y=MaxPointXYZ.y+0.001; MaxPointXYZ.z=MaxPointXYZ.z+0.001; MinPointXYZ.x=MinPointXYZ.x-0.001; MinPointXYZ.y=MinPointXYZ.y-0.001; MinPointXYZ.z=MinPointXYZ.z-0.001;*/ } //------------------------------------------------------------------------------ //просчитать сглаживающие нормали к поверхности void TTriangles::CalcSmoothNormals() { unsigned int j; if(SmoothNormals==NULL) SmoothNormals=new RfPointXYZ[CountVertex]; //память под нормали к точке //если отключенно сглаживание то учитываеться только последний вектор к грани if(!bSmooth) { for(j=0;jTriMat!=NULL) tri->TriMat->Release(); tri->render(); } } //------------------------------------------------------------------------------ void TTrianglesList::CalcMinMaxPoint() { for(unsigned int i=0;iCalcMinMaxPoint(); if(i==0) MinPointXYZ=tri->MinPointXYZ; else { if(MinPointXYZ.x>tri->MinPointXYZ.x) MinPointXYZ.x=tri->MinPointXYZ.x; if(MinPointXYZ.y>tri->MinPointXYZ.y) MinPointXYZ.y=tri->MinPointXYZ.y; if(MinPointXYZ.z>tri->MinPointXYZ.z) MinPointXYZ.z=tri->MinPointXYZ.z; } if(i==0) MaxPointXYZ=tri->MaxPointXYZ; else { if(MaxPointXYZ.xMaxPointXYZ.x) MaxPointXYZ.x=tri->MaxPointXYZ.x; if(MaxPointXYZ.yMaxPointXYZ.y) MaxPointXYZ.y=tri->MaxPointXYZ.y; if(MaxPointXYZ.zMaxPointXYZ.z) MaxPointXYZ.z=tri->MaxPointXYZ.z; } } CenterPointXYZ.x=(MaxPointXYZ.x+MinPointXYZ.x)/2.0f; CenterPointXYZ.y=(MaxPointXYZ.y+MinPointXYZ.y)/2.0f; CenterPointXYZ.z=(MaxPointXYZ.z+MinPointXYZ.z)/2.0f; } //------------------------------------------------------------------------------ void TTrianglesList::CalcSmoothNormals() { for(unsigned int i=0;iCalcSmoothNormals(); } } //------------------------------------------------------------------------------ void TTrianglesList::cutOnSmoothGroup() { for(unsigned int i=0;icutOnSmoothGroup(); } } //------------------------------------------------------------------------------ TTriMat *TTrianglesList::FindMatOnName(char *name) { for(unsigned int i=0;iname).Lower()==wxString::FromAscii(name).Lower()) return ListMat[i]; } return NULL; } //------------------------------------------------------------------------------ //разбить обьект по списку материалов (сколько материалов столшько и объектов будет) //применять после разбения по группам сглаживания и просчёта нормалей а то на границе между разными материалами не будет сглаживания void TTrianglesList::cutOnMaterials() { for(unsigned int i=0;icountMF==1) { tri->TriMat=FindMatOnName(tri->MatFaces[0].name); }else if(tri->countMF>1) //если несколько материалов то размножаем объекты { //в списке фейсов для этого материала раздные точки //составляем список уникальных точек затем копируем их //память выделяем под самый плохой вариант unsigned short *buf=new unsigned short[tri->CountVertex*2]; //уникальные номера точек for(unsigned int j=0;jcountMF;j++) { //создаём новый объект и копируем туда точки в соответствии с материалом unsigned int cnt=0; for(unsigned int k=0;kMatFaces[j].count;k++) { if(tri->MatFaces[j].faces[k]>=tri->CountFaces) return; bool b=false; for(unsigned int q=0;qfaces[tri->MatFaces[j].faces[k]].a) { b=true; break; } if(!b){buf[cnt]=tri->faces[tri->MatFaces[j].faces[k]].a; cnt++;} b=false; for(unsigned int q=0;qfaces[tri->MatFaces[j].faces[k]].b) { b=true; break; } if(!b){buf[cnt]=tri->faces[tri->MatFaces[j].faces[k]].b; cnt++;} b=false; for(unsigned int q=0;qfaces[tri->MatFaces[j].faces[k]].c) { b=true; break; } if(!b){buf[cnt]=tri->faces[tri->MatFaces[j].faces[k]].c; cnt++;} } //выбрали список точек нужных для нового обьекта теперь копируем TTriangles* newTri=Add(); newTri->TriMat=FindMatOnName(tri->MatFaces[j].name); newTri->CountVertex=cnt; newTri->Vertices=new RfPointXYZ[newTri->CountVertex]; newTri->TexVertices=new RfPointXY[newTri->CountVertex]; newTri->SmoothNormals=new RfPointXYZ[newTri->CountVertex]; newTri->CountFaces=tri->MatFaces[j].count; newTri->faces=new RsFacesABC[newTri->CountFaces]; for(unsigned int k=0;kVertices[k]=tri->Vertices[buf[k]]; newTri->TexVertices[k]=tri->TexVertices[buf[k]]; newTri->SmoothNormals[k]=tri->SmoothNormals[buf[k]]; } for(unsigned int k=0;kMatFaces[j].count;k++) { newTri->faces[k]=tri->faces[tri->MatFaces[j].faces[k]]; //ищем номер точки bool b=true; for(unsigned int q=0;qfaces[k].a==buf[q]) {newTri->faces[k].a=q; b=false; break;} } if(b||newTri->faces[k].a>=cnt) return; b=true; for(unsigned int q=0;qfaces[k].b==buf[q]) {newTri->faces[k].b=q; b=false; break;} } if(b||newTri->faces[k].b>=cnt) return; b=true; for(unsigned int q=0;qfaces[k].c==buf[q]) {newTri->faces[k].c=q; b=false; break;} } if(b||newTri->faces[k].c>=cnt) return; } } tri->del=true; delete[] buf; } } unsigned int i=0; while(iCountVertex; if(tri->del) DelTri(tri); else i++; } //домножаем текущие координаты материала на USCALE и VSCALE текущего материала for(unsigned int i=0;iTriMat!=NULL) for(unsigned int j=0;jCountVertex;j++) { tri->TexVertices[j].x*=tri->TriMat->USCALE; tri->TexVertices[j].y*=tri->TriMat->VSCALE; } } } //------------------------------------------------------------------------------