home *** CD-ROM | disk | FTP | other *** search
- /*
- * 3DS API
- *
- * Includes the support needed to render 3D Studio r4 mesh files with
- * OpenGL. Depends on the ObjGL2 class hierarchy.
- */
-
- #include <io.h>
- #include <stdio.h>
- #include <malloc.h>
- #include <fcntl.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <unistd.h>
- #include <string.h>
-
- #include "api3ds.h"
- #include "macros.h"
- #include <zlib.h>
-
- #define API3DS_TEXT_OUT 1
-
- bool Texture3DS::voodoo = false;
- bool Texture3DS::lowtextures = false;
- char* Loader3DS::buffer = 0;
-
- const char* getlastext(const char* s) {
- const char* lastext = 0;
- char c;
- while(c=*s, c) {
- if(c=='.')
- lastext = s+1;
- s++;
- }
- return lastext;
- }
-
- template <class __type> inline Vector3<__type>
- Normalize (const Vector3<__type>& V) {
- __type len = __type(1.0/sqrt(V.x*V.x + V.y*V.y + V.z*V.z));
- return Vector3<__type> (V.x*len, V.y*len, V.z*len);
- }
-
- template <class __type> inline Vector3<__type>
- CrossProduct (const Vector3<__type>& u, const Vector3<__type>& v) {
- return Vector3<__type> (u.y*v.z - u.z*v.y,
- v.x*u.z - u.x*v.z,
- u.x*v.y - u.y*v.x);
- }
-
- template <class __type> inline __type
- VectorLength(const Vector3<__type>& u) {
- return (__type)sqrt(u.x*u.x + u.y*u.y + u.z*u.z);
- }
-
- template <class __type> inline const __type&
- Minimum(const __type& a, const __type& b) {
- return (a<b ? a : b);
- }
-
- void Texture3DS::GL ()
- {
- if(Name()==0) {
- glBindTexture(GL_TEXTURE_2D, 0);
- return;
- }
- if(texture==0)
- glGenTextures(1, &texture);
-
- glBindTexture(GL_TEXTURE_2D, texture);
-
- if(altered) {
- altered = false;
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_s);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_t);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter);
- glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, border_color);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_PRIORITY, priority);
- }
- glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, env_mode);
- glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, env_color);
-
- if(!transferred) {
- Image img;
-
- String S = String("DATA\\") + Name();
- if (!img.Load(S())) img.Load(Name()());
- /*
- String S(Name());
- FILE* file;
- file = fopen(S(), "rb");
- if(!file) {
- S = String("data\\")+S;
- file = fopen(S(), "rb");
- if(!file) {
- transferred = true;
- return;
- }
- }
- fclose(file);
- */
-
- if(lowtextures) {
- img.Scale(img.width()>>1, img.height()>>1);
- }
- if(voodoo) {
- int nwidth = img.width()>256 ? 256 : img.width();
- int nheight = img.height()>256 ? 256 : img.height();
- if(nwidth!=img.width()||nheight!=img.height())
- img.Scale(nwidth, nheight);
- }
-
- switch(img.format()) {
- case OGL_IMAGE_RGB888:
- img.FlipVertical();
- glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8,
- img.width(), img.height(), 0,
- GL_RGB, GL_UNSIGNED_BYTE, img.data());
-
- if (API3DS_TEXT_OUT) cout << "texture " << Name() << " transferred" << endl;
- break;
-
- case OGL_IMAGE_RGBA8888:
- img.FlipVertical();
- glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8,
- img.width(), img.height(), 0,
- GL_RGBA, GL_UNSIGNED_BYTE, img.data());
-
-
- if (API3DS_TEXT_OUT) cout << "texture " << Name() << " transferred" << endl;
- break;
-
- default:
- if (API3DS_TEXT_OUT) cout << "Bad image type " << img.format() << endl;
- break;
- }
- transferred = true;
- }
- }
-
- void Textures3DS::GL () {
- __entity_list.rewind();
- for(int i=__entity_list.size(); i; i--) {
- (*__entity_list)->GL();
- ++__entity_list;
- }
- }
-
- Texture3DS* Textures3DS::GetOrCreate (const char* s) {
- Texture3DS* p = Get(s);
- if(!p) {
- p = new Texture3DS;
- p->Name(s);
- p->MinFilter(GL_LINEAR);
- p->MagFilter(GL_LINEAR);
-
- Add(p);
- }
- return p;
- }
-
- Material3DS::Material3DS () {
- Reset();
- }
-
- void Material3DS::Reset () {
- ambient[0] = ambient[1] = ambient[2] = 0.0F; ambient[3] = 1.0F;
- diffuse[0] = diffuse[1] = diffuse[2] = 1.0F; diffuse[3] = 1.0F;
- specular[0] = specular[1] = specular[2] = 0.0F; specular[3] = 1.0F;
-
- shininess_percent = 0;
- shininess_strenght_percent = 0;
- transparency_percent = 0;
- transparency_falloff_percent = 0;
- self_illumination_percent = 0;
- reflect_blur_percent = 0;
-
- texture1 = 0;
- texture2 = 0;
- opacity_map = 0;
- bump_map = 0;
- specular_map = 0;
- shininess_map = 0;
- self_illum_map = 0;
- reflection_map = 0;
- }
-
- void Material3DS::GL(GLenum face = GL_FRONT_AND_BACK)
- {
- diffuse[3] = 0.6F; // (GLfloat)transparency_percent/100.0
- glMaterialfv(face, GL_AMBIENT, ambient);
- glMaterialfv(face, GL_DIFFUSE, diffuse);
- glMaterialfv(face, GL_SPECULAR, specular);
- // glMaterialf(face, GL_SHININESS, (GLfloat) shininess_percent);
-
- glShadeModel(GL_SMOOTH);
- glEnable(GL_DEPTH_TEST);
-
- if(texture1==0) {
- glDisable(GL_TEXTURE_2D);
- }
- else {
- glEnable(GL_TEXTURE_2D);
- texture1->GL();
- }
- }
-
- void Material3DS::Ambient (GLfloat r, GLfloat g, GLfloat b) {
- SetVector4(ambient, r, g, b, 1.0F);
- }
- void Material3DS::Diffuse (GLfloat r, GLfloat g, GLfloat b) {
- SetVector4(diffuse, r, g, b, 1.0F);
- }
- void Material3DS::Specular (GLfloat r, GLfloat g, GLfloat b) {
- SetVector4(specular, r, g, b, 1.0F);
- }
- void Material3DS::Ambient (GLfloat* v) {
- SetVector4(ambient, *v, *(v+1), *(v+2), 1.0F);
- }
- void Material3DS::Diffuse (GLfloat* v) {
- SetVector4(diffuse, *v, *(v+1), *(v+2), 1.0F);
- }
- void Material3DS::Specular (GLfloat* v) {
- SetVector4(specular, *v, *(v+1), *(v+2), 1.0F);
- }
- void Material3DS::Ambient (GLubyte r, GLubyte g, GLubyte b) {
- SetVector4(ambient, r, g, b, 255);
- }
- void Material3DS::Diffuse (GLubyte r, GLubyte g, GLubyte b) {
- SetVector4(diffuse, r, g, b, 255);
- }
- void Material3DS::Specular (GLubyte r, GLubyte g, GLubyte b) {
- SetVector4(specular, r, g, b, 255);
- }
- void Material3DS::Ambient (GLubyte* v) {
- SetVector4(ambient, *v, *(v+1), *(v+2), 255);
- }
- void Material3DS::Diffuse (GLubyte* v) {
- SetVector4(diffuse, *v, *(v+1), *(v+2), 255);
- }
- void Material3DS::Specular (GLubyte* v) {
- SetVector4(specular, *v, *(v+1), *(v+2), 255);
- }
-
- void Material3DS::Shininess (GLint i) {
- shininess_percent = i;
- }
- void Material3DS::ShininessStrenght (GLint i) {
- shininess_strenght_percent = i;
- }
- void Material3DS::Transparency (GLint i) {
- transparency_percent = i;
- }
- void Material3DS::TransparencyFalloff (GLint i) {
- transparency_falloff_percent = i;
- }
- void Material3DS::SelfIllumination (GLint i) {
- self_illumination_percent = i;
- }
- void Material3DS::ReflectBlur (GLint i) {
- reflect_blur_percent = i;
- }
-
- void Material3DS::Texture1 (Texture3DS* t) {
- texture1 = t;
- }
- void Material3DS::Texture2 (Texture3DS* t) {
- texture2 = t;
- }
- void Material3DS::OpacityMap (Texture3DS* t) {
- opacity_map = t;
- }
- void Material3DS::BumpMap (Texture3DS* t) {
- bump_map = t;
- }
- void Material3DS::SpecularMap (Texture3DS* t) {
- specular_map = t;
- }
- void Material3DS::ShininessMap (Texture3DS* t) {
- shininess_map = t;
- }
- void Material3DS::SelfIlluminationMap (Texture3DS* t) {
- self_illum_map = t;
- }
- void Material3DS::ReflectionMap (Texture3DS* t) {
- reflection_map = t;
- }
-
- const GLfloat* Material3DS::Ambient () {
- return ambient;
- }
- const GLfloat* Material3DS::Diffuse () {
- return diffuse;
- }
- const GLfloat* Material3DS::Specular () {
- return specular;
- }
- GLint Material3DS::Shininess () {
- return shininess_percent;
- }
- GLint Material3DS::ShininessStrenght () {
- return shininess_strenght_percent;
- }
- GLint Material3DS::Transparency () {
- return transparency_percent;
- }
- GLint Material3DS::TransparencyFalloff () {
- return transparency_falloff_percent;
- }
- GLint Material3DS::SelfIllumination () {
- return self_illumination_percent;
- }
- GLint Material3DS::ReflectBlur () {
- return reflect_blur_percent;
- }
- Texture3DS* Material3DS::Texture1 () {
- return texture1;
- }
- Texture3DS* Material3DS::Texture2 () {
- return texture2;
- }
- Texture3DS* Material3DS::OpacityMap () {
- return opacity_map;
- }
- Texture3DS* Material3DS::BumpMap () {
- return bump_map;
- }
- Texture3DS* Material3DS::SpecularMap () {
- return specular_map;
- }
- Texture3DS* Material3DS::ShininessMap () {
- return shininess_map;
- }
- Texture3DS* Material3DS::SelfIlluminationMap () {
- return self_illum_map;
- }
- Texture3DS* Material3DS::ReflectionMap () {
- return reflection_map;
- }
-
-
- OmniLight3DS::OmniLight3DS () {
- Reset();
- }
-
- void OmniLight3DS::Reset ()
- {
- Diffuse(0.0F, 0.0F, 0.0F);
- Position(0.0F, 0.0F, 0.0F);
- constant_attenuation = 1.0F;
- linear_attenuation = 0.0F;
- quadratic_attenuation = 0.0F;
- }
-
- void OmniLight3DS::GL (GLenum light, double time = 0.0)
- {
- GLfloat a[4];
- a[3] = 1.0F;
- Vector3f v = diffuse.Val(time);
- v.Unpack(a);
- glLightfv(light, GL_DIFFUSE, a);
- v = position.Val(time);
- v.Unpack(a);
- glLightfv(light, GL_POSITION, a);
-
- a[0] = a[1] = a[2] = 0.0F;
- glLightfv(light, GL_SPECULAR, a);
- glLightfv(light, GL_AMBIENT, a);
- glLightf(light, GL_CONSTANT_ATTENUATION, constant_attenuation);
- glLightf(light, GL_LINEAR_ATTENUATION, linear_attenuation);
- glLightf(light, GL_QUADRATIC_ATTENUATION, quadratic_attenuation);
- }
-
- void OmniLight3DS::Diffuse (GLfloat r, GLfloat g, GLfloat b) {
- diffuse(Vector3f(r, g, b));
- }
- void OmniLight3DS::Diffuse (GLubyte r, GLubyte g, GLubyte b) {
- diffuse(Vector3f(UBYTE_TO_FLOAT(r), UBYTE_TO_FLOAT(g), UBYTE_TO_FLOAT(b)));
- }
- void OmniLight3DS::Diffuse (const Vector3f& V) {
- diffuse(V);
- }
- void OmniLight3DS::Diffuse (Dynamic<Vector3f, GLfloat> *ptr, bool strong = false) {
- diffuse(ptr, strong);
- }
-
- void OmniLight3DS::Position (GLfloat x, GLfloat y, GLfloat z) {
- position(Vector3f(x, y, z));
- }
- void OmniLight3DS::Position (const Vector3f& V) {
- position(V);
- }
- void OmniLight3DS::Position (Dynamic<Vector3f, GLfloat> *ptr, bool strong = false) {
- position(ptr, strong);
- }
-
- void OmniLight3DS::ConstantAttenuation (GLfloat f) {
- constant_attenuation = f;
- }
- void OmniLight3DS::LinearAttenuation (GLfloat f) {
- linear_attenuation = f;
- }
- void OmniLight3DS::QuadraticAttenuation (GLfloat f) {
- quadratic_attenuation = f;
- }
-
- Vector3f OmniLight3DS::Position (double time = 0.0) {
- return position.Val(time);
- }
- Vector3f OmniLight3DS::Diffuse (double time = 0.0) {
- return diffuse.Val(time);
- }
- GLfloat OmniLight3DS::ConstantAttenuation () {
- return constant_attenuation;
- }
- GLfloat OmniLight3DS::LinearAttenuation () {
- return linear_attenuation;
- }
- GLfloat OmniLight3DS::QuadraticAttenuation () {
- return quadratic_attenuation;
- }
-
- Object3DS::~Object3DS () {
- delete[] vertices;
- facegroups.rewind();
- for(int i=facegroups.size(); i; i--) {
- delete (*facegroups).indices;
- ++facegroups;
- }
- }
-
- BoundingBox BoundVertices (int n, Vertex3DS* p) {
- BoundingBox B;
- GLfloat mx, my, mz, Mx, My, Mz, a1, a2;
- mx = Mx = p->x;
- my = My = p->y;
- mz = Mz = p->z;
- Vertex3DS* p1 = p+1;
-
- for(int i=n-1; i; i--, p++, p1++)
- {
- a1 = p->x;
- a2 = p1->x;
- if(a1<=a2) {
- if(a1<mx) mx=a1;
- if(a2>Mx) Mx=a2;
- }
- else {
- if(a2<mx) mx=a2;
- if(a1>Mx) Mx=a1;
- }
-
- a1 = p->y;
- a2 = p1->y;
- if(a1<=a2) {
- if(a1<my) my=a1;
- if(a2>My) My=a2;
- }
- else {
- if(a2<my) my=a2;
- if(a1>My) My=a1;
- }
-
- a1 = p->z;
- a2 = p1->z;
- if(a1<=a2) {
- if(a1<mz) mz=a1;
- if(a2>Mz) Mz=a2;
- }
- else {
- if(a2<mz) mz=a2;
- if(a1>Mz) Mz=a1;
- }
- }
- B.Corner1(mx, my, mz);
- B.Corner2(Mx, My, Mz);
- return B;
- }
- /*
- void Object3DS::Rays (Vector3f C, Vector3f S, GLfloat I) {
- glDisable(GL_LIGHTING);
- glEnable(GL_DEPTH_TEST);
- glDepthMask(GL_ZERO);
- glDisable(GL_CULL_FACE);
- glBlendFunc(GL_ONE, GL_ONE);
- glEnable(GL_BLEND);
- glDisable(GL_TEXTURE_2D);
-
- Vector3f V1, V2, V3, V4;
-
- glBegin(GL_QUADS);
- Edge3DS* p = edges;
- Vertex3DS* v1;
- Vertex3DS* v2;
- p = edges;
- for(int z=0; z<numedges; z++, p++) {
- v1 = evertices + p->a;
- v2 = evertices + p->b;
- V1 = Vector3f(v1->x-C.x, v1->y-C.y, v1->z-C.z);
- GLfloat a1 = V1.x*p->N1_x + V1.y*p->N1_y + V1.z*p->N1_z;
- GLfloat a2 = V1.x*p->N2_x + V1.y*p->N2_y + V1.z*p->N2_z;
- if((a1*a2)<0.0) {
- V1 = Vector3f(v1->x-S.x, v1->y-S.y, v1->z-S.z);
- V2 = Vector3f(v2->x-S.x, v2->y-S.y, v2->z-S.z);
- GLfloat len1 = VectorLength(V1);
- GLfloat len2 = VectorLength(V2);
- GLfloat r1 = 1.0/len1;
- GLfloat r2 = 1.0/len2;
- a1*=r1;
- a2*=r2;
- GLfloat obrysovost = Minimum(fabs(a1), fabs(a2));
- #define PI2 (PI/2)
- obrysovost=sin(sin(sin(sin(obrysovost*PI2)*PI2)*PI2)*PI2);
-
-
-
- GLfloat i1 = (1.0-len1/I)*obrysovost;
- GLfloat i2 = (1.0-len2/I)*obrysovost;
- if(i1<0.0||i2<0.0) continue;
- len1 = I*r1;
- len2 = I*r2;
- V1 *= len1;
- V2 *= len2;
- V1 += S;
- V2 += S;
- glColor3f(i1, i1, i1);
- glVertex3f(v1->x, v1->y, v1->z);
- glColor3f(i2, i2, i2);
- glVertex3f(v2->x, v2->y, v2->z);
- glColor3f(0.0F, 0.0F, 0.0F);
- glVertex3f(V2.x, V2.y, V2.z);
- glVertex3f(V1.x, V1.y, V1.z);
- }
- }
-
- glEnd();
-
- glDisable(GL_CULL_FACE);
- glDisable(GL_BLEND);
- glDepthMask(GL_ONE);
- glEnable(GL_LIGHTING);
- glEnable(GL_DEPTH_TEST);
- }
- */
-
- void Object3DS::Rays (Vector3f C, Vector3f S, GLfloat I, GLenum sfactor, GLenum dfactor) {
- glDisable(GL_LIGHTING);
- glEnable(GL_DEPTH_TEST);
- glDepthMask(GL_ZERO);
- glDisable(GL_CULL_FACE);
- glBlendFunc(sfactor, dfactor);
- glEnable(GL_BLEND);
- glDisable(GL_TEXTURE_2D);
-
- Vector3f V1, V2, V3, V4;
-
- glBegin(GL_QUADS);
- Edge3DS* p = edges;
- Vertex3DS* v1;
- Vertex3DS* v2;
- p = edges;
- for(int z=0; z<numedges; z++, p++) {
- v1 = evertices + p->a;
- v2 = evertices + p->b;
-
- V1 = Vector3f(v1->x-C.x, v1->y-C.y, v1->z-C.z);
-
- GLfloat a1 = V1.x*p->N1_x + V1.y*p->N1_y + V1.z*p->N1_z;
- GLfloat a2 = V1.x*p->N2_x + V1.y*p->N2_y + V1.z*p->N2_z;
- if((a1*a2)<0.0) {
-
- V2 = Vector3f(v2->x-C.x, v2->y-C.y, v2->z-C.z);
- V3 = Normalize((V1+V2)*0.5F);
- V4 = Normalize(C-S);
- GLfloat d34= Dot(V3, V4);
-
- V1 = Vector3f(v1->x-S.x, v1->y-S.y, v1->z-S.z);
- V2 = Vector3f(v2->x-S.x, v2->y-S.y, v2->z-S.z);
- GLfloat len1 = VectorLength(V1);
- GLfloat len2 = VectorLength(V2);
- GLfloat r1 = 1.0/len1;
- GLfloat r2 = 1.0/len2;
- a1*=r1;
- a2*=r2;
- #define PI2 (PI/2)
-
- GLfloat obrysovost = Minimum(fabs(a1), fabs(a2));
- obrysovost=sin(sin(sin(sin(obrysovost*PI2)*PI2)*PI2)*PI2);
-
- obrysovost*=sin(sin(sin(sin(sin(sin(cos(fabs(d34)*PI2)*PI2)*PI2)*PI2)*PI2)*PI2)*PI2);
-
-
- GLfloat i1 = (1.0-len1/I)*obrysovost;
- GLfloat i2 = (1.0-len2/I)*obrysovost;
- if(i1<0.0||i2<0.0) continue;
- len1 = I*r1;
- len2 = I*r2;
- V1 *= len1;
- V2 *= len2;
- V1 += S;
- V2 += S;
- i1*=0.3;
- i2*=0.3;
- glColor3f(i1, i1, i1);
- glVertex3f(v1->x, v1->y, v1->z);
- glColor3f(i2, i2, i2);
- glVertex3f(v2->x, v2->y, v2->z);
- glColor3f(0.0F, 0.0F, 0.0F);
- glVertex3f(V2.x, V2.y, V2.z);
- glVertex3f(V1.x, V1.y, V1.z);
- }
- }
-
- glEnd();
-
- glDisable(GL_CULL_FACE);
- glDisable(GL_BLEND);
- glDepthMask(GL_ONE);
- glEnable(GL_LIGHTING);
- glEnable(GL_DEPTH_TEST);
- }
-
- void Object3DS::ShadowVolume (Vector3f S, Vector3f C, GLfloat I, int j) {
- glDisable(GL_LIGHTING);
- glEnable(GL_DEPTH_TEST);
- glDepthMask(GL_ZERO);
- // glEnable(GL_CULL_FACE);
- glDisable(GL_CULL_FACE);
- glDisable(GL_BLEND);
-
- glBlendFunc(GL_ONE, GL_ONE);
- glEnable(GL_BLEND);
-
- float cler=0.0;
- glDisable(GL_TEXTURE_2D);
-
- Vector3f V1, V2, V3;
-
- glBegin(GL_QUADS);
- Edge3DS* p = edges;
- Vertex3DS* v1;
- Vertex3DS* v2;
- p = edges;
- for(int z=0; z<numedges; z++, p++) {
- v1 = evertices + p->a;
- v2 = evertices + p->b;
-
- V1 = Vector3f(v1->x-S.x, v1->y-S.y, v1->z-S.z);
- V3 = Vector3f(v1->x-C.x, v1->y-C.y, v1->z-C.z);
-
- GLfloat a1 = V1.x*p->N1_x + V1.y*p->N1_y + V1.z*p->N1_z;
- GLfloat a2 = V1.x*p->N2_x + V1.y*p->N2_y + V1.z*p->N2_z;
- Vector3f n1=Vector3f( p->N1_x+p->N2_x, p->N1_y+p->N2_y, p->N1_z+p->N2_z)*0.5F;
- Vector3f n2=Vector3f( v1->x-v2->x, v1->y-v2->y, v1->z-v2->z);
- Vector3f n3=Cross(n2,V1);
- if ( Dot(n3,n1)<0.0 ) n3=-n3;
-
- GLfloat a3= (V3.x*n3.x + V3.y*n3.y + V3.z*n3.z)*j;
-
- if (a3>0.0)
- if((a1*a2)<0.0) {
-
- V2 = Vector3f(v2->x-S.x, v2->y-S.y, v2->z-S.z);
-
-
- float len1 = (I/sqrt(V1.x*V1.x + V1.y*V1.y + V1.z*V1.z));
- V1.x=V1.x*len1 + v1->x;
- V1.y=V1.y*len1 + v1->y;
- V1.z=V1.z*len1 + v1->z;
-
- float len2 = (I/sqrt(V2.x*V2.x + V2.y*V2.y + V2.z*V2.z));
- V2.x=V2.x*len2 + v2->x;
- V2.y=V2.y*len2 + v2->y;
- V2.z=V2.z*len2 + v2->z;
-
-
-
- glColor3f(cler,cler,cler);
- glVertex3f(v1->x, v1->y, v1->z);
- glVertex3f(v2->x, v2->y, v2->z);
- glVertex3f(V2.x, V2.y, V2.z);
- glVertex3f(V1.x, V1.y, V1.z);
- }
- }
-
- glEnd();
-
- glDisable(GL_CULL_FACE);
- glDisable(GL_BLEND);
- glDepthMask(GL_ONE);
- glEnable(GL_LIGHTING);
- glEnable(GL_DEPTH_TEST);
- }
-
-
- void Object3DS::ShortLine ( Vector3f C, GLfloat W, GLfloat r, GLfloat g, GLfloat b) {
- glDisable(GL_LIGHTING);
- glDisable(GL_CULL_FACE);
- // glDisable(GL_BLEND);
- glDisable(GL_TEXTURE_2D);
- glLineWidth(W);
- Vector3f V1;
-
- glBegin(GL_LINES);
- glColor3f(r,g,b);
-
- Edge3DS* p = edges;
- Vertex3DS* v1;
- Vertex3DS* v2;
- p = edges;
- float total=0.0;
- for(int z=0; z<numedges; z++, p++) {
- v1 = evertices + p->a;
- v2 = evertices + p->b;
- V1 = Normalize( Vector3f(v1->x-C.x, v1->y-C.y, v1->z-C.z) );
- GLfloat a1 = V1.x*p->N1_x + V1.y*p->N1_y + V1.z*p->N1_z;
- GLfloat a2 = V1.x*p->N2_x + V1.y*p->N2_y + V1.z*p->N2_z;
- // if((a1>=0.0)&&(a2>=0.0))
- // if((a1<=0.0)&&(a2<=0.0))
- {
- glVertex3f(v1->x, v1->y, v1->z);
- glVertex3f(v2->x, v2->y, v2->z);
- }
- //cout << "Vertex " << z << ": " << p->a << "," << p->b << endl;
- total++;
- }
- glEnd();
- //cout << "Shortline total: " << total << endl;
- glEnable(GL_CULL_FACE);
- glDepthMask(GL_ONE);
- glEnable(GL_LIGHTING);
- glEnable(GL_DEPTH_TEST);
- }
-
-
- void DrawLongLine(float x1,float y1, float x2, float y2)
- {
- float xl,yl;
- float xr,yr;
- float xu,yu;
- float xd,yd;
- int l,r,u,d;
- float a;
-
- l=r=u=d=0;
- float dx=x2-x1;
- float dy=y2-y1;
-
-
- if (dx!=0)
- {
- a=( 1.0-x2)/dx;
- xr=1.0;
- yr=y2+a*dy;
- if ((yr<1.0)&&(yr>=-1.0)) r=1;
-
- a=(-1.0-x2)/dx;
- xl=-1.0;
- yl=y2+a*dy;
- if ((yl<=1.0)&&(yl>-1.0)) l=1;
- }
-
- if (dy!=0)
- {
- a=( 1.0-y2)/dy;
- yu=1.0;
- xu=x2+a*dx;
- if ((xu<=1.0)&&(xu>-1.0)) u=1;
-
- a=(-1.0-y2)/dy;
- yd=-1.0;
- xd=x2+a*dx;
- if ((xd<1.0)&&(xd>=-1.0)) d=1;
- }
-
- if (l) glVertex2f(xl,yl);
- if (r) glVertex2f(xr,yr);
- if (u) glVertex2f(xu,yu);
- if (d) glVertex2f(xd,yd);
- }
-
-
- void Object3DS::LongLine ( Vector3f ang, Vector3f pos, GLfloat scale, GLfloat w, GLfloat r, GLfloat g, GLfloat b)
- {
- glLineWidth(w);
-
- GLmatrix m=Euler2Matrix(ang.x,ang.y,ang.z);
-
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glLoadIdentity();
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
- glLoadIdentity();
-
-
- glBegin(GL_LINES);
- glColor3f(r,g,b);
-
- Edge3DS* p = edges;
- Vertex3DS* v1;
- Vertex3DS* v2;
- Vector2f sc1,sc2;
- p = edges;
- for(int z=0; z<numedges; z++, p++) {
- v1 = evertices + p->a;
- v2 = evertices + p->b;
-
- Vector4f t1(v1->x,v1->y,v1->z,1.0F);
- Vector4f t2(v2->x,v2->y,v2->z,1.0F);
-
- m.MultVertex4f(t1.x,t1.y,t1.z,t1.w);
- m.MultVertex4f(t2.x,t2.y,t2.z,t2.w);
-
- sc1= Vector2f(pos.x+ scale*t1.x/ (t1.z+pos.z), pos.y+ scale*t1.y/ (t1.z+pos.z));
- sc2= Vector2f(pos.x+ scale*t2.x/ (t2.z+pos.z), pos.y+ scale*t2.y/ (t2.z+pos.z));
-
- DrawLongLine(sc1.x,sc1.y,sc2.x,sc2.y);
- }
- glEnd();
-
- glPopMatrix();
- glMatrixMode(GL_PROJECTION);
- glPopMatrix();
- glMatrixMode(GL_MODELVIEW);
-
- }
-
-
- void Object3DS::ShortLine ( Vector3f ang, Vector3f pos, GLfloat scale, GLfloat w, GLfloat r, GLfloat g, GLfloat b)
- {
- glLineWidth(w);
-
- GLmatrix m=Euler2Matrix(ang.x,ang.y,ang.z);
-
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glLoadIdentity();
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
- glLoadIdentity();
-
-
- glBegin(GL_LINES);
- glColor3f(r,g,b);
-
- Edge3DS* p = edges;
- Vertex3DS* v1;
- Vertex3DS* v2;
- Vector2f sc1,sc2;
- p = edges;
- for(int z=0; z<numedges; z++, p++) {
- v1 = evertices + p->a;
- v2 = evertices + p->b;
-
-
- Vector4f t1(v1->x,v1->y,v1->z,1.0F);
- Vector4f t2(v2->x,v2->y,v2->z,1.0F);
-
- m.MultVertex4f(t1.x,t1.y,t1.z,t1.w);
- m.MultVertex4f(t2.x,t2.y,t2.z,t2.w);
-
- sc1= Vector2f(pos.x+ scale*t1.x/ (t1.z+pos.z), pos.y+ scale*t1.y/ (t1.z+pos.z));
- sc2= Vector2f(pos.x+ scale*t2.x/ (t2.z+pos.z), pos.y+ scale*t2.y/ (t2.z+pos.z));
- glVertex2f(sc1.x, sc1.y);
- glVertex2f(sc2.x, sc2.y);
-
- }
- glEnd();
-
- glPopMatrix();
- glMatrixMode(GL_PROJECTION);
- glPopMatrix();
- glMatrixMode(GL_MODELVIEW);
-
- }
-
-
- void Object3DS::Outline ( Vector3f C, GLfloat W, GLfloat r, GLfloat g, GLfloat b) {
- glDisable(GL_LIGHTING);
- glDisable(GL_DEPTH_TEST);
- // glDepthMask(GL_ZERO);
- glDisable(GL_CULL_FACE);
- // glDisable(GL_BLEND);
- glDisable(GL_TEXTURE_2D);
- glLineWidth(W);
- Vector3f V1;
-
- glBegin(GL_LINES);
- glColor3f(r,g,b);
-
- Edge3DS* p = edges;
- Vertex3DS* v1;
- Vertex3DS* v2;
- p = edges;
- float total=0.0;
- float outl=0.0;
- float other=0.0;
-
- for(int z=0; z<numedges; z++) {
- v1 = evertices + p->a;
- v2 = evertices + p->b;
- V1 = Normalize( Vector3f(v1->x-C.x, v1->y-C.y, v1->z-C.z) );
- GLfloat a1 = V1.x*p->N1_x + V1.y*p->N1_y + V1.z*p->N1_z;
- GLfloat a2 = V1.x*p->N2_x + V1.y*p->N2_y + V1.z*p->N2_z;
- if((a1*a2)<0.0)
- {
- // GLfloat obr = Minimum(fabs(a1), fabs(a2));
- // obr=sin(sin(sin(sin(obr*PI2)*PI2)*PI2)*PI2);
- // glColor3f(obr,obr,obr);
- glVertex3f(v1->x, v1->y, v1->z);
- glVertex3f(v2->x, v2->y, v2->z);
- outl++;
- } else other++;
- total++;
- p++;
- }
- glEnd();
- //cout << "Longline total: " << total << " good: " << outl << " bad: " << other << endl;
- //if (total>numedges) cout << "error 1" << endl;
- //if (total!=outl+other) cout << "error 2" << endl;
- glEnable(GL_CULL_FACE);
- glDepthMask(GL_ONE);
- glEnable(GL_LIGHTING);
- glEnable(GL_DEPTH_TEST);
- }
-
-
- void Object3DS::Inline ( Vector3f C, GLfloat W, GLfloat r, GLfloat g, GLfloat b) {
- glDisable(GL_LIGHTING);
- glDisable(GL_DEPTH_TEST);
- // glDepthMask(GL_ZERO);
- glDisable(GL_CULL_FACE);
- // glDisable(GL_BLEND);
- glDisable(GL_TEXTURE_2D);
- glLineWidth(W);
- Vector3f V1;
-
- glBegin(GL_LINES);
- glColor3f(r,g,b);
-
- Edge3DS* p = edges;
- Vertex3DS* v1;
- Vertex3DS* v2;
- p = edges;
- float total=0.0;
- float outl=0.0;
- float other=0.0;
-
- for(int z=0; z<numedges; z++) {
- v1 = evertices + p->a;
- v2 = evertices + p->b;
- V1 = Normalize( Vector3f(v1->x-C.x, v1->y-C.y, v1->z-C.z) );
- GLfloat a1 = V1.x*p->N1_x + V1.y*p->N1_y + V1.z*p->N1_z;
- GLfloat a2 = V1.x*p->N2_x + V1.y*p->N2_y + V1.z*p->N2_z;
- if((a1*a2)>=0.0)
- {
- // GLfloat obr = Minimum(fabs(a1), fabs(a2));
- // obr=sin(sin(sin(sin(obr*PI2)*PI2)*PI2)*PI2);
- // glColor3f(obr,obr,obr);
- glVertex3f(v1->x, v1->y, v1->z);
- glVertex3f(v2->x, v2->y, v2->z);
- outl++;
- } else other++;
- total++;
- p++;
- }
- glEnd();
- if (total>numedges) cout << "error 3" << endl;
- if (total!=outl+other) cout << "error 4" << endl;
- glEnable(GL_CULL_FACE);
- glDepthMask(GL_ONE);
- glEnable(GL_LIGHTING);
- glEnable(GL_DEPTH_TEST);
- }
-
- void Object3DS::Render (double time = 0.0) {
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
- GLmatrix M = lcs.Val(time);
- glMultMatrixf(M());
-
- if(!(bbox.IsVisible())) {
- glPopMatrix();
- return;
- }
-
- glInterleavedArrays(GL_T4F_C4F_N3F_V4F, 0, (void*)vertices);
-
- glLockArraysEXT(0, numvertices);
-
- facegroups.rewind();
- for(int i=facegroups.size(); i; i--) {
- FaceGroup3DS& fg = *facegroups;
- Material3DS* mat = fg.material;
- mat->GL();
- switch(mat->Transparency()) {
- case 50:
- glDepthMask(GL_ZERO);
- glDisable(GL_CULL_FACE);
- glEnable(GL_BLEND);
- glBlendFunc(GL_ONE, GL_ONE);
- break;
- case 49:
- case 51:
- glDepthMask(GL_ZERO);
- glDisable(GL_CULL_FACE);
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- break;
- default:
- glDepthMask(GL_ONE);
- glEnable(GL_CULL_FACE);
- glDisable(GL_BLEND);
- break;
- }
- glDrawElements(GL_TRIANGLES, 3*(fg.numfaces), GL_UNSIGNED_INT, (void*)(fg.indices));
- ++facegroups;
- }
-
- glUnlockArraysEXT();
-
- glDisable(GL_CULL_FACE);
- glDisable(GL_BLEND);
- glDepthMask(GL_ONE);
-
- glPopMatrix();
- }
-
- void Object3DS::Vertices (int n, Vertex3DS* p) {
- numvertices = n;
- vertices = p;
- bbox = BoundVertices(n, p);
- }
- void Object3DS::AddFaceGroup (Material3DS* mat, int n, GLuint* ind) {
- facegroups.push_back(FaceGroup3DS(mat, n, ind));
- }
- void Object3DS::EdgeVertices (int n, Vertex3DS* p) {
- numevertices = n;
- evertices = p;
- }
- void Object3DS::Edges (int n, Edge3DS* p) {
- numedges = n;
- edges = p;
- }
- void Object3DS::Facenormals (int n, Vector3f* p) {
- numfaces = n;
- facenormals = p;
- }
- void Object3DS::CoordinateSystem (const GLmatrix& V) {
- lcs(V);
- }
- void Object3DS::CoordinateSystem (Dynamic<GLmatrix, GLfloat> *ptr, bool strong = false) {
- lcs(ptr, strong);
- }
-
- Scene3DS::Scene3DS () {
- allframes = 0;
-
- Material3DS* default_material = new Material3DS;
- default_material->Name("____DEFAULT_MATERIAL");
- Add(default_material);
-
- return;
- }
- Scene3DS::~Scene3DS () {
- lights.DeleteEntities();
- materials.DeleteEntities();
- textures.DeleteEntities();
- cameras.DeleteEntities();
- objects.DeleteEntities();
- }
- void Scene3DS::Render (double time = 0.0) {
- lights.GL(time);
- objects.Render(time);
- }
- void Scene3DS::Add (Light* p) {
- lights+=p;
- }
- void Scene3DS::Add (Texture3DS* p) {
- textures+=p;
- }
- void Scene3DS::Add (Material3DS* p) {
- materials+=p;
- }
- void Scene3DS::Add (CameraTarget3DS* p) {
- cameras+=p;
- }
- void Scene3DS::Add (RenderableEntity* p) {
- objects+=p;
- }
- void Scene3DS::Add (const RenderableEntities & os) {
- objects.Add(os);
- }
- Light* Scene3DS::GetLight (String s) {
- return lights.Get(s);
- }
- Texture3DS* Scene3DS::GetTexture (String s) {
- return textures.Get(s);
- }
- Material3DS* Scene3DS::GetMaterial (String s) {
- return materials.Get(s);
- }
- CameraTarget3DS* Scene3DS::GetCamera (String s) {
- return cameras.Get(s);
- }
- RenderableEntity* Scene3DS::GetObject (String s) {
- return objects.Get(s);
- }
-
- Lights Scene3DS::GetLights () {
- return lights;
- }
- Textures3DS Scene3DS::GetTextures () {
- return textures;
- }
- Materials3DS Scene3DS::GetMaterials () {
- return materials;
- }
- Cameras3DS Scene3DS::GetCameras () {
- return cameras;
- }
- RenderableEntities Scene3DS::GetObjects () {
- return objects;
- }
-
- void Scene3DS::Ambient (GLfloat r, GLfloat g, GLfloat b, GLfloat a=1.0) {
- SetVector4(ambient, r, g, b, a);
- }
-
- char* Loader3DS::find_chunk(char *father, unsigned short chunk_type, char *act)
- {
- char *chunk_end = father + getlong(father+2);
- while((act<chunk_end) && (getshort(act)!=chunk_type))
- act += getlong(act+2);
- if(act<chunk_end)
- return act;
- else
- return 0;
- }
-
- List<chunk3ds> Loader3DS::subchunks(char *father, char *act)
- {
- List<chunk3ds> l;
- chunk3ds c;
- char *chunk_end = father + getlong(father+2);
- while(act<chunk_end)
- {
- c.type=getshort(act);
- c.ptr=act;
- l.push_back(c);
- act+=getlong(act+2);
- }
- return l;
- }
-
- List<chunk3ds> Loader3DS::subchunks_by_type(char *father, unsigned short chunk_type, char *act)
- {
- List<chunk3ds> l;
- chunk3ds c;
- char *chunk_end = father + getlong(father+2);
- while(act<chunk_end)
- {
- if(getshort(act) == chunk_type)
- {
- c.type = getshort(act);
- c.ptr = act;
- l.push_back(c);
- }
- act+=getlong(act+2);
- }
- return l;
- }
-
- void Loader3DS::tcb_info(unsigned short flag)
- {
- // if (API3DS_TEXT_OUT) cout << flag << " ";
- if(flag&1)
- if (API3DS_TEXT_OUT) cout << "tension ";
- if(flag&2)
- if (API3DS_TEXT_OUT) cout << "continuity ";
- if(flag&4)
- if (API3DS_TEXT_OUT) cout << "bias ";
- if(flag&8)
- if (API3DS_TEXT_OUT) cout << "ease-to ";
- if(flag&16)
- if (API3DS_TEXT_OUT) cout << "ease-from ";
- }
-
- char* Loader3DS::fill_tcbee(unsigned short flag, char *p, TCBEE *tcb)
- {
- tcb->tension = 0.0;
- tcb->continuity = 0.0;
- tcb->bias = 0.0;
- tcb->easeto = 0.0;
- tcb->easefrom = 0.0;
-
- if(flag&1) {
- tcb->tension = getfloat(p);
- p+=4;
- }
- if(flag&2) {
- tcb->continuity = getfloat(p);
- p+=4;
- }
- if(flag&4) {
- tcb->bias = getfloat(p);
- p+=4;
- }
- if(flag&8) {
- tcb->easeto = getfloat(p);
- p+=4;
- }
- if(flag&16) {
- tcb->easefrom = getfloat(p);
- p+=4;
- }
- return p;
- }
-
-
- void Loader3DS::track_type_info(unsigned short flag)
- {
- switch(flag&3) {
- case 0:
- if (API3DS_TEXT_OUT) cout << "single";
- break;
- case 2:
- if (API3DS_TEXT_OUT) cout << "repeat";
- break;
- case 3:
- if (API3DS_TEXT_OUT) cout << "loop";
- break;
- }
- switch((flag&52)>>3) {
- case 1:
- if (API3DS_TEXT_OUT) cout << ", lock X";
- break;
- case 2:
- if (API3DS_TEXT_OUT) cout << ", lock Y";
- break;
- case 4:
- if (API3DS_TEXT_OUT) cout << ", lock Z";
- break;
- }
- switch((flag&896)>>7) {
- case 1:
- if (API3DS_TEXT_OUT) cout << ", unlink X";
- break;
- case 2:
- if (API3DS_TEXT_OUT) cout << ", unlink Y";
- break;
- case 4:
- if (API3DS_TEXT_OUT) cout << ", unlink Z";
- break;
- }
- }
-
- Scene3DS* Loader3DS::Load(const char *inputfile, Textures3DS* texturelib = 0)
- {
- Scene3DS* scene = 0;
- bool take_care_of_buf_alloc = buffer ? false : true;
-
- try {
-
- if(take_care_of_buf_alloc)
- buffer = new char[BUFFER_SIZE_3DS];
-
- gzFile file;
- file = gzopen(inputfile,"rb");
- if(file == 0) {
- if (API3DS_TEXT_OUT) cout << "3DS Loader: Error: Can't open """ << inputfile << """." << endl;
- throw 1;
- }
- gzread(file, buffer, BUFFER_SIZE_3DS);
- gzclose(file);
- /*
- int f = open(inputfile, O_BINARY|O_RDONLY);
- if (f==-1) {
- if (API3DS_TEXT_OUT) cout << "3DS Loader: Error: File not found." << endl;
- throw 1;
- }
-
- struct stat st;
- fstat(f,&st);
- buffer = new char[st.st_size];
- read(f,buffer,st.st_size);
- close(f);
- */
- if (API3DS_TEXT_OUT) cout << "3DS Loader: Processing \""<< inputfile << "\":" << endl;
- if (getshort(buffer)!=MAIN_3DS_CHUNK)
- {
- if (API3DS_TEXT_OUT) cout << "3DS Loader: Error: Invalid inputfile." << endl;
- throw 1;
- }
-
- // start processing
- char *pmesh = buffer;
-
- scene = new Scene3DS;
- scene->Name(inputfile);
-
- // find the editor chunk
- char *peditor = find_chunk(pmesh, EDITOR_CHUNK, pmesh+6);
-
- // look for ambient color
- char *p = find_chunk(peditor, AMBIENT_COLOR, peditor+6);
- if(p!=0)
- {
- p = find_chunk(p, RGBfloat, p+6);
- if(p!=0)
- {
- p+=6;
- if (API3DS_TEXT_OUT) cout<<" Ambient color: ("
- <<(int)(256*getfloat(p))<<", "
- <<(int)(256*getfloat(p+4))<<", "
- <<(int)(256*getfloat(p+8))<< ")" << endl;
- scene->Ambient(getfloat(p), getfloat(p+4), getfloat(p+8));
- }
- }
-
- List<chunk3ds> pmats(subchunks_by_type(peditor, MATERIAL_BLOCK, peditor+6));
- if (API3DS_TEXT_OUT) cout << " Materials: " << endl;
- char *pmat;
- pmats.rewind();
- for(int nm=pmats.size(); nm; nm--)
- {
-
- pmat = (*pmats).ptr;
- p = find_chunk(pmat, MATERIAL_NAME, pmat+6);
- if (API3DS_TEXT_OUT) cout << " \"" << (const char *)(p+6) << "\":" << endl;
-
- Material3DS *mat = new Material3DS;
- mat->Name((const char *)(p+6));
- scene->Add(mat);
-
- p = find_chunk(pmat, MATERIAL_AMBIENT_COLOR, pmat+6);
- if(p!=0)
- {
- GLubyte *rgbcolor = (GLubyte *)find_chunk(p, RGBbyte, p+6)+6;
- if (API3DS_TEXT_OUT) cout << " Ambient color: ("
- << (int) *rgbcolor << ", "
- << (int) *(rgbcolor+1) << ", "
- << (int) *(rgbcolor+2) << ")" << endl;
- mat->Ambient(*rgbcolor, *(rgbcolor+1), *(rgbcolor+2));
- }
- p = find_chunk(pmat, MATERIAL_DIFFUSE_COLOR, pmat+6);
- if(p!=0)
- {
- GLubyte *rgbcolor = (GLubyte *)find_chunk(p, RGBbyte, p+6)+6;
- if (API3DS_TEXT_OUT) cout << " Diffuse color: ("
- << (int) *rgbcolor << ", "
- << (int) *(rgbcolor+1) << ", "
- << (int) *(rgbcolor+2) << ")" << endl;
- mat->Diffuse(*rgbcolor, *(rgbcolor+1), *(rgbcolor+2));
- }
- p = find_chunk(pmat, MATERIAL_SPECULAR_COLOR, pmat+6);
- if(p!=0)
- {
- GLubyte *rgbcolor = (GLubyte *)find_chunk(p, RGBbyte, p+6)+6;
- if (API3DS_TEXT_OUT) cout << " Specular color: ("
- << (int) *rgbcolor << ", "
- << (int) *(rgbcolor+1) << ", "
- << (int) *(rgbcolor+2) << ")" << endl;
- mat->Specular(*rgbcolor, *(rgbcolor+1), *(rgbcolor+2));
- }
-
- p = find_chunk(pmat, TRANSPARENCY_PERCENT, pmat+6);
- if(p!=0)
- {
- char *percent = find_chunk(p, PERCENTword, p+6)+6;
- if (API3DS_TEXT_OUT) cout << " Transparency: " << getshort(percent) << "%" << endl;
- int xp = getshort(percent);
- mat->Transparency(xp);
- }
-
- p = find_chunk(pmat, MAP1, pmat+6);
- if(p!=0)
- {
- char *ptname = find_chunk(p, MAPPING_FILENAME, p+6)+6;
- // *-> data directory access
- // char tm_p[30]="data\\";
- // strcat(tm_p,ptname);
- // strcpy(ptname,tm_p);
-
- if (API3DS_TEXT_OUT) cout << " Diffuse map: \"" << (const char *)ptname << "\"" << endl;
-
- /*
- * An external texture library can be passed as a second argument
- * to Load(...)
- */
- Texture3DS* tex;
- if(texturelib) {
- tex = texturelib->GetOrCreate((const char*)ptname);
- }
- else {
- tex = new Texture3DS;
- tex->Name((const char *)ptname);
- tex->MinFilter(GL_LINEAR);
- tex->MagFilter(GL_LINEAR);
-
- scene->Add(tex);
- }
- mat->Texture1(tex);
-
- }
-
- ++pmats;
- }
-
- // list obj blocks within editor
- List<chunk3ds> pl(subchunks_by_type(peditor, OBJECT_BLOCK, peditor+6));
- pl.rewind();
- char *po, *pi, *ptri;
-
- RenderableEntities transparent_objects;
- bool istransparent;
-
- if (API3DS_TEXT_OUT) cout << " Object blocks:" << endl;
-
- const char *pname;
- for(int no=pl.size(); no; no--)
- {
- po = (*pl).ptr;
- ++pl;
- pi = po + 6;
- pname = (const char *)pi;
- if (API3DS_TEXT_OUT) cout << " \"" << pname << "\" ";
- while(*pi) pi++; pi++;
-
- if(find_chunk(po, TRIANGULAR_MESH, pi))
- {
- if (API3DS_TEXT_OUT) cout << "A mesh. ";
- ptri = find_chunk(po, TRIANGULAR_MESH, pi);
-
- // find vertices
- int vertex_count = 0;
- Vector3DS *pvertices = 0;
- p = find_chunk(ptri, VERTICES, ptri+6);
- if(p!=0)
- {
- vertex_count = getshort(p+6);
- pvertices = (Vector3DS *)(p+8);
- }
-
- // find faces
- int face_count = 0;
- Face3DS *pfaces = 0;
- p = find_chunk(ptri, FACES, ptri+6);
- char *pfaceschunk = p;
- if(p!=0)
- {
- face_count = getshort(p+6);
- pfaces = (Face3DS *)(p+8);
- }
-
- // find mapping info
- int map_vertex_count = 0;
- Mapping3DS *pmapping = 0;
- p = find_chunk(ptri, MAPPING_COORDS, ptri+6);
- if(p!=0)
- {
- map_vertex_count = getshort(p+6);
- pmapping = (Mapping3DS *)(p+8);
- }
-
- if(pvertices && pfaces)
- {
- if (API3DS_TEXT_OUT) cout <<"("<<vertex_count<<" vertices, "<<face_count<<" faces"<<")";
- if(pmapping)
- if (API3DS_TEXT_OUT) cout << " mapped.";
- if (API3DS_TEXT_OUT) cout << endl;
-
- Object3DS *object = new Object3DS;
- object->Name(pname);
- istransparent = false;
-
- // for every i-th face smooths[i] is the smoothing groups info
- unsigned long *smooths = 0;
- if(find_chunk(pfaceschunk, SMOOTHINGS, (char *)(pfaces+face_count))) {
- smooths = (unsigned long *)(6+find_chunk(pfaceschunk, SMOOTHINGS, (char *)(pfaces+face_count)));
- }
-
- iface Iface[face_count];
- Vector3f P1, P2, P3;
- for(int z=0; z<face_count; z++) {
- Iface[z].a = pfaces[z].a;
- Iface[z].b = pfaces[z].b;
- Iface[z].c = pfaces[z].c;
- if(smooths)
- Iface[z].sgroup = smooths[z];
- else
- Iface[z].sgroup = 1;
- Vector3DS* pv;
- pv = pvertices + pfaces[z].a;
- P1 = Vector3f(pv->x, pv->y, pv->z);
- pv = pvertices + pfaces[z].b;
- P2 = Vector3f(pv->x, pv->y, pv->z);
- pv = pvertices + pfaces[z].c;
- P3 = Vector3f(pv->x, pv->y, pv->z);
- Iface[z].N = Normalize(CrossProduct(P2-P1, P3-P1));
- Iface[z].hasmaterial = false;
- Iface[z].ab_done = !(pfaces[z].flags&4);
- Iface[z].ac_done = !(pfaces[z].flags&1);
- Iface[z].bc_done = !(pfaces[z].flags&2);
- // Iface[z].ab_done = false;
- // Iface[z].ac_done = false;
- // Iface[z].bc_done = false;
- }
-
- Vertex3DS* vert = new Vertex3DS[vertex_count*2];
-
- for(int z=0; z<vertex_count; z++) {
- vert[z].x = pvertices[z].x;
- vert[z].y = pvertices[z].y;
- vert[z].z = pvertices[z].z;
- vert[z].w = 1.0F;
- vert[z].R = vert[z].G = vert[z].B = vert[z].A = 1.0F;
- vert[z].r = 0.0F;
- vert[z].q = 1.0F;
- if(pmapping) {
- vert[z].s = pmapping[z].u;
- vert[z].t = pmapping[z].v;
- }
- else {
- vert[z].s = 0.0F;
- vert[z].t = 0.0F;
- }
-
- vert[z].i = 0.0F;
- vert[z].j = 0.0F;
- vert[z].k = 0.0F;
- }
-
- /*
- * Here we create a copy of the vertices, which is suitable for
- * creating volumetric effects.
- */
- for(int z=0; z<vertex_count; z++) {
- vert[z+vertex_count] = vert[z];
- }
- object->EdgeVertices(vertex_count*2, vert);
-
- /*
- * We build an array of normals at each face, suitable for effects.
- */
- Vector3f* fnormals = new Vector3f[face_count];
- for(int z=0; z<face_count; z++) {
- fnormals[z] = Iface[z].N;
- }
- object->Facenormals(face_count, fnormals);
-
- /*
- * For each vertex we build a table of pointers to faces
- * that share it.
- */
-
- shinfo sharings[vertex_count];
- for(int z=0; z<vertex_count; z++) {
- sharings[z].numfaces = 0;
- sharings[z].used = 0;
- sharings[z].splits = 0;
- sharings[z].p = 0;
- sharings[z].v = 0;
- sharings[z].iv = 0;
- }
-
- for(int z=0; z<face_count; z++) {
- sharings[Iface[z].a].numfaces++;
- sharings[Iface[z].b].numfaces++;
- sharings[Iface[z].c].numfaces++;
- }
-
- ftable fgroups[face_count*3];
- for(int z=0; z<(face_count*3); z++) {
- fgroups[z].group = 0;
- }
- ftable* fptr = fgroups;
- for(int z=0; z<vertex_count; z++) {
- sharings[z].p = fptr;
- fptr+=sharings[z].numfaces;
- }
-
- for(int z=0; z<face_count; z++) {
- (sharings[Iface[z].a].p + sharings[Iface[z].a].used)->fi = z;
- sharings[Iface[z].a].used++;
- (sharings[Iface[z].b].p + sharings[Iface[z].b].used)->fi = z;
- sharings[Iface[z].b].used++;
- (sharings[Iface[z].c].p + sharings[Iface[z].c].used)->fi = z;
- sharings[Iface[z].c].used++;
- }
-
- /*
- * Build an array of this objects polygon edges
- */
- Edge3DS* edges = new Edge3DS[face_count*3];
- int edge_count = 0;
-
- for(int z=0; z<face_count; z++) {
- GLuint aa = Iface[z].a;
- GLuint bb = Iface[z].b;
- GLuint cc = Iface[z].c;
- // AB edge
- if(!Iface[z].ab_done) {
- Iface[z].ab_done = true;
- edges[edge_count].a = aa;
- edges[edge_count].b = bb;
- edges[edge_count].N1_x = Iface[z].N.x;
- edges[edge_count].N1_y = Iface[z].N.y;
- edges[edge_count].N1_z = Iface[z].N.z;
-
- ftable* fp = sharings[aa].p;
- int d = 0;
- for(; d<sharings[aa].numfaces; d++, fp++) {
- if(z==fp->fi) continue;
- iface& face = Iface[fp->fi];
- if((face.a==aa&&face.b==bb)||(face.a==bb&&face.b==aa)) {
- face.ab_done = true;
- edges[edge_count].N2_x = face.N.x;
- edges[edge_count].N2_y = face.N.y;
- edges[edge_count].N2_z = face.N.z;
- break;
- }
- if((face.a==aa&&face.c==bb)||(face.a==bb&&face.c==aa)) {
- face.ac_done = true;
- edges[edge_count].N2_x = face.N.x;
- edges[edge_count].N2_y = face.N.y;
- edges[edge_count].N2_z = face.N.z;
- break;
- }
- if((face.b==aa&&face.c==bb)||(face.b==bb&&face.c==aa)) {
- face.bc_done = true;
- edges[edge_count].N2_x = face.N.x;
- edges[edge_count].N2_y = face.N.y;
- edges[edge_count].N2_z = face.N.z;
- break;
- }
- }
- if(d==sharings[aa].numfaces) {
- edges[edge_count].N2_x = -Iface[z].N.x;
- edges[edge_count].N2_y = -Iface[z].N.y;
- edges[edge_count].N2_z = -Iface[z].N.z;
- }
- edge_count++;
- }
- // AC edge
- if(!Iface[z].ac_done) {
- Iface[z].ac_done = true;
- edges[edge_count].a = aa;
- edges[edge_count].b = cc;
- edges[edge_count].N1_x = Iface[z].N.x;
- edges[edge_count].N1_y = Iface[z].N.y;
- edges[edge_count].N1_z = Iface[z].N.z;
- ftable* fp = sharings[aa].p;
- int d = 0;
- for(; d<sharings[aa].numfaces; d++, fp++) {
- if(z==fp->fi) continue;
- iface& face = Iface[fp->fi];
- if((face.a==aa&&face.b==cc)||(face.a==cc&&face.b==aa)) {
- face.ab_done = true;
- edges[edge_count].N2_x = face.N.x;
- edges[edge_count].N2_y = face.N.y;
- edges[edge_count].N2_z = face.N.z;
- break;
- }
- if((face.a==aa&&face.c==cc)||(face.a==cc&&face.c==aa)) {
- face.ac_done = true;
- edges[edge_count].N2_x = face.N.x;
- edges[edge_count].N2_y = face.N.y;
- edges[edge_count].N2_z = face.N.z;
- break;
- }
- if((face.b==aa&&face.c==cc)||(face.b==cc&&face.c==aa)) {
- face.bc_done = true;
- edges[edge_count].N2_x = face.N.x;
- edges[edge_count].N2_y = face.N.y;
- edges[edge_count].N2_z = face.N.z;
- break;
- }
- }
- if(d==sharings[aa].numfaces) {
- edges[edge_count].N2_x = -Iface[z].N.x;
- edges[edge_count].N2_y = -Iface[z].N.y;
- edges[edge_count].N2_z = -Iface[z].N.z;
- }
- edge_count++;
- }
- // BC edge
- if(!Iface[z].bc_done) {
- Iface[z].bc_done = true;
- edges[edge_count].a = bb;
- edges[edge_count].b = cc;
- edges[edge_count].N1_x = Iface[z].N.x;
- edges[edge_count].N1_y = Iface[z].N.y;
- edges[edge_count].N1_z = Iface[z].N.z;
- ftable* fp = sharings[bb].p;
- int d = 0;
- for(; d<sharings[bb].numfaces; d++, fp++) {
- if(z==fp->fi) continue;
- iface& face = Iface[fp->fi];
- if((face.a==bb&&face.b==cc)||(face.a==cc&&face.b==bb)) {
- face.ab_done = true;
- edges[edge_count].N2_x = face.N.x;
- edges[edge_count].N2_y = face.N.y;
- edges[edge_count].N2_z = face.N.z;
- break;
- }
- if((face.a==bb&&face.c==cc)||(face.a==cc&&face.c==bb)) {
- face.ac_done = true;
- edges[edge_count].N2_x = face.N.x;
- edges[edge_count].N2_y = face.N.y;
- edges[edge_count].N2_z = face.N.z;
- break;
- }
- if((face.b==bb&&face.c==cc)||(face.b==cc&&face.c==bb)) {
- face.bc_done = true;
- edges[edge_count].N2_x = face.N.x;
- edges[edge_count].N2_y = face.N.y;
- edges[edge_count].N2_z = face.N.z;
- break;
- }
- }
- if(d==sharings[bb].numfaces) {
- edges[edge_count].N2_x = -Iface[z].N.x;
- edges[edge_count].N2_y = -Iface[z].N.y;
- edges[edge_count].N2_z = -Iface[z].N.z;
- }
- edge_count++;
- }
- }
-
- object->Edges(edge_count, edges);
- if (API3DS_TEXT_OUT) cout<< " Edges: " << edge_count << endl;
-
- /*
- * For each vertex we divide the faces sharing it into groups
- * according to the smoothing info. The algorithm used assumes
- * some "good" structure of smoothing data, and cannot handle
- * all the possible (although unprobable) cases.
- */
-
- int vertex_count2 = 0;
- if(smooths) {
- for(int z=0; z<vertex_count; z++) {
- GLuint g = 0;
- ftable* fp = sharings[z].p;
- /*
- * here we try to handle out the faces w/o smoothing info
- */
- for(int d=0; d<sharings[z].numfaces; d++) {
- if(Iface[fp->fi].sgroup==0) {
- g++;
- fp->group = g;
- }
- fp++;
- }
- while(true) {
- /*
- * and from now on just the nice behaving faces
- */
- int r = 0;
- fp = sharings[z].p;
- r = 0;
- for(; r<sharings[z].numfaces; r++) {
- if(!fp->group) break;
- fp++;
- }
- if(r==sharings[z].numfaces) break;
- g++;
- unsigned long cgroup = Iface[fp->fi].sgroup;
- for(; r<sharings[z].numfaces; r++) {
- if(!fp->group)
- if(Iface[fp->fi].sgroup&cgroup)
- fp->group = g;
- fp++;
- }
- }
- sharings[z].splits = g;
- vertex_count2 += g;
- }
- }
- else {
- /*
- * This is for the case when the object is not smoothed at all.
- */
- for(int z=0; z<vertex_count; z++) {
- ftable* fp = sharings[z].p;
- for(int q=1; q<=sharings[z].numfaces; q++) {
- fp->group = q;
- fp++;
- }
- sharings[z].splits = sharings[z].numfaces;
- vertex_count2 += sharings[z].numfaces;
- }
- }
-
- Vertex3DS* vert2 = new Vertex3DS[vertex_count2];
- Vertex3DS* pvert2 = vert2;
- GLuint iiv = 0;
- for(int z=0; z<vertex_count; z++) {
- sharings[z].v = pvert2;
- sharings[z].iv = iiv;
- for(int q=sharings[z].splits; q; q--) {
- *pvert2 = vert[z];
- pvert2++;
- iiv++;
- }
- }
-
- iface Iface2[face_count];
- for(int z=0; z<face_count; z++)
- Iface2[z] = Iface[z];
-
- for(int z=0; z<vertex_count; z++) {
- ftable* fp = sharings[z].p;
- for(int q=0; q<sharings[z].numfaces; q++) {
- iface* pi_src = &Iface2[fp->fi];
- iface* pi_dst = &Iface[fp->fi];
- GLuint sv = sharings[z].iv + fp->group - 1;
- if(z==pi_src->a) pi_dst->a = sv;
- if(z==pi_src->b) pi_dst->b = sv;
- if(z==pi_src->c) pi_dst->c = sv;
- fp++;
- }
- }
-
- if (API3DS_TEXT_OUT) cout<< " Before: "<<vertex_count*3<<" After: "<<vertex_count2<<endl;
-
- iface* pif = Iface;
- for(int z=0; z<face_count; z++, pif++) {
- GLfloat nx = (pif->N).x;
- GLfloat ny = (pif->N).y;
- GLfloat nz = (pif->N).z;
- GLuint aa = pif->a;
- GLuint bb = pif->b;
- GLuint cc = pif->c;
- vert2[aa].i += nx;
- vert2[aa].j += ny;
- vert2[aa].k += nz;
- vert2[bb].i += nx;
- vert2[bb].j += ny;
- vert2[bb].k += nz;
- vert2[cc].i += nx;
- vert2[cc].j += ny;
- vert2[cc].k += nz;
- }
- for(int z=0; z<vertex_count2; z++) {
- GLfloat len = 1.0/sqrt(vert2[z].i*vert2[z].i +
- vert2[z].j*vert2[z].j +
- vert2[z].k*vert2[z].k);
- vert2[z].i *= len;
- vert2[z].j *= len;
- vert2[z].k *= len;
- }
-
- object->Vertices(vertex_count2, vert2);
-
- List<chunk3ds> pmlist(subchunks_by_type(pfaceschunk, FACES_MATERIALS, (char *)(pfaces+face_count)));
- if(pmlist.size()!=0) if (API3DS_TEXT_OUT) cout<<" Materials: ";
- pmlist.rewind();
- GLuint* pind;
- for(int q=pmlist.size(); q; q--)
- {
- p = (*pmlist).ptr;
- ++pmlist;
- if (API3DS_TEXT_OUT) cout<<(const char *)(p+6);
- Material3DS *matpointer = scene->GetMaterial((const char *)(p+6));
- if(matpointer->Transparency()==50)
- istransparent = true;
- p+=6;
- while(*p) p++; p++;
- int mapped = getshort(p);
- if(!mapped)
- // this really happens
- continue;
- if (API3DS_TEXT_OUT) cout<<" ("<<mapped<<"), ";
- p+=2;
-
- pind = new GLuint[mapped*3];
- object->AddFaceGroup(matpointer, mapped, pind);
- for(int w=mapped; w; w--, p+=2) {
- iface* pif = Iface+getshort(p);
- pif->hasmaterial = true;
- *pind = pif->a; pind++;
- *pind = pif->b; pind++;
- *pind = pif->c; pind++;
- }
- }
- if(pmlist.size()!=0)
- if (API3DS_TEXT_OUT) cout<<endl;
-
- // DEFAULT material (for faces without assigned material)
-
- int wo_material = 0;
- for(int w=0; w<face_count; w++)
- if(!(Iface[w].hasmaterial))
- wo_material++;
- if(wo_material) {
- pind = new GLuint[wo_material*3];
- Material3DS *defmat = scene->GetMaterial("____DEFAULT_MATERIAL");
- object->AddFaceGroup(defmat, wo_material, pind);
- for(int w=0; w<face_count; w++) {
- iface* pif = Iface+w;
- if(!(pif->hasmaterial)) {
- *pind = pif->a; pind++;
- *pind = pif->b; pind++;
- *pind = pif->c; pind++;
- }
- }
- }
-
- if(istransparent)
- transparent_objects+=object;
- else
- scene->Add(object);
-
- }
-
- continue;
- }
-
- // light
- if(find_chunk(po, LIGHT, pi))
- {
- if (API3DS_TEXT_OUT) cout << "A light." << endl;
- p = find_chunk(po, LIGHT, pi);
- char *vec = p+6;
- char *prgb = find_chunk(p, RGBfloat, p+18)+6;
- if (API3DS_TEXT_OUT) cout<<" Position: ("
- << getfloat(vec) <<", "
- << getfloat(vec+4) <<", "
- << getfloat(vec+8) << ")" << endl;
- if (API3DS_TEXT_OUT) cout<<" Color: ("
- <<(int)(256*getfloat(prgb))<<", "
- <<(int)(256*getfloat(prgb+4))<<", "
- <<(int)(256*getfloat(prgb+8))<< ")" << endl;
- OmniLight3DS* light = new OmniLight3DS;
- light->Name(pname);
- scene->Add(light);
- light->Position(getfloat(vec), getfloat(vec+4), getfloat(vec+8));
- light->Diffuse(getfloat(prgb), getfloat(prgb+4), getfloat(prgb+8));
- /*
- if(FindChunk(plights, LIGHT_OFF, plights+18))
- {
- newlight->state = 0;
- printf(" OFF");
- }
- */
- continue;
- }
-
- // object identified as a camera
- if(find_chunk(po, CAMERA, pi))
- {
- if (API3DS_TEXT_OUT) cout << "A camera." << endl;
- CameraTarget3DS *camera = new CameraTarget3DS;
- camera->Name(pname);
- scene->Add(camera);
- p = find_chunk(po, CAMERA, pi);
- char *vec = p+6;
- if (API3DS_TEXT_OUT) cout<<" Origin: ("
- << getfloat(vec) <<", "
- << getfloat(vec+4) <<", "
- << getfloat(vec+8) << ")" << endl;
- camera->Origin(getfloat(vec), getfloat(vec+4), getfloat(vec+8));
- vec+=12;
- if (API3DS_TEXT_OUT) cout<<" Target: ("
- << getfloat(vec) <<", "
- << getfloat(vec+4) <<", "
- << getfloat(vec+8) << ")" << endl;
- camera->Target(getfloat(vec), getfloat(vec+4), getfloat(vec+8));
- vec+=12;
- if (API3DS_TEXT_OUT) cout<<" Bank: "<<getfloat(vec)<<endl;
- vec+=4;
- if (API3DS_TEXT_OUT) cout<<" Lens: "<<getfloat(vec)<<endl;
- continue;
- }
-
- }
-
- scene->Add(transparent_objects);
-
- if (API3DS_TEXT_OUT) cout << endl;
-
- // Keyframer chunk
- // ------------------------------------------------------------------
-
- char *keyframer = find_chunk(pmesh, KEYFRAMER_CHUNK, pmesh+6);
- if(!keyframer) {
- throw 1;
- }
- if (API3DS_TEXT_OUT) cout << "Keyframer data:" << endl << endl;
-
- p = find_chunk(keyframer, FRAMES, keyframer+6);
- if(!p) {
- throw 1;
- }
- if (API3DS_TEXT_OUT) cout << "Animation frames: "<<(int)getlong(p+6)<<" to "<<(int)getlong(p+10)<<"."<<endl;
- int frames_start = (int)getlong(p+6);
- int frames_end = (int)getlong(p+10);
- int frames = frames_end-frames_start + 1;
- scene->Frames(frames);
-
- List<chunk3ds> camo(subchunks_by_type(keyframer, CAMERA_INFORMATION_BLOCK, keyframer+6));
- camo.rewind();
- for(int nc=camo.size(); nc; nc--)
- {
- if (API3DS_TEXT_OUT) cout << "Camera origin info block:" << endl;
- char *info = (*camo).ptr;
- ++camo;
-
- char *objinfo = find_chunk(info, OBJECT_INFO, info+6);
- pname = (const char *)(objinfo+6);
- if (API3DS_TEXT_OUT) cout << " Camera: " << pname << endl;
- CameraTarget3DS *camera = dynamic_cast<CameraTarget3DS*>(scene->GetCamera(pname));
- unsigned short flag, tracktype;
- unsigned long keys;
-
- char *track = find_chunk(info, POSITION_TRACK, info+6);
- if(track) {
- track+=6;
- flag = getshort(track);
- if (API3DS_TEXT_OUT) cout << " track type: ";
- track_type_info(flag);
- if (API3DS_TEXT_OUT) cout << endl;
- tracktype = flag;
-
- track+=10;
- if (API3DS_TEXT_OUT) cout << " Position keys: " << (int)getlong(track) << endl;
- keys = (int)getlong(track);
- track+=4;
-
- Dynamic<Vector3f, GLfloat> *newtrack = process_position_track(frames, keys, track, tracktype);
- if(newtrack)
- camera->Origin(newtrack, true);
- }
-
- track = find_chunk(info, ROLL_TRACK, info+6);
- if(track) {
- track+=6;
- flag = getshort(track);
- if (API3DS_TEXT_OUT) cout << " track type: ";
- track_type_info(flag);
- if (API3DS_TEXT_OUT) cout << endl;
- tracktype = flag;
-
- track+=10;
- if (API3DS_TEXT_OUT) cout << " Roll keys: " << (int)getlong(track) << endl;
- keys = (int)getlong(track);
- track+=4;
-
- Dynamic<GLfloat, GLfloat> *newtrack = process_roll_track(frames, keys, track, tracktype);
- if(newtrack)
- camera->Roll(newtrack, true);
- }
-
- }
-
- List<chunk3ds> camt(subchunks_by_type(keyframer, CAMERA_TARGET_INFORMATION_BLOCK, keyframer+6));
- camt.rewind();
- for(int nc=camt.size(); nc; nc--)
- {
- if (API3DS_TEXT_OUT) cout << "Camera target info block:" << endl;
- char *info = (*camt).ptr;
- ++camt;
-
- char *objinfo = find_chunk(info, OBJECT_INFO, info+6);
- pname = (const char *)(objinfo+6);
- if (API3DS_TEXT_OUT) cout << " Camera: " << pname << endl;
-
- char *track = find_chunk(info, POSITION_TRACK, info+6);
- if(!track)
- continue;
-
- track+=6;
- unsigned short flag = getshort(track);
- if (API3DS_TEXT_OUT) cout << " track type: ";
- track_type_info(flag);
- if (API3DS_TEXT_OUT) cout << endl;
- unsigned short tracktype = flag;
-
- track+=10;
- if (API3DS_TEXT_OUT) cout << " Position keys: " << (int)getlong(track) << endl;
- unsigned long keys = (int)getlong(track);
- track+=4;
-
- Dynamic<Vector3f, GLfloat> *newtrack = process_position_track(frames, keys, track, tracktype);
- if(!newtrack)
- continue;
-
- CameraTarget3DS *camera = dynamic_cast<CameraTarget3DS*>(scene->GetCamera(pname));
- if(!camera)
- continue;
- camera->Target(newtrack, true);
- }
-
- List<chunk3ds> caml(subchunks_by_type(keyframer, OMNI_LIGHT_INFORMATION_BLOCK, keyframer+6));
- caml.rewind();
- for(int nc=caml.size(); nc; nc--)
- {
- if (API3DS_TEXT_OUT) cout << "Omnilight info block:" << endl;
- char *info = (*caml).ptr;
- ++caml;
-
- char *objinfo = find_chunk(info, OBJECT_INFO, info+6);
- pname = (const char *)(objinfo+6);
- if (API3DS_TEXT_OUT) cout << " Omnilight: " << pname << endl;
-
- Dynamic<Vector3f, GLfloat> *newtrack;
-
- unsigned short flag, tracktype;
- unsigned long keys;
-
- OmniLight3DS *light = dynamic_cast<OmniLight3DS*>(scene->GetLight(pname));
-
- char *track = find_chunk(info, POSITION_TRACK, info+6);
- if(track) {
- track+=6;
- flag = getshort(track);
- if (API3DS_TEXT_OUT) cout << " track type: ";
- track_type_info(flag);
- if (API3DS_TEXT_OUT) cout << endl;
- tracktype = flag;
-
- track+=10;
- if (API3DS_TEXT_OUT) cout << " Position keys: " << (int)getlong(track) << endl;
- keys = (unsigned long)getlong(track);
- track+=4;
-
- newtrack = process_position_track(frames, keys, track, tracktype);
- if(newtrack)
- light->Position(newtrack, true);
- }
-
- track = find_chunk(info, COLOR_TRACK, info+6);
- if(track) {
- track+=6;
- flag = getshort(track);
- if (API3DS_TEXT_OUT) cout << " track type: ";
- track_type_info(flag);
- if (API3DS_TEXT_OUT) cout << endl;
- tracktype = flag;
-
- track+=10;
- if (API3DS_TEXT_OUT) cout << " Color keys: " << (int)getlong(track) << endl;
- keys = (unsigned long)getlong(track);
- track+=4;
-
- newtrack = process_position_track(frames, keys, track, tracktype);
- if(newtrack)
- light->Diffuse(newtrack, true);
- }
-
- }
-
- throw 1;
- }
- catch(int value) {
- if(take_care_of_buf_alloc) {
- delete[] buffer;
- buffer = 0;
- }
- return scene;
- }
- }
-
- inline float
- hermite_spline(float t, float P1, float R1, float P2, float R2) {
- return P1*(2*t*t*t - 3*t*t + 1) +
- R1*(t*t*t - 2*t*t + t) +
- P2*(-2*t*t*t + 3*t*t) +
- R2*(t*t*t - t*t);
- }
-
- Vector3f Loader3DS::position_track::getv(int sel, int n) {
- position_key *kn_1, *kn, *kn1;
- Vector3f *pn_1, *pn, *pn1;
- int d1, d2;
-
- kn = &keys[n];
- pn = &kn->p;
-
- if (sel == point) return *pn;
-
- if (n == 0) {
- //first key
- kn1 = &keys[1];
- pn1 = &kn1->p;
-
- if (count == 2) {
- //2 keys
- return (*pn1 - *pn)*(1.0F - kn->tension);
- };
- if (mode != 3) {
- //first key, no loop
- return ((*pn1 - *pn)*1.5F - getv(an,1)*0.5F)*(1.0F - kn->tension);
- } else {
- //first key, loop
- kn_1= &keys[count-2];
- d1 = keys[count-1].frame - kn_1->frame;
- d2 = kn1->frame - kn->frame;
- };
- } else if (n == count-1) {
- //last key
- kn_1 = &keys[n-1];
- pn_1 = &kn_1->p;
-
- if (count == 2) {
- //2 keys
- return (*pn - *pn_1)*(1.0F - kn->tension);
- };
- if (mode != 3) {
- //last key, no loop
- return ((*pn - *pn_1)*1.5F - getv(bn,n-1)*0.5F)*(1.0F - kn->tension);
- } else {
- //last key, loop
- kn1 = &keys[1];
- d1 = kn->frame - kn_1->frame;
- d2 = kn1->frame - keys[0].frame;
- };
- } else {
- //middle keys
- kn_1= &keys[n-1];
- kn1 = &keys[n+1];
- d1 = kn->frame - kn_1->frame;
- d2 = kn1->frame - kn->frame;
- };
- pn_1= &kn_1->p;
- pn1 = &kn1->p;
-
- float C;
- float adjust;
-
- if (sel == an) {
- C = kn->continuity;
- adjust = d1;
- } else {
- C = -kn->continuity;
- adjust = d2;
- };
- adjust /= d1 + d2;
- adjust = 0.5 + (1.0 - fabs(C))*(adjust - 0.5);
-
- return ( (*pn - *pn_1) * ((1.0F + kn->bias)*(1.0F - C))
- + (*pn1 - *pn ) * ((1.0F - kn->bias)*(1.0F + C))
- ) * ((1.0F - kn->tension)*adjust);
- };
-
- Dynamic<Vector3f, GLfloat>* Loader3DS::process_position_track(int allframes, int keys, char *track, unsigned short tracktype)
- {
- if(keys<2)
- return 0;
-
- position_track keyinfo(keys, tracktype&3);
-
- for(int g=0; g<keys; g++)
- {
- if (API3DS_TEXT_OUT) cout << " Key " << g << ": Frame " << (int)getlong(track) << ".: ";
- keyinfo[g].frame = (int)getlong(track);
- track+=4;
- unsigned short flag = getshort(track);
- tcb_info(flag);
- track = fill_tcbee(flag, track+2, &keyinfo[g]);
- float x = getfloat(track);
- float y = getfloat(track+4);
- float z = getfloat(track+8);
-
- keyinfo[g].p = Vector3f(x, y, z);
-
- if (API3DS_TEXT_OUT) cout << " (" << x << ", " << y << ", " << z << ")" << endl;
- track+=12;
- }
-
- int first_frame = keyinfo[0].frame;
- int last_frame = keyinfo[keys-1].frame;
-
- int frames = last_frame-first_frame + 1;
-
- Vector3f *curve = new Vector3f[frames];
-
- Vector3f t1, t2;
- int k = 0;
- for(int g=first_frame; g<=last_frame; g++)
- {
- if(g>(keyinfo[k+1].frame)) {
- k++;
- }
- int d = keyinfo[k+1].frame - keyinfo[k].frame;
- double t = (double)(g-keyinfo[k].frame)/(double)d;
- t1 = keyinfo.getv(bn, k);
- t2 = keyinfo.getv(an, k+1);
- float xx = hermite_spline(t, (keyinfo[k].p).x, t1.x, (keyinfo[k+1].p).x, t2.x);
- float yy = hermite_spline(t, (keyinfo[k].p).y, t1.y, (keyinfo[k+1].p).y, t2.y);
- float zz = hermite_spline(t, (keyinfo[k].p).z, t1.z, (keyinfo[k+1].p).z, t2.z);
- curve[g-first_frame] = Vector3f(xx, yy, zz);
- }
-
- DvectorLinearFramed<Vector3f, GLfloat> *newtrack = new DvectorLinearFramed<Vector3f, GLfloat>;
- newtrack->Frames(allframes, frames, first_frame, last_frame, curve);
- return newtrack;
- }
-
- GLfloat Loader3DS::roll_track::getv(int sel, int n) {
- roll_key *kn_1, *kn, *kn1;
- GLfloat *pn_1, *pn, *pn1;
- int d1, d2;
-
- kn = &keys[n];
- pn = &kn->p;
-
- if (sel == point) return *pn;
-
- if (n == 0) {
- //first key
- kn1 = &keys[1];
- pn1 = &kn1->p;
-
- if (count == 2) {
- //2 keys
- return (*pn1 - *pn)*(1.0F - kn->tension);
- };
- if (mode != 3) {
- //first key, no loop
- return ((*pn1 - *pn)*1.5F - getv(an,1)*0.5F)*(1.0F - kn->tension);
- } else {
- //first key, loop
- kn_1= &keys[count-2];
- d1 = keys[count-1].frame - kn_1->frame;
- d2 = kn1->frame - kn->frame;
- };
- } else if (n == count-1) {
- //last key
- kn_1 = &keys[n-1];
- pn_1 = &kn_1->p;
-
- if (count == 2) {
- //2 keys
- return (*pn - *pn_1)*(1.0F - kn->tension);
- };
- if (mode != 3) {
- //last key, no loop
- return ((*pn - *pn_1)*1.5F - getv(bn,n-1)*0.5F)*(1.0F - kn->tension);
- } else {
- //last key, loop
- kn1 = &keys[1];
- d1 = kn->frame - kn_1->frame;
- d2 = kn1->frame - keys[0].frame;
- };
- } else {
- //middle keys
- kn_1= &keys[n-1];
- kn1 = &keys[n+1];
- d1 = kn->frame - kn_1->frame;
- d2 = kn1->frame - kn->frame;
- };
- pn_1= &kn_1->p;
- pn1 = &kn1->p;
-
- float C;
- float adjust;
-
- if (sel == an) {
- C = kn->continuity;
- adjust = d1;
- } else {
- C = -kn->continuity;
- adjust = d2;
- };
- adjust /= d1 + d2;
- adjust = 0.5 + (1.0 - fabs(C))*(adjust - 0.5);
-
- return ( (*pn - *pn_1) * ((1.0F + kn->bias)*(1.0F - C))
- + (*pn1 - *pn ) * ((1.0F - kn->bias)*(1.0F + C))
- ) * ((1.0F - kn->tension)*adjust);
- };
-
- Dynamic<GLfloat, GLfloat>* Loader3DS::process_roll_track(int allframes, int keys, char *track, unsigned short tracktype)
- {
- if(keys<2)
- return 0;
-
- roll_track keyinfo(keys, tracktype&3);
-
- for(int g=0; g<keys; g++)
- {
- if (API3DS_TEXT_OUT) cout << " Key " << g << ": Frame " << (int)getlong(track) << ".: ";
- keyinfo[g].frame = (int)getlong(track);
- track+=4;
- unsigned short flag = getshort(track);
- tcb_info(flag);
- track = fill_tcbee(flag, track+2, &keyinfo[g]);
- float x = getfloat(track);
-
- keyinfo[g].p = x;
-
- if (API3DS_TEXT_OUT) cout << " " << x << endl;
- track+=4;
- }
-
- int first_frame = keyinfo[0].frame;
- int last_frame = keyinfo[keys-1].frame;
-
- int frames = last_frame-first_frame + 1;
-
- GLfloat *curve = new GLfloat[frames];
-
- GLfloat t1, t2;
- int k = 0;
- for(int g=first_frame; g<=last_frame; g++)
- {
- if(g>(keyinfo[k+1].frame)) {
- k++;
- }
- int d = keyinfo[k+1].frame - keyinfo[k].frame;
- double t = (double)(g-keyinfo[k].frame)/(double)d;
- t1 = keyinfo.getv(bn, k);
- t2 = keyinfo.getv(an, k+1);
- float xx = hermite_spline(t, keyinfo[k].p, t1, keyinfo[k+1].p, t2);
- curve[g-first_frame] = xx;
- }
-
- DvectorLinearFramed<GLfloat, GLfloat> *newtrack = new DvectorLinearFramed<GLfloat, GLfloat>;
- newtrack->Frames(allframes, frames, first_frame, last_frame, curve);
- return newtrack;
- }
-