From Marco Jez, new Light Wave Scene loader

This commit is contained in:
Robert Osfield
2004-01-03 20:32:27 +00:00
parent c0f2730d99
commit 687410145d
8 changed files with 756 additions and 1 deletions

View File

@@ -35,6 +35,7 @@ PLUGIN_DIRS = \
lib3ds\
logo\
lwo\
lws\
md2\
obj\
osgParticle\

View File

@@ -1977,6 +1977,33 @@ Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name Core osg
End Project Dependency
Begin Project Dependency
Project_Dep_Name Core osgDB
End Project Dependency
Begin Project Dependency
Project_Dep_Name Core osgUtil
End Project Dependency
Begin Project Dependency
Project_Dep_Name Core osgFX
End Project Dependency
Begin Project Dependency
Project_Dep_Name Core osgGL2
End Project Dependency
}}}
###############################################################################
Project: "osgPlugin lws"=.\osgPlugins\lws\lws.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency

View File

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

View File

@@ -19,7 +19,7 @@ CXXFILES =\
INC += -I$(THISDIR)
LIBS += $(OSG_LIBS) $(OTHER_LIBS) $(GL_LIBS)
LIBS += -losgFX -losgGL2 $(OSG_LIBS) $(OTHER_LIBS) $(GL_LIBS)
TARGET_BASENAME = lwo
include $(TOPDIR)/Make/cygwin_plugin_def

View File

@@ -0,0 +1,17 @@
TOPDIR = ../../..
include $(TOPDIR)/Make/makedefs
CXXFILES =\
SceneLoader.cpp\
ReaderWriterLWS.cpp\
INC += -I$(THISDIR)
LIBS += $(OSG_LIBS) $(OTHER_LIBS)
TARGET_BASENAME = lws
include $(TOPDIR)/Make/cygwin_plugin_def
PLUGIN = $(PLUGIN_PREFIX)$(TARGET_BASENAME).$(PLUGIN_EXT)
include $(TOPDIR)/Make/makerules

View File

@@ -0,0 +1,78 @@
/*******************************************************
Lightwave Scene Loader for OSG
Copyright (C) 2004 Marco Jez <marco.jez@poste.it>
OpenSceneGraph is (C) 2004 Robert Osfield
********************************************************/
#if defined(_MSC_VER)
#pragma warning( disable : 4786 )
#endif
#include <string>
#include <sstream>
#include <osgDB/Registry>
#include <osgDB/ReadFile>
#include <osgDB/FileNameUtils>
#include <osgDB/FileUtils>
#include "SceneLoader.h"
class ReaderWriterLWS : public osgDB::ReaderWriter
{
public:
ReaderWriterLWS() {}
virtual const char* className() { return "ReaderWriterLWS"; }
virtual bool acceptsExtension(const std::string &extension) {
return osgDB::equalCaseInsensitive(extension, "lws");
}
virtual ReadResult readNode(const std::string &file, const osgDB::ReaderWriter::Options *options)
{
std::string ext = osgDB::getLowerCaseFileExtension(file);
if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED;
std::string fileName = osgDB::findDataFile(file);
if (fileName.empty()) return ReadResult::FILE_NOT_FOUND;
lwosg::SceneLoader::Options conv_options = parse_options(options);
lwosg::SceneLoader scene_loader(conv_options);
osg::ref_ptr<osg::Node> node = scene_loader.load(fileName);
if (node.valid()) {
return node.take();
}
return ReadResult::FILE_NOT_HANDLED;
}
lwosg::SceneLoader::Options parse_options(const Options *options) const;
protected:
};
lwosg::SceneLoader::Options ReaderWriterLWS::parse_options(const Options *options) const
{
lwosg::SceneLoader::Options conv_options;
if (options) {
std::istringstream iss(options->getOptionString());
std::string opt;
while (iss >> opt) {
// no options yet!
}
}
return conv_options;
}
// register with Registry to instantiate the above reader/writer.
osgDB::RegisterReaderWriterProxy<ReaderWriterLWS> g_lwsReaderWriterProxy;

View File

