home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 February / Chip_2001-02_cd1.bin / bonus / demos / CS / exp / SOURCES / GLENGINE / api3ds.cpp next >
C/C++ Source or Header  |  2000-08-20  |  68KB  |  2,429 lines

  1. /*
  2.  * 3DS API
  3.  *
  4.  * Includes the support needed to render 3D Studio r4 mesh files with 
  5.  * OpenGL. Depends on the ObjGL2 class hierarchy.
  6.  */
  7.  
  8. #include <io.h>
  9. #include <stdio.h>
  10. #include <malloc.h>
  11. #include <fcntl.h>
  12. #include <sys/types.h>
  13. #include <sys/stat.h>
  14. #include <unistd.h>
  15. #include <string.h>
  16.  
  17. #include "api3ds.h"
  18. #include "macros.h"
  19. #include <zlib.h>
  20.  
  21. #define API3DS_TEXT_OUT 1
  22.  
  23. bool Texture3DS::voodoo = false;
  24. bool Texture3DS::lowtextures = false;
  25. char* Loader3DS::buffer = 0;
  26.  
  27. const char* getlastext(const char* s) {
  28.   const char* lastext = 0;
  29.   char c;
  30.   while(c=*s, c) {
  31.     if(c=='.')
  32.       lastext = s+1;
  33.     s++;
  34.   }
  35.   return lastext;
  36. }
  37.  
  38. template <class __type> inline Vector3<__type>
  39. Normalize (const Vector3<__type>& V) {
  40.   __type len = __type(1.0/sqrt(V.x*V.x + V.y*V.y + V.z*V.z));
  41.   return Vector3<__type> (V.x*len, V.y*len, V.z*len);
  42. }
  43.  
  44. template <class __type> inline Vector3<__type>
  45. CrossProduct (const Vector3<__type>& u, const Vector3<__type>& v) {
  46.   return Vector3<__type> (u.y*v.z - u.z*v.y,
  47.                           v.x*u.z - u.x*v.z,
  48.                           u.x*v.y - u.y*v.x);
  49. }
  50.  
  51. template <class __type> inline __type
  52. VectorLength(const Vector3<__type>& u) {
  53.   return (__type)sqrt(u.x*u.x + u.y*u.y + u.z*u.z);
  54. }
  55.  
  56. template <class __type> inline const __type&
  57. Minimum(const __type& a, const __type& b) {
  58.   return (a<b ? a : b);
  59. }
  60.  
  61. void Texture3DS::GL ()
  62. {
  63.   if(Name()==0) {    
  64.     glBindTexture(GL_TEXTURE_2D, 0);
  65.     return;
  66.   }
  67.   if(texture==0)
  68.     glGenTextures(1, &texture);
  69.  
  70.   glBindTexture(GL_TEXTURE_2D, texture);
  71.  
  72.   if(altered) {
  73.     altered = false;
  74.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_s);
  75.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_t);
  76.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter);
  77.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter);
  78.     glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, border_color);
  79.     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_PRIORITY, priority);
  80.   }
  81.   glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, env_mode);
  82.   glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, env_color);
  83.  
  84.   if(!transferred) {
  85.     Image img;
  86.  
  87.     String S = String("DATA\\") + Name();
  88.     if (!img.Load(S())) img.Load(Name()());
  89. /*
  90.     String S(Name());
  91.     FILE* file;
  92.     file = fopen(S(), "rb");
  93.     if(!file) {
  94.       S = String("data\\")+S;
  95.       file = fopen(S(), "rb");
  96.       if(!file) {
  97.        transferred = true;
  98.        return;
  99.       }
  100.     } 
  101.     fclose(file);
  102. */
  103.  
  104.     if(lowtextures) {
  105.       img.Scale(img.width()>>1, img.height()>>1);
  106.     }
  107.     if(voodoo) {
  108.       int nwidth = img.width()>256 ? 256 : img.width();
  109.       int nheight = img.height()>256 ? 256 : img.height();
  110.       if(nwidth!=img.width()||nheight!=img.height())
  111.         img.Scale(nwidth, nheight);
  112.     }
  113.  
  114.     switch(img.format()) {
  115.       case OGL_IMAGE_RGB888:
  116.         img.FlipVertical();
  117.         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  118.         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8,
  119.                      img.width(), img.height(), 0,
  120.                      GL_RGB, GL_UNSIGNED_BYTE, img.data());
  121.   
  122.         if (API3DS_TEXT_OUT) cout << "texture " << Name() << " transferred" << endl;
  123.         break;
  124.  
  125.       case OGL_IMAGE_RGBA8888:
  126.         img.FlipVertical();
  127.         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  128.         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8,
  129.                      img.width(), img.height(), 0,
  130.                      GL_RGBA, GL_UNSIGNED_BYTE, img.data());
  131.   
  132.  
  133.         if (API3DS_TEXT_OUT) cout << "texture " << Name() << " transferred" << endl;
  134.         break;
  135.  
  136.       default:
  137.         if (API3DS_TEXT_OUT) cout << "Bad image type " << img.format() << endl;
  138.         break;
  139.     }
  140.     transferred = true;
  141.   }
  142. }
  143.  
  144. void Textures3DS::GL () {
  145.   __entity_list.rewind();
  146.   for(int i=__entity_list.size(); i; i--) {
  147.     (*__entity_list)->GL();
  148.     ++__entity_list;
  149.   }
  150. }
  151.  
  152. Texture3DS* Textures3DS::GetOrCreate (const char* s) {
  153.   Texture3DS* p = Get(s);
  154.   if(!p) {
  155.     p = new Texture3DS;
  156.     p->Name(s);
  157.     p->MinFilter(GL_LINEAR);
  158.     p->MagFilter(GL_LINEAR);
  159.  
  160.     Add(p);
  161.   }
  162.   return p;
  163. }
  164.  
  165. Material3DS::Material3DS () {
  166.   Reset();
  167. }
  168.  
  169. void Material3DS::Reset () {
  170.   ambient[0] = ambient[1] = ambient[2] = 0.0F; ambient[3] = 1.0F;
  171.   diffuse[0] = diffuse[1] = diffuse[2] = 1.0F; diffuse[3] = 1.0F;
  172.   specular[0] = specular[1] = specular[2] = 0.0F; specular[3] = 1.0F;
  173.  
  174.   shininess_percent = 0; 
  175.   shininess_strenght_percent = 0;
  176.   transparency_percent = 0;
  177.   transparency_falloff_percent = 0;
  178.   self_illumination_percent = 0;
  179.   reflect_blur_percent = 0;
  180.  
  181.   texture1 = 0;
  182.   texture2 = 0;
  183.   opacity_map = 0;
  184.   bump_map = 0;
  185.   specular_map = 0;
  186.   shininess_map = 0;
  187.   self_illum_map = 0;
  188.   reflection_map = 0;
  189. }
  190.  
  191. void Material3DS::GL(GLenum face = GL_FRONT_AND_BACK)
  192. {
  193.   diffuse[3] = 0.6F; // (GLfloat)transparency_percent/100.0
  194.   glMaterialfv(face, GL_AMBIENT, ambient);
  195.   glMaterialfv(face, GL_DIFFUSE, diffuse);
  196.   glMaterialfv(face, GL_SPECULAR, specular);
  197. //  glMaterialf(face, GL_SHININESS, (GLfloat) shininess_percent);
  198.  
  199.   glShadeModel(GL_SMOOTH);
  200.   glEnable(GL_DEPTH_TEST);
  201.  
  202.   if(texture1==0) {
  203.     glDisable(GL_TEXTURE_2D);
  204.   }
  205.   else {
  206.     glEnable(GL_TEXTURE_2D);
  207.     texture1->GL();
  208.   }
  209. }
  210.  
  211. void Material3DS::Ambient (GLfloat r, GLfloat g, GLfloat b) {
  212.   SetVector4(ambient, r, g, b, 1.0F);
  213. }
  214. void Material3DS::Diffuse (GLfloat r, GLfloat g, GLfloat b) {
  215.   SetVector4(diffuse, r, g, b, 1.0F);
  216. }
  217. void Material3DS::Specular (GLfloat r, GLfloat g, GLfloat b) {
  218.   SetVector4(specular, r, g, b, 1.0F);
  219. }
  220. void Material3DS::Ambient (GLfloat* v) {
  221.   SetVector4(ambient, *v, *(v+1), *(v+2), 1.0F);
  222. }
  223. void Material3DS::Diffuse (GLfloat* v) {
  224.   SetVector4(diffuse, *v, *(v+1), *(v+2), 1.0F);
  225. }
  226. void Material3DS::Specular (GLfloat* v) {
  227.   SetVector4(specular, *v, *(v+1), *(v+2), 1.0F);
  228. }
  229. void Material3DS::Ambient (GLubyte r, GLubyte g, GLubyte b) {
  230.   SetVector4(ambient, r, g, b, 255);
  231. }
  232. void Material3DS::Diffuse (GLubyte r, GLubyte g, GLubyte b) {
  233.   SetVector4(diffuse, r, g, b, 255);
  234. }
  235. void Material3DS::Specular (GLubyte r, GLubyte g, GLubyte b) {
  236.   SetVector4(specular, r, g, b, 255);
  237. }
  238. void Material3DS::Ambient (GLubyte* v) {
  239.   SetVector4(ambient, *v, *(v+1), *(v+2), 255);
  240. }
  241. void Material3DS::Diffuse (GLubyte* v) {
  242.   SetVector4(diffuse, *v, *(v+1), *(v+2), 255);
  243. }
  244. void Material3DS::Specular (GLubyte* v) {
  245.   SetVector4(specular, *v, *(v+1), *(v+2), 255);
  246. }
  247.  
  248. void Material3DS::Shininess (GLint i) {
  249.   shininess_percent = i;
  250. }
  251. void Material3DS::ShininessStrenght (GLint i) { 
  252.   shininess_strenght_percent = i;
  253. }
  254. void Material3DS::Transparency (GLint i) {
  255.   transparency_percent = i;
  256. }
  257. void Material3DS::TransparencyFalloff (GLint i) {
  258.   transparency_falloff_percent = i;
  259. }
  260. void Material3DS::SelfIllumination (GLint i) {
  261.   self_illumination_percent = i;
  262. }
  263. void Material3DS::ReflectBlur (GLint i) {
  264.   reflect_blur_percent = i;
  265. }
  266.  
  267. void Material3DS::Texture1 (Texture3DS* t) {
  268.   texture1 = t;
  269. }
  270. void Material3DS::Texture2 (Texture3DS* t) {
  271.   texture2 = t;
  272. }
  273. void Material3DS::OpacityMap (Texture3DS* t) {
  274.   opacity_map = t;
  275. }
  276. void Material3DS::BumpMap (Texture3DS* t) {
  277.   bump_map = t;
  278. }
  279. void Material3DS::SpecularMap (Texture3DS* t) {
  280.   specular_map = t;
  281. }
  282. void Material3DS::ShininessMap (Texture3DS* t) {
  283.   shininess_map = t;
  284. }
  285. void Material3DS::SelfIlluminationMap (Texture3DS* t) {
  286.   self_illum_map = t;
  287. }
  288. void Material3DS::ReflectionMap (Texture3DS* t) {
  289.   reflection_map = t;
  290. }
  291.  
  292. const GLfloat* Material3DS::Ambient () {
  293.   return ambient;
  294. }
  295. const GLfloat* Material3DS::Diffuse () {
  296.   return diffuse;
  297. }
  298. const GLfloat* Material3DS::Specular () {
  299.   return specular;
  300. }
  301. GLint Material3DS::Shininess () {
  302.   return shininess_percent;
  303. }
  304. GLint Material3DS::ShininessStrenght () { 
  305.   return shininess_strenght_percent;
  306. }
  307. GLint Material3DS::Transparency () {
  308.   return transparency_percent;
  309. }
  310. GLint Material3DS::TransparencyFalloff () {
  311.   return transparency_falloff_percent;
  312. }
  313. GLint Material3DS::SelfIllumination () {
  314.   return self_illumination_percent;
  315. }
  316. GLint Material3DS::ReflectBlur () {
  317.   return reflect_blur_percent;
  318. }
  319. Texture3DS* Material3DS::Texture1 () {
  320.   return texture1;
  321. }
  322. Texture3DS* Material3DS::Texture2 () {
  323.   return texture2;
  324. }
  325. Texture3DS* Material3DS::OpacityMap () {
  326.   return opacity_map;
  327. }
  328. Texture3DS* Material3DS::BumpMap () {
  329.   return bump_map;
  330. }
  331. Texture3DS* Material3DS::SpecularMap () {
  332.   return specular_map;
  333. }
  334. Texture3DS* Material3DS::ShininessMap () {
  335.   return shininess_map;
  336. }
  337. Texture3DS* Material3DS::SelfIlluminationMap () {
  338.   return self_illum_map;
  339. }
  340. Texture3DS* Material3DS::ReflectionMap () {
  341.   return reflection_map;
  342. }
  343.  
  344.  
  345. OmniLight3DS::OmniLight3DS () {
  346.   Reset();
  347. }
  348.  
  349. void OmniLight3DS::Reset ()
  350. {
  351.   Diffuse(0.0F, 0.0F, 0.0F);
  352.   Position(0.0F, 0.0F, 0.0F);
  353.   constant_attenuation = 1.0F;
  354.   linear_attenuation = 0.0F;
  355.   quadratic_attenuation = 0.0F;
  356. }
  357.  
  358. void OmniLight3DS::GL (GLenum light, double time = 0.0)
  359. {
  360.   GLfloat a[4];
  361.   a[3] = 1.0F;
  362.   Vector3f v = diffuse.Val(time);
  363.   v.Unpack(a);
  364.   glLightfv(light, GL_DIFFUSE, a);
  365.   v = position.Val(time);
  366.   v.Unpack(a);
  367.   glLightfv(light, GL_POSITION, a);
  368.  
  369.   a[0] = a[1] = a[2] = 0.0F;
  370.   glLightfv(light, GL_SPECULAR, a);
  371.   glLightfv(light, GL_AMBIENT, a);
  372.   glLightf(light, GL_CONSTANT_ATTENUATION, constant_attenuation);
  373.   glLightf(light, GL_LINEAR_ATTENUATION, linear_attenuation);
  374.   glLightf(light, GL_QUADRATIC_ATTENUATION, quadratic_attenuation);
  375. }
  376.  
  377. void OmniLight3DS::Diffuse (GLfloat r, GLfloat g, GLfloat b) {
  378.   diffuse(Vector3f(r, g, b));
  379. }
  380. void OmniLight3DS::Diffuse (GLubyte r, GLubyte g, GLubyte b) {
  381.   diffuse(Vector3f(UBYTE_TO_FLOAT(r), UBYTE_TO_FLOAT(g), UBYTE_TO_FLOAT(b)));
  382. }
  383. void OmniLight3DS::Diffuse (const Vector3f& V) {
  384.   diffuse(V);
  385. }
  386. void OmniLight3DS::Diffuse (Dynamic<Vector3f, GLfloat> *ptr, bool strong = false) {
  387.   diffuse(ptr, strong);
  388. }
  389.  
  390. void OmniLight3DS::Position (GLfloat x, GLfloat y, GLfloat z) {
  391.   position(Vector3f(x, y, z));
  392. }
  393. void OmniLight3DS::Position (const Vector3f& V) {
  394.   position(V);
  395. }
  396. void OmniLight3DS::Position (Dynamic<Vector3f, GLfloat> *ptr, bool strong = false) {
  397.   position(ptr, strong);
  398. }
  399.  
  400. void OmniLight3DS::ConstantAttenuation (GLfloat f) {
  401.   constant_attenuation = f;
  402. }
  403. void OmniLight3DS::LinearAttenuation (GLfloat f) {
  404.   linear_attenuation = f;
  405. }
  406. void OmniLight3DS::QuadraticAttenuation (GLfloat f) {
  407.   quadratic_attenuation = f;
  408. }
  409.  
  410. Vector3f OmniLight3DS::Position (double time = 0.0) {
  411.  return position.Val(time);
  412. }
  413. Vector3f OmniLight3DS::Diffuse (double time = 0.0) {
  414.  return diffuse.Val(time);
  415. }
  416. GLfloat OmniLight3DS::ConstantAttenuation () {
  417.   return constant_attenuation;
  418. }
  419. GLfloat OmniLight3DS::LinearAttenuation () {
  420.   return linear_attenuation;
  421. }
  422. GLfloat OmniLight3DS::QuadraticAttenuation () {
  423.   return quadratic_attenuation;
  424. }
  425.  
  426. Object3DS::~Object3DS () {
  427.   delete[] vertices;
  428.   facegroups.rewind();
  429.   for(int i=facegroups.size(); i; i--) {
  430.     delete (*facegroups).indices;
  431.     ++facegroups;
  432.   }
  433. }
  434.  
  435. BoundingBox BoundVertices (int n, Vertex3DS* p) {
  436.   BoundingBox B;
  437.   GLfloat mx, my, mz, Mx, My, Mz, a1, a2;
  438.   mx = Mx = p->x;
  439.   my = My = p->y;
  440.   mz = Mz = p->z;
  441.   Vertex3DS* p1 = p+1;
  442.  
  443.   for(int i=n-1; i; i--, p++, p1++)
  444.   {
  445.     a1 = p->x;
  446.     a2 = p1->x;
  447.     if(a1<=a2) {
  448.       if(a1<mx) mx=a1;
  449.       if(a2>Mx) Mx=a2;
  450.     }
  451.     else {
  452.       if(a2<mx) mx=a2;
  453.       if(a1>Mx) Mx=a1;
  454.     }
  455.  
  456.     a1 = p->y;
  457.     a2 = p1->y;
  458.     if(a1<=a2) {
  459.       if(a1<my) my=a1;
  460.       if(a2>My) My=a2;
  461.     }
  462.     else {
  463.       if(a2<my) my=a2;
  464.       if(a1>My) My=a1;
  465.     }
  466.  
  467.     a1 = p->z;
  468.     a2 = p1->z;
  469.     if(a1<=a2) {
  470.       if(a1<mz) mz=a1;
  471.       if(a2>Mz) Mz=a2;
  472.     }
  473.     else {
  474.       if(a2<mz) mz=a2;
  475.       if(a1>Mz) Mz=a1;
  476.     }
  477.   }
  478.   B.Corner1(mx, my, mz);
  479.   B.Corner2(Mx, My, Mz);
  480.   return B;
  481. }
  482. /*
  483. void Object3DS::Rays (Vector3f C, Vector3f S, GLfloat I) {
  484.   glDisable(GL_LIGHTING);
  485.   glEnable(GL_DEPTH_TEST);
  486.   glDepthMask(GL_ZERO);
  487.   glDisable(GL_CULL_FACE);
  488.   glBlendFunc(GL_ONE, GL_ONE);
  489.   glEnable(GL_BLEND);
  490.   glDisable(GL_TEXTURE_2D);
  491.  
  492.   Vector3f V1, V2, V3, V4;
  493.  
  494.   glBegin(GL_QUADS);
  495.   Edge3DS* p = edges;
  496.   Vertex3DS* v1;
  497.   Vertex3DS* v2;
  498.   p = edges; 
  499.   for(int z=0; z<numedges; z++, p++) {
  500.     v1 = evertices + p->a;
  501.     v2 = evertices + p->b;
  502.     V1 = Vector3f(v1->x-C.x, v1->y-C.y, v1->z-C.z);
  503.     GLfloat a1 = V1.x*p->N1_x + V1.y*p->N1_y + V1.z*p->N1_z;
  504.     GLfloat a2 = V1.x*p->N2_x + V1.y*p->N2_y + V1.z*p->N2_z;
  505.     if((a1*a2)<0.0) {
  506.       V1 = Vector3f(v1->x-S.x, v1->y-S.y, v1->z-S.z);
  507.       V2 = Vector3f(v2->x-S.x, v2->y-S.y, v2->z-S.z);
  508.       GLfloat len1 = VectorLength(V1);
  509.       GLfloat len2 = VectorLength(V2);
  510.       GLfloat r1 = 1.0/len1;
  511.       GLfloat r2 = 1.0/len2;
  512.       a1*=r1;
  513.       a2*=r2;
  514.       GLfloat obrysovost = Minimum(fabs(a1), fabs(a2));
  515. #define PI2 (PI/2)
  516.       obrysovost=sin(sin(sin(sin(obrysovost*PI2)*PI2)*PI2)*PI2);
  517.  
  518.  
  519.  
  520.       GLfloat i1 = (1.0-len1/I)*obrysovost;
  521.       GLfloat i2 = (1.0-len2/I)*obrysovost;
  522.       if(i1<0.0||i2<0.0) continue;
  523.       len1 = I*r1;
  524.       len2 = I*r2;
  525.       V1 *= len1;
  526.       V2 *= len2;
  527.       V1 += S;
  528.       V2 += S;
  529.       glColor3f(i1, i1, i1);
  530.       glVertex3f(v1->x, v1->y, v1->z);
  531.       glColor3f(i2, i2, i2);
  532.       glVertex3f(v2->x, v2->y, v2->z);    
  533.       glColor3f(0.0F, 0.0F, 0.0F);
  534.       glVertex3f(V2.x, V2.y, V2.z);
  535.       glVertex3f(V1.x, V1.y, V1.z);    
  536.     }
  537.   }
  538.  
  539.   glEnd();
  540.  
  541.   glDisable(GL_CULL_FACE);
  542.   glDisable(GL_BLEND);
  543.   glDepthMask(GL_ONE);
  544.   glEnable(GL_LIGHTING);
  545.   glEnable(GL_DEPTH_TEST);
  546. }
  547. */
  548.  
  549. void Object3DS::Rays (Vector3f C, Vector3f S, GLfloat I, GLenum sfactor, GLenum dfactor) {
  550.   glDisable(GL_LIGHTING);
  551.   glEnable(GL_DEPTH_TEST);
  552.   glDepthMask(GL_ZERO);
  553.   glDisable(GL_CULL_FACE);
  554.   glBlendFunc(sfactor, dfactor);
  555.   glEnable(GL_BLEND);
  556.   glDisable(GL_TEXTURE_2D);
  557.  
  558.   Vector3f V1, V2, V3, V4;
  559.  
  560.   glBegin(GL_QUADS);
  561.   Edge3DS* p = edges;
  562.   Vertex3DS* v1;
  563.   Vertex3DS* v2;
  564.   p = edges; 
  565.   for(int z=0; z<numedges; z++, p++) {
  566.     v1 = evertices + p->a;
  567.     v2 = evertices + p->b;
  568.  
  569.     V1 = Vector3f(v1->x-C.x, v1->y-C.y, v1->z-C.z);
  570.  
  571.     GLfloat a1 = V1.x*p->N1_x + V1.y*p->N1_y + V1.z*p->N1_z;
  572.     GLfloat a2 = V1.x*p->N2_x + V1.y*p->N2_y + V1.z*p->N2_z;
  573.     if((a1*a2)<0.0) {
  574.  
  575.       V2 = Vector3f(v2->x-C.x, v2->y-C.y, v2->z-C.z);
  576.       V3 = Normalize((V1+V2)*0.5F);
  577.       V4 = Normalize(C-S);
  578.       GLfloat d34= Dot(V3, V4);
  579.  
  580.       V1 = Vector3f(v1->x-S.x, v1->y-S.y, v1->z-S.z);
  581.       V2 = Vector3f(v2->x-S.x, v2->y-S.y, v2->z-S.z);
  582.       GLfloat len1 = VectorLength(V1);
  583.       GLfloat len2 = VectorLength(V2);
  584.       GLfloat r1 = 1.0/len1;
  585.       GLfloat r2 = 1.0/len2;
  586.       a1*=r1;
  587.       a2*=r2;
  588. #define PI2 (PI/2)
  589.  
  590.       GLfloat obrysovost = Minimum(fabs(a1), fabs(a2));
  591.       obrysovost=sin(sin(sin(sin(obrysovost*PI2)*PI2)*PI2)*PI2);
  592.  
  593.       obrysovost*=sin(sin(sin(sin(sin(sin(cos(fabs(d34)*PI2)*PI2)*PI2)*PI2)*PI2)*PI2)*PI2);
  594.  
  595.  
  596.       GLfloat i1 = (1.0-len1/I)*obrysovost;
  597.       GLfloat i2 = (1.0-len2/I)*obrysovost;
  598.       if(i1<0.0||i2<0.0) continue;
  599.       len1 = I*r1;
  600.       len2 = I*r2;
  601.       V1 *= len1;
  602.       V2 *= len2;
  603.       V1 += S;
  604.       V2 += S;
  605.       i1*=0.3;
  606.       i2*=0.3;
  607.       glColor3f(i1, i1, i1);
  608.       glVertex3f(v1->x, v1->y, v1->z);
  609.       glColor3f(i2, i2, i2);
  610.       glVertex3f(v2->x, v2->y, v2->z);    
  611.       glColor3f(0.0F, 0.0F, 0.0F);
  612.       glVertex3f(V2.x, V2.y, V2.z);
  613.       glVertex3f(V1.x, V1.y, V1.z);    
  614.     }
  615.   }
  616.  
  617.   glEnd();
  618.  
  619.   glDisable(GL_CULL_FACE);
  620.   glDisable(GL_BLEND);
  621.   glDepthMask(GL_ONE);
  622.   glEnable(GL_LIGHTING);
  623.   glEnable(GL_DEPTH_TEST);
  624. }
  625.  
  626. void Object3DS::ShadowVolume (Vector3f S, Vector3f C, GLfloat I, int j) {
  627.   glDisable(GL_LIGHTING);
  628.   glEnable(GL_DEPTH_TEST);
  629.   glDepthMask(GL_ZERO);
  630. //  glEnable(GL_CULL_FACE);
  631.   glDisable(GL_CULL_FACE);
  632.   glDisable(GL_BLEND);
  633.  
  634.   glBlendFunc(GL_ONE, GL_ONE);
  635.   glEnable(GL_BLEND);
  636.  
  637.   float cler=0.0;
  638.   glDisable(GL_TEXTURE_2D);
  639.  
  640.   Vector3f V1, V2, V3;
  641.  
  642.   glBegin(GL_QUADS);
  643.   Edge3DS* p = edges;
  644.   Vertex3DS* v1;
  645.   Vertex3DS* v2;
  646.   p = edges; 
  647.   for(int z=0; z<numedges; z++, p++) {
  648.     v1 = evertices + p->a;
  649.     v2 = evertices + p->b;
  650.  
  651.     V1 = Vector3f(v1->x-S.x, v1->y-S.y, v1->z-S.z);
  652.     V3 = Vector3f(v1->x-C.x, v1->y-C.y, v1->z-C.z);
  653.  
  654.     GLfloat a1 = V1.x*p->N1_x + V1.y*p->N1_y + V1.z*p->N1_z;
  655.     GLfloat a2 = V1.x*p->N2_x + V1.y*p->N2_y + V1.z*p->N2_z;
  656.     Vector3f n1=Vector3f( p->N1_x+p->N2_x, p->N1_y+p->N2_y, p->N1_z+p->N2_z)*0.5F;
  657.     Vector3f n2=Vector3f( v1->x-v2->x,  v1->y-v2->y,  v1->z-v2->z);
  658.     Vector3f n3=Cross(n2,V1);
  659.     if ( Dot(n3,n1)<0.0 ) n3=-n3;
  660.  
  661.     GLfloat a3= (V3.x*n3.x + V3.y*n3.y + V3.z*n3.z)*j;
  662.  
  663.     if (a3>0.0)
  664.     if((a1*a2)<0.0) {
  665.  
  666.       V2 = Vector3f(v2->x-S.x, v2->y-S.y, v2->z-S.z);
  667.  
  668.  
  669.       float len1 = (I/sqrt(V1.x*V1.x + V1.y*V1.y + V1.z*V1.z));
  670.       V1.x=V1.x*len1 + v1->x;
  671.       V1.y=V1.y*len1 + v1->y;
  672.       V1.z=V1.z*len1 + v1->z;
  673.  
  674.       float len2 = (I/sqrt(V2.x*V2.x + V2.y*V2.y + V2.z*V2.z));
  675.       V2.x=V2.x*len2 + v2->x;
  676.       V2.y=V2.y*len2 + v2->y;
  677.       V2.z=V2.z*len2 + v2->z;
  678.  
  679.  
  680.  
  681.       glColor3f(cler,cler,cler);
  682.       glVertex3f(v1->x, v1->y, v1->z);
  683.       glVertex3f(v2->x, v2->y, v2->z);    
  684.       glVertex3f(V2.x, V2.y, V2.z);
  685.       glVertex3f(V1.x, V1.y, V1.z);    
  686.     }
  687.   }
  688.  
  689.   glEnd();
  690.  
  691.   glDisable(GL_CULL_FACE);
  692.   glDisable(GL_BLEND);
  693.   glDepthMask(GL_ONE);
  694.   glEnable(GL_LIGHTING);
  695.   glEnable(GL_DEPTH_TEST);
  696. }
  697.  
  698.  
  699. void Object3DS::ShortLine ( Vector3f C, GLfloat W, GLfloat r, GLfloat g, GLfloat b) {
  700.   glDisable(GL_LIGHTING);
  701.   glDisable(GL_CULL_FACE);
  702. //  glDisable(GL_BLEND);
  703.   glDisable(GL_TEXTURE_2D);
  704.   glLineWidth(W);
  705.   Vector3f V1;
  706.  
  707.   glBegin(GL_LINES);
  708.   glColor3f(r,g,b);
  709.  
  710.   Edge3DS* p = edges;
  711.   Vertex3DS* v1;
  712.   Vertex3DS* v2;
  713.   p = edges; 
  714.   float total=0.0;
  715.   for(int z=0; z<numedges; z++, p++) {
  716.     v1 = evertices + p->a;
  717.     v2 = evertices + p->b;
  718.     V1 = Normalize( Vector3f(v1->x-C.x, v1->y-C.y, v1->z-C.z) );
  719.     GLfloat a1 = V1.x*p->N1_x + V1.y*p->N1_y + V1.z*p->N1_z;
  720.     GLfloat a2 = V1.x*p->N2_x + V1.y*p->N2_y + V1.z*p->N2_z;
  721. //    if((a1>=0.0)&&(a2>=0.0))
  722. //    if((a1<=0.0)&&(a2<=0.0))
  723.       {
  724.       glVertex3f(v1->x, v1->y, v1->z);
  725.       glVertex3f(v2->x, v2->y, v2->z);    
  726.       }
  727.     //cout << "Vertex " << z << ": " << p->a << "," << p->b << endl;
  728.     total++;
  729.     }
  730.   glEnd();
  731.   //cout << "Shortline total: " << total << endl;
  732.   glEnable(GL_CULL_FACE);
  733.   glDepthMask(GL_ONE);
  734.   glEnable(GL_LIGHTING);
  735.   glEnable(GL_DEPTH_TEST);
  736. }
  737.  
  738.  
  739. void DrawLongLine(float x1,float y1, float x2, float y2)
  740. {
  741. float xl,yl;
  742. float xr,yr;
  743. float xu,yu;
  744. float xd,yd;
  745. int   l,r,u,d;
  746. float a;
  747.  
  748. l=r=u=d=0;
  749. float dx=x2-x1;
  750. float dy=y2-y1;
  751.  
  752.  
  753. if (dx!=0) 
  754.   { 
  755.   a=( 1.0-x2)/dx;
  756.   xr=1.0;
  757.   yr=y2+a*dy;
  758.   if ((yr<1.0)&&(yr>=-1.0)) r=1;
  759.  
  760.   a=(-1.0-x2)/dx;
  761.   xl=-1.0;
  762.   yl=y2+a*dy;
  763.   if ((yl<=1.0)&&(yl>-1.0)) l=1;
  764.   }
  765.  
  766. if (dy!=0) 
  767.   { 
  768.   a=( 1.0-y2)/dy;
  769.   yu=1.0;
  770.   xu=x2+a*dx;
  771.   if ((xu<=1.0)&&(xu>-1.0)) u=1;
  772.  
  773.   a=(-1.0-y2)/dy;
  774.   yd=-1.0;
  775.   xd=x2+a*dx;
  776.   if ((xd<1.0)&&(xd>=-1.0)) d=1;
  777.   }
  778.  
  779.   if (l) glVertex2f(xl,yl);
  780.   if (r) glVertex2f(xr,yr);
  781.   if (u) glVertex2f(xu,yu);
  782.   if (d) glVertex2f(xd,yd);
  783. }
  784.  
  785.  
  786. void Object3DS::LongLine ( Vector3f ang, Vector3f pos, GLfloat scale, GLfloat w, GLfloat r, GLfloat g, GLfloat b)
  787. {
  788.   glLineWidth(w);
  789.  
  790.   GLmatrix m=Euler2Matrix(ang.x,ang.y,ang.z);
  791.  
  792.   glMatrixMode(GL_PROJECTION);
  793.   glPushMatrix();
  794.   glLoadIdentity();
  795.   glMatrixMode(GL_MODELVIEW);
  796.   glPushMatrix();
  797.   glLoadIdentity();
  798.  
  799.  
  800.   glBegin(GL_LINES);
  801.   glColor3f(r,g,b);
  802.  
  803.   Edge3DS* p = edges;
  804.   Vertex3DS* v1;
  805.   Vertex3DS* v2;
  806.   Vector2f sc1,sc2;
  807.   p = edges; 
  808.   for(int z=0; z<numedges; z++, p++) {
  809.       v1 = evertices + p->a;
  810.       v2 = evertices + p->b;
  811.  
  812.       Vector4f t1(v1->x,v1->y,v1->z,1.0F); 
  813.       Vector4f t2(v2->x,v2->y,v2->z,1.0F); 
  814.  
  815.       m.MultVertex4f(t1.x,t1.y,t1.z,t1.w);
  816.       m.MultVertex4f(t2.x,t2.y,t2.z,t2.w);
  817.  
  818.       sc1= Vector2f(pos.x+ scale*t1.x/ (t1.z+pos.z), pos.y+ scale*t1.y/ (t1.z+pos.z));
  819.       sc2= Vector2f(pos.x+ scale*t2.x/ (t2.z+pos.z), pos.y+ scale*t2.y/ (t2.z+pos.z));
  820.  
  821.     DrawLongLine(sc1.x,sc1.y,sc2.x,sc2.y);
  822.     }
  823.   glEnd();
  824.  
  825.   glPopMatrix();
  826.   glMatrixMode(GL_PROJECTION);
  827.   glPopMatrix();
  828.   glMatrixMode(GL_MODELVIEW);
  829.  
  830. }
  831.  
  832.  
  833. void Object3DS::ShortLine ( Vector3f ang, Vector3f pos, GLfloat scale, GLfloat w, GLfloat r, GLfloat g, GLfloat b)
  834. {
  835.   glLineWidth(w);
  836.  
  837.   GLmatrix m=Euler2Matrix(ang.x,ang.y,ang.z);
  838.  
  839.   glMatrixMode(GL_PROJECTION);
  840.   glPushMatrix();
  841.   glLoadIdentity();
  842.   glMatrixMode(GL_MODELVIEW);
  843.   glPushMatrix();
  844.   glLoadIdentity();
  845.  
  846.  
  847.   glBegin(GL_LINES);
  848.   glColor3f(r,g,b);
  849.  
  850.   Edge3DS* p = edges;
  851.   Vertex3DS* v1;
  852.   Vertex3DS* v2;
  853.   Vector2f sc1,sc2;
  854.   p = edges; 
  855.   for(int z=0; z<numedges; z++, p++) {
  856.     v1 = evertices + p->a;
  857.     v2 = evertices + p->b;
  858.  
  859.  
  860.       Vector4f t1(v1->x,v1->y,v1->z,1.0F); 
  861.       Vector4f t2(v2->x,v2->y,v2->z,1.0F); 
  862.  
  863.       m.MultVertex4f(t1.x,t1.y,t1.z,t1.w);
  864.       m.MultVertex4f(t2.x,t2.y,t2.z,t2.w);
  865.  
  866.       sc1= Vector2f(pos.x+ scale*t1.x/ (t1.z+pos.z), pos.y+ scale*t1.y/ (t1.z+pos.z));
  867.       sc2= Vector2f(pos.x+ scale*t2.x/ (t2.z+pos.z), pos.y+ scale*t2.y/ (t2.z+pos.z));
  868.       glVertex2f(sc1.x, sc1.y);
  869.       glVertex2f(sc2.x, sc2.y);    
  870.  
  871.     }
  872.   glEnd();
  873.  
  874.   glPopMatrix();
  875.   glMatrixMode(GL_PROJECTION);
  876.   glPopMatrix();
  877.   glMatrixMode(GL_MODELVIEW);
  878.  
  879. }
  880.  
  881.  
  882. void Object3DS::Outline ( Vector3f C, GLfloat W, GLfloat r, GLfloat g, GLfloat b) {
  883.   glDisable(GL_LIGHTING);
  884.   glDisable(GL_DEPTH_TEST);
  885. //  glDepthMask(GL_ZERO);
  886.   glDisable(GL_CULL_FACE);
  887. //  glDisable(GL_BLEND);
  888.   glDisable(GL_TEXTURE_2D);
  889.   glLineWidth(W);
  890.   Vector3f V1;
  891.  
  892.   glBegin(GL_LINES);
  893.   glColor3f(r,g,b);
  894.  
  895.   Edge3DS* p = edges;
  896.   Vertex3DS* v1;
  897.   Vertex3DS* v2;
  898.   p = edges; 
  899.   float total=0.0;
  900.   float outl=0.0;
  901.   float other=0.0;
  902.  
  903.   for(int z=0; z<numedges; z++) {
  904.     v1 = evertices + p->a;
  905.     v2 = evertices + p->b;
  906.     V1 = Normalize( Vector3f(v1->x-C.x, v1->y-C.y, v1->z-C.z) );
  907.     GLfloat a1 = V1.x*p->N1_x + V1.y*p->N1_y + V1.z*p->N1_z;
  908.     GLfloat a2 = V1.x*p->N2_x + V1.y*p->N2_y + V1.z*p->N2_z;
  909.     if((a1*a2)<0.0)
  910.       {
  911. //      GLfloat obr = Minimum(fabs(a1), fabs(a2));
  912. //      obr=sin(sin(sin(sin(obr*PI2)*PI2)*PI2)*PI2);
  913. //      glColor3f(obr,obr,obr);
  914.       glVertex3f(v1->x, v1->y, v1->z);
  915.       glVertex3f(v2->x, v2->y, v2->z);    
  916.       outl++;
  917.       } else other++;
  918.     total++;
  919.     p++;
  920.     }
  921.   glEnd();
  922.   //cout << "Longline total: " << total << "  good: " << outl << "  bad: " << other << endl;
  923.   //if (total>numedges) cout << "error 1" << endl;
  924.   //if (total!=outl+other) cout << "error 2" << endl;
  925.   glEnable(GL_CULL_FACE);
  926.   glDepthMask(GL_ONE);
  927.   glEnable(GL_LIGHTING);
  928.   glEnable(GL_DEPTH_TEST);
  929. }
  930.  
  931.  
  932. void Object3DS::Inline ( Vector3f C, GLfloat W, GLfloat r, GLfloat g, GLfloat b) {
  933.   glDisable(GL_LIGHTING);
  934.   glDisable(GL_DEPTH_TEST);
  935. //  glDepthMask(GL_ZERO);
  936.   glDisable(GL_CULL_FACE);
  937. //  glDisable(GL_BLEND);
  938.   glDisable(GL_TEXTURE_2D);
  939.   glLineWidth(W);
  940.   Vector3f V1;
  941.  
  942.   glBegin(GL_LINES);
  943.   glColor3f(r,g,b);
  944.  
  945.   Edge3DS* p = edges;
  946.   Vertex3DS* v1;
  947.   Vertex3DS* v2;
  948.   p = edges; 
  949.   float total=0.0;
  950.   float outl=0.0;
  951.   float other=0.0;
  952.  
  953.   for(int z=0; z<numedges; z++) {
  954.     v1 = evertices + p->a;
  955.     v2 = evertices + p->b;
  956.     V1 = Normalize( Vector3f(v1->x-C.x, v1->y-C.y, v1->z-C.z) );
  957.     GLfloat a1 = V1.x*p->N1_x + V1.y*p->N1_y + V1.z*p->N1_z;
  958.     GLfloat a2 = V1.x*p->N2_x + V1.y*p->N2_y + V1.z*p->N2_z;
  959.     if((a1*a2)>=0.0)
  960.       {
  961. //      GLfloat obr = Minimum(fabs(a1), fabs(a2));
  962. //      obr=sin(sin(sin(sin(obr*PI2)*PI2)*PI2)*PI2);
  963. //      glColor3f(obr,obr,obr);
  964.       glVertex3f(v1->x, v1->y, v1->z);
  965.       glVertex3f(v2->x, v2->y, v2->z);    
  966.       outl++;
  967.       } else other++;
  968.     total++;
  969.     p++;
  970.     }
  971.   glEnd();
  972.   if (total>numedges) cout << "error 3" << endl;
  973.   if (total!=outl+other) cout << "error 4" << endl;
  974.   glEnable(GL_CULL_FACE);
  975.   glDepthMask(GL_ONE);
  976.   glEnable(GL_LIGHTING);
  977.   glEnable(GL_DEPTH_TEST);
  978. }
  979.  
  980. void Object3DS::Render (double time = 0.0) {
  981.   glMatrixMode(GL_MODELVIEW);
  982.   glPushMatrix();
  983.   GLmatrix M = lcs.Val(time);
  984.   glMultMatrixf(M());
  985.  
  986.   if(!(bbox.IsVisible())) {
  987.     glPopMatrix();
  988.     return;
  989.   }
  990.  
  991.   glInterleavedArrays(GL_T4F_C4F_N3F_V4F, 0, (void*)vertices);
  992.  
  993.   glLockArraysEXT(0, numvertices);
  994.  
  995.   facegroups.rewind();
  996.   for(int i=facegroups.size(); i; i--) {
  997.     FaceGroup3DS& fg = *facegroups;
  998.     Material3DS* mat = fg.material;
  999.     mat->GL();
  1000.     switch(mat->Transparency()) {
  1001.       case 50:
  1002.         glDepthMask(GL_ZERO);
  1003.         glDisable(GL_CULL_FACE);
  1004.         glEnable(GL_BLEND);
  1005.         glBlendFunc(GL_ONE, GL_ONE);
  1006.         break;
  1007.       case 49:
  1008.       case 51:
  1009.         glDepthMask(GL_ZERO);
  1010.         glDisable(GL_CULL_FACE);
  1011.         glEnable(GL_BLEND);
  1012.         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  1013.         break;
  1014.       default:
  1015.         glDepthMask(GL_ONE);
  1016.         glEnable(GL_CULL_FACE);
  1017.         glDisable(GL_BLEND);
  1018.         break;
  1019.     }
  1020.     glDrawElements(GL_TRIANGLES, 3*(fg.numfaces), GL_UNSIGNED_INT, (void*)(fg.indices));
  1021.     ++facegroups;
  1022.   }
  1023.  
  1024.   glUnlockArraysEXT();
  1025.  
  1026.   glDisable(GL_CULL_FACE);
  1027.   glDisable(GL_BLEND);
  1028.   glDepthMask(GL_ONE);
  1029.  
  1030.   glPopMatrix();
  1031. }
  1032.  
  1033. void Object3DS::Vertices (int n, Vertex3DS* p) {
  1034.   numvertices = n;
  1035.   vertices = p;
  1036.   bbox = BoundVertices(n, p);
  1037. }
  1038. void Object3DS::AddFaceGroup (Material3DS* mat, int n, GLuint* ind) {
  1039.   facegroups.push_back(FaceGroup3DS(mat, n, ind));
  1040. }
  1041. void Object3DS::EdgeVertices (int n, Vertex3DS* p) {
  1042.   numevertices = n;
  1043.   evertices = p;
  1044. }
  1045. void Object3DS::Edges (int n, Edge3DS* p) {
  1046.   numedges = n;
  1047.   edges = p;
  1048. }
  1049. void Object3DS::Facenormals (int n, Vector3f* p) {
  1050.   numfaces = n;
  1051.   facenormals = p;
  1052. }
  1053. void Object3DS::CoordinateSystem (const GLmatrix& V) {
  1054.   lcs(V);
  1055. }
  1056. void Object3DS::CoordinateSystem (Dynamic<GLmatrix, GLfloat> *ptr, bool strong = false) {
  1057.   lcs(ptr, strong);
  1058. }
  1059.  
  1060. Scene3DS::Scene3DS () {
  1061.   allframes = 0;
  1062.  
  1063.   Material3DS* default_material = new Material3DS;
  1064.   default_material->Name("____DEFAULT_MATERIAL");
  1065.   Add(default_material);
  1066.  
  1067.   return;
  1068. }
  1069. Scene3DS::~Scene3DS () {
  1070.   lights.DeleteEntities();
  1071.   materials.DeleteEntities();
  1072.   textures.DeleteEntities();
  1073.   cameras.DeleteEntities();
  1074.   objects.DeleteEntities();
  1075. }
  1076. void Scene3DS::Render (double time = 0.0) {
  1077.   lights.GL(time);
  1078.   objects.Render(time);
  1079. }
  1080. void Scene3DS::Add (Light* p) {
  1081.   lights+=p;
  1082. }
  1083. void Scene3DS::Add (Texture3DS* p) {
  1084.   textures+=p;
  1085. }
  1086. void Scene3DS::Add (Material3DS* p) {
  1087.   materials+=p;
  1088. }
  1089. void Scene3DS::Add (CameraTarget3DS* p) {
  1090.   cameras+=p;
  1091. }
  1092. void Scene3DS::Add (RenderableEntity* p) {
  1093.   objects+=p;
  1094. }
  1095. void Scene3DS::Add (const RenderableEntities & os) {
  1096.   objects.Add(os);
  1097. }
  1098. Light* Scene3DS::GetLight (String s) {
  1099.   return lights.Get(s);
  1100. }
  1101. Texture3DS* Scene3DS::GetTexture (String s) {
  1102.   return textures.Get(s);
  1103. }
  1104. Material3DS* Scene3DS::GetMaterial (String s) {
  1105.   return materials.Get(s);
  1106. }
  1107. CameraTarget3DS* Scene3DS::GetCamera (String s) {
  1108.   return cameras.Get(s);
  1109. }
  1110. RenderableEntity* Scene3DS::GetObject (String s) {
  1111.   return objects.Get(s);
  1112. }
  1113.  
  1114. Lights Scene3DS::GetLights () {
  1115.   return lights;
  1116. }
  1117. Textures3DS Scene3DS::GetTextures () {
  1118.   return textures;
  1119. }
  1120. Materials3DS Scene3DS::GetMaterials () {
  1121.   return materials;
  1122. }
  1123. Cameras3DS Scene3DS::GetCameras () {
  1124.   return cameras;
  1125. }
  1126. RenderableEntities Scene3DS::GetObjects () {
  1127.   return objects;
  1128. }
  1129.  
  1130. void Scene3DS::Ambient (GLfloat r, GLfloat g, GLfloat b, GLfloat a=1.0) {
  1131.   SetVector4(ambient, r, g, b, a);
  1132. }
  1133.  
  1134. char* Loader3DS::find_chunk(char *father, unsigned short chunk_type, char *act)
  1135. {
  1136.   char *chunk_end = father + getlong(father+2);
  1137.   while((act<chunk_end) && (getshort(act)!=chunk_type))
  1138.     act += getlong(act+2);
  1139.   if(act<chunk_end)
  1140.     return act;
  1141.   else
  1142.     return 0;
  1143. }
  1144.  
  1145. List<chunk3ds> Loader3DS::subchunks(char *father, char *act)
  1146. {
  1147.   List<chunk3ds> l;
  1148.   chunk3ds c;
  1149.   char *chunk_end = father + getlong(father+2);
  1150.   while(act<chunk_end)
  1151.   {
  1152.     c.type=getshort(act);
  1153.     c.ptr=act;
  1154.     l.push_back(c);
  1155.     act+=getlong(act+2);
  1156.   }
  1157.   return l;
  1158. }
  1159.  
  1160. List<chunk3ds> Loader3DS::subchunks_by_type(char *father, unsigned short chunk_type, char *act)
  1161. {
  1162.   List<chunk3ds> l;
  1163.   chunk3ds c;
  1164.   char *chunk_end = father + getlong(father+2);
  1165.   while(act<chunk_end)
  1166.   {
  1167.     if(getshort(act) == chunk_type)
  1168.     {
  1169.       c.type = getshort(act);
  1170.       c.ptr = act;
  1171.       l.push_back(c);
  1172.     }
  1173.     act+=getlong(act+2);
  1174.   }
  1175.   return l;
  1176. }
  1177.  
  1178. void Loader3DS::tcb_info(unsigned short flag)
  1179. {
  1180. //  if (API3DS_TEXT_OUT) cout << flag << " ";
  1181.   if(flag&1)
  1182.     if (API3DS_TEXT_OUT) cout << "tension ";
  1183.   if(flag&2)
  1184.     if (API3DS_TEXT_OUT) cout << "continuity ";
  1185.   if(flag&4)
  1186.     if (API3DS_TEXT_OUT) cout << "bias ";
  1187.   if(flag&8)
  1188.     if (API3DS_TEXT_OUT) cout << "ease-to ";
  1189.   if(flag&16)
  1190.     if (API3DS_TEXT_OUT) cout << "ease-from ";
  1191. }
  1192.  
  1193. char* Loader3DS::fill_tcbee(unsigned short flag, char *p, TCBEE *tcb)
  1194. {
  1195.   tcb->tension = 0.0;
  1196.   tcb->continuity = 0.0;
  1197.   tcb->bias = 0.0;
  1198.   tcb->easeto = 0.0;
  1199.   tcb->easefrom = 0.0;
  1200.  
  1201.   if(flag&1) {
  1202.     tcb->tension = getfloat(p);
  1203.     p+=4;
  1204.   }
  1205.   if(flag&2) {
  1206.     tcb->continuity = getfloat(p);
  1207.     p+=4;
  1208.   }
  1209.   if(flag&4) {
  1210.     tcb->bias = getfloat(p);
  1211.     p+=4;
  1212.   }
  1213.   if(flag&8) {
  1214.     tcb->easeto = getfloat(p);
  1215.     p+=4;
  1216.   }
  1217.   if(flag&16) {
  1218.     tcb->easefrom = getfloat(p);
  1219.     p+=4;
  1220.   }
  1221.   return p;
  1222. }
  1223.  
  1224.  
  1225. void Loader3DS::track_type_info(unsigned short flag)
  1226. {
  1227.   switch(flag&3) {
  1228.     case 0:
  1229.       if (API3DS_TEXT_OUT) cout << "single";
  1230.       break;
  1231.     case 2:
  1232.       if (API3DS_TEXT_OUT) cout << "repeat";
  1233.       break;
  1234.     case 3:
  1235.       if (API3DS_TEXT_OUT) cout << "loop";
  1236.       break;
  1237.   }
  1238.   switch((flag&52)>>3) {
  1239.     case 1:
  1240.       if (API3DS_TEXT_OUT) cout << ", lock X";
  1241.       break;
  1242.     case 2:
  1243.       if (API3DS_TEXT_OUT) cout << ", lock Y";
  1244.       break;
  1245.     case 4:
  1246.       if (API3DS_TEXT_OUT) cout << ", lock Z";
  1247.       break;
  1248.   }
  1249.   switch((flag&896)>>7) {
  1250.     case 1:
  1251.       if (API3DS_TEXT_OUT) cout << ", unlink X";
  1252.       break;
  1253.     case 2:
  1254.       if (API3DS_TEXT_OUT) cout << ", unlink Y";
  1255.       break;
  1256.     case 4:
  1257.       if (API3DS_TEXT_OUT) cout << ", unlink Z";
  1258.       break;
  1259.   }
  1260. }
  1261.  
  1262. Scene3DS* Loader3DS::Load(const char *inputfile, Textures3DS* texturelib = 0)
  1263. {
  1264.   Scene3DS* scene = 0;
  1265.   bool take_care_of_buf_alloc = buffer ? false : true;
  1266.  
  1267.   try {
  1268.  
  1269.   if(take_care_of_buf_alloc)
  1270.     buffer = new char[BUFFER_SIZE_3DS];
  1271.  
  1272.   gzFile file;
  1273.   file = gzopen(inputfile,"rb");
  1274.   if(file == 0) {
  1275.     if (API3DS_TEXT_OUT) cout << "3DS Loader: Error: Can't open """ << inputfile << """." << endl; 
  1276.     throw 1;
  1277.   }
  1278.   gzread(file, buffer, BUFFER_SIZE_3DS);
  1279.   gzclose(file);
  1280. /*
  1281.   int f = open(inputfile, O_BINARY|O_RDONLY);
  1282.   if (f==-1) {
  1283.     if (API3DS_TEXT_OUT) cout << "3DS Loader: Error: File not found." << endl;
  1284.     throw 1;
  1285.   }
  1286.  
  1287.   struct stat st;
  1288.   fstat(f,&st);
  1289.   buffer = new char[st.st_size];
  1290.   read(f,buffer,st.st_size);
  1291.   close(f);
  1292. */
  1293.   if (API3DS_TEXT_OUT) cout << "3DS Loader: Processing \""<< inputfile << "\":" << endl;
  1294.   if (getshort(buffer)!=MAIN_3DS_CHUNK)
  1295.   {
  1296.     if (API3DS_TEXT_OUT) cout << "3DS Loader: Error: Invalid inputfile." << endl;
  1297.     throw 1;
  1298.   }
  1299.  
  1300.   // start processing
  1301.   char *pmesh = buffer;
  1302.  
  1303.   scene = new Scene3DS;
  1304.   scene->Name(inputfile);
  1305.  
  1306.   // find the editor chunk
  1307.   char *peditor = find_chunk(pmesh, EDITOR_CHUNK, pmesh+6);
  1308.  
  1309.   // look for ambient color
  1310.   char *p = find_chunk(peditor, AMBIENT_COLOR, peditor+6);
  1311.   if(p!=0)
  1312.   {
  1313.     p = find_chunk(p, RGBfloat, p+6);
  1314.     if(p!=0)
  1315.     {
  1316.       p+=6;
  1317.       if (API3DS_TEXT_OUT) cout<<" Ambient color: ("
  1318.          <<(int)(256*getfloat(p))<<", "
  1319.          <<(int)(256*getfloat(p+4))<<", "
  1320.          <<(int)(256*getfloat(p+8))<< ")" << endl;
  1321.       scene->Ambient(getfloat(p), getfloat(p+4), getfloat(p+8));
  1322.     } 
  1323.   }
  1324.  
  1325.   List<chunk3ds> pmats(subchunks_by_type(peditor, MATERIAL_BLOCK, peditor+6));
  1326.   if (API3DS_TEXT_OUT) cout << " Materials: " << endl;
  1327.   char *pmat;
  1328.   pmats.rewind();
  1329.   for(int nm=pmats.size(); nm; nm--)
  1330.   {
  1331.  
  1332.     pmat = (*pmats).ptr;
  1333.     p = find_chunk(pmat, MATERIAL_NAME, pmat+6);
  1334.     if (API3DS_TEXT_OUT) cout << "  \"" << (const char *)(p+6) << "\":" << endl;
  1335.  
  1336.     Material3DS *mat = new Material3DS;
  1337.     mat->Name((const char *)(p+6));
  1338.     scene->Add(mat);
  1339.  
  1340.     p = find_chunk(pmat, MATERIAL_AMBIENT_COLOR, pmat+6);
  1341.     if(p!=0) 
  1342.     {
  1343.       GLubyte *rgbcolor = (GLubyte *)find_chunk(p, RGBbyte, p+6)+6;
  1344.       if (API3DS_TEXT_OUT) cout << "     Ambient color: ("
  1345.           << (int) *rgbcolor << ", "
  1346.           << (int) *(rgbcolor+1) << ", "
  1347.           << (int) *(rgbcolor+2) << ")" << endl;
  1348.       mat->Ambient(*rgbcolor, *(rgbcolor+1), *(rgbcolor+2));
  1349.     }
  1350.     p = find_chunk(pmat, MATERIAL_DIFFUSE_COLOR, pmat+6);
  1351.     if(p!=0) 
  1352.     {
  1353.       GLubyte *rgbcolor = (GLubyte *)find_chunk(p, RGBbyte, p+6)+6;
  1354.       if (API3DS_TEXT_OUT) cout << "     Diffuse color: ("
  1355.           << (int) *rgbcolor << ", "
  1356.           << (int) *(rgbcolor+1) << ", "
  1357.           << (int) *(rgbcolor+2) << ")" << endl;
  1358.       mat->Diffuse(*rgbcolor, *(rgbcolor+1), *(rgbcolor+2));
  1359.     }
  1360.     p = find_chunk(pmat, MATERIAL_SPECULAR_COLOR, pmat+6);
  1361.     if(p!=0) 
  1362.     {
  1363.       GLubyte *rgbcolor = (GLubyte *)find_chunk(p, RGBbyte, p+6)+6;
  1364.       if (API3DS_TEXT_OUT) cout << "     Specular color: ("
  1365.           << (int) *rgbcolor << ", "
  1366.           << (int) *(rgbcolor+1) << ", "
  1367.           << (int) *(rgbcolor+2) << ")" << endl;
  1368.       mat->Specular(*rgbcolor, *(rgbcolor+1), *(rgbcolor+2));
  1369.     }
  1370.  
  1371.     p = find_chunk(pmat, TRANSPARENCY_PERCENT, pmat+6);
  1372.     if(p!=0)
  1373.     {
  1374.       char *percent = find_chunk(p, PERCENTword, p+6)+6;
  1375.       if (API3DS_TEXT_OUT) cout << "     Transparency: " << getshort(percent) << "%" << endl;
  1376.       int xp = getshort(percent);
  1377.       mat->Transparency(xp);
  1378.     }
  1379.  
  1380.     p = find_chunk(pmat, MAP1, pmat+6);
  1381.     if(p!=0)
  1382.     {
  1383.       char *ptname = find_chunk(p, MAPPING_FILENAME, p+6)+6;
  1384. // *-> data directory access
  1385. //      char tm_p[30]="data\\";
  1386. //      strcat(tm_p,ptname);
  1387. //      strcpy(ptname,tm_p);
  1388.  
  1389.       if (API3DS_TEXT_OUT) cout << "     Diffuse map: \"" << (const char *)ptname << "\"" << endl;
  1390.  
  1391.       /*
  1392.        * An external texture library can be passed as a second argument
  1393.        * to Load(...)
  1394.        */
  1395.       Texture3DS* tex;
  1396.       if(texturelib) {
  1397.         tex = texturelib->GetOrCreate((const char*)ptname);
  1398.       }
  1399.       else {
  1400.         tex = new Texture3DS;
  1401.         tex->Name((const char *)ptname);
  1402.         tex->MinFilter(GL_LINEAR);
  1403.         tex->MagFilter(GL_LINEAR);
  1404.  
  1405.         scene->Add(tex);
  1406.       }
  1407.       mat->Texture1(tex);
  1408.  
  1409.     }
  1410.  
  1411.     ++pmats;
  1412.   }
  1413.  
  1414.   // list obj blocks within editor
  1415.   List<chunk3ds> pl(subchunks_by_type(peditor, OBJECT_BLOCK, peditor+6));
  1416.   pl.rewind();
  1417.   char *po, *pi, *ptri;
  1418.  
  1419.   RenderableEntities transparent_objects;
  1420.   bool istransparent;
  1421.  
  1422.   if (API3DS_TEXT_OUT) cout << " Object blocks:" << endl;
  1423.  
  1424.   const char *pname;
  1425.   for(int no=pl.size(); no; no--)
  1426.   {
  1427.     po = (*pl).ptr;
  1428.     ++pl;
  1429.     pi = po + 6;
  1430.     pname = (const char *)pi;
  1431.     if (API3DS_TEXT_OUT) cout << "  \"" << pname << "\" ";
  1432.     while(*pi) pi++; pi++;
  1433.  
  1434.     if(find_chunk(po, TRIANGULAR_MESH, pi))
  1435.     {
  1436.       if (API3DS_TEXT_OUT) cout << "A mesh. ";
  1437.       ptri = find_chunk(po, TRIANGULAR_MESH, pi);
  1438.  
  1439.       // find vertices
  1440.       int vertex_count = 0;
  1441.       Vector3DS *pvertices = 0;
  1442.       p = find_chunk(ptri, VERTICES, ptri+6);
  1443.       if(p!=0)
  1444.         {
  1445.           vertex_count = getshort(p+6);
  1446.           pvertices = (Vector3DS *)(p+8);
  1447.         }
  1448.  
  1449.       // find faces
  1450.       int face_count = 0;
  1451.       Face3DS *pfaces = 0;
  1452.       p = find_chunk(ptri, FACES, ptri+6);
  1453.       char *pfaceschunk = p;
  1454.       if(p!=0)
  1455.         {
  1456.           face_count = getshort(p+6);
  1457.           pfaces = (Face3DS *)(p+8);
  1458.         }
  1459.  
  1460.       // find mapping info
  1461.       int map_vertex_count = 0;
  1462.       Mapping3DS *pmapping = 0;
  1463.       p = find_chunk(ptri, MAPPING_COORDS, ptri+6);
  1464.       if(p!=0)
  1465.         {
  1466.           map_vertex_count = getshort(p+6);
  1467.           pmapping = (Mapping3DS *)(p+8);
  1468.         }
  1469.  
  1470.       if(pvertices && pfaces)
  1471.       {
  1472.         if (API3DS_TEXT_OUT) cout <<"("<<vertex_count<<" vertices, "<<face_count<<" faces"<<")";
  1473.         if(pmapping)
  1474.           if (API3DS_TEXT_OUT) cout << " mapped.";
  1475.         if (API3DS_TEXT_OUT) cout << endl;
  1476.  
  1477.         Object3DS *object = new Object3DS;
  1478.         object->Name(pname);
  1479.         istransparent = false;
  1480.  
  1481.         // for every i-th face smooths[i] is the smoothing groups info
  1482.         unsigned long *smooths = 0;
  1483.         if(find_chunk(pfaceschunk, SMOOTHINGS, (char *)(pfaces+face_count))) {
  1484.           smooths = (unsigned long *)(6+find_chunk(pfaceschunk, SMOOTHINGS, (char *)(pfaces+face_count)));
  1485.         }
  1486.  
  1487.         iface Iface[face_count];
  1488.         Vector3f P1, P2, P3;
  1489.         for(int z=0; z<face_count; z++) {
  1490.           Iface[z].a = pfaces[z].a;
  1491.           Iface[z].b = pfaces[z].b;
  1492.           Iface[z].c = pfaces[z].c;
  1493.           if(smooths)
  1494.             Iface[z].sgroup = smooths[z];
  1495.           else
  1496.             Iface[z].sgroup = 1;
  1497.           Vector3DS* pv;
  1498.           pv = pvertices + pfaces[z].a;
  1499.           P1 = Vector3f(pv->x, pv->y, pv->z);
  1500.           pv = pvertices + pfaces[z].b;
  1501.           P2 = Vector3f(pv->x, pv->y, pv->z);
  1502.           pv = pvertices + pfaces[z].c;
  1503.           P3 = Vector3f(pv->x, pv->y, pv->z);
  1504.           Iface[z].N = Normalize(CrossProduct(P2-P1, P3-P1));
  1505.           Iface[z].hasmaterial = false;
  1506.           Iface[z].ab_done = !(pfaces[z].flags&4);
  1507.           Iface[z].ac_done = !(pfaces[z].flags&1);
  1508.           Iface[z].bc_done = !(pfaces[z].flags&2);
  1509. //          Iface[z].ab_done = false;
  1510. //          Iface[z].ac_done = false;
  1511. //          Iface[z].bc_done = false;
  1512.         }
  1513.  
  1514.         Vertex3DS* vert = new Vertex3DS[vertex_count*2];
  1515.  
  1516.         for(int z=0; z<vertex_count; z++) {
  1517.           vert[z].x = pvertices[z].x;
  1518.           vert[z].y = pvertices[z].y;
  1519.           vert[z].z = pvertices[z].z;
  1520.           vert[z].w = 1.0F;
  1521.           vert[z].R = vert[z].G = vert[z].B = vert[z].A = 1.0F;
  1522.           vert[z].r = 0.0F;
  1523.           vert[z].q = 1.0F;
  1524.           if(pmapping) {
  1525.             vert[z].s = pmapping[z].u;
  1526.             vert[z].t = pmapping[z].v;
  1527.           }
  1528.           else {
  1529.             vert[z].s = 0.0F;
  1530.             vert[z].t = 0.0F;
  1531.           }
  1532.  
  1533.           vert[z].i = 0.0F;
  1534.           vert[z].j = 0.0F;
  1535.           vert[z].k = 0.0F;
  1536.         }
  1537.  
  1538.         /*
  1539.          * Here we create a copy of the vertices, which is suitable for
  1540.          * creating volumetric effects.
  1541.          */
  1542.         for(int z=0; z<vertex_count; z++) {
  1543.           vert[z+vertex_count] = vert[z];
  1544.         }
  1545.         object->EdgeVertices(vertex_count*2, vert);
  1546.  
  1547.         /*
  1548.          * We build an array of normals at each face, suitable for effects.
  1549.          */
  1550.         Vector3f* fnormals = new Vector3f[face_count];
  1551.         for(int z=0; z<face_count; z++) {
  1552.           fnormals[z] = Iface[z].N;
  1553.         }
  1554.         object->Facenormals(face_count, fnormals);
  1555.  
  1556.         /*
  1557.          * For each vertex we build a table of pointers to faces 
  1558.          * that share it.
  1559.          */
  1560.  
  1561.         shinfo sharings[vertex_count];
  1562.         for(int z=0; z<vertex_count; z++) {
  1563.           sharings[z].numfaces = 0;
  1564.           sharings[z].used = 0;
  1565.           sharings[z].splits = 0;
  1566.           sharings[z].p = 0;
  1567.           sharings[z].v = 0;
  1568.           sharings[z].iv = 0;
  1569.         }
  1570.           
  1571.         for(int z=0; z<face_count; z++) {
  1572.           sharings[Iface[z].a].numfaces++;
  1573.           sharings[Iface[z].b].numfaces++;
  1574.           sharings[Iface[z].c].numfaces++;
  1575.         }
  1576.         
  1577.         ftable fgroups[face_count*3];
  1578.         for(int z=0; z<(face_count*3); z++) {
  1579.           fgroups[z].group = 0;
  1580.         }
  1581.         ftable* fptr = fgroups;
  1582.         for(int z=0; z<vertex_count; z++) {
  1583.           sharings[z].p = fptr;
  1584.           fptr+=sharings[z].numfaces;
  1585.         }
  1586.         
  1587.         for(int z=0; z<face_count; z++) {
  1588.           (sharings[Iface[z].a].p + sharings[Iface[z].a].used)->fi = z;
  1589.           sharings[Iface[z].a].used++;
  1590.           (sharings[Iface[z].b].p + sharings[Iface[z].b].used)->fi = z;
  1591.           sharings[Iface[z].b].used++;
  1592.           (sharings[Iface[z].c].p + sharings[Iface[z].c].used)->fi = z;
  1593.           sharings[Iface[z].c].used++;
  1594.         }
  1595.  
  1596.         /*
  1597.          * Build an array of this objects polygon edges
  1598.          */
  1599.         Edge3DS* edges = new Edge3DS[face_count*3];
  1600.         int edge_count = 0;
  1601.  
  1602.         for(int z=0; z<face_count; z++) {
  1603.           GLuint aa = Iface[z].a;
  1604.           GLuint bb = Iface[z].b;
  1605.           GLuint cc = Iface[z].c;
  1606.           // AB edge
  1607.           if(!Iface[z].ab_done) {
  1608.             Iface[z].ab_done = true;
  1609.             edges[edge_count].a = aa;
  1610.             edges[edge_count].b = bb;
  1611.             edges[edge_count].N1_x = Iface[z].N.x;
  1612.             edges[edge_count].N1_y = Iface[z].N.y;
  1613.             edges[edge_count].N1_z = Iface[z].N.z;
  1614.  
  1615.             ftable* fp = sharings[aa].p;
  1616.             int d = 0;
  1617.             for(; d<sharings[aa].numfaces; d++, fp++) {
  1618.               if(z==fp->fi) continue;
  1619.               iface& face = Iface[fp->fi];
  1620.               if((face.a==aa&&face.b==bb)||(face.a==bb&&face.b==aa)) {
  1621.                 face.ab_done = true;
  1622.                 edges[edge_count].N2_x = face.N.x;
  1623.                 edges[edge_count].N2_y = face.N.y;
  1624.                 edges[edge_count].N2_z = face.N.z;
  1625.                 break;
  1626.               }
  1627.               if((face.a==aa&&face.c==bb)||(face.a==bb&&face.c==aa)) {
  1628.                 face.ac_done = true;
  1629.                 edges[edge_count].N2_x = face.N.x;
  1630.                 edges[edge_count].N2_y = face.N.y;
  1631.                 edges[edge_count].N2_z = face.N.z;
  1632.                 break;
  1633.               }
  1634.               if((face.b==aa&&face.c==bb)||(face.b==bb&&face.c==aa)) {
  1635.                 face.bc_done = true;
  1636.                 edges[edge_count].N2_x = face.N.x;
  1637.                 edges[edge_count].N2_y = face.N.y;
  1638.                 edges[edge_count].N2_z = face.N.z;
  1639.                 break;
  1640.               }
  1641.             }
  1642.             if(d==sharings[aa].numfaces) {
  1643.               edges[edge_count].N2_x = -Iface[z].N.x;
  1644.               edges[edge_count].N2_y = -Iface[z].N.y;
  1645.               edges[edge_count].N2_z = -Iface[z].N.z;
  1646.             }
  1647.             edge_count++;
  1648.           }
  1649.           // AC edge
  1650.           if(!Iface[z].ac_done) {
  1651.             Iface[z].ac_done = true;
  1652.             edges[edge_count].a = aa;
  1653.             edges[edge_count].b = cc;
  1654.             edges[edge_count].N1_x = Iface[z].N.x;
  1655.             edges[edge_count].N1_y = Iface[z].N.y;
  1656.             edges[edge_count].N1_z = Iface[z].N.z;
  1657.             ftable* fp = sharings[aa].p;
  1658.             int d = 0;
  1659.             for(; d<sharings[aa].numfaces; d++, fp++) {
  1660.               if(z==fp->fi) continue;
  1661.               iface& face = Iface[fp->fi];
  1662.               if((face.a==aa&&face.b==cc)||(face.a==cc&&face.b==aa)) {
  1663.                 face.ab_done = true;
  1664.                 edges[edge_count].N2_x = face.N.x;
  1665.                 edges[edge_count].N2_y = face.N.y;
  1666.                 edges[edge_count].N2_z = face.N.z;
  1667.                 break;
  1668.               }
  1669.               if((face.a==aa&&face.c==cc)||(face.a==cc&&face.c==aa)) {
  1670.                 face.ac_done = true;
  1671.                 edges[edge_count].N2_x = face.N.x;
  1672.                 edges[edge_count].N2_y = face.N.y;
  1673.                 edges[edge_count].N2_z = face.N.z;
  1674.                 break;
  1675.               }
  1676.               if((face.b==aa&&face.c==cc)||(face.b==cc&&face.c==aa)) {
  1677.                 face.bc_done = true;
  1678.                 edges[edge_count].N2_x = face.N.x;
  1679.                 edges[edge_count].N2_y = face.N.y;
  1680.                 edges[edge_count].N2_z = face.N.z;
  1681.                 break;
  1682.               }
  1683.             }
  1684.             if(d==sharings[aa].numfaces) {
  1685.               edges[edge_count].N2_x = -Iface[z].N.x;
  1686.               edges[edge_count].N2_y = -Iface[z].N.y;
  1687.               edges[edge_count].N2_z = -Iface[z].N.z;
  1688.             }
  1689.             edge_count++;
  1690.           }
  1691.           // BC edge
  1692.           if(!Iface[z].bc_done) {
  1693.             Iface[z].bc_done = true;
  1694.             edges[edge_count].a = bb;
  1695.             edges[edge_count].b = cc;
  1696.             edges[edge_count].N1_x = Iface[z].N.x;
  1697.             edges[edge_count].N1_y = Iface[z].N.y;
  1698.             edges[edge_count].N1_z = Iface[z].N.z;
  1699.             ftable* fp = sharings[bb].p;
  1700.             int d = 0;
  1701.             for(; d<sharings[bb].numfaces; d++, fp++) {
  1702.               if(z==fp->fi) continue;
  1703.               iface& face = Iface[fp->fi];
  1704.               if((face.a==bb&&face.b==cc)||(face.a==cc&&face.b==bb)) {
  1705.                 face.ab_done = true;
  1706.                 edges[edge_count].N2_x = face.N.x;
  1707.                 edges[edge_count].N2_y = face.N.y;
  1708.                 edges[edge_count].N2_z = face.N.z;
  1709.                 break;
  1710.               }
  1711.               if((face.a==bb&&face.c==cc)||(face.a==cc&&face.c==bb)) {
  1712.                 face.ac_done = true;
  1713.                 edges[edge_count].N2_x = face.N.x;
  1714.                 edges[edge_count].N2_y = face.N.y;
  1715.                 edges[edge_count].N2_z = face.N.z;
  1716.                 break;
  1717.               }
  1718.               if((face.b==bb&&face.c==cc)||(face.b==cc&&face.c==bb)) {
  1719.                 face.bc_done = true;
  1720.                 edges[edge_count].N2_x = face.N.x;
  1721.                 edges[edge_count].N2_y = face.N.y;
  1722.                 edges[edge_count].N2_z = face.N.z;
  1723.                 break;
  1724.               }
  1725.             }
  1726.             if(d==sharings[bb].numfaces) {
  1727.               edges[edge_count].N2_x = -Iface[z].N.x;
  1728.               edges[edge_count].N2_y = -Iface[z].N.y;
  1729.               edges[edge_count].N2_z = -Iface[z].N.z;
  1730.             }
  1731.             edge_count++;
  1732.           }
  1733.         }
  1734.  
  1735.         object->Edges(edge_count, edges);
  1736.         if (API3DS_TEXT_OUT) cout<< "         Edges: " << edge_count << endl;
  1737.         
  1738.         /* 
  1739.          * For each vertex we divide the faces sharing it into groups
  1740.          * according to the smoothing info. The algorithm used assumes
  1741.          * some "good" structure of smoothing data, and cannot handle
  1742.          * all the possible (although unprobable) cases.
  1743.          */
  1744.        
  1745.         int vertex_count2 = 0;
  1746.         if(smooths) {
  1747.           for(int z=0; z<vertex_count; z++) {
  1748.             GLuint g = 0;
  1749.             ftable* fp = sharings[z].p;
  1750.             /*
  1751.              * here we try to handle out the faces w/o smoothing info
  1752.              */
  1753.             for(int d=0; d<sharings[z].numfaces; d++) {
  1754.               if(Iface[fp->fi].sgroup==0) {
  1755.                 g++;
  1756.                 fp->group = g;
  1757.               }
  1758.               fp++;
  1759.             }
  1760.             while(true) {
  1761.               /*
  1762.                * and from now on just the nice behaving faces
  1763.                */
  1764.               int r = 0;
  1765.               fp = sharings[z].p;
  1766.               r = 0;
  1767.               for(; r<sharings[z].numfaces; r++) {
  1768.                 if(!fp->group) break;
  1769.                 fp++;
  1770.               }
  1771.               if(r==sharings[z].numfaces) break;
  1772.               g++;
  1773.               unsigned long cgroup = Iface[fp->fi].sgroup;
  1774.               for(; r<sharings[z].numfaces; r++) {
  1775.                 if(!fp->group) 
  1776.                   if(Iface[fp->fi].sgroup&cgroup)
  1777.                     fp->group = g;
  1778.                 fp++;
  1779.               }
  1780.             }
  1781.             sharings[z].splits = g;
  1782.             vertex_count2 += g;
  1783.           }
  1784.         }
  1785.         else {
  1786.           /*
  1787.            * This is for the case when the object is not smoothed at all.
  1788.            */
  1789.           for(int z=0; z<vertex_count; z++) {
  1790.             ftable* fp = sharings[z].p;
  1791.             for(int q=1; q<=sharings[z].numfaces; q++) {
  1792.               fp->group = q;
  1793.               fp++;
  1794.             }
  1795.             sharings[z].splits = sharings[z].numfaces;
  1796.             vertex_count2 += sharings[z].numfaces;
  1797.           }
  1798.         }
  1799.  
  1800.         Vertex3DS* vert2 = new Vertex3DS[vertex_count2];
  1801.         Vertex3DS* pvert2 = vert2;
  1802.         GLuint iiv = 0;
  1803.         for(int z=0; z<vertex_count; z++) {
  1804.           sharings[z].v = pvert2;
  1805.           sharings[z].iv = iiv;
  1806.           for(int q=sharings[z].splits; q; q--) {
  1807.             *pvert2 = vert[z];
  1808.             pvert2++;
  1809.             iiv++;
  1810.           }
  1811.         }
  1812.  
  1813.         iface Iface2[face_count];
  1814.         for(int z=0; z<face_count; z++)
  1815.           Iface2[z] = Iface[z];
  1816.  
  1817.         for(int z=0; z<vertex_count; z++) {
  1818.           ftable* fp = sharings[z].p;
  1819.           for(int q=0; q<sharings[z].numfaces; q++) {
  1820.             iface* pi_src = &Iface2[fp->fi];
  1821.             iface* pi_dst = &Iface[fp->fi];
  1822.             GLuint sv = sharings[z].iv + fp->group - 1;
  1823.             if(z==pi_src->a) pi_dst->a = sv;
  1824.             if(z==pi_src->b) pi_dst->b = sv;
  1825.             if(z==pi_src->c) pi_dst->c = sv;
  1826.             fp++;
  1827.           }  
  1828.         }
  1829.  
  1830.         if (API3DS_TEXT_OUT) cout<< "         Before: "<<vertex_count*3<<" After: "<<vertex_count2<<endl;
  1831.           
  1832.         iface* pif = Iface;
  1833.         for(int z=0; z<face_count; z++, pif++) {
  1834.           GLfloat nx = (pif->N).x;
  1835.           GLfloat ny = (pif->N).y;
  1836.           GLfloat nz = (pif->N).z;
  1837.           GLuint aa = pif->a;
  1838.           GLuint bb = pif->b;
  1839.           GLuint cc = pif->c;
  1840.           vert2[aa].i += nx;
  1841.           vert2[aa].j += ny;
  1842.           vert2[aa].k += nz;
  1843.           vert2[bb].i += nx;
  1844.           vert2[bb].j += ny;
  1845.           vert2[bb].k += nz;
  1846.           vert2[cc].i += nx;
  1847.           vert2[cc].j += ny;
  1848.           vert2[cc].k += nz;
  1849.         }
  1850.         for(int z=0; z<vertex_count2; z++) {
  1851.           GLfloat len = 1.0/sqrt(vert2[z].i*vert2[z].i +
  1852.                                  vert2[z].j*vert2[z].j +
  1853.                                  vert2[z].k*vert2[z].k);
  1854.           vert2[z].i *= len;
  1855.           vert2[z].j *= len;
  1856.           vert2[z].k *= len;
  1857.         }
  1858.           
  1859.         object->Vertices(vertex_count2, vert2);
  1860.             
  1861.         List<chunk3ds> pmlist(subchunks_by_type(pfaceschunk, FACES_MATERIALS, (char *)(pfaces+face_count)));
  1862.         if(pmlist.size()!=0) if (API3DS_TEXT_OUT) cout<<"    Materials: ";
  1863.         pmlist.rewind();
  1864.         GLuint* pind;
  1865.         for(int q=pmlist.size(); q; q--)
  1866.         {
  1867.           p = (*pmlist).ptr;
  1868.           ++pmlist;
  1869.           if (API3DS_TEXT_OUT) cout<<(const char *)(p+6);
  1870.           Material3DS *matpointer = scene->GetMaterial((const char *)(p+6));
  1871.           if(matpointer->Transparency()==50)
  1872.             istransparent = true;
  1873.           p+=6;
  1874.           while(*p) p++; p++;
  1875.           int mapped = getshort(p);
  1876.           if(!mapped)
  1877.             // this really happens
  1878.             continue;
  1879.           if (API3DS_TEXT_OUT) cout<<" ("<<mapped<<"), ";
  1880.           p+=2;
  1881.  
  1882.           pind = new GLuint[mapped*3];
  1883.           object->AddFaceGroup(matpointer, mapped, pind);
  1884.           for(int w=mapped; w; w--, p+=2) {
  1885.             iface* pif = Iface+getshort(p);
  1886.             pif->hasmaterial = true;
  1887.             *pind = pif->a; pind++;
  1888.             *pind = pif->b; pind++;
  1889.             *pind = pif->c; pind++;
  1890.           }
  1891.         }
  1892.         if(pmlist.size()!=0)
  1893.           if (API3DS_TEXT_OUT) cout<<endl;
  1894.  
  1895.         // DEFAULT material (for faces without assigned material)
  1896.  
  1897.         int wo_material = 0;
  1898.         for(int w=0; w<face_count; w++)
  1899.           if(!(Iface[w].hasmaterial))
  1900.             wo_material++;
  1901.         if(wo_material) {
  1902.           pind = new GLuint[wo_material*3];
  1903.           Material3DS *defmat = scene->GetMaterial("____DEFAULT_MATERIAL");
  1904.           object->AddFaceGroup(defmat, wo_material, pind);
  1905.           for(int w=0; w<face_count; w++) {
  1906.             iface* pif = Iface+w;
  1907.             if(!(pif->hasmaterial)) {
  1908.               *pind = pif->a; pind++;
  1909.               *pind = pif->b; pind++;
  1910.               *pind = pif->c; pind++;
  1911.             }
  1912.           }
  1913.         }
  1914.  
  1915.         if(istransparent)
  1916.           transparent_objects+=object;
  1917.         else
  1918.           scene->Add(object);
  1919.   
  1920.       }
  1921.  
  1922.       continue;
  1923.     }
  1924.  
  1925.     // light
  1926.     if(find_chunk(po, LIGHT, pi))
  1927.     {
  1928.       if (API3DS_TEXT_OUT) cout << "A light." << endl;
  1929.       p = find_chunk(po, LIGHT, pi);
  1930.       char *vec = p+6;
  1931.       char *prgb = find_chunk(p, RGBfloat, p+18)+6;
  1932.       if (API3DS_TEXT_OUT) cout<<"     Position: ("
  1933.          << getfloat(vec) <<", "
  1934.          << getfloat(vec+4) <<", "
  1935.          << getfloat(vec+8) << ")" << endl;
  1936.       if (API3DS_TEXT_OUT) cout<<"     Color: ("
  1937.          <<(int)(256*getfloat(prgb))<<", "
  1938.          <<(int)(256*getfloat(prgb+4))<<", "
  1939.          <<(int)(256*getfloat(prgb+8))<< ")" << endl;
  1940.       OmniLight3DS* light = new OmniLight3DS;
  1941.       light->Name(pname);
  1942.       scene->Add(light);
  1943.       light->Position(getfloat(vec), getfloat(vec+4), getfloat(vec+8));
  1944.       light->Diffuse(getfloat(prgb), getfloat(prgb+4), getfloat(prgb+8));
  1945. /*
  1946.         if(FindChunk(plights, LIGHT_OFF, plights+18))
  1947.           {
  1948.             newlight->state = 0;
  1949.             printf(" OFF");
  1950.           }
  1951. */
  1952.         continue;
  1953.       }
  1954.  
  1955.     // object identified as a camera
  1956.     if(find_chunk(po, CAMERA, pi))
  1957.     {
  1958.       if (API3DS_TEXT_OUT) cout << "A camera." << endl;
  1959.       CameraTarget3DS *camera = new CameraTarget3DS;
  1960.       camera->Name(pname);
  1961.       scene->Add(camera);
  1962.       p = find_chunk(po, CAMERA, pi);
  1963.       char *vec = p+6;
  1964.       if (API3DS_TEXT_OUT) cout<<"     Origin: ("
  1965.          << getfloat(vec) <<", "
  1966.          << getfloat(vec+4) <<", "
  1967.          << getfloat(vec+8) << ")" << endl;
  1968.       camera->Origin(getfloat(vec), getfloat(vec+4), getfloat(vec+8));
  1969.       vec+=12;
  1970.       if (API3DS_TEXT_OUT) cout<<"     Target: ("
  1971.          << getfloat(vec) <<", "
  1972.          << getfloat(vec+4) <<", "
  1973.          << getfloat(vec+8) << ")" << endl;
  1974.       camera->Target(getfloat(vec), getfloat(vec+4), getfloat(vec+8));
  1975.       vec+=12;
  1976.       if (API3DS_TEXT_OUT) cout<<"    Bank: "<<getfloat(vec)<<endl;
  1977.       vec+=4;
  1978.       if (API3DS_TEXT_OUT) cout<<"    Lens: "<<getfloat(vec)<<endl;
  1979.       continue;
  1980.     }
  1981.  
  1982.   }
  1983.  
  1984.   scene->Add(transparent_objects);
  1985.  
  1986.   if (API3DS_TEXT_OUT) cout << endl;
  1987.  
  1988.   // Keyframer chunk
  1989.   // ------------------------------------------------------------------
  1990.  
  1991.   char *keyframer = find_chunk(pmesh, KEYFRAMER_CHUNK, pmesh+6);
  1992.   if(!keyframer) {
  1993.     throw 1;
  1994.   }
  1995.   if (API3DS_TEXT_OUT) cout << "Keyframer data:" << endl << endl;
  1996.  
  1997.   p = find_chunk(keyframer, FRAMES, keyframer+6);
  1998.   if(!p) {
  1999.     throw 1;
  2000.   }
  2001.   if (API3DS_TEXT_OUT) cout << "Animation frames: "<<(int)getlong(p+6)<<" to "<<(int)getlong(p+10)<<"."<<endl;
  2002.   int frames_start = (int)getlong(p+6);
  2003.   int frames_end = (int)getlong(p+10);
  2004.   int frames = frames_end-frames_start + 1;
  2005.   scene->Frames(frames);
  2006.  
  2007.   List<chunk3ds> camo(subchunks_by_type(keyframer, CAMERA_INFORMATION_BLOCK, keyframer+6));
  2008.   camo.rewind();
  2009.   for(int nc=camo.size(); nc; nc--) 
  2010.   {
  2011.     if (API3DS_TEXT_OUT) cout << "Camera origin info block:" << endl;
  2012.     char *info = (*camo).ptr;
  2013.     ++camo;
  2014.  
  2015.     char *objinfo = find_chunk(info, OBJECT_INFO, info+6);
  2016.     pname = (const char *)(objinfo+6);
  2017.     if (API3DS_TEXT_OUT) cout << "  Camera: " << pname << endl;
  2018.     CameraTarget3DS *camera = dynamic_cast<CameraTarget3DS*>(scene->GetCamera(pname));
  2019.     unsigned short flag, tracktype;
  2020.     unsigned long keys;
  2021.  
  2022.     char *track = find_chunk(info, POSITION_TRACK, info+6);
  2023.     if(track) {
  2024.       track+=6;
  2025.       flag = getshort(track);
  2026.       if (API3DS_TEXT_OUT) cout << "    track type: ";
  2027.       track_type_info(flag);
  2028.       if (API3DS_TEXT_OUT) cout << endl;
  2029.       tracktype = flag;
  2030.  
  2031.       track+=10;
  2032.       if (API3DS_TEXT_OUT) cout << "    Position keys: " << (int)getlong(track) << endl;
  2033.       keys = (int)getlong(track);
  2034.       track+=4;
  2035.     
  2036.       Dynamic<Vector3f, GLfloat> *newtrack = process_position_track(frames, keys, track, tracktype);
  2037.       if(newtrack)
  2038.         camera->Origin(newtrack, true);
  2039.     }
  2040.  
  2041.     track = find_chunk(info, ROLL_TRACK, info+6);
  2042.     if(track) {
  2043.       track+=6;
  2044.       flag = getshort(track);
  2045.       if (API3DS_TEXT_OUT) cout << "    track type: ";
  2046.       track_type_info(flag);
  2047.       if (API3DS_TEXT_OUT) cout << endl;
  2048.       tracktype = flag;
  2049.  
  2050.       track+=10;
  2051.       if (API3DS_TEXT_OUT) cout << "    Roll keys: " << (int)getlong(track) << endl;
  2052.       keys = (int)getlong(track);
  2053.       track+=4;
  2054.     
  2055.       Dynamic<GLfloat, GLfloat> *newtrack = process_roll_track(frames, keys, track, tracktype);
  2056.       if(newtrack)
  2057.         camera->Roll(newtrack, true);
  2058.     }
  2059.  
  2060.   }
  2061.  
  2062.   List<chunk3ds> camt(subchunks_by_type(keyframer, CAMERA_TARGET_INFORMATION_BLOCK, keyframer+6));
  2063.   camt.rewind();
  2064.   for(int nc=camt.size(); nc; nc--) 
  2065.   {
  2066.     if (API3DS_TEXT_OUT) cout << "Camera target info block:" << endl;
  2067.     char *info = (*camt).ptr;
  2068.     ++camt;
  2069.  
  2070.     char *objinfo = find_chunk(info, OBJECT_INFO, info+6);
  2071.     pname = (const char *)(objinfo+6);
  2072.     if (API3DS_TEXT_OUT) cout << "  Camera: " << pname << endl;
  2073.  
  2074.     char *track = find_chunk(info, POSITION_TRACK, info+6);
  2075.     if(!track)
  2076.       continue;
  2077.  
  2078.     track+=6;
  2079.     unsigned short flag = getshort(track);
  2080.     if (API3DS_TEXT_OUT) cout << "    track type: ";
  2081.     track_type_info(flag);
  2082.     if (API3DS_TEXT_OUT) cout << endl;
  2083.     unsigned short tracktype = flag;
  2084.  
  2085.     track+=10;
  2086.     if (API3DS_TEXT_OUT) cout << "    Position keys: " << (int)getlong(track) << endl;
  2087.     unsigned long keys = (int)getlong(track);
  2088.     track+=4;
  2089.     
  2090.     Dynamic<Vector3f, GLfloat> *newtrack = process_position_track(frames, keys, track, tracktype);
  2091.     if(!newtrack)
  2092.       continue;
  2093.  
  2094.     CameraTarget3DS *camera = dynamic_cast<CameraTarget3DS*>(scene->GetCamera(pname));
  2095.     if(!camera)
  2096.       continue;
  2097.     camera->Target(newtrack, true);
  2098.   }
  2099.  
  2100.   List<chunk3ds> caml(subchunks_by_type(keyframer, OMNI_LIGHT_INFORMATION_BLOCK, keyframer+6));
  2101.   caml.rewind();
  2102.   for(int nc=caml.size(); nc; nc--)
  2103.   {
  2104.     if (API3DS_TEXT_OUT) cout << "Omnilight info block:" << endl;
  2105.     char *info = (*caml).ptr;
  2106.     ++caml;
  2107.  
  2108.     char *objinfo = find_chunk(info, OBJECT_INFO, info+6);
  2109.     pname = (const char *)(objinfo+6);
  2110.     if (API3DS_TEXT_OUT) cout << "  Omnilight: " << pname << endl;
  2111.  
  2112.     Dynamic<Vector3f, GLfloat> *newtrack;
  2113.     
  2114.     unsigned short flag, tracktype;
  2115.     unsigned long keys;
  2116.  
  2117.     OmniLight3DS *light = dynamic_cast<OmniLight3DS*>(scene->GetLight(pname));
  2118.  
  2119.     char *track = find_chunk(info, POSITION_TRACK, info+6);
  2120.     if(track) {
  2121.       track+=6;
  2122.       flag = getshort(track);
  2123.       if (API3DS_TEXT_OUT) cout << "    track type: ";
  2124.       track_type_info(flag);
  2125.       if (API3DS_TEXT_OUT) cout << endl;
  2126.       tracktype = flag;
  2127.  
  2128.       track+=10;
  2129.       if (API3DS_TEXT_OUT) cout << "    Position keys: " << (int)getlong(track) << endl;
  2130.       keys = (unsigned long)getlong(track);
  2131.       track+=4;
  2132.  
  2133.       newtrack = process_position_track(frames, keys, track, tracktype);
  2134.       if(newtrack) 
  2135.         light->Position(newtrack, true);
  2136.     }
  2137.  
  2138.     track = find_chunk(info, COLOR_TRACK, info+6);
  2139.     if(track) {
  2140.       track+=6;
  2141.       flag = getshort(track);
  2142.       if (API3DS_TEXT_OUT) cout << "    track type: ";
  2143.       track_type_info(flag);
  2144.       if (API3DS_TEXT_OUT) cout << endl;
  2145.       tracktype = flag;
  2146.  
  2147.       track+=10;
  2148.       if (API3DS_TEXT_OUT) cout << "    Color keys: " << (int)getlong(track) << endl;
  2149.       keys = (unsigned long)getlong(track);
  2150.       track+=4;
  2151.  
  2152.       newtrack = process_position_track(frames, keys, track, tracktype);
  2153.       if(newtrack) 
  2154.         light->Diffuse(newtrack, true);
  2155.     }
  2156.  
  2157.   }
  2158.  
  2159.     throw 1;
  2160.   }
  2161.   catch(int value) {
  2162.     if(take_care_of_buf_alloc) {
  2163.       delete[] buffer;
  2164.       buffer = 0;
  2165.     }
  2166.     return scene;
  2167.   }
  2168. }
  2169.  
  2170. inline float
  2171. hermite_spline(float t, float P1, float R1, float P2, float R2) {
  2172.   return P1*(2*t*t*t - 3*t*t + 1) +
  2173.          R1*(t*t*t - 2*t*t + t) +
  2174.          P2*(-2*t*t*t + 3*t*t) +
  2175.          R2*(t*t*t - t*t);
  2176. }
  2177.  
  2178. Vector3f Loader3DS::position_track::getv(int sel, int n) {
  2179.   position_key *kn_1, *kn, *kn1;
  2180.   Vector3f *pn_1, *pn, *pn1;
  2181.   int d1, d2;
  2182.  
  2183.   kn = &keys[n];
  2184.   pn = &kn->p;
  2185.  
  2186.   if (sel == point) return *pn;
  2187.  
  2188.   if (n == 0) {
  2189.     //first key
  2190.     kn1 = &keys[1];
  2191.     pn1 = &kn1->p;
  2192.  
  2193.     if (count == 2) {
  2194.       //2 keys
  2195.       return (*pn1 - *pn)*(1.0F - kn->tension);
  2196.     };
  2197.     if (mode != 3) {
  2198.       //first key, no loop
  2199.       return ((*pn1 - *pn)*1.5F - getv(an,1)*0.5F)*(1.0F - kn->tension);
  2200.     } else {
  2201.       //first key, loop
  2202.       kn_1= &keys[count-2];
  2203.       d1 = keys[count-1].frame - kn_1->frame;
  2204.       d2 = kn1->frame - kn->frame;
  2205.     };
  2206.   } else if (n == count-1) {
  2207.     //last key
  2208.     kn_1 = &keys[n-1];
  2209.     pn_1 = &kn_1->p;
  2210.  
  2211.     if (count == 2) {
  2212.       //2 keys
  2213.       return (*pn - *pn_1)*(1.0F - kn->tension);
  2214.     };
  2215.     if (mode != 3) {
  2216.       //last key, no loop
  2217.       return ((*pn - *pn_1)*1.5F - getv(bn,n-1)*0.5F)*(1.0F - kn->tension);
  2218.     } else {
  2219.       //last key, loop
  2220.       kn1 = &keys[1];
  2221.       d1 = kn->frame - kn_1->frame;
  2222.       d2 = kn1->frame - keys[0].frame;
  2223.     };
  2224.   } else {
  2225.     //middle keys
  2226.     kn_1= &keys[n-1];
  2227.     kn1 = &keys[n+1];
  2228.     d1 = kn->frame - kn_1->frame;
  2229.     d2 = kn1->frame - kn->frame;
  2230.   };
  2231.   pn_1= &kn_1->p;
  2232.   pn1 = &kn1->p;
  2233.  
  2234.   float C;
  2235.   float adjust;
  2236.  
  2237.   if (sel == an) {
  2238.     C = kn->continuity;
  2239.     adjust = d1;
  2240.   } else {
  2241.     C = -kn->continuity;
  2242.     adjust = d2;
  2243.   };
  2244.   adjust /= d1 + d2;
  2245.   adjust = 0.5 + (1.0 - fabs(C))*(adjust - 0.5);
  2246.  
  2247.   return (   (*pn  - *pn_1) * ((1.0F + kn->bias)*(1.0F - C))
  2248.            + (*pn1 - *pn  ) * ((1.0F - kn->bias)*(1.0F + C))
  2249.          ) * ((1.0F - kn->tension)*adjust);
  2250. };
  2251.  
  2252. Dynamic<Vector3f, GLfloat>* Loader3DS::process_position_track(int allframes, int keys, char *track, unsigned short tracktype)
  2253. {
  2254.   if(keys<2)
  2255.     return 0;
  2256.  
  2257.   position_track keyinfo(keys, tracktype&3);
  2258.  
  2259.   for(int g=0; g<keys; g++)
  2260.   {
  2261.     if (API3DS_TEXT_OUT) cout << "    Key " << g << ": Frame " << (int)getlong(track) << ".: ";
  2262.     keyinfo[g].frame = (int)getlong(track);
  2263.     track+=4;
  2264.     unsigned short flag = getshort(track);
  2265.     tcb_info(flag);
  2266.     track = fill_tcbee(flag, track+2, &keyinfo[g]);
  2267.     float x = getfloat(track);
  2268.     float y = getfloat(track+4);
  2269.     float z = getfloat(track+8);
  2270.  
  2271.     keyinfo[g].p = Vector3f(x, y, z);
  2272.  
  2273.     if (API3DS_TEXT_OUT) cout << "  (" << x << ", " << y << ", " << z << ")" << endl;
  2274.     track+=12;
  2275.   }
  2276.  
  2277.   int first_frame = keyinfo[0].frame;
  2278.   int last_frame = keyinfo[keys-1].frame;
  2279.  
  2280.   int frames = last_frame-first_frame + 1;
  2281.  
  2282.   Vector3f *curve = new Vector3f[frames];
  2283.  
  2284.   Vector3f t1, t2;
  2285.   int k = 0;
  2286.   for(int g=first_frame; g<=last_frame; g++)
  2287.   {
  2288.     if(g>(keyinfo[k+1].frame)) {
  2289.       k++;
  2290.     }
  2291.     int d = keyinfo[k+1].frame - keyinfo[k].frame;
  2292.     double t = (double)(g-keyinfo[k].frame)/(double)d;
  2293.     t1 = keyinfo.getv(bn, k);
  2294.     t2 = keyinfo.getv(an, k+1);
  2295.     float xx = hermite_spline(t, (keyinfo[k].p).x, t1.x, (keyinfo[k+1].p).x, t2.x);
  2296.     float yy = hermite_spline(t, (keyinfo[k].p).y, t1.y, (keyinfo[k+1].p).y, t2.y);
  2297.     float zz = hermite_spline(t, (keyinfo[k].p).z, t1.z, (keyinfo[k+1].p).z, t2.z);
  2298.     curve[g-first_frame] = Vector3f(xx, yy, zz);
  2299.   }
  2300.  
  2301.   DvectorLinearFramed<Vector3f, GLfloat> *newtrack = new DvectorLinearFramed<Vector3f, GLfloat>;
  2302.   newtrack->Frames(allframes, frames, first_frame, last_frame, curve);
  2303.   return newtrack;
  2304. }
  2305.  
  2306. GLfloat Loader3DS::roll_track::getv(int sel, int n) {
  2307.   roll_key *kn_1, *kn, *kn1;
  2308.   GLfloat *pn_1, *pn, *pn1;
  2309.   int d1, d2;
  2310.  
  2311.   kn = &keys[n];
  2312.   pn = &kn->p;
  2313.  
  2314.   if (sel == point) return *pn;
  2315.  
  2316.   if (n == 0) {
  2317.     //first key
  2318.     kn1 = &keys[1];
  2319.     pn1 = &kn1->p;
  2320.  
  2321.     if (count == 2) {
  2322.       //2 keys
  2323.       return (*pn1 - *pn)*(1.0F - kn->tension);
  2324.     };
  2325.     if (mode != 3) {
  2326.       //first key, no loop
  2327.       return ((*pn1 - *pn)*1.5F - getv(an,1)*0.5F)*(1.0F - kn->tension);
  2328.     } else {
  2329.       //first key, loop
  2330.       kn_1= &keys[count-2];
  2331.       d1 = keys[count-1].frame - kn_1->frame;
  2332.       d2 = kn1->frame - kn->frame;
  2333.     };
  2334.   } else if (n == count-1) {
  2335.     //last key
  2336.     kn_1 = &keys[n-1];
  2337.     pn_1 = &kn_1->p;
  2338.  
  2339.     if (count == 2) {
  2340.       //2 keys
  2341.       return (*pn - *pn_1)*(1.0F - kn->tension);
  2342.     };
  2343.     if (mode != 3) {
  2344.       //last key, no loop
  2345.       return ((*pn - *pn_1)*1.5F - getv(bn,n-1)*0.5F)*(1.0F - kn->tension);
  2346.     } else {
  2347.       //last key, loop
  2348.       kn1 = &keys[1];
  2349.       d1 = kn->frame - kn_1->frame;
  2350.       d2 = kn1->frame - keys[0].frame;
  2351.     };
  2352.   } else {
  2353.     //middle keys
  2354.     kn_1= &keys[n-1];
  2355.     kn1 = &keys[n+1];
  2356.     d1 = kn->frame - kn_1->frame;
  2357.     d2 = kn1->frame - kn->frame;
  2358.   };
  2359.   pn_1= &kn_1->p;
  2360.   pn1 = &kn1->p;
  2361.  
  2362.   float C;
  2363.   float adjust;
  2364.  
  2365.   if (sel == an) {
  2366.     C = kn->continuity;
  2367.     adjust = d1;
  2368.   } else {
  2369.     C = -kn->continuity;
  2370.     adjust = d2;
  2371.   };
  2372.   adjust /= d1 + d2;
  2373.   adjust = 0.5 + (1.0 - fabs(C))*(adjust - 0.5);
  2374.  
  2375.   return (   (*pn  - *pn_1) * ((1.0F + kn->bias)*(1.0F - C))
  2376.            + (*pn1 - *pn  ) * ((1.0F - kn->bias)*(1.0F + C))
  2377.          ) * ((1.0F - kn->tension)*adjust);
  2378. };
  2379.  
  2380. Dynamic<GLfloat, GLfloat>* Loader3DS::process_roll_track(int allframes, int keys, char *track, unsigned short tracktype)
  2381. {
  2382.   if(keys<2)
  2383.     return 0;
  2384.  
  2385.   roll_track keyinfo(keys, tracktype&3);
  2386.  
  2387.   for(int g=0; g<keys; g++)
  2388.   {
  2389.     if (API3DS_TEXT_OUT) cout << "    Key " << g << ": Frame " << (int)getlong(track) << ".: ";
  2390.     keyinfo[g].frame = (int)getlong(track);
  2391.     track+=4;
  2392.     unsigned short flag = getshort(track);
  2393.     tcb_info(flag);
  2394.     track = fill_tcbee(flag, track+2, &keyinfo[g]);
  2395.     float x = getfloat(track);
  2396.  
  2397.     keyinfo[g].p = x;
  2398.  
  2399.     if (API3DS_TEXT_OUT) cout << "  " << x << endl;
  2400.     track+=4;
  2401.   }
  2402.  
  2403.   int first_frame = keyinfo[0].frame;
  2404.   int last_frame = keyinfo[keys-1].frame;
  2405.  
  2406.   int frames = last_frame-first_frame + 1;
  2407.  
  2408.   GLfloat *curve = new GLfloat[frames];
  2409.  
  2410.   GLfloat t1, t2;
  2411.   int k = 0;
  2412.   for(int g=first_frame; g<=last_frame; g++)
  2413.   {
  2414.     if(g>(keyinfo[k+1].frame)) {
  2415.       k++;
  2416.     }
  2417.     int d = keyinfo[k+1].frame - keyinfo[k].frame;
  2418.     double t = (double)(g-keyinfo[k].frame)/(double)d;
  2419.     t1 = keyinfo.getv(bn, k);
  2420.     t2 = keyinfo.getv(an, k+1);
  2421.     float xx = hermite_spline(t, keyinfo[k].p, t1, keyinfo[k+1].p, t2);
  2422.     curve[g-first_frame] = xx;
  2423.   }
  2424.  
  2425.   DvectorLinearFramed<GLfloat, GLfloat> *newtrack = new DvectorLinearFramed<GLfloat, GLfloat>;
  2426.   newtrack->Frames(allframes, frames, first_frame, last_frame, curve);
  2427.   return newtrack;
  2428. }
  2429.