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: ssgSaveOBJ.cxx 1568 2002-09-02 06:05:49Z sjbaker $
22 */
23 
24 //
25 // Wavefront OBJ export for SSG/PLIB
26 // Ported from IVCON by Dave McClurg (dpm@efn.org) in March-2000
27 //
28 
29 #include "ssgLocal.h"
30 
31 static FILE *fileout ;
32 static int total_vert ;
33 static int total_normal ;
34 
save_vtx_table(ssgVtxTable * vt)35 static void save_vtx_table ( ssgVtxTable *vt )
36 {
37   float w = 1.0f ;
38 	short iv1, iv2;
39 
40   GLenum mode = vt -> getPrimitiveType () ;
41 	//fprintf ( fileout, "g test\n" ); wk: Pfusch fixme: is this necessary? NIV135
42 
43   if (( mode == GL_LINES ) || ( mode == GL_LINE_LOOP) || ( mode == GL_LINE_STRIP))
44   {
45     int num_vert = vt -> getNumVertices () ;
46 
47     // V: vertex coordinates.
48     for ( int i = 0; i < num_vert; i++ ) {
49       sgVec3 vert ;
50       sgCopyVec3 ( vert, vt -> getVertex ( i ) ) ;
51       fprintf ( fileout, "v %f %f %f %f\n",
52         vert[0], vert[1], vert[2], w );
53     }
54 
55 
56 
57     // L: lines.
58     fprintf ( fileout, "\n" );
59 		int num_lines = vt -> getNumLines () ;
60     for ( int j = 0; j < num_lines; j ++ )
61     { vt -> getLine ( j, &iv1, &iv2 ) ;
62       fprintf ( fileout, "l %d %d\n",
63          total_vert + j + 1,
64          total_vert + j + 2 );
65     }
66 
67     total_vert += num_vert ;
68   }
69   else if ( mode == GL_TRIANGLES ||
70     mode == GL_TRIANGLE_FAN ||
71     mode == GL_TRIANGLE_STRIP )
72   {
73     int num_vert = vt -> getNumVertices () ;
74 
75     // V: vertex coordinates.
76     for ( int i = 0; i < num_vert; i++ ) {
77       sgVec3 vert ;
78       sgCopyVec3 ( vert, vt -> getVertex ( i ) ) ;
79       fprintf ( fileout, "v %f %f %f %f\n",
80         vert[0], vert[1], vert[2], w );
81     }
82 
83     // VN: Vertex face normal vectors.
84     bool haveNormals = ( vt -> getNumNormals () >= num_vert ) ;
85     if ( haveNormals )
86     {
87       fprintf ( fileout, "\n" );
88       for ( int i = 0; i < num_vert; i++ ) {
89         sgVec3 vert ;
90         sgCopyVec3 ( vert, vt -> getNormal ( i ) ) ;
91         fprintf ( fileout, "vn %f %f %f\n",
92           vert[0], vert[1], vert[2] );
93       }
94     }
95 
96     // F: faces.
97     fprintf ( fileout, "\n" );
98     int num_face = vt -> getNumTriangles () ;
99     for ( int j = 0; j < num_face; j++ )
100     {
101       short face[3];
102       vt -> getTriangle ( j, &face[0], &face[1], &face[2] ) ;
103 
104       fprintf ( fileout, "f" );
105       for ( int ivert = 0; ivert < 3; ivert++ ) {
106         if ( haveNormals )
107           fprintf ( fileout, " %d//%d",
108             total_vert + face[ivert] + 1,
109             total_normal + face[ivert] + 1 );
110         else
111           fprintf ( fileout, " %d",
112             total_vert + face[ivert] + 1 );
113       }
114       fprintf ( fileout, "\n" );
115     }
116 
117     total_vert += num_vert ;
118     if ( haveNormals )
119        total_normal += num_vert ;
120   }
121 }
122 
123 
save_entities(ssgEntity * e)124 static void save_entities ( ssgEntity *e )
125 {
126   if ( e -> isAKindOf ( ssgTypeBranch() ) )
127   {
128     ssgBranch *br = (ssgBranch *) e ;
129 
130     for ( int i = 0 ; i < br -> getNumKids () ; i++ )
131       save_entities ( br -> getKid ( i ) ) ;
132   }
133   else
134   if ( e -> isAKindOf ( ssgTypeVtxTable() ) )
135   {
136     ssgVtxTable *vt = (ssgVtxTable *) e ;
137     save_vtx_table ( vt ) ;
138   }
139 }
140 
141 
142 /******************************************************************************/
143 
ssgSaveOBJ(const char * filename,ssgEntity * ent)144 int ssgSaveOBJ ( const char *filename, ssgEntity *ent )
145 
146 /******************************************************************************/
147 
148 /*
149   Purpose:
150 
151     OBJ_WRITE writes a Wavefront OBJ file.
152 
153   Example:
154 
155     #  magnolia.obj
156 
157     mtllib ./vp.mtl
158 
159     g
160     v -3.269770 -39.572201 0.876128
161     v -3.263720 -39.507999 2.160890
162     ...
163     v 0.000000 -9.988540 0.000000
164     g stem
165     s 1
166     usemtl brownskn
167     f 8 9 11 10
168     f 12 13 15 14
169     ...
170     f 788 806 774
171 
172   Modified:
173 
174     01 September 1998
175 
176   Author:
177 
178     John Burkardt
179 */
180 {
181   fileout = fopen ( filename, "wa" ) ;
182 
183   if ( fileout == NULL )
184   {
185     ulSetError ( UL_WARNING, "ssgSaveOBJ: Failed to open '%s' for writing", filename ) ;
186     return FALSE ;
187   }
188 
189 /*
190   Initialize.
191 */
192   fprintf ( fileout, "# %s created by SSG.\n", filename );
193   fprintf ( fileout, "\n" );
194   fprintf ( fileout, "g SSG\n" );
195   fprintf ( fileout, "\n" );
196 
197   total_vert = 0 ;
198   total_normal = 0 ;
199 
200   save_entities ( ent ) ;
201 
202 /*
203   Close.
204 */
205   fclose ( fileout ) ;
206   return TRUE;
207 }
208