Convert from DOS back to Unix newlines
This commit is contained in:
parent
d1732a4dca
commit
0f2f27689a
|
|
@ -1,230 +1,230 @@
|
|||
// Filename: config_egg.cxx
|
||||
// Created by: drose (19Mar00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 "config_egg.h"
|
||||
#include "eggRenderMode.h"
|
||||
#include "eggAnimData.h"
|
||||
#include "eggAnimPreload.h"
|
||||
#include "eggAttributes.h"
|
||||
#include "eggBin.h"
|
||||
#include "eggBinMaker.h"
|
||||
#include "eggComment.h"
|
||||
#include "eggCompositePrimitive.h"
|
||||
#include "eggCoordinateSystem.h"
|
||||
#include "eggCurve.h"
|
||||
#include "eggExternalReference.h"
|
||||
#include "eggFilenameNode.h"
|
||||
#include "eggGroup.h"
|
||||
#include "eggGroupNode.h"
|
||||
#include "eggGroupUniquifier.h"
|
||||
#include "eggLine.h"
|
||||
#include "eggMaterial.h"
|
||||
#include "eggNameUniquifier.h"
|
||||
#include "eggNamedObject.h"
|
||||
#include "eggNode.h"
|
||||
#include "eggNurbsCurve.h"
|
||||
#include "eggNurbsSurface.h"
|
||||
#include "eggObject.h"
|
||||
#include "eggPatch.h"
|
||||
#include "eggPoint.h"
|
||||
#include "eggPolygon.h"
|
||||
#include "eggPolysetMaker.h"
|
||||
#include "eggPoolUniquifier.h"
|
||||
#include "eggPrimitive.h"
|
||||
#include "eggSAnimData.h"
|
||||
#include "eggSurface.h"
|
||||
#include "eggSwitchCondition.h"
|
||||
#include "eggTable.h"
|
||||
#include "eggTexture.h"
|
||||
#include "eggTriangleFan.h"
|
||||
#include "eggTriangleStrip.h"
|
||||
#include "eggUserData.h"
|
||||
#include "eggVertex.h"
|
||||
#include "eggVertexPool.h"
|
||||
#include "eggVertexUV.h"
|
||||
#include "eggVertexAux.h"
|
||||
#include "eggXfmAnimData.h"
|
||||
#include "eggXfmSAnim.h"
|
||||
|
||||
#include "dconfig.h"
|
||||
|
||||
Configure(config_egg);
|
||||
NotifyCategoryDef(egg, "");
|
||||
|
||||
ConfigureFn(config_egg) {
|
||||
init_libegg();
|
||||
}
|
||||
|
||||
ConfigVariableBool egg_support_old_anims
|
||||
("egg-support-old-anims", true,
|
||||
PRC_DESC("Set this true to support loading of old character animation files, which "
|
||||
"had the convention that the order \"phr\" implied a reversed roll."));
|
||||
|
||||
ConfigVariableBool egg_mesh
|
||||
("egg-mesh", true,
|
||||
PRC_DESC("Set this true to convert triangles and higher-order polygons "
|
||||
"into triangle strips and triangle fans when an egg file is "
|
||||
"loaded or converted to bam. Set this false just to triangulate "
|
||||
"everything into independent triangles."));
|
||||
|
||||
ConfigVariableBool egg_retesselate_coplanar
|
||||
("egg-retesselate-coplanar", false,
|
||||
PRC_DESC("If this is true, the egg loader may reverse the "
|
||||
"tesselation direction of a single pair of planar triangles that "
|
||||
"share the same properties, if that will help get a better "
|
||||
"triangle strip. In some rare cases, doing so can distort the "
|
||||
"UV's on a face; turning this off should eliminate that artifact "
|
||||
"(at the cost of less-effective triangle stripping)."));
|
||||
|
||||
ConfigVariableBool egg_unroll_fans
|
||||
("egg-unroll-fans", true,
|
||||
PRC_DESC("Set this true to allow the egg loader to convert weak triangle "
|
||||
"fans--triangles that share the same vertex but aren't "
|
||||
"connected enough to justify making a triangle fan primitive "
|
||||
"from them--into a series of zig-zag triangles that can make "
|
||||
"a triangle strip that might connect better with its neighbors."));
|
||||
|
||||
ConfigVariableBool egg_show_tstrips
|
||||
("egg-show-tstrips", false,
|
||||
PRC_DESC("Set this true to color each triangle strip a random color, with "
|
||||
"the leading triangle a little bit darker, so you can visually "
|
||||
"observe the quality of the triangle stripping algorithm."));
|
||||
|
||||
ConfigVariableBool egg_show_qsheets
|
||||
("egg-show-qsheets", false,
|
||||
PRC_DESC("Set this true to color each quadsheet a random color, so you "
|
||||
"can visually observe the quadsheet algorithm."));
|
||||
|
||||
ConfigVariableBool egg_show_quads
|
||||
("egg-show-quads", false,
|
||||
PRC_DESC("Set this true to color each detected quad a random color, so "
|
||||
"you can visually observe the algorithm that unifies pairs of "
|
||||
"triangles into quads (prior to generating triangle strips)."));
|
||||
|
||||
ConfigVariableBool egg_subdivide_polys
|
||||
("egg-subdivide-polys", true,
|
||||
PRC_DESC("This is obsolete. In the old Geom implementation, it used to "
|
||||
"be true to force higher-order polygons that were not otherwise "
|
||||
"meshed to be subdivided into triangles. In the new "
|
||||
"Geom implementation, this happens anyway."));
|
||||
|
||||
ConfigVariableBool egg_consider_fans
|
||||
("egg-consider-fans", false,
|
||||
PRC_DESC("Set this true to enable the egg mesher to consider making "
|
||||
"triangle fans out of triangles that are connected at a common "
|
||||
"vertex. This may help if your scene involves lots of such "
|
||||
"connected triangles, but it can also make the overall stripping "
|
||||
"less effective (by interfering with triangle strips)."));
|
||||
|
||||
ConfigVariableDouble egg_max_tfan_angle
|
||||
("egg-max-tfan-angle", 40.0,
|
||||
PRC_DESC("The maximum average angle per triangle to allow in a triangle "
|
||||
"fan. If triangles are larger than this--that is, more loosely "
|
||||
"packed--then we figure a triangle strip is likely to do a "
|
||||
"more effective job than a triangle fan, and the fan maker leaves "
|
||||
"it alone."));
|
||||
|
||||
ConfigVariableInt egg_min_tfan_tris
|
||||
("egg-min-tfan-tris", 4,
|
||||
PRC_DESC("The minimum number of triangles that must be involved in order "
|
||||
"to generate a triangle fan. Fewer than this is just interrupting "
|
||||
"a triangle strip."));
|
||||
|
||||
ConfigVariableDouble egg_coplanar_threshold
|
||||
("egg-coplanar-threshold", 0.01,
|
||||
PRC_DESC("The numerical threshold below which polygons are considered "
|
||||
"to be coplanar. Determined empirically."));
|
||||
|
||||
ConfigVariableInt egg_test_vref_integrity
|
||||
("egg-test-vref-integrity", 20,
|
||||
PRC_DESC("The maximum number of vertices a primitive may have before "
|
||||
"its vertices will no longer be checked for internal integrity. "
|
||||
"This is meaningful in non-production builds only."));
|
||||
|
||||
ConfigVariableInt egg_recursion_limit
|
||||
("egg-recursion-limit", 1000,
|
||||
PRC_DESC("The maximum number of levels that recursive algorithms within "
|
||||
"the egg library are allowed to traverse. This is a simple hack "
|
||||
"to prevent deeply-recursive algorithms from triggering a stack "
|
||||
"overflow. Set it larger to run more efficiently if your stack "
|
||||
"allows it; set it lower if you experience stack overflows."));
|
||||
|
||||
ConfigVariableInt egg_precision
|
||||
("egg-precision", 15,
|
||||
PRC_DESC("The number of digits of precision to write out for values in "
|
||||
"an egg file. Leave this at 0 to use the default setting for the "
|
||||
"stream."));
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: init_libegg
|
||||
// Description: Initializes the library. This must be called at
|
||||
// least once before any of the functions or classes in
|
||||
// this library can be used. Normally it will be
|
||||
// called by the static initializers and need not be
|
||||
// called explicitly, but special cases exist.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
init_libegg() {
|
||||
static bool initialized = false;
|
||||
if (initialized) {
|
||||
return;
|
||||
}
|
||||
initialized = true;
|
||||
|
||||
EggRenderMode::init_type();
|
||||
EggAnimData::init_type();
|
||||
EggAnimPreload::init_type();
|
||||
EggAttributes::init_type();
|
||||
EggBin::init_type();
|
||||
EggBinMaker::init_type();
|
||||
EggComment::init_type();
|
||||
EggCompositePrimitive::init_type();
|
||||
EggCoordinateSystem::init_type();
|
||||
EggCurve::init_type();
|
||||
EggData::init_type();
|
||||
EggExternalReference::init_type();
|
||||
EggFilenameNode::init_type();
|
||||
EggGroup::init_type();
|
||||
EggGroupNode::init_type();
|
||||
EggGroupUniquifier::init_type();
|
||||
EggLine::init_type();
|
||||
EggMaterial::init_type();
|
||||
EggNameUniquifier::init_type();
|
||||
EggNamedObject::init_type();
|
||||
EggNode::init_type();
|
||||
EggNurbsCurve::init_type();
|
||||
EggNurbsSurface::init_type();
|
||||
EggObject::init_type();
|
||||
EggPatch::init_type();
|
||||
EggPoint::init_type();
|
||||
EggPolygon::init_type();
|
||||
EggPolysetMaker::init_type();
|
||||
EggPoolUniquifier::init_type();
|
||||
EggPrimitive::init_type();
|
||||
EggSAnimData::init_type();
|
||||
EggSurface::init_type();
|
||||
EggSwitchCondition::init_type();
|
||||
EggSwitchConditionDistance::init_type();
|
||||
EggTable::init_type();
|
||||
EggTexture::init_type();
|
||||
EggTriangleFan::init_type();
|
||||
EggTriangleStrip::init_type();
|
||||
EggUserData::init_type();
|
||||
EggVertex::init_type();
|
||||
EggVertexPool::init_type();
|
||||
EggVertexUV::init_type();
|
||||
EggVertexAux::init_type();
|
||||
EggXfmAnimData::init_type();
|
||||
EggXfmSAnim::init_type();
|
||||
}
|
||||
// Filename: config_egg.cxx
|
||||
// Created by: drose (19Mar00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 "config_egg.h"
|
||||
#include "eggRenderMode.h"
|
||||
#include "eggAnimData.h"
|
||||
#include "eggAnimPreload.h"
|
||||
#include "eggAttributes.h"
|
||||
#include "eggBin.h"
|
||||
#include "eggBinMaker.h"
|
||||
#include "eggComment.h"
|
||||
#include "eggCompositePrimitive.h"
|
||||
#include "eggCoordinateSystem.h"
|
||||
#include "eggCurve.h"
|
||||
#include "eggExternalReference.h"
|
||||
#include "eggFilenameNode.h"
|
||||
#include "eggGroup.h"
|
||||
#include "eggGroupNode.h"
|
||||
#include "eggGroupUniquifier.h"
|
||||
#include "eggLine.h"
|
||||
#include "eggMaterial.h"
|
||||
#include "eggNameUniquifier.h"
|
||||
#include "eggNamedObject.h"
|
||||
#include "eggNode.h"
|
||||
#include "eggNurbsCurve.h"
|
||||
#include "eggNurbsSurface.h"
|
||||
#include "eggObject.h"
|
||||
#include "eggPatch.h"
|
||||
#include "eggPoint.h"
|
||||
#include "eggPolygon.h"
|
||||
#include "eggPolysetMaker.h"
|
||||
#include "eggPoolUniquifier.h"
|
||||
#include "eggPrimitive.h"
|
||||
#include "eggSAnimData.h"
|
||||
#include "eggSurface.h"
|
||||
#include "eggSwitchCondition.h"
|
||||
#include "eggTable.h"
|
||||
#include "eggTexture.h"
|
||||
#include "eggTriangleFan.h"
|
||||
#include "eggTriangleStrip.h"
|
||||
#include "eggUserData.h"
|
||||
#include "eggVertex.h"
|
||||
#include "eggVertexPool.h"
|
||||
#include "eggVertexUV.h"
|
||||
#include "eggVertexAux.h"
|
||||
#include "eggXfmAnimData.h"
|
||||
#include "eggXfmSAnim.h"
|
||||
|
||||
#include "dconfig.h"
|
||||
|
||||
Configure(config_egg);
|
||||
NotifyCategoryDef(egg, "");
|
||||
|
||||
ConfigureFn(config_egg) {
|
||||
init_libegg();
|
||||
}
|
||||
|
||||
ConfigVariableBool egg_support_old_anims
|
||||
("egg-support-old-anims", true,
|
||||
PRC_DESC("Set this true to support loading of old character animation files, which "
|
||||
"had the convention that the order \"phr\" implied a reversed roll."));
|
||||
|
||||
ConfigVariableBool egg_mesh
|
||||
("egg-mesh", true,
|
||||
PRC_DESC("Set this true to convert triangles and higher-order polygons "
|
||||
"into triangle strips and triangle fans when an egg file is "
|
||||
"loaded or converted to bam. Set this false just to triangulate "
|
||||
"everything into independent triangles."));
|
||||
|
||||
ConfigVariableBool egg_retesselate_coplanar
|
||||
("egg-retesselate-coplanar", false,
|
||||
PRC_DESC("If this is true, the egg loader may reverse the "
|
||||
"tesselation direction of a single pair of planar triangles that "
|
||||
"share the same properties, if that will help get a better "
|
||||
"triangle strip. In some rare cases, doing so can distort the "
|
||||
"UV's on a face; turning this off should eliminate that artifact "
|
||||
"(at the cost of less-effective triangle stripping)."));
|
||||
|
||||
ConfigVariableBool egg_unroll_fans
|
||||
("egg-unroll-fans", true,
|
||||
PRC_DESC("Set this true to allow the egg loader to convert weak triangle "
|
||||
"fans--triangles that share the same vertex but aren't "
|
||||
"connected enough to justify making a triangle fan primitive "
|
||||
"from them--into a series of zig-zag triangles that can make "
|
||||
"a triangle strip that might connect better with its neighbors."));
|
||||
|
||||
ConfigVariableBool egg_show_tstrips
|
||||
("egg-show-tstrips", false,
|
||||
PRC_DESC("Set this true to color each triangle strip a random color, with "
|
||||
"the leading triangle a little bit darker, so you can visually "
|
||||
"observe the quality of the triangle stripping algorithm."));
|
||||
|
||||
ConfigVariableBool egg_show_qsheets
|
||||
("egg-show-qsheets", false,
|
||||
PRC_DESC("Set this true to color each quadsheet a random color, so you "
|
||||
"can visually observe the quadsheet algorithm."));
|
||||
|
||||
ConfigVariableBool egg_show_quads
|
||||
("egg-show-quads", false,
|
||||
PRC_DESC("Set this true to color each detected quad a random color, so "
|
||||
"you can visually observe the algorithm that unifies pairs of "
|
||||
"triangles into quads (prior to generating triangle strips)."));
|
||||
|
||||
ConfigVariableBool egg_subdivide_polys
|
||||
("egg-subdivide-polys", true,
|
||||
PRC_DESC("This is obsolete. In the old Geom implementation, it used to "
|
||||
"be true to force higher-order polygons that were not otherwise "
|
||||
"meshed to be subdivided into triangles. In the new "
|
||||
"Geom implementation, this happens anyway."));
|
||||
|
||||
ConfigVariableBool egg_consider_fans
|
||||
("egg-consider-fans", false,
|
||||
PRC_DESC("Set this true to enable the egg mesher to consider making "
|
||||
"triangle fans out of triangles that are connected at a common "
|
||||
"vertex. This may help if your scene involves lots of such "
|
||||
"connected triangles, but it can also make the overall stripping "
|
||||
"less effective (by interfering with triangle strips)."));
|
||||
|
||||
ConfigVariableDouble egg_max_tfan_angle
|
||||
("egg-max-tfan-angle", 40.0,
|
||||
PRC_DESC("The maximum average angle per triangle to allow in a triangle "
|
||||
"fan. If triangles are larger than this--that is, more loosely "
|
||||
"packed--then we figure a triangle strip is likely to do a "
|
||||
"more effective job than a triangle fan, and the fan maker leaves "
|
||||
"it alone."));
|
||||
|
||||
ConfigVariableInt egg_min_tfan_tris
|
||||
("egg-min-tfan-tris", 4,
|
||||
PRC_DESC("The minimum number of triangles that must be involved in order "
|
||||
"to generate a triangle fan. Fewer than this is just interrupting "
|
||||
"a triangle strip."));
|
||||
|
||||
ConfigVariableDouble egg_coplanar_threshold
|
||||
("egg-coplanar-threshold", 0.01,
|
||||
PRC_DESC("The numerical threshold below which polygons are considered "
|
||||
"to be coplanar. Determined empirically."));
|
||||
|
||||
ConfigVariableInt egg_test_vref_integrity
|
||||
("egg-test-vref-integrity", 20,
|
||||
PRC_DESC("The maximum number of vertices a primitive may have before "
|
||||
"its vertices will no longer be checked for internal integrity. "
|
||||
"This is meaningful in non-production builds only."));
|
||||
|
||||
ConfigVariableInt egg_recursion_limit
|
||||
("egg-recursion-limit", 1000,
|
||||
PRC_DESC("The maximum number of levels that recursive algorithms within "
|
||||
"the egg library are allowed to traverse. This is a simple hack "
|
||||
"to prevent deeply-recursive algorithms from triggering a stack "
|
||||
"overflow. Set it larger to run more efficiently if your stack "
|
||||
"allows it; set it lower if you experience stack overflows."));
|
||||
|
||||
ConfigVariableInt egg_precision
|
||||
("egg-precision", 15,
|
||||
PRC_DESC("The number of digits of precision to write out for values in "
|
||||
"an egg file. Leave this at 0 to use the default setting for the "
|
||||
"stream."));
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: init_libegg
|
||||
// Description: Initializes the library. This must be called at
|
||||
// least once before any of the functions or classes in
|
||||
// this library can be used. Normally it will be
|
||||
// called by the static initializers and need not be
|
||||
// called explicitly, but special cases exist.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
init_libegg() {
|
||||
static bool initialized = false;
|
||||
if (initialized) {
|
||||
return;
|
||||
}
|
||||
initialized = true;
|
||||
|
||||
EggRenderMode::init_type();
|
||||
EggAnimData::init_type();
|
||||
EggAnimPreload::init_type();
|
||||
EggAttributes::init_type();
|
||||
EggBin::init_type();
|
||||
EggBinMaker::init_type();
|
||||
EggComment::init_type();
|
||||
EggCompositePrimitive::init_type();
|
||||
EggCoordinateSystem::init_type();
|
||||
EggCurve::init_type();
|
||||
EggData::init_type();
|
||||
EggExternalReference::init_type();
|
||||
EggFilenameNode::init_type();
|
||||
EggGroup::init_type();
|
||||
EggGroupNode::init_type();
|
||||
EggGroupUniquifier::init_type();
|
||||
EggLine::init_type();
|
||||
EggMaterial::init_type();
|
||||
EggNameUniquifier::init_type();
|
||||
EggNamedObject::init_type();
|
||||
EggNode::init_type();
|
||||
EggNurbsCurve::init_type();
|
||||
EggNurbsSurface::init_type();
|
||||
EggObject::init_type();
|
||||
EggPatch::init_type();
|
||||
EggPoint::init_type();
|
||||
EggPolygon::init_type();
|
||||
EggPolysetMaker::init_type();
|
||||
EggPoolUniquifier::init_type();
|
||||
EggPrimitive::init_type();
|
||||
EggSAnimData::init_type();
|
||||
EggSurface::init_type();
|
||||
EggSwitchCondition::init_type();
|
||||
EggSwitchConditionDistance::init_type();
|
||||
EggTable::init_type();
|
||||
EggTexture::init_type();
|
||||
EggTriangleFan::init_type();
|
||||
EggTriangleStrip::init_type();
|
||||
EggUserData::init_type();
|
||||
EggVertex::init_type();
|
||||
EggVertexPool::init_type();
|
||||
EggVertexUV::init_type();
|
||||
EggVertexAux::init_type();
|
||||
EggXfmAnimData::init_type();
|
||||
EggXfmSAnim::init_type();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,48 +1,48 @@
|
|||
// Filename: config_egg.h
|
||||
// Created by: drose (19Mar00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 CONFIG_EGG_H
|
||||
#define CONFIG_EGG_H
|
||||
|
||||
#include "pandabase.h"
|
||||
#include "notifyCategoryProxy.h"
|
||||
#include "configVariableSearchPath.h"
|
||||
#include "configVariableBool.h"
|
||||
#include "configVariableEnum.h"
|
||||
#include "configVariableDouble.h"
|
||||
#include "configVariableInt.h"
|
||||
|
||||
NotifyCategoryDecl(egg, EXPCL_PANDAEGG, EXPTP_PANDAEGG);
|
||||
|
||||
extern ConfigVariableBool egg_support_old_anims;
|
||||
|
||||
extern EXPCL_PANDAEGG ConfigVariableBool egg_mesh;
|
||||
extern EXPCL_PANDAEGG ConfigVariableBool egg_retesselate_coplanar;
|
||||
extern EXPCL_PANDAEGG ConfigVariableBool egg_unroll_fans;
|
||||
extern EXPCL_PANDAEGG ConfigVariableBool egg_show_tstrips;
|
||||
extern EXPCL_PANDAEGG ConfigVariableBool egg_show_qsheets;
|
||||
extern EXPCL_PANDAEGG ConfigVariableBool egg_show_quads;
|
||||
#define egg_false_color (egg_show_tstrips | egg_show_qsheets | egg_show_quads)
|
||||
extern EXPCL_PANDAEGG ConfigVariableBool egg_subdivide_polys;
|
||||
extern EXPCL_PANDAEGG ConfigVariableBool egg_consider_fans;
|
||||
extern EXPCL_PANDAEGG ConfigVariableDouble egg_max_tfan_angle;
|
||||
extern EXPCL_PANDAEGG ConfigVariableInt egg_min_tfan_tris;
|
||||
extern EXPCL_PANDAEGG ConfigVariableDouble egg_coplanar_threshold;
|
||||
extern EXPCL_PANDAEGG ConfigVariableInt egg_test_vref_integrity;
|
||||
extern EXPCL_PANDAEGG ConfigVariableInt egg_recursion_limit;
|
||||
extern EXPCL_PANDAEGG ConfigVariableInt egg_precision;
|
||||
|
||||
extern EXPCL_PANDAEGG void init_libegg();
|
||||
|
||||
#endif
|
||||
// Filename: config_egg.h
|
||||
// Created by: drose (19Mar00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 CONFIG_EGG_H
|
||||
#define CONFIG_EGG_H
|
||||
|
||||
#include "pandabase.h"
|
||||
#include "notifyCategoryProxy.h"
|
||||
#include "configVariableSearchPath.h"
|
||||
#include "configVariableBool.h"
|
||||
#include "configVariableEnum.h"
|
||||
#include "configVariableDouble.h"
|
||||
#include "configVariableInt.h"
|
||||
|
||||
NotifyCategoryDecl(egg, EXPCL_PANDAEGG, EXPTP_PANDAEGG);
|
||||
|
||||
extern ConfigVariableBool egg_support_old_anims;
|
||||
|
||||
extern EXPCL_PANDAEGG ConfigVariableBool egg_mesh;
|
||||
extern EXPCL_PANDAEGG ConfigVariableBool egg_retesselate_coplanar;
|
||||
extern EXPCL_PANDAEGG ConfigVariableBool egg_unroll_fans;
|
||||
extern EXPCL_PANDAEGG ConfigVariableBool egg_show_tstrips;
|
||||
extern EXPCL_PANDAEGG ConfigVariableBool egg_show_qsheets;
|
||||
extern EXPCL_PANDAEGG ConfigVariableBool egg_show_quads;
|
||||
#define egg_false_color (egg_show_tstrips | egg_show_qsheets | egg_show_quads)
|
||||
extern EXPCL_PANDAEGG ConfigVariableBool egg_subdivide_polys;
|
||||
extern EXPCL_PANDAEGG ConfigVariableBool egg_consider_fans;
|
||||
extern EXPCL_PANDAEGG ConfigVariableDouble egg_max_tfan_angle;
|
||||
extern EXPCL_PANDAEGG ConfigVariableInt egg_min_tfan_tris;
|
||||
extern EXPCL_PANDAEGG ConfigVariableDouble egg_coplanar_threshold;
|
||||
extern EXPCL_PANDAEGG ConfigVariableInt egg_test_vref_integrity;
|
||||
extern EXPCL_PANDAEGG ConfigVariableInt egg_recursion_limit;
|
||||
extern EXPCL_PANDAEGG ConfigVariableInt egg_precision;
|
||||
|
||||
extern EXPCL_PANDAEGG void init_libegg();
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,414 +1,414 @@
|
|||
// Filename: eggData.cxx
|
||||
// Created by: drose (20Jan99)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 "eggData.h"
|
||||
#include "eggCoordinateSystem.h"
|
||||
#include "eggTextureCollection.h"
|
||||
#include "eggMaterialCollection.h"
|
||||
#include "eggComment.h"
|
||||
#include "eggPoolUniquifier.h"
|
||||
#include "config_egg.h"
|
||||
#include "config_util.h"
|
||||
#include "config_express.h"
|
||||
#include "string_utils.h"
|
||||
#include "dSearchPath.h"
|
||||
#include "virtualFileSystem.h"
|
||||
#include "lightMutexHolder.h"
|
||||
#include "zStream.h"
|
||||
|
||||
extern int eggyyparse();
|
||||
#include "parserDefs.h"
|
||||
#include "lexerDefs.h"
|
||||
|
||||
TypeHandle EggData::_type_handle;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggData::resolve_egg_filename
|
||||
// Access: Public, Static
|
||||
// Description: Looks for the indicated filename, first along the
|
||||
// indicated searchpath, and then along the model_path.
|
||||
// If found, updates the filename to the full path and
|
||||
// returns true; otherwise, returns false.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool EggData::
|
||||
resolve_egg_filename(Filename &egg_filename, const DSearchPath &searchpath) {
|
||||
VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
|
||||
|
||||
if (egg_filename.is_fully_qualified() && vfs->exists(egg_filename)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
vfs->resolve_filename(egg_filename, searchpath, "egg") ||
|
||||
vfs->resolve_filename(egg_filename, get_model_path(), "egg");
|
||||
|
||||
return vfs->exists(egg_filename);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggData::read
|
||||
// Access: Public
|
||||
// Description: Opens the indicated filename and reads the egg data
|
||||
// contents from it. Returns true if the file was
|
||||
// successfully opened and read, false if there were
|
||||
// some errors, in which case the data may be partially
|
||||
// read.
|
||||
//
|
||||
// error is the output stream to which to write error
|
||||
// messages.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool EggData::
|
||||
read(Filename filename, string display_name) {
|
||||
filename.set_text();
|
||||
set_egg_filename(filename);
|
||||
|
||||
if (display_name.empty()) {
|
||||
display_name = filename;
|
||||
}
|
||||
|
||||
VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
|
||||
|
||||
PT(VirtualFile) vfile = vfs->get_file(filename);
|
||||
if (vfile == NULL) {
|
||||
egg_cat.error() << "Could not find " << display_name << "\n";
|
||||
return false;
|
||||
}
|
||||
set_egg_timestamp(vfile->get_timestamp());
|
||||
|
||||
istream *file = vfile->open_read_file(true);
|
||||
if (file == (istream *)NULL) {
|
||||
egg_cat.error() << "Unable to open " << display_name << "\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
egg_cat.info()
|
||||
<< "Reading " << display_name << "\n";
|
||||
|
||||
bool read_ok = read(*file);
|
||||
vfile->close_read_file(file);
|
||||
return read_ok;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggData::read
|
||||
// Access: Public
|
||||
// Description: Parses the egg syntax contained in the indicated
|
||||
// input stream. Returns true if the stream was a
|
||||
// completely valid egg file, false if there were some
|
||||
// errors, in which case the data may be partially read.
|
||||
//
|
||||
// Before you call this routine, you should probably
|
||||
// call set_egg_filename() to set the name of the egg
|
||||
// file we're processing, if at all possible. If there
|
||||
// is no such filename, you may set it to the empty
|
||||
// string.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool EggData::
|
||||
read(istream &in) {
|
||||
// First, dispense with any children we had previously. We will
|
||||
// replace them with the new data.
|
||||
clear();
|
||||
|
||||
// Create a temporary EggData structure to read into. We initialize
|
||||
// it with a copy of ourselves, so that it will get our _coordsys
|
||||
// value, if the user set it.
|
||||
PT(EggData) data = new EggData(*this);
|
||||
|
||||
int error_count;
|
||||
{
|
||||
LightMutexHolder holder(egg_lock);
|
||||
egg_init_parser(in, get_egg_filename(), data, data);
|
||||
eggyyparse();
|
||||
egg_cleanup_parser();
|
||||
error_count = egg_error_count();
|
||||
}
|
||||
|
||||
data->post_read();
|
||||
|
||||
steal_children(*data);
|
||||
(*this) = *data;
|
||||
|
||||
return (error_count == 0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggData::merge
|
||||
// Access: Public
|
||||
// Description: Appends the other egg structure to the end of this
|
||||
// one. The other egg structure is invalidated.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void EggData::
|
||||
merge(EggData &other) {
|
||||
if (get_coordinate_system() == CS_default) {
|
||||
// If we haven't specified a coordinate system yet, we inherit the
|
||||
// other one's.
|
||||
set_coordinate_system(other.get_coordinate_system());
|
||||
|
||||
} else {
|
||||
// Otherwise, the other one is forced into our coordinate system
|
||||
// before we merge.
|
||||
other.set_coordinate_system(get_coordinate_system());
|
||||
}
|
||||
steal_children(other);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggData::load_externals
|
||||
// Access: Public
|
||||
// Description: Loads up all the egg files referenced by <File>
|
||||
// entries within the egg structure, and inserts their
|
||||
// contents in place of the <File> entries. Searches
|
||||
// for files in the searchpath, if not found directly,
|
||||
// and writes error messages to the indicated output
|
||||
// stream. Returns true if all externals were loaded
|
||||
// successfully, false otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool EggData::
|
||||
load_externals(const DSearchPath &searchpath) {
|
||||
return
|
||||
r_load_externals(searchpath, get_coordinate_system(), NULL);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggData::load_externals
|
||||
// Access: Public
|
||||
// Description: Loads up all the egg files referenced by <File>
|
||||
// entries within the egg structure, and inserts their
|
||||
// contents in place of the <File> entries. Searches
|
||||
// for files in the searchpath, if not found directly,
|
||||
// and writes error messages to the indicated output
|
||||
// stream. Returns true if all externals were loaded
|
||||
// successfully, false otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool EggData::
|
||||
load_externals(const DSearchPath &searchpath, BamCacheRecord *record) {
|
||||
return
|
||||
r_load_externals(searchpath, get_coordinate_system(), record);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggData::collapse_equivalent_textures
|
||||
// Access: Public
|
||||
// Description: Removes duplicate references to the same texture
|
||||
// image with the same properties. Considers two
|
||||
// texture references with identical properties, but
|
||||
// different tref names, to be equivalent, and collapses
|
||||
// them, choosing one tref name to keep arbitrarily.
|
||||
// Returns the number of textures removed.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int EggData::
|
||||
collapse_equivalent_textures() {
|
||||
EggTextureCollection textures;
|
||||
textures.find_used_textures(this);
|
||||
return
|
||||
textures.collapse_equivalent_textures(~EggTexture::E_tref_name, this);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggData::collapse_equivalent_materials
|
||||
// Access: Public
|
||||
// Description: Removes duplicate references to the same material
|
||||
// with the same properties. Considers two material
|
||||
// references with identical properties, but different
|
||||
// mref names, to be equivalent, and collapses them,
|
||||
// choosing one mref name to keep arbitrarily. Returns
|
||||
// the number of materials removed.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int EggData::
|
||||
collapse_equivalent_materials() {
|
||||
EggMaterialCollection materials;
|
||||
materials.find_used_materials(this);
|
||||
return
|
||||
materials.collapse_equivalent_materials(~EggMaterial::E_mref_name, this);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggData::write_egg
|
||||
// Access: Public
|
||||
// Description: The main interface for writing complete egg files.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool EggData::
|
||||
write_egg(Filename filename) {
|
||||
VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
|
||||
filename.set_text();
|
||||
vfs->delete_file(filename);
|
||||
ostream *file = vfs->open_write_file(filename, true, true);
|
||||
if (file == (ostream *)NULL) {
|
||||
egg_cat.error() << "Unable to open " << filename << " for writing.\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
bool wrote_ok = write_egg(*file);
|
||||
vfs->close_write_file(file);
|
||||
return wrote_ok;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggData::write_egg
|
||||
// Access: Public
|
||||
// Description: The main interface for writing complete egg files.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool EggData::
|
||||
write_egg(ostream &out) {
|
||||
pre_write();
|
||||
|
||||
if (egg_precision > 0) {
|
||||
// Change the egg precision as requested.
|
||||
streamsize orig_precision = out.precision();
|
||||
out.precision((streamsize)egg_precision);
|
||||
write(out, 0);
|
||||
out.precision(orig_precision);
|
||||
} else {
|
||||
// Use the stream default precision.
|
||||
write(out, 0);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggData::set_coordinate_system
|
||||
// Access: Public
|
||||
// Description: Changes the coordinate system of the EggData. If the
|
||||
// coordinate system was previously different, this may
|
||||
// result in a conversion of the data.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void EggData::
|
||||
set_coordinate_system(CoordinateSystem new_coordsys) {
|
||||
if (new_coordsys == CS_default) {
|
||||
new_coordsys = get_default_coordinate_system();
|
||||
}
|
||||
if (new_coordsys != _coordsys &&
|
||||
(_coordsys != CS_default && _coordsys != CS_invalid)) {
|
||||
// Time to convert the data.
|
||||
LMatrix4d mat = LMatrix4d::convert_mat(_coordsys, new_coordsys);
|
||||
LMatrix4d inv = LMatrix4d::convert_mat(new_coordsys, _coordsys);
|
||||
|
||||
r_transform(mat, inv, new_coordsys);
|
||||
r_transform_vertices(mat);
|
||||
|
||||
// Now we have to update the under_flags to ensure that all the
|
||||
// cached relative matrices are correct.
|
||||
update_under(0);
|
||||
}
|
||||
|
||||
_coordsys = new_coordsys;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggData::write
|
||||
// Access: Protected, Virtual
|
||||
// Description: Writes the egg data out to the indicated output
|
||||
// stream.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void EggData::
|
||||
write(ostream &out, int indent_level) const {
|
||||
PT(EggCoordinateSystem) ecs = new EggCoordinateSystem(_coordsys);
|
||||
ecs->write(out, indent_level);
|
||||
EggGroupNode::write(out, indent_level);
|
||||
out << flush;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggData::post_read
|
||||
// Access: Private
|
||||
// Description: Does whatever processing is appropriate after reading
|
||||
// the data in from an egg file.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void EggData::
|
||||
post_read() {
|
||||
CoordinateSystem old_coordsys = _coordsys;
|
||||
_coordsys = find_coordsys_entry();
|
||||
|
||||
if (_coordsys == CS_default) {
|
||||
// If the egg file didn't contain a <CoordinateSystem> entry,
|
||||
// assume it's Y-up, by convention.
|
||||
_coordsys = CS_yup_right;
|
||||
|
||||
} else if (_coordsys == CS_invalid) {
|
||||
egg_cat.warning()
|
||||
<< "Contradictory <CoordinateSystem> entries encountered.\n";
|
||||
_coordsys = CS_yup_right;
|
||||
}
|
||||
|
||||
r_mark_coordsys(_coordsys);
|
||||
|
||||
if (old_coordsys != CS_default) {
|
||||
// Now if we had a previous definition, enforce it. This might
|
||||
// convert the data to the given coordinate system.
|
||||
set_coordinate_system(old_coordsys);
|
||||
}
|
||||
|
||||
// Fill this in before we automatically resolve pathnames.
|
||||
_had_absolute_pathnames = has_absolute_pathnames();
|
||||
|
||||
if (get_auto_resolve_externals()) {
|
||||
// Resolve filenames that are relative to the egg file.
|
||||
DSearchPath dir;
|
||||
dir.append_directory(get_egg_filename().get_dirname());
|
||||
resolve_filenames(dir);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggData::pre_write
|
||||
// Access: Private
|
||||
// Description: Does whatever processing is appropriate just before
|
||||
// writing the data out to an egg file. This includes
|
||||
// verifying that vertex pool names are unique, etc.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void EggData::
|
||||
pre_write() {
|
||||
// Pull out all of the texture definitions in the file and massage
|
||||
// them a bit.
|
||||
EggTextureCollection textures;
|
||||
textures.extract_textures(this);
|
||||
|
||||
// Remove any textures that aren't being used.
|
||||
textures.remove_unused_textures(this);
|
||||
|
||||
// Collapse out any textures that are completely equivalent. For
|
||||
// this purpose, we consider two textures with identical properties
|
||||
// but different tref names to be different.
|
||||
textures.collapse_equivalent_textures(~0, this);
|
||||
|
||||
// Make sure all of the textures have unique TRef names.
|
||||
textures.uniquify_trefs();
|
||||
textures.sort_by_tref();
|
||||
|
||||
// Do the same thing with the materials.
|
||||
EggMaterialCollection materials;
|
||||
materials.extract_materials(this);
|
||||
materials.remove_unused_materials(this);
|
||||
materials.collapse_equivalent_materials(~0, this);
|
||||
materials.uniquify_mrefs();
|
||||
materials.sort_by_mref();
|
||||
|
||||
// Now put them all back at the head of the file, after any initial
|
||||
// comment records.
|
||||
iterator ci = begin();
|
||||
while (ci != end() && (*ci)->is_of_type(EggComment::get_class_type())) {
|
||||
++ci;
|
||||
}
|
||||
textures.insert_textures(this, ci);
|
||||
materials.insert_materials(this, ci);
|
||||
|
||||
// Also make sure that the vertex pools are uniquely named. This
|
||||
// also checks textures and materials, which is kind of redundant
|
||||
// since we just did that, but we don't mind.
|
||||
EggPoolUniquifier pu;
|
||||
pu.uniquify(this);
|
||||
}
|
||||
// Filename: eggData.cxx
|
||||
// Created by: drose (20Jan99)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 "eggData.h"
|
||||
#include "eggCoordinateSystem.h"
|
||||
#include "eggTextureCollection.h"
|
||||
#include "eggMaterialCollection.h"
|
||||
#include "eggComment.h"
|
||||
#include "eggPoolUniquifier.h"
|
||||
#include "config_egg.h"
|
||||
#include "config_util.h"
|
||||
#include "config_express.h"
|
||||
#include "string_utils.h"
|
||||
#include "dSearchPath.h"
|
||||
#include "virtualFileSystem.h"
|
||||
#include "lightMutexHolder.h"
|
||||
#include "zStream.h"
|
||||
|
||||
extern int eggyyparse();
|
||||
#include "parserDefs.h"
|
||||
#include "lexerDefs.h"
|
||||
|
||||
TypeHandle EggData::_type_handle;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggData::resolve_egg_filename
|
||||
// Access: Public, Static
|
||||
// Description: Looks for the indicated filename, first along the
|
||||
// indicated searchpath, and then along the model_path.
|
||||
// If found, updates the filename to the full path and
|
||||
// returns true; otherwise, returns false.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool EggData::
|
||||
resolve_egg_filename(Filename &egg_filename, const DSearchPath &searchpath) {
|
||||
VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
|
||||
|
||||
if (egg_filename.is_fully_qualified() && vfs->exists(egg_filename)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
vfs->resolve_filename(egg_filename, searchpath, "egg") ||
|
||||
vfs->resolve_filename(egg_filename, get_model_path(), "egg");
|
||||
|
||||
return vfs->exists(egg_filename);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggData::read
|
||||
// Access: Public
|
||||
// Description: Opens the indicated filename and reads the egg data
|
||||
// contents from it. Returns true if the file was
|
||||
// successfully opened and read, false if there were
|
||||
// some errors, in which case the data may be partially
|
||||
// read.
|
||||
//
|
||||
// error is the output stream to which to write error
|
||||
// messages.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool EggData::
|
||||
read(Filename filename, string display_name) {
|
||||
filename.set_text();
|
||||
set_egg_filename(filename);
|
||||
|
||||
if (display_name.empty()) {
|
||||
display_name = filename;
|
||||
}
|
||||
|
||||
VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
|
||||
|
||||
PT(VirtualFile) vfile = vfs->get_file(filename);
|
||||
if (vfile == NULL) {
|
||||
egg_cat.error() << "Could not find " << display_name << "\n";
|
||||
return false;
|
||||
}
|
||||
set_egg_timestamp(vfile->get_timestamp());
|
||||
|
||||
istream *file = vfile->open_read_file(true);
|
||||
if (file == (istream *)NULL) {
|
||||
egg_cat.error() << "Unable to open " << display_name << "\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
egg_cat.info()
|
||||
<< "Reading " << display_name << "\n";
|
||||
|
||||
bool read_ok = read(*file);
|
||||
vfile->close_read_file(file);
|
||||
return read_ok;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggData::read
|
||||
// Access: Public
|
||||
// Description: Parses the egg syntax contained in the indicated
|
||||
// input stream. Returns true if the stream was a
|
||||
// completely valid egg file, false if there were some
|
||||
// errors, in which case the data may be partially read.
|
||||
//
|
||||
// Before you call this routine, you should probably
|
||||
// call set_egg_filename() to set the name of the egg
|
||||
// file we're processing, if at all possible. If there
|
||||
// is no such filename, you may set it to the empty
|
||||
// string.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool EggData::
|
||||
read(istream &in) {
|
||||
// First, dispense with any children we had previously. We will
|
||||
// replace them with the new data.
|
||||
clear();
|
||||
|
||||
// Create a temporary EggData structure to read into. We initialize
|
||||
// it with a copy of ourselves, so that it will get our _coordsys
|
||||
// value, if the user set it.
|
||||
PT(EggData) data = new EggData(*this);
|
||||
|
||||
int error_count;
|
||||
{
|
||||
LightMutexHolder holder(egg_lock);
|
||||
egg_init_parser(in, get_egg_filename(), data, data);
|
||||
eggyyparse();
|
||||
egg_cleanup_parser();
|
||||
error_count = egg_error_count();
|
||||
}
|
||||
|
||||
data->post_read();
|
||||
|
||||
steal_children(*data);
|
||||
(*this) = *data;
|
||||
|
||||
return (error_count == 0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggData::merge
|
||||
// Access: Public
|
||||
// Description: Appends the other egg structure to the end of this
|
||||
// one. The other egg structure is invalidated.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void EggData::
|
||||
merge(EggData &other) {
|
||||
if (get_coordinate_system() == CS_default) {
|
||||
// If we haven't specified a coordinate system yet, we inherit the
|
||||
// other one's.
|
||||
set_coordinate_system(other.get_coordinate_system());
|
||||
|
||||
} else {
|
||||
// Otherwise, the other one is forced into our coordinate system
|
||||
// before we merge.
|
||||
other.set_coordinate_system(get_coordinate_system());
|
||||
}
|
||||
steal_children(other);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggData::load_externals
|
||||
// Access: Public
|
||||
// Description: Loads up all the egg files referenced by <File>
|
||||
// entries within the egg structure, and inserts their
|
||||
// contents in place of the <File> entries. Searches
|
||||
// for files in the searchpath, if not found directly,
|
||||
// and writes error messages to the indicated output
|
||||
// stream. Returns true if all externals were loaded
|
||||
// successfully, false otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool EggData::
|
||||
load_externals(const DSearchPath &searchpath) {
|
||||
return
|
||||
r_load_externals(searchpath, get_coordinate_system(), NULL);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggData::load_externals
|
||||
// Access: Public
|
||||
// Description: Loads up all the egg files referenced by <File>
|
||||
// entries within the egg structure, and inserts their
|
||||
// contents in place of the <File> entries. Searches
|
||||
// for files in the searchpath, if not found directly,
|
||||
// and writes error messages to the indicated output
|
||||
// stream. Returns true if all externals were loaded
|
||||
// successfully, false otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool EggData::
|
||||
load_externals(const DSearchPath &searchpath, BamCacheRecord *record) {
|
||||
return
|
||||
r_load_externals(searchpath, get_coordinate_system(), record);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggData::collapse_equivalent_textures
|
||||
// Access: Public
|
||||
// Description: Removes duplicate references to the same texture
|
||||
// image with the same properties. Considers two
|
||||
// texture references with identical properties, but
|
||||
// different tref names, to be equivalent, and collapses
|
||||
// them, choosing one tref name to keep arbitrarily.
|
||||
// Returns the number of textures removed.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int EggData::
|
||||
collapse_equivalent_textures() {
|
||||
EggTextureCollection textures;
|
||||
textures.find_used_textures(this);
|
||||
return
|
||||
textures.collapse_equivalent_textures(~EggTexture::E_tref_name, this);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggData::collapse_equivalent_materials
|
||||
// Access: Public
|
||||
// Description: Removes duplicate references to the same material
|
||||
// with the same properties. Considers two material
|
||||
// references with identical properties, but different
|
||||
// mref names, to be equivalent, and collapses them,
|
||||
// choosing one mref name to keep arbitrarily. Returns
|
||||
// the number of materials removed.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int EggData::
|
||||
collapse_equivalent_materials() {
|
||||
EggMaterialCollection materials;
|
||||
materials.find_used_materials(this);
|
||||
return
|
||||
materials.collapse_equivalent_materials(~EggMaterial::E_mref_name, this);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggData::write_egg
|
||||
// Access: Public
|
||||
// Description: The main interface for writing complete egg files.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool EggData::
|
||||
write_egg(Filename filename) {
|
||||
VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
|
||||
filename.set_text();
|
||||
vfs->delete_file(filename);
|
||||
ostream *file = vfs->open_write_file(filename, true, true);
|
||||
if (file == (ostream *)NULL) {
|
||||
egg_cat.error() << "Unable to open " << filename << " for writing.\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
bool wrote_ok = write_egg(*file);
|
||||
vfs->close_write_file(file);
|
||||
return wrote_ok;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggData::write_egg
|
||||
// Access: Public
|
||||
// Description: The main interface for writing complete egg files.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool EggData::
|
||||
write_egg(ostream &out) {
|
||||
pre_write();
|
||||
|
||||
if (egg_precision > 0) {
|
||||
// Change the egg precision as requested.
|
||||
streamsize orig_precision = out.precision();
|
||||
out.precision((streamsize)egg_precision);
|
||||
write(out, 0);
|
||||
out.precision(orig_precision);
|
||||
} else {
|
||||
// Use the stream default precision.
|
||||
write(out, 0);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggData::set_coordinate_system
|
||||
// Access: Public
|
||||
// Description: Changes the coordinate system of the EggData. If the
|
||||
// coordinate system was previously different, this may
|
||||
// result in a conversion of the data.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void EggData::
|
||||
set_coordinate_system(CoordinateSystem new_coordsys) {
|
||||
if (new_coordsys == CS_default) {
|
||||
new_coordsys = get_default_coordinate_system();
|
||||
}
|
||||
if (new_coordsys != _coordsys &&
|
||||
(_coordsys != CS_default && _coordsys != CS_invalid)) {
|
||||
// Time to convert the data.
|
||||
LMatrix4d mat = LMatrix4d::convert_mat(_coordsys, new_coordsys);
|
||||
LMatrix4d inv = LMatrix4d::convert_mat(new_coordsys, _coordsys);
|
||||
|
||||
r_transform(mat, inv, new_coordsys);
|
||||
r_transform_vertices(mat);
|
||||
|
||||
// Now we have to update the under_flags to ensure that all the
|
||||
// cached relative matrices are correct.
|
||||
update_under(0);
|
||||
}
|
||||
|
||||
_coordsys = new_coordsys;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggData::write
|
||||
// Access: Protected, Virtual
|
||||
// Description: Writes the egg data out to the indicated output
|
||||
// stream.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void EggData::
|
||||
write(ostream &out, int indent_level) const {
|
||||
PT(EggCoordinateSystem) ecs = new EggCoordinateSystem(_coordsys);
|
||||
ecs->write(out, indent_level);
|
||||
EggGroupNode::write(out, indent_level);
|
||||
out << flush;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggData::post_read
|
||||
// Access: Private
|
||||
// Description: Does whatever processing is appropriate after reading
|
||||
// the data in from an egg file.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void EggData::
|
||||
post_read() {
|
||||
CoordinateSystem old_coordsys = _coordsys;
|
||||
_coordsys = find_coordsys_entry();
|
||||
|
||||
if (_coordsys == CS_default) {
|
||||
// If the egg file didn't contain a <CoordinateSystem> entry,
|
||||
// assume it's Y-up, by convention.
|
||||
_coordsys = CS_yup_right;
|
||||
|
||||
} else if (_coordsys == CS_invalid) {
|
||||
egg_cat.warning()
|
||||
<< "Contradictory <CoordinateSystem> entries encountered.\n";
|
||||
_coordsys = CS_yup_right;
|
||||
}
|
||||
|
||||
r_mark_coordsys(_coordsys);
|
||||
|
||||
if (old_coordsys != CS_default) {
|
||||
// Now if we had a previous definition, enforce it. This might
|
||||
// convert the data to the given coordinate system.
|
||||
set_coordinate_system(old_coordsys);
|
||||
}
|
||||
|
||||
// Fill this in before we automatically resolve pathnames.
|
||||
_had_absolute_pathnames = has_absolute_pathnames();
|
||||
|
||||
if (get_auto_resolve_externals()) {
|
||||
// Resolve filenames that are relative to the egg file.
|
||||
DSearchPath dir;
|
||||
dir.append_directory(get_egg_filename().get_dirname());
|
||||
resolve_filenames(dir);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggData::pre_write
|
||||
// Access: Private
|
||||
// Description: Does whatever processing is appropriate just before
|
||||
// writing the data out to an egg file. This includes
|
||||
// verifying that vertex pool names are unique, etc.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void EggData::
|
||||
pre_write() {
|
||||
// Pull out all of the texture definitions in the file and massage
|
||||
// them a bit.
|
||||
EggTextureCollection textures;
|
||||
textures.extract_textures(this);
|
||||
|
||||
// Remove any textures that aren't being used.
|
||||
textures.remove_unused_textures(this);
|
||||
|
||||
// Collapse out any textures that are completely equivalent. For
|
||||
// this purpose, we consider two textures with identical properties
|
||||
// but different tref names to be different.
|
||||
textures.collapse_equivalent_textures(~0, this);
|
||||
|
||||
// Make sure all of the textures have unique TRef names.
|
||||
textures.uniquify_trefs();
|
||||
textures.sort_by_tref();
|
||||
|
||||
// Do the same thing with the materials.
|
||||
EggMaterialCollection materials;
|
||||
materials.extract_materials(this);
|
||||
materials.remove_unused_materials(this);
|
||||
materials.collapse_equivalent_materials(~0, this);
|
||||
materials.uniquify_mrefs();
|
||||
materials.sort_by_mref();
|
||||
|
||||
// Now put them all back at the head of the file, after any initial
|
||||
// comment records.
|
||||
iterator ci = begin();
|
||||
while (ci != end() && (*ci)->is_of_type(EggComment::get_class_type())) {
|
||||
++ci;
|
||||
}
|
||||
textures.insert_textures(this, ci);
|
||||
materials.insert_materials(this, ci);
|
||||
|
||||
// Also make sure that the vertex pools are uniquely named. This
|
||||
// also checks textures and materials, which is kind of redundant
|
||||
// since we just did that, but we don't mind.
|
||||
EggPoolUniquifier pu;
|
||||
pu.uniquify(this);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,25 +1,25 @@
|
|||
#begin ss_lib_target
|
||||
#define TARGET p3objegg
|
||||
#define LOCAL_LIBS p3converter p3pandatoolbase
|
||||
#define OTHER_LIBS \
|
||||
p3egg:c pandaegg:m \
|
||||
p3pipeline:c p3event:c p3pstatclient:c panda:m \
|
||||
p3pandabase:c p3pnmimage:c p3mathutil:c p3linmath:c p3putil:c p3express:c \
|
||||
p3interrogatedb:c p3prc:c p3dconfig:c p3dtoolconfig:m \
|
||||
p3dtoolutil:c p3dtoolbase:c p3dtool:m \
|
||||
$[if $[WANT_NATIVE_NET],p3nativenet:c] \
|
||||
$[if $[and $[HAVE_NET],$[WANT_NATIVE_NET]],p3net:c p3downloader:c]
|
||||
|
||||
#define UNIX_SYS_LIBS \
|
||||
m
|
||||
|
||||
#define SOURCES \
|
||||
config_objegg.cxx config_objegg.h \
|
||||
objToEggConverter.cxx objToEggConverter.h objToEggConverter.I \
|
||||
eggToObjConverter.cxx eggToObjConverter.h
|
||||
|
||||
#define INSTALL_HEADERS \
|
||||
objToEggConverter.h objToEggConverter.I \
|
||||
eggToObjConverter.h
|
||||
|
||||
#end ss_lib_target
|
||||
#begin ss_lib_target
|
||||
#define TARGET p3objegg
|
||||
#define LOCAL_LIBS p3converter p3pandatoolbase
|
||||
#define OTHER_LIBS \
|
||||
p3egg:c pandaegg:m \
|
||||
p3pipeline:c p3event:c p3pstatclient:c panda:m \
|
||||
p3pandabase:c p3pnmimage:c p3mathutil:c p3linmath:c p3putil:c p3express:c \
|
||||
p3interrogatedb:c p3prc:c p3dconfig:c p3dtoolconfig:m \
|
||||
p3dtoolutil:c p3dtoolbase:c p3dtool:m \
|
||||
$[if $[WANT_NATIVE_NET],p3nativenet:c] \
|
||||
$[if $[and $[HAVE_NET],$[WANT_NATIVE_NET]],p3net:c p3downloader:c]
|
||||
|
||||
#define UNIX_SYS_LIBS \
|
||||
m
|
||||
|
||||
#define SOURCES \
|
||||
config_objegg.cxx config_objegg.h \
|
||||
objToEggConverter.cxx objToEggConverter.h objToEggConverter.I \
|
||||
eggToObjConverter.cxx eggToObjConverter.h
|
||||
|
||||
#define INSTALL_HEADERS \
|
||||
objToEggConverter.h objToEggConverter.I \
|
||||
eggToObjConverter.h
|
||||
|
||||
#end ss_lib_target
|
||||
|
|
|
|||
|
|
@ -1,462 +1,462 @@
|
|||
// 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 "config_egg.h"
|
||||
#include "eggData.h"
|
||||
#include "string_utils.h"
|
||||
#include "streamReader.h"
|
||||
#include "virtualFileSystem.h"
|
||||
#include "eggPolygon.h"
|
||||
#include "eggPoint.h"
|
||||
#include "eggLine.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;
|
||||
}
|
||||
if (egg_precision != 0) {
|
||||
file->precision(egg_precision);
|
||||
}
|
||||
|
||||
_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 = (file != (ostream *)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 or points. 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(EggPrimitive::get_class_type())) {
|
||||
EggPrimitive *egg_prim = DCAST(EggPrimitive, egg_node);
|
||||
EggPrimitive::iterator pi;
|
||||
for (pi = egg_prim->begin(); pi != egg_prim->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,
|
||||
// points, or lines encountered.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void EggToObjConverter::
|
||||
write_faces(ostream &out, EggNode *egg_node) {
|
||||
if (egg_node->is_of_type(EggPrimitive::get_class_type())) {
|
||||
const char *prim_type = NULL;
|
||||
if (egg_node->is_of_type(EggPolygon::get_class_type())) {
|
||||
prim_type = "f";
|
||||
} else if (egg_node->is_of_type(EggPoint::get_class_type())) {
|
||||
prim_type = "p";
|
||||
} else if (egg_node->is_of_type(EggLine::get_class_type())) {
|
||||
prim_type = "l";
|
||||
}
|
||||
|
||||
if (prim_type != NULL) {
|
||||
write_group_reference(out, egg_node);
|
||||
|
||||
EggPrimitive *egg_prim = DCAST(EggPrimitive, egg_node);
|
||||
|
||||
out << prim_type;
|
||||
EggPrimitive::iterator pi;
|
||||
for (pi = egg_prim->begin(); pi != egg_prim->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 **)PANDA_MALLOC_ARRAY(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";
|
||||
}
|
||||
PANDA_FREE_ARRAY(vertices);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// 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)
|
||||
{
|
||||
}
|
||||
// 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 "config_egg.h"
|
||||
#include "eggData.h"
|
||||
#include "string_utils.h"
|
||||
#include "streamReader.h"
|
||||
#include "virtualFileSystem.h"
|
||||
#include "eggPolygon.h"
|
||||
#include "eggPoint.h"
|
||||
#include "eggLine.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;
|
||||
}
|
||||
if (egg_precision != 0) {
|
||||
file->precision(egg_precision);
|
||||
}
|
||||
|
||||
_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 = (file != (ostream *)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 or points. 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(EggPrimitive::get_class_type())) {
|
||||
EggPrimitive *egg_prim = DCAST(EggPrimitive, egg_node);
|
||||
EggPrimitive::iterator pi;
|
||||
for (pi = egg_prim->begin(); pi != egg_prim->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,
|
||||
// points, or lines encountered.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void EggToObjConverter::
|
||||
write_faces(ostream &out, EggNode *egg_node) {
|
||||
if (egg_node->is_of_type(EggPrimitive::get_class_type())) {
|
||||
const char *prim_type = NULL;
|
||||
if (egg_node->is_of_type(EggPolygon::get_class_type())) {
|
||||
prim_type = "f";
|
||||
} else if (egg_node->is_of_type(EggPoint::get_class_type())) {
|
||||
prim_type = "p";
|
||||
} else if (egg_node->is_of_type(EggLine::get_class_type())) {
|
||||
prim_type = "l";
|
||||
}
|
||||
|
||||
if (prim_type != NULL) {
|
||||
write_group_reference(out, egg_node);
|
||||
|
||||
EggPrimitive *egg_prim = DCAST(EggPrimitive, egg_node);
|
||||
|
||||
out << prim_type;
|
||||
EggPrimitive::iterator pi;
|
||||
for (pi = egg_prim->begin(); pi != egg_prim->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 **)PANDA_MALLOC_ARRAY(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";
|
||||
}
|
||||
PANDA_FREE_ARRAY(vertices);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// 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)
|
||||
{
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,152 +1,152 @@
|
|||
// Filename: ObjToEggConverter.h
|
||||
// Created by: drose (07Dec10)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 OBJTOEGGCONVERTER_H
|
||||
#define OBJTOEGGCONVERTER_H
|
||||
|
||||
#include "pandatoolbase.h"
|
||||
|
||||
#include "somethingToEggConverter.h"
|
||||
#include "eggVertexPool.h"
|
||||
#include "eggGroup.h"
|
||||
#include "geomVertexData.h"
|
||||
#include "geomVertexWriter.h"
|
||||
#include "geomPrimitive.h"
|
||||
#include "geomNode.h"
|
||||
#include "pandaNode.h"
|
||||
#include "pvector.h"
|
||||
#include "epvector.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : ObjToEggConverter
|
||||
// Description : Convert an Obj file to egg data.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class ObjToEggConverter : public SomethingToEggConverter {
|
||||
public:
|
||||
ObjToEggConverter();
|
||||
ObjToEggConverter(const ObjToEggConverter ©);
|
||||
~ObjToEggConverter();
|
||||
|
||||
virtual SomethingToEggConverter *make_copy();
|
||||
|
||||
virtual string get_name() const;
|
||||
virtual string get_extension() const;
|
||||
virtual bool supports_compressed() const;
|
||||
virtual bool supports_convert_to_node(const LoaderOptions &options) const;
|
||||
|
||||
virtual bool convert_file(const Filename &filename);
|
||||
virtual PT(PandaNode) convert_to_node(const LoaderOptions &options, const Filename &filename);
|
||||
|
||||
protected:
|
||||
bool process(const Filename &filename);
|
||||
bool process_line(const string &line);
|
||||
bool process_ref_plane_res(const string &line);
|
||||
|
||||
bool process_v(vector_string &words);
|
||||
bool process_vt(vector_string &words);
|
||||
bool process_xvt(vector_string &words);
|
||||
bool process_xvc(vector_string &words);
|
||||
bool process_vn(vector_string &words);
|
||||
bool process_f(vector_string &words);
|
||||
bool process_g(vector_string &words);
|
||||
|
||||
EggVertex *get_face_vertex(const string &face_reference);
|
||||
void generate_egg_points();
|
||||
|
||||
bool process_node(const Filename &filename);
|
||||
bool process_line_node(const string &line);
|
||||
|
||||
bool process_f_node(vector_string &words);
|
||||
bool process_g_node(vector_string &words);
|
||||
|
||||
void generate_points();
|
||||
int add_synth_normal(const LVecBase3d &normal);
|
||||
|
||||
// Read from the obj file.
|
||||
int _line_number;
|
||||
typedef epvector<LVecBase4d> Vec4Table;
|
||||
typedef epvector<LVecBase3d> Vec3Table;
|
||||
typedef epvector<LVecBase2d> Vec2Table;
|
||||
typedef pmap<LVecBase3d, int> UniqueVec3Table;
|
||||
|
||||
Vec4Table _v_table;
|
||||
Vec3Table _vn_table, _rgb_table;
|
||||
Vec3Table _vt_table;
|
||||
Vec2Table _xvt_table;
|
||||
Vec3Table _synth_vn_table;
|
||||
UniqueVec3Table _unique_synth_vn_table;
|
||||
LVecBase2d _ref_plane_res;
|
||||
bool _v4_given, _vt3_given;
|
||||
bool _f_given;
|
||||
|
||||
pset<string> _ignored_tags;
|
||||
|
||||
// Structures filled when creating an egg file.
|
||||
PT(EggVertexPool) _vpool;
|
||||
PT(EggGroup) _root_group;
|
||||
EggGroup *_current_group;
|
||||
|
||||
// Structures filled when creating a PandaNode directly.
|
||||
PT(PandaNode) _root_node;
|
||||
|
||||
class VertexEntry {
|
||||
public:
|
||||
VertexEntry();
|
||||
VertexEntry(const ObjToEggConverter *converter, const string &obj_vertex);
|
||||
|
||||
INLINE bool operator < (const VertexEntry &other) const;
|
||||
INLINE bool operator == (const VertexEntry &other) const;
|
||||
INLINE bool matches_except_normal(const VertexEntry &other) const;
|
||||
|
||||
// The 1-based vertex, texcoord, and normal index numbers
|
||||
// appearing in the obj file for this vertex. 0 if the index
|
||||
// number is not given.
|
||||
int _vi, _vti, _vni;
|
||||
|
||||
// The 1-based index number to the synthesized normal, if needed.
|
||||
int _synth_vni;
|
||||
};
|
||||
typedef pmap<VertexEntry, int> UniqueVertexEntries;
|
||||
typedef pvector<VertexEntry> VertexEntries;
|
||||
|
||||
class VertexData {
|
||||
public:
|
||||
VertexData(PandaNode *parent, const string &name);
|
||||
|
||||
int add_vertex(const ObjToEggConverter *converter, const VertexEntry &entry);
|
||||
void add_triangle(const ObjToEggConverter *converter, const VertexEntry &v0,
|
||||
const VertexEntry &v1, const VertexEntry &v2,
|
||||
int synth_vni);
|
||||
void close_geom(const ObjToEggConverter *converter);
|
||||
|
||||
PT(PandaNode) _parent;
|
||||
string _name;
|
||||
PT(GeomNode) _geom_node;
|
||||
|
||||
PT(GeomPrimitive) _prim;
|
||||
VertexEntries _entries;
|
||||
UniqueVertexEntries _unique_entries;
|
||||
|
||||
bool _v4_given, _vt3_given;
|
||||
bool _vt_given, _rgb_given, _vn_given;
|
||||
};
|
||||
|
||||
VertexData *_current_vertex_data;
|
||||
|
||||
friend class VertexData;
|
||||
};
|
||||
|
||||
#include "objToEggConverter.I"
|
||||
|
||||
#endif
|
||||
// Filename: ObjToEggConverter.h
|
||||
// Created by: drose (07Dec10)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 OBJTOEGGCONVERTER_H
|
||||
#define OBJTOEGGCONVERTER_H
|
||||
|
||||
#include "pandatoolbase.h"
|
||||
|
||||
#include "somethingToEggConverter.h"
|
||||
#include "eggVertexPool.h"
|
||||
#include "eggGroup.h"
|
||||
#include "geomVertexData.h"
|
||||
#include "geomVertexWriter.h"
|
||||
#include "geomPrimitive.h"
|
||||
#include "geomNode.h"
|
||||
#include "pandaNode.h"
|
||||
#include "pvector.h"
|
||||
#include "epvector.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : ObjToEggConverter
|
||||
// Description : Convert an Obj file to egg data.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class ObjToEggConverter : public SomethingToEggConverter {
|
||||
public:
|
||||
ObjToEggConverter();
|
||||
ObjToEggConverter(const ObjToEggConverter ©);
|
||||
~ObjToEggConverter();
|
||||
|
||||
virtual SomethingToEggConverter *make_copy();
|
||||
|
||||
virtual string get_name() const;
|
||||
virtual string get_extension() const;
|
||||
virtual bool supports_compressed() const;
|
||||
virtual bool supports_convert_to_node(const LoaderOptions &options) const;
|
||||
|
||||
virtual bool convert_file(const Filename &filename);
|
||||
virtual PT(PandaNode) convert_to_node(const LoaderOptions &options, const Filename &filename);
|
||||
|
||||
protected:
|
||||
bool process(const Filename &filename);
|
||||
bool process_line(const string &line);
|
||||
bool process_ref_plane_res(const string &line);
|
||||
|
||||
bool process_v(vector_string &words);
|
||||
bool process_vt(vector_string &words);
|
||||
bool process_xvt(vector_string &words);
|
||||
bool process_xvc(vector_string &words);
|
||||
bool process_vn(vector_string &words);
|
||||
bool process_f(vector_string &words);
|
||||
bool process_g(vector_string &words);
|
||||
|
||||
EggVertex *get_face_vertex(const string &face_reference);
|
||||
void generate_egg_points();
|
||||
|
||||
bool process_node(const Filename &filename);
|
||||
bool process_line_node(const string &line);
|
||||
|
||||
bool process_f_node(vector_string &words);
|
||||
bool process_g_node(vector_string &words);
|
||||
|
||||
void generate_points();
|
||||
int add_synth_normal(const LVecBase3d &normal);
|
||||
|
||||
// Read from the obj file.
|
||||
int _line_number;
|
||||
typedef epvector<LVecBase4d> Vec4Table;
|
||||
typedef epvector<LVecBase3d> Vec3Table;
|
||||
typedef epvector<LVecBase2d> Vec2Table;
|
||||
typedef pmap<LVecBase3d, int> UniqueVec3Table;
|
||||
|
||||
Vec4Table _v_table;
|
||||
Vec3Table _vn_table, _rgb_table;
|
||||
Vec3Table _vt_table;
|
||||
Vec2Table _xvt_table;
|
||||
Vec3Table _synth_vn_table;
|
||||
UniqueVec3Table _unique_synth_vn_table;
|
||||
LVecBase2d _ref_plane_res;
|
||||
bool _v4_given, _vt3_given;
|
||||
bool _f_given;
|
||||
|
||||
pset<string> _ignored_tags;
|
||||
|
||||
// Structures filled when creating an egg file.
|
||||
PT(EggVertexPool) _vpool;
|
||||
PT(EggGroup) _root_group;
|
||||
EggGroup *_current_group;
|
||||
|
||||
// Structures filled when creating a PandaNode directly.
|
||||
PT(PandaNode) _root_node;
|
||||
|
||||
class VertexEntry {
|
||||
public:
|
||||
VertexEntry();
|
||||
VertexEntry(const ObjToEggConverter *converter, const string &obj_vertex);
|
||||
|
||||
INLINE bool operator < (const VertexEntry &other) const;
|
||||
INLINE bool operator == (const VertexEntry &other) const;
|
||||
INLINE bool matches_except_normal(const VertexEntry &other) const;
|
||||
|
||||
// The 1-based vertex, texcoord, and normal index numbers
|
||||
// appearing in the obj file for this vertex. 0 if the index
|
||||
// number is not given.
|
||||
int _vi, _vti, _vni;
|
||||
|
||||
// The 1-based index number to the synthesized normal, if needed.
|
||||
int _synth_vni;
|
||||
};
|
||||
typedef pmap<VertexEntry, int> UniqueVertexEntries;
|
||||
typedef pvector<VertexEntry> VertexEntries;
|
||||
|
||||
class VertexData {
|
||||
public:
|
||||
VertexData(PandaNode *parent, const string &name);
|
||||
|
||||
int add_vertex(const ObjToEggConverter *converter, const VertexEntry &entry);
|
||||
void add_triangle(const ObjToEggConverter *converter, const VertexEntry &v0,
|
||||
const VertexEntry &v1, const VertexEntry &v2,
|
||||
int synth_vni);
|
||||
void close_geom(const ObjToEggConverter *converter);
|
||||
|
||||
PT(PandaNode) _parent;
|
||||
string _name;
|
||||
PT(GeomNode) _geom_node;
|
||||
|
||||
PT(GeomPrimitive) _prim;
|
||||
VertexEntries _entries;
|
||||
UniqueVertexEntries _unique_entries;
|
||||
|
||||
bool _v4_given, _vt3_given;
|
||||
bool _vt_given, _rgb_given, _vn_given;
|
||||
};
|
||||
|
||||
VertexData *_current_vertex_data;
|
||||
|
||||
friend class VertexData;
|
||||
};
|
||||
|
||||
#include "objToEggConverter.I"
|
||||
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Reference in New Issue