1 /*
2      PLIB - A Suite of Portable Game Libraries
3      Copyright (C) 1998,2002  Steve Baker
4 
5      This library is free software; you can redistribute it and/or
6      modify it under the terms of the GNU Library General Public
7      License as published by the Free Software Foundation; either
8      version 2 of the License, or (at your option) any later version.
9 
10      This library is distributed in the hope that it will be useful,
11      but WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      Library General Public License for more details.
14 
15      You should have received a copy of the GNU Library General Public
16      License along with this library; if not, write to the Free Software
17      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
18 
19      For further information visit http://plib.sourceforge.net
20 
21      $Id: ssgSaveIV.cxx 2011 2005-01-15 17:59:31Z sjbaker $
22 */
23 
24 //
25 // IV ( Open Inventor ASCII ) export for SSG/PLIB
26 // Written by Bram Stolk (bram at sara.nl)
27 //
28 // Keep in mind that:
29 // ssg's Transform's are non-leaf nodes, which correspond to Inventor's
30 // Transform nodes which are leaf nodes.
31 // Inventor's Material nodes are scene graph leaf nodes.
32 // The corresponding State objects from ssg however, are not scene graph nodes.
33 //
34 // DONE:
35 // scene graph hierarchy
36 // transformation
37 // states
38 // colour per vertex
39 // normal per vertex
40 // textures
41 // texture coordinates
42 // alpha transparency
43 //
44 // TODO:
45 // lights
46 // rendermodes
47 //
48 
49 
50 #include <assert.h>
51 
52 #include "ssgLocal.h"
53 
54 
55 // auxiliary stuff for indenting the inventor file.
56 static int indentLevel ;
indent(FILE * f)57 static void indent ( FILE *f )
58 {
59   for ( int i=0; i<indentLevel; i++ )
60     fprintf( f, "  " ) ;
61 }
62 
63 
writeTransform(ssgTransform * transform,FILE * f)64 static void writeTransform ( ssgTransform *transform, FILE *f )
65 {
66   indent( f ) ;
67   sgMat4 m;
68   transform->getTransform( m ) ;
69   fprintf
70   (
71     f,
72     "MatrixTransform { matrix %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f }\n",
73     m[0][0], m[0][1], m[0][2], m[0][3],
74     m[1][0], m[1][1], m[1][2], m[1][3],
75     m[2][0], m[2][1], m[2][2], m[2][3],
76     m[3][0], m[3][1], m[3][2], m[3][3]
77   ) ;
78 }
79 
80 
81 // ssg leaf nodes contain the geometry, which we will convert to
82 // Inventor's IndexedFaceSet.
writeLeaf(ssgLeaf * leaf,FILE * f)83 static void writeLeaf ( ssgLeaf *leaf, FILE *f )
84 {
85   int cnt = leaf->getNumTriangles() ;
86   int nv  = leaf->getNumVertices() ;
87   int nn  = leaf->getNumNormals() ;
88   int nc  = leaf->getNumColours() ;
89   int nt  = leaf->getNumTexCoords() ;
90 
91   ssgState *st = leaf->getState() ;
92   ssgSimpleState *state = 0 ;
93   char *textureName = 0 ;
94   int i;
95 
96   indent( f );
97   fprintf( f, "# %d triangles, %d verts, %d normals, %d colours, %d texturecoords\n", cnt, nv,nn,nc,nt ) ;
98 
99   if ( st && st -> isAKindOf ( ssgTypeSimpleState() ) )
100   {
101     state = (ssgSimpleState*) st ;
102     textureName = state->getTextureFilename();
103   }
104   else
105     state = NULL ;
106 
107   if ( state || nc )
108   {
109     indent( f ) ;
110     fprintf( f, "Material {\n" ) ;
111     indentLevel++ ;
112 
113     indent( f ) ;
114     fprintf( f, "diffuseColor " ) ;
115     if ( nc )
116     {
117       // multiple colour values: colour-per-vertex
118       fprintf( f, "[ " ) ;
119       for ( i=0; i<nc; i++ )
120       {
121         float *col = leaf->getColour( i ) ;
122         fprintf( f,"%f %f %f, ", col[0],col[1],col[2] ) ;
123       }
124       fprintf( f, "]\n" ) ;
125     }
126     else
127     {
128       // single colour value
129       float r=0, g=0, b=0;
130       if ( state )
131       {
132         r = state->diffuse_colour[ 0 ] ;
133         g = state->diffuse_colour[ 1 ] ;
134         b = state->diffuse_colour[ 2 ] ;
135       }
136       fprintf( f, "%f %f %f\n", r,g,b ) ;
137     }
138     if ( state )
139     {
140       indent( f );
141       fprintf( f,"ambientColor %f %f %f\n", state->ambient_colour[0], state->ambient_colour[1], state->ambient_colour[2] ) ;
142       indent( f );
143       fprintf( f,"specularColor %f %f %f\n", state->specular_colour[0], state->specular_colour[1], state->specular_colour[2] ) ;
144       indent( f );
145       fprintf( f,"emissiveColor %f %f %f\n", state->emission_colour[0], state->emission_colour[1], state->emission_colour[2] ) ;
146       indent( f );
147       fprintf( f, "shininess %f\n", state->shininess ) ;
148       if ( state->isEnabled( GL_BLEND ) )
149       {
150         float a = state->diffuse_colour[ 3 ] ;
151         indent( f ) ;
152         fprintf( f, "transparency %f\n", 1.0-a );
153       }
154     }
155 
156     indentLevel-- ;
157     indent( f ) ;
158     fprintf( f, "}\n" ) ;
159   }
160 
161   if ( textureName )
162   {
163     indent( f ) ;
164     fprintf( f, "Texture2 { filename %c%s%c }\n", '"', textureName, '"' ) ;
165   }
166 
167   if ( nn )
168   {
169     indent( f ) ;
170     fprintf( f, "Normal {\n") ;
171     indentLevel++ ;
172 
173     indent( f ) ;
174     fprintf( f, "vector [ " ) ;
175     for ( i=0; i<nn; i++ )
176     {
177       float *nrm = leaf->getNormal( i ) ;
178       fprintf( f, "%f %f %f, ", nrm[ 0 ], nrm[ 1 ], nrm[ 2 ] );
179     }
180     fprintf( f, " ]\n" );
181     indentLevel-- ;
182 
183     indent( f ) ;
184     fprintf( f, "}\n" ) ;
185   }
186 
187   if ( nt && textureName )
188   {
189     indent( f ) ;
190     fprintf( f, "SoTextureCoordinate2 { point [ " ) ;
191     for ( i=0; i<nt; i++ )
192     {
193       float *t = leaf->getTexCoord( i ) ;
194       fprintf( f, "%f %f, ", t[ 0 ], t[ 1 ] ) ;
195     }
196     fprintf( f, " ] }\n" ) ;
197   }
198 
199   indent( f ) ;
200   fprintf( f, "Coordinate3 { point [ " ) ;
201   for ( i=0; i<nv; i++ )
202   {
203     float *v = leaf->getVertex( i ) ;
204     assert( v ) ;
205     fprintf( f, "%f %f %f, ", v[ 0 ], v[ 1 ], v[ 2 ] ) ;
206   }
207   fprintf( f, " ] }\n" ) ;
208 
209   indent( f ) ;
210   fprintf( f, "IndexedFaceSet {\n" ) ;
211 
212   indent( f ) ;
213   fprintf( f, "  coordIndex [ " ) ;
214   for ( i=0; i<cnt; i++ )
215   {
216     short idx0, idx1, idx2 ;
217     leaf->getTriangle( i, &idx0, &idx1, &idx2 ) ;
218     fprintf( f, "%d,%d,%d,-1,", idx0, idx1, idx2 ) ;
219   }
220 
221   fprintf( f, " ]\n" ) ;
222   indent( f ) ;
223   fprintf( f, "}\n" ) ;
224 }
225 
226 
227 // Handles pre-order traversal of the ssg hierarchy.
preHandle(ssgEntity * ent,FILE * f)228 static void preHandle ( ssgEntity *ent, FILE *f )
229 {
230   // Put some comments in the inventor output file.
231   indent( f ) ;
232   const char *name = ent->getName() ;
233   fprintf( f, "# %s (%s)\n", ent->getTypeName(), (name)?name:"unnamed") ;
234 
235   if ( ent && ent -> isAKindOf ( ssgTypeBranch () ) )
236   {
237     ssgBranch *branch = (ssgBranch*) ent ;
238 
239     // ssg's branch nodes are translated to inventor's separator node.
240     indent( f ) ;
241     fprintf( f,"Separator {\n" ) ;
242     indentLevel++ ;
243 
244     if ( branch -> isAKindOf ( ssgTypeTransform() ) )
245       writeTransform( (ssgTransform*) branch, f ) ;
246   }
247   else
248     writeLeaf( (ssgLeaf*) ent, f ) ;
249 }
250 
251 
252 // Handles post-order traversal of the ssg hierarchy.
postHandle(ssgEntity * ent,FILE * f)253 static void postHandle ( ssgEntity *ent, FILE *f )
254 {
255   if ( ent && ent -> isAKindOf ( ssgTypeBranch() ) )
256   {
257     // For branches, we use IV's Seperator, which we need to close now.
258     indentLevel-- ;
259     indent( f ) ;
260     fprintf( f, "}\n" ) ;
261   }
262 }
263 
264 
265 // Traverses ssg hierarchy.
walkTree(ssgEntity * ent,FILE * f)266 static void walkTree ( ssgEntity *ent, FILE *f )
267 {
268   preHandle( ent, f ) ;
269   if ( ent && ent -> isAKindOf ( ssgTypeBranch() ) )
270   {
271     ssgBranch *branch = (ssgBranch*) ent ;
272 
273     for ( int i=0; i<branch->getNumKids(); i++ )
274     {
275       ssgEntity *kid = branch->getKid( i );
276       assert( kid ) ;
277       walkTree( kid, f ) ;
278     }
279   }
280   postHandle( ent, f ) ;
281 }
282 
283 
284 // Entry point: save ssg hierarchy as an OpenInventor file.
ssgSaveIV(const char * filename,ssgEntity * ent)285 int ssgSaveIV ( const char *filename, ssgEntity *ent )
286 {
287   FILE *f = fopen( filename, "w" ) ;
288   if ( !f )
289     return FALSE ;
290   fprintf( f, "#Inventor V2.1 ascii\n" ) ;
291   fprintf
292   (
293     f,
294     "#Export from plib version %d.%d.%d\n\n",
295     PLIB_MAJOR_VERSION, PLIB_MINOR_VERSION, PLIB_TINY_VERSION
296   ) ;
297   indentLevel = 0 ;
298   walkTree( ent, f ) ;
299   return TRUE ;
300 }
301 
302