[Plib-cvs] CVS: plib/src/ssg ssgSaveVRML1.cxx,NONE,1.1 Makefile.am,1.30,1.31 ssg.cxx,1.44,1.45 ssg.h
Brought to you by:
sjbaker
|
From: Wolfram K. <wol...@us...> - 2002-01-17 16:14:27
|
Update of /cvsroot/plib/plib/src/ssg
In directory usw-pr-cvs1:/tmp/cvs-serv8987
Modified Files:
Makefile.am ssg.cxx ssg.h
Added Files:
ssgSaveVRML1.cxx
Log Message:
Adding ssgSaveVRML1
--- NEW FILE: ssgSaveVRML1.cxx ---
/*
PLIB - A Suite of Portable Game Libraries
Copyright (C) 2001 Steve Baker
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
For further information visit http://plib.sourceforge.net
$Id: ssgSaveVRML1.cxx,v 1.1 2002/01/17 16:14:23 wolfram_kuss Exp $
--------------------------------------------------------------------
This save routine was written by Warren Wilbur to support a sub-set
of the standard Virtual Reality Modelling Language v1.0 (i.e. VRML1.0).
The Version 1.0 Specification, 9-Nov-95 was used and should be available
at www.vrml.org
When reporting bugs/difficulties please mention 'VRML' in the subject
of your email and post to the plib developers mailing list.
*/
#include <stdio.h>
#include "ssgLocal.h"
#include "ssgLoaderWriterStuff.h"
/* Function name: SaveVRML1MaterialNode
*
* Limitations: Before calling this function you must verify that
* at least one material exists whose textureName
* matches the one passed in to this function,
* otherwise you might save a empty Material node!
*
* Notes: Saving empty Material notes will create an
* unnecessary choking hazard for VRML loaders :(
*/
static void SaveVRML1MaterialNode(FILE *fd, ssgIndexArray *materials_ptr,
ssgSimpleStateArray *ssa_ptr,
char *textureName, bool saveDiffuse,
bool saveAmbient, bool saveEmission,
bool saveSpecular)
{
ssgSimpleState *ss_ptr;
int i;
/* Tell VRML loaders that we are providing a single color for each
* face in the array of indices written below. */
fprintf(fd, " MaterialBinding { value PER_FACE }\n");
fprintf(fd, " Material {\n");
if (saveDiffuse)
{
fprintf(fd, " diffuseColor [\n");
for (i = 0; i < materials_ptr->getNum(); i++)
{
ss_ptr = ssa_ptr->get(*(materials_ptr->get(i)));
/* If we are trying to save all untextured materials then check
* if either ptr is NULL */
if ( ( (textureName == NULL)&&
((ss_ptr == NULL)||(ss_ptr->getTextureFilename() == NULL)) )||
/* If we are trying to save all materials that are textured by
* a specific texture then check if the texture filename matches */
( (textureName != NULL)&&(ss_ptr != NULL)&&
(ss_ptr->getTextureFilename() != NULL)&&
(!strcmp(textureName, ss_ptr->getTextureFilename())) ) )
{
float diffuse0, diffuse1, diffuse2;
diffuse0 = ss_ptr->diffuse_colour[0];
diffuse1 = ss_ptr->diffuse_colour[1];
diffuse2 = ss_ptr->diffuse_colour[2];
#ifdef EXPERIMENTAL_ADD_AMBIENT_TO_DIFFUSE
diffuse0 += ss_ptr->ambient_colour[0];
diffuse1 += ss_ptr->ambient_colour[1];
diffuse2 += ss_ptr->ambient_colour[2];
#endif //EXPERIMENTAL_ADD_AMBIENT_TO_DIFFUSE
#ifdef EXPERIMENTAL_ADD_EMISSION_TO_DIFFUSE
diffuse0 += ss_ptr->emission_colour[0];
diffuse1 += ss_ptr->emission_colour[1];
diffuse2 += ss_ptr->emission_colour[2];
#endif //EXPERIMENTAL_ADD_EMISSION_TO_DIFFUSE
#ifdef EXPERIMENTAL_ADD_SPECULAR_TO_DIFFUSE
diffuse0 += ss_ptr->specular_colour[0];
diffuse1 += ss_ptr->specular_colour[1];
diffuse2 += ss_ptr->specular_colour[2];
#endif //EXPERIMENTAL_ADD_SPECULAR_TO_DIFFUSE
/* OpenGL caps the maximum RGB value for a colour to 1.0 when it
* calculates colours in a scene. If we don't cap the value OpenGL
* will do it for us. */
fprintf(fd, " %f %f %f,\n", diffuse0 > 1.0 ? 1.0:diffuse0,
diffuse1 > 1.0 ? 1.0:diffuse1, diffuse2 > 1.0 ? 1.0:diffuse2);
}
}
fprintf(fd, " ]\n"); //close diffuseColor array
}
if (saveAmbient)
{
fprintf(fd, " ambientColor [\n");
for (i = 0; i < materials_ptr->getNum(); i++)
{
ss_ptr = ssa_ptr->get(*(materials_ptr->get(i)));
/* If we are trying to save all untextured materials then check
* if either ptr is NULL */
if ( ( (textureName == NULL)&&
((ss_ptr == NULL)||(ss_ptr->getTextureFilename() == NULL)) )||
/* If we are trying to save all materials that are textured by
* a specific texture then check if the texture filename matches */
( (textureName != NULL)&&(ss_ptr != NULL)&&
(ss_ptr->getTextureFilename() != NULL)&&
(!strcmp(textureName, ss_ptr->getTextureFilename())) ) )
{
fprintf(fd, " %f %f %f,\n", ss_ptr->ambient_colour[0],
ss_ptr->ambient_colour[1], ss_ptr->ambient_colour[2]);
}
fprintf(fd, " ]\n"); //close ambientColor array
}
}
if(saveEmission)
{
fprintf(fd, " emissiveColor [\n");
for (i = 0; i < materials_ptr->getNum(); i++)
{
ss_ptr = ssa_ptr->get(*(materials_ptr->get(i)));
/* If we are trying to save all untextured materials then check
* if either ptr is NULL */
if ( ( (textureName == NULL)&&
((ss_ptr == NULL)||(ss_ptr->getTextureFilename() == NULL)) )||
/* If we are trying to save all materials that are textured by
* a specific texture then check if the texture filename matches */
( (textureName != NULL)&&(ss_ptr != NULL)&&
(ss_ptr->getTextureFilename() != NULL)&&
(!strcmp(textureName, ss_ptr->getTextureFilename())) ) )
{
fprintf(fd, " %f %f %f,\n", ss_ptr->emission_colour[0],
ss_ptr->emission_colour[1], ss_ptr->emission_colour[2]);
}
fprintf(fd, " ]\n"); //close emissionColor array
}
}
if(saveSpecular)
{
fprintf(fd, " specularColor [\n");
for (i = 0; i < materials_ptr->getNum(); i++)
{
ss_ptr = ssa_ptr->get(*(materials_ptr->get(i)));
/* If we are trying to save all untextured materials then check
* if either ptr is NULL */
if ( ( (textureName == NULL)&&
((ss_ptr == NULL)||(ss_ptr->getTextureFilename() == NULL)) )||
/* If we are trying to save all materials that are textured by
* a specific texture then check if the texture filename matches */
( (textureName != NULL)&&(ss_ptr != NULL)&&
(ss_ptr->getTextureFilename() != NULL)&&
(!strcmp(textureName, ss_ptr->getTextureFilename())) ) )
{
fprintf(fd, " %f %f %f,\n", ss_ptr->specular_colour[0],
ss_ptr->specular_colour[1], ss_ptr->specular_colour[2]);
}
fprintf(fd, " ]\n"); //close specularColor array
}
}
fprintf(fd, " }\n"); //close Material node
return;
}
/* The 'main' entry point for saving a model in VRML1.0 */
int ssgSaveVRML1( const char* fname, ssgEntity *ent ) {
ssgVertexArray *vertices_ptr;
ssgIndexArray *indices_ptr;
FILE *fd;
ssgSimpleStateArray ssa;
ssgTexCoordArray *texcoord_ptr;
ssgIndexArray *materials_ptr;
bool textured_faces_found, untextured_faces_found,
textureFacesAlreadySaved;
int i, j, index1, index2, index3;
ssgSimpleState *ss_ptr, *ss_ptr2;
fd = fopen ( fname, "w" ) ;
if ( fd == NULL )
{
ulSetError ( UL_WARNING, "ssgSaveVRML1: Failed to open '%s' for writing",
fname );
return FALSE ;
}
vertices_ptr = new ssgVertexArray();
indices_ptr = new ssgIndexArray();
materials_ptr = new ssgIndexArray();
texcoord_ptr = new ssgTexCoordArray();
sgMat4 ident;
sgMakeIdentMat4( ident );
ssgAccumVerticesAndFaces( ent, ident, vertices_ptr, indices_ptr, -1.0f,
&ssa, materials_ptr, texcoord_ptr);
/* The spec requires every file to begin with these characters */
fprintf(fd, "#VRML V1.0 ascii\n\n");
/* Since a VRML file contains only one parent node we must use a
* node type that can have several child 'nodes' so we can save
* the materials, texture coordinates, vertices, and indices each
* as (seperate) child nodes. */
fprintf(fd, "Separator {\n");
/* Save all the individual vertices used in the model. It doesn't
* matter if there are duplicates... */
fprintf(fd, " Coordinate3 {\n point [\n");
for (i = 0; i < vertices_ptr->getNum(); i++)
{
fprintf(fd, " %f %f %f,\n", vertices_ptr->get(i)[0],
vertices_ptr->get(i)[1], vertices_ptr->get(i)[2]);
}
fprintf(fd, " ]\n }\n"); //close point array and
//Coordinate3
/* Chcck if the model is textured at all. This test will help us parse
* out how to save the model since it may be totally textured, partially
* textured, or not textured at all. */
textured_faces_found = false;
untextured_faces_found = false;
for (i = 0; i < materials_ptr->getNum(); i++)
{
ss_ptr = ssa.get(*(materials_ptr->get(i)));
if ( (ss_ptr != NULL)&&(ss_ptr->getTextureFilename() != NULL) )
{
textured_faces_found = true;
}
else
{
untextured_faces_found = true;
}
}
if (untextured_faces_found)
{
/* Save all the material node fields which VRML supports. Note that the
* VRML spec discourages complicated uses of the Material Node. We
* cannot expect VRML implementations to support the full syntax
* of the Material Node including ambient, diffuse, specular, emissive,
* shininess, and transparency. We should be always be okay if we just
* use diffuse. */
SaveVRML1MaterialNode(fd, materials_ptr, &ssa, NULL,
true, false, false, false);
/* Save all faces that are not textured in a single IndexedFaceSet node */
fprintf(fd, " IndexedFaceSet {\n coordIndex [\n");
for (i = 0; i < indices_ptr->getNum(); i+=3)
{
ss_ptr = ssa.get(*(materials_ptr->get(i/3)));
/* Make sure this face doesn't have a texture associated with it */
if ( (ss_ptr == NULL)||(ss_ptr->getTextureFilename() == NULL) )
{
index1 = *indices_ptr->get(i);
index2 = *indices_ptr->get(i+1);
index3 = *indices_ptr->get(i+2);
/* Check for index overflow since PLIB stores it as a short */
if ( (index1 < 0)||(index2 < 0)||(index3 < 0) )
{
printf("Save error: index overflow, value won't fit in 16bits.\n");
}
else
{
fprintf(fd, " %d, %d, %d, -1,\n", index1, index2,
index3);
}
}
}
fprintf(fd, " ]\n }\n"); //close coordIndex array and
//IndexedFaceSet
}
if (textured_faces_found)
{
/* Save all texture coordinates (per-vertex) for all the textures in
* the model. It doesn't matter if there is one texture or more than
* one since we will specify which texture to use with the coordinates
* before saving the portion of the indexed face set which uses that
* texture. */
fprintf(fd, " TextureCoordinate2 {\n point [\n");
for (i = 0; i < texcoord_ptr->getNum(); i++)
{
/* In VrmlView Pro 3.0 (Linux) textured models appear correct Left-Right
* but the texture is reversed Top-Bottom. Enabling the INVERSE_REPEAT
* macro fixes the problem for VrmlView. I don't want to enable this until
* I figure out where the problem really is!? */
//#define INVERSE_REPEAT(a) (a > 0.0 ? 1.0 - a:a + 1.0)
#define INVERSE_REPEAT(a) a
fprintf(fd, " %f %f,\n", texcoord_ptr->get(i)[0],
INVERSE_REPEAT(texcoord_ptr->get(i)[1]));
}
fprintf(fd, " ]\n }\n");
/* Now save separate Texture2 and IndexedFaceSet node pairs for each
* texture used in the model. Each of the IndexedFaceSet(s) will
* reference back to the initial vertices, materials, and texture
* coordinates (due to the lack of Seperator nodes in between).
* Find the first textured face starting at the i'th face. In this
* manner we will find the next texture used in the model and save
* all faces that are textured with it. */
for (i = 0; i < indices_ptr->getNum(); i+=3)
{
ss_ptr = ssa.get(*(materials_ptr->get(i/3)));
if ( (ss_ptr != NULL)&&(ss_ptr->getTextureFilename() != NULL) )
{
/* We've found the next textured face. Since we save all
* faces using a texture when we find the first face using
* that texture we must check if the faces for this texture
* have already been saved. If we can find a face using
* this texture earlier in the list of faces then we know
* that it has already been saved. */
textureFacesAlreadySaved = false;
for (j = 0; j < i; j+=3)
{
ss_ptr2 = ssa.get(*(materials_ptr->get(j/3)));
if ( (ss_ptr2 != NULL)&&
(ss_ptr2->getTextureFilename() != NULL)&&
(!strcmp(ss_ptr->getTextureFilename(),
ss_ptr2->getTextureFilename())) )
{
textureFacesAlreadySaved = true;
break;
}
}
if (!textureFacesAlreadySaved)
{
fprintf(fd, " Texture2 {\n");
fprintf(fd, " filename %s\n", ss_ptr->getTextureFilename());
//TODO: support CLAMP mode as well.
fprintf(fd, " wrapS REPEAT\n");
fprintf(fd, " wrapT REPEAT\n");
fprintf(fd, " }\n");
/* Save all the materials needed by this following indexed face
* set. This will save all materials that have the same texture
* filename specified below. */
SaveVRML1MaterialNode(fd, materials_ptr, &ssa,
ss_ptr->getTextureFilename(),
true, false, false, false);
fprintf(fd, " IndexedFaceSet {\n coordIndex [\n");
for (j = i; j < indices_ptr->getNum(); j+=3)
{
/* Save each face which is textured by the Texture2 node defined
* above. */
ss_ptr2 = ssa.get(*(materials_ptr->get(j/3)));
if ( (ss_ptr2 != NULL)&&
(ss_ptr2->getTextureFilename() != NULL)&&
(!strcmp(ss_ptr->getTextureFilename(),
ss_ptr2->getTextureFilename())) )
{
index1 = *indices_ptr->get(j);
index2 = *indices_ptr->get(j+1);
index3 = *indices_ptr->get(j+2);
/* Check for index overflow since PLIB stores it as a
* short */
if ( (index1 < 0)||(index2 < 0)||(index3 < 0) )
{
printf("Save error: index overflow, value "
"won't fit in 16bits.\n");
}
else
{
fprintf(fd, " %d, %d, %d, -1,\n",
index1, index2, index3);
}
}
}
fprintf(fd, " ]\n }\n"); //close coordIndex array and
//IndexedFaceSet
}
}
}
}
fprintf(fd, "}\n"); //close Seperator
fclose( fd ) ;
delete vertices_ptr;
delete indices_ptr;
delete materials_ptr;
delete texcoord_ptr;
return TRUE;
}
Index: Makefile.am
===================================================================
RCS file: /cvsroot/plib/plib/src/ssg/Makefile.am,v
retrieving revision 1.30
retrieving revision 1.31
diff -u -d -r1.30 -r1.31
--- Makefile.am 2001/10/03 10:21:10 1.30
+++ Makefile.am 2002/01/17 16:14:22 1.31
@@ -18,7 +18,7 @@
ssgLoadOBJ.cxx ssgSaveOBJ.cxx ssgVtxArray.cxx ssgLoadMD2.cxx \
ssgLoadMDL.cxx ssgLoadX.cxx ssgSaveX.cxx ssgLoaderWriterStuff.cxx \
ssgLoadFLT.cxx ssgLoadM.cxx ssgSaveM.cxx ssgLoadStrip.cxx \
- ssgLoadOFF.cxx ssgSaveOFF.cxx ssgSaveQHI.cxx ssgLoadVRML1.cxx \
+ ssgLoadOFF.cxx ssgSaveOFF.cxx ssgSaveQHI.cxx ssgLoadVRML1.cxx ssgSaveVRML1.cxx\
ssgLoaderWriterStuff.h ssgMSFSPalette.h ssg3ds.h ssgLoadMDL.h \
ssgSave3ds.cxx ssgAxisTransform.cxx ssgLoadATG.cxx ssgSaveATG.cxx\
ssgLoadIV.cxx ssgLoad.cxx ssgLoadVRML.h
Index: ssg.cxx
===================================================================
RCS file: /cvsroot/plib/plib/src/ssg/ssg.cxx,v
retrieving revision 1.44
retrieving revision 1.45
diff -u -d -r1.44 -r1.45
--- ssg.cxx 2001/12/17 05:09:09 1.44
+++ ssg.cxx 2002/01/17 16:14:22 1.45
@@ -136,7 +136,7 @@
ssgAddModelFormat ( ".off" , ssgLoadOFF , ssgSaveOFF ) ;
ssgAddModelFormat ( ".atg" , ssgLoadATG , ssgSaveATG ) ;
ssgAddModelFormat ( ".qhi" , NULL , ssgSaveQHI ) ;
- ssgAddModelFormat ( ".wrl", ssgLoadVRML1 , NULL ) ;
+ ssgAddModelFormat ( ".wrl", ssgLoadVRML1, ssgSaveVRML1 ) ;
ssgAddModelFormat ( ".iv", ssgLoadIV , NULL ) ;
Index: ssg.h
===================================================================
RCS file: /cvsroot/plib/plib/src/ssg/ssg.h,v
retrieving revision 1.128
retrieving revision 1.129
diff -u -d -r1.128 -r1.129
--- ssg.h 2001/12/17 04:52:30 1.128
+++ ssg.h 2002/01/17 16:14:23 1.129
@@ -2609,6 +2609,7 @@
int ssgSaveQHI ( const char *fname, ssgEntity *ent ) ;
int ssgSave3ds ( const char *fname, ssgEntity *ent ) ;
int ssgSaveATG ( const char *fname, ssgEntity *ent ) ;
+int ssgSaveVRML1( const char *fname, ssgEntity *ent ) ;
ssgEntity *ssgLoad ( const char *fname, const ssgLoaderOptions *options = NULL ) ;
|