From Marco Jez, updates to the LWO loader.
This commit is contained in:
@@ -53,7 +53,7 @@ BSC32=bscmake.exe
|
||||
# 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_lwo.dll" /libpath:"../../../lib"
|
||||
# ADD LINK32 glu32.lib /nologo /dll /pdb:none /machine:I386 /nodefaultlib:"LIBC" /out:"../../../bin/osgdb_lwo.dll" /libpath:"../../../lib"
|
||||
# SUBTRACT LINK32 /nodefaultlib
|
||||
|
||||
!ELSEIF "$(CFG)" == "osgPlugin lwo - Win32 Debug"
|
||||
@@ -80,7 +80,7 @@ BSC32=bscmake.exe
|
||||
# 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_lwod.dll" /pdbtype:sept /libpath:"../../../lib"
|
||||
# ADD LINK32 glu32.lib /nologo /dll /debug /machine:I386 /nodefaultlib:"LIBC" /out:"../../../bin/osgdb_lwod.dll" /pdbtype:sept /libpath:"../../../lib"
|
||||
# SUBTRACT LINK32 /pdb:none
|
||||
|
||||
!ENDIF
|
||||
@@ -94,36 +94,136 @@ LINK32=link.exe
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\osgPlugins\lwo\lw.cpp
|
||||
SOURCE=..\..\..\src\osgPlugins\lwo\Block.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\osgPlugins\lwo\Clip.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\osgPlugins\lwo\Converter.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\osgPlugins\lwo\Object.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\osgPlugins\lwo\Polygon.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\osgPlugins\lwo\Surface.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\osgPlugins\lwo\Tessellator.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\osgPlugins\lwo\Unit.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\osgPlugins\lwo\VertexMap.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\osgPlugins\lwo\ReaderWriterLWO.cpp
|
||||
# End Source File
|
||||
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\osgPlugins\lwo\Lwo2.cpp
|
||||
SOURCE=..\..\..\src\osgPlugins\lwo\old_lw.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\osgPlugins\lwo\Lwo2Layer.cpp
|
||||
SOURCE=..\..\..\src\osgPlugins\lwo\old_Lwo2.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\osgPlugins\lwo\old_Lwo2Layer.cpp
|
||||
# End Source File
|
||||
|
||||
# End Group
|
||||
# Begin Group "Header Files"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Src\osgPlugins\lwo\lw.h
|
||||
SOURCE=..\..\..\Src\osgPlugins\lwo\Block.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Src\osgPlugins\lwo\Lwo2Layer.h
|
||||
SOURCE=..\..\..\Src\osgPlugins\lwo\Clip.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Src\osgPlugins\lwo\Lwo2.h
|
||||
SOURCE=..\..\..\Src\osgPlugins\lwo\Converter.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Src\osgPlugins\lwo\iffparser.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Src\osgPlugins\lwo\Layer.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Src\osgPlugins\lwo\lwo2chunks.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Src\osgPlugins\lwo\lwo2parser.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Src\osgPlugins\lwo\lwo2read.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Src\osgPlugins\lwo\lwo2types.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Src\osgPlugins\lwo\Object.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Src\osgPlugins\lwo\Polygon.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Src\osgPlugins\lwo\Surface.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Src\osgPlugins\lwo\Tessellator.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Src\osgPlugins\lwo\Unit.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Src\osgPlugins\lwo\VertexMap.h
|
||||
# End Source File
|
||||
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Src\osgPlugins\lwo\old_lw.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Src\osgPlugins\lwo\old_Lwo2Layer.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Src\osgPlugins\lwo\old_Lwo2.h
|
||||
# End Source File
|
||||
|
||||
# End Group
|
||||
# End Target
|
||||
# Begin Group "Header Files No. 1"
|
||||
|
||||
147
src/osgPlugins/lwo/Block.cpp
Normal file
147
src/osgPlugins/lwo/Block.cpp
Normal file
@@ -0,0 +1,147 @@
|
||||
/*******************************************************
|
||||
Lightwave Object Loader for OSG
|
||||
|
||||
Copyright (C) 2004 Marco Jez <marco.jez@poste.it>
|
||||
OpenSceneGraph is (C) 2004 Robert Osfield
|
||||
********************************************************/
|
||||
|
||||
#include "Block.h"
|
||||
|
||||
#include <osg/Notify>
|
||||
#include <osg/Matrix>
|
||||
|
||||
using namespace lwosg;
|
||||
|
||||
Block::Block(const lwo2::FORM::SURF::BLOK *blok)
|
||||
: enabled_(true),
|
||||
opacity_type_(ADDITIVE),
|
||||
opacity_amount_(1)
|
||||
{
|
||||
if (blok) {
|
||||
compile(blok);
|
||||
}
|
||||
}
|
||||
|
||||
void Block::read_common_attributes(const iff::Chunk_list &subchunks)
|
||||
{
|
||||
for (iff::Chunk_list::const_iterator i=subchunks.begin(); i!=subchunks.end(); ++i) {
|
||||
const lwo2::FORM::SURF::BLOK::CHAN *chan = dynamic_cast<const lwo2::FORM::SURF::BLOK::CHAN *>(*i);
|
||||
if (chan) {
|
||||
channel_ = std::string(chan->texture_channel.id, 4);
|
||||
}
|
||||
const lwo2::FORM::SURF::BLOK::ENAB *enab = dynamic_cast<const lwo2::FORM::SURF::BLOK::ENAB *>(*i);
|
||||
if (enab) {
|
||||
enabled_ = enab->enable != 0;
|
||||
}
|
||||
const lwo2::FORM::SURF::BLOK::OPAC *opac = dynamic_cast<const lwo2::FORM::SURF::BLOK::OPAC *>(*i);
|
||||
if (opac) {
|
||||
opacity_type_ = static_cast<Opacity_type>(opac->type);
|
||||
opacity_amount_ = opac->opacity.fraction;
|
||||
}
|
||||
const lwo2::FORM::SURF::BLOK::AXIS *axis = dynamic_cast<const lwo2::FORM::SURF::BLOK::AXIS *>(*i);
|
||||
if (axis) {
|
||||
displacement_axis_ = static_cast<Axis_type>(axis->displacement_axis);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Block::compile(const lwo2::FORM::SURF::BLOK *blok)
|
||||
{
|
||||
const lwo2::FORM::SURF::BLOK::IMAP *imap = dynamic_cast<const lwo2::FORM::SURF::BLOK::IMAP *>(blok->header);
|
||||
if (imap) {
|
||||
type_ = "IMAP";
|
||||
ordinal_ = imap->ordinal;
|
||||
|
||||
// read common parameters
|
||||
read_common_attributes(imap->block_attributes);
|
||||
|
||||
// read imagemap-related attributes
|
||||
for (iff::Chunk_list::const_iterator i=blok->attributes.begin(); i!=blok->attributes.end(); ++i) {
|
||||
const lwo2::FORM::SURF::BLOK::IMAP::TMAP *tmap = dynamic_cast<const lwo2::FORM::SURF::BLOK::IMAP::TMAP *>(*i);
|
||||
if (tmap) {
|
||||
Texture_mapping mapping;
|
||||
for (iff::Chunk_list::const_iterator i=tmap->attributes.begin(); i!=tmap->attributes.end(); ++i) {
|
||||
const lwo2::FORM::SURF::BLOK::IMAP::TMAP::CNTR *cntr = dynamic_cast<const lwo2::FORM::SURF::BLOK::IMAP::TMAP::CNTR *>(*i);
|
||||
if (cntr) {
|
||||
mapping.center_ = osg::Vec3(cntr->vector.X, cntr->vector.Y, cntr->vector.Z);
|
||||
}
|
||||
const lwo2::FORM::SURF::BLOK::IMAP::TMAP::SIZE *size = dynamic_cast<const lwo2::FORM::SURF::BLOK::IMAP::TMAP::SIZE *>(*i);
|
||||
if (size) {
|
||||
mapping.size_ = osg::Vec3(size->vector.X, size->vector.Y, size->vector.Z);
|
||||
}
|
||||
const lwo2::FORM::SURF::BLOK::IMAP::TMAP::ROTA *rota = dynamic_cast<const lwo2::FORM::SURF::BLOK::IMAP::TMAP::ROTA *>(*i);
|
||||
if (rota) {
|
||||
mapping.rotation_ = osg::Vec3(rota->vector.X, rota->vector.Y, rota->vector.Z);
|
||||
}
|
||||
const lwo2::FORM::SURF::BLOK::IMAP::TMAP::CSYS *csys = dynamic_cast<const lwo2::FORM::SURF::BLOK::IMAP::TMAP::CSYS *>(*i);
|
||||
if (csys) {
|
||||
mapping.csys_ = static_cast<Texture_mapping::Coordinate_system_type>(csys->type);
|
||||
}
|
||||
}
|
||||
imap_.mapping = mapping;
|
||||
}
|
||||
|
||||
const lwo2::FORM::SURF::BLOK::IMAP::PROJ *proj = dynamic_cast<const lwo2::FORM::SURF::BLOK::IMAP::PROJ *>(*i);
|
||||
if (proj) {
|
||||
imap_.projection = static_cast<Image_map::Projection_mode>(proj->projection_mode);
|
||||
}
|
||||
|
||||
const lwo2::FORM::SURF::BLOK::IMAP::AXIS *axis = dynamic_cast<const lwo2::FORM::SURF::BLOK::IMAP::AXIS *>(*i);
|
||||
if (axis) {
|
||||
imap_.axis = static_cast<Image_map::Axis_type>(axis->texture_axis);
|
||||
}
|
||||
|
||||
const lwo2::FORM::SURF::BLOK::IMAP::IMAG *imag = dynamic_cast<const lwo2::FORM::SURF::BLOK::IMAP::IMAG *>(*i);
|
||||
if (imag) {
|
||||
imap_.image_map = imag->texture_image.index;
|
||||
}
|
||||
|
||||
const lwo2::FORM::SURF::BLOK::IMAP::WRAP *wrap = dynamic_cast<const lwo2::FORM::SURF::BLOK::IMAP::WRAP *>(*i);
|
||||
if (wrap) {
|
||||
imap_.width_wrap = static_cast<Image_map::Wrap_type>(wrap->width_wrap);
|
||||
imap_.height_wrap = static_cast<Image_map::Wrap_type>(wrap->height_wrap);
|
||||
}
|
||||
|
||||
const lwo2::FORM::SURF::BLOK::IMAP::WRPW *wrpw = dynamic_cast<const lwo2::FORM::SURF::BLOK::IMAP::WRPW *>(*i);
|
||||
if (wrpw) {
|
||||
imap_.wrap_amount_w = wrpw->cycles.fraction;
|
||||
}
|
||||
|
||||
const lwo2::FORM::SURF::BLOK::IMAP::WRPH *wrph = dynamic_cast<const lwo2::FORM::SURF::BLOK::IMAP::WRPH *>(*i);
|
||||
if (wrph) {
|
||||
imap_.wrap_amount_h = wrph->cycles.fraction;
|
||||
}
|
||||
|
||||
const lwo2::FORM::SURF::BLOK::IMAP::VMAP *vmap = dynamic_cast<const lwo2::FORM::SURF::BLOK::IMAP::VMAP *>(*i);
|
||||
if (vmap) {
|
||||
imap_.uv_map = vmap->txuv_map_name;
|
||||
}
|
||||
|
||||
const lwo2::FORM::SURF::BLOK::IMAP::TAMP *tamp = dynamic_cast<const lwo2::FORM::SURF::BLOK::IMAP::TAMP *>(*i);
|
||||
if (tamp) {
|
||||
imap_.texture_amplitude = tamp->amplitude.fraction;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
osg::notify(osg::WARN) << "Warning: lwosg::Block: only IMAP (image map) block types are supported, this block will be ignored" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
osg::Vec3 Block::setup_texture_point(const osg::Vec3 &P) const
|
||||
{
|
||||
osg::Vec3 Q = P;
|
||||
|
||||
const osg::Vec3 &ypr = imap_.mapping.rotation_;
|
||||
Q -= imap_.mapping.center_;
|
||||
Q = Q * osg::Matrix::rotate(ypr.z(), osg::Vec3(0, 0, -1));
|
||||
Q = Q * osg::Matrix::rotate(ypr.x(), osg::Vec3(0, 1, 0));
|
||||
Q = Q * osg::Matrix::rotate(ypr.y(), osg::Vec3(-1, 0, 0));
|
||||
if (imap_.projection != Image_map::SPHERICAL) {
|
||||
Q.x() *= 1/imap_.mapping.size_.x();
|
||||
Q.y() *= 1/imap_.mapping.size_.y();
|
||||
Q.z() *= 1/imap_.mapping.size_.z();
|
||||
}
|
||||
|
||||
return Q;
|
||||
}
|
||||
144
src/osgPlugins/lwo/Block.h
Normal file
144
src/osgPlugins/lwo/Block.h
Normal file
@@ -0,0 +1,144 @@
|
||||
/*******************************************************
|
||||
Lightwave Object Loader for OSG
|
||||
|
||||
Copyright (C) 2004 Marco Jez <marco.jez@poste.it>
|
||||
OpenSceneGraph is (C) 2004 Robert Osfield
|
||||
********************************************************/
|
||||
|
||||
#ifndef LWOSG_BLOCK_
|
||||
#define LWOSG_BLOCK_
|
||||
|
||||
#include "lwo2chunks.h"
|
||||
|
||||
#include <osg/Vec3>
|
||||
|
||||
#ifdef DIFFERENCE
|
||||
#undef DIFFERENCE
|
||||
#endif
|
||||
|
||||
namespace lwosg
|
||||
{
|
||||
|
||||
class Clip;
|
||||
|
||||
struct Texture_mapping {
|
||||
|
||||
enum Coordinate_system_type {
|
||||
OBJECT = 0,
|
||||
WORLD = 1
|
||||
};
|
||||
|
||||
osg::Vec3 center_;
|
||||
osg::Vec3 size_;
|
||||
osg::Vec3 rotation_;
|
||||
// missing: OREF, FALL
|
||||
Coordinate_system_type csys_;
|
||||
|
||||
Texture_mapping()
|
||||
: size_(1, 1, 1),
|
||||
csys_(OBJECT)
|
||||
{}
|
||||
};
|
||||
|
||||
struct Image_map {
|
||||
|
||||
enum Axis_type {
|
||||
X = 0,
|
||||
Y = 1,
|
||||
Z = 2
|
||||
};
|
||||
|
||||
enum Projection_mode {
|
||||
PLANAR = 0,
|
||||
CYLINDRICAL = 1,
|
||||
SPHERICAL = 2,
|
||||
CUBIC = 3,
|
||||
FRONT_PROJECTION = 4,
|
||||
UV = 5
|
||||
};
|
||||
|
||||
enum Wrap_type {
|
||||
RESET = 0,
|
||||
REPEAT = 1,
|
||||
MIRROR = 2,
|
||||
EDGE = 3
|
||||
};
|
||||
|
||||
Texture_mapping mapping;
|
||||
Projection_mode projection;
|
||||
Axis_type axis;
|
||||
int image_map;
|
||||
const Clip *clip; // is filled by Surface::compile()
|
||||
Wrap_type width_wrap;
|
||||
Wrap_type height_wrap;
|
||||
float wrap_amount_w;
|
||||
float wrap_amount_h;
|
||||
std::string uv_map;
|
||||
// missing: AAST, PIXB, STCK
|
||||
float texture_amplitude;
|
||||
|
||||
Image_map()
|
||||
: image_map(-1),
|
||||
clip(0),
|
||||
width_wrap(REPEAT),
|
||||
height_wrap(REPEAT),
|
||||
wrap_amount_w(1),
|
||||
wrap_amount_h(1),
|
||||
texture_amplitude(1)
|
||||
{}
|
||||
};
|
||||
|
||||
class Block {
|
||||
public:
|
||||
|
||||
enum Axis_type {
|
||||
X = 0,
|
||||
Y = 1,
|
||||
Z = 2
|
||||
};
|
||||
|
||||
enum Opacity_type {
|
||||
NORMAL = 0,
|
||||
SUBTRACTIVE = 1,
|
||||
DIFFERENCE = 2,
|
||||
MULTIPLY = 3,
|
||||
DIVIDE = 4,
|
||||
ALPHA = 5,
|
||||
TEXTURE_DISPLACEMENT = 6,
|
||||
ADDITIVE = 7
|
||||
};
|
||||
|
||||
Block(const lwo2::FORM::SURF::BLOK *blok = 0);
|
||||
|
||||
void compile(const lwo2::FORM::SURF::BLOK *blok = 0);
|
||||
|
||||
inline const std::string &get_type() const { return type_; }
|
||||
inline const std::string &get_ordinal() const { return ordinal_; }
|
||||
inline const std::string &get_channel() const { return channel_; }
|
||||
inline bool enabled() const { return enabled_; }
|
||||
inline Opacity_type get_opacity_type() const { return opacity_type_; }
|
||||
inline float get_opacity_amount() const { return opacity_amount_; }
|
||||
inline Axis_type get_displacement_axis() const { return displacement_axis_; }
|
||||
inline const Image_map &get_image_map() const { return imap_; }
|
||||
inline Image_map &get_image_map() { return imap_; }
|
||||
|
||||
osg::Vec3 setup_texture_point(const osg::Vec3 &P) const;
|
||||
|
||||
protected:
|
||||
void read_common_attributes(const iff::Chunk_list &subchunks);
|
||||
|
||||
private:
|
||||
std::string type_;
|
||||
std::string ordinal_;
|
||||
std::string channel_;
|
||||
bool enabled_;
|
||||
Opacity_type opacity_type_;
|
||||
float opacity_amount_;
|
||||
Axis_type displacement_axis_;
|
||||
|
||||
Image_map imap_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
25
src/osgPlugins/lwo/Clip.cpp
Normal file
25
src/osgPlugins/lwo/Clip.cpp
Normal file
@@ -0,0 +1,25 @@
|
||||
/*******************************************************
|
||||
Lightwave Object Loader for OSG
|
||||
|
||||
Copyright (C) 2004 Marco Jez <marco.jez@poste.it>
|
||||
OpenSceneGraph is (C) 2004 Robert Osfield
|
||||
********************************************************/
|
||||
|
||||
#include "Clip.h"
|
||||
|
||||
using namespace lwosg;
|
||||
|
||||
Clip::Clip(const lwo2::FORM::CLIP *clip)
|
||||
{
|
||||
if (clip) {
|
||||
compile(clip);
|
||||
}
|
||||
}
|
||||
|
||||
void Clip::compile(const lwo2::FORM::CLIP *clip)
|
||||
{
|
||||
for (iff::Chunk_list::const_iterator j=clip->attributes.begin(); j!=clip->attributes.end(); ++j) {
|
||||
const lwo2::FORM::CLIP::STIL *stil = dynamic_cast<const lwo2::FORM::CLIP::STIL *>(*j);
|
||||
if (stil) still_filename_ = stil->name.name;
|
||||
}
|
||||
}
|
||||
35
src/osgPlugins/lwo/Clip.h
Normal file
35
src/osgPlugins/lwo/Clip.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/*******************************************************
|
||||
Lightwave Object Loader for OSG
|
||||
|
||||
Copyright (C) 2004 Marco Jez <marco.jez@poste.it>
|
||||
OpenSceneGraph is (C) 2004 Robert Osfield
|
||||
********************************************************/
|
||||
|
||||
#ifndef LWOSG_CLIP_
|
||||
#define LWOSG_CLIP_
|
||||
|
||||
#include "lwo2chunks.h"
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
namespace lwosg
|
||||
{
|
||||
|
||||
class Clip {
|
||||
public:
|
||||
Clip(const lwo2::FORM::CLIP *clip = 0);
|
||||
|
||||
void compile(const lwo2::FORM::CLIP *clip);
|
||||
|
||||
inline const std::string &get_still_filename() const { return still_filename_; }
|
||||
|
||||
private:
|
||||
std::string still_filename_;
|
||||
};
|
||||
|
||||
typedef std::map<int, Clip> Clip_map;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
283
src/osgPlugins/lwo/Converter.cpp
Normal file
283
src/osgPlugins/lwo/Converter.cpp
Normal file
@@ -0,0 +1,283 @@
|
||||
/*******************************************************
|
||||
Lightwave Object Loader for OSG
|
||||
|
||||
Copyright (C) 2004 Marco Jez <marco.jez@poste.it>
|
||||
OpenSceneGraph is (C) 2004 Robert Osfield
|
||||
********************************************************/
|
||||
|
||||
#include "Converter.h"
|
||||
#include "Tessellator.h"
|
||||
|
||||
#include <osg/Notify>
|
||||
#include <osg/Geode>
|
||||
#include <osg/Geometry>
|
||||
#include <osg/CullFace>
|
||||
#include <osg/LightModel>
|
||||
|
||||
#include <osgDB/FileUtils>
|
||||
|
||||
#include "lwo2parser.h"
|
||||
|
||||
#include <fstream>
|
||||
|
||||
using namespace lwosg;
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
struct GeometryBin {
|
||||
osg::ref_ptr<osg::DrawElementsUInt> deui_points;
|
||||
osg::ref_ptr<osg::DrawElementsUInt> deui_lines;
|
||||
osg::ref_ptr<osg::DrawElementsUInt> deui_triangles;
|
||||
|
||||
GeometryBin()
|
||||
: deui_points(new osg::DrawElementsUInt(GL_POINTS)),
|
||||
deui_lines(new osg::DrawElementsUInt(GL_LINES)),
|
||||
deui_triangles(new osg::DrawElementsUInt(GL_TRIANGLES))
|
||||
{}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Converter::Converter()
|
||||
: root_(new osg::Group)
|
||||
{
|
||||
}
|
||||
|
||||
Converter::Converter(const Options &options)
|
||||
: root_(new osg::Group),
|
||||
options_(options)
|
||||
{
|
||||
}
|
||||
|
||||
osg::Group *Converter::convert(Object &obj)
|
||||
{
|
||||
if (root_->getNumChildren() > 0) {
|
||||
root_->removeChild(0, root_->getNumChildren());
|
||||
}
|
||||
|
||||
osg::notify(osg::INFO) << "INFO: lwosg::Converter: flattening per-polygon vertex maps\n";
|
||||
for (Object::Layer_map::iterator i=obj.layers().begin(); i!=obj.layers().end(); ++i) {
|
||||
for (Layer::Unit_list::iterator j=i->second.units().begin(); j!=i->second.units().end(); ++j) {
|
||||
j->flatten_maps();
|
||||
}
|
||||
}
|
||||
|
||||
osg::notify(osg::INFO) << "INFO: lwosg::Converter: creating scene graph\n";
|
||||
build_scene_graph(obj);
|
||||
|
||||
return root_.get();
|
||||
}
|
||||
|
||||
void Converter::build_scene_graph(Object &obj)
|
||||
{
|
||||
// generate layer structure
|
||||
typedef std::map<int, osg::ref_ptr<osg::Group> > Layer_group_map;
|
||||
Layer_group_map lymap;
|
||||
|
||||
osg::notify(osg::DEBUG_INFO) << "DEBUG INFO: lwosg::Converter: creating layer structure\n";
|
||||
|
||||
// create a flat layer structure, no parenting since it's handled in scene files
|
||||
for (Object::Layer_map::const_iterator i=obj.layers().begin(); i!=obj.layers().end(); ++i) {
|
||||
const Layer &layer = i->second;
|
||||
osg::ref_ptr<osg::Group> new_group = new osg::Group;
|
||||
lymap[layer.number()] = new_group.get();
|
||||
if (layer.get_layer_chunk()) {
|
||||
new_group->setName(layer.get_layer_chunk()->name);
|
||||
if (layer.get_layer_chunk()->flags & 1) {
|
||||
new_group->setNodeMask(0);
|
||||
}
|
||||
} else {
|
||||
new_group->setName("Default_layer");
|
||||
}
|
||||
root_->addChild(new_group.get());
|
||||
}
|
||||
|
||||
for (Object::Layer_map::iterator li=obj.layers().begin(); li!=obj.layers().end(); ++li) {
|
||||
Layer &layer = li->second;
|
||||
|
||||
osg::Group *layer_group = lymap[layer.number()].get();
|
||||
|
||||
osg::notify(osg::DEBUG_INFO) << "DEBUG INFO: lwosg::Converter: processing layer '" << layer_group->getName() << "'\n";
|
||||
|
||||
for (Layer::Unit_list::iterator j=layer.units().begin(); j!=layer.units().end(); ++j) {
|
||||
|
||||
osg::notify(osg::DEBUG_INFO) << "DEBUG INFO: lwosg::Converter: \tcreating primitives\n";
|
||||
|
||||
int tess_success = 0;
|
||||
int tess_fail = 0;
|
||||
|
||||
typedef std::map<const Surface *, GeometryBin> GeometryBin_map;
|
||||
GeometryBin_map bins;
|
||||
|
||||
typedef std::map<const Surface *, Unit::Index_list> Remapping_map;
|
||||
Remapping_map remappings;
|
||||
|
||||
// compute remapping map for default surface
|
||||
j->compute_vertex_remapping(0, remappings[0]);
|
||||
|
||||
// compute remapping maps for other surfaces
|
||||
for (Object::Surface_map::const_iterator h=obj.surfaces().begin(); h!=obj.surfaces().end(); ++h) {
|
||||
j->compute_vertex_remapping(&h->second, remappings[&h->second]);
|
||||
}
|
||||
|
||||
// create primitive sets, taking into account remapping maps
|
||||
for (unsigned k=0; k<j->polygons().size(); ++k) {
|
||||
const Polygon &poly = j->polygons()[k];
|
||||
GeometryBin &bin = bins[poly.get_surface()];
|
||||
const Unit::Index_list &remapping = remappings[poly.get_surface()];
|
||||
|
||||
if (poly.indices().size() == 1) {
|
||||
bin.deui_points->push_back(remapping[poly.indices()[0]]);
|
||||
}
|
||||
if (poly.indices().size() == 2) {
|
||||
bin.deui_lines->push_back(remapping[poly.indices()[0]]);
|
||||
bin.deui_lines->push_back(remapping[poly.indices()[1]]);
|
||||
}
|
||||
if (poly.indices().size() == 3) {
|
||||
bin.deui_triangles->push_back(remapping[poly.indices()[0]]);
|
||||
bin.deui_triangles->push_back(remapping[poly.indices()[1]]);
|
||||
bin.deui_triangles->push_back(remapping[poly.indices()[2]]);
|
||||
}
|
||||
if (poly.indices().size() >= 4) {
|
||||
Tessellator tess;
|
||||
if (tess.tessellate(poly, j->points(), bin.deui_triangles.get(), &remapping)) {
|
||||
++tess_success;
|
||||
} else {
|
||||
++tess_fail;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (tess_success > 0) {
|
||||
osg::notify(osg::DEBUG_INFO) << "DEBUG INFO: lwosg::Converter: " << tess_success << " polygons have been tessellated correctly\n";
|
||||
}
|
||||
|
||||
if (tess_fail > 0) {
|
||||
osg::notify(osg::WARN) << "Warning: lwosg::Converter: could not tessellate " << tess_fail << " polygons correctly. This is probably due to self-intersecting polygons being used, try to Triple them in Lightwave and restart the conversion" << std::endl;
|
||||
}
|
||||
|
||||
// create normal array
|
||||
osg::ref_ptr<osg::Vec3Array> normals = j->normals()->asVec3Array(j->points()->size());
|
||||
|
||||
for (GeometryBin_map::iterator i=bins.begin(); i!=bins.end(); ++i) {
|
||||
const Surface *surface = i->first;
|
||||
GeometryBin &bin = i->second;
|
||||
|
||||
const Unit::Index_list &remapping = remappings[surface];
|
||||
|
||||
// clean up points and normals according to remapping map
|
||||
osg::notify(osg::DEBUG_INFO) << "DEBUG INFO: lwosg::Converter: \tcleaning up redundant vertices and vertex attributes for surface '" << (surface ? surface->get_name() : std::string("anonymous")) << "'\n";
|
||||
osg::ref_ptr<osg::Vec3Array> new_points = new osg::Vec3Array;
|
||||
osg::ref_ptr<osg::Vec3Array> new_normals = new osg::Vec3Array;
|
||||
for (unsigned pi=0; pi<j->points()->size(); ++pi) {
|
||||
if (remapping[pi] != -1) {
|
||||
new_points->push_back((*j->points())[pi]);
|
||||
new_normals->push_back((*normals)[pi]);
|
||||
}
|
||||
}
|
||||
|
||||
osg::notify(osg::DEBUG_INFO) << "DEBUG INFO: lwosg::Converter: \tcreating geometry for surface '" << (surface ? surface->get_name() : std::string("anonymous")) << "'\n";
|
||||
|
||||
osg::ref_ptr<osg::Geode> geode = new osg::Geode;
|
||||
|
||||
osg::ref_ptr<osg::Geometry> geo = new osg::Geometry;
|
||||
geode->addDrawable(geo.get());
|
||||
|
||||
geo->setVertexArray(new_points.get());
|
||||
geo->setNormalArray(new_normals.get());
|
||||
geo->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
|
||||
|
||||
if (surface) {
|
||||
geode->setName(surface->get_name());
|
||||
|
||||
// apply surface parameters and texture/color maps according to remapping map
|
||||
osg::ref_ptr<VertexMap_map> rm_texture_maps = j->texture_maps()->remap(remapping);
|
||||
osg::ref_ptr<VertexMap_map> rm_rgb_maps = j->rgb_maps()->remap(remapping);
|
||||
osg::ref_ptr<VertexMap_map> rm_rgba_maps = j->rgba_maps()->remap(remapping);
|
||||
osg::Group *sgrp = surface->apply(geo.get(),
|
||||
rm_texture_maps.get(),
|
||||
rm_rgb_maps.get(),
|
||||
rm_rgba_maps.get(),
|
||||
options_.max_tex_units,
|
||||
options_.use_osgfx,
|
||||
options_.force_arb_compression);
|
||||
if (sgrp) {
|
||||
sgrp->addChild(geode.get());
|
||||
layer_group->addChild(sgrp);
|
||||
} else {
|
||||
layer_group->addChild(geode.get());
|
||||
}
|
||||
} else {
|
||||
layer_group->addChild(geode.get());
|
||||
}
|
||||
|
||||
// add primitive sets to geometry
|
||||
if (!bin.deui_points->empty()) geo->addPrimitiveSet(bin.deui_points.get());
|
||||
if (!bin.deui_lines->empty()) geo->addPrimitiveSet(bin.deui_lines.get());
|
||||
if (!bin.deui_triangles->empty()) geo->addPrimitiveSet(bin.deui_triangles.get());
|
||||
}
|
||||
}
|
||||
|
||||
osg::ref_ptr<osg::CullFace> cf = new osg::CullFace;
|
||||
cf->setMode(osg::CullFace::BACK);
|
||||
root_->getOrCreateStateSet()->setAttributeAndModes(cf.get());
|
||||
|
||||
if (options_.apply_light_model) {
|
||||
osg::ref_ptr<osg::LightModel> lm = new osg::LightModel;
|
||||
lm->setTwoSided(true);
|
||||
lm->setColorControl(osg::LightModel::SEPARATE_SPECULAR_COLOR);
|
||||
lm->setAmbientIntensity(osg::Vec4(0, 0, 0, 0));
|
||||
lm->setLocalViewer(true);
|
||||
root_->getOrCreateStateSet()->setAttributeAndModes(lm.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
osg::Group *Converter::convert(const iff::Chunk_list &data)
|
||||
{
|
||||
Object obj(data);
|
||||
obj.set_coordinate_system_fixer(options_.csf.get());
|
||||
return convert(obj);
|
||||
}
|
||||
|
||||
osg::Group *Converter::convert(const std::string &filename)
|
||||
{
|
||||
std::string file = osgDB::findDataFile(filename);
|
||||
if (file.empty()) return 0;
|
||||
|
||||
std::ifstream ifs(file.c_str(), std::ios_base::in | std::ios_base::binary);
|
||||
if (!ifs.is_open()) return 0;
|
||||
|
||||
std::vector<char> buffer;
|
||||
char c;
|
||||
while (ifs.get(c)) buffer.push_back(c);
|
||||
|
||||
lwo2::Parser<std::vector<char>::const_iterator > parser(osg::notify(osg::DEBUG_INFO));
|
||||
|
||||
try
|
||||
{
|
||||
parser.parse(buffer.begin(), buffer.end());
|
||||
}
|
||||
catch(lwo2::parser_error &e)
|
||||
{
|
||||
std::cerr << e.what() << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (iff::Chunk_list::const_iterator i=parser.chunks().begin(); i!=parser.chunks().end(); ++i) {
|
||||
const lwo2::FORM *form = dynamic_cast<const lwo2::FORM *>(*i);
|
||||
if (form) {
|
||||
Object obj(form->data);
|
||||
obj.set_coordinate_system_fixer(options_.csf.get());
|
||||
if (!convert(obj)) {
|
||||
return 0;
|
||||
}
|
||||
root_->setName(file);
|
||||
return root_.get();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
59
src/osgPlugins/lwo/Converter.h
Normal file
59
src/osgPlugins/lwo/Converter.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/*******************************************************
|
||||
Lightwave Object Loader for OSG
|
||||
|
||||
Copyright (C) 2004 Marco Jez <marco.jez@poste.it>
|
||||
OpenSceneGraph is (C) 2004 Robert Osfield
|
||||
********************************************************/
|
||||
|
||||
#ifndef LWOSG_CONVERTER_
|
||||
#define LWOSG_CONVERTER_
|
||||
|
||||
#include "Object.h"
|
||||
#include "iffparser.h"
|
||||
|
||||
#include <osg/ref_ptr>
|
||||
#include <osg/Group>
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace lwosg
|
||||
{
|
||||
|
||||
class Converter {
|
||||
public:
|
||||
|
||||
struct Options {
|
||||
osg::ref_ptr<CoordinateSystemFixer> csf;
|
||||
int max_tex_units;
|
||||
bool apply_light_model;
|
||||
bool use_osgfx;
|
||||
bool force_arb_compression;
|
||||
|
||||
Options(): csf(new LwoCoordFixer), max_tex_units(0), apply_light_model(true), use_osgfx(false), force_arb_compression(false) {}
|
||||
};
|
||||
|
||||
Converter();
|
||||
Converter(const Options &options);
|
||||
|
||||
osg::Group *convert(Object &obj);
|
||||
osg::Group *convert(const iff::Chunk_list &data);
|
||||
osg::Group *convert(const std::string &filename);
|
||||
|
||||
inline osg::Group *get_root() { return root_.get(); }
|
||||
inline const osg::Group *get_root() const { return root_.get(); }
|
||||
|
||||
inline const Options &get_options() const { return options_; }
|
||||
inline Options &get_options() { return options_; }
|
||||
inline void set_options(const Options &options) { options_ = options; }
|
||||
|
||||
protected:
|
||||
void build_scene_graph(Object &obj);
|
||||
|
||||
private:
|
||||
osg::ref_ptr<osg::Group> root_;
|
||||
Options options_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -2,15 +2,24 @@ TOPDIR = ../../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
lw.cpp\
|
||||
Lwo2.cpp\
|
||||
Lwo2Layer.cpp\
|
||||
old_lw.cpp\
|
||||
old_Lwo2.cpp\
|
||||
old_Lwo2Layer.cpp\
|
||||
Block.cpp\
|
||||
Clip.cpp\
|
||||
Converter.cpp\
|
||||
Object.cpp\
|
||||
Polygon.cpp\
|
||||
Surface.cpp\
|
||||
Tessellator.cpp\
|
||||
Unit.cpp\
|
||||
VertexMap.cpp\
|
||||
ReaderWriterLWO.cpp\
|
||||
|
||||
|
||||
INC += -I$(THISDIR)
|
||||
|
||||
LIBS += $(OSG_LIBS) $(OTHER_LIBS)
|
||||
LIBS += $(OSG_LIBS) $(OTHER_LIBS) $(GL_LIBS)
|
||||
|
||||
TARGET_BASENAME = lwo
|
||||
include $(TOPDIR)/Make/cygwin_plugin_def
|
||||
|
||||
84
src/osgPlugins/lwo/Layer.h
Normal file
84
src/osgPlugins/lwo/Layer.h
Normal file
@@ -0,0 +1,84 @@
|
||||
/*******************************************************
|
||||
Lightwave Object Loader for OSG
|
||||
|
||||
Copyright (C) 2004 Marco Jez <marco.jez@poste.it>
|
||||
OpenSceneGraph is (C) 2004 Robert Osfield
|
||||
********************************************************/
|
||||
|
||||
#ifndef LWOSG_LAYER_
|
||||
#define LWOSG_LAYER_
|
||||
|
||||
#include "lwo2chunks.h"
|
||||
|
||||
#include "Unit.h"
|
||||
|
||||
namespace lwosg
|
||||
{
|
||||
|
||||
class Layer {
|
||||
public:
|
||||
typedef std::vector<Unit> Unit_list;
|
||||
|
||||
inline Layer();
|
||||
|
||||
inline const lwo2::FORM::LAYR *get_layer_chunk() const;
|
||||
inline void set_layer_chunk(const lwo2::FORM::LAYR *layr);
|
||||
|
||||
inline int number() const;
|
||||
|
||||
inline Unit_list &units();
|
||||
inline const Unit_list &units() const;
|
||||
inline osg::Vec3 pivot() const;
|
||||
|
||||
private:
|
||||
const lwo2::FORM::LAYR *layr_;
|
||||
Unit_list units_;
|
||||
};
|
||||
|
||||
// INLINE METHODS
|
||||
|
||||
inline Layer::Layer()
|
||||
: layr_(0)
|
||||
{
|
||||
}
|
||||
|
||||
inline Layer::Unit_list &Layer::units()
|
||||
{
|
||||
return units_;
|
||||
}
|
||||
|
||||
inline const Layer::Unit_list &Layer::units() const
|
||||
{
|
||||
return units_;
|
||||
}
|
||||
|
||||
inline osg::Vec3 Layer::pivot() const
|
||||
{
|
||||
if (layr_) {
|
||||
return osg::Vec3(layr_->pivot.X, layr_->pivot.Y, layr_->pivot.Z);
|
||||
}
|
||||
return osg::Vec3(0, 0, 0);
|
||||
}
|
||||
|
||||
inline const lwo2::FORM::LAYR *Layer::get_layer_chunk() const
|
||||
{
|
||||
return layr_;
|
||||
}
|
||||
|
||||
inline void Layer::set_layer_chunk(const lwo2::FORM::LAYR *layr)
|
||||
{
|
||||
layr_ = layr;
|
||||
}
|
||||
|
||||
inline int Layer::number() const
|
||||
{
|
||||
if (layr_) {
|
||||
return layr_->number;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
461
src/osgPlugins/lwo/Object.cpp
Normal file
461
src/osgPlugins/lwo/Object.cpp
Normal file
@@ -0,0 +1,461 @@
|
||||
/*******************************************************
|
||||
Lightwave Object Loader for OSG
|
||||
|
||||
Copyright (C) 2004 Marco Jez <marco.jez@poste.it>
|
||||
OpenSceneGraph is (C) 2004 Robert Osfield
|
||||
********************************************************/
|
||||
|
||||
#include "Object.h"
|
||||
|
||||
#include <osg/Notify>
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
using namespace lwosg;
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
bool triangle_is_clockwise(const osg::Vec3Array *points, int a, int b, int c)
|
||||
{
|
||||
const osg::Vec3 &A = (*points)[a];
|
||||
const osg::Vec3 &B = (*points)[b];
|
||||
const osg::Vec3 &C = (*points)[c];
|
||||
float area2 = 0;
|
||||
area2 += A.x() * B.y() - B.x() * A.y();
|
||||
area2 += B.x() * C.y() - C.x() * B.y();
|
||||
area2 += C.x() * A.y() - A.x() * C.y();
|
||||
return area2 < 0;
|
||||
}
|
||||
|
||||
float cylindrical_angle(float x, float y)
|
||||
{
|
||||
float r = sqrtf(x*x+y*y);
|
||||
if (r == 0) return 0;
|
||||
x /= r;
|
||||
float a;
|
||||
if (x < 0 && y >= 0) a = osg::PI_2 - acosf(-x);
|
||||
if (x < 0 && y < 0) a = acosf(-x) + osg::PI_2;
|
||||
if (x >= 0 && y >= 0) a = acosf(x) + 3 * osg::PI_2;
|
||||
if (x >= 0 && y < 0) a = 3 * osg::PI_2 - acosf(x);
|
||||
return a/osg::PI/2;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Object::Object()
|
||||
: csf_(new LwoCoordFixer)
|
||||
{
|
||||
}
|
||||
|
||||
Object::Object(const iff::Chunk_list &data)
|
||||
: csf_(new LwoCoordFixer)
|
||||
{
|
||||
build(data);
|
||||
}
|
||||
|
||||
void Object::build(const iff::Chunk_list &data)
|
||||
{
|
||||
clips_.clear();
|
||||
surfaces_.clear();
|
||||
layers_.clear();
|
||||
comment_.clear();
|
||||
description_.clear();
|
||||
|
||||
osg::notify(osg::INFO) << "INFO: lwosg::Object: scanning clips\n";
|
||||
scan_clips(data);
|
||||
osg::notify(osg::INFO) << "INFO: lwosg::Object: scanning surfaces\n";
|
||||
scan_surfaces(data);
|
||||
osg::notify(osg::INFO) << "INFO: lwosg::Object: parsing LWO2 chunks and building object\n";
|
||||
parse(data);
|
||||
osg::notify(osg::INFO) << "INFO: lwosg::Object: generating normals\n";
|
||||
generate_normals();
|
||||
osg::notify(osg::INFO) << "INFO: lwosg::Object: generating automatic texture maps\n";
|
||||
generate_auto_texture_maps();
|
||||
}
|
||||
|
||||
void Object::scan_clips(const iff::Chunk_list &data)
|
||||
{
|
||||
for (iff::Chunk_list::const_iterator i=data.begin(); i!=data.end(); ++i) {
|
||||
const lwo2::FORM::CLIP *clip = dynamic_cast<const lwo2::FORM::CLIP *>(*i);
|
||||
if (clip) {
|
||||
clips_[clip->index] = Clip(clip);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Object::scan_surfaces(const iff::Chunk_list &data)
|
||||
{
|
||||
for (iff::Chunk_list::const_iterator i=data.begin(); i!=data.end(); ++i) {
|
||||
const lwo2::FORM::SURF *surf = dynamic_cast<const lwo2::FORM::SURF *>(*i);
|
||||
if (surf) {
|
||||
surfaces_[surf->name] = Surface(surf, clips_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Object::parse(const iff::Chunk_list &data)
|
||||
{
|
||||
typedef std::vector<std::string> String_list;
|
||||
String_list tag_strings;
|
||||
|
||||
Layer current_layer;
|
||||
|
||||
for (iff::Chunk_list::const_iterator i=data.begin(); i!=data.end(); ++i) {
|
||||
|
||||
const lwo2::FORM::LAYR *layr = dynamic_cast<const lwo2::FORM::LAYR *>(*i);
|
||||
if (layr) {
|
||||
if (!current_layer.units().empty() || current_layer.get_layer_chunk()) {
|
||||
layers_[current_layer.number()] = current_layer;
|
||||
}
|
||||
current_layer.set_layer_chunk(layr);
|
||||
current_layer.units().clear();
|
||||
}
|
||||
|
||||
const lwo2::FORM::PNTS *pnts = dynamic_cast<const lwo2::FORM::PNTS *>(*i);
|
||||
if (pnts) {
|
||||
Unit new_unit;
|
||||
for (lwo2::FORM::PNTS::Point_list::const_iterator i=pnts->point_location.begin(); i!=pnts->point_location.end(); ++i) {
|
||||
new_unit.points()->push_back(csf_->fix_point(osg::Vec3(i->X, i->Y, i->Z) /*+ current_layer.pivot()*/));
|
||||
}
|
||||
new_unit.shares().assign(new_unit.points()->size(), Unit::Index_list());
|
||||
current_layer.units().push_back(new_unit);
|
||||
}
|
||||
|
||||
const lwo2::FORM::VMAP *vmap = dynamic_cast<const lwo2::FORM::VMAP *>(*i);
|
||||
if (vmap && !current_layer.units().empty()) {
|
||||
std::string type(vmap->type.id, 4);
|
||||
if (type == "WGHT") {
|
||||
if (vmap->dimension != 1) {
|
||||
osg::notify(osg::WARN) << "Warning: Lwo2Object: invalid " << type << " vertex map dimension: " << vmap->dimension << std::endl;
|
||||
continue;
|
||||
}
|
||||
VertexMap *new_map = current_layer.units().back().weight_maps()->getOrCreate(vmap->name);
|
||||
for (lwo2::FORM::VMAP::Mapping_list::const_iterator i=vmap->mapping.begin(); i!=vmap->mapping.end(); ++i) {
|
||||
(*new_map)[i->vert.index] = osg::Vec4(i->value.at(0), 0, 0, 0);
|
||||
}
|
||||
}
|
||||
if (type == "MNVW") {
|
||||
if (vmap->dimension != 1) {
|
||||
osg::notify(osg::WARN) << "Warning: Lwo2Object: invalid " << type << " vertex map dimension: " << vmap->dimension << std::endl;
|
||||
continue;
|
||||
}
|
||||
VertexMap *new_map = current_layer.units().back().subpatch_weight_maps()->getOrCreate(vmap->name);
|
||||
for (lwo2::FORM::VMAP::Mapping_list::const_iterator i=vmap->mapping.begin(); i!=vmap->mapping.end(); ++i) {
|
||||
(*new_map)[i->vert.index] = osg::Vec4(i->value.at(0), 0, 0, 0);
|
||||
}
|
||||
}
|
||||
if (type == "TXUV") {
|
||||
if (vmap->dimension != 2) {
|
||||
osg::notify(osg::WARN) << "Warning: Lwo2Object: invalid " << type << " vertex map dimension: " << vmap->dimension << std::endl;
|
||||
continue;
|
||||
}
|
||||
VertexMap *new_map = current_layer.units().back().texture_maps()->getOrCreate(vmap->name);
|
||||
for (lwo2::FORM::VMAP::Mapping_list::const_iterator i=vmap->mapping.begin(); i!=vmap->mapping.end(); ++i) {
|
||||
(*new_map)[i->vert.index] = osg::Vec4(i->value.at(0), i->value.at(1), 0, 0);
|
||||
}
|
||||
}
|
||||
if (type == "RGB ") {
|
||||
if (vmap->dimension != 3) {
|
||||
osg::notify(osg::WARN) << "Warning: Lwo2Object: invalid " << type << " vertex map dimension: " << vmap->dimension << std::endl;
|
||||
continue;
|
||||
}
|
||||
VertexMap *new_map = current_layer.units().back().rgb_maps()->getOrCreate(vmap->name);
|
||||
for (lwo2::FORM::VMAP::Mapping_list::const_iterator i=vmap->mapping.begin(); i!=vmap->mapping.end(); ++i) {
|
||||
(*new_map)[i->vert.index] = osg::Vec4(i->value.at(0), i->value.at(1), i->value.at(2), 1);
|
||||
}
|
||||
}
|
||||
if (type == "RGBA") {
|
||||
if (vmap->dimension != 4) {
|
||||
osg::notify(osg::WARN) << "Warning: Lwo2Object: invalid " << type << " vertex map dimension: " << vmap->dimension << std::endl;
|
||||
continue;
|
||||
}
|
||||
VertexMap *new_map = current_layer.units().back().rgba_maps()->getOrCreate(vmap->name);
|
||||
for (lwo2::FORM::VMAP::Mapping_list::const_iterator i=vmap->mapping.begin(); i!=vmap->mapping.end(); ++i) {
|
||||
(*new_map)[i->vert.index] = osg::Vec4(i->value.at(0), i->value.at(1), i->value.at(2), i->value.at(3));
|
||||
}
|
||||
}
|
||||
if (type == "MORF") {
|
||||
if (vmap->dimension != 3) {
|
||||
osg::notify(osg::WARN) << "Warning: Lwo2Object: invalid " << type << " vertex map dimension: " << vmap->dimension << std::endl;
|
||||
continue;
|
||||
}
|
||||
VertexMap *new_map = current_layer.units().back().displacement_maps()->getOrCreate(vmap->name);
|
||||
for (lwo2::FORM::VMAP::Mapping_list::const_iterator i=vmap->mapping.begin(); i!=vmap->mapping.end(); ++i) {
|
||||
(*new_map)[i->vert.index] = osg::Vec4(i->value.at(0), i->value.at(1), i->value.at(2), 0);
|
||||
}
|
||||
}
|
||||
if (type == "SPOT") {
|
||||
if (vmap->dimension != 3) {
|
||||
osg::notify(osg::WARN) << "Warning: Lwo2Object: invalid " << type << " vertex map dimension: " << vmap->dimension << std::endl;
|
||||
continue;
|
||||
}
|
||||
VertexMap *new_map = current_layer.units().back().spot_maps()->getOrCreate(vmap->name);
|
||||
for (lwo2::FORM::VMAP::Mapping_list::const_iterator i=vmap->mapping.begin(); i!=vmap->mapping.end(); ++i) {
|
||||
(*new_map)[i->vert.index] = osg::Vec4(csf_->fix_point(osg::Vec3(i->value.at(0), i->value.at(1), i->value.at(2))), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const lwo2::FORM::POLS *pols = dynamic_cast<const lwo2::FORM::POLS *>(*i);
|
||||
if (pols && !current_layer.units().empty()) {
|
||||
std::string type(pols->type.id, 4);
|
||||
if (type != "FACE") {
|
||||
osg::notify(osg::INFO) << "INFO: Lwo2Object: polygon list of type " << type << " not supported, rendering may be inaccurate" << std::endl;
|
||||
}
|
||||
for (lwo2::FORM::POLS::Polygon_list::const_iterator i=pols->polygons.begin(); i!=pols->polygons.end(); ++i) {
|
||||
Polygon polygon;
|
||||
bool must_invert_winding = csf_->invert_winding();
|
||||
|
||||
// FIX FOR A LIGHTWAVE BUG? MAYBE IT IS A FEATURE, I DON'T KNOW...
|
||||
// if the first vertex is at a concave corner, we must invert the winding of the polygon
|
||||
// beacuse it appears as flipped in Lighwave. Also, we tell the polygon to invert its normal.
|
||||
// (not implemented yet)
|
||||
/*if (i->vert.size() >= 4) {
|
||||
if (must_invert_winding == triangle_is_clockwise(current_layer.units().back().points(), i->vert.front().index, i->vert.back().index, i->vert[1].index)) {
|
||||
must_invert_winding = !must_invert_winding;
|
||||
polygon.set_invert_normal(true);
|
||||
}
|
||||
}*/
|
||||
|
||||
if (must_invert_winding) {
|
||||
for (unsigned j=0; j<i->numvert; ++j) {
|
||||
int index = i->vert.at((i->numvert-j)%i->numvert).index;
|
||||
polygon.indices().push_back(index);
|
||||
current_layer.units().back().shares().at(index).push_back(current_layer.units().back().polygons().size());
|
||||
}
|
||||
} else {
|
||||
for (unsigned j=0; j<i->numvert; ++j) {
|
||||
int index = i->vert.at(j).index;
|
||||
polygon.indices().push_back(index);
|
||||
current_layer.units().back().shares().at(index).push_back(current_layer.units().back().polygons().size());
|
||||
}
|
||||
}
|
||||
current_layer.units().back().polygons().push_back(polygon);
|
||||
}
|
||||
}
|
||||
|
||||
const lwo2::FORM::TAGS *tags = dynamic_cast<const lwo2::FORM::TAGS *>(*i);
|
||||
if (tags) {
|
||||
tag_strings = tags->tag_string;
|
||||
}
|
||||
|
||||
const lwo2::FORM::PTAG *ptag = dynamic_cast<const lwo2::FORM::PTAG *>(*i);
|
||||
if (ptag && !current_layer.units().empty()) {
|
||||
std::string type(ptag->type.id, 4);
|
||||
if (type == "SURF") {
|
||||
for (lwo2::FORM::PTAG::Mapping_list::const_iterator i=ptag->mapping.begin(); i!=ptag->mapping.end(); ++i) {
|
||||
current_layer.units().back().polygons().at(i->poly.index).set_surface(&surfaces_[tag_strings.at(i->tag)]);
|
||||
}
|
||||
}
|
||||
if (type == "PART") {
|
||||
for (lwo2::FORM::PTAG::Mapping_list::const_iterator i=ptag->mapping.begin(); i!=ptag->mapping.end(); ++i) {
|
||||
current_layer.units().back().polygons().at(i->poly.index).set_part_name(tag_strings.at(i->tag));
|
||||
}
|
||||
}
|
||||
if (type == "SMGP") {
|
||||
for (lwo2::FORM::PTAG::Mapping_list::const_iterator i=ptag->mapping.begin(); i!=ptag->mapping.end(); ++i) {
|
||||
current_layer.units().back().polygons().at(i->poly.index).set_smoothing_group(tag_strings.at(i->tag));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const lwo2::FORM::VMAD *vmad = dynamic_cast<const lwo2::FORM::VMAD *>(*i);
|
||||
if (vmad && !current_layer.units().empty()) {
|
||||
std::string type(vmad->type.id, 4);
|
||||
if (type == "WGHT") {
|
||||
if (vmad->dimension != 1) {
|
||||
osg::notify(osg::WARN) << "Warning: Lwo2Object: invalid " << type << " discontinuous vertex map dimension: " << vmad->dimension << std::endl;
|
||||
continue;
|
||||
}
|
||||
for (lwo2::FORM::VMAD::Mapping_list::const_iterator i=vmad->mapping.begin(); i!=vmad->mapping.end(); ++i) {
|
||||
VertexMap *this_map = current_layer.units().back().polygons().at(i->poly.index).weight_maps()->getOrCreate(vmad->name);
|
||||
(*this_map)[i->vert.index] = osg::Vec4(i->value.at(0), 0, 0, 0);
|
||||
}
|
||||
}
|
||||
if (type == "TXUV") {
|
||||
if (vmad->dimension != 2) {
|
||||
osg::notify(osg::WARN) << "Warning: Lwo2Object: invalid " << type << " discontinuous vertex map dimension: " << vmad->dimension << std::endl;
|
||||
continue;
|
||||
}
|
||||
for (lwo2::FORM::VMAD::Mapping_list::const_iterator i=vmad->mapping.begin(); i!=vmad->mapping.end(); ++i) {
|
||||
VertexMap *this_map = current_layer.units().back().polygons().at(i->poly.index).texture_maps()->getOrCreate(vmad->name);
|
||||
(*this_map)[i->vert.index] = osg::Vec4(i->value.at(0), i->value.at(1), 0, 0);
|
||||
}
|
||||
}
|
||||
if (type == "RGB ") {
|
||||
if (vmad->dimension != 3) {
|
||||
osg::notify(osg::WARN) << "Warning: Lwo2Object: invalid " << type << " discontinuous vertex map dimension: " << vmad->dimension << std::endl;
|
||||
continue;
|
||||
}
|
||||
for (lwo2::FORM::VMAD::Mapping_list::const_iterator i=vmad->mapping.begin(); i!=vmad->mapping.end(); ++i) {
|
||||
VertexMap *this_map = current_layer.units().back().polygons().at(i->poly.index).rgb_maps()->getOrCreate(vmad->name);
|
||||
(*this_map)[i->vert.index] = osg::Vec4(i->value.at(0), i->value.at(1), i->value.at(2), 1);
|
||||
}
|
||||
}
|
||||
if (type == "RGBA") {
|
||||
if (vmad->dimension != 4) {
|
||||
osg::notify(osg::WARN) << "Warning: Lwo2Object: invalid " << type << " discontinuous vertex map dimension: " << vmad->dimension << std::endl;
|
||||
continue;
|
||||
}
|
||||
for (lwo2::FORM::VMAD::Mapping_list::const_iterator i=vmad->mapping.begin(); i!=vmad->mapping.end(); ++i) {
|
||||
VertexMap *this_map = current_layer.units().back().polygons().at(i->poly.index).rgba_maps()->getOrCreate(vmad->name);
|
||||
(*this_map)[i->vert.index] = osg::Vec4(i->value.at(0), i->value.at(1), i->value.at(2), i->value.at(3));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const lwo2::FORM::DESC *desc = dynamic_cast<const lwo2::FORM::DESC *>(*i);
|
||||
if (desc) {
|
||||
description_ = desc->description_line;
|
||||
}
|
||||
|
||||
const lwo2::FORM::TEXT *text = dynamic_cast<const lwo2::FORM::TEXT *>(*i);
|
||||
if (text) {
|
||||
comment_ = text->comment;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!current_layer.units().empty() || current_layer.get_layer_chunk()) {
|
||||
layers_[current_layer.number()] = current_layer;
|
||||
}
|
||||
}
|
||||
|
||||
void Object::generate_normals()
|
||||
{
|
||||
for (Layer_map::iterator i=layers_.begin(); i!=layers_.end(); ++i) {
|
||||
for (Layer::Unit_list::iterator j=i->second.units().begin(); j!=i->second.units().end(); ++j) {
|
||||
j->generate_normals();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Object::generate_auto_texture_maps()
|
||||
{
|
||||
for (Surface_map::iterator i=surfaces_.begin(); i!=surfaces_.end(); ++i) {
|
||||
for (Surface::Block_map::iterator j=i->second.blocks().begin(); j!=i->second.blocks().end(); ++j) {
|
||||
Block &block = j->second;
|
||||
if (block.get_type() == "IMAP") {
|
||||
if (block.get_image_map().projection == Image_map::UV) continue;
|
||||
|
||||
Image_map::Axis_type axis = block.get_image_map().axis;
|
||||
|
||||
std::ostringstream oss;
|
||||
oss << "Auto_map_" << █
|
||||
std::string map_name = oss.str();
|
||||
|
||||
osg::notify(osg::DEBUG_INFO) << "DEBUG INFO: lwosg::Object: creating automatic texture map '" << map_name << "'\n";
|
||||
|
||||
for (Layer_map::iterator k=layers_.begin(); k!=layers_.end(); ++k) {
|
||||
for (Layer::Unit_list::iterator h=k->second.units().begin(); h!=k->second.units().end(); ++h) {
|
||||
|
||||
osg::ref_ptr<VertexMap> new_map = new VertexMap;
|
||||
(*h->texture_maps())[map_name] = new_map.get();
|
||||
|
||||
if (block.get_image_map().projection == Image_map::FRONT_PROJECTION) {
|
||||
osg::notify(osg::WARN) << "Warning: lwosg::Object: front projection is not supported" << std::endl;
|
||||
}
|
||||
|
||||
if (block.get_image_map().projection == Image_map::CUBIC) {
|
||||
|
||||
for (Unit::Polygon_list::iterator p=h->polygons().begin(); p!=h->polygons().end(); ++p) {
|
||||
|
||||
Polygon &poly = *p;
|
||||
osg::ref_ptr<VertexMap> local_uv_map = poly.texture_maps()->getOrCreate(map_name);
|
||||
|
||||
osg::Vec3 N = csf_->fix_vector(poly.face_normal(h->points()));
|
||||
|
||||
Image_map::Axis_type axis = Image_map::X;
|
||||
if (N.y() > N.x() && N.y() > N.z()) axis = Image_map::Y;
|
||||
if (-N.y() > N.x() && -N.y() > N.z()) axis = Image_map::Y;
|
||||
if (N.z() > N.x() && N.z() > N.y()) axis = Image_map::Z;
|
||||
if (-N.z() > N.x() && -N.z() > N.y()) axis = Image_map::Z;
|
||||
|
||||
for (Polygon::Index_list::iterator i=poly.indices().begin(); i!=poly.indices().end(); ++i) {
|
||||
|
||||
// fetch vertex
|
||||
osg::Vec3 P = csf_->fix_point((*h->points())[*i]);
|
||||
|
||||
// setup scale/translation/rotation
|
||||
P = block.setup_texture_point(P);
|
||||
|
||||
osg::Vec2 uv;
|
||||
switch (axis) {
|
||||
case Image_map::X: uv.set(P.z(), P.y()); break;
|
||||
case Image_map::Y: uv.set(P.x(), P.z()); break;
|
||||
case Image_map::Z: uv.set(P.x(), P.y()); break;
|
||||
default: ;
|
||||
}
|
||||
uv += osg::Vec2(0.5f, 0.5f);
|
||||
|
||||
osg::Vec4 map_value(uv.x(), uv.y(), 0, 0);
|
||||
|
||||
if ((new_map->find(*i) != new_map->end()) && (map_value != (*new_map.get())[*i])) {
|
||||
(*local_uv_map.get())[*i] = map_value;
|
||||
} else {
|
||||
(*new_map.get())[*i] = map_value;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
for (unsigned p=0; p<h->points()->size(); ++p) {
|
||||
|
||||
// fetch vertex
|
||||
osg::Vec3 P = csf_->fix_point((*h->points())[p]);
|
||||
|
||||
// setup scale/translation/rotation
|
||||
P = block.setup_texture_point(P);
|
||||
|
||||
osg::Vec2 uv;
|
||||
|
||||
if (block.get_image_map().projection == Image_map::PLANAR) {
|
||||
switch (axis) {
|
||||
case Image_map::X: uv.set(P.z(), P.y()); break;
|
||||
case Image_map::Y: uv.set(P.x(), P.z()); break;
|
||||
case Image_map::Z: uv.set(P.x(), P.y()); break;
|
||||
default: ;
|
||||
}
|
||||
uv += osg::Vec2(0.5f, 0.5f);
|
||||
}
|
||||
|
||||
if (block.get_image_map().projection == Image_map::CYLINDRICAL) {
|
||||
switch (axis) {
|
||||
case Image_map::X: uv.set(cylindrical_angle(-P.z(), -P.y()), P.x()); break;
|
||||
case Image_map::Y: uv.set(cylindrical_angle(P.x(), P.z()), P.y()); break;
|
||||
case Image_map::Z: uv.set(cylindrical_angle(P.x(), -P.y()), P.z()); break;
|
||||
default: ;
|
||||
}
|
||||
uv.x() *= block.get_image_map().wrap_amount_w;
|
||||
uv += osg::Vec2(0, 0.5f);
|
||||
}
|
||||
|
||||
if (block.get_image_map().projection == Image_map::SPHERICAL) {
|
||||
float r = P.length();
|
||||
if (r != 0) {
|
||||
switch (axis) {
|
||||
case Image_map::X: uv.set(cylindrical_angle(-P.z(), -P.y()), (asinf(P.x()/r) + osg::PI_2) / osg::PI); break;
|
||||
case Image_map::Y: uv.set(cylindrical_angle(P.x(), P.z()), (asinf(P.y()/r) + osg::PI_2) / osg::PI); break;
|
||||
case Image_map::Z: uv.set(cylindrical_angle(P.x(), -P.y()), (asinf(P.z()/r) + osg::PI_2) / osg::PI); break;
|
||||
default: ;
|
||||
}
|
||||
}
|
||||
uv.x() *= block.get_image_map().wrap_amount_w;
|
||||
uv.y() *= block.get_image_map().wrap_amount_h;
|
||||
}
|
||||
|
||||
(*new_map.get())[p] = osg::Vec4(uv.x(), uv.y(), 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
block.get_image_map().uv_map = map_name;
|
||||
block.get_image_map().projection = Image_map::UV;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
126
src/osgPlugins/lwo/Object.h
Normal file
126
src/osgPlugins/lwo/Object.h
Normal file
@@ -0,0 +1,126 @@
|
||||
/*******************************************************
|
||||
Lightwave Object Loader for OSG
|
||||
|
||||
Copyright (C) 2004 Marco Jez <marco.jez@poste.it>
|
||||
OpenSceneGraph is (C) 2004 Robert Osfield
|
||||
********************************************************/
|
||||
|
||||
#ifndef LWOSG_OBJECT_
|
||||
#define LWOSG_OBJECT_
|
||||
|
||||
#include "Layer.h"
|
||||
#include "Surface.h"
|
||||
#include "Clip.h"
|
||||
#include "Unit.h"
|
||||
|
||||
#include "iffparser.h"
|
||||
|
||||
#include <osg/Referenced>
|
||||
#include <osg/ref_ptr>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
namespace lwosg
|
||||
{
|
||||
|
||||
class CoordinateSystemFixer: public osg::Referenced {
|
||||
public:
|
||||
virtual osg::Vec3 fix_point(const osg::Vec3 &P) const = 0;
|
||||
virtual osg::Vec4 fix_point(const osg::Vec4 &P) const = 0;
|
||||
virtual osg::Vec3 fix_vector(const osg::Vec3 &V) const = 0;
|
||||
virtual osg::Vec4 fix_vector(const osg::Vec4 &V) const = 0;
|
||||
virtual inline bool invert_winding() const { return false; }
|
||||
|
||||
protected:
|
||||
virtual ~CoordinateSystemFixer() {}
|
||||
CoordinateSystemFixer &operator=(const CoordinateSystemFixer &) { return *this; }
|
||||
};
|
||||
|
||||
class LwoCoordFixer: public CoordinateSystemFixer {
|
||||
public:
|
||||
inline osg::Vec3 fix_point(const osg::Vec3 &P) const;
|
||||
inline osg::Vec4 fix_point(const osg::Vec4 &P) const;
|
||||
inline osg::Vec3 fix_vector(const osg::Vec3 &V) const;
|
||||
inline osg::Vec4 fix_vector(const osg::Vec4 &V) const;
|
||||
inline bool invert_winding() const { return true; }
|
||||
|
||||
protected:
|
||||
virtual ~LwoCoordFixer() {}
|
||||
LwoCoordFixer &operator=(const LwoCoordFixer &) { return *this; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
class Object {
|
||||
public:
|
||||
|
||||
typedef std::map<int, Layer> Layer_map;
|
||||
typedef std::map<std::string, Surface> Surface_map;
|
||||
|
||||
Object();
|
||||
Object(const iff::Chunk_list &data);
|
||||
|
||||
inline CoordinateSystemFixer *get_coordinate_system_fixer() { return csf_.get(); }
|
||||
inline const CoordinateSystemFixer *get_coordinate_system_fixer() const { return csf_.get(); }
|
||||
inline void set_coordinate_system_fixer(CoordinateSystemFixer *csf) { csf_ = csf; }
|
||||
|
||||
void build(const iff::Chunk_list &data);
|
||||
|
||||
inline Layer_map &layers() { return layers_; }
|
||||
inline const Layer_map &layers() const { return layers_; }
|
||||
|
||||
inline Surface_map &surfaces() { return surfaces_; }
|
||||
inline const Surface_map &surfaces() const { return surfaces_; }
|
||||
|
||||
inline const std::string &get_comment() const { return comment_; }
|
||||
inline const std::string &get_description() const { return description_; }
|
||||
|
||||
protected:
|
||||
void scan_clips(const iff::Chunk_list &data);
|
||||
void scan_surfaces(const iff::Chunk_list &data);
|
||||
void parse(const iff::Chunk_list &data);
|
||||
|
||||
void generate_normals();
|
||||
void generate_auto_texture_maps();
|
||||
|
||||
private:
|
||||
Layer_map layers_;
|
||||
|
||||
typedef std::map<int, Clip> Clip_map;
|
||||
Clip_map clips_;
|
||||
|
||||
Surface_map surfaces_;
|
||||
|
||||
std::string comment_;
|
||||
std::string description_;
|
||||
|
||||
osg::ref_ptr<CoordinateSystemFixer> csf_;
|
||||
};
|
||||
|
||||
// INLINE METHODS
|
||||
|
||||
inline osg::Vec3 LwoCoordFixer::fix_point(const osg::Vec3 &P) const
|
||||
{
|
||||
return osg::Vec3(P.x(), P.z(), P.y());
|
||||
}
|
||||
|
||||
inline osg::Vec4 LwoCoordFixer::fix_point(const osg::Vec4 &P) const
|
||||
{
|
||||
return osg::Vec4(fix_point(osg::Vec3(P.x(), P.y(), P.z())), P.w());
|
||||
}
|
||||
|
||||
inline osg::Vec3 LwoCoordFixer::fix_vector(const osg::Vec3 &V) const
|
||||
{
|
||||
return fix_point(V);
|
||||
}
|
||||
|
||||
inline osg::Vec4 LwoCoordFixer::fix_vector(const osg::Vec4 &V) const
|
||||
{
|
||||
return fix_point(V);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
22
src/osgPlugins/lwo/Polygon.cpp
Normal file
22
src/osgPlugins/lwo/Polygon.cpp
Normal file
@@ -0,0 +1,22 @@
|
||||
/*******************************************************
|
||||
Lightwave Object Loader for OSG
|
||||
|
||||
Copyright (C) 2004 Marco Jez <marco.jez@poste.it>
|
||||
OpenSceneGraph is (C) 2004 Robert Osfield
|
||||
********************************************************/
|
||||
|
||||
#include "Polygon.h"
|
||||
|
||||
using namespace lwosg;
|
||||
|
||||
Polygon::Polygon()
|
||||
: surf_(0),
|
||||
local_normals_(new VertexMap),
|
||||
weight_maps_(new VertexMap_map),
|
||||
texture_maps_(new VertexMap_map),
|
||||
rgb_maps_(new VertexMap_map),
|
||||
rgba_maps_(new VertexMap_map),
|
||||
invert_normal_(false),
|
||||
last_used_points_(0)
|
||||
{
|
||||
}
|
||||
118
src/osgPlugins/lwo/Polygon.h
Normal file
118
src/osgPlugins/lwo/Polygon.h
Normal file
@@ -0,0 +1,118 @@
|
||||
/*******************************************************
|
||||
Lightwave Object Loader for OSG
|
||||
|
||||
Copyright (C) 2004 Marco Jez <marco.jez@poste.it>
|
||||
OpenSceneGraph is (C) 2004 Robert Osfield
|
||||
********************************************************/
|
||||
|
||||
#ifndef LWOSG_POLYGON_
|
||||
#define LWOSG_POLYGON_
|
||||
|
||||
#include "lwo2chunks.h"
|
||||
#include "Surface.h"
|
||||
#include "VertexMap.h"
|
||||
|
||||
#include <osg/Vec3>
|
||||
#include <osg/Array>
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
namespace lwosg
|
||||
{
|
||||
|
||||
class Polygon {
|
||||
public:
|
||||
typedef std::vector<int> Index_list;
|
||||
typedef std::map<int, int> Duplication_map;
|
||||
|
||||
Polygon();
|
||||
|
||||
inline void set_invert_normal(bool v = true) { invert_normal_ = v; }
|
||||
|
||||
inline const Index_list &indices() const { return indices_; }
|
||||
inline Index_list &indices() { dirty_normal(); return indices_; }
|
||||
|
||||
inline const Duplication_map &dup_vertices() const { return dup_vertices_; }
|
||||
inline Duplication_map &dup_vertices() { return dup_vertices_; }
|
||||
|
||||
inline const VertexMap *local_normals() const { return local_normals_.get(); }
|
||||
inline VertexMap *local_normals() { return local_normals_.get(); }
|
||||
|
||||
inline const VertexMap_map *weight_maps() const { return weight_maps_.get(); }
|
||||
inline VertexMap_map *weight_maps() { return weight_maps_.get(); }
|
||||
|
||||
inline const VertexMap_map *texture_maps() const { return texture_maps_.get(); }
|
||||
inline VertexMap_map *texture_maps() { return texture_maps_.get(); }
|
||||
|
||||
inline const VertexMap_map *rgb_maps() const { return rgb_maps_.get(); }
|
||||
inline VertexMap_map *rgb_maps() { return rgb_maps_.get(); }
|
||||
|
||||
inline const VertexMap_map *rgba_maps() const { return rgba_maps_.get(); }
|
||||
inline VertexMap_map *rgba_maps() { return rgba_maps_.get(); }
|
||||
|
||||
inline bool has_surface() const { return surf_ != 0; }
|
||||
inline const Surface *get_surface() const { return surf_; }
|
||||
inline void set_surface(const Surface *s) { surf_ = s; }
|
||||
|
||||
inline bool has_part() const { return !part_.empty(); }
|
||||
inline const std::string &get_part_name() const { return part_; }
|
||||
inline void set_part_name(const std::string &n) { part_ = n; }
|
||||
|
||||
inline bool has_smoothing_group() const { return !smoothing_group_.empty(); }
|
||||
inline const std::string &get_smoothing_group() const { return smoothing_group_; }
|
||||
inline void set_smoothing_group(const std::string &n) { smoothing_group_ = n; }
|
||||
|
||||
inline const osg::Vec3 &face_normal(const osg::Vec3Array *points) const;
|
||||
|
||||
protected:
|
||||
inline void dirty_normal() { last_used_points_ = 0; }
|
||||
|
||||
private:
|
||||
Index_list indices_;
|
||||
Duplication_map dup_vertices_;
|
||||
|
||||
const Surface *surf_;
|
||||
std::string part_;
|
||||
std::string smoothing_group_;
|
||||
|
||||
osg::ref_ptr<VertexMap> local_normals_;
|
||||
osg::ref_ptr<VertexMap_map> weight_maps_;
|
||||
osg::ref_ptr<VertexMap_map> texture_maps_;
|
||||
osg::ref_ptr<VertexMap_map> rgb_maps_;
|
||||
osg::ref_ptr<VertexMap_map> rgba_maps_;
|
||||
|
||||
bool invert_normal_;
|
||||
|
||||
mutable const osg::Vec3Array *last_used_points_;
|
||||
mutable osg::Vec3 normal_;
|
||||
};
|
||||
|
||||
// INLINE METHODS
|
||||
|
||||
inline const osg::Vec3 &Polygon::face_normal(const osg::Vec3Array *points) const
|
||||
{
|
||||
if (last_used_points_ != points) {
|
||||
normal_.set(0, 0, 0);
|
||||
if (indices_.size() >= 3) {
|
||||
const osg::Vec3 &A = points->at(indices_.front());
|
||||
const osg::Vec3 &B = points->at(indices_[1]);
|
||||
const osg::Vec3 &C = points->at(indices_.back());
|
||||
if (invert_normal_) {
|
||||
normal_ = (C - A) ^ (B - A);
|
||||
} else {
|
||||
normal_ = (B - A) ^ (C - A);
|
||||
}
|
||||
float len = normal_.length();
|
||||
if (len != 0) {
|
||||
normal_ /= len;
|
||||
}
|
||||
}
|
||||
last_used_points_ = points;
|
||||
}
|
||||
return normal_;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
51
src/osgPlugins/lwo/README.txt
Normal file
51
src/osgPlugins/lwo/README.txt
Normal file
@@ -0,0 +1,51 @@
|
||||
LIGHTWAVE (LWO2) PLUGIN INTRODUCTION
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
This is the plugin version of my LWO2->OSG converter. It has all the
|
||||
features (and drawbacks) of the original converter but it doesn't replace
|
||||
it completely.
|
||||
I'm planning to further enhance the stand-alone converter by adding osgNV
|
||||
compatibility and I can't do this on the plugin version because I'm not going
|
||||
to introduce a dependancy to osgNV into OSG.
|
||||
There is also a LWS plugin which reads Lightwave scene files; make sure you
|
||||
only read scene files that point to LWO2 (not LWO1) objects, otherwise you may
|
||||
experience problems (the LWO1 plugin doesn't convert the coordinate system
|
||||
correctly).
|
||||
|
||||
|
||||
PLUGIN OPTIONS
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
USE_OLD_READER pass control to the old LWO/LWO2 reader plugin
|
||||
(all other options ignored)
|
||||
|
||||
FORCE_ARB_COMPRESSION create compressed textures
|
||||
|
||||
USE_OSGFX use osgFX effects to improve visual appearance
|
||||
|
||||
NO_LIGHTMODEL_ATTRIBUTE prevent the plugin from creating a LightModel
|
||||
state attribute; using this option may result in
|
||||
visual artifacts
|
||||
|
||||
MAX_TEXTURE_UNITS <n> set the maximum number of texture units to be
|
||||
used when creating multi-textured surfaces
|
||||
|
||||
|
||||
NOTES
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
NOTE_1: this plugin works fine in reading LWO2 files but it's not well
|
||||
optimized,so you can expect slowness and large memory usage.
|
||||
|
||||
NOTE_2: the LWS (scene) support is a quick-and-dirty work, it's there
|
||||
only because I needed it. Do not pretend too much from it, at least until
|
||||
I improve it somehow.
|
||||
|
||||
NOTE_3: the osgFX support is still limited, only osgFX::SpecularHighlights
|
||||
is used to improve the specularity effects on materials that have a specular
|
||||
component. Future enhancements will allow osgFX to be used more widely to
|
||||
give a better visual matching between the original LWO2 model and OSG.
|
||||
|
||||
|
||||
Marco Jez <marco.jez@poste.it>
|
||||
January 2004
|
||||
@@ -4,6 +4,7 @@
|
||||
* Lightwave Object loader for Open Scene Graph
|
||||
*
|
||||
* Copyright (C) 2001 Ulrich Hertlein <u.hertlein@web.de>
|
||||
* Improved LWO2 reader is (C) 2003-2004 Marco Jez <marco.jez@poste.it>
|
||||
*
|
||||
* The Open Scene Graph (OSG) is a cross platform C++/OpenGL library for
|
||||
* real-time rendering of large 3D photo-realistic models.
|
||||
@@ -15,6 +16,7 @@
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
|
||||
#include <osg/Notify>
|
||||
@@ -34,8 +36,10 @@
|
||||
#include <osgUtil/SmoothingVisitor>
|
||||
#include <osgUtil/Tesselator>
|
||||
|
||||
#include "lw.h"
|
||||
#include "Lwo2.h"
|
||||
#include "Converter.h"
|
||||
|
||||
#include "old_lw.h"
|
||||
#include "old_Lwo2.h"
|
||||
|
||||
class ReaderWriterLWO : public osgDB::ReaderWriter
|
||||
{
|
||||
@@ -49,7 +53,7 @@ public:
|
||||
|
||||
virtual ReadResult readNode(const std::string& file, const osgDB::ReaderWriter::Options* options)
|
||||
{
|
||||
std::string ext = osgDB::getLowerCaseFileExtension(file);
|
||||
std::string ext = osgDB::getLowerCaseFileExtension(file);
|
||||
if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED;
|
||||
|
||||
std::string fileName = osgDB::findDataFile( file );
|
||||
@@ -58,10 +62,18 @@ public:
|
||||
ReadResult result = readNode_LWO1(fileName,options);
|
||||
if (result.success()) return result;
|
||||
|
||||
return readNode_LWO2(fileName,options);
|
||||
if (!options || options->getOptionString() != "USE_OLD_READER") {
|
||||
ReadResult result = readNode_LWO2(fileName, options);
|
||||
if (result.success()) return result;
|
||||
}
|
||||
|
||||
return readNode_old_LWO2(fileName, options);
|
||||
}
|
||||
|
||||
lwosg::Converter::Options parse_options(const Options *options) const;
|
||||
|
||||
virtual ReadResult readNode_LWO2(const std::string& fileName, const osgDB::ReaderWriter::Options*);
|
||||
virtual ReadResult readNode_old_LWO2(const std::string& fileName, const osgDB::ReaderWriter::Options*);
|
||||
virtual ReadResult readNode_LWO1(const std::string& fileName, const osgDB::ReaderWriter::Options*);
|
||||
|
||||
protected:
|
||||
@@ -70,12 +82,48 @@ protected:
|
||||
|
||||
};
|
||||
|
||||
lwosg::Converter::Options ReaderWriterLWO::parse_options(const Options *options) const
|
||||
{
|
||||
lwosg::Converter::Options conv_options;
|
||||
|
||||
if (options) {
|
||||
std::istringstream iss(options->getOptionString());
|
||||
std::string opt;
|
||||
while (iss >> opt) {
|
||||
if (opt == "FORCE_ARB_COMPRESSION") conv_options.force_arb_compression = true;
|
||||
if (opt == "USE_OSGFX") conv_options.use_osgfx = true;
|
||||
if (opt == "NO_LIGHTMODEL_ATTRIBUTE") conv_options.apply_light_model = false;
|
||||
if (opt == "MAX_TEXTURE_UNITS") {
|
||||
int n;
|
||||
if (iss >> n) {
|
||||
conv_options.max_tex_units = n;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return conv_options;
|
||||
}
|
||||
|
||||
|
||||
// register with Registry to instantiate the above reader/writer.
|
||||
osgDB::RegisterReaderWriterProxy<ReaderWriterLWO> g_lwoReaderWriterProxy;
|
||||
|
||||
osgDB::ReaderWriter::ReadResult ReaderWriterLWO::readNode_LWO2(const std::string &fileName, const osgDB::ReaderWriter::Options *options)
|
||||
{
|
||||
lwosg::Converter::Options conv_options = parse_options(options);
|
||||
|
||||
osgDB::ReaderWriter::ReadResult ReaderWriterLWO::readNode_LWO2(const std::string& fileName, const osgDB::ReaderWriter::Options*)
|
||||
lwosg::Converter converter(conv_options);
|
||||
osg::ref_ptr<osg::Node> node = converter.convert(fileName);
|
||||
if (node.valid()) {
|
||||
return node.take();
|
||||
}
|
||||
|
||||
return ReadResult::FILE_NOT_HANDLED;
|
||||
}
|
||||
|
||||
|
||||
osgDB::ReaderWriter::ReadResult ReaderWriterLWO::readNode_old_LWO2(const std::string& fileName, const osgDB::ReaderWriter::Options*)
|
||||
{
|
||||
std::auto_ptr<Lwo2> lwo2(new Lwo2());
|
||||
if (lwo2->ReadFile(fileName))
|
||||
|
||||
329
src/osgPlugins/lwo/Surface.cpp
Normal file
329
src/osgPlugins/lwo/Surface.cpp
Normal file
@@ -0,0 +1,329 @@
|
||||
/*******************************************************
|
||||
Lightwave Object Loader for OSG
|
||||
|
||||
Copyright (C) 2004 Marco Jez <marco.jez@poste.it>
|
||||
OpenSceneGraph is (C) 2004 Robert Osfield
|
||||
********************************************************/
|
||||
|
||||
#include "Surface.h"
|
||||
|
||||
#include <osg/Material>
|
||||
#include <osg/CullFace>
|
||||
#include <osg/Texture2D>
|
||||
#include <osg/TexEnvCombine>
|
||||
#include <osg/TexGen>
|
||||
#include <osg/BlendFunc>
|
||||
#include <osg/Notify>
|
||||
|
||||
#include <osgFX/SpecularHighlights>
|
||||
|
||||
#include <osgDB/ReadFile>
|
||||
|
||||
using namespace lwosg;
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
osg::Texture::WrapMode osg_wrap_mode(Image_map::Wrap_type w)
|
||||
{
|
||||
switch (w) {
|
||||
case Image_map::RESET: return osg::Texture::CLAMP;
|
||||
case Image_map::REPEAT: return osg::Texture::REPEAT;
|
||||
case Image_map::MIRROR: return osg::Texture::MIRROR;
|
||||
case Image_map::EDGE: return osg::Texture::CLAMP_TO_EDGE;
|
||||
default: return osg::Texture::REPEAT;
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Surface::Surface()
|
||||
: base_color_(0.784f, 0.784f, 0.784f),
|
||||
diffuse_(1.0f),
|
||||
luminosity_(0),
|
||||
specularity_(0),
|
||||
reflection_(0),
|
||||
transparency_(0),
|
||||
translucency_(0),
|
||||
glossiness_(0.4f),
|
||||
sidedness_(FRONT_ONLY),
|
||||
max_smoothing_angle_(0)
|
||||
{
|
||||
}
|
||||
|
||||
Surface::Surface(const lwo2::FORM::SURF *surf, const Clip_map &clips)
|
||||
: base_color_(0.784f, 0.784f, 0.784f),
|
||||
diffuse_(1.0f),
|
||||
luminosity_(0),
|
||||
specularity_(0),
|
||||
reflection_(0),
|
||||
transparency_(0),
|
||||
translucency_(0),
|
||||
glossiness_(0.4f),
|
||||
sidedness_(FRONT_ONLY),
|
||||
max_smoothing_angle_(0)
|
||||
{
|
||||
compile(surf, clips);
|
||||
}
|
||||
|
||||
void Surface::compile(const lwo2::FORM::SURF *surf, const Clip_map &clips)
|
||||
{
|
||||
// invalidate the stateset so it will be rebuilt
|
||||
stateset_ = 0;
|
||||
|
||||
name_ = surf->name;
|
||||
|
||||
for (iff::Chunk_list::const_iterator j=surf->attributes.begin(); j!=surf->attributes.end(); ++j) {
|
||||
|
||||
const lwo2::FORM::SURF::COLR *colr = dynamic_cast<const lwo2::FORM::SURF::COLR *>(*j);
|
||||
if (colr) base_color_ = osg::Vec3(colr->base_color.red, colr->base_color.green, colr->base_color.blue);
|
||||
|
||||
const lwo2::FORM::SURF::DIFF *diff = dynamic_cast<const lwo2::FORM::SURF::DIFF *>(*j);
|
||||
if (diff) diffuse_ = diff->intensity.fraction;
|
||||
|
||||
const lwo2::FORM::SURF::LUMI *lumi = dynamic_cast<const lwo2::FORM::SURF::LUMI *>(*j);
|
||||
if (lumi) luminosity_ = lumi->intensity.fraction;
|
||||
|
||||
const lwo2::FORM::SURF::SPEC *spec = dynamic_cast<const lwo2::FORM::SURF::SPEC *>(*j);
|
||||
if (spec) specularity_ = spec->intensity.fraction;
|
||||
|
||||
const lwo2::FORM::SURF::REFL *refl = dynamic_cast<const lwo2::FORM::SURF::REFL *>(*j);
|
||||
if (refl) reflection_ = refl->intensity.fraction;
|
||||
|
||||
const lwo2::FORM::SURF::TRAN *tran = dynamic_cast<const lwo2::FORM::SURF::TRAN *>(*j);
|
||||
if (tran) transparency_ = tran->intensity.fraction;
|
||||
|
||||
const lwo2::FORM::SURF::TRNL *trnl = dynamic_cast<const lwo2::FORM::SURF::TRNL *>(*j);
|
||||
if (trnl) translucency_ = trnl->intensity.fraction;
|
||||
|
||||
const lwo2::FORM::SURF::GLOS *glos = dynamic_cast<const lwo2::FORM::SURF::GLOS *>(*j);
|
||||
if (glos) glossiness_ = glos->glossiness.fraction;
|
||||
|
||||
const lwo2::FORM::SURF::SIDE *side = dynamic_cast<const lwo2::FORM::SURF::SIDE *>(*j);
|
||||
if (side) sidedness_ = static_cast<Sidedness>(side->sidedness);
|
||||
|
||||
const lwo2::FORM::SURF::SMAN *sman = dynamic_cast<const lwo2::FORM::SURF::SMAN *>(*j);
|
||||
if (sman) max_smoothing_angle_ = sman->max_smoothing_angle.radians;
|
||||
|
||||
const lwo2::FORM::SURF::VCOL *vcol = dynamic_cast<const lwo2::FORM::SURF::VCOL *>(*j);
|
||||
if (vcol) {
|
||||
color_map_intensity_ = vcol->intensity.fraction;
|
||||
color_map_type_ = std::string(vcol->vmap_type.id, 4);
|
||||
color_map_name_ = vcol->name;
|
||||
}
|
||||
|
||||
const lwo2::FORM::SURF::BLOK *blok = dynamic_cast<const lwo2::FORM::SURF::BLOK *>(*j);
|
||||
if (blok) {
|
||||
Block new_block(blok);
|
||||
if (new_block.get_type() == "IMAP") {
|
||||
Clip_map::const_iterator i = clips.find(new_block.get_image_map().image_map);
|
||||
if (i != clips.end()) {
|
||||
new_block.get_image_map().clip = &i->second;
|
||||
} else {
|
||||
osg::notify(osg::WARN) << "Warning: lwosg::Surface: cannot find clip number " << new_block.get_image_map().image_map << std::endl;
|
||||
}
|
||||
}
|
||||
blocks_.insert(std::make_pair(new_block.get_ordinal(), new_block));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Surface::generate_stateset(int max_tex_units, bool force_arb_compression) const
|
||||
{
|
||||
if (!stateset_.valid()) {
|
||||
|
||||
stateset_ = new osg::StateSet;
|
||||
|
||||
osg::ref_ptr<osg::Material> material = new osg::Material;
|
||||
material->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4(base_color_ * diffuse_, 1-transparency_));
|
||||
material->setAmbient(osg::Material::FRONT_AND_BACK, material->getDiffuse(osg::Material::FRONT_AND_BACK));
|
||||
material->setSpecular(osg::Material::FRONT_AND_BACK, osg::Vec4(specularity_, specularity_, specularity_, 1));
|
||||
material->setShininess(osg::Material::FRONT_AND_BACK, powf(2, 10 * glossiness_ + 2));
|
||||
material->setEmission(osg::Material::FRONT_AND_BACK, osg::Vec4(base_color_ * luminosity_, 1-transparency_));
|
||||
stateset_->setAttributeAndModes(material.get());
|
||||
|
||||
if (!color_map_name_.empty()) {
|
||||
material->setColorMode(osg::Material::AMBIENT_AND_DIFFUSE);
|
||||
}
|
||||
|
||||
if (transparency_ > 0) {
|
||||
osg::ref_ptr<osg::BlendFunc> bf = new osg::BlendFunc;
|
||||
bf->setFunction(osg::BlendFunc::SRC_ALPHA, osg::BlendFunc::ONE_MINUS_SRC_ALPHA);
|
||||
stateset_->setAttributeAndModes(bf.get());
|
||||
stateset_->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
|
||||
}
|
||||
|
||||
if (sidedness_ == FRONT_AND_BACK) {
|
||||
stateset_->setMode(GL_CULL_FACE, osg::StateAttribute::OFF);
|
||||
} else {
|
||||
osg::ref_ptr<osg::CullFace> cf = new osg::CullFace;
|
||||
switch (sidedness_) {
|
||||
case NONE: cf->setMode(osg::CullFace::FRONT_AND_BACK); break;
|
||||
case FRONT_ONLY: cf->setMode(osg::CullFace::BACK); break;
|
||||
case BACK_ONLY: cf->setMode(osg::CullFace::FRONT); break;
|
||||
default: ;
|
||||
}
|
||||
stateset_->setAttributeAndModes(cf.get());
|
||||
}
|
||||
|
||||
int unit = 0;
|
||||
for (Block_map::const_iterator i=blocks_.begin(); i!=blocks_.end(); ++i) {
|
||||
|
||||
const Block &block = i->second;
|
||||
if (!block.enabled()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (block.get_type() == "IMAP") {
|
||||
if (block.get_channel() == "COLR") {
|
||||
if (block.get_image_map().clip) {
|
||||
std::string image_file = block.get_image_map().clip->get_still_filename();
|
||||
if (!image_file.empty()) {
|
||||
|
||||
if (unit >= max_tex_units && max_tex_units > 0) {
|
||||
osg::notify(osg::WARN) << "Warning: lwosg::Surface: maximum number of texture units (" << max_tex_units << ") has been reached, skipping incoming blocks" << std::endl;
|
||||
break;
|
||||
}
|
||||
|
||||
osg::ref_ptr<osg::Texture2D> texture = new osg::Texture2D;
|
||||
if (force_arb_compression)
|
||||
texture->setInternalFormatMode(osg::Texture::USE_ARB_COMPRESSION);
|
||||
texture->setImage(osgDB::readImageFile(image_file));
|
||||
texture->setWrap(osg::Texture::WRAP_S, osg_wrap_mode(block.get_image_map().width_wrap));
|
||||
texture->setWrap(osg::Texture::WRAP_T, osg_wrap_mode(block.get_image_map().height_wrap));
|
||||
texture->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR_MIPMAP_LINEAR);
|
||||
texture->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);
|
||||
stateset_->setTextureAttributeAndModes(unit, texture.get());
|
||||
|
||||
osg::ref_ptr<osg::TexEnvCombine> tec = new osg::TexEnvCombine;
|
||||
switch (block.get_opacity_type()) {
|
||||
case Block::NORMAL:
|
||||
{
|
||||
float s = block.get_opacity_amount();
|
||||
if (unit == 0) {
|
||||
tec->setCombine_RGB(osg::TexEnvCombine::MODULATE);
|
||||
osg::Vec3 color(diffuse_, diffuse_, diffuse_);
|
||||
color = color * s + base_color_ * (1 - s);
|
||||
material->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4(color, 1-transparency_));
|
||||
material->setAmbient(osg::Material::FRONT_AND_BACK, material->getDiffuse(osg::Material::FRONT_AND_BACK));
|
||||
material->setColorMode(osg::Material::OFF);
|
||||
} else {
|
||||
tec->setCombine_RGB(osg::TexEnvCombine::INTERPOLATE);
|
||||
tec->setConstantColor(osg::Vec4(s, s, s, s));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case Block::ADDITIVE:
|
||||
tec->setCombine_RGB(osg::TexEnvCombine::ADD);
|
||||
break;
|
||||
|
||||
case Block::SUBTRACTIVE:
|
||||
osg::notify(osg::WARN) << "Warning: lwosg::Surface: 'Subtractive' blending mode is not supported, falling back to 'Difference' mode" << std::endl;
|
||||
case Block::DIFFERENCE:
|
||||
tec->setCombine_RGB(osg::TexEnvCombine::SUBTRACT);
|
||||
break;
|
||||
|
||||
case Block::MULTIPLY:
|
||||
tec->setCombine_RGB(osg::TexEnvCombine::MODULATE);
|
||||
break;
|
||||
|
||||
case Block::DIVIDE:
|
||||
osg::notify(osg::WARN) << "Warning: lwosg::Surface: 'Divide' blending mode is not supported" << std::endl;
|
||||
break;
|
||||
|
||||
case Block::ALPHA:
|
||||
osg::notify(osg::WARN) << "Warning: lwosg::Surface: 'Alpha' blending mode is not supported" << std::endl;
|
||||
break;
|
||||
|
||||
case Block::TEXTURE_DISPLACEMENT:
|
||||
osg::notify(osg::WARN) << "Warning: lwosg::Surface: 'Texture Displacement' blending mode is not supported" << std::endl;
|
||||
break;
|
||||
|
||||
default: ;
|
||||
};
|
||||
|
||||
stateset_->setTextureAttributeAndModes(unit, tec.get());
|
||||
++unit;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
osg::notify(osg::WARN) << "Warning: lwosg::Surface: texture channels of type '" << block.get_channel() << "' are not supported, this block will be ignored" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
osg::Group *Surface::apply(osg::Geometry *geo, const VertexMap_map *texture_maps, const VertexMap_map *rgb_maps, const VertexMap_map *rgba_maps, int max_tex_units, bool use_osgfx, bool force_arb_compression) const
|
||||
{
|
||||
int num_points = 0;
|
||||
|
||||
if (geo->getVertexArray()) {
|
||||
num_points = static_cast<int>(geo->getVertexArray()->getNumElements());
|
||||
}
|
||||
|
||||
generate_stateset(max_tex_units, force_arb_compression);
|
||||
geo->setStateSet(stateset_.get());
|
||||
|
||||
int unit = 0;
|
||||
for (Block_map::const_iterator i=blocks_.begin(); i!=blocks_.end(); ++i) {
|
||||
const Block &block = i->second;
|
||||
if (block.get_type() == "IMAP" && block.get_channel() == "COLR" && block.get_image_map().clip) {
|
||||
std::string image_file = block.get_image_map().clip->get_still_filename();
|
||||
if (!image_file.empty()) {
|
||||
if (block.get_image_map().projection == Image_map::UV) {
|
||||
VertexMap_map::const_iterator i = texture_maps->find(block.get_image_map().uv_map);
|
||||
if (i != texture_maps->end()) {
|
||||
geo->setTexCoordArray(unit, i->second->asVec2Array(num_points));
|
||||
} else {
|
||||
osg::notify(osg::WARN) << "Warning: lwosg::Surface: surface '" << name_ << "' needs texture map named '" << block.get_image_map().uv_map << "' but I can't find it" << std::endl;
|
||||
}
|
||||
}
|
||||
++unit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
osg::Vec4 color = osg::Vec4(base_color_, 1-transparency_);
|
||||
|
||||
const VertexMap_map *color_maps = 0;
|
||||
|
||||
if (color_map_type_ == "RGB ") {
|
||||
color_maps = rgb_maps;
|
||||
}
|
||||
|
||||
if (color_map_type_ == "RGBA") {
|
||||
color_maps = rgba_maps;
|
||||
}
|
||||
|
||||
if (color_maps) {
|
||||
VertexMap_map::const_iterator i = color_maps->find(color_map_name_);
|
||||
if (i != color_maps->end() && !i->second->empty()) {
|
||||
geo->setColorArray(i->second->asVec4Array(num_points, color * color_map_intensity_, color * color_map_intensity_));
|
||||
geo->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
|
||||
} else {
|
||||
osg::notify(osg::WARN) << "Warning: lwosg::Surface: surface '" << name_ << "' needs color map named '" << color_map_name_ << "' but I can't find it" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
// create osgFX specularity if needed
|
||||
if (use_osgfx && glossiness_ > 0 && specularity_ > 0) {
|
||||
if (unit >= max_tex_units && max_tex_units > 0) {
|
||||
osg::notify(osg::WARN) << "Warning: lwosg::Surface: can't apply osgFX specular lighting: maximum number of texture units (" << max_tex_units << ") has been reached" << std::endl;
|
||||
} else {
|
||||
osg::ref_ptr<osgFX::SpecularHighlights> sh = new osgFX::SpecularHighlights;
|
||||
sh->setTextureUnit(unit);
|
||||
osg::Material *material = dynamic_cast<osg::Material *>(stateset_->getAttribute(osg::StateAttribute::MATERIAL));
|
||||
if (material) {
|
||||
sh->setSpecularColor(material->getSpecular(osg::Material::FRONT_AND_BACK));
|
||||
sh->setSpecularExponent(powf(2, 10 * glossiness_ + 2));
|
||||
material->setSpecular(osg::Material::FRONT_AND_BACK, osg::Vec4(0, 0, 0, 0));
|
||||
material->setShininess(osg::Material::FRONT_AND_BACK, 0);
|
||||
}
|
||||
return sh.take();
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
105
src/osgPlugins/lwo/Surface.h
Normal file
105
src/osgPlugins/lwo/Surface.h
Normal file
@@ -0,0 +1,105 @@
|
||||
/*******************************************************
|
||||
Lightwave Object Loader for OSG
|
||||
|
||||
Copyright (C) 2004 Marco Jez <marco.jez@poste.it>
|
||||
OpenSceneGraph is (C) 2004 Robert Osfield
|
||||
********************************************************/
|
||||
|
||||
#ifndef LWOSG_SURFACE_
|
||||
#define LWOSG_SURFACE_
|
||||
|
||||
#include "lwo2chunks.h"
|
||||
|
||||
#include "VertexMap.h"
|
||||
#include "Block.h"
|
||||
#include "Clip.h"
|
||||
|
||||
#include <osg/ref_ptr>
|
||||
#include <osg/Vec3>
|
||||
#include <osg/StateSet>
|
||||
#include <osg/Geometry>
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
namespace lwosg
|
||||
{
|
||||
|
||||
class Surface {
|
||||
public:
|
||||
|
||||
enum Sidedness {
|
||||
NONE = 0,
|
||||
FRONT_ONLY = 1,
|
||||
BACK_ONLY = 2,
|
||||
FRONT_AND_BACK = 3
|
||||
};
|
||||
|
||||
typedef std::multimap<std::string, Block> Block_map;
|
||||
|
||||
Surface();
|
||||
Surface(const lwo2::FORM::SURF *surf, const Clip_map &clips);
|
||||
|
||||
void compile(const lwo2::FORM::SURF *surf, const Clip_map &clips);
|
||||
|
||||
osg::Group *apply(osg::Geometry *geo, const VertexMap_map *texture_maps, const VertexMap_map *rgb_maps, const VertexMap_map *rgba_maps, int max_tex_units = 0, bool use_osgfx = false, bool force_arb_compression = false) const;
|
||||
|
||||
void generate_stateset(int max_tex_units = 0, bool force_arb_compression = false) const;
|
||||
|
||||
inline const std::string &get_name() const { return name_; }
|
||||
inline void set_name(const std::string &n) { name_ = n; }
|
||||
|
||||
inline const osg::Vec3 &get_base_color() const { return base_color_; }
|
||||
|
||||
inline float get_diffuse() const { return diffuse_; }
|
||||
inline float get_luminosity() const { return luminosity_; }
|
||||
inline float get_specularity() const { return specularity_; }
|
||||
inline float get_reflection() const { return reflection_; }
|
||||
inline float get_transparency() const { return transparency_; }
|
||||
inline float get_translucency() const { return translucency_; }
|
||||
inline float get_glossiness() const { return glossiness_; }
|
||||
|
||||
inline Sidedness get_sidedness() const { return sidedness_; }
|
||||
|
||||
inline float get_max_smoothing_angle() const { return max_smoothing_angle_; }
|
||||
|
||||
inline const std::string &get_color_map_type() const { return color_map_type_; }
|
||||
inline const std::string &get_color_map_name() const { return color_map_name_; }
|
||||
inline float get_color_map_intensity() const { return color_map_intensity_; }
|
||||
|
||||
inline Block_map &blocks() { return blocks_; }
|
||||
inline const Block_map &blocks() const { return blocks_; }
|
||||
/*
|
||||
inline const std::string &get_uv_map_name() const { return uv_map_name_; }
|
||||
|
||||
inline bool has_clip() const { return clip_ != 0; }
|
||||
inline const Clip *get_clip() const { return clip_; }
|
||||
inline void set_clip(const Clip *c) { clip_ = c; }
|
||||
*/
|
||||
private:
|
||||
std::string name_;
|
||||
osg::Vec3 base_color_;
|
||||
float diffuse_;
|
||||
float luminosity_;
|
||||
float specularity_;
|
||||
float reflection_;
|
||||
float transparency_;
|
||||
float translucency_;
|
||||
float glossiness_;
|
||||
Sidedness sidedness_;
|
||||
float max_smoothing_angle_;
|
||||
std::string color_map_type_;
|
||||
std::string color_map_name_;
|
||||
float color_map_intensity_;
|
||||
|
||||
Block_map blocks_;
|
||||
/*
|
||||
std::string uv_map_name_;
|
||||
const Clip *clip_;
|
||||
*/
|
||||
mutable osg::ref_ptr<osg::StateSet> stateset_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
121
src/osgPlugins/lwo/Tessellator.cpp
Normal file
121
src/osgPlugins/lwo/Tessellator.cpp
Normal file
@@ -0,0 +1,121 @@
|
||||
/*******************************************************
|
||||
Lightwave Object Loader for OSG
|
||||
|
||||
Copyright (C) 2004 Marco Jez <marco.jez@poste.it>
|
||||
OpenSceneGraph is (C) 2004 Robert Osfield
|
||||
********************************************************/
|
||||
|
||||
#include "Tessellator.h"
|
||||
|
||||
using namespace lwosg;
|
||||
|
||||
namespace lwosg
|
||||
{
|
||||
|
||||
void CALLBACK cb_begin_data(GLenum type, void *data)
|
||||
{
|
||||
Tessellator *tess = static_cast<Tessellator *>(data);
|
||||
tess->prim_type_ = type;
|
||||
tess->incoming_.clear();
|
||||
}
|
||||
|
||||
void CALLBACK cb_vertex_data(void *vertex_data, void *data)
|
||||
{
|
||||
Tessellator *tess = static_cast<Tessellator *>(data);
|
||||
tess->incoming_.push_back(*static_cast<int *>(vertex_data));
|
||||
}
|
||||
|
||||
void CALLBACK cb_end_data(void *data)
|
||||
{
|
||||
Tessellator *tess = static_cast<Tessellator *>(data);
|
||||
tess->finalize_primitive();
|
||||
}
|
||||
|
||||
void CALLBACK cb_error_data(GLenum error, void *data)
|
||||
{
|
||||
Tessellator *tess = static_cast<Tessellator *>(data);
|
||||
tess->last_error_ = error;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool Tessellator::tessellate(const Polygon &poly, const osg::Vec3Array *points, osg::DrawElementsUInt *out, const std::vector<int> *remap)
|
||||
{
|
||||
out_ = out;
|
||||
last_error_ = 0;
|
||||
|
||||
GLUtesselator *tess = gluNewTess();
|
||||
|
||||
gluTessCallback(tess, GLU_TESS_BEGIN_DATA, reinterpret_cast<void (CALLBACK *)()>(cb_begin_data));
|
||||
gluTessCallback(tess, GLU_TESS_VERTEX_DATA, reinterpret_cast<void (CALLBACK *)()>(cb_vertex_data));
|
||||
gluTessCallback(tess, GLU_TESS_END_DATA, reinterpret_cast<void (CALLBACK *)()>(cb_end_data));
|
||||
gluTessCallback(tess, GLU_TESS_ERROR_DATA, reinterpret_cast<void (CALLBACK *)()>(cb_error_data));
|
||||
|
||||
gluTessBeginPolygon(tess, this);
|
||||
gluTessBeginContour(tess);
|
||||
|
||||
double *vertices = new double[poly.indices().size() * 3];
|
||||
int *indices = new int[poly.indices().size()];
|
||||
|
||||
double *v = vertices;
|
||||
int *x = indices;
|
||||
for (Polygon::Index_list::const_iterator i=poly.indices().begin(); i!=poly.indices().end(); ++i, v+=3, ++x) {
|
||||
const osg::Vec3 &P = (*points)[*i];
|
||||
v[0] = P.x();
|
||||
v[1] = P.y();
|
||||
v[2] = P.z();
|
||||
if (remap) {
|
||||
*x = (*remap)[*i];
|
||||
} else {
|
||||
*x = *i;
|
||||
}
|
||||
gluTessVertex(tess, v, x);
|
||||
}
|
||||
|
||||
gluTessEndContour(tess);
|
||||
gluTessEndPolygon(tess);
|
||||
gluDeleteTess(tess);
|
||||
|
||||
delete[] vertices;
|
||||
delete[] indices;
|
||||
|
||||
return last_error_ == 0;
|
||||
}
|
||||
|
||||
Tessellator::~Tessellator()
|
||||
{
|
||||
}
|
||||
|
||||
void Tessellator::finalize_primitive()
|
||||
{
|
||||
if (incoming_.size() < 3) return;
|
||||
|
||||
if (prim_type_ == GL_TRIANGLES) {
|
||||
for (Index_list::const_iterator i=incoming_.begin(); i!=incoming_.end(); ++i) {
|
||||
out_->push_back(*i);
|
||||
}
|
||||
}
|
||||
|
||||
if (prim_type_ == GL_TRIANGLE_FAN) {
|
||||
for (Index_list::const_iterator i=incoming_.begin()+1; (i+1)!=incoming_.end(); ++i) {
|
||||
out_->push_back(incoming_.front());
|
||||
out_->push_back(*i);
|
||||
out_->push_back(*(i+1));
|
||||
}
|
||||
}
|
||||
|
||||
if (prim_type_ == GL_TRIANGLE_STRIP) {
|
||||
int j = 0;
|
||||
for (Index_list::const_iterator i=incoming_.begin(); (i+2)!=incoming_.end(); ++i, ++j) {
|
||||
if ((j % 2) == 0) {
|
||||
out_->push_back(*i);
|
||||
out_->push_back(*(i+1));
|
||||
out_->push_back(*(i+2));
|
||||
} else {
|
||||
out_->push_back(*i);
|
||||
out_->push_back(*(i+2));
|
||||
out_->push_back(*(i+1));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
53
src/osgPlugins/lwo/Tessellator.h
Normal file
53
src/osgPlugins/lwo/Tessellator.h
Normal file
@@ -0,0 +1,53 @@
|
||||
/*******************************************************
|
||||
Lightwave Object Loader for OSG
|
||||
|
||||
Copyright (C) 2004 Marco Jez <marco.jez@poste.it>
|
||||
OpenSceneGraph is (C) 2004 Robert Osfield
|
||||
********************************************************/
|
||||
|
||||
#ifndef LWOSG_TESSELLATOR_
|
||||
#define LWOSG_TESSELLATOR_
|
||||
|
||||
#include "Polygon.h"
|
||||
|
||||
#include <osg/ref_ptr>
|
||||
#include <osg/Array>
|
||||
#include <osg/PrimitiveSet>
|
||||
#include <osg/GLU>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#ifndef CALLBACK
|
||||
#define CALLBACK
|
||||
#endif
|
||||
|
||||
namespace lwosg
|
||||
{
|
||||
|
||||
class Tessellator {
|
||||
public:
|
||||
bool tessellate(const Polygon &poly, const osg::Vec3Array *points, osg::DrawElementsUInt *out, const std::vector<int> *remap = 0);
|
||||
|
||||
~Tessellator();
|
||||
|
||||
protected:
|
||||
void finalize_primitive();
|
||||
|
||||
private:
|
||||
friend void CALLBACK cb_begin_data(GLenum, void *);
|
||||
friend void CALLBACK cb_vertex_data(void *, void *);
|
||||
friend void CALLBACK cb_end_data(void *);
|
||||
friend void CALLBACK cb_error_data(GLenum, void *);
|
||||
|
||||
osg::ref_ptr<osg::DrawElementsUInt> out_;
|
||||
|
||||
GLenum prim_type_;
|
||||
GLenum last_error_;
|
||||
|
||||
typedef std::vector<int> Index_list;
|
||||
Index_list incoming_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
242
src/osgPlugins/lwo/Unit.cpp
Normal file
242
src/osgPlugins/lwo/Unit.cpp
Normal file
@@ -0,0 +1,242 @@
|
||||
/*******************************************************
|
||||
Lightwave Object Loader for OSG
|
||||
|
||||
Copyright (C) 2004 Marco Jez <marco.jez@poste.it>
|
||||
OpenSceneGraph is (C) 2004 Robert Osfield
|
||||
********************************************************/
|
||||
|
||||
#include "Unit.h"
|
||||
|
||||
using namespace lwosg;
|
||||
|
||||
Unit::Unit()
|
||||
: points_(new osg::Vec3Array),
|
||||
normals_(new VertexMap),
|
||||
weight_maps_(new VertexMap_map),
|
||||
subpatch_weight_maps_(new VertexMap_map),
|
||||
texture_maps_(new VertexMap_map),
|
||||
rgb_maps_(new VertexMap_map),
|
||||
rgba_maps_(new VertexMap_map),
|
||||
displacement_maps_(new VertexMap_map),
|
||||
spot_maps_(new VertexMap_map)
|
||||
{
|
||||
}
|
||||
|
||||
float Unit::angle_between_polygons(const Polygon &p1, const Polygon &p2) const
|
||||
{
|
||||
float a = p1.face_normal(points_.get()) * p2.face_normal(points_.get());
|
||||
if (a > 1) return 0;
|
||||
if (a < -1) return osg::PI;
|
||||
return acosf(a);
|
||||
}
|
||||
|
||||
void Unit::find_shared_polygons(int vertex_index, std::vector<int> &poly_indices)
|
||||
{
|
||||
int k = 0;
|
||||
for (Polygon_list::const_iterator i=polygons_.begin(); i!=polygons_.end(); ++i, ++k) {
|
||||
for (Polygon::Index_list::const_iterator j=i->indices().begin(); j!=i->indices().end(); ++j) {
|
||||
if (*j == vertex_index) {
|
||||
poly_indices.push_back(k);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Unit::generate_normals()
|
||||
{
|
||||
// create smoothed normals
|
||||
for (Polygon_list::iterator i=polygons_.begin(); i!=polygons_.end(); ++i) {
|
||||
osg::Vec4 N = osg::Vec4(i->face_normal(points_.get()), 0);
|
||||
for (Polygon::Index_list::iterator j=i->indices().begin(); j!=i->indices().end(); ++j) {
|
||||
(*normals_.get())[*j] += N;
|
||||
}
|
||||
}
|
||||
|
||||
// normalize smoothed normals
|
||||
for (VertexMap::iterator ni=normals_->begin(); ni!=normals_->end(); ++ni) {
|
||||
float l = ni->second.length();
|
||||
if (l != 0) ni->second /= l;
|
||||
}
|
||||
|
||||
// compute per-polygon normals
|
||||
int pn = 0;
|
||||
for (Polygon_list::iterator pi=polygons_.begin(); pi!=polygons_.end(); ++pi, ++pn) {
|
||||
|
||||
Polygon &poly = *pi;
|
||||
|
||||
float max_smoothing_angle = 0;
|
||||
if (poly.has_surface()) {
|
||||
max_smoothing_angle = poly.get_surface()->get_max_smoothing_angle();
|
||||
}
|
||||
|
||||
for (Polygon::Index_list::const_iterator j=poly.indices().begin(); j!=poly.indices().end(); ++j) {
|
||||
|
||||
osg::Vec4 N(poly.face_normal(points_.get()), 0);
|
||||
unsigned num_smoothed = 1;
|
||||
|
||||
const Index_list &shared_polys = shares_.at(*j);
|
||||
|
||||
for (unsigned k=0; k<shared_polys.size(); ++k) {
|
||||
if (shared_polys[k] != pn) {
|
||||
const Polygon &shared_poly = polygons_.at(shared_polys[k]);
|
||||
float angle = angle_between_polygons(poly, shared_poly);
|
||||
if (angle <= max_smoothing_angle && (poly.get_smoothing_group() == shared_poly.get_smoothing_group())) {
|
||||
N += osg::Vec4(shared_poly.face_normal(points_.get()), 0);
|
||||
++num_smoothed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (num_smoothed != shared_polys.size()) {
|
||||
float l = N.length();
|
||||
if (l != 0) N /= l;
|
||||
(*poly.local_normals())[*j] = N;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Unit::flatten_maps()
|
||||
{
|
||||
for (Polygon_list::iterator i=polygons().begin(); i!=polygons().end(); ++i) {
|
||||
|
||||
// flatten normal map
|
||||
flatten_map(*i, i->local_normals(), normals_.get());
|
||||
i->local_normals()->clear();
|
||||
|
||||
VertexMap_map::const_iterator j;
|
||||
|
||||
// flatten weight maps
|
||||
while (!i->weight_maps()->empty()) {
|
||||
VertexMap_map::iterator j = i->weight_maps()->begin();
|
||||
flatten_map(*i, j->second.get(), weight_maps_->getOrCreate(j->first));
|
||||
i->weight_maps()->erase(j);
|
||||
}
|
||||
|
||||
// flatten texture maps
|
||||
while (!i->texture_maps()->empty()) {
|
||||
VertexMap_map::iterator j = i->texture_maps()->begin();
|
||||
flatten_map(*i, j->second.get(), texture_maps_->getOrCreate(j->first));
|
||||
i->texture_maps()->erase(j);
|
||||
}
|
||||
|
||||
// flatten rgb maps
|
||||
while (!i->rgb_maps()->empty()) {
|
||||
VertexMap_map::iterator j = i->rgb_maps()->begin();
|
||||
flatten_map(*i, j->second.get(), rgb_maps_->getOrCreate(j->first));
|
||||
i->rgb_maps()->erase(j);
|
||||
}
|
||||
|
||||
// flatten rgba maps
|
||||
while (!i->rgba_maps()->empty()) {
|
||||
VertexMap_map::iterator j = i->rgba_maps()->begin();
|
||||
flatten_map(*i, j->second.get(), rgba_maps_->getOrCreate(j->first));
|
||||
i->rgba_maps()->erase(j);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void Unit::flatten_map(Polygon &poly, const VertexMap *local_map, VertexMap *global_map)
|
||||
{
|
||||
int j = 0;
|
||||
for (Polygon::Index_list::iterator i=poly.indices().begin(); i!=poly.indices().end(); ++i, ++j) {
|
||||
|
||||
// try original vertex index
|
||||
VertexMap::const_iterator k = local_map->find(*i);
|
||||
|
||||
// try duplicated vertex index
|
||||
if (k == local_map->end()) {
|
||||
k = local_map->find(poly.dup_vertices()[j]);
|
||||
}
|
||||
|
||||
if (k != local_map->end()) {
|
||||
|
||||
// duplication may be needed!
|
||||
if (poly.dup_vertices()[j] == 0) {
|
||||
|
||||
// duplicate point
|
||||
points_->push_back(points_->at(*i));
|
||||
|
||||
int new_index = static_cast<int>(points_->size())-1;
|
||||
|
||||
// duplicate normal
|
||||
(*normals_.get())[new_index] = (*normals_.get())[*i];
|
||||
|
||||
// duplicate share
|
||||
shares_.push_back(shares_.at(*i));
|
||||
|
||||
VertexMap_map::iterator vm;
|
||||
|
||||
// duplicate weights
|
||||
for (vm=weight_maps()->begin(); vm!=weight_maps()->end(); ++vm) {
|
||||
if (vm->second->find(*i) != vm->second->end())
|
||||
(*vm->second.get())[new_index] = (*vm->second.get())[*i];
|
||||
}
|
||||
|
||||
// duplicate subpatch weights
|
||||
for (vm=subpatch_weight_maps()->begin(); vm!=subpatch_weight_maps()->end(); ++vm) {
|
||||
if (vm->second->find(*i) != vm->second->end())
|
||||
(*vm->second.get())[new_index] = (*vm->second.get())[*i];
|
||||
}
|
||||
|
||||
// duplicate texture UVs
|
||||
for (vm=texture_maps()->begin(); vm!=texture_maps()->end(); ++vm) {
|
||||
if (vm->second->find(*i) != vm->second->end())
|
||||
(*vm->second.get())[new_index] = (*vm->second.get())[*i];
|
||||
}
|
||||
|
||||
// duplicate RGBs
|
||||
for (vm=rgb_maps()->begin(); vm!=rgb_maps()->end(); ++vm) {
|
||||
if (vm->second->find(*i) != vm->second->end())
|
||||
(*vm->second.get())[new_index] = (*vm->second.get())[*i];
|
||||
}
|
||||
|
||||
// duplicate RGBAs
|
||||
for (vm=rgba_maps()->begin(); vm!=rgba_maps()->end(); ++vm) {
|
||||
if (vm->second->find(*i) != vm->second->end())
|
||||
(*vm->second.get())[new_index] = (*vm->second.get())[*i];
|
||||
}
|
||||
|
||||
// duplicate displacements
|
||||
for (vm=displacement_maps()->begin(); vm!=displacement_maps()->end(); ++vm) {
|
||||
if (vm->second->find(*i) != vm->second->end())
|
||||
(*vm->second.get())[new_index] = (*vm->second.get())[*i];
|
||||
}
|
||||
|
||||
// duplicate spots
|
||||
for (vm=spot_maps()->begin(); vm!=spot_maps()->end(); ++vm) {
|
||||
if (vm->second->find(*i) != vm->second->end())
|
||||
(*vm->second.get())[new_index] = (*vm->second.get())[*i];
|
||||
}
|
||||
|
||||
// update vertex index
|
||||
poly.dup_vertices()[j] = *i;
|
||||
*i = new_index;
|
||||
}
|
||||
|
||||
(*global_map)[*i] = k->second;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Unit::compute_vertex_remapping(const Surface *surf, Index_list &remap) const
|
||||
{
|
||||
remap.assign(points_->size(), -1);
|
||||
for (Polygon_list::const_iterator i=polygons_.begin(); i!=polygons_.end(); ++i) {
|
||||
if (i->get_surface() == surf) {
|
||||
for (Polygon::Index_list::const_iterator j=i->indices().begin(); j!=i->indices().end(); ++j) {
|
||||
remap[*j] = *j;
|
||||
}
|
||||
}
|
||||
}
|
||||
int offset = 0;
|
||||
for (Index_list::iterator j=remap.begin(); j!=remap.end(); ++j) {
|
||||
if (*j == -1) {
|
||||
++offset;
|
||||
} else {
|
||||
*j -= offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
91
src/osgPlugins/lwo/Unit.h
Normal file
91
src/osgPlugins/lwo/Unit.h
Normal file
@@ -0,0 +1,91 @@
|
||||
/*******************************************************
|
||||
Lightwave Object Loader for OSG
|
||||
|
||||
Copyright (C) 2004 Marco Jez <marco.jez@poste.it>
|
||||
OpenSceneGraph is (C) 2004 Robert Osfield
|
||||
********************************************************/
|
||||
|
||||
#ifndef LWOSG_UNIT_
|
||||
#define LWOSG_UNIT_
|
||||
|
||||
#include "Polygon.h"
|
||||
#include "VertexMap.h"
|
||||
|
||||
#include <osg/ref_ptr>
|
||||
#include <osg/Array>
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace lwosg
|
||||
{
|
||||
|
||||
class Unit {
|
||||
public:
|
||||
|
||||
typedef std::vector<Polygon> Polygon_list;
|
||||
typedef std::vector<int> Index_list;
|
||||
typedef std::vector<Index_list> Sharing_list;
|
||||
|
||||
Unit();
|
||||
|
||||
inline osg::Vec3Array *points() { return points_.get(); }
|
||||
inline const osg::Vec3Array *points() const { return points_.get(); }
|
||||
|
||||
inline VertexMap *normals() { return normals_.get(); }
|
||||
inline const VertexMap *normals() const { return normals_.get(); }
|
||||
|
||||
inline Polygon_list &polygons() { return polygons_; }
|
||||
inline const Polygon_list &polygons() const { return polygons_; }
|
||||
|
||||
inline Sharing_list &shares() { return shares_; }
|
||||
inline const Sharing_list &shares() const { return shares_; }
|
||||
|
||||
inline const VertexMap_map *weight_maps() const { return weight_maps_.get(); }
|
||||
inline VertexMap_map *weight_maps() { return weight_maps_.get(); }
|
||||
|
||||
inline const VertexMap_map *subpatch_weight_maps() const { return subpatch_weight_maps_.get(); }
|
||||
inline VertexMap_map *subpatch_weight_maps() { return subpatch_weight_maps_.get(); }
|
||||
|
||||
inline const VertexMap_map *texture_maps() const { return texture_maps_.get(); }
|
||||
inline VertexMap_map *texture_maps() { return texture_maps_.get(); }
|
||||
|
||||
inline const VertexMap_map *rgb_maps() const { return rgb_maps_.get(); }
|
||||
inline VertexMap_map *rgb_maps() { return rgb_maps_.get(); }
|
||||
|
||||
inline const VertexMap_map *rgba_maps() const { return rgba_maps_.get(); }
|
||||
inline VertexMap_map *rgba_maps() { return rgba_maps_.get(); }
|
||||
|
||||
inline const VertexMap_map *displacement_maps() const { return displacement_maps_.get(); }
|
||||
inline VertexMap_map *displacement_maps() { return displacement_maps_.get(); }
|
||||
|
||||
inline const VertexMap_map *spot_maps() const { return spot_maps_.get(); }
|
||||
inline VertexMap_map *spot_maps() { return spot_maps_.get(); }
|
||||
|
||||
void flatten_maps();
|
||||
void generate_normals();
|
||||
|
||||
void compute_vertex_remapping(const Surface *surf, Index_list &remap) const;
|
||||
|
||||
protected:
|
||||
float angle_between_polygons(const Polygon &p1, const Polygon &p2) const;
|
||||
void find_shared_polygons(int vertex_index, std::vector<int> &poly_indices);
|
||||
void flatten_map(Polygon &poly, const VertexMap *local_map, VertexMap *global_map);
|
||||
|
||||
private:
|
||||
osg::ref_ptr<osg::Vec3Array> points_;
|
||||
Polygon_list polygons_;
|
||||
Sharing_list shares_;
|
||||
|
||||
osg::ref_ptr<VertexMap> normals_;
|
||||
osg::ref_ptr<VertexMap_map> weight_maps_;
|
||||
osg::ref_ptr<VertexMap_map> subpatch_weight_maps_;
|
||||
osg::ref_ptr<VertexMap_map> texture_maps_;
|
||||
osg::ref_ptr<VertexMap_map> rgb_maps_;
|
||||
osg::ref_ptr<VertexMap_map> rgba_maps_;
|
||||
osg::ref_ptr<VertexMap_map> displacement_maps_;
|
||||
osg::ref_ptr<VertexMap_map> spot_maps_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
81
src/osgPlugins/lwo/VertexMap.cpp
Normal file
81
src/osgPlugins/lwo/VertexMap.cpp
Normal file
@@ -0,0 +1,81 @@
|
||||
/*******************************************************
|
||||
Lightwave Object Loader for OSG
|
||||
|
||||
Copyright (C) 2004 Marco Jez <marco.jez@poste.it>
|
||||
OpenSceneGraph is (C) 2004 Robert Osfield
|
||||
********************************************************/
|
||||
|
||||
#include "VertexMap.h"
|
||||
|
||||
#include <osg/Notify>
|
||||
|
||||
using namespace lwosg;
|
||||
|
||||
osg::Vec4Array *VertexMap::asVec4Array(int num_vertices, const osg::Vec4 &default_value, const osg::Vec4 &modulator) const
|
||||
{
|
||||
osg::ref_ptr<osg::Vec4Array> array = new osg::Vec4Array;
|
||||
array->assign(num_vertices, default_value);
|
||||
for (VertexMap::const_iterator i=begin(); i!=end(); ++i) {
|
||||
osg::Vec4 value = i->second;
|
||||
value.x() *= modulator.x();
|
||||
value.y() *= modulator.y();
|
||||
value.z() *= modulator.z();
|
||||
value.w() *= modulator.w();
|
||||
array->at(i->first) = value;
|
||||
}
|
||||
return array.take();
|
||||
}
|
||||
|
||||
osg::Vec2Array *VertexMap::asVec2Array(int num_vertices, const osg::Vec2 &default_value, const osg::Vec2 &modulator) const
|
||||
{
|
||||
osg::ref_ptr<osg::Vec2Array> array = new osg::Vec2Array;
|
||||
array->assign(num_vertices, default_value);
|
||||
for (VertexMap::const_iterator i=begin(); i!=end(); ++i) {
|
||||
osg::Vec4 value = i->second;
|
||||
value.x() *= modulator.x();
|
||||
value.y() *= modulator.y();
|
||||
array->at(i->first) = osg::Vec2(value.x(), value.y());
|
||||
}
|
||||
return array.take();
|
||||
}
|
||||
|
||||
osg::Vec3Array *VertexMap::asVec3Array(int num_vertices, const osg::Vec3 &default_value, const osg::Vec3 &modulator) const
|
||||
{
|
||||
osg::ref_ptr<osg::Vec3Array> array = new osg::Vec3Array;
|
||||
array->assign(num_vertices, default_value);
|
||||
for (VertexMap::const_iterator i=begin(); i!=end(); ++i) {
|
||||
osg::Vec4 value = i->second;
|
||||
value.x() *= modulator.x();
|
||||
value.y() *= modulator.y();
|
||||
value.z() *= modulator.z();
|
||||
array->at(i->first) = osg::Vec3(value.x(), value.y(), value.z());
|
||||
}
|
||||
return array.take();
|
||||
}
|
||||
|
||||
VertexMap *VertexMap::remap(const std::vector<int> &remapping) const
|
||||
{
|
||||
osg::ref_ptr<VertexMap> result = new VertexMap;
|
||||
|
||||
for (VertexMap::const_iterator i=begin(); i!=end(); ++i) {
|
||||
if (i->first >= static_cast<int>(remapping.size())) {
|
||||
osg::notify(osg::WARN) << "Warning: lwosg::remap(): remapping index not found for vertex " << i->first << " (map size " << remapping.size() << ")" << std::endl;
|
||||
} else {
|
||||
int new_index = remapping[i->first];
|
||||
if (new_index != -1) {
|
||||
(*result.get())[new_index] = i->second;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result.take();
|
||||
}
|
||||
|
||||
VertexMap_map *VertexMap_map::remap(const std::vector<int> &remapping) const
|
||||
{
|
||||
osg::ref_ptr<VertexMap_map> result = new VertexMap_map;
|
||||
for (VertexMap_map::const_iterator i=begin(); i!=end(); ++i) {
|
||||
(*result.get())[i->first] = i->second->remap(remapping);
|
||||
}
|
||||
return result.take();
|
||||
}
|
||||
74
src/osgPlugins/lwo/VertexMap.h
Normal file
74
src/osgPlugins/lwo/VertexMap.h
Normal file
@@ -0,0 +1,74 @@
|
||||
/*******************************************************
|
||||
Lightwave Object Loader for OSG
|
||||
|
||||
Copyright (C) 2004 Marco Jez <marco.jez@poste.it>
|
||||
OpenSceneGraph is (C) 2004 Robert Osfield
|
||||
********************************************************/
|
||||
|
||||
#ifndef LWOSG_VERTEXMAP_
|
||||
#define LWOSG_VERTEXMAP_
|
||||
|
||||
#include <osg/Vec2>
|
||||
#include <osg/Vec3>
|
||||
#include <osg/Vec4>
|
||||
#include <osg/Array>
|
||||
#include <osg/Referenced>
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
namespace lwosg
|
||||
{
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// VERTEX MAP
|
||||
|
||||
typedef std::map<int, osg::Vec4> VertexMap_impl;
|
||||
|
||||
class VertexMap: public VertexMap_impl, public osg::Referenced {
|
||||
public:
|
||||
VertexMap(): VertexMap_impl(), osg::Referenced() {}
|
||||
|
||||
osg::Vec2Array *asVec2Array(int num_vertices, const osg::Vec2 &default_value = osg::Vec2(0, 0), const osg::Vec2 &modulator = osg::Vec2(1, 1)) const;
|
||||
osg::Vec3Array *asVec3Array(int num_vertices, const osg::Vec3 &default_value = osg::Vec3(0, 0, 0), const osg::Vec3 &modulator = osg::Vec3(1, 1, 1)) const;
|
||||
osg::Vec4Array *asVec4Array(int num_vertices, const osg::Vec4 &default_value = osg::Vec4(0, 0, 0, 0), const osg::Vec4 &modulator = osg::Vec4(1, 1, 1, 1)) const;
|
||||
|
||||
VertexMap *remap(const std::vector<int> &remapping) const;
|
||||
|
||||
protected:
|
||||
virtual ~VertexMap() {}
|
||||
VertexMap &operator=(const VertexMap &) { return *this; }
|
||||
};
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// VERTEX MAP MAP
|
||||
|
||||
typedef std::map<std::string, osg::ref_ptr<VertexMap> > VertexMap_map_impl;
|
||||
|
||||
class VertexMap_map: public VertexMap_map_impl, public osg::Referenced {
|
||||
public:
|
||||
VertexMap_map(): VertexMap_map_impl(), osg::Referenced() {}
|
||||
|
||||
VertexMap *getOrCreate(const std::string &name)
|
||||
{
|
||||
osg::ref_ptr<VertexMap> &vmap = operator[](name);
|
||||
if (!vmap.valid()) {
|
||||
vmap = new VertexMap;
|
||||
}
|
||||
return vmap.get();
|
||||
}
|
||||
|
||||
VertexMap_map *remap(const std::vector<int> &remapping) const;
|
||||
|
||||
protected:
|
||||
virtual ~VertexMap_map() {}
|
||||
VertexMap_map &operator=(const VertexMap_map &) { return *this; }
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
114
src/osgPlugins/lwo/iffparser.h
Normal file
114
src/osgPlugins/lwo/iffparser.h
Normal file
@@ -0,0 +1,114 @@
|
||||
/*******************************************************
|
||||
Lightwave Object Loader for OSG
|
||||
|
||||
Copyright (C) 2004 Marco Jez <marco.jez@poste.it>
|
||||
OpenSceneGraph is (C) 2004 Robert Osfield
|
||||
********************************************************/
|
||||
|
||||
#ifndef IFFPARSER_
|
||||
#define IFFPARSER_
|
||||
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
|
||||
namespace iff
|
||||
{
|
||||
|
||||
typedef std::vector<struct Chunk *> Chunk_list;
|
||||
|
||||
struct Chunk {
|
||||
|
||||
virtual ~Chunk()
|
||||
{
|
||||
Chunk_list *fod = free_on_destroy();
|
||||
if (fod) {
|
||||
for (Chunk_list::iterator i=fod->begin(); i!=fod->end(); ++i) {
|
||||
delete *i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual Chunk_list *free_on_destroy() { return 0; }
|
||||
};
|
||||
|
||||
template<typename Iter>
|
||||
class GenericParser {
|
||||
public:
|
||||
GenericParser();
|
||||
GenericParser(std::ostream &os);
|
||||
|
||||
virtual ~GenericParser();
|
||||
|
||||
void clear();
|
||||
void parse(Iter begin, Iter end);
|
||||
|
||||
inline const Chunk_list &chunks() const;
|
||||
|
||||
protected:
|
||||
virtual Chunk *parse_chunk_data(const std::string &tag, const std::string &context, Iter it, Iter end) = 0;
|
||||
Chunk *parse_chunk(Iter &it, const std::string &context);
|
||||
|
||||
inline std::ostream &os() { return os_; }
|
||||
|
||||
private:
|
||||
Chunk_list chunks_;
|
||||
std::ostream &os_;
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// IMPLEMENTATION OF TEMPLATE FUNCTIONS
|
||||
|
||||
# define IP_TMP template<class Iter>
|
||||
|
||||
IP_TMP GenericParser<Iter>::GenericParser()
|
||||
: os_(std::cout)
|
||||
{
|
||||
}
|
||||
|
||||
IP_TMP GenericParser<Iter>::GenericParser(std::ostream &os)
|
||||
: os_(os)
|
||||
{
|
||||
}
|
||||
|
||||
IP_TMP GenericParser<Iter>::~GenericParser()
|
||||
{
|
||||
}
|
||||
|
||||
IP_TMP void GenericParser<Iter>::clear()
|
||||
{
|
||||
chunks_.clear();
|
||||
}
|
||||
|
||||
IP_TMP void GenericParser<Iter>::parse(Iter begin, Iter end)
|
||||
{
|
||||
Iter it = begin;
|
||||
while (it < end) {
|
||||
Chunk *chk = parse_chunk(it, "");
|
||||
if (chk) chunks_.push_back(chk);
|
||||
}
|
||||
}
|
||||
|
||||
IP_TMP Chunk *GenericParser<Iter>::parse_chunk(Iter &it, const std::string &context)
|
||||
{
|
||||
std::string tag;
|
||||
for (int i=0; i<4; ++i) tag.push_back(*(it++));
|
||||
unsigned int len = ((static_cast<unsigned int>(*(it++)) & 0xFF) << 24) |
|
||||
((static_cast<unsigned int>(*(it++)) & 0xFF) << 16) |
|
||||
((static_cast<unsigned int>(*(it++)) & 0xFF) << 8) |
|
||||
(static_cast<unsigned int>(*(it++)) & 0xFF);
|
||||
os_ << "DEBUG INFO: iffparser: reading chunk " << tag << ", length = " << len << ", context = " << context << "\n";
|
||||
Chunk *chk = parse_chunk_data(tag, context, it, it+len);
|
||||
if (!chk) os_ << "DEBUG INFO: iffparser: \tprevious chunk not handled\n";
|
||||
it += len;
|
||||
if ((len % 2) != 0) ++it;
|
||||
return chk;
|
||||
}
|
||||
|
||||
IP_TMP const Chunk_list &GenericParser<Iter>::chunks() const
|
||||
{
|
||||
return chunks_;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
623
src/osgPlugins/lwo/lwo2chunks.h
Normal file
623
src/osgPlugins/lwo/lwo2chunks.h
Normal file
@@ -0,0 +1,623 @@
|
||||
|
||||
/****************************************************************************
|
||||
|
||||
Chunk definitions for the LWO2 file format
|
||||
|
||||
Copyright (C) 2002 by Marco Jez
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef LWO2CHUNKS_
|
||||
#define LWO2CHUNKS_
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning ( disable : 4786 )
|
||||
#endif
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "iffparser.h"
|
||||
#include "lwo2types.h"
|
||||
|
||||
#define CHUNK(name) struct name: public iff::Chunk
|
||||
#define SUBCHUNK CHUNK
|
||||
#define FREE_ON_DESTROY(list) iff::Chunk_list *free_on_destroy() { return &list; }
|
||||
|
||||
namespace lwo2
|
||||
{
|
||||
|
||||
typedef iff::Chunk SubChunk;
|
||||
|
||||
CHUNK (FORM) {
|
||||
|
||||
ID4 type;
|
||||
iff::Chunk_list data;
|
||||
|
||||
FREE_ON_DESTROY(data);
|
||||
|
||||
CHUNK (LAYR) {
|
||||
U2 number;
|
||||
U2 flags;
|
||||
VEC12 pivot;
|
||||
S0 name;
|
||||
I2 parent;
|
||||
};
|
||||
|
||||
CHUNK (PNTS) {
|
||||
typedef std::vector<VEC12> Point_list;
|
||||
Point_list point_location;
|
||||
};
|
||||
|
||||
CHUNK (VMAP) {
|
||||
ID4 type;
|
||||
U2 dimension;
|
||||
S0 name;
|
||||
|
||||
struct mapping_type {
|
||||
VX vert;
|
||||
std::vector<F4> value;
|
||||
};
|
||||
|
||||
typedef std::vector<mapping_type> Mapping_list;
|
||||
Mapping_list mapping;
|
||||
};
|
||||
|
||||
CHUNK (POLS) {
|
||||
ID4 type;
|
||||
|
||||
struct polygon_type {
|
||||
U2 numvert;
|
||||
U2 flags;
|
||||
std::vector<VX> vert;
|
||||
};
|
||||
|
||||
typedef std::vector<polygon_type> Polygon_list;
|
||||
Polygon_list polygons;
|
||||
};
|
||||
|
||||
CHUNK (TAGS) {
|
||||
typedef std::vector<S0> String_list;
|
||||
String_list tag_string;
|
||||
};
|
||||
|
||||
CHUNK (PTAG) {
|
||||
ID4 type;
|
||||
|
||||
struct mapping_type {
|
||||
VX poly;
|
||||
U2 tag;
|
||||
};
|
||||
|
||||
typedef std::vector<mapping_type> Mapping_list;
|
||||
Mapping_list mapping;
|
||||
};
|
||||
|
||||
CHUNK (VMAD) {
|
||||
ID4 type;
|
||||
U2 dimension;
|
||||
S0 name;
|
||||
|
||||
struct mapping_type {
|
||||
VX vert;
|
||||
VX poly;
|
||||
std::vector<F4> value;
|
||||
};
|
||||
|
||||
typedef std::vector<mapping_type> Mapping_list;
|
||||
Mapping_list mapping;
|
||||
};
|
||||
|
||||
CHUNK (ENVL) {
|
||||
VX index;
|
||||
iff::Chunk_list attributes;
|
||||
|
||||
FREE_ON_DESTROY(attributes);
|
||||
|
||||
SUBCHUNK (TYPE) {
|
||||
U1 user_format;
|
||||
U1 type;
|
||||
};
|
||||
|
||||
SUBCHUNK (PRE) {
|
||||
U2 type;
|
||||
};
|
||||
|
||||
SUBCHUNK (POST) {
|
||||
U2 type;
|
||||
};
|
||||
|
||||
SUBCHUNK (KEY) {
|
||||
F4 time;
|
||||
F4 value;
|
||||
};
|
||||
|
||||
SUBCHUNK (SPAN) {
|
||||
ID4 type;
|
||||
std::vector<F4> parameters;
|
||||
};
|
||||
|
||||
SUBCHUNK (CHAN) {
|
||||
S0 server_name;
|
||||
U2 flags;
|
||||
std::vector<U1> data;
|
||||
};
|
||||
|
||||
SUBCHUNK (NAME) {
|
||||
S0 channel_name;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
CHUNK (CLIP) {
|
||||
U4 index;
|
||||
iff::Chunk_list attributes;
|
||||
|
||||
FREE_ON_DESTROY(attributes);
|
||||
|
||||
SUBCHUNK (STIL) {
|
||||
FNAM0 name;
|
||||
};
|
||||
|
||||
SUBCHUNK (ISEQ) {
|
||||
U1 num_digits;
|
||||
U1 flags;
|
||||
I2 offset;
|
||||
U2 reserved;
|
||||
I2 start;
|
||||
I2 end;
|
||||
FNAM0 prefix;
|
||||
S0 suffix;
|
||||
};
|
||||
|
||||
SUBCHUNK (ANIM) {
|
||||
FNAM0 filename;
|
||||
S0 server_name;
|
||||
U2 flags;
|
||||
std::vector<U1> data;
|
||||
};
|
||||
|
||||
SUBCHUNK (XREF) {
|
||||
U4 index;
|
||||
S0 string;
|
||||
};
|
||||
|
||||
SUBCHUNK (STCC) {
|
||||
I2 lo;
|
||||
I2 hi;
|
||||
FNAM0 name;
|
||||
};
|
||||
|
||||
SUBCHUNK (TIME) {
|
||||
FP4 start_time;
|
||||
FP4 duration;
|
||||
FP4 frame_rate;
|
||||
};
|
||||
|
||||
SUBCHUNK (CONT) {
|
||||
FP4 contrast_delta;
|
||||
VX envelope;
|
||||
};
|
||||
|
||||
SUBCHUNK (BRIT) {
|
||||
FP4 brightness_delta;
|
||||
VX envelope;
|
||||
};
|
||||
|
||||
SUBCHUNK (SATR) {
|
||||
FP4 saturation_delta;
|
||||
VX envelope;
|
||||
};
|
||||
|
||||
SUBCHUNK (HUE) {
|
||||
FP4 hue_rotation;
|
||||
VX envelope;
|
||||
};
|
||||
|
||||
SUBCHUNK (GAMM) {
|
||||
F4 gamma;
|
||||
VX envelope;
|
||||
};
|
||||
|
||||
SUBCHUNK (NEGA) {
|
||||
U2 enable;
|
||||
};
|
||||
|
||||
SUBCHUNK (IFLT) {
|
||||
S0 server_name;
|
||||
U2 flags;
|
||||
std::vector<U1> data;
|
||||
};
|
||||
|
||||
SUBCHUNK (PFLT) {
|
||||
S0 server_name;
|
||||
U2 flags;
|
||||
std::vector<U1> data;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
CHUNK (SURF) {
|
||||
S0 name;
|
||||
S0 source;
|
||||
iff::Chunk_list attributes;
|
||||
|
||||
FREE_ON_DESTROY(attributes);
|
||||
|
||||
SUBCHUNK (COLR) {
|
||||
COL12 base_color;
|
||||
VX envelope;
|
||||
};
|
||||
|
||||
SUBCHUNK (DIFF) {
|
||||
FP4 intensity;
|
||||
VX envelope;
|
||||
};
|
||||
|
||||
SUBCHUNK (LUMI) {
|
||||
FP4 intensity;
|
||||
VX envelope;
|
||||
};
|
||||
|
||||
SUBCHUNK (SPEC) {
|
||||
FP4 intensity;
|
||||
VX envelope;
|
||||
};
|
||||
|
||||
SUBCHUNK (REFL) {
|
||||
FP4 intensity;
|
||||
VX envelope;
|
||||
};
|
||||
|
||||
SUBCHUNK (TRAN) {
|
||||
FP4 intensity;
|
||||
VX envelope;
|
||||
};
|
||||
|
||||
SUBCHUNK (TRNL) {
|
||||
FP4 intensity;
|
||||
VX envelope;
|
||||
};
|
||||
|
||||
SUBCHUNK (GLOS) {
|
||||
FP4 glossiness;
|
||||
VX envelope;
|
||||
};
|
||||
|
||||
SUBCHUNK (SHRP) {
|
||||
FP4 sharpness;
|
||||
VX envelope;
|
||||
};
|
||||
|
||||
SUBCHUNK (BUMP) {
|
||||
FP4 strength;
|
||||
VX envelope;
|
||||
};
|
||||
|
||||
SUBCHUNK (SIDE) {
|
||||
U2 sidedness;
|
||||
};
|
||||
|
||||
SUBCHUNK (SMAN) {
|
||||
ANG4 max_smoothing_angle;
|
||||
};
|
||||
|
||||
SUBCHUNK (RFOP) {
|
||||
U2 reflection_options;
|
||||
};
|
||||
|
||||
SUBCHUNK (RIMG) {
|
||||
VX image;
|
||||
};
|
||||
|
||||
SUBCHUNK (RSAN) {
|
||||
ANG4 seam_angle;
|
||||
VX envelope;
|
||||
};
|
||||
|
||||
SUBCHUNK (RBLR) {
|
||||
FP4 blur_percentage;
|
||||
VX envelope;
|
||||
};
|
||||
|
||||
SUBCHUNK (RIND) {
|
||||
F4 refractive_index;
|
||||
VX envelope;
|
||||
};
|
||||
|
||||
SUBCHUNK (TROP) {
|
||||
U2 transparency_options;
|
||||
};
|
||||
|
||||
SUBCHUNK (TIMG) {
|
||||
VX image;
|
||||
};
|
||||
|
||||
SUBCHUNK (TBLR) {
|
||||
FP4 blur_percentage;
|
||||
VX envelope;
|
||||
};
|
||||
|
||||
SUBCHUNK (CLRH) {
|
||||
FP4 color_highlights;
|
||||
VX envelope;
|
||||
};
|
||||
|
||||
SUBCHUNK (CLRF) {
|
||||
FP4 color_filter;
|
||||
VX envelope;
|
||||
};
|
||||
|
||||
SUBCHUNK (ADTR) {
|
||||
FP4 additive;
|
||||
VX envelope;
|
||||
};
|
||||
|
||||
SUBCHUNK (GLOW) {
|
||||
U2 type;
|
||||
F4 intensity;
|
||||
VX intensity_envelope;
|
||||
F4 size;
|
||||
VX size_envelope;
|
||||
};
|
||||
|
||||
SUBCHUNK (LINE) {
|
||||
U2 flags;
|
||||
F4 size;
|
||||
VX size_envelope;
|
||||
COL12 color;
|
||||
VX color_envelope;
|
||||
};
|
||||
|
||||
SUBCHUNK (ALPH) {
|
||||
U2 mode;
|
||||
FP4 value;
|
||||
};
|
||||
|
||||
SUBCHUNK (VCOL) {
|
||||
FP4 intensity;
|
||||
VX envelope;
|
||||
ID4 vmap_type;
|
||||
S0 name;
|
||||
};
|
||||
|
||||
// surface blocks
|
||||
|
||||
SUBCHUNK (BLOK) {
|
||||
SubChunk *header;
|
||||
iff::Chunk_list attributes;
|
||||
|
||||
FREE_ON_DESTROY(attributes);
|
||||
|
||||
// block headers
|
||||
|
||||
SUBCHUNK (IMAP) {
|
||||
S0 ordinal;
|
||||
iff::Chunk_list block_attributes; // common attributes (see above)
|
||||
|
||||
FREE_ON_DESTROY(block_attributes);
|
||||
|
||||
// attributes specific to IMAP and PROC
|
||||
|
||||
SUBCHUNK (TMAP) {
|
||||
iff::Chunk_list attributes;
|
||||
|
||||
FREE_ON_DESTROY(attributes);
|
||||
|
||||
SUBCHUNK (CNTR) {
|
||||
VEC12 vector;
|
||||
VX envelope;
|
||||
};
|
||||
|
||||
SUBCHUNK (SIZE) {
|
||||
VEC12 vector;
|
||||
VX envelope;
|
||||
};
|
||||
|
||||
SUBCHUNK (ROTA) {
|
||||
VEC12 vector;
|
||||
VX envelope;
|
||||
};
|
||||
|
||||
SUBCHUNK (OREF) {
|
||||
S0 object_name;
|
||||
};
|
||||
|
||||
SUBCHUNK (FALL) {
|
||||
U2 type;
|
||||
VEC12 vector;
|
||||
VX envelope;
|
||||
};
|
||||
|
||||
SUBCHUNK (CSYS) {
|
||||
U2 type;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
// attributes specific to image maps
|
||||
|
||||
SUBCHUNK (PROJ) {
|
||||
U2 projection_mode;
|
||||
};
|
||||
|
||||
SUBCHUNK (AXIS) {
|
||||
U2 texture_axis;
|
||||
};
|
||||
|
||||
SUBCHUNK (IMAG) {
|
||||
VX texture_image;
|
||||
};
|
||||
|
||||
SUBCHUNK (WRAP) {
|
||||
U2 width_wrap;
|
||||
U2 height_wrap;
|
||||
};
|
||||
|
||||
SUBCHUNK (WRPW) {
|
||||
FP4 cycles;
|
||||
VX envelope;
|
||||
};
|
||||
|
||||
SUBCHUNK (WRPH) {
|
||||
FP4 cycles;
|
||||
VX envelope;
|
||||
};
|
||||
|
||||
SUBCHUNK (VMAP) {
|
||||
S0 txuv_map_name;
|
||||
};
|
||||
|
||||
SUBCHUNK (AAST) {
|
||||
U2 flags;
|
||||
FP4 antialiasing_strength;
|
||||
};
|
||||
|
||||
SUBCHUNK (PIXB) {
|
||||
U2 flags;
|
||||
};
|
||||
|
||||
SUBCHUNK (STCK) {
|
||||
U2 on_off;
|
||||
FP4 time;
|
||||
};
|
||||
|
||||
SUBCHUNK (TAMP) {
|
||||
FP4 amplitude;
|
||||
VX envelope;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
SUBCHUNK (PROC) {
|
||||
S0 ordinal;
|
||||
iff::Chunk_list block_attributes;
|
||||
|
||||
FREE_ON_DESTROY(block_attributes);
|
||||
|
||||
typedef IMAP::TMAP TMAP;
|
||||
|
||||
// attributes specific to procedural textures
|
||||
|
||||
SUBCHUNK (AXIS) {
|
||||
U2 axis;
|
||||
};
|
||||
|
||||
SUBCHUNK (VALU) {
|
||||
std::vector<FP4> value;
|
||||
};
|
||||
|
||||
SUBCHUNK (FUNC) {
|
||||
S0 algorithm_name;
|
||||
std::vector<U1> data;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
SUBCHUNK (GRAD) {
|
||||
S0 ordinal;
|
||||
iff::Chunk_list block_attributes;
|
||||
|
||||
FREE_ON_DESTROY(block_attributes);
|
||||
|
||||
// attributes specific to gradient textures
|
||||
|
||||
SUBCHUNK (PNAM) {
|
||||
S0 parameter;
|
||||
};
|
||||
|
||||
SUBCHUNK (INAM) {
|
||||
S0 item_name;
|
||||
};
|
||||
|
||||
SUBCHUNK (GRST) {
|
||||
FP4 input_range;
|
||||
};
|
||||
|
||||
SUBCHUNK (GREN) {
|
||||
FP4 input_range;
|
||||
};
|
||||
|
||||
SUBCHUNK (GRPT) {
|
||||
U2 repeat_mode;
|
||||
};
|
||||
|
||||
SUBCHUNK (FKEY) {
|
||||
struct value_type {
|
||||
FP4 input;
|
||||
FP4 output[4];
|
||||
};
|
||||
|
||||
typedef std::vector<value_type> Value_list;
|
||||
Value_list values;
|
||||
};
|
||||
|
||||
SUBCHUNK (IKEY) {
|
||||
std::vector<U2> interpolation;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
SUBCHUNK (SHDR) {
|
||||
S0 ordinal;
|
||||
iff::Chunk_list block_attributes;
|
||||
|
||||
FREE_ON_DESTROY(block_attributes);
|
||||
|
||||
// attributes specific to shaders
|
||||
|
||||
SUBCHUNK (FUNC) {
|
||||
S0 algorithm_name;
|
||||
std::vector<U1> data;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
// attributes common to all header types
|
||||
|
||||
SUBCHUNK (CHAN) {
|
||||
ID4 texture_channel;
|
||||
};
|
||||
|
||||
SUBCHUNK (ENAB) {
|
||||
U2 enable;
|
||||
};
|
||||
|
||||
SUBCHUNK (OPAC) {
|
||||
U2 type;
|
||||
FP4 opacity;
|
||||
VX envelope;
|
||||
};
|
||||
|
||||
SUBCHUNK (AXIS) {
|
||||
U2 displacement_axis;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
CHUNK (BBOX) {
|
||||
VEC12 min;
|
||||
VEC12 max;
|
||||
};
|
||||
|
||||
CHUNK (DESC) {
|
||||
S0 description_line;
|
||||
};
|
||||
|
||||
CHUNK (TEXT) {
|
||||
S0 comment;
|
||||
};
|
||||
|
||||
CHUNK (ICON) {
|
||||
U2 encoding;
|
||||
U2 width;
|
||||
std::vector<U1> data;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
908
src/osgPlugins/lwo/lwo2parser.h
Normal file
908
src/osgPlugins/lwo/lwo2parser.h
Normal file
@@ -0,0 +1,908 @@
|
||||
/*******************************************************
|
||||
Lightwave Object Loader for OSG
|
||||
|
||||
Copyright (C) 2004 Marco Jez <marco.jez@poste.it>
|
||||
OpenSceneGraph is (C) 2004 Robert Osfield
|
||||
********************************************************/
|
||||
|
||||
#ifndef LWO2PARSER_
|
||||
#define LWO2PARSER_
|
||||
|
||||
#include "iffparser.h"
|
||||
#include "lwo2chunks.h"
|
||||
#include "lwo2read.h"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
|
||||
namespace lwo2
|
||||
{
|
||||
|
||||
class parser_error: public std::runtime_error {
|
||||
public:
|
||||
parser_error(const std::string &message): std::runtime_error("[LWO2 parser error] " + message) {}
|
||||
};
|
||||
|
||||
template<typename Iter>
|
||||
class Parser: public iff::GenericParser<Iter> {
|
||||
public:
|
||||
Parser();
|
||||
Parser(std::ostream &os);
|
||||
|
||||
virtual ~Parser();
|
||||
|
||||
protected:
|
||||
virtual iff::Chunk *parse_chunk_data(const std::string &tag, const std::string &context, Iter it, Iter end);
|
||||
iff::Chunk *parse_subchunk(Iter &it, const std::string &context);
|
||||
};
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// IMPLEMENTATION OF TEMPLATE FUNCTIONS
|
||||
|
||||
# define LP_TMP template<class Iter>
|
||||
|
||||
LP_TMP Parser<Iter>::Parser()
|
||||
: iff::GenericParser<Iter>()
|
||||
{
|
||||
}
|
||||
|
||||
LP_TMP Parser<Iter>::Parser(std::ostream &os)
|
||||
: iff::GenericParser<Iter>(os)
|
||||
{
|
||||
}
|
||||
|
||||
LP_TMP Parser<Iter>::~Parser()
|
||||
{
|
||||
}
|
||||
|
||||
LP_TMP iff::Chunk *Parser<Iter>::parse_chunk_data(const std::string &tag, const std::string &context, Iter it, Iter end)
|
||||
{
|
||||
// GLOBAL CONTEXT
|
||||
if (context.empty()) {
|
||||
if (tag == "FORM") {
|
||||
FORM *chk = new FORM;
|
||||
chk->type = read_ID4(it);
|
||||
if (std::string(chk->type.id, 4) != "LWO2") {
|
||||
throw parser_error("invalid file format");
|
||||
}
|
||||
while (it < end)
|
||||
chk->data.push_back(parse_chunk(it, "FORM"));
|
||||
return chk;
|
||||
}
|
||||
}
|
||||
|
||||
// FORM CONTEXT
|
||||
if (context == "FORM") {
|
||||
|
||||
if (tag == "LAYR") {
|
||||
FORM::LAYR *chk = new FORM::LAYR;
|
||||
chk->number = read_U2(it);
|
||||
chk->flags = read_U2(it);
|
||||
chk->pivot = read_VEC12(it);
|
||||
chk->name = read_S0(it);
|
||||
if (it < end) {
|
||||
chk->parent = read_I2(it);
|
||||
} else {
|
||||
chk->parent = -1;
|
||||
}
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "PNTS") {
|
||||
FORM::PNTS *chk = new FORM::PNTS;
|
||||
while (it < end) {
|
||||
chk->point_location.push_back(read_VEC12(it));
|
||||
}
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "VMAP") {
|
||||
FORM::VMAP *chk = new FORM::VMAP;
|
||||
chk->type = read_ID4(it);
|
||||
chk->dimension = read_U2(it);
|
||||
chk->name = read_S0(it);
|
||||
while (it < end) {
|
||||
FORM::VMAP::mapping_type mp;
|
||||
mp.vert = read_VX(it);
|
||||
for (int i=0; i<chk->dimension; ++i) {
|
||||
mp.value.push_back(read_F4(it));
|
||||
}
|
||||
chk->mapping.push_back(mp);
|
||||
}
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "POLS") {
|
||||
FORM::POLS *chk = new FORM::POLS;
|
||||
chk->type = read_ID4(it);
|
||||
while (it < end) {
|
||||
FORM::POLS::polygon_type pl;
|
||||
U2 nvf = read_U2(it);
|
||||
pl.flags = nvf >> 10;
|
||||
pl.numvert = nvf & 0x03FF;
|
||||
for (int i=0; i<pl.numvert; ++i)
|
||||
pl.vert.push_back(read_VX(it));
|
||||
chk->polygons.push_back(pl);
|
||||
}
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "TAGS") {
|
||||
FORM::TAGS *chk = new FORM::TAGS;
|
||||
while (it < end) {
|
||||
std::string tags = read_S0(it);
|
||||
chk->tag_string.push_back(tags);
|
||||
}
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "PTAG") {
|
||||
FORM::PTAG *chk = new FORM::PTAG;
|
||||
chk->type = read_ID4(it);
|
||||
while (it < end) {
|
||||
FORM::PTAG::mapping_type mp;
|
||||
mp.poly = read_VX(it);
|
||||
mp.tag = read_U2(it);
|
||||
chk->mapping.push_back(mp);
|
||||
}
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "VMAD") {
|
||||
FORM::VMAD *chk = new FORM::VMAD;
|
||||
chk->type = read_ID4(it);
|
||||
chk->dimension = read_U2(it);
|
||||
chk->name = read_S0(it);
|
||||
while (it < end) {
|
||||
FORM::VMAD::mapping_type mp;
|
||||
mp.vert = read_VX(it);
|
||||
mp.poly = read_VX(it);
|
||||
for (int i=0; i<chk->dimension; ++i)
|
||||
mp.value.push_back(read_F4(it));
|
||||
chk->mapping.push_back(mp);
|
||||
}
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "ENVL") {
|
||||
FORM::ENVL *chk = new FORM::ENVL;
|
||||
chk->index = read_VX(it);
|
||||
while (it < end) {
|
||||
chk->attributes.push_back(parse_subchunk(it, "FORM::ENVL"));
|
||||
}
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "CLIP") {
|
||||
FORM::CLIP *chk = new FORM::CLIP;
|
||||
chk->index = read_U4(it);
|
||||
while (it < end) {
|
||||
chk->attributes.push_back(parse_subchunk(it, "FORM::CLIP"));
|
||||
}
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "SURF") {
|
||||
FORM::SURF *chk = new FORM::SURF;
|
||||
chk->name = read_S0(it);
|
||||
chk->source = read_S0(it);
|
||||
while (it < end) {
|
||||
chk->attributes.push_back(parse_subchunk(it, "FORM::SURF"));
|
||||
}
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "BBOX") {
|
||||
FORM::BBOX *chk = new FORM::BBOX;
|
||||
chk->min = read_VEC12(it);
|
||||
chk->max = read_VEC12(it);
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "DESC") {
|
||||
FORM::DESC *chk = new FORM::DESC;
|
||||
chk->description_line = read_S0(it);
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "TEXT") {
|
||||
FORM::TEXT *chk = new FORM::TEXT;
|
||||
chk->comment = read_S0(it);
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "ICON") {
|
||||
FORM::ICON *chk = new FORM::ICON;
|
||||
chk->encoding = read_U2(it);
|
||||
chk->width = read_U2(it);
|
||||
while (it < end) chk->data.push_back(read_U1(it));
|
||||
return chk;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// ENVELOPE CONTEXT
|
||||
if (context == "FORM::ENVL") {
|
||||
|
||||
if (tag == "TYPE") {
|
||||
FORM::ENVL::TYPE *chk = new FORM::ENVL::TYPE;
|
||||
chk->user_format = read_U1(it);
|
||||
chk->type = read_U1(it);
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "PRE ") {
|
||||
FORM::ENVL::PRE *chk = new FORM::ENVL::PRE;
|
||||
chk->type = read_U2(it);
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "POST") {
|
||||
FORM::ENVL::POST *chk = new FORM::ENVL::POST;
|
||||
chk->type = read_U2(it);
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "KEY ") {
|
||||
FORM::ENVL::KEY *chk = new FORM::ENVL::KEY;
|
||||
chk->time = read_F4(it);
|
||||
chk->value = read_F4(it);
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "SPAN") {
|
||||
FORM::ENVL::SPAN *chk = new FORM::ENVL::SPAN;
|
||||
chk->type = read_ID4(it);
|
||||
while (it < end) chk->parameters.push_back(read_F4(it));
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "CHAN") {
|
||||
FORM::ENVL::CHAN *chk = new FORM::ENVL::CHAN;
|
||||
chk->server_name = read_S0(it);
|
||||
chk->flags = read_U2(it);
|
||||
while (it < end) chk->data.push_back(read_U1(it));
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "NAME") {
|
||||
FORM::ENVL::NAME *chk = new FORM::ENVL::NAME;
|
||||
chk->channel_name = read_S0(it);
|
||||
return chk;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// CLIP CONTEXT
|
||||
if (context == "FORM::CLIP") {
|
||||
|
||||
if (tag == "STIL") {
|
||||
FORM::CLIP::STIL *chk = new FORM::CLIP::STIL;
|
||||
chk->name = read_FNAM0(it);
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "ISEQ") {
|
||||
FORM::CLIP::ISEQ *chk = new FORM::CLIP::ISEQ;
|
||||
chk->num_digits = read_U1(it);
|
||||
chk->flags = read_U1(it);
|
||||
chk->offset = read_I2(it);
|
||||
chk->reserved = read_U2(it);
|
||||
chk->start = read_I2(it);
|
||||
chk->end = read_I2(it);
|
||||
chk->prefix = read_FNAM0(it);
|
||||
chk->suffix = read_S0(it);
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "ANIM") {
|
||||
FORM::CLIP::ANIM *chk = new FORM::CLIP::ANIM;
|
||||
chk->filename = read_FNAM0(it);
|
||||
chk->server_name = read_S0(it);
|
||||
chk->flags = read_U2(it);
|
||||
while (it < end) chk->data.push_back(read_U1(it));
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "XREF") {
|
||||
FORM::CLIP::XREF *chk = new FORM::CLIP::XREF;
|
||||
chk->index = read_U4(it);
|
||||
chk->string = read_S0(it);
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "STCC") {
|
||||
FORM::CLIP::STCC *chk = new FORM::CLIP::STCC;
|
||||
chk->lo = read_I2(it);
|
||||
chk->hi = read_I2(it);
|
||||
chk->name = read_FNAM0(it);
|
||||
}
|
||||
|
||||
if (tag == "TIME") {
|
||||
FORM::CLIP::TIME *chk = new FORM::CLIP::TIME;
|
||||
chk->start_time = read_FP4(it);
|
||||
chk->duration = read_FP4(it);
|
||||
chk->frame_rate = read_FP4(it);
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "CONT") {
|
||||
FORM::CLIP::CONT *chk = new FORM::CLIP::CONT;
|
||||
chk->contrast_delta = read_FP4(it);
|
||||
chk->envelope = read_VX(it);
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "BRIT") {
|
||||
FORM::CLIP::BRIT *chk = new FORM::CLIP::BRIT;
|
||||
chk->brightness_delta = read_FP4(it);
|
||||
chk->envelope = read_VX(it);
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "SATR") {
|
||||
FORM::CLIP::SATR *chk = new FORM::CLIP::SATR;
|
||||
chk->saturation_delta = read_FP4(it);
|
||||
chk->envelope = read_VX(it);
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "HUE ") {
|
||||
FORM::CLIP::HUE *chk = new FORM::CLIP::HUE;
|
||||
chk->hue_rotation = read_FP4(it);
|
||||
chk->envelope = read_VX(it);
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "GAMM") {
|
||||
FORM::CLIP::GAMM *chk = new FORM::CLIP::GAMM;
|
||||
chk->gamma = read_F4(it);
|
||||
chk->envelope = read_VX(it);
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "NEGA") {
|
||||
FORM::CLIP::NEGA *chk = new FORM::CLIP::NEGA;
|
||||
chk->enable = read_U2(it);
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "IFLT") {
|
||||
FORM::CLIP::IFLT *chk = new FORM::CLIP::IFLT;
|
||||
chk->server_name = read_S0(it);
|
||||
chk->flags = read_U2(it);
|
||||
while (it < end) chk->data.push_back(read_U1(it));
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "PFLT") {
|
||||
FORM::CLIP::PFLT *chk = new FORM::CLIP::PFLT;
|
||||
chk->server_name = read_S0(it);
|
||||
chk->flags = read_U2(it);
|
||||
while (it < end) chk->data.push_back(read_U1(it));
|
||||
return chk;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// SURFACE CONTEXT
|
||||
if (context == "FORM::SURF") {
|
||||
|
||||
if (tag == "COLR") {
|
||||
FORM::SURF::COLR *chk = new FORM::SURF::COLR;
|
||||
chk->base_color = read_COL12(it);
|
||||
chk->envelope = read_VX(it);
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "DIFF") {
|
||||
FORM::SURF::DIFF *chk = new FORM::SURF::DIFF;
|
||||
chk->intensity = read_FP4(it);
|
||||
chk->envelope = read_VX(it);
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "LUMI") {
|
||||
FORM::SURF::LUMI *chk = new FORM::SURF::LUMI;
|
||||
chk->intensity = read_FP4(it);
|
||||
chk->envelope = read_VX(it);
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "SPEC") {
|
||||
FORM::SURF::SPEC *chk = new FORM::SURF::SPEC;
|
||||
chk->intensity = read_FP4(it);
|
||||
chk->envelope = read_VX(it);
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "REFL") {
|
||||
FORM::SURF::REFL *chk = new FORM::SURF::REFL;
|
||||
chk->intensity = read_FP4(it);
|
||||
chk->envelope = read_VX(it);
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "TRAN") {
|
||||
FORM::SURF::TRAN *chk = new FORM::SURF::TRAN;
|
||||
chk->intensity = read_FP4(it);
|
||||
chk->envelope = read_VX(it);
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "TRNL") {
|
||||
FORM::SURF::TRNL *chk = new FORM::SURF::TRNL;
|
||||
chk->intensity = read_FP4(it);
|
||||
chk->envelope = read_VX(it);
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "GLOS") {
|
||||
FORM::SURF::GLOS *chk = new FORM::SURF::GLOS;
|
||||
chk->glossiness = read_FP4(it);
|
||||
chk->envelope = read_VX(it);
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "SHRP") {
|
||||
FORM::SURF::SHRP *chk = new FORM::SURF::SHRP;
|
||||
chk->sharpness = read_FP4(it);
|
||||
chk->envelope = read_VX(it);
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "BUMP") {
|
||||
FORM::SURF::BUMP *chk = new FORM::SURF::BUMP;
|
||||
chk->strength = read_FP4(it);
|
||||
chk->envelope = read_VX(it);
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "SIDE") {
|
||||
FORM::SURF::SIDE *chk = new FORM::SURF::SIDE;
|
||||
chk->sidedness = read_U2(it);
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "SMAN") {
|
||||
FORM::SURF::SMAN *chk = new FORM::SURF::SMAN;
|
||||
chk->max_smoothing_angle = read_ANG4(it);
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "RFOP") {
|
||||
FORM::SURF::RFOP *chk = new FORM::SURF::RFOP;
|
||||
chk->reflection_options = read_U2(it);
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "RIMG") {
|
||||
FORM::SURF::RIMG *chk = new FORM::SURF::RIMG;
|
||||
chk->image = read_VX(it);
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "RSAN") {
|
||||
FORM::SURF::RSAN *chk = new FORM::SURF::RSAN;
|
||||
chk->seam_angle = read_ANG4(it);
|
||||
chk->envelope = read_VX(it);
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "RBLR") {
|
||||
FORM::SURF::RBLR *chk = new FORM::SURF::RBLR;
|
||||
chk->blur_percentage = read_FP4(it);
|
||||
chk->envelope = read_VX(it);
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "RIND") {
|
||||
FORM::SURF::RIND *chk = new FORM::SURF::RIND;
|
||||
chk->refractive_index = read_F4(it);
|
||||
chk->envelope = read_VX(it);
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "TROP") {
|
||||
FORM::SURF::TROP *chk = new FORM::SURF::TROP;
|
||||
chk->transparency_options = read_U2(it);
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "TIMG") {
|
||||
FORM::SURF::TIMG *chk = new FORM::SURF::TIMG;
|
||||
chk->image = read_VX(it);
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "TBLR") {
|
||||
FORM::SURF::TBLR *chk = new FORM::SURF::TBLR;
|
||||
chk->blur_percentage = read_FP4(it);
|
||||
chk->envelope = read_VX(it);
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "CLRH") {
|
||||
FORM::SURF::CLRH *chk = new FORM::SURF::CLRH;
|
||||
chk->color_highlights = read_FP4(it);
|
||||
chk->envelope = read_VX(it);
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "CLRF") {
|
||||
FORM::SURF::CLRF *chk = new FORM::SURF::CLRF;
|
||||
chk->color_filter = read_FP4(it);
|
||||
chk->envelope = read_VX(it);
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "ADTR") {
|
||||
FORM::SURF::ADTR *chk = new FORM::SURF::ADTR;
|
||||
chk->additive = read_FP4(it);
|
||||
chk->envelope = read_VX(it);
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "GLOW") {
|
||||
FORM::SURF::GLOW *chk = new FORM::SURF::GLOW;
|
||||
chk->type = read_U2(it);
|
||||
chk->intensity = read_F4(it);
|
||||
chk->intensity_envelope = read_VX(it);
|
||||
chk->size = read_F4(it);
|
||||
chk->size_envelope = read_VX(it);
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "LINE") {
|
||||
FORM::SURF::LINE *chk = new FORM::SURF::LINE;
|
||||
chk->flags = read_U2(it);
|
||||
if (it < end) {
|
||||
chk->size = read_F4(it);
|
||||
chk->size_envelope = read_VX(it);
|
||||
if (it < end) {
|
||||
chk->color = read_COL12(it);
|
||||
chk->color_envelope = read_VX(it);
|
||||
}
|
||||
}
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "ALPH") {
|
||||
FORM::SURF::ALPH *chk = new FORM::SURF::ALPH;
|
||||
chk->mode = read_U2(it);
|
||||
chk->value = read_FP4(it);
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "VCOL") {
|
||||
FORM::SURF::VCOL *chk = new FORM::SURF::VCOL;
|
||||
chk->intensity = read_FP4(it);
|
||||
chk->envelope = read_VX(it);
|
||||
chk->vmap_type = read_ID4(it);
|
||||
chk->name = read_S0(it);
|
||||
return chk;
|
||||
}
|
||||
|
||||
// surface blocks
|
||||
|
||||
if (tag == "BLOK") {
|
||||
FORM::SURF::BLOK *chk = new FORM::SURF::BLOK;
|
||||
std::string hid;
|
||||
for (Iter tempit=it; tempit<(it+4); ++tempit) hid.push_back(*tempit);
|
||||
chk->header = parse_subchunk(it, "FORM::SURF::BLOK");
|
||||
while (it < end) {
|
||||
chk->attributes.push_back(parse_subchunk(it, "FORM::SURF::BLOK::" + hid));
|
||||
}
|
||||
return chk;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (context == "FORM::SURF::BLOK") { // block headers
|
||||
|
||||
if (tag == "IMAP") {
|
||||
FORM::SURF::BLOK::IMAP *chk = new FORM::SURF::BLOK::IMAP;
|
||||
chk->ordinal = read_S0(it);
|
||||
while (it < end) {
|
||||
chk->block_attributes.push_back(parse_subchunk(it, "FORM::SURF::BLOK"));
|
||||
}
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "PROC") {
|
||||
FORM::SURF::BLOK::PROC *chk = new FORM::SURF::BLOK::PROC;
|
||||
chk->ordinal = read_S0(it);
|
||||
while (it < end) {
|
||||
chk->block_attributes.push_back(parse_subchunk(it, "FORM::SURF::BLOK"));
|
||||
}
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "GRAD") {
|
||||
FORM::SURF::BLOK::GRAD *chk = new FORM::SURF::BLOK::GRAD;
|
||||
chk->ordinal = read_S0(it);
|
||||
while (it < end) {
|
||||
chk->block_attributes.push_back(parse_subchunk(it, "FORM::SURF::BLOK"));
|
||||
}
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "SHDR") {
|
||||
FORM::SURF::BLOK::SHDR *chk = new FORM::SURF::BLOK::SHDR;
|
||||
chk->ordinal = read_S0(it);
|
||||
while (it < end) {
|
||||
chk->block_attributes.push_back(parse_subchunk(it, "FORM::SURF::BLOK"));
|
||||
}
|
||||
return chk;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (context == "FORM::SURF::BLOK") { // attributes common to all block headers
|
||||
|
||||
if (tag == "CHAN") {
|
||||
FORM::SURF::BLOK::CHAN *chk = new FORM::SURF::BLOK::CHAN;
|
||||
chk->texture_channel = read_ID4(it);
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "ENAB") {
|
||||
FORM::SURF::BLOK::ENAB *chk = new FORM::SURF::BLOK::ENAB;
|
||||
chk->enable = read_U2(it);
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "OPAC") {
|
||||
FORM::SURF::BLOK::OPAC *chk = new FORM::SURF::BLOK::OPAC;
|
||||
chk->type = read_U2(it);
|
||||
chk->opacity = read_FP4(it);
|
||||
chk->envelope = read_VX(it);
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "AXIS") {
|
||||
FORM::SURF::BLOK::AXIS *chk = new FORM::SURF::BLOK::AXIS;
|
||||
chk->displacement_axis = read_U2(it);
|
||||
return chk;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (context == "FORM::SURF::BLOK::IMAP" || context == "FORM::SURF::BLOK::PROC") {
|
||||
|
||||
if (tag == "TMAP") {
|
||||
FORM::SURF::BLOK::IMAP::TMAP *chk = new FORM::SURF::BLOK::IMAP::TMAP;
|
||||
while (it < end) chk->attributes.push_back(parse_subchunk(it, "FORM::SURF::BLOK::IMAP/PROC::TMAP"));
|
||||
return chk;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (context == "FORM::SURF::BLOK::IMAP/PROC::TMAP") {
|
||||
|
||||
if (tag == "CNTR") {
|
||||
FORM::SURF::BLOK::IMAP::TMAP::CNTR *chk = new FORM::SURF::BLOK::IMAP::TMAP::CNTR;
|
||||
chk->vector = read_VEC12(it);
|
||||
chk->envelope = read_VX(it);
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "SIZE") {
|
||||
FORM::SURF::BLOK::IMAP::TMAP::SIZE *chk = new FORM::SURF::BLOK::IMAP::TMAP::SIZE;
|
||||
chk->vector = read_VEC12(it);
|
||||
chk->envelope = read_VX(it);
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "ROTA") {
|
||||
FORM::SURF::BLOK::IMAP::TMAP::ROTA *chk = new FORM::SURF::BLOK::IMAP::TMAP::ROTA;
|
||||
chk->vector = read_VEC12(it);
|
||||
chk->envelope = read_VX(it);
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "OREF") {
|
||||
FORM::SURF::BLOK::IMAP::TMAP::OREF *chk = new FORM::SURF::BLOK::IMAP::TMAP::OREF;
|
||||
chk->object_name = read_S0(it);
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "FALL") {
|
||||
FORM::SURF::BLOK::IMAP::TMAP::FALL *chk = new FORM::SURF::BLOK::IMAP::TMAP::FALL;
|
||||
chk->type = read_U2(it);
|
||||
chk->vector = read_VEC12(it);
|
||||
chk->envelope = read_VX(it);
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "CSYS") {
|
||||
FORM::SURF::BLOK::IMAP::TMAP::CSYS *chk = new FORM::SURF::BLOK::IMAP::TMAP::CSYS;
|
||||
chk->type = read_U2(it);
|
||||
return chk;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (context == "FORM::SURF::BLOK::IMAP") {
|
||||
|
||||
if (tag == "PROJ") {
|
||||
FORM::SURF::BLOK::IMAP::PROJ *chk = new FORM::SURF::BLOK::IMAP::PROJ;
|
||||
chk->projection_mode = read_U2(it);
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "AXIS") {
|
||||
FORM::SURF::BLOK::IMAP::AXIS *chk = new FORM::SURF::BLOK::IMAP::AXIS;
|
||||
chk->texture_axis = read_U2(it);
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "IMAG") {
|
||||
FORM::SURF::BLOK::IMAP::IMAG *chk = new FORM::SURF::BLOK::IMAP::IMAG;
|
||||
chk->texture_image = read_VX(it);
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "WRAP") {
|
||||
FORM::SURF::BLOK::IMAP::WRAP *chk = new FORM::SURF::BLOK::IMAP::WRAP;
|
||||
chk->width_wrap = read_U2(it);
|
||||
chk->height_wrap = read_U2(it);
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "WRPW") {
|
||||
FORM::SURF::BLOK::IMAP::WRPW *chk = new FORM::SURF::BLOK::IMAP::WRPW;
|
||||
chk->cycles = read_FP4(it);
|
||||
chk->envelope = read_VX(it);
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "WRPH") {
|
||||
FORM::SURF::BLOK::IMAP::WRPH *chk = new FORM::SURF::BLOK::IMAP::WRPH;
|
||||
chk->cycles = read_FP4(it);
|
||||
chk->envelope = read_VX(it);
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "VMAP") {
|
||||
FORM::SURF::BLOK::IMAP::VMAP *chk = new FORM::SURF::BLOK::IMAP::VMAP;
|
||||
chk->txuv_map_name = read_S0(it);
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "AAST") {
|
||||
FORM::SURF::BLOK::IMAP::AAST *chk = new FORM::SURF::BLOK::IMAP::AAST;
|
||||
chk->flags = read_U2(it);
|
||||
chk->antialiasing_strength = read_FP4(it);
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "PIXB") {
|
||||
FORM::SURF::BLOK::IMAP::PIXB *chk = new FORM::SURF::BLOK::IMAP::PIXB;
|
||||
chk->flags = read_U2(it);
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "STCK") {
|
||||
FORM::SURF::BLOK::IMAP::STCK *chk = new FORM::SURF::BLOK::IMAP::STCK;
|
||||
chk->on_off = read_U2(it);
|
||||
chk->time = read_FP4(it);
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "TAMP") {
|
||||
FORM::SURF::BLOK::IMAP::TAMP *chk = new FORM::SURF::BLOK::IMAP::TAMP;
|
||||
chk->amplitude = read_FP4(it);
|
||||
chk->envelope = read_VX(it);
|
||||
return chk;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (context == "FORM::SURF::BLOK::PROC") {
|
||||
|
||||
if (tag == "AXIS") {
|
||||
FORM::SURF::BLOK::PROC::AXIS *chk = new FORM::SURF::BLOK::PROC::AXIS;
|
||||
chk->axis = read_U2(it);
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "VALU") {
|
||||
FORM::SURF::BLOK::PROC::VALU *chk = new FORM::SURF::BLOK::PROC::VALU;
|
||||
while (it < end) chk->value.push_back(read_FP4(it));
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "FUNC") {
|
||||
FORM::SURF::BLOK::PROC::FUNC *chk = new FORM::SURF::BLOK::PROC::FUNC;
|
||||
chk->algorithm_name = read_S0(it);
|
||||
while (it < end) chk->data.push_back(read_U1(it));
|
||||
return chk;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (context == "FORM::SURF::BLOK::GRAD") {
|
||||
|
||||
if (tag == "PNAM") {
|
||||
FORM::SURF::BLOK::GRAD::PNAM *chk = new FORM::SURF::BLOK::GRAD::PNAM;
|
||||
chk->parameter = read_S0(it);
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "INAM") {
|
||||
FORM::SURF::BLOK::GRAD::INAM *chk = new FORM::SURF::BLOK::GRAD::INAM;
|
||||
chk->item_name = read_S0(it);
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "GRST") {
|
||||
FORM::SURF::BLOK::GRAD::GRST *chk = new FORM::SURF::BLOK::GRAD::GRST;
|
||||
chk->input_range = read_FP4(it);
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "GREN") {
|
||||
FORM::SURF::BLOK::GRAD::GREN *chk = new FORM::SURF::BLOK::GRAD::GREN;
|
||||
chk->input_range = read_FP4(it);
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "GRPT") {
|
||||
FORM::SURF::BLOK::GRAD::GRPT *chk = new FORM::SURF::BLOK::GRAD::GRPT;
|
||||
chk->repeat_mode = read_U2(it);
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "FKEY") {
|
||||
FORM::SURF::BLOK::GRAD::FKEY *chk = new FORM::SURF::BLOK::GRAD::FKEY;
|
||||
while (it < end) {
|
||||
FORM::SURF::BLOK::GRAD::FKEY::value_type val;
|
||||
val.input = read_FP4(it);
|
||||
for (int i=0; i<4; ++i) val.output[i] = read_FP4(it);
|
||||
chk->values.push_back(val);
|
||||
}
|
||||
return chk;
|
||||
}
|
||||
|
||||
if (tag == "IKEY") {
|
||||
FORM::SURF::BLOK::GRAD::IKEY *chk = new FORM::SURF::BLOK::GRAD::IKEY;
|
||||
while (it < end) chk->interpolation.push_back(read_U2(it));
|
||||
return chk;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (context == "FORM::SURF::BLOK::SHDR") {
|
||||
|
||||
if (tag == "FUNC") {
|
||||
FORM::SURF::BLOK::SHDR::FUNC *chk = new FORM::SURF::BLOK::SHDR::FUNC;
|
||||
chk->algorithm_name = read_S0(it);
|
||||
while (it < end) chk->data.push_back(read_U1(it));
|
||||
return chk;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
LP_TMP iff::Chunk *Parser<Iter>::parse_subchunk(Iter &it, const std::string &context)
|
||||
{
|
||||
std::string tag;
|
||||
for (int i=0; i<4; ++i) tag.push_back(*(it++));
|
||||
unsigned int len = ((static_cast<unsigned int>(*(it++)) & 0xFF) << 8) |
|
||||
(static_cast<unsigned int>(*(it++)) & 0xFF);
|
||||
os() << "DEBUG INFO: lwo2parser: reading subchunk " << tag << ", length = " << len << ", context = " << context << "\n";
|
||||
iff::Chunk *chk = parse_chunk_data(tag, context, it, it+len);
|
||||
if (!chk) os() << "DEBUG INFO: lwo2parser: \tprevious subchunk not handled\n";
|
||||
it += len;
|
||||
if ((len % 2) != 0) ++it;
|
||||
return chk;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
147
src/osgPlugins/lwo/lwo2read.h
Normal file
147
src/osgPlugins/lwo/lwo2read.h
Normal file
@@ -0,0 +1,147 @@
|
||||
|
||||
/****************************************************************************
|
||||
|
||||
Functions for reading basic data types from LWO2 files
|
||||
|
||||
Copyright (C) 2002 by Marco Jez
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef LWO2READ_
|
||||
#define LWO2READ_
|
||||
|
||||
#include "lwo2types.h"
|
||||
|
||||
namespace lwo2
|
||||
{
|
||||
|
||||
template<class Iter>
|
||||
I1 read_I1(Iter &it)
|
||||
{
|
||||
return static_cast<I1>(*(it++));
|
||||
}
|
||||
|
||||
template<class Iter>
|
||||
I2 read_I2(Iter &it)
|
||||
{
|
||||
return ((static_cast<I2>(*(it++)) & 0xFF) << 8) |
|
||||
(static_cast<I2>(*(it++)) & 0xFF);
|
||||
}
|
||||
|
||||
template<class Iter>
|
||||
I4 read_I4(Iter &it)
|
||||
{
|
||||
return ((static_cast<I4>(*(it++)) & 0xFF) << 24) |
|
||||
((static_cast<I4>(*(it++)) & 0xFF) << 16) |
|
||||
((static_cast<I4>(*(it++)) & 0xFF) << 8) |
|
||||
(static_cast<I4>(*(it++)) & 0xFF);
|
||||
}
|
||||
|
||||
template<class Iter>
|
||||
U1 read_U1(Iter &it)
|
||||
{
|
||||
return static_cast<U1>(*(it++));
|
||||
}
|
||||
|
||||
template<class Iter>
|
||||
U2 read_U2(Iter &it)
|
||||
{
|
||||
return ((static_cast<U2>(*(it++)) & 0xFF) << 8) |
|
||||
(static_cast<U2>(*(it++)) & 0xFF);
|
||||
}
|
||||
|
||||
template<class Iter>
|
||||
U4 read_U4(Iter &it)
|
||||
{
|
||||
return ((static_cast<U4>(*(it++)) & 0xFF) << 24) |
|
||||
((static_cast<U4>(*(it++)) & 0xFF) << 16) |
|
||||
((static_cast<U4>(*(it++)) & 0xFF) << 8) |
|
||||
(static_cast<U4>(*(it++)) & 0xFF);
|
||||
}
|
||||
|
||||
template<class Iter>
|
||||
F4 read_F4(Iter &it)
|
||||
{
|
||||
U4 u4 = read_U4(it);
|
||||
return *reinterpret_cast<F4 *>(&u4);
|
||||
}
|
||||
|
||||
template<class Iter>
|
||||
ID4 read_ID4(Iter &it)
|
||||
{
|
||||
ID4 value;
|
||||
for (int i=0; i<4; ++i) value.id[i] = *(it++);
|
||||
return value;
|
||||
}
|
||||
|
||||
template<class Iter>
|
||||
S0 read_S0(Iter &it)
|
||||
{
|
||||
S0 value;
|
||||
while (*it) {
|
||||
value.push_back(*(it++));
|
||||
}
|
||||
++it;
|
||||
if (value.length() % 2 == 0) ++it;
|
||||
return value;
|
||||
}
|
||||
|
||||
template<class Iter>
|
||||
VX read_VX(Iter &it)
|
||||
{
|
||||
VX vx;
|
||||
if ((*it & 0xFF) == 0xFF) {
|
||||
vx.index = read_U4(it) & 0x00FFFFFF;
|
||||
} else {
|
||||
vx.index = static_cast<U4>(read_U2(it));
|
||||
}
|
||||
return vx;
|
||||
}
|
||||
|
||||
template<class Iter>
|
||||
COL12 read_COL12(Iter &it)
|
||||
{
|
||||
COL12 value;
|
||||
value.red = read_F4(it);
|
||||
value.green = read_F4(it);
|
||||
value.blue = read_F4(it);
|
||||
return value;
|
||||
}
|
||||
|
||||
template<class Iter>
|
||||
VEC12 read_VEC12(Iter &it)
|
||||
{
|
||||
VEC12 value;
|
||||
value.X = read_F4(it);
|
||||
value.Y = read_F4(it);
|
||||
value.Z = read_F4(it);
|
||||
return value;
|
||||
}
|
||||
|
||||
template<class Iter>
|
||||
FP4 read_FP4(Iter &it)
|
||||
{
|
||||
FP4 value;
|
||||
value.fraction = read_F4(it);
|
||||
return value;
|
||||
}
|
||||
|
||||
template<class Iter>
|
||||
ANG4 read_ANG4(Iter &it)
|
||||
{
|
||||
ANG4 value;
|
||||
value.radians = read_F4(it);
|
||||
return value;
|
||||
}
|
||||
|
||||
template<class Iter>
|
||||
FNAM0 read_FNAM0(Iter &it)
|
||||
{
|
||||
FNAM0 value;
|
||||
value.name = read_S0(it);
|
||||
return value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
65
src/osgPlugins/lwo/lwo2types.h
Normal file
65
src/osgPlugins/lwo/lwo2types.h
Normal file
@@ -0,0 +1,65 @@
|
||||
|
||||
/****************************************************************************
|
||||
|
||||
Basic data types used in LWO2 files
|
||||
|
||||
Copyright (C) 2002-2003 Marco Jez
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef LWO2TYPES_
|
||||
#define LWO2TYPES_
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace lwo2
|
||||
{
|
||||
|
||||
// basic types
|
||||
|
||||
struct ID4 {
|
||||
char id[4];
|
||||
};
|
||||
|
||||
typedef signed char I1;
|
||||
typedef signed short int I2;
|
||||
typedef signed int I4;
|
||||
typedef unsigned char U1;
|
||||
typedef unsigned short int U2;
|
||||
typedef unsigned int U4;
|
||||
typedef float F4;
|
||||
typedef std::string S0;
|
||||
|
||||
// composite types
|
||||
|
||||
struct VX {
|
||||
U4 index;
|
||||
};
|
||||
|
||||
struct COL12 {
|
||||
F4 red;
|
||||
F4 green;
|
||||
F4 blue;
|
||||
};
|
||||
|
||||
struct VEC12 {
|
||||
F4 X;
|
||||
F4 Y;
|
||||
F4 Z;
|
||||
};
|
||||
|
||||
struct FP4 {
|
||||
F4 fraction;
|
||||
};
|
||||
|
||||
struct ANG4 {
|
||||
F4 radians;
|
||||
};
|
||||
|
||||
struct FNAM0 {
|
||||
S0 name;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -37,8 +37,8 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
#include "Lwo2.h"
|
||||
#include "Lwo2Layer.h"
|
||||
#include "old_Lwo2.h"
|
||||
#include "old_Lwo2Layer.h"
|
||||
|
||||
Lwo2::Lwo2():
|
||||
_current_layer(0),
|
||||
@@ -23,7 +23,7 @@
|
||||
* The OSG homepage is http://www.openscenegraph.org/
|
||||
*/
|
||||
|
||||
#include "Lwo2Layer.h"
|
||||
#include "old_Lwo2Layer.h"
|
||||
|
||||
Lwo2Layer::Lwo2Layer():
|
||||
_number(0),
|
||||
@@ -16,7 +16,7 @@
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lw.h"
|
||||
#include "old_lw.h"
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
Reference in New Issue
Block a user