From Marco Jez, new Light Wave Scene loader
This commit is contained in:
@@ -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
|
||||
|
||||
17
src/osgPlugins/lws/GNUmakefile
Normal file
17
src/osgPlugins/lws/GNUmakefile
Normal 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
|
||||
78
src/osgPlugins/lws/ReaderWriterLWS.cpp
Normal file
78
src/osgPlugins/lws/ReaderWriterLWS.cpp
Normal 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;
|
||||
361
src/osgPlugins/lws/SceneLoader.cpp
Normal file
361
src/osgPlugins/lws/SceneLoader.cpp
Normal 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;
|
||||
}
|
||||
150
src/osgPlugins/lws/SceneLoader.h
Normal file
150
src/osgPlugins/lws/SceneLoader.h
Normal 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
|
||||
Reference in New Issue
Block a user