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