Название: Модель из 3dmax_ в Open GL
Отправлено: Witcher000 от Ноябрь 20, 2009, 01:42
Такой вот вопрос : возможно ли экспортировать модель, сделанную в 3d studio max_ (расширение .max) в open gl на qt 4.0.0 ? Если да, то существуют ли вообще плагины для 3д макса_, которые бы хоть как-то это рреализовывали?
Название: Re: Модель из 3dmax_ в Open GL
Отправлено: break от Ноябрь 20, 2009, 04:59
я пока не слышал чтобы в OpenGL оговаривался свой собственный формат файлов модели - это API для рисования примитивов и т.д. Экспортите модель из макса в 3DS или OBJ - и пользуйтесь готовыми библиотеками загрузки изображений из этих открытых форматов 3D моделей, а потом отрисовывайте операторами OpenGL
Название: Re: Модель из 3dmax_ в Open GL
Отправлено: Igors от Ноябрь 20, 2009, 11:31
Экспортите модель из макса в 3DS или OBJ
Совершенно верно, в .max файле очень много чего + он нестабилен, меняется от версии к версии. Перегоняйте в файл модели
Название: Re: Модель из 3dmax_ в Open GL
Отправлено: ieroglif от Январь 10, 2010, 16:31
класс для загрузки и отрисовки из 3ds файла. (в него умеет сохранять макс без проблем) класс глючный (не уверен в корректной работе нормалей) и выполняет только базовые функции отрисовки полигонов (без цветов и материалов). класс QGLVector - обычный, хранит в себе 3 координаты. В общем, думаю, можно оттолкнуться и использовать для написания своего кода. //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 model class vertex{ public: float x,y,z; }; //MapCoord - for storing texture mapping coords class mapcoord{ public: float u,v; };
//The three ints for the polygon //represent the no.s(or rank) of it's 3 vertices class 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; }
Название: Re: Модель из 3dmax_ в Open GL
Отправлено: Igors от Январь 10, 2010, 16:45
класс для загрузки и отрисовки из 3ds файла. (в него умеет сохранять макс без проблем) класс глючный (не уверен в корректной работе нормалей) и выполняет только базовые функции отрисовки полигонов (без цветов и материалов). класс QGLVector - обычный, хранит в себе 3 координаты. В общем, думаю, можно оттолкнуться и использовать для написания своего кода.
Вопрос: сколько строк (в %) было использовано для повторения операций над всеми 3-мя компонентами (x, y, z)? Технику-то подтянуть надо.
Название: Re: Модель из 3dmax_ в Open GL
Отправлено: ieroglif от Январь 10, 2010, 22:29
класс для загрузки и отрисовки из 3ds файла. (в него умеет сохранять макс без проблем) класс глючный (не уверен в корректной работе нормалей) и выполняет только базовые функции отрисовки полигонов (без цветов и материалов). класс QGLVector - обычный, хранит в себе 3 координаты. В общем, думаю, можно оттолкнуться и использовать для написания своего кода.
Вопрос: сколько строк (в %) было использовано для повторения операций над всеми 3-мя компонентами (x, y, z)? Технику-то подтянуть надо. Ответ: критикуешь - предлагай. Вот приходишь так на форум, выкладываешь свой кусок кода на просьбу человека, а следующий приходит и говорит что код уродский. Ну выложи свой.
Название: Re: Модель из 3dmax_ в Open GL
Отправлено: romank от Январь 10, 2010, 23:39
Редкий "великий русский программист" пройдет чтобы не плюнуть в код. Привыкайте.
Название: Re: Модель из 3dmax_ в Open GL
Отправлено: Dendy от Январь 11, 2010, 05:37
ieroglif, учитесь воспринимать критику. Дальше в теме по существу.
Название: Re: Модель из 3dmax_ в Open GL
Отправлено: Igors от Январь 11, 2010, 15:17
Дальше в теме по существу.
Согласен :) 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); } };
Теперь ф-ция CalcNormal может выглядеть напр. так void QGLMesh::CalcNormal(const & vertex p1, const & vertex p2, const & vertex p3, vertex *res) { *res = ((p2 - p1) | (p3 - p1)).normalize(); } { А про вертексные нормали можно долго говорить (после того как ieroglif перестанет обижаться :))
|