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: ssgSaveAC.cxx 2117 2007-09-13 23:21:09Z fayjf $
22 */
23 
24 
25 #include "ssgLocal.h"
26 #include "ssgLoaderWriterStuff.h"
27 
28 static ssgSimpleStateArray gSSL ;
29 static const int writeTextureWithoutPath = TRUE ;
30 
31 struct saveTriangle
32 {
33   int    v [ 3 ] ;
34   sgVec2 t [ 3 ] ;
35 } ;
36 
37 static FILE       *save_fd ;
38 static sgVec3       *vlist ;
39 static saveTriangle *tlist ;
40 
41 
ssgSaveLeaf(ssgEntity * ent)42 static int ssgSaveLeaf ( ssgEntity *ent )
43 { int i;
44   assert ( ent -> isAKindOf ( ssgTypeLeaf() ) ) ;
45 
46   ssgLeaf *vt = (ssgLeaf *) ent ;
47 
48   int num_verts = vt -> getNumVertices  () ;
49   int num_tris  = vt -> getNumTriangles () ;
50 
51   vlist = new sgVec3 [ num_verts ] ;
52   tlist = new saveTriangle [ num_tris ] ;
53 
54   for ( i = 0 ; i < num_verts; i++ )
55     sgCopyVec3 ( vlist[i], vt->getVertex ( i ) ) ;
56 
57   for ( i = 0 ; i < num_tris ; i++ )
58   {
59     short vv0, vv1, vv2 ;
60 
61     vt -> getTriangle ( i, &vv0, &vv1, &vv2 ) ;
62 
63     tlist[i].v[0] = vv0 ;
64     tlist[i].v[1] = vv1 ;
65     tlist[i].v[2] = vv2 ;
66 
67     sgCopyVec2 ( tlist[i].t[0], vt->getTexCoord ( vv0 ) ) ;
68     sgCopyVec2 ( tlist[i].t[1], vt->getTexCoord ( vv1 ) ) ;
69     sgCopyVec2 ( tlist[i].t[2], vt->getTexCoord ( vv2 ) ) ;
70   }
71 
72   fprintf ( save_fd, "OBJECT poly\n" ) ;
73   fprintf ( save_fd, "name \"%s\"\n", ent->getPrintableName() ) ;
74 
75   ssgState* st = vt -> getState () ;
76 
77   if ( st && st -> isAKindOf ( ssgTypeSimpleState() ) )
78   {
79     ssgSimpleState* ss = (ssgSimpleState*) vt -> getState () ;
80 
81     if ( ss -> isEnabled ( GL_TEXTURE_2D ) )
82     {
83       const char* tfname = ss -> getTextureFilename () ;
84 
85       if (( tfname != NULL ) && ( tfname[0] != 0 ))
86       {
87         if ( writeTextureWithoutPath )
88         {
89 
90           const char *s = strrchr ( tfname, '\\' ) ;
91           if ( s == NULL )
92             s = strrchr ( tfname, '/' ) ;
93 
94           if ( s == NULL )
95             fprintf ( save_fd, "texture \"%s\"\n", tfname ) ;
96           else
97             fprintf ( save_fd, "texture \"%s\"\n", ++s ) ;
98         }
99         else
100           fprintf ( save_fd, "texture \"%s\"\n", tfname ) ;
101       }
102     }
103   }
104 
105   fprintf ( save_fd, "numvert %d\n", num_verts ) ;
106 
107   for ( i = 0 ; i < num_verts ; i++ )
108     fprintf ( save_fd, "%g %g %g\n", vlist[i][0],vlist[i][2],-vlist[i][1] ) ;
109 
110   fprintf ( save_fd, "numsurf %d\n", num_tris ) ;
111 
112   for ( i = 0 ; i < num_tris ; i++ )
113   {
114     fprintf ( save_fd, "SURF 0x0%x\n", (! vt -> getCullFace () ) << 5 ) ;
115     ssgState *s = vt->getState ();
116 
117     int istate = 0;
118 
119     if ( s != NULL )
120       if ( s -> isAKindOf ( ssgTypeSimpleState() ) )
121       {
122         istate = gSSL.findIndex ( (ssgSimpleState *) s ) ;
123         assert ( istate >= 0 ) ;
124       }
125 
126     fprintf ( save_fd, "mat %d\n", istate ) ;
127     fprintf ( save_fd, "refs 3\n" ) ;
128     fprintf ( save_fd, "%d %g %g\n",
129                   tlist[i].v[0],tlist[i].t[0][0],tlist[i].t[0][1] ) ;
130     fprintf ( save_fd, "%d %g %g\n",
131                   tlist[i].v[1],tlist[i].t[1][0],tlist[i].t[1][1] ) ;
132     fprintf ( save_fd, "%d %g %g\n",
133                   tlist[i].v[2],tlist[i].t[2][0],tlist[i].t[2][1] ) ;
134   }
135 
136   fprintf ( save_fd, "kids 0\n" ) ;
137 
138   delete [] vlist ;
139   delete [] tlist ;
140 
141   return TRUE ;
142 }
143 
144 
145 
ssgSaveACInner(ssgEntity * ent)146 static int ssgSaveACInner ( ssgEntity *ent )
147 {
148   /* WARNING - RECURSIVE! */
149 
150   if ( ent -> isAKindOf ( ssgTypeBranch() ) )
151   {
152     ssgBranch *br = (ssgBranch *) ent ;
153 
154     fprintf ( save_fd, "OBJECT group\n" ) ;
155     fprintf ( save_fd, "kids %d\n", ent->getNumKids() ) ;
156 
157     for ( int i = 0 ; i < br -> getNumKids () ; i++ )
158       if ( ! ssgSaveACInner( br -> getKid ( i ) ) )
159         return FALSE ;
160 
161     return TRUE ;
162   }
163 
164   return ssgSaveLeaf ( ent ) ;
165 }
166 
167 
168 
169 
ssgSaveAC(const char * filename,ssgEntity * ent)170 int ssgSaveAC ( const char *filename, ssgEntity *ent )
171 {
172   int i ;
173 
174   save_fd = fopen ( filename, "wa" ) ;
175 
176   if ( save_fd == NULL )
177   {
178     ulSetError ( UL_WARNING,
179                  "ssgSaveAC: Failed to open '%s' for writing", filename ) ;
180     return FALSE ;
181   }
182 
183   fprintf ( save_fd, "AC3Db\n" ) ;
184 
185   gSSL.collect( ent );
186 
187   /*
188     There is a *huge* problem here.
189 
190     The AC3D format doesn't support per-vertex or even
191     per-polygon colours.
192 
193     You *must* use materials.
194 
195     Hence what we really should do is to collect together
196     all the per-vertex colours in the SSG model and make
197     a material from each one (possibly more if that colour
198     is on many polygons which have different ssgSimpleState's.
199 
200     For now, I'll cheat and set the GL_COLORMATERIAL colours
201     to white - which works *reasonably* well for most heavily
202     textured models...well, at least you don't get uninitialised
203     colours coming from SSG.
204   */
205 
206   for (i = 0 ; i < gSSL.getNum(); i++)
207   {
208     sgVec4 white = { 1, 1, 1, 1 } ;
209 
210     ssgSimpleState * ss = gSSL.get(i);
211 
212     float *em = ss->getMaterial (GL_EMISSION );
213     float *sp = ss->getMaterial (GL_SPECULAR );
214     float *am = ss->getMaterial (GL_AMBIENT  );
215     float *di = ss->getMaterial (GL_DIFFUSE  );
216 
217     if ( ss->isEnabled ( GL_COLOR_MATERIAL ) )
218     {
219       switch ( ss->getColourMaterial () )
220       {
221         case GL_AMBIENT_AND_DIFFUSE : am = di = white ; break ;
222         case GL_EMISSION : em = white ; break ;
223         case GL_SPECULAR : sp = white ; break ;
224         case GL_AMBIENT  : am = white ; break ;
225         case GL_DIFFUSE  : di = white ; break ;
226       }
227     }
228 
229     int shiny = (int) ss->getShininess ();
230 
231     fprintf ( save_fd, "MATERIAL \"%s\""
232                        " rgb %f %f %f"
233                        " amb %f %f %f"
234                        " emis %f %f %f"
235                        " spec %f %f %f"
236                        " shi %d  trans %f\n",
237                        ss->getPrintableName(),
238                        di[0], di[1], di[2],
239                        am[0], am[1], am[2],
240                        em[0], em[1], em[2],
241                        sp[0], sp[1], sp[2],
242                        shiny, 1.0-di[3] ) ;
243   }
244 
245   fprintf ( save_fd, "OBJECT world\n" ) ;
246   fprintf ( save_fd, "kids 1\n" ) ;
247 
248   int bReturn = ssgSaveACInner ( ent ) ;
249 
250   gSSL.removeAll () ;
251 
252   fclose ( save_fd ) ;
253 
254   return bReturn ;
255 }
256 
257 
258