loader.saveModel(), EggToObjConverter, etc.

This commit is contained in:
David Rose 2012-12-20 00:09:14 +00:00
parent a02e494ae3
commit 3af8da3bcd
40 changed files with 2869 additions and 1535 deletions

View File

@ -289,6 +289,75 @@ class Loader(DirectObject):
assert Loader.notify.debug("Unloading model: %s" % (modelNode.getFullpath()))
ModelPool.releaseModel(modelNode)
def saveModel(self, modelPath, node, loaderOptions = None,
callback = None, extraArgs = [], priority = None):
""" Saves the model (a NodePath or PandaNode) to the indicated
filename path. Returns true on success, false on failure. If
a callback is used, the model is saved asynchronously, and the
true/false status is passed to the callback function. """
if loaderOptions == None:
loaderOptions = LoaderOptions()
else:
loaderOptions = LoaderOptions(loaderOptions)
if isinstance(modelPath, types.StringTypes) or \
isinstance(modelPath, Filename):
# We were given a single model pathname.
modelList = [modelPath]
nodeList = [node]
if phaseChecker:
phaseChecker(modelPath, loaderOptions)
gotList = False
else:
# Assume we were given a list of model pathnames.
modelList = modelPath
nodeList = node
gotList = True
assert(len(modelList) == len(nodeList))
# Make sure we have PandaNodes, not NodePaths.
for i in range(len(nodeList)):
if isinstance(nodeList[i], NodePath):
nodeList[i] = nodeList[i].node()
# From here on, we deal with a list of (filename, node) pairs.
modelList = zip(modelList, nodeList)
if callback is None:
# We got no callback, so it's a synchronous save.
result = []
for modelPath, node in modelList:
thisResult = self.loader.saveSync(Filename(modelPath), loaderOptions, node)
result.append(thisResult)
if gotList:
return result
else:
return result[0]
else:
# We got a callback, so we want an asynchronous (threaded)
# save. We'll return immediately, but when all of the
# requested models have been saved, we'll invoke the
# callback (passing it the models on the parameter list).
cb = Loader.Callback(len(modelList), gotList, callback, extraArgs)
i=0
for modelPath, node in modelList:
request = self.loader.makeAsyncSaveRequest(Filename(modelPath), loaderOptions, node)
if priority is not None:
request.setPriority(priority)
request.setDoneEvent(self.hook)
request.setPythonObject((cb, i))
i+=1
self.loader.saveAsync(request)
cb.requests[request] = True
return cb
# font loading funcs
def loadFont(self, modelPath,
@ -875,4 +944,7 @@ class Loader(DirectObject):
elif hasattr(request, "getSound"):
object = request.getSound()
elif hasattr(request, "getSuccess"):
object = request.getSuccess()
cb.gotObject(i, object)

View File

@ -20,8 +20,10 @@
eggBinner.h \
eggLoader.h eggLoader.I \
eggRenderState.h eggRenderState.I \
eggSaver.h eggSaver.I \
egg_parametrics.h \
load_egg_file.h \
save_egg_file.h \
loaderFileTypeEgg.h
#define INCLUDED_SOURCES \
@ -32,8 +34,10 @@
eggBinner.cxx \
eggLoader.cxx \
eggRenderState.cxx \
eggSaver.cxx \
egg_parametrics.cxx \
load_egg_file.cxx \
save_egg_file.cxx \
loaderFileTypeEgg.cxx
#if $[DONT_COMBINE_PGRAPH]
@ -43,8 +47,8 @@
#endif
#define INSTALL_HEADERS \
egg_parametrics.h load_egg_file.h config_egg2pg.h
egg_parametrics.h load_egg_file.h save_egg_file.h config_egg2pg.h
#define IGATESCAN load_egg_file.h
#define IGATESCAN load_egg_file.h save_egg_file.h
#end lib_target

25
panda/src/egg2pg/eggSaver.I Executable file
View File

@ -0,0 +1,25 @@
// Filename: eggSaver.I
// Created by: drose (19Dec12)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: EggSaver::get_egg_data
// Access: Published
// Description: Returns the EggData populated within this class.
////////////////////////////////////////////////////////////////////
INLINE EggData *EggSaver::
get_egg_data() const {
return _data;
}

1132
panda/src/egg2pg/eggSaver.cxx Executable file

File diff suppressed because it is too large Load Diff

110
panda/src/egg2pg/eggSaver.h Executable file
View File

@ -0,0 +1,110 @@
// Filename: eggSaver.h
// Created by: drose (19Dec12)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
#ifndef EGGSAVER_H
#define EGGSAVER_H
#include "pandabase.h"
#include "luse.h"
#include "eggTextureCollection.h"
#include "eggMaterialCollection.h"
class WorkingNodePath;
class EggGroup;
class EggGroupNode;
class EggVertexPool;
class EggTexture;
class LODNode;
class SequenceNode;
class SwitchNode;
class AnimBundleNode;
class AnimGroup;
class Character;
class PartGroup;
class CollisionNode;
class GeomNode;
class GeomVertexData;
class GeomPrimitive;
class PandaNode;
class RenderState;
class Texture;
class CharacterJoint;
class EggVertex;
////////////////////////////////////////////////////////////////////
// Class : EggSaver
// Description : Converts the scene graph beginning at the indicated
// node into an EggData structure, for writing to an egg
// file. The conversion is not necessarily complete
// (some Panda or egg constructs are not fully supported
// by this class).
////////////////////////////////////////////////////////////////////
class EggSaver {
PUBLISHED:
EggSaver(EggData *data = NULL);
void add_node(PandaNode *node);
INLINE EggData *get_egg_data() const;
private:
typedef pmap<const CharacterJoint*, pvector<pair<EggVertex*,PN_stdfloat> > > CharacterJointMap;
void convert_node(const WorkingNodePath &node_path, EggGroupNode *egg_parent,
bool has_decal);
void convert_lod_node(LODNode *node, const WorkingNodePath &node_path,
EggGroupNode *egg_parent, bool has_decal);
void convert_sequence_node(SequenceNode *node, const WorkingNodePath &node_path,
EggGroupNode *egg_parent, bool has_decal);
void convert_switch_node(SwitchNode *node, const WorkingNodePath &node_path,
EggGroupNode *egg_parent, bool has_decal);
EggGroupNode *convert_animGroup_node(AnimGroup *animGroup, double fps );
void convert_anim_node(AnimBundleNode *node, const WorkingNodePath &node_path,
EggGroupNode *egg_parent, bool has_decal);
void convert_character_node(Character *node, const WorkingNodePath &node_path,
EggGroupNode *egg_parent, bool has_decal);
void convert_character_bundle(PartGroup *bundleNode, EggGroupNode *egg_parent, CharacterJointMap *jointMap);
void convert_collision_node(CollisionNode *node, const WorkingNodePath &node_path,
EggGroupNode *egg_parent, bool has_decal);
void convert_geom_node(GeomNode *node, const WorkingNodePath &node_path,
EggGroupNode *egg_parent, bool has_decal, CharacterJointMap *jointMap=NULL);
void convert_primitive(const GeomVertexData *vertex_data,
const GeomPrimitive *primitive,
const RenderState *net_state,
const LMatrix4 &net_mat, EggGroupNode *egg_parent,
CharacterJointMap *jointMap);
void recurse_nodes(const WorkingNodePath &node_path, EggGroupNode *egg_parent,
bool has_decal);
bool apply_node_properties(EggGroup *egg_group, PandaNode *node, bool allow_backstage = true);
bool apply_tags(EggGroup *egg_group, PandaNode *node);
bool apply_tag(EggGroup *egg_group, PandaNode *node, const string &tag);
EggTexture *get_egg_texture(Texture *tex);
static EggPrimitive *make_egg_polygon();
static EggPrimitive *make_egg_patch();
static EggPrimitive *make_egg_point();
static EggPrimitive *make_egg_line();
PT(EggData) _data;
PT(EggVertexPool) _vpool;
EggTextureCollection _textures;
EggMaterialCollection _materials;
};
#include "eggSaver.I"
#endif

View File

@ -14,6 +14,7 @@
#include "loaderFileTypeEgg.h"
#include "load_egg_file.h"
#include "save_egg_file.h"
#include "eggData.h"
@ -60,6 +61,30 @@ supports_compressed() const {
return true;
}
////////////////////////////////////////////////////////////////////
// Function: LoaderFileTypeEgg::supports_load
// Access: Published, Virtual
// Description: Returns true if the file type can be used to load
// files, and load_file() is supported. Returns false
// if load_file() is unimplemented and will always fail.
////////////////////////////////////////////////////////////////////
bool LoaderFileTypeEgg::
supports_load() const {
return true;
}
////////////////////////////////////////////////////////////////////
// Function: LoaderFileTypeEgg::supports_save
// Access: Published, Virtual
// Description: Returns true if the file type can be used to save
// files, and save_file() is supported. Returns false
// if save_file() is unimplemented and will always fail.
////////////////////////////////////////////////////////////////////
bool LoaderFileTypeEgg::
supports_save() const {
return true;
}
////////////////////////////////////////////////////////////////////
// Function: LoaderFileTypeEgg::load_file
// Access: Public, Virtual
@ -71,3 +96,14 @@ load_file(const Filename &path, const LoaderOptions &,
PT(PandaNode) result = load_egg_file(path, CS_default, record);
return result;
}
////////////////////////////////////////////////////////////////////
// Function: LoaderFileTypeEgg::save_file
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
bool LoaderFileTypeEgg::
save_file(const Filename &path, const LoaderOptions &options,
PandaNode *node) const {
return save_egg_file(path, node);
}

View File

@ -31,8 +31,13 @@ public:
virtual string get_extension() const;
virtual bool supports_compressed() const;
virtual bool supports_load() const;
virtual bool supports_save() const;
virtual PT(PandaNode) load_file(const Filename &path, const LoaderOptions &optoins,
BamCacheRecord *record) const;
virtual bool save_file(const Filename &path, const LoaderOptions &options,
PandaNode *node) const;
public:
static TypeHandle get_class_type() {

View File

@ -3,3 +3,4 @@
#include "config_egg2pg.cxx"
#include "egg_parametrics.cxx"
#include "eggRenderState.cxx"
#include "deferredNodeProperty.cxx"

View File

@ -1,6 +1,7 @@
#include "deferredNodeProperty.cxx"
#include "eggBinner.cxx"
#include "eggLoader.cxx"
#include "eggSaver.cxx"
#include "load_egg_file.cxx"
#include "save_egg_file.cxx"
#include "loaderFileTypeEgg.cxx"

View File

@ -0,0 +1,52 @@
// Filename: save_egg_file.cxx
// Created by: drose (26Feb02)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
#include "save_egg_file.h"
#include "eggSaver.h"
#include "config_egg2pg.h"
#include "sceneGraphReducer.h"
#include "virtualFileSystem.h"
#include "config_util.h"
////////////////////////////////////////////////////////////////////
// Function: save_egg_file
// Description: A convenience function; converts the indicated scene
// graph to an egg file and writes it to disk.
////////////////////////////////////////////////////////////////////
bool
save_egg_file(const Filename &filename, PandaNode *node, CoordinateSystem cs) {
PT(EggData) data = new EggData;
if (cs == CS_default) {
cs = get_default_coordinate_system();
}
data->set_coordinate_system(cs);
EggSaver saver(data);
saver.add_node(node);
return data->write_egg(filename);
}
////////////////////////////////////////////////////////////////////
// Function: save_egg_data
// Description: Another convenience function; works like
// save_egg_file() but populates an EggData instead of
// writing the results to disk.
////////////////////////////////////////////////////////////////////
bool
save_egg_data(EggData *data, PandaNode *node) {
EggSaver saver(data);
saver.add_node(node);
return true;
}

View File

@ -0,0 +1,44 @@
// Filename: save_egg_file.h
// Created by: drose (19Dec12)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
#ifndef SAVE_EGG_FILE_H
#define SAVE_EGG_FILE_H
#include "pandabase.h"
#include "pandaNode.h"
#include "coordinateSystem.h"
#include "eggData.h"
BEGIN_PUBLISH
////////////////////////////////////////////////////////////////////
// Function: save_egg_file
// Description: A convenience function; converts the indicated scene
// graph to an egg file and writes it to disk.
////////////////////////////////////////////////////////////////////
EXPCL_PANDAEGG bool
save_egg_file(const Filename &filename, PandaNode *node,
CoordinateSystem cs = CS_default);
////////////////////////////////////////////////////////////////////
// Function: save_egg_data
// Description: Another convenience function; works like
// save_egg_file() but populates an EggData instead of
// writing the results to disk.
////////////////////////////////////////////////////////////////////
EXPCL_PANDAEGG bool
save_egg_data(EggData *data, PandaNode *node);
END_PUBLISH
#endif

View File

@ -67,6 +67,7 @@
materialCollection.I materialCollection.h \
modelFlattenRequest.I modelFlattenRequest.h \
modelLoadRequest.I modelLoadRequest.h \
modelSaveRequest.I modelSaveRequest.h \
modelNode.I modelNode.h \
modelPool.I modelPool.h \
modelRoot.I modelRoot.h \
@ -167,6 +168,7 @@
materialCollection.cxx \
modelFlattenRequest.cxx \
modelLoadRequest.cxx \
modelSaveRequest.cxx \
modelNode.cxx \
modelPool.cxx \
modelRoot.cxx \
@ -262,6 +264,7 @@
materialCollection.I materialCollection.h \
modelFlattenRequest.I modelFlattenRequest.h \
modelLoadRequest.I modelLoadRequest.h \
modelSaveRequest.I modelSaveRequest.h \
modelNode.I modelNode.h \
modelPool.I modelPool.h \
modelRoot.I modelRoot.h \

View File

@ -55,6 +55,7 @@
#include "materialAttrib.h"
#include "modelFlattenRequest.h"
#include "modelLoadRequest.h"
#include "modelSaveRequest.h"
#include "modelNode.h"
#include "modelRoot.h"
#include "nodePath.h"
@ -473,6 +474,7 @@ init_libpgraph() {
MaterialAttrib::init_type();
ModelFlattenRequest::init_type();
ModelLoadRequest::init_type();
ModelSaveRequest::init_type();
ModelNode::init_type();
ModelRoot::init_type();
NodePath::init_type();

View File

@ -200,11 +200,11 @@ load_sync(const Filename &filename, const LoaderOptions &options) const {
// Function: Loader::load_async
// Access: Published
// Description: Begins an asynchronous load request. To use this
// call, first create a new ModelLoadRequest object with
// the filename you wish to load, and then add that
// object to the Loader with load_async. This function
// will return immediately, and the model will be loaded
// in the background.
// call, first call make_async_request() to create a new
// ModelLoadRequest object with the filename you wish to
// load, and then add that object to the Loader with
// load_async. This function will return immediately,
// and the model will be loaded in the background.
//
// To determine when the model has completely loaded,
// you may poll request->is_ready() from time to time,
@ -218,6 +218,45 @@ load_async(AsyncTask *request) {
_task_manager->add(request);
}
////////////////////////////////////////////////////////////////////
// Function: Loader::save_sync
// Access: Published
// Description: Saves the file immediately, waiting for it to
// complete.
////////////////////////////////////////////////////////////////////
INLINE bool Loader::
save_sync(const Filename &filename, const LoaderOptions &options,
PandaNode *node) const {
if (!_file_types_loaded) {
load_file_types();
}
return save_file(filename, options, node);
}
////////////////////////////////////////////////////////////////////
// Function: Loader::save_async
// Access: Published
// Description: Begins an asynchronous save request. To use this
// call, first call make_async_save_request() to create
// a new ModelSaveRequest object with the filename you
// wish to load, and then add that object to the Loader
// with save_async. This function will return
// immediately, and the model will be loaded in the
// background.
//
// To determine when the model has completely loaded,
// you may poll request->is_ready() from time to time,
// or set the done_event on the request object and
// listen for that event. When the request is ready,
// you may retrieve the success or failure via
// request->get_success().
////////////////////////////////////////////////////////////////////
INLINE void Loader::
save_async(AsyncTask *request) {
request->set_task_chain(_task_chain);
_task_manager->add(request);
}
////////////////////////////////////////////////////////////////////
// Function: Loader::get_global_ptr
// Access: Published

View File

@ -18,6 +18,7 @@
#include "config_pgraph.h"
#include "modelPool.h"
#include "modelLoadRequest.h"
#include "modelSaveRequest.h"
#include "config_express.h"
#include "config_util.h"
#include "virtualFileSystem.h"
@ -84,6 +85,19 @@ make_async_request(const Filename &filename, const LoaderOptions &options) {
filename, options, this);
}
////////////////////////////////////////////////////////////////////
// Function: Loader::make_async_save_request
// Access: Published
// Description: Returns a new AsyncTask object suitable for adding to
// save_async() to start an asynchronous model save.
////////////////////////////////////////////////////////////////////
PT(AsyncTask) Loader::
make_async_save_request(const Filename &filename, const LoaderOptions &options,
PandaNode *node) {
return new ModelSaveRequest(string("model_save:")+filename.get_basename(),
filename, options, node, this);
}
////////////////////////////////////////////////////////////////////
// Function: Loader::load_bam_stream
// Access: Published
@ -176,6 +190,13 @@ load_file(const Filename &filename, const LoaderOptions &options) const {
reg->write(loader_cat.error(false), 2);
}
return NULL;
} else if (!requested_type->supports_load()) {
if (report_errors) {
loader_cat.error()
<< requested_type->get_name() << " file type (."
<< extension << ") does not support loading.\n";
}
return NULL;
} else if (pz_file && !requested_type->supports_compressed()) {
if (report_errors) {
loader_cat.error()
@ -338,6 +359,102 @@ try_load_file(const Filename &pathname, const LoaderOptions &options,
return NULL;
}
////////////////////////////////////////////////////////////////////
// Function: Loader::save_file
// Access: Private
// Description: Saves a scene graph to a single file, if possible.
// The file type written is implicit in the filename
// extension.
////////////////////////////////////////////////////////////////////
bool Loader::
save_file(const Filename &filename, const LoaderOptions &options,
PandaNode *node) const {
Filename this_filename(filename);
LoaderOptions this_options(options);
bool report_errors = (this_options.get_flags() & LoaderOptions::LF_report_errors) != 0;
string extension = this_filename.get_extension();
if (extension.empty()) {
// If the filename has no filename extension, append the default
// extension specified in the Config file.
this_filename = this_filename.get_fullpath() + default_model_extension.get_value();
extension = this_filename.get_extension();
}
bool pz_file = false;
#ifdef HAVE_ZLIB
if (extension == "pz") {
pz_file = true;
extension = Filename(this_filename.get_basename_wo_extension()).get_extension();
}
#endif // HAVE_ZLIB
if (extension.empty()) {
if (report_errors) {
loader_cat.error()
<< "Cannot save " << this_filename
<< " without filename extension.\n";
}
return NULL;
}
LoaderFileTypeRegistry *reg = LoaderFileTypeRegistry::get_global_ptr();
LoaderFileType *requested_type =
reg->get_type_from_extension(extension);
if (requested_type == (LoaderFileType *)NULL) {
if (report_errors) {
loader_cat.error()
<< "Extension of file " << this_filename
<< " is unrecognized; cannot save.\n";
loader_cat.error(false)
<< "Currently known scene file types are:\n";
reg->write(loader_cat.error(false), 2);
}
return NULL;
} else if (!requested_type->supports_save()) {
if (report_errors) {
loader_cat.error()
<< requested_type->get_name() << " file type (."
<< extension << ") does not support saving.\n";
}
return NULL;
} else if (pz_file && !requested_type->supports_compressed()) {
if (report_errors) {
loader_cat.error()
<< requested_type->get_name() << " file type (."
<< extension << ") does not support in-line compression.\n";
}
return NULL;
}
VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
bool result = try_save_file(this_filename, this_options, node, requested_type);
if (!result) {
if (report_errors) {
loader_cat.error()
<< "Couldn't save file " << this_filename << ".\n";
}
}
return result;
}
////////////////////////////////////////////////////////////////////
// Function: Loader::try_save_file
// Access: Private
// Description: The implementation of save_file(), this tries to
// write a specific file type.
////////////////////////////////////////////////////////////////////
bool Loader::
try_save_file(const Filename &pathname, const LoaderOptions &options,
PandaNode *node, LoaderFileType *requested_type) const {
bool report_errors = ((options.get_flags() & LoaderOptions::LF_report_errors) != 0 || loader_cat.is_debug());
bool result = requested_type->save_file(pathname, options, node);
return result;
}
////////////////////////////////////////////////////////////////////
// Function: Loader::load_file_types

View File

@ -92,6 +92,13 @@ PUBLISHED:
const LoaderOptions &options = LoaderOptions());
INLINE void load_async(AsyncTask *request);
INLINE bool save_sync(const Filename &filename, const LoaderOptions &options,
PandaNode *node) const;
PT(AsyncTask) make_async_save_request(const Filename &filename,
const LoaderOptions &options,
PandaNode *node);
INLINE void save_async(AsyncTask *request);
BLOCKING PT(PandaNode) load_bam_stream(istream &in);
virtual void output(ostream &out) const;
@ -103,6 +110,11 @@ private:
PT(PandaNode) try_load_file(const Filename &pathname, const LoaderOptions &options,
LoaderFileType *requested_type) const;
bool save_file(const Filename &filename, const LoaderOptions &options,
PandaNode *node) const;
bool try_save_file(const Filename &filename, const LoaderOptions &options,
PandaNode *node, LoaderFileType *requested_type) const;
static void make_global_ptr();
PT(AsyncTaskManager) _task_manager;

View File

@ -81,7 +81,7 @@ get_allow_disk_cache(const LoaderOptions &options) const {
////////////////////////////////////////////////////////////////////
// Function: LoaderFileType::get_allow_ram_cache
// Access: Published
// Access: Published, Virtual
// Description: Returns true if the loader flags allow retrieving the
// model from the in-memory ModelPool cache, false
// otherwise.
@ -91,6 +91,30 @@ get_allow_ram_cache(const LoaderOptions &options) const {
return (options.get_flags() & (LoaderOptions::LF_no_ram_cache | _no_cache_flags)) == 0;
}
////////////////////////////////////////////////////////////////////
// Function: LoaderFileType::supports_load
// Access: Published, Virtual
// Description: Returns true if the file type can be used to load
// files, and load_file() is supported. Returns false
// if load_file() is unimplemented and will always fail.
////////////////////////////////////////////////////////////////////
bool LoaderFileType::
supports_load() const {
return true;
}
////////////////////////////////////////////////////////////////////
// Function: LoaderFileType::supports_save
// Access: Published, Virtual
// Description: Returns true if the file type can be used to save
// files, and save_file() is supported. Returns false
// if save_file() is unimplemented and will always fail.
////////////////////////////////////////////////////////////////////
bool LoaderFileType::
supports_save() const {
return false;
}
////////////////////////////////////////////////////////////////////
// Function: LoaderFileType::load_file
// Access: Public, Virtual
@ -103,3 +127,16 @@ load_file(const Filename &path, const LoaderOptions &options,
<< get_type() << " cannot read PandaNode objects.\n";
return NULL;
}
////////////////////////////////////////////////////////////////////
// Function: LoaderFileType::save_file
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
bool LoaderFileType::
save_file(const Filename &path, const LoaderOptions &options,
PandaNode *node) const {
loader_cat.error()
<< get_type() << " cannot save PandaNode objects.\n";
return NULL;
}

View File

@ -49,9 +49,14 @@ PUBLISHED:
virtual bool get_allow_disk_cache(const LoaderOptions &options) const;
virtual bool get_allow_ram_cache(const LoaderOptions &options) const;
virtual bool supports_load() const;
virtual bool supports_save() const;
public:
virtual PT(PandaNode) load_file(const Filename &path, const LoaderOptions &options,
BamCacheRecord *record) const;
virtual bool save_file(const Filename &path, const LoaderOptions &options,
PandaNode *node) const;
protected:
int _no_cache_flags;

View File

@ -63,6 +63,30 @@ supports_compressed() const {
return true;
}
////////////////////////////////////////////////////////////////////
// Function: LoaderFileTypeBam::supports_load
// Access: Published, Virtual
// Description: Returns true if the file type can be used to load
// files, and load_file() is supported. Returns false
// if load_file() is unimplemented and will always fail.
////////////////////////////////////////////////////////////////////
bool LoaderFileTypeBam::
supports_load() const {
return true;
}
////////////////////////////////////////////////////////////////////
// Function: LoaderFileTypeBam::supports_save
// Access: Published, Virtual
// Description: Returns true if the file type can be used to save
// files, and save_file() is supported. Returns false
// if save_file() is unimplemented and will always fail.
////////////////////////////////////////////////////////////////////
bool LoaderFileTypeBam::
supports_save() const {
return true;
}
////////////////////////////////////////////////////////////////////
// Function: LoaderFileTypeBam::load_file
// Access: Public, Virtual
@ -94,3 +118,26 @@ load_file(const Filename &path, const LoaderOptions &options,
return node;
}
////////////////////////////////////////////////////////////////////
// Function: LoaderFileTypeBam::save_file
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
bool LoaderFileTypeBam::
save_file(const Filename &path, const LoaderOptions &options,
PandaNode *node) const {
BamFile bam_file;
bool report_errors = (options.get_flags() & LoaderOptions::LF_report_errors) != 0;
bool okflag = false;
if (bam_file.open_write(path, report_errors)) {
if (bam_file.write_object(node)) {
okflag = true;
}
bam_file.close();
}
return okflag;
}

View File

@ -31,8 +31,13 @@ public:
virtual string get_extension() const;
virtual bool supports_compressed() const;
virtual bool supports_load() const;
virtual bool supports_save() const;
virtual PT(PandaNode) load_file(const Filename &path, const LoaderOptions &options,
BamCacheRecord *record) const;
virtual bool save_file(const Filename &path, const LoaderOptions &options,
PandaNode *node) const;
public:
static TypeHandle get_class_type() {

View File

@ -0,0 +1,82 @@
// Filename: modelSaveRequest.I
// Created by: drose (19Dec12)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: ModelSaveRequest::get_filename
// Access: Published
// Description: Returns the filename associated with this
// asynchronous ModelSaveRequest.
////////////////////////////////////////////////////////////////////
INLINE const Filename &ModelSaveRequest::
get_filename() const {
return _filename;
}
////////////////////////////////////////////////////////////////////
// Function: ModelSaveRequest::get_options
// Access: Published
// Description: Returns the LoaderOptions associated with this
// asynchronous ModelSaveRequest.
////////////////////////////////////////////////////////////////////
INLINE const LoaderOptions &ModelSaveRequest::
get_options() const {
return _options;
}
////////////////////////////////////////////////////////////////////
// Function: ModelSaveRequest::get_node
// Access: Published
// Description: Returns the node that was passed to the constructor.
////////////////////////////////////////////////////////////////////
INLINE PandaNode *ModelSaveRequest::
get_node() const {
return _node;
}
////////////////////////////////////////////////////////////////////
// Function: ModelSaveRequest::get_loader
// Access: Published
// Description: Returns the Loader object associated with this
// asynchronous ModelSaveRequest.
////////////////////////////////////////////////////////////////////
INLINE Loader *ModelSaveRequest::
get_loader() const {
return _loader;
}
////////////////////////////////////////////////////////////////////
// Function: ModelSaveRequest::is_ready
// Access: Published
// Description: Returns true if this request has completed, false if
// it is still pending. When this returns true, you may
// retrieve the success flag with get_success().
////////////////////////////////////////////////////////////////////
INLINE bool ModelSaveRequest::
is_ready() const {
return _is_ready;
}
////////////////////////////////////////////////////////////////////
// Function: ModelSaveRequest::get_success
// Access: Published
// Description: Returns the true if the model was saved successfully,
// false otherwise. It is an error to call this unless
// is_ready() returns true.
////////////////////////////////////////////////////////////////////
INLINE bool ModelSaveRequest::
get_success() const {
nassertr(_is_ready, NULL);
return _success;
}

View File

@ -0,0 +1,58 @@
// Filename: modelSaveRequest.cxx
// Created by: drose (19Dec12)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
#include "modelSaveRequest.h"
#include "loader.h"
#include "config_pgraph.h"
TypeHandle ModelSaveRequest::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: ModelSaveRequest::Constructor
// Access: Published
// Description: Create a new ModelSaveRequest, and add it to the loader
// via save_async(), to begin an asynchronous save.
////////////////////////////////////////////////////////////////////
ModelSaveRequest::
ModelSaveRequest(const string &name,
const Filename &filename, const LoaderOptions &options,
PandaNode *node, Loader *loader) :
AsyncTask(name),
_filename(filename),
_options(options),
_node(node),
_loader(loader),
_is_ready(false),
_success(false)
{
}
////////////////////////////////////////////////////////////////////
// Function: ModelSaveRequest::do_task
// Access: Protected, Virtual
// Description: Performs the task: that is, saves the one model.
////////////////////////////////////////////////////////////////////
AsyncTask::DoneStatus ModelSaveRequest::
do_task() {
double delay = async_load_delay;
if (delay != 0.0) {
Thread::sleep(delay);
}
_success = _loader->save_sync(_filename, _options, _node);
_is_ready = true;
// Don't continue the task; we're done.
return DS_done;
}

View File

@ -0,0 +1,83 @@
// Filename: modelSaveRequest.h
// Created by: drose (19Dec12)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
#ifndef MODELSAVEREQUEST
#define MODELSAVEREQUEST
#include "pandabase.h"
#include "asyncTask.h"
#include "filename.h"
#include "loaderOptions.h"
#include "pandaNode.h"
#include "pointerTo.h"
#include "loader.h"
////////////////////////////////////////////////////////////////////
// Class : ModelSaveRequest
// Description : A class object that manages a single asynchronous
// model save request. Create a new ModelSaveRequest,
// and add it to the loader via save_async(), to begin
// an asynchronous save.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA_PGRAPH ModelSaveRequest : public AsyncTask {
public:
ALLOC_DELETED_CHAIN(ModelSaveRequest);
PUBLISHED:
ModelSaveRequest(const string &name,
const Filename &filename,
const LoaderOptions &options,
PandaNode *node, Loader *loader);
INLINE const Filename &get_filename() const;
INLINE const LoaderOptions &get_options() const;
INLINE PandaNode *get_node() const;
INLINE Loader *get_loader() const;
INLINE bool is_ready() const;
INLINE bool get_success() const;
protected:
virtual DoneStatus do_task();
private:
Filename _filename;
LoaderOptions _options;
PT(PandaNode) _node;
PT(Loader) _loader;
bool _is_ready;
bool _success;
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
AsyncTask::init_type();
register_type(_type_handle, "ModelSaveRequest",
AsyncTask::get_class_type());
}
virtual TypeHandle get_type() const {
return get_class_type();
}
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
private:
static TypeHandle _type_handle;
};
#include "modelSaveRequest.I"
#endif

View File

@ -11,6 +11,7 @@
#include "materialCollection.cxx"
#include "modelFlattenRequest.cxx"
#include "modelLoadRequest.cxx"
#include "modelSaveRequest.cxx"
#include "modelNode.cxx"
#include "modelPool.cxx"
#include "modelRoot.cxx"

File diff suppressed because it is too large Load Diff

View File

@ -18,33 +18,6 @@
#include "pandatoolbase.h"
#include "somethingToEgg.h"
#include "luse.h"
#include "eggTextureCollection.h"
#include "eggMaterialCollection.h"
class WorkingNodePath;
class EggGroup;
class EggGroupNode;
class EggVertexPool;
class EggTexture;
class LODNode;
class SequenceNode;
class SwitchNode;
class AnimBundleNode;
class AnimGroup;
class Character;
class PartGroup;
class CollisionNode;
class GeomNode;
class GeomVertexData;
class GeomPrimitive;
class PandaNode;
class RenderState;
class Texture;
class CharacterJoint;
class EggVertex;
typedef pmap<const CharacterJoint*, pvector<pair<EggVertex*,PN_stdfloat> > > CharacterJointMap;
////////////////////////////////////////////////////////////////////
// Class : BamToEgg
@ -59,46 +32,6 @@ public:
void run();
private:
void convert_node(const WorkingNodePath &node_path, EggGroupNode *egg_parent,
bool has_decal);
void convert_lod_node(LODNode *node, const WorkingNodePath &node_path,
EggGroupNode *egg_parent, bool has_decal);
void convert_sequence_node(SequenceNode *node, const WorkingNodePath &node_path,
EggGroupNode *egg_parent, bool has_decal);
void convert_switch_node(SwitchNode *node, const WorkingNodePath &node_path,
EggGroupNode *egg_parent, bool has_decal);
EggGroupNode *convert_animGroup_node(AnimGroup *animGroup, double fps );
void convert_anim_node(AnimBundleNode *node, const WorkingNodePath &node_path,
EggGroupNode *egg_parent, bool has_decal);
void convert_character_node(Character *node, const WorkingNodePath &node_path,
EggGroupNode *egg_parent, bool has_decal);
void convert_character_bundle(PartGroup *bundleNode, EggGroupNode *egg_parent, CharacterJointMap *jointMap);
void convert_collision_node(CollisionNode *node, const WorkingNodePath &node_path,
EggGroupNode *egg_parent, bool has_decal);
void convert_geom_node(GeomNode *node, const WorkingNodePath &node_path,
EggGroupNode *egg_parent, bool has_decal, CharacterJointMap *jointMap=NULL);
void convert_primitive(const GeomVertexData *vertex_data,
const GeomPrimitive *primitive,
const RenderState *net_state,
const LMatrix4 &net_mat, EggGroupNode *egg_parent,
CharacterJointMap *jointMap);
void recurse_nodes(const WorkingNodePath &node_path, EggGroupNode *egg_parent,
bool has_decal);
bool apply_node_properties(EggGroup *egg_group, PandaNode *node, bool allow_backstage = true);
bool apply_tags(EggGroup *egg_group, PandaNode *node);
bool apply_tag(EggGroup *egg_group, PandaNode *node, const string &tag);
EggTexture *get_egg_texture(Texture *tex);
static EggPrimitive *make_egg_polygon();
static EggPrimitive *make_egg_patch();
static EggPrimitive *make_egg_point();
static EggPrimitive *make_egg_line();
EggVertexPool *_vpool;
EggTextureCollection _textures;
EggMaterialCollection _materials;
};
#endif

View File

@ -13,9 +13,12 @@
#define SOURCES \
somethingToEggConverter.I somethingToEggConverter.cxx \
somethingToEggConverter.h
somethingToEggConverter.h \
eggToSomethingConverter.I eggToSomethingConverter.cxx \
eggToSomethingConverter.h
#define INSTALL_HEADERS \
somethingToEggConverter.I somethingToEggConverter.h
somethingToEggConverter.I somethingToEggConverter.h \
eggToSomethingConverter.I eggToSomethingConverter.h
#end ss_lib_target

View File

@ -0,0 +1,81 @@
// Filename: eggToSomethingConverter.I
// Created by: drose (26Sep12)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: EggToSomethingConverter::clear_error
// Access: Public
// Description: Resets the error flag to the no-error state.
// had_error() will return false until a new error is
// generated.
////////////////////////////////////////////////////////////////////
INLINE void EggToSomethingConverter::
clear_error() {
_error = false;
}
////////////////////////////////////////////////////////////////////
// Function: EggToSomethingConverter::had_error
// Access: Public
// Description: Returns true if an error was detected during the
// conversion process, false otherwise.
////////////////////////////////////////////////////////////////////
INLINE bool EggToSomethingConverter::
had_error() const {
return _error;
}
////////////////////////////////////////////////////////////////////
// Function: EggToSomethingConverter::clear_egg_data
// Access: Public
// Description: Sets the EggData to NULL and makes the converter
// invalid.
////////////////////////////////////////////////////////////////////
INLINE void EggToSomethingConverter::
clear_egg_data() {
set_egg_data((EggData *)NULL);
}
////////////////////////////////////////////////////////////////////
// Function: EggToSomethingConverter::get_egg_data
// Access: Public
// Description: Returns the EggData structure.
////////////////////////////////////////////////////////////////////
INLINE EggData *EggToSomethingConverter::
get_egg_data() {
return _egg_data;
}
////////////////////////////////////////////////////////////////////
// Function: EggToSomethingConverter::set_output_units
// Access: Public
// Description: Specifies the units that the EggData has already been
// scaled to. This is informational only; if the target
// file format supports it, this information will be
// written to the header.
////////////////////////////////////////////////////////////////////
void EggToSomethingConverter::
set_output_units(DistanceUnit output_units) {
_output_units = output_units;
}
////////////////////////////////////////////////////////////////////
// Function: EggToSomethingConverter::get_output_units
// Access: Public
// Description: Returns the value supplied to set_output_units().
////////////////////////////////////////////////////////////////////
DistanceUnit EggToSomethingConverter::
get_output_units() const {
return _output_units;
}

View File

@ -0,0 +1,85 @@
// Filename: eggToSomethingConverter.cxx
// Created by: drose (26Apr01)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
#include "eggToSomethingConverter.h"
#include "eggData.h"
////////////////////////////////////////////////////////////////////
// Function: EggToSomethingConverter::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
EggToSomethingConverter::
EggToSomethingConverter() {
_egg_data = (EggData *)NULL;
_error = false;
}
////////////////////////////////////////////////////////////////////
// Function: EggToSomethingConverter::Copy Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
EggToSomethingConverter::
EggToSomethingConverter(const EggToSomethingConverter &copy) {
_egg_data = (EggData *)NULL;
_error = false;
}
////////////////////////////////////////////////////////////////////
// Function: EggToSomethingConverter::Destructor
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
EggToSomethingConverter::
~EggToSomethingConverter() {
clear_egg_data();
}
////////////////////////////////////////////////////////////////////
// Function: EggToSomethingConverter::set_egg_data
// Access: Public
// Description: Sets the egg data that will be filled in when
// convert_file() is called. This must be called before
// convert_file().
////////////////////////////////////////////////////////////////////
void EggToSomethingConverter::
set_egg_data(EggData *egg_data) {
_egg_data = egg_data;
}
////////////////////////////////////////////////////////////////////
// Function: EggToSomethingConverter::get_additional_extensions
// Access: Public, Virtual
// Description: Returns a space-separated list of extension, in
// addition to the one returned by get_extension(), that
// are recognized by this converter.
////////////////////////////////////////////////////////////////////
string EggToSomethingConverter::
get_additional_extensions() const {
return string();
}
////////////////////////////////////////////////////////////////////
// Function: EggToSomethingConverter::supports_compressed
// Access: Published, Virtual
// Description: Returns true if this file type can transparently save
// compressed files (with a .pz extension), false
// otherwise.
////////////////////////////////////////////////////////////////////
bool EggToSomethingConverter::
supports_compressed() const {
return false;
}

View File

@ -0,0 +1,77 @@
// Filename: eggToSomethingConverter.h
// Created by: drose (26Sep12)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
#ifndef EGGTOSOMETHINGCONVERTER_H
#define EGGTOSOMETHINGCONVERTER_H
#include "pandatoolbase.h"
#include "filename.h"
#include "pointerTo.h"
#include "distanceUnit.h"
#include "coordinateSystem.h"
class EggData;
class EggGroupNode;
////////////////////////////////////////////////////////////////////
// Class : EggToSomethingConverter
// Description : This is a base class for a family of converter
// classes that manage a conversion from egg format to
// some other file type.
//
// Classes of this type can be used to implement egg2xxx
// converter programs, as well as LoaderFileTypeXXX
// run-time savers.
////////////////////////////////////////////////////////////////////
class EggToSomethingConverter {
public:
EggToSomethingConverter();
EggToSomethingConverter(const EggToSomethingConverter &copy);
virtual ~EggToSomethingConverter();
virtual EggToSomethingConverter *make_copy()=0;
INLINE void clear_error();
INLINE bool had_error() const;
void set_egg_data(EggData *egg_data);
INLINE void clear_egg_data();
INLINE EggData *get_egg_data();
INLINE void set_output_units(DistanceUnit output_units);
INLINE DistanceUnit get_output_units() const;
INLINE void set_output_coordinate_system(CoordinateSystem output_coordinate_system) const;
INLINE CoordinateSystem get_output_coordinate_system() const;
virtual string get_name() const=0;
virtual string get_extension() const=0;
virtual string get_additional_extensions() const;
virtual bool supports_compressed() const;
virtual bool write_file(const Filename &filename)=0;
protected:
PT(EggData) _egg_data;
DistanceUnit _output_units;
CoordinateSystem _output_coordinate_system;
bool _error;
};
#include "eggToSomethingConverter.I"
#endif

View File

@ -15,9 +15,11 @@
#define SOURCES \
config_objegg.cxx config_objegg.h \
objToEggConverter.cxx objToEggConverter.h
objToEggConverter.cxx objToEggConverter.h \
eggToObjConverter.cxx eggToObjConverter.h
#define INSTALL_HEADERS \
objToEggConverter.h
objToEggConverter.h \
eggToObjConverter.h
#end ss_lib_target

View File

@ -0,0 +1,445 @@
// Filename: eggToObjConverter.cxx
// Created by: drose (19Dec12)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
#include "eggToObjConverter.h"
#include "config_objegg.h"
#include "eggData.h"
#include "string_utils.h"
#include "streamReader.h"
#include "virtualFileSystem.h"
#include "eggPolygon.h"
#include "dcast.h"
////////////////////////////////////////////////////////////////////
// Function: EggToObjConverter::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
EggToObjConverter::
EggToObjConverter() {
}
////////////////////////////////////////////////////////////////////
// Function: EggToObjConverter::Copy Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
EggToObjConverter::
EggToObjConverter(const EggToObjConverter &copy) :
EggToSomethingConverter(copy)
{
}
////////////////////////////////////////////////////////////////////
// Function: EggToObjConverter::Destructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
EggToObjConverter::
~EggToObjConverter() {
}
////////////////////////////////////////////////////////////////////
// Function: EggToObjConverter::make_copy
// Access: Public, Virtual
// Description: Allocates and returns a new copy of the converter.
////////////////////////////////////////////////////////////////////
EggToSomethingConverter *EggToObjConverter::
make_copy() {
return new EggToObjConverter(*this);
}
////////////////////////////////////////////////////////////////////
// Function: EggToObjConverter::get_name
// Access: Public, Virtual
// Description: Returns the English name of the file type this
// converter supports.
////////////////////////////////////////////////////////////////////
string EggToObjConverter::
get_name() const {
return "obj";
}
////////////////////////////////////////////////////////////////////
// Function: EggToObjConverter::get_extension
// Access: Public, Virtual
// Description: Returns the common extension of the file type this
// converter supports.
////////////////////////////////////////////////////////////////////
string EggToObjConverter::
get_extension() const {
return "obj";
}
////////////////////////////////////////////////////////////////////
// Function: EggToObjConverter::supports_compressed
// Access: Published, Virtual
// Description: Returns true if this file type can transparently save
// compressed files (with a .pz extension), false
// otherwise.
////////////////////////////////////////////////////////////////////
bool EggToObjConverter::
supports_compressed() const {
return true;
}
////////////////////////////////////////////////////////////////////
// Function: EggToObjConverter::write_file
// Access: Public, Virtual
// Description: Handles the conversion of the internal EggData to the
// target file format, written to the specified
// filename.
////////////////////////////////////////////////////////////////////
bool EggToObjConverter::
write_file(const Filename &filename) {
clear_error();
if (_egg_data->get_coordinate_system() == CS_default) {
_egg_data->set_coordinate_system(CS_zup_right);
}
if (!process(filename)) {
_error = true;
}
return !had_error();
}
////////////////////////////////////////////////////////////////////
// Function: EggToObjConverter::process
// Access: Private
// Description:
////////////////////////////////////////////////////////////////////
bool EggToObjConverter::
process(const Filename &filename) {
_egg_data->flatten_transforms();
collect_vertices(_egg_data);
VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
Filename obj_filename = Filename::text_filename(filename);
vfs->delete_file(obj_filename);
ostream *file = vfs->open_write_file(obj_filename, true, true);
if (file == (ostream *)NULL) {
return false;
}
_current_group = NULL;
/*
(*file) << "\n#\n"
<< "# obj file generated by the following command:\n"
<< "# " << get_exec_command() << "\n"
<< "#\n\n";
*/
write_vertices(*file, "v", 3, _unique_vert3);
write_vertices(*file, "v", 4, _unique_vert4);
write_vertices(*file, "vt", 2, _unique_uv2);
write_vertices(*file, "vt", 3, _unique_uv3);
write_vertices(*file, "vn", 3, _unique_norm);
write_faces(*file, _egg_data);
bool success = (void *)(*file) != NULL;
vfs->close_write_file(file);
return success;
}
////////////////////////////////////////////////////////////////////
// Function: EggToObjConverter::collect_vertices
// Access: Private
// Description: Recursively walks the egg structure, looking for
// vertices referenced by polygons. Any such vertices
// are added to the vertex tables for writing to the obj
// file.
////////////////////////////////////////////////////////////////////
void EggToObjConverter::
collect_vertices(EggNode *egg_node) {
if (egg_node->is_of_type(EggPolygon::get_class_type())) {
EggPolygon *egg_poly = DCAST(EggPolygon, egg_node);
EggPolygon::iterator pi;
for (pi = egg_poly->begin(); pi != egg_poly->end(); ++pi) {
record_vertex(*pi);
}
} else if (egg_node->is_of_type(EggGroupNode::get_class_type())) {
EggGroupNode *egg_group = DCAST(EggGroupNode, egg_node);
EggGroupNode::iterator ci;
for (ci = egg_group->begin(); ci != egg_group->end(); ++ci) {
collect_vertices(*ci);
}
}
}
////////////////////////////////////////////////////////////////////
// Function: EggToObjConverter::write_faces
// Access: Private
// Description: Recursively walks the egg structure again, this time
// writing out the face records for any polygons
// encountered.
////////////////////////////////////////////////////////////////////
void EggToObjConverter::
write_faces(ostream &out, EggNode *egg_node) {
if (egg_node->is_of_type(EggPolygon::get_class_type())) {
write_group_reference(out, egg_node);
EggPolygon *egg_poly = DCAST(EggPolygon, egg_node);
out << "f";
EggPolygon::iterator pi;
for (pi = egg_poly->begin(); pi != egg_poly->end(); ++pi) {
VertexDef &vdef = _vmap[(*pi)];
int vert_index = -1;
int uv_index = -1;
int norm_index = -1;
if (vdef._vert3_index != -1) {
vert_index = vdef._vert3_index + 1;
} else if (vdef._vert4_index != -1) {
vert_index = vdef._vert4_index + 1 + (int)_unique_vert3.size();
}
if (vdef._uv2_index != -1) {
uv_index = vdef._uv2_index + 1;
} else if (vdef._uv3_index != -1) {
uv_index = vdef._uv3_index + 1 + (int)_unique_uv2.size();
}
if (vdef._norm_index != -1) {
norm_index = vdef._norm_index + 1;
}
if (vert_index == -1) {
continue;
}
if (norm_index != -1) {
if (uv_index != -1) {
out << " " << vert_index << "/" << uv_index << "/" << norm_index;
} else {
out << " " << vert_index << "//" << norm_index;
}
} else if (uv_index != -1) {
out << " " << vert_index << "/" << uv_index;
} else {
out << " " << vert_index;
}
}
out << "\n";
} else if (egg_node->is_of_type(EggGroupNode::get_class_type())) {
EggGroupNode *egg_group = DCAST(EggGroupNode, egg_node);
EggGroupNode::iterator ci;
for (ci = egg_group->begin(); ci != egg_group->end(); ++ci) {
write_faces(out, *ci);
}
}
}
////////////////////////////////////////////////////////////////////
// Function: EggToObjConverter::write_group_reference
// Access: Private
// Description: Writes the "g" tag to describe this polygon's group,
// if needed.
////////////////////////////////////////////////////////////////////
void EggToObjConverter::
write_group_reference(ostream &out, EggNode *egg_node) {
EggGroupNode *egg_group = egg_node->get_parent();
if (egg_group == _current_group) {
// Same group we wrote last time.
return;
}
string group_name;
get_group_name(group_name, egg_group);
if (group_name.empty()) {
out << "g default\n";
} else {
out << "g" << group_name << "\n";
}
_current_group = egg_group;
}
////////////////////////////////////////////////////////////////////
// Function: EggToObjConverter::get_group_name
// Access: Private
// Description: Recursively determines the appropriate string to
// write for the "g" tag to describe a particular
// EggGroupNode.
////////////////////////////////////////////////////////////////////
void EggToObjConverter::
get_group_name(string &group_name, EggGroupNode *egg_group) {
string name = trim(egg_group->get_name());
if (!name.empty()) {
group_name += ' ';
// Remove nonstandard characters.
for (string::const_iterator ni = name.begin(); ni != name.end(); ++ni) {
char c = (*ni);
if (!isalnum(c)) {
c = '_';
}
group_name += c;
}
}
// Now recurse.
EggGroupNode *egg_parent = egg_group->get_parent();
if (egg_parent != NULL) {
get_group_name(group_name, egg_parent);
}
}
////////////////////////////////////////////////////////////////////
// Function: EggToObjConverter::record_vertex
// Access: Private
// Description: Adds the indicated EggVertex to the unique vertex
// tables, for writing later by write_vertices().
////////////////////////////////////////////////////////////////////
void EggToObjConverter::
record_vertex(EggVertex *vertex) {
VertexDef &vdef = _vmap[vertex];
switch (vertex->get_num_dimensions()) {
case 1:
vdef._vert3_index = record_unique(_unique_vert3, vertex->get_pos1());
break;
case 2:
vdef._vert3_index = record_unique(_unique_vert3, vertex->get_pos2());
break;
case 3:
vdef._vert3_index = record_unique(_unique_vert3, vertex->get_pos3());
break;
case 4:
vdef._vert4_index = record_unique(_unique_vert4, vertex->get_pos4());
break;
}
if (vertex->has_uv("")) {
vdef._uv2_index = record_unique(_unique_uv2, vertex->get_uv(""));
} else if (vertex->has_uvw("")) {
vdef._uv3_index = record_unique(_unique_uv3, vertex->get_uvw(""));
}
if (vertex->has_normal()) {
vdef._norm_index = record_unique(_unique_norm, vertex->get_normal());
}
}
////////////////////////////////////////////////////////////////////
// Function: EggToObjConverter::record_unique
// Access: Private
// Description: Records the indicated vertex value, returning the
// shared index if this value already appears elsewhere
// in the table, or the new unique index if this is the
// first time this value appears.
////////////////////////////////////////////////////////////////////
int EggToObjConverter::
record_unique(UniqueVertices &unique, const LVecBase4d &vec) {
// We record a zero-based index. Note that we will actually write
// out a one-based index to the obj file, as required by the
// standard.
int index = unique.size();
UniqueVertices::iterator ui = unique.insert(UniqueVertices::value_type(vec, index)).first;
return (*ui).second;
}
////////////////////////////////////////////////////////////////////
// Function: EggToObjConverter::record_unique
// Access: Private
// Description: Records the indicated vertex value, returning the
// shared index if this value already appears elsewhere
// in the table, or the new unique index if this is the
// first time this value appears.
////////////////////////////////////////////////////////////////////
int EggToObjConverter::
record_unique(UniqueVertices &unique, const LVecBase3d &vec) {
return record_unique(unique, LVecBase4d(vec[0], vec[1], vec[2], 0.0));
}
////////////////////////////////////////////////////////////////////
// Function: EggToObjConverter::record_unique
// Access: Private
// Description: Records the indicated vertex value, returning the
// shared index if this value already appears elsewhere
// in the table, or the new unique index if this is the
// first time this value appears.
////////////////////////////////////////////////////////////////////
int EggToObjConverter::
record_unique(UniqueVertices &unique, const LVecBase2d &vec) {
return record_unique(unique, LVecBase4d(vec[0], vec[1], 0.0, 0.0));
}
////////////////////////////////////////////////////////////////////
// Function: EggToObjConverter::record_unique
// Access: Private
// Description: Records the indicated vertex value, returning the
// shared index if this value already appears elsewhere
// in the table, or the new unique index if this is the
// first time this value appears.
////////////////////////////////////////////////////////////////////
int EggToObjConverter::
record_unique(UniqueVertices &unique, double pos) {
return record_unique(unique, LVecBase4d(pos, 0.0, 0.0, 0.0));
}
////////////////////////////////////////////////////////////////////
// Function: EggToObjConverter::write_vertices
// Access: Private
// Description: Actually writes the vertex values recorded in the
// indicated table to the obj output stream.
////////////////////////////////////////////////////////////////////
void EggToObjConverter::
write_vertices(ostream &out, const string &prefix, int num_components,
const UniqueVertices &unique) {
// First, sort the list into numeric order.
int num_vertices = (int)unique.size();
const LVecBase4d **vertices = (const LVecBase4d **)alloca(num_vertices * sizeof(LVecBase4d *));
memset(vertices, 0, num_vertices * sizeof(LVecBase4d *));
UniqueVertices::const_iterator ui;
for (ui = unique.begin(); ui != unique.end(); ++ui) {
int index = (*ui).second;
const LVecBase4d &vec = (*ui).first;
nassertv(index >= 0 && index < num_vertices);
nassertv(vertices[index] == NULL);
vertices[index] = &vec;
}
for (int i = 0; i < num_vertices; ++i) {
out << prefix;
const LVecBase4d &vec = *(vertices[i]);
for (int ci = 0; ci < num_components; ++ci) {
out << " " << vec[ci];
}
out << "\n";
}
}
////////////////////////////////////////////////////////////////////
// Function: EggToObjConverter::VertexDef::Constructor
// Access: Private
// Description:
////////////////////////////////////////////////////////////////////
EggToObjConverter::VertexDef::
VertexDef() :
_vert3_index(-1),
_vert4_index(-1),
_uv2_index(-1),
_uv3_index(-1),
_norm_index(-1)
{
}

View File

@ -0,0 +1,79 @@
// Filename: eggToObjConverter.h
// Created by: drose (19Dec12)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
#ifndef EGGTOOBJCONVERTER_H
#define EGGTOOBJCONVERTER_H
#include "pandatoolbase.h"
#include "eggToSomethingConverter.h"
#include "eggVertexPool.h"
#include "eggGroup.h"
////////////////////////////////////////////////////////////////////
// Class : EggToObjConverter
// Description : Convert an obj file to egg data.
////////////////////////////////////////////////////////////////////
class EggToObjConverter : public EggToSomethingConverter {
public:
EggToObjConverter();
EggToObjConverter(const EggToObjConverter &copy);
~EggToObjConverter();
virtual EggToSomethingConverter *make_copy();
virtual string get_name() const;
virtual string get_extension() const;
virtual bool supports_compressed() const;
virtual bool write_file(const Filename &filename);
private:
typedef pmap<LVecBase4d, int> UniqueVertices;
class VertexDef {
public:
VertexDef();
int _vert3_index;
int _vert4_index;
int _uv2_index;
int _uv3_index;
int _norm_index;
};
typedef pmap<EggVertex *, VertexDef> VertexMap;
bool process(const Filename &filename);
void collect_vertices(EggNode *egg_node);
void write_faces(ostream &out, EggNode *egg_node);
void write_group_reference(ostream &out, EggNode *egg_node);
void get_group_name(string &group_name, EggGroupNode *egg_group);
void record_vertex(EggVertex *vertex);
int record_unique(UniqueVertices &unique, const LVecBase4d &vec);
int record_unique(UniqueVertices &unique, const LVecBase3d &vec);
int record_unique(UniqueVertices &unique, const LVecBase2d &vec);
int record_unique(UniqueVertices &unique, double pos);
void write_vertices(ostream &out, const string &prefix, int num_components,
const UniqueVertices &unique);
private:
bool _triangulate_polygons;
UniqueVertices _unique_vert3, _unique_vert4, _unique_uv2, _unique_uv3, _unique_norm;
VertexMap _vmap;
EggGroupNode *_current_group;
};
#endif

View File

@ -12,8 +12,8 @@
//
////////////////////////////////////////////////////////////////////
#ifndef ObjTOEGGCONVERTER_H
#define ObjTOEGGCONVERTER_H
#ifndef OBJTOEGGCONVERTER_H
#define OBJTOEGGCONVERTER_H
#include "pandatoolbase.h"

View File

@ -22,7 +22,7 @@
#begin bin_target
#define TARGET egg2obj
#define LOCAL_LIBS p3eggbase p3progbase
#define LOCAL_LIBS p3objegg p3eggbase p3progbase
#define SOURCES \
eggToObj.cxx eggToObj.h

View File

@ -60,26 +60,10 @@ run() {
nout << " (" << num_produced << " triangles produced.)\n";
}
_data->flatten_transforms();
collect_vertices(_data);
EggToObjConverter saver;
saver.set_egg_data(_data);
ostream &out = get_output();
_current_group = NULL;
out << "\n#\n"
<< "# obj file generated by the following command:\n"
<< "# " << get_exec_command() << "\n"
<< "#\n\n";
write_vertices(out, "v", 3, _unique_vert3);
write_vertices(out, "v", 4, _unique_vert4);
write_vertices(out, "vt", 2, _unique_uv2);
write_vertices(out, "vt", 3, _unique_uv3);
write_vertices(out, "vn", 3, _unique_norm);
write_faces(out, _data);
if (!out) {
if (!saver.write_file(get_output_filename())) {
nout << "An error occurred while writing.\n";
exit(1);
}
@ -98,293 +82,6 @@ handle_args(ProgramBase::Args &args) {
return EggToSomething::handle_args(args);
}
////////////////////////////////////////////////////////////////////
// Function: EggToObj::collect_vertices
// Access: Private
// Description: Recursively walks the egg structure, looking for
// vertices referenced by polygons. Any such vertices
// are added to the vertex tables for writing to the obj
// file.
////////////////////////////////////////////////////////////////////
void EggToObj::
collect_vertices(EggNode *egg_node) {
if (egg_node->is_of_type(EggPolygon::get_class_type())) {
EggPolygon *egg_poly = DCAST(EggPolygon, egg_node);
EggPolygon::iterator pi;
for (pi = egg_poly->begin(); pi != egg_poly->end(); ++pi) {
record_vertex(*pi);
}
} else if (egg_node->is_of_type(EggGroupNode::get_class_type())) {
EggGroupNode *egg_group = DCAST(EggGroupNode, egg_node);
EggGroupNode::iterator ci;
for (ci = egg_group->begin(); ci != egg_group->end(); ++ci) {
collect_vertices(*ci);
}
}
}
////////////////////////////////////////////////////////////////////
// Function: EggToObj::write_faces
// Access: Private
// Description: Recursively walks the egg structure again, this time
// writing out the face records for any polygons
// encountered.
////////////////////////////////////////////////////////////////////
void EggToObj::
write_faces(ostream &out, EggNode *egg_node) {
if (egg_node->is_of_type(EggPolygon::get_class_type())) {
write_group_reference(out, egg_node);
EggPolygon *egg_poly = DCAST(EggPolygon, egg_node);
out << "f";
EggPolygon::iterator pi;
for (pi = egg_poly->begin(); pi != egg_poly->end(); ++pi) {
VertexDef &vdef = _vmap[(*pi)];
int vert_index = -1;
int uv_index = -1;
int norm_index = -1;
if (vdef._vert3_index != -1) {
vert_index = vdef._vert3_index + 1;
} else if (vdef._vert4_index != -1) {
vert_index = vdef._vert4_index + 1 + (int)_unique_vert3.size();
}
if (vdef._uv2_index != -1) {
uv_index = vdef._uv2_index + 1;
} else if (vdef._uv3_index != -1) {
uv_index = vdef._uv3_index + 1 + (int)_unique_uv2.size();
}
if (vdef._norm_index != -1) {
norm_index = vdef._norm_index + 1;
}
if (vert_index == -1) {
continue;
}
if (norm_index != -1) {
if (uv_index != -1) {
out << " " << vert_index << "/" << uv_index << "/" << norm_index;
} else {
out << " " << vert_index << "//" << norm_index;
}
} else if (uv_index != -1) {
out << " " << vert_index << "/" << uv_index;
} else {
out << " " << vert_index;
}
}
out << "\n";
} else if (egg_node->is_of_type(EggGroupNode::get_class_type())) {
EggGroupNode *egg_group = DCAST(EggGroupNode, egg_node);
EggGroupNode::iterator ci;
for (ci = egg_group->begin(); ci != egg_group->end(); ++ci) {
write_faces(out, *ci);
}
}
}
////////////////////////////////////////////////////////////////////
// Function: EggToObj::write_group_reference
// Access: Private
// Description: Writes the "g" tag to describe this polygon's group,
// if needed.
////////////////////////////////////////////////////////////////////
void EggToObj::
write_group_reference(ostream &out, EggNode *egg_node) {
EggGroupNode *egg_group = egg_node->get_parent();
if (egg_group == _current_group) {
// Same group we wrote last time.
return;
}
string group_name;
get_group_name(group_name, egg_group);
if (group_name.empty()) {
out << "g default\n";
} else {
out << "g" << group_name << "\n";
}
_current_group = egg_group;
}
////////////////////////////////////////////////////////////////////
// Function: EggToObj::get_group_name
// Access: Private
// Description: Recursively determines the appropriate string to
// write for the "g" tag to describe a particular
// EggGroupNode.
////////////////////////////////////////////////////////////////////
void EggToObj::
get_group_name(string &group_name, EggGroupNode *egg_group) {
string name = trim(egg_group->get_name());
if (!name.empty()) {
group_name += ' ';
// Remove nonstandard characters.
for (string::const_iterator ni = name.begin(); ni != name.end(); ++ni) {
char c = (*ni);
if (!isalnum(c)) {
c = '_';
}
group_name += c;
}
}
// Now recurse.
EggGroupNode *egg_parent = egg_group->get_parent();
if (egg_parent != NULL) {
get_group_name(group_name, egg_parent);
}
}
////////////////////////////////////////////////////////////////////
// Function: EggToObj::record_vertex
// Access: Private
// Description: Adds the indicated EggVertex to the unique vertex
// tables, for writing later by write_vertices().
////////////////////////////////////////////////////////////////////
void EggToObj::
record_vertex(EggVertex *vertex) {
VertexDef &vdef = _vmap[vertex];
switch (vertex->get_num_dimensions()) {
case 1:
vdef._vert3_index = record_unique(_unique_vert3, vertex->get_pos1());
break;
case 2:
vdef._vert3_index = record_unique(_unique_vert3, vertex->get_pos2());
break;
case 3:
vdef._vert3_index = record_unique(_unique_vert3, vertex->get_pos3());
break;
case 4:
vdef._vert4_index = record_unique(_unique_vert4, vertex->get_pos4());
break;
}
if (vertex->has_uv("")) {
vdef._uv2_index = record_unique(_unique_uv2, vertex->get_uv(""));
} else if (vertex->has_uvw("")) {
vdef._uv3_index = record_unique(_unique_uv3, vertex->get_uvw(""));
}
if (vertex->has_normal()) {
vdef._norm_index = record_unique(_unique_norm, vertex->get_normal());
}
}
////////////////////////////////////////////////////////////////////
// Function: EggToObj::record_unique
// Access: Private
// Description: Records the indicated vertex value, returning the
// shared index if this value already appears elsewhere
// in the table, or the new unique index if this is the
// first time this value appears.
////////////////////////////////////////////////////////////////////
int EggToObj::
record_unique(UniqueVertices &unique, const LVecBase4d &vec) {
// We record a zero-based index. Note that we will actually write
// out a one-based index to the obj file, as required by the
// standard.
int index = unique.size();
UniqueVertices::iterator ui = unique.insert(UniqueVertices::value_type(vec, index)).first;
return (*ui).second;
}
////////////////////////////////////////////////////////////////////
// Function: EggToObj::record_unique
// Access: Private
// Description: Records the indicated vertex value, returning the
// shared index if this value already appears elsewhere
// in the table, or the new unique index if this is the
// first time this value appears.
////////////////////////////////////////////////////////////////////
int EggToObj::
record_unique(UniqueVertices &unique, const LVecBase3d &vec) {
return record_unique(unique, LVecBase4d(vec[0], vec[1], vec[2], 0.0));
}
////////////////////////////////////////////////////////////////////
// Function: EggToObj::record_unique
// Access: Private
// Description: Records the indicated vertex value, returning the
// shared index if this value already appears elsewhere
// in the table, or the new unique index if this is the
// first time this value appears.
////////////////////////////////////////////////////////////////////
int EggToObj::
record_unique(UniqueVertices &unique, const LVecBase2d &vec) {
return record_unique(unique, LVecBase4d(vec[0], vec[1], 0.0, 0.0));
}
////////////////////////////////////////////////////////////////////
// Function: EggToObj::record_unique
// Access: Private
// Description: Records the indicated vertex value, returning the
// shared index if this value already appears elsewhere
// in the table, or the new unique index if this is the
// first time this value appears.
////////////////////////////////////////////////////////////////////
int EggToObj::
record_unique(UniqueVertices &unique, double pos) {
return record_unique(unique, LVecBase4d(pos, 0.0, 0.0, 0.0));
}
////////////////////////////////////////////////////////////////////
// Function: EggToObj::write_vertices
// Access: Private
// Description: Actually writes the vertex values recorded in the
// indicated table to the obj output stream.
////////////////////////////////////////////////////////////////////
void EggToObj::
write_vertices(ostream &out, const string &prefix, int num_components,
const UniqueVertices &unique) {
// First, sort the list into numeric order.
int num_vertices = (int)unique.size();
const LVecBase4d **vertices = (const LVecBase4d **)alloca(num_vertices * sizeof(LVecBase4d *));
memset(vertices, 0, num_vertices * sizeof(LVecBase4d *));
UniqueVertices::const_iterator ui;
for (ui = unique.begin(); ui != unique.end(); ++ui) {
int index = (*ui).second;
const LVecBase4d &vec = (*ui).first;
nassertv(index >= 0 && index < num_vertices);
nassertv(vertices[index] == NULL);
vertices[index] = &vec;
}
for (int i = 0; i < num_vertices; ++i) {
out << prefix;
const LVecBase4d &vec = *(vertices[i]);
for (int ci = 0; ci < num_components; ++ci) {
out << " " << vec[ci];
}
out << "\n";
}
}
////////////////////////////////////////////////////////////////////
// Function: EggToObj::VertexDef::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
EggToObj::VertexDef::
VertexDef() :
_vert3_index(-1),
_vert4_index(-1),
_uv2_index(-1),
_uv3_index(-1),
_norm_index(-1)
{
}
int main(int argc, char *argv[]) {
// A call to pystub() to force libpystub.so to be linked in.
pystub();

View File

@ -17,10 +17,7 @@
#include "pandatoolbase.h"
#include "eggToSomething.h"
#include "pmap.h"
class EggNode;
class EggVertex;
#include "eggToObjConverter.h"
////////////////////////////////////////////////////////////////////
// Class : EggToObj
@ -35,39 +32,8 @@ public:
protected:
virtual bool handle_args(Args &args);
private:
typedef pmap<LVecBase4d, int> UniqueVertices;
class VertexDef {
public:
VertexDef();
int _vert3_index;
int _vert4_index;
int _uv2_index;
int _uv3_index;
int _norm_index;
};
typedef pmap<EggVertex *, VertexDef> VertexMap;
void collect_vertices(EggNode *egg_node);
void write_faces(ostream &out, EggNode *egg_node);
void write_group_reference(ostream &out, EggNode *egg_node);
void get_group_name(string &group_name, EggGroupNode *egg_group);
void record_vertex(EggVertex *vertex);
int record_unique(UniqueVertices &unique, const LVecBase4d &vec);
int record_unique(UniqueVertices &unique, const LVecBase3d &vec);
int record_unique(UniqueVertices &unique, const LVecBase2d &vec);
int record_unique(UniqueVertices &unique, double pos);
void write_vertices(ostream &out, const string &prefix, int num_components,
const UniqueVertices &unique);
private:
bool _triangulate_polygons;
UniqueVertices _unique_vert3, _unique_vert4, _unique_uv2, _unique_uv3, _unique_norm;
VertexMap _vmap;
EggGroupNode *_current_group;
};
#endif

View File

@ -28,6 +28,7 @@
#include "dxfToEggConverter.h"
#include "vrmlToEggConverter.h"
#include "objToEggConverter.h"
#include "eggToObjConverter.h"
#include "config_xfile.h"
#include "xFileToEggConverter.h"
@ -91,8 +92,9 @@ init_libptloader() {
XFileToEggConverter *xfile = new XFileToEggConverter;
reg->register_type(new LoaderFileTypePandatool(xfile));
ObjToEggConverter *obj = new ObjToEggConverter;
reg->register_type(new LoaderFileTypePandatool(obj));
ObjToEggConverter *obj_egg = new ObjToEggConverter;
EggToObjConverter *egg_obj = new EggToObjConverter;
reg->register_type(new LoaderFileTypePandatool(obj_egg, egg_obj));
//#ifdef HAVE_FCOLLADA
// DAEToEggConverter *dae = new DAEToEggConverter;

View File

@ -15,8 +15,10 @@
#include "loaderFileTypePandatool.h"
#include "config_ptloader.h"
#include "somethingToEggConverter.h"
#include "eggToSomethingConverter.h"
#include "config_util.h"
#include "load_egg_file.h"
#include "save_egg_file.h"
#include "eggData.h"
#include "loaderOptions.h"
#include "bamCacheRecord.h"
@ -29,10 +31,13 @@ TypeHandle LoaderFileTypePandatool::_type_handle;
// Description:
////////////////////////////////////////////////////////////////////
LoaderFileTypePandatool::
LoaderFileTypePandatool(SomethingToEggConverter *converter) :
_converter(converter)
LoaderFileTypePandatool(SomethingToEggConverter *loader,
EggToSomethingConverter *saver) :
_loader(loader), _saver(saver)
{
converter->set_merge_externals(true);
if (_loader != (SomethingToEggConverter *)NULL) {
_loader->set_merge_externals(true);
}
}
////////////////////////////////////////////////////////////////////
@ -51,7 +56,10 @@ LoaderFileTypePandatool::
////////////////////////////////////////////////////////////////////
string LoaderFileTypePandatool::
get_name() const {
return _converter->get_name();
if (_loader != (SomethingToEggConverter *)NULL) {
return _loader->get_name();
}
return _saver->get_name();
}
////////////////////////////////////////////////////////////////////
@ -61,7 +69,10 @@ get_name() const {
////////////////////////////////////////////////////////////////////
string LoaderFileTypePandatool::
get_extension() const {
return _converter->get_extension();
if (_loader != (SomethingToEggConverter *)NULL) {
return _loader->get_extension();
}
return _saver->get_extension();
}
////////////////////////////////////////////////////////////////////
@ -73,7 +84,10 @@ get_extension() const {
////////////////////////////////////////////////////////////////////
string LoaderFileTypePandatool::
get_additional_extensions() const {
return _converter->get_additional_extensions();
if (_loader != (SomethingToEggConverter *)NULL) {
return _loader->get_additional_extensions();
}
return _saver->get_additional_extensions();
}
////////////////////////////////////////////////////////////////////
@ -85,7 +99,34 @@ get_additional_extensions() const {
////////////////////////////////////////////////////////////////////
bool LoaderFileTypePandatool::
supports_compressed() const {
return _converter->supports_compressed();
if (_loader != (SomethingToEggConverter *)NULL) {
return _loader->supports_compressed();
}
return _saver->supports_compressed();
}
////////////////////////////////////////////////////////////////////
// Function: LoaderFileTypePandatool::supports_load
// Access: Published, Virtual
// Description: Returns true if the file type can be used to load
// files, and load_file() is supported. Returns false
// if load_file() is unimplemented and will always fail.
////////////////////////////////////////////////////////////////////
bool LoaderFileTypePandatool::
supports_load() const {
return (_loader != NULL);
}
////////////////////////////////////////////////////////////////////
// Function: LoaderFileTypePandatool::supports_save
// Access: Published, Virtual
// Description: Returns true if the file type can be used to save
// files, and save_file() is supported. Returns false
// if save_file() is unimplemented and will always fail.
////////////////////////////////////////////////////////////////////
bool LoaderFileTypePandatool::
supports_save() const {
return (_saver != NULL);
}
////////////////////////////////////////////////////////////////////
@ -108,39 +149,44 @@ resolve_filename(Filename &path) const {
PT(PandaNode) LoaderFileTypePandatool::
load_file(const Filename &path, const LoaderOptions &options,
BamCacheRecord *record) const {
if (_loader == NULL) {
return NULL;
}
if (record != (BamCacheRecord *)NULL) {
record->add_dependent_file(path);
}
PT(PandaNode) result;
SomethingToEggConverter *loader = _loader->make_copy();
PT(EggData) egg_data = new EggData;
_converter->set_egg_data(egg_data);
loader->set_egg_data(egg_data);
DSearchPath file_path;
file_path.append_directory(path.get_dirname());
_converter->get_path_replace()->_path = file_path;
loader->get_path_replace()->_path = file_path;
// Convert animation, if the converter supports it.
switch (options.get_flags() & LoaderOptions::LF_convert_anim) {
case LoaderOptions::LF_convert_anim:
_converter->set_animation_convert(AC_both);
loader->set_animation_convert(AC_both);
break;
case LoaderOptions::LF_convert_skeleton:
_converter->set_animation_convert(AC_model);
loader->set_animation_convert(AC_model);
break;
case LoaderOptions::LF_convert_channels:
_converter->set_animation_convert(AC_chan);
loader->set_animation_convert(AC_chan);
break;
default:
break;
}
if (_converter->convert_file(path)) {
DistanceUnit input_units = _converter->get_input_units();
if (loader->convert_file(path)) {
DistanceUnit input_units = loader->get_input_units();
if (input_units != DU_invalid && ptloader_units != DU_invalid &&
input_units != ptloader_units) {
// Convert the file to the units specified by the ptloader-units
@ -160,6 +206,32 @@ load_file(const Filename &path, const LoaderOptions &options,
result = load_egg_data(egg_data);
}
_converter->clear_egg_data();
delete loader;
return result.p();
}
////////////////////////////////////////////////////////////////////
// Function: LoaderFileTypePandatool::save_file
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
bool LoaderFileTypePandatool::
save_file(const Filename &path, const LoaderOptions &options,
PandaNode *node) const {
if (_saver == NULL) {
return false;
}
PT(EggData) egg_data = new EggData;
if (!save_egg_data(egg_data, node)) {
return false;
}
EggToSomethingConverter *saver = _saver->make_copy();
saver->set_egg_data(egg_data);
bool result = saver->write_file(path);
delete saver;
}

View File

@ -20,6 +20,7 @@
#include "loaderFileType.h"
class SomethingToEggConverter;
class EggToSomethingConverter;
////////////////////////////////////////////////////////////////////
// Class : LoaderFileTypePandatool
@ -30,7 +31,8 @@ class SomethingToEggConverter;
////////////////////////////////////////////////////////////////////
class EXPCL_PTLOADER LoaderFileTypePandatool : public LoaderFileType {
public:
LoaderFileTypePandatool(SomethingToEggConverter *converter);
LoaderFileTypePandatool(SomethingToEggConverter *loader,
EggToSomethingConverter *saver = NULL);
virtual ~LoaderFileTypePandatool();
virtual string get_name() const;
@ -38,12 +40,18 @@ public:
virtual string get_additional_extensions() const;
virtual bool supports_compressed() const;
virtual bool supports_load() const;
virtual bool supports_save() const;
virtual void resolve_filename(Filename &path) const;
virtual PT(PandaNode) load_file(const Filename &path, const LoaderOptions &options,
BamCacheRecord *record) const;
virtual bool save_file(const Filename &path, const LoaderOptions &options,
PandaNode *node) const;
private:
SomethingToEggConverter *_converter;
SomethingToEggConverter *_loader;
EggToSomethingConverter *_saver;
public:
static TypeHandle get_class_type() {