@@ -0,0 +1,361 @@
/*******************************************************
Lightwave Scene Loader for OSG
Copyright (C) 2004 Marco Jez <marco.jez@poste.it>
OpenSceneGraph is (C) 2004 Robert Osfield
********************************************************/
#include "SceneLoader.h"
#include <osg/Notify>
#include <osg/PositionAttitudeTransform>
#include <osg/AnimationPath>
#include <osgDB/FileUtils>
#include <osgDB/FileNameUtils>
#include <osgDB/ReadFile>
#include <osgDB/WriteFile>
#include <fstream>
#include <sstream>
using namespace lwosg;
namespace
{
int str_to_int(const std::string &s)
{
std::istringstream iss(s);
int n;
iss >> n;
return n;
}
int hex_to_int(const std::string &s)
{
std::istringstream iss(s);
int n;
iss >> std::hex >> n;
return n;
}
osg::Quat rotate_ypr(const osg::Vec3 &ypr, const osg::Vec3 pivot_rot = osg::Vec3(0, 0, 0))
{
osg::Quat Q1(ypr.z(), osg::Vec3(0, -1, 0));
osg::Quat Q2(ypr.y(), osg::Vec3(-1, 0, 0));
osg::Quat Q3(ypr.x(), osg::Vec3(0, 0, -1));
osg::Quat Q4(pivot_rot.z(), osg::Vec3(0, -1, 0));
osg::Quat Q5(pivot_rot.y(), osg::Vec3(-1, 0, 0));
osg::Quat Q6(pivot_rot.x(), osg::Vec3(0, 0, -1));
return Q1 * Q2 * Q3 * Q4 * Q5 * Q6;
}
void trim(std::string& str)
{
// trim any trailing control characters.
//std::cout<<"trim string "<<str<<std::endl;
while (!str.empty() && str[str.size()-1]<32)
{
// removing control character
//std::cout<<" removing control character "<<(int)str[str.size()-1]<<std::endl;
str.erase(str.size()-1);
}
}
}
SceneLoader::SceneLoader()
: capture_obj_motion_(false),
capture_cam_motion_(false)
{
}
SceneLoader::SceneLoader(const Options &options)
: capture_obj_motion_(false),
capture_cam_motion_(false),
options_(options)
{
}
osg::Group *SceneLoader::load(const std::string &filename, bool search)
{
std::string fname;
if (search) {
fname = osgDB::findDataFile(filename);
if (fname.empty()) return 0;
} else {
fname = filename;
}
std::ifstream ifs(fname.c_str());
if (!ifs.is_open()) return 0;
clear();
std::string identifier;
while (ifs >> identifier) {
if (identifier == "{") {
ifs >> identifier;
std::ws(ifs);
std::vector<std::string> data;
std::string data_line;
while (std::getline(ifs, data_line)) {
trim(data_line);
if (data_line == "}") {
std::ws(ifs);
break;
}
data.push_back(data_line);
std::ws(ifs);
}
if (!data.empty()) {
if (!parse_block(identifier, data)) {
return 0;
}
}
} else {
std::string data;
std::getline(ifs, data);
trim(data);
std::istringstream iss(data);
std::ws(iss);
std::getline(iss, data);
trim(data);
if (!parse_block(identifier, data)) {
return 0;
}
}
}
// build camera animations
for (Scene_camera_list::iterator ci=scene_cameras_.begin(); ci!=scene_cameras_.end(); ++ci) {
if (!ci->motion.keys.empty()) {
osg::ref_ptr<osg::AnimationPath> ap = new osg::AnimationPath;
for (Motion_envelope::Key_map::const_iterator j=ci->motion.keys.begin(); j!=ci->motion.keys.end(); ++j) {
osg::Vec3 pos(options_.csf->fix_point(j->second.position));
//const osg::Vec3 &ypr = j->second.ypr;
osg::AnimationPath::ControlPoint cp(pos, osg::Quat(osg::PI_2, osg::Vec3(1, 0, 0)) * rotate_ypr(j->second.ypr), j->second.scale);
ap->insert(j->first, cp);
}
camera_animations_.push_back(ap.get());
}
}
// build objects and object animations
typedef std::map<int, osg::ref_ptr<osg::PositionAttitudeTransform> > PAT_map;
PAT_map pats;
int j = 0;
for (Scene_object_list::iterator i=scene_objects_.begin(); i!=scene_objects_.end(); ++i, ++j) {
osg::ref_ptr<osg::PositionAttitudeTransform> pat = pats[j];
if (!pat.valid()) {
pat = new osg::PositionAttitudeTransform;
pats[j] = pat;
}
pat->addChild(i->layer_node.get());
pat->setPivotPoint(options_.csf->fix_point(i->pivot));
// still
if (!i->motion.keys.empty()) {
pat->setPosition(options_.csf->fix_point(i->motion.keys.begin()->second.position));
pat->setAttitude(rotate_ypr(i->motion.keys.begin()->second.ypr, i->pivot_rot));
}
// animation
if (i->motion.keys.size() > 1) {
osg::ref_ptr<osg::AnimationPath> ap = new osg::AnimationPath;
for (Motion_envelope::Key_map::const_iterator j=i->motion.keys.begin(); j!=i->motion.keys.end(); ++j) {
osg::Vec3 pos(options_.csf->fix_point(j->second.position));
osg::AnimationPath::ControlPoint cp(pos, rotate_ypr(j->second.ypr, i->pivot_rot), j->second.scale);
ap->insert(j->first, cp);
}
osg::ref_ptr<osg::AnimationPathCallback> apc = new osg::AnimationPathCallback(ap.get());
pat->setUpdateCallback(apc.get());
}
if (i->parent == -1) {
root_->addChild(pat.get());
} else {
if (i->parent < static_cast<int>(scene_objects_.size())) {
osg::ref_ptr<osg::PositionAttitudeTransform> parent = pats[i->parent];
if (!parent.valid()) {
parent = new osg::PositionAttitudeTransform;
pats[i->parent] = parent;
}
parent->addChild(pat.get());
} else {
osg::notify(osg::WARN) << "Warning: lwosg::SceneLoader: invalid parent" << std::endl;
}
}
}
return root_.get();
}
bool SceneLoader::parse_block(const std::string &name, const std::string &data)
{
std::istringstream iss(data);
if (name == "AddCamera") {
scene_cameras_.push_back(Scene_camera());
}
if (name == "AddNullObject") {
osg::ref_ptr<osg::Group> nullobjnode = new osg::Group;
nullobjnode->setName(data);
objects_[data] = nullobjnode;
Scene_object so;
so.layer_node = nullobjnode.get();
scene_objects_.push_back(so);
}
if (name == "LoadObjectLayer") {
unsigned layer;
iss >> layer;
std::ws(iss);
std::string filename;
std::getline(iss, filename);
// trim any trailing control characters.
trim(filename);
if (!filename.empty())
{
osg::ref_ptr<osg::Group> objnode;
Object_map::const_iterator i = objects_.find(filename);
if (i == objects_.end()) {
osg::notify(osg::NOTICE) << "Loading object \"" << filename << "\"" << std::endl;
objnode = dynamic_cast<osg::Group *>(osgDB::readNodeFile(filename));
if (!objnode.valid()) return false;
objects_[filename] = objnode;
} else {
objnode = i->second;
}
if (layer > objnode->getNumChildren()) {
osg::notify(osg::WARN) << "Warning: lwosg::SceneLoader: layer " << layer << " does not exist in object " << filename << std::endl;
return 0;
}
Scene_object so;
so.layer_node = objnode->getChild(layer-1);
if (so.layer_node.valid()) {
scene_objects_.push_back(so);
}
}
}
if (name == "PivotPosition") {
if (!scene_objects_.empty()) {
osg::Vec3 pivot;
iss >> pivot.x() >> pivot.y() >> pivot.z();
scene_objects_.back().pivot = pivot;
}
}
if (name == "PivotRotation") {
if (!scene_objects_.empty()) {
osg::Vec3 pivot;
iss >> pivot.x() >> pivot.y() >> pivot.z();
scene_objects_.back().pivot_rot = pivot * (osg::PI / 180.0f);
}
}
if (name == "ParentItem") {
if (!scene_objects_.empty()) {
std::string id;
iss >> id;
if (id.length() == 8) {
if (id[0] == '1') {
id.erase(0, 1);
scene_objects_.back().parent = hex_to_int(id);
}
} else {
scene_objects_.back().parent = str_to_int(id);
}
}
}
if (name == "NumChannels") {
iss >> channel_count_;
}
if (name == "Channel") {
iss >> current_channel_;
}
if (name == "ObjectMotion") {
capture_obj_motion_ = true;
}
if (name == "CameraMotion") {
capture_cam_motion_ = true;
}
return true;
}
bool SceneLoader::parse_block(const std::string &name, const std::vector<std::string> &data)
{
if (name == "Envelope") {
if (((capture_obj_motion_ && !scene_objects_.empty()) ||
(capture_cam_motion_ && !scene_cameras_.empty())) &&
(data.size() >= 2)) {
Motion_envelope::Key_map &keys = capture_obj_motion_ ? scene_objects_.back().motion.keys : scene_cameras_.back().motion.keys;
if (current_channel_ >= (channel_count_ - 1)) {
capture_obj_motion_ = false;
capture_cam_motion_ = false;
}
for (unsigned i=1; i<data.size(); ++i) {
std::istringstream iss(data[i]);
std::string key_id;
iss >> key_id;
if (key_id == "Key") {
float value;
double time;
if (iss >> value >> time) {
switch (current_channel_) {
case 0: keys[time].position.x() = value; break;
case 1: keys[time].position.y() = value; break;
case 2: keys[time].position.z() = value; break;
case 3: keys[time].ypr.x() = value; break;
case 4: keys[time].ypr.y() = value; break;
case 5: keys[time].ypr.z() = value; break;
case 6: keys[time].scale.x() = value; break;
case 7: keys[time].scale.y() = value; break;
case 8: keys[time].scale.z() = value; break;
default: ;
}
}
}
}
}
}
return true;
}
void SceneLoader::clear()
{
root_ = new osg::Group;
objects_.clear();
scene_objects_.clear();
scene_cameras_.clear();
camera_animations_.clear();
channel_count_ = 0;
current_channel_ = 0;
}

