mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-03 02:15:43 -04:00
loader.saveModel(), EggToObjConverter, etc.
This commit is contained in:
parent
a02e494ae3
commit
3af8da3bcd
@ -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)
|
||||
|
@ -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
25
panda/src/egg2pg/eggSaver.I
Executable 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
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
110
panda/src/egg2pg/eggSaver.h
Executable 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
|
@ -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);
|
||||
}
|
||||
|
@ -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() {
|
||||
|
@ -3,3 +3,4 @@
|
||||
#include "config_egg2pg.cxx"
|
||||
#include "egg_parametrics.cxx"
|
||||
#include "eggRenderState.cxx"
|
||||
#include "deferredNodeProperty.cxx"
|
||||
|
@ -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"
|
||||
|
||||
|
52
panda/src/egg2pg/save_egg_file.cxx
Executable file
52
panda/src/egg2pg/save_egg_file.cxx
Executable 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;
|
||||
}
|
44
panda/src/egg2pg/save_egg_file.h
Executable file
44
panda/src/egg2pg/save_egg_file.h
Executable 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
|
@ -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 \
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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() {
|
||||
|
82
panda/src/pgraph/modelSaveRequest.I
Executable file
82
panda/src/pgraph/modelSaveRequest.I
Executable 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;
|
||||
}
|
58
panda/src/pgraph/modelSaveRequest.cxx
Executable file
58
panda/src/pgraph/modelSaveRequest.cxx
Executable 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;
|
||||
}
|
83
panda/src/pgraph/modelSaveRequest.h
Executable file
83
panda/src/pgraph/modelSaveRequest.h
Executable 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
|
@ -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
@ -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
|
||||
|
@ -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
|
||||
|
81
pandatool/src/converter/eggToSomethingConverter.I
Executable file
81
pandatool/src/converter/eggToSomethingConverter.I
Executable 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;
|
||||
}
|
85
pandatool/src/converter/eggToSomethingConverter.cxx
Executable file
85
pandatool/src/converter/eggToSomethingConverter.cxx
Executable 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 ©) {
|
||||
_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;
|
||||
}
|
77
pandatool/src/converter/eggToSomethingConverter.h
Executable file
77
pandatool/src/converter/eggToSomethingConverter.h
Executable 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 ©);
|
||||
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
|
||||
|
||||
|
@ -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
|
||||
|
445
pandatool/src/objegg/eggToObjConverter.cxx
Executable file
445
pandatool/src/objegg/eggToObjConverter.cxx
Executable 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 ©) :
|
||||
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)
|
||||
{
|
||||
}
|
79
pandatool/src/objegg/eggToObjConverter.h
Executable file
79
pandatool/src/objegg/eggToObjConverter.h
Executable 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 ©);
|
||||
~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
|
@ -12,8 +12,8 @@
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef ObjTOEGGCONVERTER_H
|
||||
#define ObjTOEGGCONVERTER_H
|
||||
#ifndef OBJTOEGGCONVERTER_H
|
||||
#define OBJTOEGGCONVERTER_H
|
||||
|
||||
#include "pandatoolbase.h"
|
||||
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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() {
|
||||
|
Loading…
x
Reference in New Issue
Block a user