в open gl на qt 4.0.0
//QGLMesh.h#ifndef QGLMESH_H#define QGLMESH_H#include "glheaders.h"#include <QMap>#include "qglvector.h"// --- List of define to allow the loading of 3ds file --- //// --- CHUNK PRIMAIRE --- //#define MAIN3DS 0x4D4D// --- MAIN CHUNKS --- //#define EDIT3DS 0x3D3D// --- EDIT3DS --- //#define EDIT_MATERIAL 0xAFFF#define EDIT_OBJECT 0x4000// --- MATERIAL DEFINITION --- //#define MATERIAL_NAME 0xA000#define MATERIAL_AMBIENT 0xA010#define MATERIAL_DIFFUSE 0xA020#define MATERIAL_SPECULAR 0xA030#define MATERIAL_TEXTURE 0xA200#define TEXTURE_NAME 0xA300#define U_COORDS 0xA356#define V_COORDS 0xA354#define U_COORDS_OFFSET 0xA358#define V_COORDS_OFFSET 0xA35A#define TEXT_ROTATION_ANGLE 0xA35C#define COLOR_RGB 0x0011// --- MESH EDITION --- //#define OBJECT 0x4000#define OBJ_TRIMESH 0x4100#define TRI_VERTEX 0x4110#define TRI_FACE 0x4120#define MATERIAL_MAP_INFO 0x4130#define MAP_COORDS 0x4140#define LOCAL_MATRIX 0x4160// --- CAMERA & LIGHT --- //#define CAMERA 0x4700#define LIGHT 0x4600#define SPOT_LIGHT 0x4610#include <QObject>#include <QString>//Basic Classes://Required for representing the loaded modelclass vertex{public: float x,y,z;};//MapCoord - for storing texture mapping coordsclass mapcoord{public: float u,v;};//The three ints for the polygon//represent the no.s(or rank) of it's 3 verticesclass polygon{public: int a,b,c; vertex normal;};class object{public: char name[20]; int numVerts,numPolys; vertex v[3000]; polygon p[3000]; mapcoord m[3000];};class QGLMesh{public: QGLMesh(); ~QGLMesh(); void Load(QString fileName); void Draw(); GLint listNum; bool smoth;private: object *obj; void CalcNormal(vertex p1,vertex p2, vertex p3, vertex *res); GLfloat vertexes[3000]; GLfloat normales[3000]; GLint smoth_normales[3000]; QMap<QGLVector,QGLVector> smooth_normales_map; int numVertex;};//QGLMesh.cpp#include "qglmesh.h"#include <math.h>#include <QFile>QGLMesh::QGLMesh(){ obj = new object(); numVertex = 0; smoth = false;}QGLMesh::~QGLMesh(){ delete obj;}void QGLMesh::Draw(){ glNormalPointer(GL_FLOAT,0,normales); if ( smoth ) glNormalPointer(GL_FLOAT,0,smoth_normales); glVertexPointer(3,GL_FLOAT,0,vertexes); glDrawArrays(GL_TRIANGLES,0,numVertex);}void QGLMesh::Load(QString fileName){ char temp; //Temporary char for reading name of object short chunkID,readsize; //Stores ID of current chunk. int chunkLength; short useless; QFile f(fileName); f.open(QIODevice::ReadOnly); int i; f.seek(0); f.read((char*)&chunkID,2); if ( chunkID != MAIN3DS ) { return; } f.read((char*)&readsize,4); while ( f.pos() < readsize ) { f.read((char*)&chunkID,2); f.read((char*)&chunkLength,4); switch (chunkID) { case MAIN3DS: //Skip these chunks break; case EDIT3DS: break; case EDIT_OBJECT: //Chunk containing name for(i=0;i<20;i++) { temp = f.read(1).at(0);// obj->name[i]=temp; if(temp == '\0')break; } break; case 0x3f80: //Skip again break; case OBJ_TRIMESH: break; case TRI_VERTEX: //Chunk with num of vertices followed by their coordinates f.read((char*)&i,2); obj->numVerts = i; for (i=0; i<obj->numVerts; i++) { f.read((char*)&obj->v[i].x,4); f.read((char*)&obj->v[i].y,4); f.read((char*)&obj->v[i].z,4); } break; case TRI_FACE: //Chunk with numPolys and the indices f.read((char*)&obj->numPolys,2); for (i=0; i<obj->numPolys; i++) { f.read((char*)&obj->p[i].a,2); f.read((char*)&obj->p[i].b,2); f.read((char*)&obj->p[i].c,2); f.read((char*)&useless,2); } break; case MAP_COORDS: //Chunk with texture coords f.read((char*)&useless,2); for (i=0; i<obj->numVerts; i++) { f.read((char*)&obj->m[i].u,4); f.read((char*)&obj->m[i].v,4); } break; default: f.seek(f.pos()+chunkLength-6); } } f.close(); for (i=0;i<obj->numPolys;i++) { CalcNormal( obj->v[ obj->p[i].a ], obj->v[ obj->p[i].b ], obj->v[ obj->p[i].c ], &obj->p[i].normal ); } int vc = 0; int nc = 0; //QGLVector ver,nor; QMap< QGLVector, QGLVector > norms; for ( int i=0; i<obj->numPolys; i++ ) { normales[nc] = obj->p[i].normal.x; nc++; normales[nc] = obj->p[i].normal.y; nc++; normales[nc] = obj->p[i].normal.z; nc++; vertexes[vc] = obj->v[ obj->p[i].a ].x; vc++; vertexes[vc] = obj->v[ obj->p[i].a ].y; vc++; vertexes[vc] = obj->v[ obj->p[i].a ].z; vc++; numVertex++; norms.insertMulti(QGLVector(obj->v[ obj->p[i].a ].x,obj->v[ obj->p[i].a ].y,obj->v[ obj->p[i].a ].z),QGLVector(obj->p[i].normal.x,obj->p[i].normal.y,obj->p[i].normal.z)); normales[nc] = obj->p[i].normal.x; nc++; normales[nc] = obj->p[i].normal.y; nc++; normales[nc] = obj->p[i].normal.z; nc++; vertexes[vc] = obj->v[ obj->p[i].b ].x; vc++; vertexes[vc] = obj->v[ obj->p[i].b ].y; vc++; vertexes[vc] = obj->v[ obj->p[i].b ].z; vc++; numVertex++; norms.insertMulti(QGLVector(obj->v[ obj->p[i].b ].x,obj->v[ obj->p[i].b ].y,obj->v[ obj->p[i].b ].z),QGLVector(obj->p[i].normal.x,obj->p[i].normal.y,obj->p[i].normal.z)); normales[nc] = obj->p[i].normal.x; nc++; normales[nc] = obj->p[i].normal.y; nc++; normales[nc] = obj->p[i].normal.z; nc++; vertexes[vc] = obj->v[ obj->p[i].c ].x; vc++; vertexes[vc] = obj->v[ obj->p[i].c ].y; vc++; vertexes[vc] = obj->v[ obj->p[i].c ].z; vc++; numVertex++; norms.insertMulti(QGLVector(obj->v[ obj->p[i].c ].x,obj->v[ obj->p[i].c ].y,obj->v[ obj->p[i].c ].z),QGLVector(obj->p[i].normal.x,obj->p[i].normal.y,obj->p[i].normal.z)); } QGLVector vert,cnorm; QList< QGLVector > vert_normales; smooth_normales_map.clear(); for ( int i=0; i<numVertex-3; i=i+3 ) { vert.x = vertexes[i]; vert.y = vertexes[i+1]; vert.z = vertexes[i+2]; vert_normales.clear(); vert_normales = norms.values(vert); int cnt = 1; cnorm.load(0,0,0); for ( int j=0; j<vert_normales.size();j++) { cnt++; cnorm.x = cnorm.x + vert_normales.at(j).x; cnorm.y = cnorm.y + vert_normales.at(j).y; cnorm.z = cnorm.z + vert_normales.at(j).z; } cnorm.x /= cnt; cnorm.y /= cnt; cnorm.z /= cnt; smooth_normales_map.insert(vert,cnorm); } for ( int i=0; i<numVertex-3; i=i+3 ) { vert.x = vertexes[i]; vert.y = vertexes[i+1]; vert.z = vertexes[i+2]; smoth_normales[i] = smooth_normales_map[ vert ].x; smoth_normales[i+1] = smooth_normales_map[ vert ].y; smoth_normales[i+2] = smooth_normales_map[ vert ].z; }}void QGLMesh::CalcNormal(vertex p1,vertex p2, vertex p3, vertex *res){ vertex v1, v2; float length, ilength; v1.x = p2.x - p1.x; v1.y = p2.y - p1.y; v1.z = p2.z - p1.z; v2.x = p3.x - p1.x; v2.y = p3.y - p1.y; v2.z = p3.z - p1.z; res->x = v1.y*v2.z - v1.z*v2.y; res->y = v1.z*v2.x - v1.x*v2.z; res->z = v1.x*v2.y - v1.y*v2.x; length = res->x*res->x + res->y*res->y + res->z*res->z; length = sqrtf(length); // извлечение корня - это очень плохо ilength = 1/length; res->x *= ilength; res->y *= ilength; res->z *= ilength;}
class vertex{public: float x,y,z;};
struct vertex {// avoid constructor vertex & xyz( float _x = 0.0f, float _y = 0.0f, float _z = 0.0f ) { x = _x; y = _y; z = _z; return *this; }// math vertex & operator += ( const vertex & t ) { x += t.x; y += t.y; z += t.z; return *this; } vertex & operator -= ( const vertex & t ) { x -= t.x; y -= t.y; z -= t.z; return *this; } vertex & operator *= ( float t ) { x *= t; y *= t; z *= t; return *this; } vertex & operator /= ( float t ) { x /= t; y /= t; z /= t; return *this; } // length & normalize float lenSq ( void ) const { return x * x + y * y + z * z; } float length ( void ) const { return sqrtf(lenSq); } vertex & normalize( void ) { return *this /= length(); }// friend operators friend vertex operator + ( const vertex & a , const vertex & b ) { vertex t; return t.xyz(a.x + b.x, a.y + b.y, a.z + b.z); } friend vertex operator - ( const vertex & a , const vertex & b ) { vertex t; return t.xyz(a.x - b.x, a.y - b.y, a.z - b.z); } friend vertex operator * ( const vertex & a, float t ) { vertex v = a; return v *= t; } friend vertex operator / ( const vertex & a, float t ) { vertex v = a; return v /= t; } // scalar product (overloaded *) friend float operator * ( const vertex & a , const vertex & b ) { return a.x * b.x + a.y * b.y + a.z * b.z; } // vector product (overloaded |) friend vertex operator | ( const vertex & a , const vertex & b ) { vertex t; return t.xyz(a.y * b.z - a.z * b.y, a.x * b.z - a.z * b.x, a.x * b.y - a.y * b.x); }};
void QGLMesh::CalcNormal(const & vertex p1, const & vertex p2, const & vertex p3, vertex *res){ *res = ((p2 - p1) | (p3 - p1)).normalize();}{