View File

@@ -0,0 +1,150 @@
/*******************************************************
Lightwave Scene Loader for OSG
Copyright (C) 2004 Marco Jez <marco.jez@poste.it>
OpenSceneGraph is (C) 2004 Robert Osfield
********************************************************/
#ifndef LWOSG_SCENELOADER_
#define LWOSG_SCENELOADER_
#include <osg/Group>
#include <osg/Vec3>
#include <osg/AnimationPath>
#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 SceneLoader {
public:
struct Options {
osg::ref_ptr<CoordinateSystemFixer> csf;
Options(): csf(new LwoCoordFixer) {}
};
typedef std::vector<osg::ref_ptr<osg::AnimationPath> > Animation_list;
SceneLoader();
SceneLoader(const Options &options);
osg::Group *load(const std::string &filename, bool search = false);
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; }
inline const Animation_list &get_camera_animations() const { return camera_animations_; }
inline Animation_list &get_camera_animations() { return camera_animations_; }
protected:
bool parse_block(const std::string &name, const std::string &data);
bool parse_block(const std::string &name, const std::vector<std::string> &data);
void clear();
private:
typedef std::map<std::string, osg::ref_ptr<osg::Group> > Object_map;
Object_map objects_;
Animation_list camera_animations_;
struct Motion_envelope {
struct Key {
osg::Vec3 position;
osg::Vec3 ypr;
osg::Vec3 scale;
Key(): scale(1, 1, 1) {}
};
typedef std::map<double, Key> Key_map;
Key_map keys;
};
struct Scene_object {
osg::ref_ptr<osg::Node> layer_node;
int parent;
osg::Vec3 pivot;
osg::Vec3 pivot_rot;
Motion_envelope motion;
Scene_object(): parent(-1) {}
};
struct Scene_camera {
Motion_envelope motion;
};
typedef std::vector<Scene_object> Scene_object_list;
Scene_object_list scene_objects_;
typedef std::vector<Scene_camera> Scene_camera_list;
Scene_camera_list scene_cameras_;
osg::ref_ptr<osg::Group> root_;
int current_channel_;
int channel_count_;
bool capture_obj_motion_;
bool capture_cam_motion_;
Options options_;
};
// 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