From Geoff Michel, added AC3D .ac and GEO .geo loaders.

This commit is contained in:
Robert Osfield
2002-10-31 12:51:09 +00:00
parent 21ee9e4cb7
commit 24746728e4
14 changed files with 4515 additions and 1 deletions

View File

@@ -26,8 +26,10 @@ PLUGIN_DIRS = \
osgParticle\
osgText\
rgb\
ac3d\
lib3ds\
flt\
geo\
iv\
obj\
lwo\

View File

@@ -1044,7 +1044,28 @@ Package=<4>
###############################################################################
Project: "osgPlugin flt"=.\osgPlugins\flt\flt.dsp - Package Owner=<4>
Project: "osgPlugin geo"=.\osgPlugins\geo\geo.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name Core osg
End Project Dependency
Begin Project Dependency
Project_Dep_Name Core osgDB
End Project Dependency
Begin Project Dependency
Project_Dep_Name Core osgUtil
End Project Dependency
}}}
###############################################################################
Project: "osgPlugin ac3d"=.\osgPlugins\ac3d\ac3d.dsp - Package Owner=<4>
Package=<5>
{{{

View File

@@ -0,0 +1,109 @@
# Microsoft Developer Studio Project File - Name="osgPlugin ac3d" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
CFG=osgPlugin ac3d - Win32 Release
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "ac3d.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "ac3d.mak" CFG="osgPlugin ac3d - Win32 Release"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "osgPlugin ac3d - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "osgPlugin ac3d - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
MTL=midl.exe
RSC=rc.exe
!IF "$(CFG)" == "osgPlugin ac3d - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "../../../lib"
# PROP Intermediate_Dir "Release"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /YX /FD /c
# ADD CPP /nologo /MD /W3 /GR /GX /O2 /I "../../../include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /YX /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x809 /d "NDEBUG"
# ADD RSC /l 0x809 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
# ADD LINK32 /nologo /dll /pdb:none /machine:I386 /nodefaultlib:"LIBC" /out:"../../../bin/osgdb_ac.dll" /libpath:"../../../lib"
# SUBTRACT LINK32 /nodefaultlib
!ELSEIF "$(CFG)" == "osgPlugin ac3d - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "../../../lib"
# PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /YX /FD /GZ /c
# ADD CPP /nologo /MDd /W3 /Gm /vmg /vd0 /GR /GX /Zi /Od /I "../../../include" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "WIN32" /D "_DEBUG" /YX /FD /GZ /c
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x809 /d "_DEBUG"
# ADD RSC /l 0x809 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
# ADD LINK32 /nologo /dll /debug /machine:I386 /nodefaultlib:"LIBC" /out:"../../../bin/osgdb_ac.dll" /pdbtype:sept /libpath:"../../../lib"
# SUBTRACT LINK32 /nodefaultlib
!ENDIF
# Begin Target
# Name "osgPlugin ac3d - Win32 Release"
# Name "osgPlugin ac3d - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\ac3d\ac3d.cpp
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# End Group
# Begin Group "Resource Files"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
# End Group
# End Target
# End Project

View File

@@ -0,0 +1,125 @@
# Microsoft Developer Studio Project File - Name="osgPlugin geo" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
CFG=osgPlugin geo - Win32 Release
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "geo.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "geo.mak" CFG="osgPlugin geo - Win32 Release"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "osgPlugin geo - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "osgPlugin geo - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
MTL=midl.exe
RSC=rc.exe
!IF "$(CFG)" == "osgPlugin geo - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "../../../lib"
# PROP Intermediate_Dir "Release"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /YX /FD /c
# ADD CPP /nologo /MD /W3 /GR /GX /O2 /I "../../../include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /YX /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x809 /d "NDEBUG"
# ADD RSC /l 0x809 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
# ADD LINK32 /nologo /dll /pdb:none /machine:I386 /nodefaultlib:"LIBC" /out:"../../../bin/osgdb_geo.dll" /libpath:"../../../lib"
# SUBTRACT LINK32 /nodefaultlib
!ELSEIF "$(CFG)" == "osgPlugin geo - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "../../../lib"
# PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /YX /FD /GZ /c
# ADD CPP /nologo /MDd /W3 /Gm /vmg /vd0 /GR /GX /Zi /Od /I "../../../include" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "WIN32" /D "_DEBUG" /YX /FD /GZ /c
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x809 /d "_DEBUG"
# ADD RSC /l 0x809 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
# ADD LINK32 /nologo /dll /debug /machine:I386 /nodefaultlib:"LIBC" /out:"../../../bin/osgdb_geod.dll" /pdbtype:sept /libpath:"../../../lib"
# SUBTRACT LINK32 /nodefaultlib
!ENDIF
# Begin Target
# Name "osgPlugin geo - Win32 Release"
# Name "osgPlugin geo - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\geo\ReaderWriterGEO.cpp
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\geo\geoFormat.h
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\geo\geoTypes.h
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\geo\geoUnits.h
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\geo\osgGeoStructs.h
# End Source File
# End Group
# Begin Group "Resource Files"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
# End Group
# End Target
# End Project

View File

@@ -0,0 +1,13 @@
TOPDIR = ../../..
include $(TOPDIR)/Make/makedefs
CXXFILES =\
ac3d.cpp\
LIBS += $(OSG_LIBS) $(OTHER_LIBS)
TARGET_BASENAME = ac
include $(TOPDIR)/Make/cygwin_plugin_def
PLUGIN = $(PLUGIN_PREFIX)$(TARGET_BASENAME).$(PLUGIN_EXT)
include $(TOPDIR)/Make/makerules

View File

@@ -0,0 +1,775 @@
// 30 Oct 2002
// AC3D loader for models generated by the AC3D modeller (www.ac3d.org)
// part of this source code were supplied by the AC3D project (Andy Colebourne)
// eg the basic parsing of an AC3D file.
// Conversion from AC3D scenegraph to OSG by GW Michel.
#include <stdio.h>
#include <malloc.h>
#include <math.h>
#include <osg/CullFace>
#include <osg/Geode>
#include <osg/Group>
#include <osg/Geometry> //Set>
#include <osg/Light>
#include <osg/LightSource>
#include <osg/Material>
#include <osg/Texture2D>
#include <osg/TexEnv>
#include <osg/StateSet>
#include <osg/Notify>
#include <osg/Texture2D>
#include <osgDB/FileNameUtils>
#include <osgDB/Registry>
#include <osgDB/ReadFile>
#include <osgDB/FileUtils>
#include <osgUtil/Tesselator>
#include <osgUtil/SmoothingVisitor>
#include "osgac3d.h"
class ReaderWriterAC : public osgDB::ReaderWriter
{
public:
virtual const char* className() { return "AC3D Database Reader"; }
virtual bool acceptsExtension(const std::string& extension)
{
return osgDB::equalCaseInsensitive(extension,"ac");
}
virtual ReadResult readNode(const std::string& fileName,const osgDB::ReaderWriter::Options*)
{
osg::Group *grp; // holder for all loaded objects
grp=ac_load_ac3d(fileName.c_str());
return grp;
};
private:
};
static int line = 0;
static char buff[255];
static osg::Material *palette[255];
static int num_palette = 0;
static int startmatindex = 0;
osg::Material*ac_palette_get_material(int id)
{
return(palette[id]);
}
Boolean read_line(FILE *f)
{
fgets(buff, 255, f); line++;
return(TRUE);
}
int tokc = 0;
char *tokv[30];
Prototype int get_tokens(char *s, int *argc, char *argv[])
/** bung '\0' chars at the end of tokens and set up the array (tokv) and count (tokc)
like argv argc **/
{
char *p = s;
char *st;
char c;
//int n;
int tc;
tc = 0;
while ((c = *p))
{
if ((c != ' ') && (c != '\t') && (c != '\n') && ( c != 13))
{
if (c == '"')
{
c = *p++;
st = p;
while ((c = *p) && ((c != '"')&&(c != '\n')&& ( c != 13)) )
{
if (c == '\\')
strcpy(p, p+1);
p++;
}
*p=0;
argv[tc++] = st;
}
else
{
st = p;
while ((c = *p) && ((c != ' ') && (c != '\t') && (c != '\n') && ( c != 13)) )
p++;
*p=0;
argv[tc++] = st;
}
}
p++;
}
*argc = tc;
return(tc);
}
void initobject(ACObject *ob)
{
ob->loc[0] = ob->loc[1] = ob->loc[2] = 0.0;
ob->name = ob->url = NULL;
ob->data = NULL;
ob->num_vert = 0;
ob->num_surf = 0;
ob->texture = NULL;
ob->texture_repeat_x = ob->texture_repeat_y = 1.0;
ob->texture_offset_x = ob->texture_offset_y = 0.0;
ob->kids = NULL;
ob->num_kids = 0;
ob->matrix[0] = 1;
ob->matrix[1] = 0;
ob->matrix[2] = 0;
ob->matrix[3] = 0;
ob->matrix[4] = 1;
ob->matrix[5] = 0;
ob->matrix[6] = 0;
ob->matrix[7] = 0;
ob->matrix[8] = 1;
}
void init_surface(ACSurface *s)
{
s->num_vertref = 0;
s->flags = 0;
s->mat = 0;
// s->normal.x = 0.0; s->normal.z = 0.0; s->normal.z = 0.0;
}
void osgtri_calc_normal(osg::Vec3 &v1, osg::Vec3 &v2, osg::Vec3 &v3, osg::Vec3 &n)
{
osg::Vec3 side1=v2-v1;
osg::Vec3 side2=v3-v2;
n=side1^side2;
n.normalize();
}
ACSurface *read_surface(FILE *f, ACSurface *s,osg::UShortArray *nusidx,
osg::Vec2Array *tcs)
{
char t[20];
init_surface(s);
while (!feof(f))
{
read_line(f);
sscanf(buff, "%s", t);
if (streq(t, "SURF"))
{
int flgs;
if (get_tokens(buff, &tokc, tokv) != 2)
{
printf("SURF should be followed by one flags argument\n");
}
else
{
flgs = strtol(tokv[1], NULL, 0);
s->flags = flgs;
}
}
else
if (streq(t, "mat"))
{
int mindx;
sscanf(buff, "%s %d", t, &mindx);
s->mat = mindx+startmatindex;
}
else
if (streq(t, "refs"))
{
int num, n;
int ind;
osg::Vec2 tx;
sscanf(buff, "%s %d", t, &num);
s->num_vertref = num;
for (n = 0; n < num; n++)
{
fscanf(f, "%d %f %f\n", &ind, &tx[0], &tx[1]); line++;
nusidx->push_back(ind);
if (tcs) tcs->push_back(tx);
}
return(s);
}
else
printf("ignoring %s\n", t);
}
return(NULL);
}
/*void ac_object_calc_vertex_normals(ACObject *ob)
{
int s, v, vr;
/ ** for each vertex in this object ** /
for (v = 0; v < ob->num_vert; v++)
{
ACNormal n = {0, 0, 0};
int found = 0;
/ ** go through each surface ** /
for (s = 0; s < ob->num_surf; s++)
{
ACSurface *surf = &ob->surfaces[s];
/ ** check if this vertex is used in this surface ** /
/ ** if it is, use it to create an average normal ** /
for (vr = 0; vr < surf->num_vertref; vr++)
if (surf->vertref[vr] == v)
{
n.x+=surf->normal.x;
n.y+=surf->normal.y;
n.z+=surf->normal.z;
found++;
}
}
if (found > 0)
{
n.x /= found;
n.y /= found;
n.z /= found;
}
ob->vertices[v].normal = n;
}
} */
int string_to_objecttype(char *s)
{
if (streq("world", s))
return(OBJECT_WORLD);
if (streq("poly", s))
return(OBJECT_NORMAL);
if (streq("group", s))
return(OBJECT_GROUP);
if (streq("light", s))
return(OBJECT_LIGHT);
return(OBJECT_NORMAL);
}
void
protate(osg::Vec3 p, float m[9])
{ // p-> m*p, m is 3.3 matrix
osg::Vec3 t=p;
p[0]=m[0]*t[0]+m[1]*t[1]+m[2]*t[3];
p[1]=m[3]*t[0]+m[4]*t[1]+m[5]*t[3];
p[2]=m[6]*t[0]+m[7]*t[1]+m[8]*t[3];
}
osg::Group *ac_load_object(FILE *f,const ACObject *parent)
{
// most of this logic came from Andy Colebourne (developer of the AC3D editor) so it had better be right!
char t[20];
osg::Group *gp=NULL;
osg::Geode *geode=NULL;
osg::Vec3Array *normals = NULL; // new osg::Vec3Array; // NULL;
ACObject ob; // local storage for stuff taken from AC's loader
osg::Vec3Array *vertpool = new osg::Vec3Array;
if (parent) ob.loc=parent->loc; // copy loc
while (!feof(f))
{
read_line(f);
sscanf(buff, "%s", t);
if (streq(t, "MATERIAL"))
{
if (get_tokens(buff, &tokc, tokv) != 22)
{
printf("expected 21 params after \"MATERIAL\" - line %d\n", line);
}
else
{
osg::Material *numat=new osg::Material();
osg::Vec4 cdiff((float)atof(tokv[3]), (float)atof(tokv[4]),
(float)atof(tokv[5]), 1.0-(float)atof(tokv[21]));
numat->setDiffuse(osg::Material::FRONT_AND_BACK,cdiff);
osg::Vec4 camb((float)atof(tokv[7]),(float)atof(tokv[8]),
(float)atof(tokv[9]),1.0-(float)atof(tokv[21]));
numat->setAmbient(osg::Material::FRONT_AND_BACK,camb);
osg::Vec4 cspec((float)atof(tokv[15]), (float)atof(tokv[16]),
(float)atof(tokv[17]),1.0-(float)atof(tokv[21]));
numat->setSpecular(osg::Material::FRONT_AND_BACK,cspec);
osg::Vec4 cemm((float)atof(tokv[11]),(float)atof(tokv[12]),(float)atof(tokv[13]),1.0-(float)atof(tokv[21]));
numat->setSpecular(osg::Material::FRONT_AND_BACK,cemm);
//numat->setTransparency(osg::Material::FRONT_AND_BACK, 1.0-(float)atof(tokv[21]));
palette[num_palette++] = numat;
}
}
else
if (streq(t, "OBJECT"))
{
char type[20];
char str[20];
osg::Vec3 loc=ob.loc;
if (!gp) gp = new osg::Group();
initobject(&ob); // rezero data for object
ob.loc=loc;
sscanf(buff, "%s %s", str, type);
ob.type = string_to_objecttype(type);
}
else
if (streq(t, "data"))
{
if (get_tokens(buff, &tokc, tokv) != 2)
printf("expected 'data <number>' at line %d\n", line);
else
{
char *str;
int len;
len = atoi(tokv[1]);
if (len > 0)
{
str = (char *)myalloc(len+1);
fread(str, len, 1, f);
str[len] = 0;
fscanf(f, "\n"); line++;
ob.data = STRING(str);
myfree(str);
}
}
}
else
if (streq(t, "name"))
{
int numtok = get_tokens(buff, &tokc, tokv);
if (numtok != 2)
{
printf("expected quoted name at line %d (got %d tokens)\n", line, numtok);
}
else
if (gp) gp->setName(tokv[1]);
}
else
if (streq(t, "texture"))
{
if (get_tokens(buff, &tokc, tokv) != 2)
printf("expected quoted texture name at line %d\n", line);
else
{
osg::Image *ctx= osgDB::readImageFile(tokv[1]);
if (ctx) { // image coukd be read
ob.texture = new osg::Texture2D;// ac_load_texture(tokv[1]);
ob.texture->setImage(ctx);
if (ob.texture_repeat_x > 0.1) {
ob.texture->setWrap(osg::Texture2D::WRAP_S, osg::Texture2D::REPEAT);
} else {
ob.texture->setWrap(osg::Texture2D::WRAP_S, osg::Texture2D::CLAMP);
}
if (ob.texture_repeat_y > 0.1) {
ob.texture->setWrap(osg::Texture2D::WRAP_T, osg::Texture2D::REPEAT);
} else {
ob.texture->setWrap(osg::Texture2D::WRAP_T, osg::Texture2D::CLAMP);
}
}
}
}
else
if (streq(t, "texrep"))
{
if (get_tokens(buff, &tokc, tokv) != 3)
printf("expected 'texrep <float> <float>' at line %d\n", line);
else
{
ob.texture_repeat_x = atof(tokv[1]);
ob.texture_repeat_y = atof(tokv[2]);
}
}
else
if (streq(t, "texoff"))
{
if (get_tokens(buff, &tokc, tokv) != 3)
printf("expected 'texoff <float> <float>' at line %d\n", line);
else
{
ob.texture_offset_x = atof(tokv[1]);
ob.texture_offset_y = atof(tokv[2]);
}
}
else
if (streq(t, "rot"))
{
float r[9];
char str2[5];
int n;
sscanf(buff, "%s %f %f %f %f %f %f %f %f %f", str2,
&r[0], &r[1], &r[2], &r[3], &r[4], &r[5], &r[6], &r[7], &r[8] );
for (n = 0; n < 9; n++)
ob.matrix[n] = r[n];
}
else
if (streq(t, "loc"))
{
char str[5];
osg::Vec3 loc;
sscanf(buff, "%s %f %f %f", str, &loc[0], &loc[1], &loc[2]);
ob.loc+=loc;
}
else
if (streq(t, "url"))
{
if (get_tokens(buff, &tokc, tokv) != 2)
printf("expected one arg to url at line %d (got %d)\n", line, tokv);
else
ob.url = STRING(tokv[1]);
}
else
if (streq(t, "numvert"))
{
int num, n;
char str[10];
if (ob.type == OBJECT_GROUP || ob.type == OBJECT_WORLD) {
} else if (ob.type == OBJECT_NORMAL) {
if (geode) {
osgUtil::Tesselator tesselator;
for(unsigned int i=0;i<geode->getNumDrawables();++i)
{
osg::Geometry* geom = dynamic_cast<osg::Geometry*>(geode->getDrawable(i));
if (geom) tesselator.retesselatePolygons(*geom);
}
}
geode = new osg::Geode();
gp->addChild(geode);
geode->setName(gp->getName());
normals = new osg::Vec3Array;
}
sscanf(buff, "%s %d", str, &num);
if (num > 0)
{
ob.num_vert = num;
for (n = 0; n < num; n++)
{
osg::Vec3 p;
fscanf(f, "%f %f %f\n", &p[0], &p[1], &p[2]); line++;
protate(p, ob.matrix);
vertpool->push_back(p+ob.loc);
}
}
}
else
if (streq(t, "numsurf"))
{
int num, n;
char str[10];
// this is not obvious (what is?). Each set of surfaces can have different material on each surface.
// so I set up a set of 'bins' for
// the primitives (geometry list, geomlist)
// the coords array of each geometry (Vec3Array list, vertslist)
// the tx coords array for each geometry (Vec2Array list, texslist)
// then I add a new geometry to the current Geode for each new material as it is found.
std::vector<int> ia; // list of materials required- generate one geode per material
typedef std::vector<osg::Geometry *> geomlist;
geomlist glist;
typedef std::vector<osg::Vec3Array *> vertslist;
vertslist vlists; // list of vertices for each glist element
typedef std::vector<osg::Vec2Array *> texslist;
texslist txlists; // list of texture coords for each glist element
sscanf(buff, "%s %d", str, &num);
if (num > 0)
{
int needSmooth=0; // flat shaded
ob.num_surf = num;
for (n = 0; n < num; n++)
{
osg::Geometry *geom=NULL; // the surface will be addded to this geometry
osg::Vec3Array *vgeom=NULL; // vertices corresponding to geom taken from vertexpool
osg::Vec2Array *tgeom=NULL; // texture coords corresponding to geom taken from vertexpool
ACSurface asurf;
osg::UShortArray *nusidx = new osg::UShortArray; // indices into the vertices
osg::Vec2Array *tcs=new osg::Vec2Array; // texture coordinates for this object
ACSurface *news = read_surface(f, &asurf, nusidx, tcs);
if (news == NULL)
{
printf("error whilst reading surface at line: %d\n", line);
return(NULL);
} else {
int i=0;
for (std::vector<int>::iterator itr= ia.begin(); itr<ia.end(); itr++, i++) {
if ((*itr)==asurf.mat) {
geom=glist[i];
vgeom=vlists[i];
tgeom=txlists[i]; // what is current texture array
}
}
if (!geom) { // then we need a new geometry
osg::Vec3Array *verts = new osg::Vec3Array;
osg::Vec2Array *tcrds=new osg::Vec2Array; // texture coordinates for this object
vgeom=verts;
tgeom=tcrds; // what is current texture array
vlists.push_back(verts);
txlists.push_back(tcrds);
geom=new osg::Geometry();
geom->setNormalBinding(osg::Geometry::BIND_PER_PRIMITIVE);
geom->setNormalArray(normals);
geom->setVertexArray(verts);
if (ob.texture) {
geom->setTexCoordArray(0,tgeom); // share same set of TexCoords
}
osg::Material*mat=ac_palette_get_material(asurf.mat);
osg::StateSet *dstate = new osg::StateSet;
dstate->setMode( GL_LIGHTING, osg::StateAttribute::ON );
dstate->setAttribute(mat);
const osg::Vec4 cdiff =mat->getDiffuse(osg::Material::FRONT_AND_BACK);
if (cdiff[3]<0.99) {
dstate->setMode(GL_BLEND,osg::StateAttribute::ON);
dstate->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
} else {
dstate->setMode(GL_BLEND,osg::StateAttribute::OFF);
}
if (ob.texture) dstate->setTextureMode(0,GL_TEXTURE_2D,osg::StateAttribute::OFF);
if (ob.texture) {
osg::TexEnv* texenv = new osg::TexEnv;
texenv->setMode(osg::TexEnv::MODULATE);
dstate->setTextureAttribute(0, texenv );
dstate->setTextureAttributeAndModes(0,ob.texture,osg::StateAttribute::ON);
}
if (asurf.flags & SURFACE_TWOSIDED) dstate->setMode( GL_CULL_FACE, osg::StateAttribute::OFF );
else dstate->setMode( GL_CULL_FACE, osg::StateAttribute::ON );
geom->setStateSet( dstate );
glist.push_back(geom);
geode->addDrawable(geom);
ia.push_back(asurf.mat);
}
osg::Vec3Array* normals = geom->getNormalArray();
/** calc surface normal **/
if (asurf.num_vertref >= 3) {
osg::Vec3 norm;
osg::ushort i1=(*nusidx)[0];
osg::ushort i2=(*nusidx)[1];
osg::ushort i3=(*nusidx)[2];
osgtri_calc_normal((*vertpool)[i1],
(*vertpool)[i2],
(*vertpool)[i3], norm);
normals->push_back(norm);
}
int nstart=(*vgeom).size();
for (i=0; i<asurf.num_vertref; i++) {
int i1=(*nusidx)[i];
(*vgeom).push_back((*vertpool)[i1]);
(*tgeom).push_back((*tcs)[i]);
}
GLenum poltype=osg::Primitive::POLYGON;
if (asurf.flags & SURFACE_TYPE_CLOSEDLINE) poltype=osg::Primitive::LINE_LOOP;
if (asurf.flags & SURFACE_TYPE_LINE) poltype=osg::Primitive::LINE_STRIP;
geom->addPrimitive(new osg::DrawArrays(poltype,nstart,asurf.num_vertref));
if (asurf.flags & 0x10) needSmooth++;
}
}
for (geomlist::iterator itr= glist.begin(); itr<glist.end(); itr++) {
osgUtil::Tesselator tesselator;
if (*itr) tesselator.retesselatePolygons(**itr);
if (needSmooth) {
osgUtil::SmoothingVisitor smoother;
smoother.smooth(**itr);
}
}
}
}
else
if (streq(t, "kids")) /** 'kids' is the last token in an object **/
{
int num, n;
sscanf(buff, "%s %d", t, &num);
if (num != 0)
{
// ob.kids = (ACObject **)myalloc(num * sizeof(ACObject *) );
ob.num_kids = num;
for (n = 0; n < num; n++)
{
osg::Group *k = ac_load_object(f,&ob); //, ob);
if (k == NULL)
{
printf("error reading expected child object %d of %d at line: %d\n", n+1, num, line);
return(gp);
}
else
//ob.kids[n] = k;
gp->addChild(k);
}
}
if (geode) {
osgUtil::Tesselator tesselator;
for(unsigned int i=0;i<geode->getNumDrawables();++i)
{
osg::Geometry* geom = dynamic_cast<osg::Geometry*>(geode->getDrawable(i));
if (geom) tesselator.retesselatePolygons(*geom);
}
}
return(gp);
}
}
if (geode) {
osgUtil::Tesselator tesselator;
for(unsigned int i=0;i<geode->getNumDrawables();++i)
{
osg::Geometry* geom = dynamic_cast<osg::Geometry*>(geode->getDrawable(i));
if (geom) tesselator.retesselatePolygons(*geom);
}
}
return(gp);
}
/*void ac_calc_vertex_normals(ACObject *ob)
{
int n;
ac_object_calc_vertex_normals(ob);
if (ob->num_kids)
for (n = 0; n < ob->num_kids; n++)
ac_calc_vertex_normals(ob->kids[n]);
}*/
osg::Group *ac_load_ac3d(const char *fname)
{
FILE *f = fopen(fname, "r");
osg::Group *ret = NULL;
if (f == NULL)
{
printf("can't open %s\n", fname);
return(NULL);
}
read_line(f);
if (strncmp(buff, "AC3D", 4))
{
printf("ac_load_ac '%s' is not a valid AC3D file.", fname);
fclose(f);
return(0);
}
startmatindex = num_palette;
ret = ac_load_object(f,NULL); //, NULL);
fclose(f);
// ac_calc_vertex_normals(ret);
// here I need to calculate nromals for this object
return(ret);
}
void ac_dump(ACObject *ob)
{ // not yet finished option ot output AC3D file from OSG scene.
int n;
printf("OBJECT name %s\nloc %f %f %f\nnum_vert %d\nnum_surf %d\n",
ob->name, ob->loc[0], ob->loc[1], ob->loc[2], ob->num_vert, ob->num_surf);
// for (n=0; n < ob->num_vert; n++)
// printf("\tv %f %f %f\n", ob->vertices[n].x, ob->vertices[n].y, ob->vertices[n].z);
for (n=0; n < ob->num_surf; n++)
{
//// ACSurface *s = &ob->surfaces[n];
// printf("surface %d, %d refs, mat %d\n", n, s->num_vertref, s->mat);
}
/* this structure not used in OSG
if (ob->num_kids)
for (n = 0; n < ob->num_kids; n++)
ac_dump(ob->kids[n]);
*/
}
// now register with osg::Registry to instantiate the above
// reader/writer.
osgDB::RegisterReaderWriterProxy<ReaderWriterAC> g_readerWriter_AC_Proxy;

View File

@@ -0,0 +1,81 @@
// 30 Oct 2002
// AC3D loader for models generated by the AC3D modeller (www.ac3d.org)
// part of this source code were supplied by the AC3D project (Andy Colebourne)
// eg the basic parsing of an AC3D file, values of constants in this include file..
// Conversion from AC3D scenegraph to OSG by GW Michel.
// == Opinion: ac3d is a valuable, very easy to use 3D modeller.
// use can be picked up in hours rather than weeks.
// Other loaders and modellers are available for OSG.
typedef struct ACSurface_t
{
int num_vertref;
int flags;
int mat;
} ACSurface;
typedef struct ACObject_t
{
osg::Vec3 loc;
char *name;
char *data;
char *url;
int num_vert;
int num_surf;
float texture_repeat_x, texture_repeat_y;
float texture_offset_x, texture_offset_y;
int num_kids;
struct ACObject_t **kids;
float matrix[9];
int type;
osg::Texture2D *texture;
} ACObject;
#define OBJECT_WORLD 999
#define OBJECT_NORMAL 0
#define OBJECT_GROUP 1
#define OBJECT_LIGHT 2
#define SURFACE_SHADED (1<<4)
#define SURFACE_TWOSIDED (1<<5)
#define SURFACE_TYPE_POLYGON (0)
#define SURFACE_TYPE_CLOSEDLINE (1)
#define SURFACE_TYPE_LINE (2)
#define Prototype
#define Private static
#define Boolean int
#define FALSE (0)
#define TRUE (!FALSE)
#define STRING(s) (char *)(strcpy((char *)myalloc(strlen(s)+1), s))
#define streq(a,b) (!strcmp(a,b))
#define myalloc malloc
#define myfree free
Prototype osg::Group *ac_load_ac3d(const char *filename);
Prototype osg::Material *ac_palette_get_material(int index);

View File

@@ -0,0 +1,775 @@
// 30 Oct 2002
// AC3D loader for models generated by the AC3D modeller (www.ac3d.org)
// part of this source code were supplied by the AC3D project (Andy Colebourne)
// eg the basic parsing of an AC3D file.
// Conversion from AC3D scenegraph to OSG by GW Michel.
#include <stdio.h>
#include <malloc.h>
#include <math.h>
#include <osg/CullFace>
#include <osg/Geode>
#include <osg/Group>
#include <osg/Geometry> //Set>
#include <osg/Light>
#include <osg/LightSource>
#include <osg/Material>
#include <osg/Texture2D>
#include <osg/TexEnv>
#include <osg/StateSet>
#include <osg/Notify>
#include <osg/Texture2D>
#include <osgDB/FileNameUtils>
#include <osgDB/Registry>
#include <osgDB/ReadFile>
#include <osgDB/FileUtils>
#include <osgUtil/Tesselator>
#include <osgUtil/SmoothingVisitor>
#include "osgac3d.h"
class ReaderWriterAC : public osgDB::ReaderWriter
{
public:
virtual const char* className() { return "AC3D Database Reader"; }
virtual bool acceptsExtension(const std::string& extension)
{
return osgDB::equalCaseInsensitive(extension,"ac");
}
virtual ReadResult readNode(const std::string& fileName,const osgDB::ReaderWriter::Options*)
{
osg::Group *grp; // holder for all loaded objects
grp=ac_load_ac3d(fileName.c_str());
return grp;
};
private:
};
static int line = 0;
static char buff[255];
static osg::Material *palette[255];
static int num_palette = 0;
static int startmatindex = 0;
osg::Material*ac_palette_get_material(int id)
{
return(palette[id]);
}
Boolean read_line(FILE *f)
{
fgets(buff, 255, f); line++;
return(TRUE);
}
int tokc = 0;
char *tokv[30];
Prototype int get_tokens(char *s, int *argc, char *argv[])
/** bung '\0' chars at the end of tokens and set up the array (tokv) and count (tokc)
like argv argc **/
{
char *p = s;
char *st;
char c;
//int n;
int tc;
tc = 0;
while ((c = *p))
{
if ((c != ' ') && (c != '\t') && (c != '\n') && ( c != 13))
{
if (c == '"')
{
c = *p++;
st = p;
while ((c = *p) && ((c != '"')&&(c != '\n')&& ( c != 13)) )
{
if (c == '\\')
strcpy(p, p+1);
p++;
}
*p=0;
argv[tc++] = st;
}
else
{
st = p;
while ((c = *p) && ((c != ' ') && (c != '\t') && (c != '\n') && ( c != 13)) )
p++;
*p=0;
argv[tc++] = st;
}
}
p++;
}
*argc = tc;
return(tc);
}
void initobject(ACObject *ob)
{
ob->loc[0] = ob->loc[1] = ob->loc[2] = 0.0;
ob->name = ob->url = NULL;
ob->data = NULL;
ob->num_vert = 0;
ob->num_surf = 0;
ob->texture = NULL;
ob->texture_repeat_x = ob->texture_repeat_y = 1.0;
ob->texture_offset_x = ob->texture_offset_y = 0.0;
ob->kids = NULL;
ob->num_kids = 0;
ob->matrix[0] = 1;
ob->matrix[1] = 0;
ob->matrix[2] = 0;
ob->matrix[3] = 0;
ob->matrix[4] = 1;
ob->matrix[5] = 0;
ob->matrix[6] = 0;
ob->matrix[7] = 0;
ob->matrix[8] = 1;
}
void init_surface(ACSurface *s)
{
s->num_vertref = 0;
s->flags = 0;
s->mat = 0;
// s->normal.x = 0.0; s->normal.z = 0.0; s->normal.z = 0.0;
}
void osgtri_calc_normal(osg::Vec3 &v1, osg::Vec3 &v2, osg::Vec3 &v3, osg::Vec3 &n)
{
osg::Vec3 side1=v2-v1;
osg::Vec3 side2=v3-v2;
n=side1^side2;
n.normalize();
}
ACSurface *read_surface(FILE *f, ACSurface *s,osg::UShortArray *nusidx,
osg::Vec2Array *tcs)
{
char t[20];
init_surface(s);
while (!feof(f))
{
read_line(f);
sscanf(buff, "%s", t);
if (streq(t, "SURF"))
{
int flgs;
if (get_tokens(buff, &tokc, tokv) != 2)
{
printf("SURF should be followed by one flags argument\n");
}
else
{
flgs = strtol(tokv[1], NULL, 0);
s->flags = flgs;
}
}
else
if (streq(t, "mat"))
{
int mindx;
sscanf(buff, "%s %d", t, &mindx);
s->mat = mindx+startmatindex;
}
else
if (streq(t, "refs"))
{
int num, n;
int ind;
osg::Vec2 tx;
sscanf(buff, "%s %d", t, &num);
s->num_vertref = num;
for (n = 0; n < num; n++)
{
fscanf(f, "%d %f %f\n", &ind, &tx[0], &tx[1]); line++;
nusidx->push_back(ind);
if (tcs) tcs->push_back(tx);
}
return(s);
}
else
printf("ignoring %s\n", t);
}
return(NULL);
}
/*void ac_object_calc_vertex_normals(ACObject *ob)
{
int s, v, vr;
/ ** for each vertex in this object ** /
for (v = 0; v < ob->num_vert; v++)
{
ACNormal n = {0, 0, 0};
int found = 0;
/ ** go through each surface ** /
for (s = 0; s < ob->num_surf; s++)
{
ACSurface *surf = &ob->surfaces[s];
/ ** check if this vertex is used in this surface ** /
/ ** if it is, use it to create an average normal ** /
for (vr = 0; vr < surf->num_vertref; vr++)
if (surf->vertref[vr] == v)
{
n.x+=surf->normal.x;
n.y+=surf->normal.y;
n.z+=surf->normal.z;
found++;
}
}
if (found > 0)
{
n.x /= found;
n.y /= found;
n.z /= found;
}
ob->vertices[v].normal = n;
}
} */
int string_to_objecttype(char *s)
{
if (streq("world", s))
return(OBJECT_WORLD);
if (streq("poly", s))
return(OBJECT_NORMAL);
if (streq("group", s))
return(OBJECT_GROUP);
if (streq("light", s))
return(OBJECT_LIGHT);
return(OBJECT_NORMAL);
}
void
protate(osg::Vec3 p, float m[9])
{ // p-> m*p, m is 3.3 matrix
osg::Vec3 t=p;
p[0]=m[0]*t[0]+m[1]*t[1]+m[2]*t[3];
p[1]=m[3]*t[0]+m[4]*t[1]+m[5]*t[3];
p[2]=m[6]*t[0]+m[7]*t[1]+m[8]*t[3];
}
osg::Group *ac_load_object(FILE *f,const ACObject *parent)
{
// most of this logic came from Andy Colebourne (developer of the AC3D editor) so it had better be right!
char t[20];
osg::Group *gp=NULL;
osg::Geode *geode=NULL;
osg::Vec3Array *normals = NULL; // new osg::Vec3Array; // NULL;
ACObject ob; // local storage for stuff taken from AC's loader
osg::Vec3Array *vertpool = new osg::Vec3Array;
if (parent) ob.loc=parent->loc; // copy loc
while (!feof(f))
{
read_line(f);
sscanf(buff, "%s", t);
if (streq(t, "MATERIAL"))
{
if (get_tokens(buff, &tokc, tokv) != 22)
{
printf("expected 21 params after \"MATERIAL\" - line %d\n", line);
}
else
{
osg::Material *numat=new osg::Material();
osg::Vec4 cdiff((float)atof(tokv[3]), (float)atof(tokv[4]),
(float)atof(tokv[5]), 1.0-(float)atof(tokv[21]));
numat->setDiffuse(osg::Material::FRONT_AND_BACK,cdiff);
osg::Vec4 camb((float)atof(tokv[7]),(float)atof(tokv[8]),
(float)atof(tokv[9]),1.0-(float)atof(tokv[21]));
numat->setAmbient(osg::Material::FRONT_AND_BACK,camb);
osg::Vec4 cspec((float)atof(tokv[15]), (float)atof(tokv[16]),
(float)atof(tokv[17]),1.0-(float)atof(tokv[21]));
numat->setSpecular(osg::Material::FRONT_AND_BACK,cspec);
osg::Vec4 cemm((float)atof(tokv[11]),(float)atof(tokv[12]),(float)atof(tokv[13]),1.0-(float)atof(tokv[21]));
numat->setSpecular(osg::Material::FRONT_AND_BACK,cemm);
//numat->setTransparency(osg::Material::FRONT_AND_BACK, 1.0-(float)atof(tokv[21]));
palette[num_palette++] = numat;
}
}
else
if (streq(t, "OBJECT"))
{
char type[20];
char str[20];
osg::Vec3 loc=ob.loc;
if (!gp) gp = new osg::Group();
initobject(&ob); // rezero data for object
ob.loc=loc;
sscanf(buff, "%s %s", str, type);
ob.type = string_to_objecttype(type);
}
else
if (streq(t, "data"))
{
if (get_tokens(buff, &tokc, tokv) != 2)
printf("expected 'data <number>' at line %d\n", line);
else
{
char *str;
int len;
len = atoi(tokv[1]);
if (len > 0)
{
str = (char *)myalloc(len+1);
fread(str, len, 1, f);
str[len] = 0;
fscanf(f, "\n"); line++;
ob.data = STRING(str);
myfree(str);
}
}
}
else
if (streq(t, "name"))
{
int numtok = get_tokens(buff, &tokc, tokv);
if (numtok != 2)
{
printf("expected quoted name at line %d (got %d tokens)\n", line, numtok);
}
else
if (gp) gp->setName(tokv[1]);
}
else
if (streq(t, "texture"))
{
if (get_tokens(buff, &tokc, tokv) != 2)
printf("expected quoted texture name at line %d\n", line);
else
{
osg::Image *ctx= osgDB::readImageFile(tokv[1]);
if (ctx) { // image coukd be read
ob.texture = new osg::Texture2D;// ac_load_texture(tokv[1]);
ob.texture->setImage(ctx);
if (ob.texture_repeat_x > 0.1) {
ob.texture->setWrap(osg::Texture2D::WRAP_S, osg::Texture2D::REPEAT);
} else {
ob.texture->setWrap(osg::Texture2D::WRAP_S, osg::Texture2D::CLAMP);
}
if (ob.texture_repeat_y > 0.1) {
ob.texture->setWrap(osg::Texture2D::WRAP_T, osg::Texture2D::REPEAT);
} else {
ob.texture->setWrap(osg::Texture2D::WRAP_T, osg::Texture2D::CLAMP);
}
}
}
}
else
if (streq(t, "texrep"))
{
if (get_tokens(buff, &tokc, tokv) != 3)
printf("expected 'texrep <float> <float>' at line %d\n", line);
else
{
ob.texture_repeat_x = atof(tokv[1]);
ob.texture_repeat_y = atof(tokv[2]);
}
}
else
if (streq(t, "texoff"))
{
if (get_tokens(buff, &tokc, tokv) != 3)
printf("expected 'texoff <float> <float>' at line %d\n", line);
else
{
ob.texture_offset_x = atof(tokv[1]);
ob.texture_offset_y = atof(tokv[2]);
}
}
else
if (streq(t, "rot"))
{
float r[9];
char str2[5];
int n;
sscanf(buff, "%s %f %f %f %f %f %f %f %f %f", str2,
&r[0], &r[1], &r[2], &r[3], &r[4], &r[5], &r[6], &r[7], &r[8] );
for (n = 0; n < 9; n++)
ob.matrix[n] = r[n];
}
else
if (streq(t, "loc"))
{
char str[5];
osg::Vec3 loc;
sscanf(buff, "%s %f %f %f", str, &loc[0], &loc[1], &loc[2]);
ob.loc+=loc;
}
else
if (streq(t, "url"))
{
if (get_tokens(buff, &tokc, tokv) != 2)
printf("expected one arg to url at line %d (got %d)\n", line, tokv);
else
ob.url = STRING(tokv[1]);
}
else
if (streq(t, "numvert"))
{
int num, n;
char str[10];
if (ob.type == OBJECT_GROUP || ob.type == OBJECT_WORLD) {
} else if (ob.type == OBJECT_NORMAL) {
if (geode) {
osgUtil::Tesselator tesselator;
for(unsigned int i=0;i<geode->getNumDrawables();++i)
{
osg::Geometry* geom = dynamic_cast<osg::Geometry*>(geode->getDrawable(i));
if (geom) tesselator.retesselatePolygons(*geom);
}
}
geode = new osg::Geode();
gp->addChild(geode);
geode->setName(gp->getName());
normals = new osg::Vec3Array;
}
sscanf(buff, "%s %d", str, &num);
if (num > 0)
{
ob.num_vert = num;
for (n = 0; n < num; n++)
{
osg::Vec3 p;
fscanf(f, "%f %f %f\n", &p[0], &p[1], &p[2]); line++;
protate(p, ob.matrix);
vertpool->push_back(p+ob.loc);
}
}
}
else
if (streq(t, "numsurf"))
{
int num, n;
char str[10];
// this is not obvious (what is?). Each set of surfaces can have different material on each surface.
// so I set up a set of 'bins' for
// the primitives (geometry list, geomlist)
// the coords array of each geometry (Vec3Array list, vertslist)
// the tx coords array for each geometry (Vec2Array list, texslist)
// then I add a new geometry to the current Geode for each new material as it is found.
std::vector<int> ia; // list of materials required- generate one geode per material
typedef std::vector<osg::Geometry *> geomlist;
geomlist glist;
typedef std::vector<osg::Vec3Array *> vertslist;
vertslist vlists; // list of vertices for each glist element
typedef std::vector<osg::Vec2Array *> texslist;
texslist txlists; // list of texture coords for each glist element
sscanf(buff, "%s %d", str, &num);
if (num > 0)
{
int needSmooth=0; // flat shaded
ob.num_surf = num;
for (n = 0; n < num; n++)
{
osg::Geometry *geom=NULL; // the surface will be addded to this geometry
osg::Vec3Array *vgeom=NULL; // vertices corresponding to geom taken from vertexpool
osg::Vec2Array *tgeom=NULL; // texture coords corresponding to geom taken from vertexpool
ACSurface asurf;
osg::UShortArray *nusidx = new osg::UShortArray; // indices into the vertices
osg::Vec2Array *tcs=new osg::Vec2Array; // texture coordinates for this object
ACSurface *news = read_surface(f, &asurf, nusidx, tcs);
if (news == NULL)
{
printf("error whilst reading surface at line: %d\n", line);
return(NULL);
} else {
int i=0;
for (std::vector<int>::iterator itr= ia.begin(); itr<ia.end(); itr++, i++) {
if ((*itr)==asurf.mat) {
geom=glist[i];
vgeom=vlists[i];
tgeom=txlists[i]; // what is current texture array
}
}
if (!geom) { // then we need a new geometry
osg::Vec3Array *verts = new osg::Vec3Array;
osg::Vec2Array *tcrds=new osg::Vec2Array; // texture coordinates for this object
vgeom=verts;
tgeom=tcrds; // what is current texture array
vlists.push_back(verts);
txlists.push_back(tcrds);
geom=new osg::Geometry();
geom->setNormalBinding(osg::Geometry::BIND_PER_PRIMITIVE);
geom->setNormalArray(normals);
geom->setVertexArray(verts);
if (ob.texture) {
geom->setTexCoordArray(0,tgeom); // share same set of TexCoords
}
osg::Material*mat=ac_palette_get_material(asurf.mat);
osg::StateSet *dstate = new osg::StateSet;
dstate->setMode( GL_LIGHTING, osg::StateAttribute::ON );
dstate->setAttribute(mat);
const osg::Vec4 cdiff =mat->getDiffuse(osg::Material::FRONT_AND_BACK);
if (cdiff[3]<0.99) {
dstate->setMode(GL_BLEND,osg::StateAttribute::ON);
dstate->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
} else {
dstate->setMode(GL_BLEND,osg::StateAttribute::OFF);
}
if (ob.texture) dstate->setTextureMode(0,GL_TEXTURE_2D,osg::StateAttribute::OFF);
if (ob.texture) {
osg::TexEnv* texenv = new osg::TexEnv;
texenv->setMode(osg::TexEnv::MODULATE);
dstate->setTextureAttribute(0, texenv );
dstate->setTextureAttributeAndModes(0,ob.texture,osg::StateAttribute::ON);
}
if (asurf.flags & SURFACE_TWOSIDED) dstate->setMode( GL_CULL_FACE, osg::StateAttribute::OFF );
else dstate->setMode( GL_CULL_FACE, osg::StateAttribute::ON );
geom->setStateSet( dstate );
glist.push_back(geom);
geode->addDrawable(geom);
ia.push_back(asurf.mat);
}
osg::Vec3Array* normals = geom->getNormalArray();
/** calc surface normal **/
if (asurf.num_vertref >= 3) {
osg::Vec3 norm;
osg::ushort i1=(*nusidx)[0];
osg::ushort i2=(*nusidx)[1];
osg::ushort i3=(*nusidx)[2];
osgtri_calc_normal((*vertpool)[i1],
(*vertpool)[i2],
(*vertpool)[i3], norm);
normals->push_back(norm);
}
int nstart=(*vgeom).size();
for (i=0; i<asurf.num_vertref; i++) {
int i1=(*nusidx)[i];
(*vgeom).push_back((*vertpool)[i1]);
(*tgeom).push_back((*tcs)[i]);
}
GLenum poltype=osg::Primitive::POLYGON;
if (asurf.flags & SURFACE_TYPE_CLOSEDLINE) poltype=osg::Primitive::LINE_LOOP;
if (asurf.flags & SURFACE_TYPE_LINE) poltype=osg::Primitive::LINE_STRIP;
geom->addPrimitive(new osg::DrawArrays(poltype,nstart,asurf.num_vertref));
if (asurf.flags & 0x10) needSmooth++;
}
}
for (geomlist::iterator itr= glist.begin(); itr<glist.end(); itr++) {
osgUtil::Tesselator tesselator;
if (*itr) tesselator.retesselatePolygons(**itr);
if (needSmooth) {
osgUtil::SmoothingVisitor smoother;
smoother.smooth(**itr);
}
}
}
}
else
if (streq(t, "kids")) /** 'kids' is the last token in an object **/
{
int num, n;
sscanf(buff, "%s %d", t, &num);
if (num != 0)
{
// ob.kids = (ACObject **)myalloc(num * sizeof(ACObject *) );
ob.num_kids = num;
for (n = 0; n < num; n++)
{
osg::Group *k = ac_load_object(f,&ob); //, ob);
if (k == NULL)
{
printf("error reading expected child object %d of %d at line: %d\n", n+1, num, line);
return(gp);
}
else
//ob.kids[n] = k;
gp->addChild(k);
}
}
if (geode) {
osgUtil::Tesselator tesselator;
for(unsigned int i=0;i<geode->getNumDrawables();++i)
{
osg::Geometry* geom = dynamic_cast<osg::Geometry*>(geode->getDrawable(i));
if (geom) tesselator.retesselatePolygons(*geom);
}
}
return(gp);
}
}
if (geode) {
osgUtil::Tesselator tesselator;
for(unsigned int i=0;i<geode->getNumDrawables();++i)
{
osg::Geometry* geom = dynamic_cast<osg::Geometry*>(geode->getDrawable(i));
if (geom) tesselator.retesselatePolygons(*geom);
}
}
return(gp);
}
/*void ac_calc_vertex_normals(ACObject *ob)
{
int n;
ac_object_calc_vertex_normals(ob);
if (ob->num_kids)
for (n = 0; n < ob->num_kids; n++)
ac_calc_vertex_normals(ob->kids[n]);
}*/
osg::Group *ac_load_ac3d(const char *fname)
{
FILE *f = fopen(fname, "r");
osg::Group *ret = NULL;
if (f == NULL)
{
printf("can't open %s\n", fname);
return(NULL);
}
read_line(f);
if (strncmp(buff, "AC3D", 4))
{
printf("ac_load_ac '%s' is not a valid AC3D file.", fname);
fclose(f);
return(0);
}
startmatindex = num_palette;
ret = ac_load_object(f,NULL); //, NULL);
fclose(f);
// ac_calc_vertex_normals(ret);
// here I need to calculate nromals for this object
return(ret);
}
void ac_dump(ACObject *ob)
{ // not yet finished option ot output AC3D file from OSG scene.
int n;
printf("OBJECT name %s\nloc %f %f %f\nnum_vert %d\nnum_surf %d\n",
ob->name, ob->loc[0], ob->loc[1], ob->loc[2], ob->num_vert, ob->num_surf);
// for (n=0; n < ob->num_vert; n++)
// printf("\tv %f %f %f\n", ob->vertices[n].x, ob->vertices[n].y, ob->vertices[n].z);
for (n=0; n < ob->num_surf; n++)
{
//// ACSurface *s = &ob->surfaces[n];
// printf("surface %d, %d refs, mat %d\n", n, s->num_vertref, s->mat);
}
/* this structure not used in OSG
if (ob->num_kids)
for (n = 0; n < ob->num_kids; n++)
ac_dump(ob->kids[n]);
*/
}
// now register with osg::Registry to instantiate the above
// reader/writer.
osgDB::RegisterReaderWriterProxy<ReaderWriterAC> g_readerWriter_AC_Proxy;

View File

@@ -0,0 +1,13 @@
TOPDIR = ../../..
include $(TOPDIR)/Make/makedefs
CXXFILES =\
ReaderWriterGEO.cpp
LIBS += $(OSG_LIBS) $(OTHER_LIBS)
TARGET_BASENAME = geo
include $(TOPDIR)/Make/cygwin_plugin_def
PLUGIN = $(PLUGIN_PREFIX)$(TARGET_BASENAME).$(PLUGIN_EXT)
include $(TOPDIR)/Make/makerules

View File

@@ -0,0 +1,626 @@
// GEO format (carbon graphics Inc) loader for the OSG real time scene graph
// www.carbongraphics.com for more information about the Geo animation+ modeller
// 2002
#include "osg/Image"
#include "osg/Group"
#include "osg/LOD"
#include "osg/Billboard"
#include <osg/Sequence>
#include <osg/Switch>
#include <osg/Geode>
#include <osg/Geometry>
#include <osg/MatrixTransform>
#include <osg/Material>
#include <osg/Notify>
#include <osg/Texture2D>
#include <osg/TexEnv>
#include <osg/StateSet>
#include <osg/PositionAttitudeTransform>
#include "osgDB/FileNameUtils"
#include "osgDB/Registry"
#include <osgDB/ReadFile>
#include "osgDB/Input"
#include "osgDB/Output"
#include <stdio.h>
// specific to GEO
#include "geoFormat.h"
#include "geoTypes.h"
#include "geoUnits.h"
#include "osgGeoStructs.h"
using namespace osg;
using namespace osgDB;
class vertexInfo { // holds vertex information for an entire osg::geometry
public:
vertexInfo(const float *coord_pool, const float *normal_pool) {
norms=new osg::Vec3Array;
coords=new osg::Vec3Array;
txcoords=new osg::Vec2Array;
coordindices=new osg::IntArray;
normindices=new osg::IntArray;
txindices=new osg::IntArray;
cpool=coord_pool; npool=normal_pool;
}
inline osg::Vec3Array *getNorms() const { return norms;}
inline osg::Vec3Array *getCoords() const { return coords;}
inline osg::Vec2Array *getTexCoords() const { return txcoords;}
inline osg::IntArray *getCoordIndices() const { return coordindices;}
inline osg::IntArray *getNormIndices() const { return normindices;}
inline osg::IntArray *getTextureIndices() const { return txindices;}
void addIndices(georecord *gr)
{ // this must only be called with a vertex georecord.
if (gr->getType()==DB_DSK_VERTEX) {
const geoField *gfd=gr->getField(GEO_DB_VRTX_NORMAL);
int nrmindex=gfd ? gfd->getUInt():0;
normindices->push_back(nrmindex);
norms->push_back(osg::Vec3(npool[3*nrmindex],npool[3*nrmindex+1],npool[3*nrmindex+2]));
gfd=gr->getField(GEO_DB_VRTX_COORD);
unsigned int idx=gfd ? gfd->getInt():0;
coords->push_back(osg::Vec3(cpool[3*idx],cpool[3*idx+1],cpool[3*idx+2]));
coordindices->push_back(txcoords->size());
txindices->push_back(txcoords->size());
float *uvc=NULL;
gfd=gr->getField(GEO_DB_VRTX_UV_SET_1);
if (gfd) {
uvc=(float *)gfd->getstore(0);
}
if (uvc) { // then there are tx coords
osg::Vec2 uv(uvc[0], uvc[1]);
txcoords->push_back(uv);
} else {
txcoords->push_back(osg::Vec2(0,0));
}
}
}
friend inline std::ostream& operator << (std::ostream& output, const vertexInfo& vf)
{
const osg::Vec2Array *txa=vf.getTexCoords();
osg::IntArray *normindices=vf.getNormIndices();
osg::IntArray *txind = vf.getTextureIndices();
output << " vertexinfo " << txa->size() << " nrm: " << normindices->size()<<
" txinds " << txind->size()<<std::endl;
uint i;
for (i=0; i< txa->size(); i++) {
const osg::Vec2 uvt=(*txa)[i];
output << " U " << uvt.x() << " v " << uvt.y() << std::endl;
}
for (i=0; i<normindices->size(); i++) {
output << "Nind " << i << " = " << (*normindices)[i] << std::endl;
}
return output; // to enable cascading, monkey copy from osg\plane or \quat, Ubyte4, vec2,3,4,...
}
private:
const float *cpool; // passed in from the geo file
const float *npool;
osg::Vec3Array *norms;
osg::Vec3Array *coords;
osg::Vec2Array *txcoords;
osg::IntArray *coordindices;
osg::IntArray *normindices;
osg::IntArray *txindices;
};
class ReaderWriterGEO : public ReaderWriter
{
public:
virtual const char* className() { return "GEO Reader/Writer"; }
virtual bool acceptsExtension(const std::string& extension)
{
return equalCaseInsensitive(extension,"gem") || equalCaseInsensitive(extension,"geo");
}
virtual ReadResult readObject(const std::string& fileName, const Options* opt) { return readNode(fileName,opt); }
virtual ReadResult readNode(const std::string& fileName, const Options*)
{
std::string ext = getFileExtension(fileName);
if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED;
std::ifstream fin(fileName.c_str(), std::ios::binary | std::ios::in );
if (fin.is_open() )
{ // read the input file.
typedef std::vector<osg::Node*> NodeList;
NodeList nodeList;
geoRecordList recs;
osg::Material *mt=new osg::Material;
matlist.push_back(mt);
// load all nodes in file, placing them in a linear list corresponding to the on disk file.
while(!fin.eof())
{
georecord gr;
gr.readfile(fin);
// osg::notify(osg::WARN) << gr << std::endl;
recs.push_back(gr); // add to a list of all records
}
fin.close();
// now sort the reocrds so that any record followed by a PUSh has a child set = next record, etc
std::vector<georecord *> sorted=sort(recs); // tree-list of sorted record pointers
std::fstream fout("georex.txt", std::ios::out );
fout << "Debug file " << std::endl;
// output(fout,sorted); // print details of the sorted tree, with records indented.
nodeList=makeosg(sorted, fout); // make a list of osg nodes
fout.close();
if (nodeList.empty())
{
return ReadResult("No data loaded from "+fileName);
}
else if (nodeList.size()==1)
{
return nodeList.front();
}
else
{
Group* group = osgNew Group;
group->setName("import group");
for(NodeList::iterator itr=nodeList.begin();
itr!=nodeList.end();
++itr)
{
group->addChild(*itr);
}
return group;
}
}
else
{
return 0L;
}
}
std::vector<georecord *> sort(geoRecordList &recs) { // return a tree-list of sorted record pointers
// which mirrors the original .geo file (containers hold push/pop blocks).
std::vector<georecord *> sorted;
class georecord *curparent=NULL;
for (geoRecordList::iterator itr=recs.begin();
itr!=recs.end();
++itr) {
// osg::notify(osg::WARN) << *itr << std::endl;
// now parse for push/pops and add to lists
if ((*itr).getType()==DB_DSK_COORD_POOL) {
const geoField *gfd=itr->getField(GEO_DB_COORD_POOL_VALUES);
coord_pool= (gfd) ? (gfd->getVec3Arr()):NULL;
} else if ((*itr).getType()==DB_DSK_NORMAL_POOL) {
const geoField *gfd=itr->getField(GEO_DB_NORMAL_POOL_VALUES);
normal_pool= (gfd) ? (gfd->getVec3Arr()):NULL;
}
if ((*itr).getType()==DB_DSK_PUSH) {
curparent= itr-1;
} else if ((*itr).getType()==DB_DSK_POP) {
if (curparent) curparent=curparent->getparent();
} else {
if (curparent) {
(*itr).setparent(curparent);
curparent->addchild(itr);
} else {
sorted.push_back(itr);
}
}
}
return sorted;
}
int getprim(const std::vector<georecord *> gr,vertexInfo &vinf)
{ // fills vinf with txcoords = texture coordinates, txindex=txindex etc
int nv=0;
if (gr.size()>0) {
for (std::vector<georecord *>::const_iterator itr=gr.begin();
itr!=gr.end();
++itr) {
vinf.addIndices((*itr));
nv++;
}
}
return nv;
}
std::vector<osg::Geometry *>makeGeometry(const std::vector<georecord *> gr, const unsigned int imat)
{
// txcoords returns with a set of vec2 (UV coords for texturing)
std::vector<osg::Geometry *> geom;
if (gr.size()>0) {
std::vector<int> ia; // list of texture indices found i this geode; sort into new
vertexInfo vinf(coord_pool,normal_pool); // holds all types of coords, indices etc
int nstart=0; // start of list
for (std::vector<georecord *>::const_iterator itr=gr.begin();
itr!=gr.end();
++itr) {
if ((*itr)->getType()==DB_DSK_POLYGON) {
int txidx=-1;
const geoField *gfd=(*itr)->getField(GEO_DB_POLY_TEX);
if (gfd) txidx=gfd->getInt();
int igidx=0, igeom=-1;
for (IntArray::const_iterator itrint=ia.begin();
itrint!=ia.end();
++itrint) {
if (txidx==(*itrint)) igeom=igidx;
igidx++;
}
if (igeom<0) {
osg::Geometry *nug;
nug=new osg::Geometry;
nug->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
nug->setVertexArray(vinf.getCoords());
nug->setNormalArray(vinf.getNorms());
StateSet *dstate=new StateSet;
if (txidx>=0 && (unsigned int)txidx<txlist.size()) {
dstate->setTextureAttribute(0, txenvlist[txidx] );
dstate->setTextureAttributeAndModes(0,txlist[txidx],osg::StateAttribute::ON);
}
if (imat>0 && imat<matlist.size()) dstate->setAttribute(matlist[imat]);
else dstate->setAttribute(matlist[0]);
nug->setStateSet( dstate );
geom.push_back(nug);
igeom=ia.size();
ia.push_back(txidx); // look up table for which texture corresponds to which geom
}
int nv=getprim((*itr)->getchildren(),vinf);
geom[igeom]->addPrimitive(new osg::DrawArrays(osg::Primitive::POLYGON,nstart,nv));
nstart+=nv;
}
}
osg::Vec2Array *txa=vinf.getTexCoords();
if (txa->size() > 0 ) {
for (std::vector<osg::Geometry *>::iterator itr=geom.begin();
itr!=geom.end();
++itr) {
(*itr)->setTexCoordArray(0, txa);
}
}
// osg::notify(osg::WARN) << vinf;
}
return geom;
}
osg::Group *makeGroup(const georecord *gr) { // group or Static transform
osg::Group *gp=NULL;
const geoField *gfd=gr->getField(GEO_DB_GRP_TRANSFORM);
if (gfd) {
osg::MatrixTransform *tr=new osg::MatrixTransform;
osg::Matrix mx;
float * m44=gfd->getMat44Arr();
mx.set(m44); // hope uses same convention as OSG else will need to use set(m44[0],m44[1]...)
tr->setMatrix(mx);
gp=tr;
} else {
gp=new osg::Group;
}
gfd=gr->getField(GEO_DB_GRP_NAME);
if (gfd) {
gp->setName(gfd->getChar());
}
return gp;
}
osg::Group * makeSwitch(const georecord *gr) {
osg::Switch *sw=new Switch;
const geoField *gfd=gr->getField(GEO_DB_SWITCH_CURRENT_MASK);
sw->setValue(osg::Switch::ALL_CHILDREN_OFF);
if (gfd) {
int imask;
imask=gfd->getInt();
sw->setValue(imask);
osg::notify(osg::WARN) << gr << " imask " << imask << std::endl;
} else {
sw->setValue(0);
osg::notify(osg::WARN) << gr << " No mask " << std::endl;
}
gfd=gr->getField(GEO_DB_SWITCH_NAME);
if (gfd) {
sw->setName(gfd->getChar());
}
return sw;
}
osg::Sequence *makeSequence(const georecord *gr)
{
Sequence *sq=new Sequence;
const geoField *gfd=gr->getField(GEO_DB_SEQUENCE_NAME);
if (gfd) {
sq->setName(gfd->getChar());
}
return sq;
}
osg::LOD *makeLOD(const georecord *gr)
{
osg::LOD *gp=new LOD;
const geoField *gfd=gr->getField(GEO_DB_LOD_IN);
float in = gfd ? gfd->getFloat() : 100.0;
gfd=gr->getField(GEO_DB_LOD_OUT);
float out = gfd ? gfd->getFloat() : 0.0;
gp->setRange(0,out,in);
gfd=gr->getField(GEO_DB_LOD_NAME);
if (gfd) {
gp->setName(gfd->getChar());
}
return gp;
}
osg::PositionAttitudeTransform *makeHeader(const georecord *gr) {
osg::PositionAttitudeTransform *nup=NULL;
const geoField *gfd=gr->getField(GEO_DB_HDR_UP_AXIS);
if (gfd) {
unsigned iup=gfd->getUInt();
if (iup==GEO_DB_UP_AXIS_X) {
nup=new PositionAttitudeTransform();
osg::Quat q;
q.set(1,1,0,0);
q/=q.length();
nup->setAttitude(q);
} else if (iup==GEO_DB_UP_AXIS_Y) {
nup=new PositionAttitudeTransform();
osg::Quat q;
q.set(1,0,0,1);
q/=q.length();
nup->setAttitude(q);
}
}
return nup;
}
void makeTexture(const georecord *gr) {
// scans the fields of this record and puts a new texture & environment into 'pool' stor
const geoField *gfd=gr->getField(GEO_DB_TEX_FILE_NAME);
const char *name = gfd->getChar();
if (name) {
Texture2D *tx=new Texture2D;
Image *ctx=osgDB::readImageFile(name);
if (ctx) {
ctx->setFileName(name);
tx->setImage(ctx);
}
gfd=gr->getField(GEO_DB_TEX_WRAPS);
osg::Texture2D::WrapMode wm=Texture2D::REPEAT;
if (gfd) {
unsigned iwrap= gfd->getUInt();
wm = (iwrap==GEO_DB_TEX_CLAMP) ? Texture2D::CLAMP : Texture2D::REPEAT;
}
tx->setWrap(Texture2D::WRAP_S, wm);
gfd=gr->getField(GEO_DB_TEX_WRAPT);
wm=Texture2D::REPEAT;
if (gfd) {
unsigned iwrap= gfd->getUInt();
wm = (iwrap==GEO_DB_TEX_CLAMP) ? Texture2D::CLAMP : Texture2D::REPEAT;
}
tx->setWrap(Texture2D::WRAP_T, wm);
txlist.push_back(tx);
osg::TexEnv* texenv = new osg::TexEnv;
osg::TexEnv::Mode md=osg::TexEnv::MODULATE;
gfd=gr->getField(GEO_DB_TEX_ENV);
texenv->setMode(md);
if (gfd) {
unsigned imod=gfd->getUInt();
switch (imod) {
case GEO_DB_TEX_MODULATE:
md=osg::TexEnv::MODULATE;
break;
case GEO_DB_TEX_DECAL:
md=osg::TexEnv::DECAL;
break;
case GEO_DB_TEX_BLEND:
md=osg::TexEnv::BLEND;
break;
}
}
gfd=gr->getField(GEO_DB_TEX_MINFILTER);
osg::Texture::FilterMode filt=osg::Texture::NEAREST_MIPMAP_NEAREST;
if (gfd) {
unsigned imod=gfd->getUInt();
switch (imod) {
case GEO_DB_TEX_NEAREST_MIPMAP_NEAREST:
filt=osg::Texture::LINEAR_MIPMAP_LINEAR;
break;
case GEO_DB_TEX_LINEAR_MIPMAP_NEAREST:
filt=osg::Texture::LINEAR_MIPMAP_NEAREST;
break;
case GEO_DB_TEX_NEAREST_MIPMAP_LINEAR:
filt=osg::Texture::NEAREST_MIPMAP_LINEAR;
break;
case GEO_DB_TEX_LINEAR_MIPMAP_LINEAR:
filt=osg::Texture::NEAREST_MIPMAP_NEAREST;
break;
}
}
tx->setFilter(osg::Texture::MIN_FILTER, filt);
gfd=gr->getField(GEO_DB_TEX_MAGFILTER);
if (gfd) {
unsigned imod=gfd->getUInt();
switch (imod) {
case GEO_DB_TEX_NEAREST:
filt=osg::Texture::LINEAR;
break;
case GEO_DB_TEX_LINEAR:
filt=osg::Texture::NEAREST;
break;
}
}
txenvlist.push_back(texenv);
}
}
std::vector<Node *> makeosg(const std::vector<georecord *> gr, std::fstream &fout) {
// recursive traversal of records and extract osg::Nodes equivalent
Group *geodeholder=NULL;
std::vector<Node *> nodelist;
if (gr.size()>0) {
for (std::vector<georecord *>::const_iterator itr=gr.begin();
itr!=gr.end();
++itr) {
const georecord *gr=*itr;
if (gr->getType()== DB_DSK_GEODE) { // geodes can require >1 geometry for example if polygons have different texture indices.
if (!geodeholder) {
geodeholder=new osg::Group;
}
Geode *geode=new Geode;
const geoField *gfd=gr->getField(GEO_DB_RENDERGROUP_MAT);
const unsigned int imat=gfd ? gfd->getInt():0;
std::vector<osg::Geometry *>geom=makeGeometry((*itr)->getchildren(),imat);
for (std::vector<osg::Geometry *>::iterator itr=geom.begin();
itr!=geom.end();
++itr)
{
geode->addDrawable((*itr));
}
geodeholder->addChild(geode);
} else {
Group *holder=NULL;
const geoField *gfd;
switch (gr->getType()) {
case DB_DSK_HEADER:
holder=makeHeader(gr);
break;
case DB_DSK_MATERIAL: {
osg::Material *mt=new osg::Material;
gr->setMaterial(mt);
matlist.push_back(mt);
}
break;
case DB_DSK_TEXTURE:
makeTexture(gr);
break;
case DB_DSK_GROUP:
holder=makeGroup(gr);
break;
case DB_DSK_BEHAVIOR:
holder=new MatrixTransform;
gfd=gr->getField(GEO_DB_BEHAVIOR_NAME);
if (gfd) {
holder->setName(gfd->getChar());
}
break;
case DB_DSK_LOD:
holder=makeLOD(gr);
break;
case DB_DSK_SEQUENCE:
holder=makeSequence(gr);
break;
case DB_DSK_SWITCH:
holder=makeSwitch(gr);
break;
case DB_DSK_CUBE:
holder=new Group;
gfd=gr->getField(GEO_DB_GRP_NAME);
if (gfd) {
holder->setName(gfd->getChar());
}
break;
case DB_DSK_SPHERE:
holder=new Group;
gfd=gr->getField(GEO_DB_GRP_NAME);
if (gfd) {
holder->setName(gfd->getChar());
}
break;
case DB_DSK_CONE:
holder=new Group;
gfd=gr->getField(GEO_DB_GRP_NAME);
if (gfd) {
holder->setName(gfd->getChar());
}
break;
case DB_DSK_CYLINDER:
holder=new Group;
gfd=gr->getField(GEO_DB_GRP_NAME);
if (gfd) {
holder->setName(gfd->getChar());
}
break;
case DB_DSK_INSTANCE:
holder=new Group;
/*gfd=gr->getField(GEO_DB_GRP_NAME);
if (gfd) {
holder->setName(gfd->getChar());
} */
break;
case DB_DSK_PAGE:
holder=new Group;
gfd=gr->getField(GEO_DB_PAGE_NAME);
if (gfd) {
holder->setName(gfd->getChar());
}
break;
case DB_DSK_FLOAT_VAR:
case DB_DSK_INT_VAR:
case DB_DSK_LONG_VAR:
case DB_DSK_DOUBLE_VAR:
case DB_DSK_BOOL_VAR:
case DB_DSK_FLOAT2_VAR:
case DB_DSK_FLOAT3_VAR:
case DB_DSK_FLOAT4_VAR:
case DB_DSK_INTERNAL_VARS:
case DB_DSK_LOCAL_VARS:
case DB_DSK_EXTERNAL_VARS:
fout << "==Unhandled option " << gr->getType() << std::endl;
fout << (*gr) << std::endl;
break;
case DB_DSK_CLAMP_ACTION:
case DB_DSK_RANGE_ACTION:
case DB_DSK_ROTATE_ACTION:
case DB_DSK_TRANSLATE_ACTION:
case DB_DSK_SCALE_ACTION:
case DB_DSK_ARITHMETIC_ACTION:
case DB_DSK_LOGIC_ACTION:
case DB_DSK_CONDITIONAL_ACTION:
case DB_DSK_LOOPING_ACTION:
case DB_DSK_COMPARE_ACTION:
case DB_DSK_VISIBILITY_ACTION:
case DB_DSK_STRING_CONTENT_ACTION:
holder=new Group;
fout << "==Poorly handled option " << gr->getType() << std::endl;
fout << (*gr) << std::endl;
break;
default: {
osg::Group *gp=new Group;
holder=gp;
}
break;
}
nodelist.push_back(holder);
std::vector<Node *> child=makeosg((*itr)->getchildren(),fout);
for (std::vector<Node *>::iterator itr=child.begin();
itr!=child.end();
++itr) {
holder->addChild(*itr);
}
}
}
}
if (geodeholder) nodelist.push_back(geodeholder);
return nodelist;
}
void output(std::fstream &fout,std::vector<georecord *> gr)
{ // debugging - print the tree of records
static int depth=0;
depth++;
if (gr.size()>0) {
for (std::vector<georecord *>::iterator itr=gr.begin();
itr!=gr.end();
++itr) {
// osg::notify(osg::WARN)
for (int i=0; i<depth-1; i++) fout << " " ;
fout << "Node type " << (*itr)->getType() << " ";
fout << (**itr) << std::endl;
fout << std::endl;
output(fout,(*itr)->getchildren());
}
}
depth--;
}
private:
// std::fstream fout; // debug output
static float *coord_pool; // current vertex ooords
static float *normal_pool; // current pool of normal vectors
std::vector<osg::Texture2D *> txlist; // list of textures for this model
std::vector<osg::TexEnv *> txenvlist; // list of texture environments for the textures
std::vector<osg::Material *> matlist; // list of materials for current model
};
// now register with Registry to instantiate the above
// reader/writer.
osgDB::RegisterReaderWriterProxy<ReaderWriterGEO> gReaderWriter_GEO_Proxy;
float *ReaderWriterGEO::coord_pool=NULL; // current vertex ooords
float *ReaderWriterGEO::normal_pool=NULL; // current vertex ooords

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,377 @@
/*===========================================================================*\
NAME: geoTypes.h
DESCRIPTION: Constants fro Node types etc.
AUTHOR: Andy Bushnell
-------------------------------------------------------------------------
PROPRIETARY RIGHTS NOTICE:
This software contains proprietary information and trade secrets of Carbon
Graphics LLC. No part or all of this software may be reproduced in any form,
without the written permission of Carbon Graphics LLC.
Exception:
This Software file can be used by third-party software developers (without
using the Geo SDK libraries) for any purpose OTHER THAN loading Geo format
files into an application or executable (such as, though not limited to,
geometry Modelers & animation systems) which is primarily intended to allow for
the CREATION or MODIFICATION of geometric or animation data.
Specifically,using this software (either all or part thereof) to aid in the
creation of a Geo format loader for a run-time system, game engine, toolkit
IG (Image Generation) System or any software where the PRIMARY purpose is
real-time image playback and interactivity and not Model Creation and/or
modification is permitted.
COPYRIGHT NOTICE:
Copyright <20> 1998-2001 Carbon Graphics Llc, ALL RIGHTS RESERVED
\*===========================================================================*/
#ifndef _GEO_TYPES_H_
#define _GEO_TYPES_H_
#ifndef uint
#define uint unsigned int
#endif
#ifndef ushort
//#define ushort unsigned short
#endif
#ifndef ubyte
#define ubyte unsigned char
#endif
/**
* constants to identify the plugin type
*/
const uint GEO_PLUGIN_TYPE_UNDEFINED = 1;
const uint GEO_PLUGIN_TYPE_GEOMETRY_IMPORTER = 2;
const uint GEO_PLUGIN_TYPE_GEOMETRY_EXPORTER = 3;
const uint GEO_PLUGIN_TYPE_IMAGE_IMPORTER = 4;
const uint GEO_PLUGIN_TYPE_TOOL = 5;
const uint GEO_PLUGIN_TYPE_BEHAVIOR = 6;
const uint GEO_PLUGIN_TYPE_GROUP_NODE_DEF = 7;
const uint GEO_PLUGIN_TYPE_LAST = GEO_PLUGIN_TYPE_GROUP_NODE_DEF;
/** user tool constant - put in favorites menu & toolbar */
const uint GEO_TOOL_TYPE_USER = 1;
/** create tool constant - put in create menu & toolbar */
const uint GEO_TOOL_TYPE_CREATE = 2;
/** modify tool constant - put in modify menu & toolbar */
const uint GEO_TOOL_TYPE_MODIFY = 3;
/** helper point tool constant - put in helpers menu & toolbar */
const uint GEO_TOOL_TYPE_HELPER_PT = 4;
/** appearance tool constant - put in plugins menu & toolbar */
const uint GEO_TOOL_TYPE_APPEARANCE = 5;
/** behavior tool constant - put in plugins menu & toolbar */
const uint GEO_TOOL_TYPE_BEHAVIOR = 6;
/** behavior tool constant - put in plugins menu & toolbar */
const uint GEO_TOOL_TYPE_OPTIMIZE = 7;
/** convenience constant */
const uint GEO_TOOL_TYPE_LAST = GEO_TOOL_TYPE_OPTIMIZE;
/**
* Node Type identifiers. These tokens encode the Node's inheritance
* information within the type
*
* The GEO Node Type Class Hierarchy is as follows...
*
* GEO_DB_BASE
* GEO_DB_GROUP
* GEO_DB_BILLBOARD
* GEO_DB_SEQUENCE
* GEO_DB_LOD
* GEO_DB_SWITCH
* GEO_DB_RENDERGROUP
* GEO_DB_BASE_GROUP
* GEO_DB_EXTERNAL
* GEO_DB_INSTANCE
* GEO_DB_PAGE
* GEO_DB_TRANSFORM (*)
* GEO_DB_GEOMETRY
* GEO_DB_SURFACE
* GEO_DB_COORDINATE_SURFACE
* GEO_DB_POLYGON
* GEO_DB_LIGHTPT
* GEO_DB_MESH (*)
* GEO_DB_PARAMETRIC_SURFACE (*)
* GEO_DB_QUADRIC (*)
* GEO_DB_TEXT
* GEO_DB_BASE_SURFACE (*)
* GEO_DB_VERTEX
* GEO_DB_HEADER
*
* (*) Not available in Geo Version 1.0
*/
const uint GEO_DB_BASE = 0x00000003;
const uint GEO_DB_GROUP = (0x00000004 | GEO_DB_BASE);
const uint GEO_DB_SEQUENCE = (0x00000010 | GEO_DB_GROUP);
const uint GEO_DB_LOD = (0x00000020 | GEO_DB_GROUP);
const uint GEO_DB_SWITCH = (0x00000040 | GEO_DB_GROUP);
const uint GEO_DB_RENDERGROUP = (0x00000080 | GEO_DB_GROUP);
const uint GEO_DB_GEOMETRY = (0x00000100 | GEO_DB_BASE);
const uint GEO_DB_SURFACE = (0x00000200 | GEO_DB_GEOMETRY);
const uint GEO_DB_COORDINATE_SURFACE = (0x00000400 | GEO_DB_SURFACE);
const uint GEO_DB_POLYGON = (0x00000800 | GEO_DB_COORDINATE_SURFACE);
const uint GEO_DB_MESH = (0x00001000 | GEO_DB_POLYGON);
const uint GEO_DB_PARAMETRIC_SURFACE = (0x00002000 | GEO_DB_SURFACE);
const uint GEO_DB_QUADRIC = (0x00004000 | GEO_DB_PARAMETRIC_SURFACE);
const uint GEO_DB_PAGE = (0x00008000 | GEO_DB_GROUP);
const uint GEO_DB_TEXT = (0x00040000 | GEO_DB_SURFACE);
const uint GEO_DB_VERTEX = (0x00080000 | GEO_DB_GEOMETRY);
const uint GEO_DB_HEADER = (0x00100000 | GEO_DB_BASE);
const uint GEO_DB_TRANSFORM = (0x00200000 | GEO_DB_GROUP);
const uint GEO_DB_BASE_GROUP = (0x00400000 | GEO_DB_GROUP);
const uint GEO_DB_BASE_SURFACE = (0x00800000 | GEO_DB_SURFACE);
const uint GEO_DB_EXTERNAL = (0x01000000 | GEO_DB_GROUP);
const uint GEO_DB_INSTANCE = (0x04000000 | GEO_DB_GROUP);
const uint GEO_DB_LIGHTPT = (0x08000000 | GEO_DB_POLYGON);
// older version types for Compatability & convenience
//
const uint GEO_DB_ALL = GEO_DB_BASE;
const uint GEO_DB_ALL_GROUP_TYPES = GEO_DB_GROUP;
const uint GEO_DB_ALL_SURFACE_TYPES = GEO_DB_SURFACE;
const uint GEO_DB_ALL_SHAPE_TYPES = GEO_DB_PARAMETRIC_SURFACE;
const uint GEO_DB_ALL_GEOMETRY_TYPES = GEO_DB_GEOMETRY;
///////////////////////////////////////////////////////////////////////////////
/** constants to identify the type of picking to be done */
const uint GEO_PICK_GROUP = 0x00000001;
const uint GEO_PICK_PRIM = 0x00000002;
const uint GEO_PICK_VERTEX = 0x00000004;
const uint GEO_PICK_EDGE = 0x00000008; // Future
const uint GEO_PICK_GRID = 0x00000010;
const uint GEO_PICK_NON_NODE = 0x00000020; // manipulators, user geometry etc.
const uint GEO_PICK_EXTERNAL = 0x00000040;
///////////////////////////////////////////////////////////////////////////////
/** constants to identify mouse button usage */
const uint GEO_NO_MOUSE = 0x00000000;
const uint GEO_LEFT_MOUSE = 0x00000001;
const uint GEO_MIDDLE_MOUSE = 0x00000002;
const uint GEO_RIGHT_MOUSE = 0x00000004;
const uint GEO_LEFT_AND_RIGHT_MOUSE = 0x00000008;
const uint GEO_MIDDLE_AND_RIGHT_MOUSE = 0x00000010;
///////////////////////////////////////////////////////////////////////////////
/** Predefined model unit identifier. database model units can be modified
* via set/getUnits
*/
const uint GEO_DB_INCHES = 1;
const uint GEO_DB_FEET = 2;
const uint GEO_DB_YARDS = 3;
const uint GEO_DB_MILES = 4;
const uint GEO_DB_CENTIMETERS = 5;
const uint GEO_DB_METERS = 6;
const uint GEO_DB_KILOMETERS = 7;
///////////////////////////////////////////////////////////////////////////////
/** Constants to define the modeler's intended "up" direction if that
* makes any sense
*/
const int GEO_DB_UP_AXIS_X = 1;
const int GEO_DB_UP_AXIS_Y = 2; // the default
const int GEO_DB_UP_AXIS_Z = 3;
///////////////////////////////////////////////////////////////////////////////
/** Constants to control the drawing effect
*
* Constants to control the drawing of geometry primitives - usefull if user
* wants to call standard draw method in a tool postDraw callback
*/
const uint GEO_DB_SOLID = 0x00000001;
const uint GEO_DB_WIRE = 0x00000002;
const uint GEO_DB_OUTLINED = 0x00000008;
const uint GEO_DB_ZBUFFER = 0x00000100;
const uint GEO_DB_BACKFACE = 0x00000400;
const uint GEO_DB_DRAW_FACE_NORMALS = 0x00001000;
const uint GEO_DB_DRAW_VERTEX_NORMALS = 0x00002000;
const uint GEO_DB_TEXTURE = 0x00010000;
const uint GEO_DB_HIGHLIGHT = 0x00020000;
const uint GEO_DB_PICKING = 0x00040000;
const uint GEO_DB_HIGHLIGHT_DASHED = 0x00080000;
const uint GEO_DB_ILLUMINATED = 0x01000000;
const uint GEO_DB_NORMAL_PER_PRIM = 0x04000000;
const uint GEO_DB_NORMAL_PER_VERTEX = 0x08000000;
const uint GEO_DB_COLOR_PER_GEODE = 0x10000000;
const uint GEO_DB_COLOR_PER_PRIM = 0x20000000;
const uint GEO_DB_COLOR_PER_VERTEX = 0x40000000;
///////////////////////////////////////////////////////////////////////////////
/** Constants to control the switch Node behavior
*
* Switch Nodes can either be addative (in which case the
* accumulate drawable children) or selective (in which case
* the determine which of their children should be drawn).
*
* Selctive control is not implemented.
*/
const uint GEO_SWITCH_TYPE_ADDATIVE = 1;
const uint GEO_SWITCH_TYPE_SELECTIVE = 2;
///////////////////////////////////////////////////////////////////////////////
/** Type Tokens for Node & Tool Gui Widgets */
const int GUI_FLOAT = 1;
const int GUI_INT = 2;
const int GUI_STRING = 3;
///////////////////////////////////////////////////////////////////////////////
/** geoWidget Typedef - Used by Node & Tool Gui Widgets */
typedef void geoWidget;
///////////////////////////////////////////////////////////////////////////////
/** Animated String padding tokens */
const int GEO_TEXT_PAD_NONE = 0;
const int GEO_TEXT_PAD_WITH_SPACES = 1;
const int GEO_TEXT_PAD_WITH_ZEROES = 2;
///////////////////////////////////////////////////////////////////////////////
// Polygon draw style types
//
const int GEO_POLY_DSTYLE_SOLID = 0;
const int GEO_POLY_DSTYLE_OPEN_WIRE = 1;
const int GEO_POLY_DSTYLE_CLOSED_WIRE = 2;
const int GEO_POLY_DSTYLE_POINTS = 3;
const int GEO_POLY_DSTYLE_SOLID_BOTH_SIDES = 4;
///////////////////////////////////////////////////////////////////////////////
// Polygon shade style types
//
const int GEO_POLY_SHADEMODEL_FLAT = 0;
const int GEO_POLY_SHADEMODEL_GOURAUD = 1;
const int GEO_POLY_SHADEMODEL_LIT = 2;
const int GEO_POLY_SHADEMODEL_LIT_GOURAUD = 3;
///////////////////////////////////////////////////////////////////////////////
// Texture Mapping types
//
const int GEO_POLY_PLANAR_MAP = 0;
const int GEO_POLY_CYLINDRICAL_MAP = 1;
const int GEO_POLY_SPHERICAL_MAP = 2;
///////////////////////////////////////////////////////////////////////////////
// STring type constants
//
const int GEO_TEXT_RASTER = 0;
const int GEO_TEXT_STROKE = 1;
///////////////////////////////////////////////////////////////////////////////
// Justification constants
//
const int GEO_TEXT_LEFT_JUSTIFY = 0;
const int GEO_TEXT_CENTER_JUSTIFY = 1;
const int GEO_TEXT_RIGHT_JUSTIFY = 2;
///////////////////////////////////////////////////////////////////////////////
// Direction constants
//
const int GEO_TEXT_LEFT_TO_RIGHT = 0;
const int GEO_TEXT_RIGHT_TO_LEFT = 1;
const int GEO_TEXT_TOP_TO_BOTTOM = 2;
const int GEO_TEXT_BOTTOM_TO_TOP = 3;
///////////////////////////////////////////////////////////////////////////////
// LightPoint Type constants
//
const int GEO_DB_LIGHTPT_OMNI_DIRECTIONAL = 0;
const int GEO_DB_LIGHTPT_UNI_DIRECTIONAL = 1;
const int GEO_DB_LIGHTPT_BI_DIRECTIONAL = 2;
///////////////////////////////////////////////////////////////////////////////
// Texture Record Wrap S & T Modes
const unsigned GEO_DB_TEX_CLAMP = 0x00000001;
const unsigned GEO_DB_TEX_REPEAT = 0x00000002;
///////////////////////////////////////////////////////////////////////////////
// Texture Record MagFilter
const unsigned GEO_DB_TEX_NEAREST = 0x00000001;
const unsigned GEO_DB_TEX_LINEAR = 0x00000002;
///////////////////////////////////////////////////////////////////////////////
// Texture Record MinFilter
const unsigned GEO_DB_TEX_NEAREST_MIPMAP_NEAREST = 0x00000004;
const unsigned GEO_DB_TEX_LINEAR_MIPMAP_NEAREST = 0x00000008;
const unsigned GEO_DB_TEX_NEAREST_MIPMAP_LINEAR = 0x00000010;
const unsigned GEO_DB_TEX_LINEAR_MIPMAP_LINEAR = 0x00000020;
///////////////////////////////////////////////////////////////////////////////
// Texture Record TexEnv
const unsigned GEO_DB_TEX_MODULATE = 0x00000001;
const unsigned GEO_DB_TEX_DECAL = 0x00000002;
const unsigned GEO_DB_TEX_BLEND = 0x00000004;
#endif //_GEO_TYPES_H_

View File

@@ -0,0 +1,74 @@
/*===========================================================================*\
NAME: geoUnits.h
DESCRIPTION: Constants to convert coordinate data to/from meters (Geo
default)
AUTHOR: Andy Bushnell
-------------------------------------------------------------------------
PROPRIETARY RIGHTS NOTICE:
This software contains proprietary information and trade secrets of Carbon
Graphics LLC. No part or all of this software may be reproduced in any form,
without the written permission of Carbon Graphics LLC.
Exception:
This Software file can be used by third-party software developers (without
using the Geo SDK libraries) for any purpose OTHER THAN loading Geo format
files into an application or executable (such as, though not limited to,
geometry Modelers & animation systems) which is primarily intended to allow for
the CREATION or MODIFICATION of geometric or animation data.
Specifically,using this software (either all or part thereof) to aid in the
creation of a Geo format loader for a run-time system, game engine, toolkit
IG (Image Generation) System or any software where the PRIMARY purpose is
real-time image playback and interactivity and not Model Creation and/or
modification is permitted.
COPYRIGHT NOTICE:
Copyright <20> 1998-2001 Carbon Graphics Llc, ALL RIGHTS RESERVED
\*===========================================================================*/
#ifndef _GEO_UNITS_H_
#define _GEO_UNITS_H_
const float KM_TO_METERS = 1000.0f;
const float CM_TO_METERS = 0.01f;
const float MM_TO_METERS = 0.001f;
const float NM_TO_METERS = 1852.0f;
const float MILES_TO_METERS = 1609.344f;
const float YARDS_TO_METERS = 0.9144f;
const float FEET_TO_METERS = 0.3048f;
const float INCHES_TO_METERS= 0.0254f;
const float METERS_TO_KM = 0.001f;
const float METERS_TO_CM = 100.0f;
const float METERS_TO_MM = 1000.0f;
const float METERS_TO_NM = 0.0005399568035f;
const float METERS_TO_MILES = 0.0006213711922f;
const float METERS_TO_YARDS = 1.093613298f;
const float METERS_TO_FEET = 3.280839895f;
const float METERS_TO_INCHES= 39.37007874f;
const float CM_TO_FEET = 0.03280839895f;
const float CM_TO_INCHES = 0.3937007874f;
const float FEET_TO_YARDS = 0.333333333f;
const float FEET_TO_CM = 30.48f;
const float FEET_TO_INCHES = 12.0f;
const float INCHES_TO_FEET = 0.083333333f;
const float INCHES_TO_CM = 2.54f;
const float MPH_TO_FPS = 1.4667f;
const float MPH_TO_MPS = 0.447f;
#endif //_GEO_UNITS_H_

View File

@@ -0,0 +1,466 @@
/*===========================================================================*\
NAME: osgGeoStructs.h
DESCRIPTION: OSG data format for reading a Geo file into OSG
AUTHOR: Geoff Michel
// -------------------------------------------------------------------------
\ *===========================================================================*/
#ifndef _GEO_STRUCTS_H_
#define _GEO_STRUCTS_H_
class geoField { // holds one field of data as read from the disk of a GEO file
public:
geoField() {
tokenId=TypeId=0; numItems=0;storeSize=0;
}
unsigned char *readStorage(std::ifstream &fin, const unsigned sz) {
unsigned char *st=new unsigned char[numItems*sz];
storeSize=sz;
fin.read((char *)st, sz*numItems);
return st;
}
void storageRead(std::ifstream &fin) {
switch (TypeId) {
case DB_CHAR:
storage=readStorage(fin,SIZEOF_CHAR);
break;
case DB_SHORT:
storage=readStorage(fin,SIZEOF_SHORT);
break;
case DB_INT:
storage=readStorage(fin,SIZEOF_INT);
break;
case DB_FLOAT:
storage=readStorage(fin,SIZEOF_FLOAT);
break;
case DB_LONG:
storage=readStorage(fin,SIZEOF_LONG);
break;
case DB_ULONG:
storage=readStorage(fin,SIZEOF_ULONG);
break;
case DB_DOUBLE:
storage=readStorage(fin,SIZEOF_DOUBLE);
break;
case DB_VEC2F:
storage=readStorage(fin,SIZEOF_VEC2F);
break;
case DB_VEC3F:
storage=readStorage(fin,SIZEOF_VEC3F);
break;
case DB_VEC4F:
storage=readStorage(fin,SIZEOF_VEC4F);
break;
case DB_VEC16F:
storage=readStorage(fin,SIZEOF_VEC16F);
break;
case DB_VEC2I:
storage=readStorage(fin,SIZEOF_VEC2I);
break;
case DB_VEC3I:
storage=readStorage(fin,SIZEOF_VEC3I);
break;
case DB_VEC4I:
storage=readStorage(fin,SIZEOF_VEC4I);
break;
case DB_VEC2D:
storage=readStorage(fin,SIZEOF_VEC2D);
break;
case DB_VEC3D:
storage=readStorage(fin,SIZEOF_VEC3D);
break;
case DB_VEC4D:
storage=readStorage(fin,SIZEOF_VEC4D);
break;
case DB_VEC16D:
storage=readStorage(fin,SIZEOF_VEC16D);
break;
case DB_VRTX_STRUCT:
storage=readStorage(fin,SIZEOF_VRTX_STRUCT);
break;
case DB_UINT:
storage=readStorage(fin,SIZEOF_UINT);
break;
case DB_USHORT:
storage=readStorage(fin,SIZEOF_USHORT);
break;
case DB_UCHAR:
storage=readStorage(fin,SIZEOF_UCHAR);
break;
case DB_EXT_STRUCT:
storage=readStorage(fin,SIZEOF_EXT_STRUCT);
break;
case DB_SHORT_WITH_PADDING:
storage=readStorage(fin,SIZEOF_ULONG);
break;
case DB_CHAR_WITH_PADDING:
storage=readStorage(fin,SIZEOF_CHAR_WITH_PADDING);
break;
case DB_USHORT_WITH_PADDING:
storage=readStorage(fin,SIZEOF_USHORT_WITH_PADDING);
break;
case DB_UCHAR_WITH_PADDING:
storage=readStorage(fin,SIZEOF_UCHAR_WITH_PADDING);
break;
case DB_BOOL_WITH_PADDING:
storage=readStorage(fin,SIZEOF_BOOL_WITH_PADDING);
break;
case DB_EXTENDED_FIELD_STRUCT:
storage=readStorage(fin,SIZEOF_EXTENDED_FIELD_STRUCT);
break;
case DB_VEC4UC:
storage=readStorage(fin,SIZEOF_VEC4UC);
break;
case DB_DISCRETE_MAPPING_STRUCT:
storage=readStorage(fin,SIZEOF_DISCRETE_MAPPING_STRUCT);
break;
case DB_BITFLAGS:
storage=readStorage(fin,SIZEOF_BITFLAGS);
break;
}
}
void readfile(std::ifstream &fin) {
osg::uchar tokid, type;
osg::ushort nits;
if (!fin.eof()) {
fin.read((char *)&tokid,1);fin.read((char *)&type,1);
fin.read((char *)&nits,sizeof(unsigned short));
if (TypeId == GEO_DB_EXTENDED_FIELD) {
fin.read((char *)&tokenId,sizeof(tokenId));fin.read((char *)&TypeId,sizeof(TypeId));
fin.read((char *)&numItems,sizeof(unsigned int));
} else {
tokenId=tokid; TypeId=type;
numItems=nits;
}
storageRead(fin); // allocate & fill the storage
}
}
inline osg::uchar getToken() const { return tokenId;}
inline osg::uchar getType() const { return TypeId;}
inline unsigned short getNum() const { return numItems;}
inline unsigned char *getstore (unsigned int i) const {
return storage+i*storeSize;
}
void uncompress() { // folow the recipe to uncompress
if (TypeId==DB_VEC3F) { // already uncompressed
} else {
float *norms=new float[numItems*SIZEOF_VEC3F]; // uncompressed size
for (uint i=0; i<numItems; i++) {
switch (TypeId) {
case DB_UINT:
norms[3*i]=storage[4*i+1]/255.0f;
norms[3*i+1]=storage[4*i+2]/255.0f;
norms[3*i+2]=storage[4*i+3]/255.0f;
if (storage[4*i] & 0x01) norms[3*i] *= -1;
if (storage[4*i] & 0x02) norms[3*i+1] *= -1;
if (storage[4*i] & 0x04) norms[3*i+2] *= -1;
break;
case DB_SHORT:
norms[3*i]=(storage[6*i]*255+storage[6*i+1])/32767.0f;
norms[3*i+1]=(storage[6*i+2]*255+storage[6*i+3])/32767.0f;
norms[3*i+2]=(storage[6*i+4]*255+storage[6*i+5])/32767.0f;
break;
case DB_CHAR:
norms[3*i]=storage[3*i]/127.0f;
norms[3*i+1]=storage[3*i+1]/127.0f;
norms[3*i+2]=storage[3*i+2]/127.0f;
break;
}
}
delete [] storage;
TypeId=DB_VEC3F;
storage=(unsigned char *)norms;
}
}
void warn(const char *type, unsigned tval) const { if (getType() != tval)
osg::notify(osg::WARN) << "Wrong type " << type <<" expecting "<< getType() << std::endl;}
unsigned int getUInt() const {warn("getUInt",DB_UINT); return *((unsigned int*)storage);} // return int value
char *getChar() const {warn("getChar",DB_CHAR); return (char *)storage;} // return chars, eg for name or file name
int getInt() const {warn("getInt", DB_INT); return *((int*)storage);} // return int value
float getFloat() const {warn("getFloat", DB_FLOAT); return (*(float *)storage); }
float *getFloatArr() const {warn("getFloatArr", DB_FLOAT); return ( (float *)storage); }
float *getVec3Arr() const {warn("getVec3Arr", DB_VEC3F); return ( (float *)storage); }
float *getMat44Arr() const {warn("getMat44Arr", DB_VEC16F); return ( (float *)storage); }
double getDouble() const {warn("getDouble", DB_DOUBLE); return (*(double *)storage); }
friend inline std::ostream& operator << (std::ostream& output, const geoField& gf)
{
if (gf.tokenId!=GEO_DB_LAST_FIELD) {
output << " Field:token " << (int)gf.tokenId << " type " << (int)gf.TypeId
<< " num its " << gf.numItems << " size " << gf.storeSize << std::endl;
for (uint i=0; i<gf.numItems; i++) {
int j,k;
union {
unsigned char *uch;
char *ch;
float *ft;
int *in;
uint *uin;
short *sh;
osg::ushort *ush;
long *ln;
unsigned long *uln;
double *dbl;
} st;
st.uch=gf.storage+i*gf.storeSize;
switch (gf.TypeId) {
case DB_CHAR:
if (st.ch[0]) output << st.ch[0];
break;
case DB_SHORT:
output << st.sh[0] << std::endl;
break;
case DB_INT:
output << st.in[0] << std::endl;
break;
case DB_FLOAT:
output << st.ft[0] << std::endl;
break;
case DB_LONG:
output << st.ln[0] << std::endl;
break;
case DB_ULONG:
output << st.uln[0] << std::endl;
break;
case DB_DOUBLE:
output << st.dbl[0] << std::endl;
break;
case DB_VEC2F:
for (j=0; j<2; j++) output << st.ft[j] << " ";
output << std::endl;
break;
case DB_VEC3F:
for (j=0; j<3; j++) output << st.ft[j] << " ";
output << std::endl;
break;
case DB_VEC4F:
for (j=0; j<4; j++) output << st.ft[j] << " ";
output << std::endl;
break;
case DB_VEC16F:
for (j=0; j<4; j++) {
for (k=0; k<4; k++) output << st.ch[j*4+k] << " ";
output << std::endl;
}
break;
case DB_VEC2I:
for (j=0; j<2; j++) output << st.in[j] << " ";
output << std::endl;
break;
case DB_VEC3I:
for ( j=0; j<3; j++) output << st.in[j] << " ";
output << std::endl;
break;
case DB_VEC4I:
for ( j=0; j<4; j++) output << st.in[j] << " ";
output << std::endl;
break;
case DB_VEC2D:
for ( j=0; j<2; j++) output << st.dbl[j] << " ";
output << std::endl;
break;
case DB_VEC3D:
for ( j=0; j<3; j++) output << st.dbl[j] << " ";
output << std::endl;
break;
case DB_VEC4D:
for ( j=0; j<4; j++) output << st.dbl[j] << " ";
output << std::endl;
break;
case DB_VEC16D:
for (j=0; j<4; j++) {
for (k=0; k<4; k++) output << st.dbl[j*4+k] << " ";
output << std::endl;
}
break;
case DB_VRTX_STRUCT:
output << st.ch[0] << std::endl;
break;
case DB_UINT:
output << st.uin[0] << std::endl;
break;
case DB_USHORT:
output << st.ush[0] << std::endl;
break;
case DB_UCHAR:
output << (int)st.ch[0] << std::endl;
break;
case DB_EXT_STRUCT:
output << st.ch[0] << std::endl;
break;
case DB_SHORT_WITH_PADDING:
output << st.ch[0] << std::endl;
break;
case DB_CHAR_WITH_PADDING:
output << st.ch[0] << std::endl;
break;
case DB_USHORT_WITH_PADDING:
output << st.ch[0] << std::endl;
break;
case DB_UCHAR_WITH_PADDING:
output << (int)st.ch[0] << std::endl;
break;
case DB_BOOL_WITH_PADDING:
output << st.ch[0] << std::endl;
break;
case DB_EXTENDED_FIELD_STRUCT:
output << st.ch[0] << std::endl;
break;
case DB_VEC4UC:
for ( j=0; j<4; j++) output << (int)st.uch[j] << " ";
output << std::endl;
break;
case DB_DISCRETE_MAPPING_STRUCT:
output << st.ch[i] << std::endl;
break;
case DB_BITFLAGS:
output << st.ch[i] << std::endl;
break;
}
}
}
return output; // to enable cascading, monkey copy from osg\plane or \quat, Ubyte4, vec2,3,4,...
}
private:
osg::ushort tokenId, TypeId; // these are longer than standard field; are extended field length
uint numItems;
unsigned char *storage; // data relating
uint storeSize; // size*numItems in storage
};
class georecord { // holds a single record with a vector of geoFields as read from disk
public:
typedef std::vector< geoField > geoFieldList;
georecord() {id=0; parent=NULL; instance=NULL;}
~georecord() {;}
inline int getType(void) const {return id;}
inline void setparent(georecord *p) { parent=p;}
inline class georecord *getparent() { return parent;}
inline std::vector<georecord *> getchildren(void) { return children;}
void addchild(class georecord *gr) { children.push_back(gr);}
void readfile(std::ifstream &fin) {
if (!fin.eof()) {
fin.read((char *)&id,sizeof(int));
if (id==DB_DSK_PUSH) {
// there are no fields for a push
} else if (id==DB_DSK_POP) {
// there are no fields for a pop
} else { // get the fields
geoField gf;
do {
gf.readfile(fin);
if (id == DB_DSK_NORMAL_POOL && gf.getToken()==GEO_DB_NORMAL_POOL_VALUES) {
// uncompress the normals
gf.uncompress();
}
fields.push_back(gf);
} while (gf.getToken()!=GEO_DB_LAST_FIELD);
}
}
}
friend inline std::ostream& operator << (std::ostream& output, const georecord& gr)
{
if (gr.id == DB_DSK_PUSH) output << "Push" << std::endl;
else if (gr.id == DB_DSK_POP) output << "Pop" << std::endl;
else if (gr.id == DB_DSK_HEADER) output << "Header" << std::endl;
else if (gr.id == DB_DSK_GROUP) output << "Group" << std::endl;
else if (gr.id == DB_DSK_BILLBOARD) output << "Billboard" << std::endl;
else if (gr.id == DB_DSK_SEQUENCE) output << "Sequence" << std::endl;
else if (gr.id == DB_DSK_LOD) output << "LOD" << std::endl;
else if (gr.id == DB_DSK_GEODE) output << "Geode" << std::endl;
else if (gr.id == DB_DSK_POLYGON) output << "Polygon" << std::endl;
else if (gr.id == DB_DSK_MESH) output << "Mesh" << std::endl;
else if (gr.id == DB_DSK_CUBE) output << "Cube" << std::endl;
else if (gr.id == DB_DSK_SPHERE) output << "Sphere" << std::endl;
else if (gr.id == DB_DSK_CONE) output << "Cone" << std::endl;
else if (gr.id == DB_DSK_CYLINDER) output << "Cylinder" << std::endl;
else if (gr.id == DB_DSK_VERTEX) output << "Vertex" << std::endl;
else if (gr.id == DB_DSK_TEXTURE) output << "Texture" << std::endl;
else if (gr.id == DB_DSK_MATERIAL) output << "Material" << std::endl;
else if (gr.id == DB_DSK_VIEW) output << "View" << std::endl;
else if (gr.id == DB_DSK_EXTENSION_LIST) output << "Extensions" << std::endl;
else if (gr.id == DB_DSK_COORD_POOL) output << "Coords" << std::endl;
else if (gr.id == DB_DSK_NORMAL_POOL) output << "Normals" << std::endl;
else if (gr.id == DB_DSK_SWITCH) output << "Switch" << std::endl;
else if (gr.id == DB_DSK_TEXT) output << "Text" << std::endl;
else if (gr.id == DB_DSK_BASE_GROUP) output << "Base group" << std::endl;
else if (gr.id == DB_DSK_BASE_SURFACE) output << "Base Surface" << std::endl;
else if (gr.id == DB_DSK_INSTANCE) output << "Instance" << std::endl;
else if (gr.id == DB_DSK_LIGHTPT) output << "Light Point" << std::endl;
else if (gr.id == DB_DSK_EXTERNAL) output << "External" << std::endl;
else if (gr.id == DB_DSK_PAGE) output << "Page" << std::endl;
else if (gr.id == DB_DSK_COLOR_PALETTE) output << "Colour palette" << std::endl;
else output << " inp record " << gr.id << std::endl;
for (geoFieldList::const_iterator itr=gr.fields.begin();
itr!=gr.fields.end();
++itr)
{
output << *itr << std::endl;
}
return output; // to enable cascading, monkey copy from osg\plane or \quat, Ubyte4, vec2,3,4,...
}
/* const char *getCharField(const int fieldid) const {
const geoField *gfd=getField(fieldid);
if (gfd) return (char *)gfd->getstore(0);
return NULL;
} */
const geoField *getField(const int fieldid) const { // return field if it exists.
for (geoFieldList::const_iterator itr=fields.begin();
itr!=fields.end();
++itr)
{
if (itr->getToken()==fieldid) return itr;
}
return NULL;
}
void setMaterial(osg::Material *mt) const {
if (id == DB_DSK_MATERIAL) {
for (geoFieldList::const_iterator itr=fields.begin();
itr!=fields.end();
++itr)
{
float *fval;
if (itr->getToken()==GEO_DB_MAT_AMBIENT) {
fval= (float *)(*itr).getstore(0);
mt->setAmbient(osg::Material::FRONT_AND_BACK, osg::Vec4(fval[0],fval[1],fval[2],fval[3]));
}
if (itr->getToken()==GEO_DB_MAT_DIFFUSE) {
fval= (float *)(*itr).getstore(0);
mt->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4(fval[0],fval[1],fval[2],fval[3]));
}
if (itr->getToken()==GEO_DB_MAT_SPECULAR) {
fval= (float *)(*itr).getstore(0);
mt->setSpecular(osg::Material::FRONT_AND_BACK, osg::Vec4(fval[0],fval[1],fval[2],fval[3]));
}
if (itr->getToken()==GEO_DB_MAT_EMISSIVE) {
fval= (float *)(*itr).getstore(0);
mt->setEmission(osg::Material::FRONT_AND_BACK, osg::Vec4(fval[0],fval[1],fval[2],fval[3]));
}
if (itr->getToken()==GEO_DB_MAT_SHININESS) {
fval= (float *)(*itr).getstore(0);
mt->setShininess(osg::Material::FRONT_AND_BACK, fval[0]);
}
}
}
}
private:
int id;
std::vector<geoField> fields; // each geo record has a variable number of fields
class georecord *parent; // parent of pushed/popped records
class georecord *instance; // this record is an instance of the pointed to record
std::vector< georecord *> children; // children of this record
};
typedef std::vector< georecord > geoRecordList;
#endif //_GEO_STRUCTS_H_