From 891c04db072093d98ff571948d59d413f85242ec Mon Sep 17 00:00:00 2001 From: David Rose Date: Fri, 3 Oct 2003 01:47:45 +0000 Subject: [PATCH] add egg2flt --- pandatool/src/flt/fltGeometry.I | 32 + pandatool/src/flt/fltGeometry.cxx | 32 +- pandatool/src/flt/fltGeometry.h | 14 +- pandatool/src/flt/fltHeader.cxx | 24 + pandatool/src/flt/fltHeader.h | 2 + pandatool/src/flt/fltMaterial.cxx | 2 +- pandatool/src/flt/fltPackedColor.I | 10 +- pandatool/src/flt/fltTexture.cxx | 2 +- pandatool/src/flt/fltVertex.I | 11 + pandatool/src/flt/fltVertex.cxx | 27 +- pandatool/src/flt/fltVertex.h | 2 + pandatool/src/flt/fltVertexList.cxx | 3 +- pandatool/src/fltegg/fltToEggConverter.cxx | 2 +- pandatool/src/fltegg/fltToEggLevelState.cxx | 2 +- pandatool/src/fltprogs/Sources.pp | 15 + pandatool/src/fltprogs/eggToFlt.cxx | 660 ++++++++++++++++++++ pandatool/src/fltprogs/eggToFlt.h | 77 +++ pandatool/src/fltprogs/fltToEgg.cxx | 4 +- pandatool/src/fltprogs/fltToEgg.h | 10 +- pandatool/src/progbase/Sources.pp | 5 +- pandatool/src/progbase/withOutputFile.I | 29 + pandatool/src/progbase/withOutputFile.h | 4 + 22 files changed, 934 insertions(+), 35 deletions(-) create mode 100644 pandatool/src/fltprogs/eggToFlt.cxx create mode 100644 pandatool/src/fltprogs/eggToFlt.h create mode 100644 pandatool/src/progbase/withOutputFile.I diff --git a/pandatool/src/flt/fltGeometry.I b/pandatool/src/flt/fltGeometry.I index c64855d632..de6debc128 100644 --- a/pandatool/src/flt/fltGeometry.I +++ b/pandatool/src/flt/fltGeometry.I @@ -39,6 +39,22 @@ get_texture() const { return _header->get_texture(_texture_index); } +//////////////////////////////////////////////////////////////////// +// Function: FltGeometry::set_texture +// Access: Public +// Description: Applies the indicated texture to this face, or if the +// texture is NULL, clears it. +//////////////////////////////////////////////////////////////////// +INLINE void FltGeometry:: +set_texture(FltTexture *texture) { + if (texture == (FltTexture *)NULL) { + _texture_index = -1; + } else { + _header->add_texture(texture); + _texture_index = texture->_pattern_index; + } +} + //////////////////////////////////////////////////////////////////// // Function: FltGeometry::has_material // Access: Public @@ -61,6 +77,22 @@ get_material() const { return _header->get_material(_material_index); } +//////////////////////////////////////////////////////////////////// +// Function: FltGeometry::set_material +// Access: Public +// Description: Applies the indicated material to this face, or if the +// material is NULL, clears it. +//////////////////////////////////////////////////////////////////// +INLINE void FltGeometry:: +set_material(FltMaterial *material) { + if (material == (FltMaterial *)NULL) { + _material_index = -1; + } else { + _header->add_material(material); + _material_index = material->_material_index; + } +} + //////////////////////////////////////////////////////////////////// // Function: FltGeometry::has_color // Access: Public diff --git a/pandatool/src/flt/fltGeometry.cxx b/pandatool/src/flt/fltGeometry.cxx index 5cd3450a45..1d228558f0 100644 --- a/pandatool/src/flt/fltGeometry.cxx +++ b/pandatool/src/flt/fltGeometry.cxx @@ -33,7 +33,7 @@ FltGeometry:: FltGeometry(FltHeader *header) : FltBeadID(header) { _ir_color = 0; _relative_priority = 0; - _draw_type = DT_solid_backface; + _draw_type = DT_solid_cull_backface; _texwhite = false; _color_name_index = 0; _alt_color_name_index = 0; @@ -47,7 +47,7 @@ FltGeometry(FltHeader *header) : FltBeadID(header) { _transparency = 0; _lod_generation_control = 0; _line_style_index = 0; - _flags = 0; + _flags = F_no_color; _light_mode = LM_face_no_normal; _texture_mapping_index = 0; _color_index = 0; @@ -94,6 +94,18 @@ get_color() const { return color; } +//////////////////////////////////////////////////////////////////// +// Function: FltGeometry::set_color +// Access: Public +// Description: Sets the primary color of the face, using the packed +// color convention. +//////////////////////////////////////////////////////////////////// +void FltGeometry:: +set_color(const Colorf &color) { + set_rgb(RGBColorf(color[0], color[1], color[2])); + _transparency = (int)floor((1.0 - color[3]) * 65535.0); +} + //////////////////////////////////////////////////////////////////// // Function: FltGeometry::get_rgb // Access: Public @@ -117,6 +129,22 @@ get_rgb() const { _packed_color); } +//////////////////////////////////////////////////////////////////// +// Function: FltGeometry::set_rgb +// Access: Public +// Description: Sets the primary color of the face, using the packed +// color convention; does not affect transparency. +//////////////////////////////////////////////////////////////////// +void FltGeometry:: +set_rgb(const RGBColorf &rgb) { + _packed_color.set_rgb(rgb); + _flags = ((_flags & ~F_no_color) | F_packed_color); + + // If we have a color, we can't have a material. + _material_index = -1; + _texwhite = false; +} + //////////////////////////////////////////////////////////////////// // Function: FltGeometry::has_alt_color // Access: Public diff --git a/pandatool/src/flt/fltGeometry.h b/pandatool/src/flt/fltGeometry.h index 5fa003169b..5ee0256510 100644 --- a/pandatool/src/flt/fltGeometry.h +++ b/pandatool/src/flt/fltGeometry.h @@ -42,14 +42,14 @@ public: FltGeometry(FltHeader *header); enum DrawType { - DT_solid_backface = 0, - DT_solid_no_backface = 1, + DT_solid_cull_backface = 0, + DT_solid_no_cull = 1, DT_wireframe = 2, DT_wireframe_close = 3, DT_wireframe_highlight = 4, - DT_omni_light = 5, - DT_uni_light = 6, - DT_bi_light = 7 + DT_omni_light = 8, + DT_uni_light = 9, + DT_bi_light = 10 }; enum BillboardType { @@ -102,13 +102,17 @@ public: public: INLINE bool has_texture() const; INLINE FltTexture *get_texture() const; + INLINE void set_texture(FltTexture *texture); INLINE bool has_material() const; INLINE FltMaterial *get_material() const; + INLINE void set_material(FltMaterial *material); INLINE bool has_color() const; Colorf get_color() const; + void set_color(const Colorf &color); RGBColorf get_rgb() const; + void set_rgb(const RGBColorf &rgb); bool has_alt_color() const; Colorf get_alt_color() const; diff --git a/pandatool/src/flt/fltHeader.cxx b/pandatool/src/flt/fltHeader.cxx index 699887203f..6ac970c360 100644 --- a/pandatool/src/flt/fltHeader.cxx +++ b/pandatool/src/flt/fltHeader.cxx @@ -103,6 +103,8 @@ FltHeader(PathReplace *path_replace) : FltBeadID(this) { _vertex_lookups_stale = false; _current_vertex_offset = 0; + _next_material_index = 1; + _next_pattern_index = 1; _got_color_palette = false; _got_14_material_palette = false; _got_eyepoint_trackplane_palette = false; @@ -957,6 +959,17 @@ clear_materials() { //////////////////////////////////////////////////////////////////// void FltHeader:: add_material(FltMaterial *material) { + if (material->_material_index < 0) { + // We need to make up a new material index for the material. + material->_material_index = _next_material_index; + _next_material_index++; + + } else { + // Make sure our next generated material index will be different + // from any existing material indices. + _next_material_index = max(_next_material_index, material->_material_index + 1); + } + _materials[material->_material_index] = material; } @@ -1018,6 +1031,17 @@ clear_textures() { //////////////////////////////////////////////////////////////////// void FltHeader:: add_texture(FltTexture *texture) { + if (texture->_pattern_index < 0) { + // We need to make up a new pattern index for the texture. + texture->_pattern_index = _next_pattern_index; + _next_pattern_index++; + + } else { + // Make sure our next generated pattern index will be different + // from any existing texture indices. + _next_pattern_index = max(_next_pattern_index, texture->_pattern_index + 1); + } + _textures[texture->_pattern_index] = texture; } diff --git a/pandatool/src/flt/fltHeader.h b/pandatool/src/flt/fltHeader.h index aa44f421fc..b4b894ed45 100644 --- a/pandatool/src/flt/fltHeader.h +++ b/pandatool/src/flt/fltHeader.h @@ -279,12 +279,14 @@ private: bool _got_14_material_palette; typedef pmap Materials; Materials _materials; + int _next_material_index; // Support for the texture palette. AttrUpdate _auto_attr_update; typedef pmap Textures; Textures _textures; + int _next_pattern_index; // Support for the light source palette. diff --git a/pandatool/src/flt/fltMaterial.cxx b/pandatool/src/flt/fltMaterial.cxx index 8e7e1206d8..b5d03e0753 100644 --- a/pandatool/src/flt/fltMaterial.cxx +++ b/pandatool/src/flt/fltMaterial.cxx @@ -29,7 +29,7 @@ TypeHandle FltMaterial::_type_handle; //////////////////////////////////////////////////////////////////// FltMaterial:: FltMaterial(FltHeader *header) : FltRecord(header) { - _material_index = 0; + _material_index = -1; _flags = 0; _ambient.set(0.0, 0.0, 0.0); _diffuse.set(0.0, 0.0, 0.0); diff --git a/pandatool/src/flt/fltPackedColor.I b/pandatool/src/flt/fltPackedColor.I index e3e47f7121..f8ec692878 100644 --- a/pandatool/src/flt/fltPackedColor.I +++ b/pandatool/src/flt/fltPackedColor.I @@ -68,9 +68,9 @@ get_rgb() const { INLINE void FltPackedColor:: set_color(const Colorf &color) { _r = (int)floor(color[0] * 255.0); - _g = (int)floor(color[0] * 255.0); - _b = (int)floor(color[0] * 255.0); - _a = (int)floor(color[0] * 255.0); + _g = (int)floor(color[1] * 255.0); + _b = (int)floor(color[2] * 255.0); + _a = (int)floor(color[3] * 255.0); } //////////////////////////////////////////////////////////////////// @@ -83,7 +83,7 @@ set_color(const Colorf &color) { INLINE void FltPackedColor:: set_rgb(const RGBColorf &color) { _r = (int)floor(color[0] * 255.0); - _g = (int)floor(color[0] * 255.0); - _b = (int)floor(color[0] * 255.0); + _g = (int)floor(color[1] * 255.0); + _b = (int)floor(color[2] * 255.0); _a = 255; } diff --git a/pandatool/src/flt/fltTexture.cxx b/pandatool/src/flt/fltTexture.cxx index 2fc6fd14fc..fc65b9fb43 100644 --- a/pandatool/src/flt/fltTexture.cxx +++ b/pandatool/src/flt/fltTexture.cxx @@ -32,7 +32,7 @@ TypeHandle FltTexture::_type_handle; //////////////////////////////////////////////////////////////////// FltTexture:: FltTexture(FltHeader *header) : FltRecord(header) { - _pattern_index = 0; + _pattern_index = -1; _x_location = 0; _y_location = 0; diff --git a/pandatool/src/flt/fltVertex.I b/pandatool/src/flt/fltVertex.I index 6da8e35cce..27cf840bbd 100644 --- a/pandatool/src/flt/fltVertex.I +++ b/pandatool/src/flt/fltVertex.I @@ -30,3 +30,14 @@ has_color() const { return ((_flags & F_no_color) == 0 && (_color_index != -1 || ((_flags & F_packed_color) != 0))); } + +//////////////////////////////////////////////////////////////////// +// Function: FltVertex::set_color +// Access: Public +// Description: Sets the color of the vertex, using the packed +// color convention. The alpha component is ignored. +//////////////////////////////////////////////////////////////////// +INLINE void FltVertex:: +set_color(const Colorf &color) { + set_rgb(RGBColorf(color[0], color[1], color[2])); +} diff --git a/pandatool/src/flt/fltVertex.cxx b/pandatool/src/flt/fltVertex.cxx index 65485bb49f..b04785c4d4 100644 --- a/pandatool/src/flt/fltVertex.cxx +++ b/pandatool/src/flt/fltVertex.cxx @@ -31,7 +31,7 @@ TypeHandle FltVertex::_type_handle; FltVertex:: FltVertex(FltHeader *header) : FltRecord(header) { _color_name_index = 0; - _flags = 0; + _flags = F_no_color; _pos.set(0.0, 0.0, 0.0); _normal.set(0.0, 0.0, 0.0); _uv.set(0.0, 0.0); @@ -117,10 +117,10 @@ get_record_length() const { //////////////////////////////////////////////////////////////////// // Function: FltVertex::get_color // Access: Public -// Description: If has_color() indicates true, returns the primary -// color of the face, as a four-component value. In the -// case of a vertex, the alpha channel will always be -// 1.0, as MultiGen does not store transparency +// Description: If has_color() indicates true, returns the +// color of the vertex, as a four-component value. In +// the case of a vertex, the alpha channel will always +// be 1.0, as MultiGen does not store transparency // per-vertex. //////////////////////////////////////////////////////////////////// Colorf FltVertex:: @@ -134,9 +134,8 @@ get_color() const { //////////////////////////////////////////////////////////////////// // Function: FltVertex::get_rgb // Access: Public -// Description: If has_color() indicates true, returns the primary -// color of the face, as a three-component value -// ignoring transparency. +// Description: If has_color() indicates true, returns the +// color of the vertex, as a three-component value. //////////////////////////////////////////////////////////////////// RGBColorf FltVertex:: get_rgb() const { @@ -146,6 +145,18 @@ get_rgb() const { _packed_color); } +//////////////////////////////////////////////////////////////////// +// Function: FltVertex::set_rgb +// Access: Public +// Description: Sets the color of the vertex, using the packed +// color convention. +//////////////////////////////////////////////////////////////////// +void FltVertex:: +set_rgb(const RGBColorf &rgb) { + _packed_color.set_rgb(rgb); + _flags = ((_flags & ~F_no_color) | F_packed_color); +} + //////////////////////////////////////////////////////////////////// // Function: FltVertex::extract_record // Access: Protected, Virtual diff --git a/pandatool/src/flt/fltVertex.h b/pandatool/src/flt/fltVertex.h index 1b049e1a44..dfaadf7e84 100644 --- a/pandatool/src/flt/fltVertex.h +++ b/pandatool/src/flt/fltVertex.h @@ -64,7 +64,9 @@ public: public: INLINE bool has_color() const; Colorf get_color() const; + INLINE void set_color(const Colorf &color); RGBColorf get_rgb() const; + void set_rgb(const RGBColorf &rgb); protected: diff --git a/pandatool/src/flt/fltVertexList.cxx b/pandatool/src/flt/fltVertexList.cxx index 36f29127dc..a64100c4ae 100644 --- a/pandatool/src/flt/fltVertexList.cxx +++ b/pandatool/src/flt/fltVertexList.cxx @@ -67,11 +67,10 @@ clear_vertices() { // Function: FltVertexList::add_vertex // Access: Public // Description: Adds a new vertex to the end of the vertex list. -// Care must be taken to ensure the vertex is also added -// to the vertex palette. //////////////////////////////////////////////////////////////////// void FltVertexList:: add_vertex(FltVertex *vertex) { + _header->add_vertex(vertex); _vertices.push_back(vertex); } diff --git a/pandatool/src/fltegg/fltToEggConverter.cxx b/pandatool/src/fltegg/fltToEggConverter.cxx index 6aaf9007ed..b72819e8c4 100644 --- a/pandatool/src/fltegg/fltToEggConverter.cxx +++ b/pandatool/src/fltegg/fltToEggConverter.cxx @@ -526,7 +526,7 @@ setup_geometry(const FltGeometry *flt_geom, FltToEggLevelState &state, } } - if (flt_geom->_draw_type == FltGeometry::DT_solid_no_backface) { + if (flt_geom->_draw_type == FltGeometry::DT_solid_no_cull) { // A double-sided polygon. egg_prim->set_bface_flag(true); } diff --git a/pandatool/src/fltegg/fltToEggLevelState.cxx b/pandatool/src/fltegg/fltToEggLevelState.cxx index b6613ed8a6..f74dd344f1 100644 --- a/pandatool/src/fltegg/fltToEggLevelState.cxx +++ b/pandatool/src/fltegg/fltToEggLevelState.cxx @@ -65,7 +65,7 @@ ParentNodes() { // // This collects together polygons that share the same // billboard axis and/or transform space into the same -// group, rather that wastefully creating a group per +// group, rather than wastefully creating a group per // polygon. //////////////////////////////////////////////////////////////////// EggGroupNode *FltToEggLevelState:: diff --git a/pandatool/src/fltprogs/Sources.pp b/pandatool/src/fltprogs/Sources.pp index 2622116c70..82438b10c2 100644 --- a/pandatool/src/fltprogs/Sources.pp +++ b/pandatool/src/fltprogs/Sources.pp @@ -59,3 +59,18 @@ fltToEgg.cxx fltToEgg.h #end bin_target + +#begin bin_target + #define TARGET egg2flt + #define LOCAL_LIBS flt eggbase progbase + + #define OTHER_LIBS \ + egg:c pandaegg:m \ + linmath:c panda:m \ + express:c pandaexpress:m \ + dtoolutil:c dtoolbase:c dconfig:c dtoolconfig:m dtool:m pystub + + #define SOURCES \ + eggToFlt.cxx eggToFlt.h + +#end bin_target diff --git a/pandatool/src/fltprogs/eggToFlt.cxx b/pandatool/src/fltprogs/eggToFlt.cxx new file mode 100644 index 0000000000..de42b78398 --- /dev/null +++ b/pandatool/src/fltprogs/eggToFlt.cxx @@ -0,0 +1,660 @@ +// Filename: eggToFlt.cxx +// Created by: drose (01Oct03) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://www.panda3d.org/license.txt . +// +// To contact the maintainers of this program write to +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#include "eggToFlt.h" +#include "fltHeader.h" +#include "fltBead.h" +#include "fltGroup.h" +#include "fltFace.h" +#include "fltVertexList.h" +#include "fltVertex.h" +#include "fltTexture.h" +#include "fltTransformTranslate.h" +#include "fltTransformRotateAboutEdge.h" +#include "fltTransformScale.h" +#include "fltTransformGeneralMatrix.h" +#include "eggPolygon.h" +#include "eggPoint.h" +#include "eggPrimitive.h" +#include "eggExternalReference.h" +#include "eggGroup.h" +#include "eggGroupNode.h" +#include "eggTexture.h" +#include "eggTransform3d.h" +#include "dcast.h" +#include "string_utils.h" +#include "vector_string.h" + +//////////////////////////////////////////////////////////////////// +// Function: EggToFlt::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +EggToFlt:: +EggToFlt() : + EggToSomething("MultiGen", ".flt", true, false) +{ + set_binary_output(true); + set_program_description + ("egg2flt converts files from egg format to MultiGen .flt " + "format. It attempts to be as robust as possible, and matches " + "the capabilities of flt2egg. Generally, converting a model " + "from egg2flt and then back via flt2egg will result in essentially " + "the same egg file, within the limitations of what can be " + "represented in flt."); + + add_option + ("attr", "none/new/all", 0, + "Specifies whether to write (or rewrite) .attr files for each " + "texture image. MultiGen stores texture properties like mipmapping " + "in a separate .attr file for each different texture image. " + "If this parameter is \"none\", these files will not be generated; " + "if this is \"new\", these files will only be generated if they " + "do not already exist (even if the properties have changed). " + "Specifying \"all\" causes these to be rewritten every time.", + &EggToFlt::dispatch_attr, NULL, &_auto_attr_update); + + // Flt files are always in the z-up coordinate system. Don't + // confuse the user with this meaningless option. + remove_option("cs"); + _coordinate_system = CS_zup_right; + _got_coordinate_system = true; + _auto_attr_update = FltHeader::AU_if_missing; +} + +//////////////////////////////////////////////////////////////////// +// Function: EggToFlt::run +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +void EggToFlt:: +run() { + _flt_header = new FltHeader(_path_replace); + _flt_header->set_auto_attr_update(_auto_attr_update); + + traverse(&_data, _flt_header, FltGeometry::BT_none); + + // Finally, write the resulting file out. + FltError result = _flt_header->write_flt(get_output()); + if (result != FE_ok) { + nout << "Cannot write " << get_output_filename() << "\n"; + exit(1); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: EggToFlt::dispatch_attr +// Access: Protected, Static +// Description: Dispatch function for the -attr parameter. +//////////////////////////////////////////////////////////////////// +bool EggToFlt:: +dispatch_attr(const string &opt, const string &arg, void *var) { + FltHeader::AttrUpdate *ip = (FltHeader::AttrUpdate *)var; + + if (cmp_nocase(arg, "none") == 0) { + *ip = FltHeader::AU_none; + + } else if (cmp_nocase(arg, "new") == 0) { + *ip = FltHeader::AU_if_missing; + + } else if (cmp_nocase(arg, "all") == 0) { + *ip = FltHeader::AU_always; + + } else { + nout << "-" << opt + << " requires either \"none\", \"new\", or \"all\".\n"; + return false; + } + + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: EggToFlt::traverse +// Access: Private +// Description: +//////////////////////////////////////////////////////////////////// +void EggToFlt:: +traverse(EggNode *egg_node, FltBead *flt_node, + FltGeometry::BillboardType billboard) { + if (egg_node->is_of_type(EggPolygon::get_class_type()) || + egg_node->is_of_type(EggPoint::get_class_type())) { + // It's a polygon or point light. + EggPrimitive *egg_primitive = DCAST(EggPrimitive, egg_node); + convert_primitive(egg_primitive, flt_node, billboard); + + } else if (egg_node->is_of_type(EggExternalReference::get_class_type())) { + // Convert external references. + + } else if (egg_node->is_of_type(EggGroup::get_class_type())) { + // An EggGroup creates a fltBead, and recurses. + EggGroup *egg_group = DCAST(EggGroup, egg_node); + + if (egg_group->get_group_type() == EggGroup::GT_joint) { + // Ignore joints and their children. + return; + } + + convert_group(egg_group, flt_node, billboard); + + } else if (egg_node->is_of_type(EggGroupNode::get_class_type())) { + // Some kind of grouping node other than an EggGroup. Just recurse. + EggGroupNode *egg_group = DCAST(EggGroupNode, egg_node); + EggGroupNode::iterator ci; + for (ci = egg_group->begin(); ci != egg_group->end(); ++ci) { + traverse(*ci, flt_node, billboard); + } + } +} + +//////////////////////////////////////////////////////////////////// +// Function: EggToFlt::convert_primitive +// Access: Private +// Description: Converts an egg polygon or series of light points to +// the corresponding Flt geometry, and adds it to the +// indicated flt_node. +//////////////////////////////////////////////////////////////////// +void EggToFlt:: +convert_primitive(EggPrimitive *egg_primitive, FltBead *flt_node, + FltGeometry::BillboardType billboard) { + FltFace *flt_face = new FltFace(_flt_header); + flt_node->add_child(flt_face); + + flt_face->_billboard_type = billboard; + + if (egg_primitive->has_color()) { + flt_face->set_color(egg_primitive->get_color()); + } + + if (egg_primitive->is_of_type(EggPoint::get_class_type())) { + // A series of points, instead of a polygon. + flt_face->_draw_type = FltFace::DT_omni_light; + + } else if (egg_primitive->get_bface_flag()) { + // A polygon whose backface is visible. + flt_face->_draw_type = FltFace::DT_solid_no_cull; + + } else { + // A normal polygon. + flt_face->_draw_type = FltFace::DT_solid_cull_backface; + } + + if (egg_primitive->has_texture()) { + EggTexture *egg_texture = egg_primitive->get_texture(); + FltTexture *flt_texture = get_flt_texture(egg_texture); + flt_face->set_texture(flt_texture); + } + + // Create a vertex list representing the vertices in the + // primitive, and add it as a child of the face bead. This is how + // Flt files associate vertices with faces. + FltVertexList *flt_vertices = new FltVertexList(_flt_header); + flt_face->add_child(flt_vertices); + + EggPrimitive::iterator vi; + bool all_verts_have_color = true; + bool all_verts_have_normal = true; + for (vi = egg_primitive->begin(); vi != egg_primitive->end(); ++vi) { + EggVertex *egg_vertex = (*vi); + FltVertex *flt_vertex = get_flt_vertex(egg_vertex, egg_primitive); + flt_vertices->add_vertex(flt_vertex); + + if (!egg_vertex->has_color()) { + all_verts_have_color = false; + } + if (!egg_vertex->has_normal()) { + all_verts_have_normal = false; + } + } + if (all_verts_have_color) { + // If all the vertices of the face have a color specification, + // then we specify per-vertex color on the face. + if (all_verts_have_normal) { + // And similarly with the normals. + flt_face->_light_mode = FltFace::LM_vertex_with_normal; + } else { + flt_face->_light_mode = FltFace::LM_vertex_no_normal; + } + } else { + if (all_verts_have_normal) { + flt_face->_light_mode = FltFace::LM_face_with_normal; + } else { + flt_face->_light_mode = FltFace::LM_face_no_normal; + } + } +} + +//////////////////////////////////////////////////////////////////// +// Function: EggToFlt::convert_group +// Access: Private +// Description: Converts an egg group to the corresponding flt group, +// and adds it to the indicated parent node. Also +// recurses on the children of the egg group. +//////////////////////////////////////////////////////////////////// +void EggToFlt:: +convert_group(EggGroup *egg_group, FltBead *flt_node, + FltGeometry::BillboardType billboard) { + ostringstream egg_syntax; + + FltGroup *flt_group = new FltGroup(_flt_header); + flt_node->add_child(flt_group); + + flt_group->set_id(egg_group->get_name()); + + switch (egg_group->get_billboard_type()) { + // MultiGen represents billboarding at the polygon level, so we + // have to remember this flag for later. + case EggGroup::BT_axis: + billboard = FltGeometry::BT_axial; + break; + + case EggGroup::BT_point_world_relative: + billboard = FltGeometry::BT_point; + break; + + case EggGroup::BT_point_camera_relative: + // Not sure if this is the right flag for MultiGen. + billboard = FltGeometry::BT_fixed; + break; + + default: + break; + } + + if (egg_group->has_transform()) { + apply_transform(egg_group, flt_group); + } + + if (egg_group->get_switch_flag()) { + if (egg_group->get_switch_fps() != 0.0) { + // A sequence animation. + flt_group->_flags |= FltGroup::F_forward_animation; + egg_syntax + << " fps { " << egg_group->get_switch_fps() << " }\n"; + } else { + // Just a switch node. + egg_group->write_switch_flags(egg_syntax, 2); + } + } + + // Pick up any additional egg attributes that MultiGen doesn't + // support; these will get written to the comment field where + // flt2egg will find it. + egg_group->write_collide_flags(egg_syntax, 2); + egg_group->write_model_flags(egg_syntax, 2); + egg_group->write_object_types(egg_syntax, 2); + egg_group->write_decal_flags(egg_syntax, 2); + egg_group->write_tags(egg_syntax, 2); + egg_group->write_render_mode(egg_syntax, 2); + + apply_egg_syntax(egg_syntax.str(), flt_group); + + EggGroup::iterator ci; + for (ci = egg_group->begin(); ci != egg_group->end(); ++ci) { + traverse(*ci, flt_group, billboard); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: EggToFlt::apply_transform +// Access: Private +// Description: Applies the indicated egg transform to the indicated +// flt bead. +//////////////////////////////////////////////////////////////////// +void EggToFlt:: +apply_transform(EggTransform3d *egg_transform, FltBead *flt_node) { + flt_node->clear_transform(); + + bool components_ok = true; + int num_components = egg_transform->get_num_components(); + for (int i = num_components - 1; i >= 0 && components_ok; i--) { + switch (egg_transform->get_component_type(i)) { + case EggTransform3d::CT_translate: + { + FltTransformTranslate *translate = + new FltTransformTranslate(_flt_header); + translate->set(LPoint3d::zero(), egg_transform->get_component_vector(i)); + flt_node->add_transform_step(translate); + } + break; + + case EggTransform3d::CT_rotx: + { + FltTransformRotateAboutEdge *rotate = + new FltTransformRotateAboutEdge(_flt_header); + rotate->set(LPoint3d::zero(), LPoint3d(1.0, 0.0, 0.0), + egg_transform->get_component_number(i)); + flt_node->add_transform_step(rotate); + } + break; + + case EggTransform3d::CT_roty: + { + FltTransformRotateAboutEdge *rotate = + new FltTransformRotateAboutEdge(_flt_header); + rotate->set(LPoint3d::zero(), LPoint3d(0.0, 1.0, 0.0), + egg_transform->get_component_number(i)); + flt_node->add_transform_step(rotate); + } + break; + + case EggTransform3d::CT_rotz: + { + FltTransformRotateAboutEdge *rotate = + new FltTransformRotateAboutEdge(_flt_header); + rotate->set(LPoint3d::zero(), LPoint3d(0.0, 0.0, 1.0), + egg_transform->get_component_number(i)); + flt_node->add_transform_step(rotate); + } + break; + + case EggTransform3d::CT_rotate: + { + FltTransformRotateAboutEdge *rotate = + new FltTransformRotateAboutEdge(_flt_header); + rotate->set(LPoint3d::zero(), egg_transform->get_component_vector(i), + egg_transform->get_component_number(i)); + flt_node->add_transform_step(rotate); + } + break; + + case EggTransform3d::CT_scale: + { + FltTransformScale *scale = new FltTransformScale(_flt_header); + scale->set(LPoint3d::zero(), LCAST(float, egg_transform->get_component_vector(i))); + flt_node->add_transform_step(scale); + } + break; + + case EggTransform3d::CT_uniform_scale: + { + FltTransformScale *scale = new FltTransformScale(_flt_header); + float factor = (float)egg_transform->get_component_number(i); + scale->set(LPoint3d::zero(), LVecBase3f(factor, factor, factor)); + flt_node->add_transform_step(scale); + } + break; + + case EggTransform3d::CT_matrix: + { + FltTransformGeneralMatrix *matrix = + new FltTransformGeneralMatrix(_flt_header); + matrix->set_matrix(egg_transform->get_component_matrix(i)); + flt_node->add_transform_step(matrix); + } + break; + + default: + // Don't know how to convert this component. + components_ok = false; + } + } + + if (components_ok) { + // Verify that the transform was computed correctly. + if (!flt_node->get_transform().almost_equal(egg_transform->get_transform())) { + nout << "Incorrect transform! Expected:\n"; + egg_transform->get_transform().write(nout, 2); + nout << "Computed:\n"; + flt_node->get_transform().write(nout, 2); + nout << "\n"; + components_ok = false; + } + } + + if (!components_ok) { + // Just store the overall transform. + flt_node->set_transform(egg_transform->get_transform()); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: EggToFlt::apply_egg_syntax +// Access: Private +// Description: Adds the indicated sequence of egg syntax lines +// (presumably representing egg features not directly +// supported by MultiGen) to the flt record as a +// comment, so that flt2egg will reapply it to the egg +// groups. +//////////////////////////////////////////////////////////////////// +void EggToFlt:: +apply_egg_syntax(const string &egg_syntax, FltRecord *flt_record) { + if (!egg_syntax.empty()) { + ostringstream out; + out << " {\n" + << egg_syntax + << "}"; + flt_record->set_comment(out.str()); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: EggToFlt::get_flt_vertex +// Access: Private +// Description: Returns a FltVertex corresponding to the indicated +// EggVertex. If the vertex has not been seen before +// (in this particular vertex frame), creates a new one. +//////////////////////////////////////////////////////////////////// +FltVertex *EggToFlt:: +get_flt_vertex(EggVertex *egg_vertex, EggNode *context) { + const LMatrix4d *frame = context->get_vertex_to_node_ptr(); + VertexMap &vertex_map = _vertex_map_per_frame[frame]; + + VertexMap::iterator vi = vertex_map.find(egg_vertex); + if (vi != vertex_map.end()) { + return (*vi).second; + } + FltVertex *flt_vertex = new FltVertex(_flt_header); + flt_vertex->_pos = egg_vertex->get_pos3(); + + if (egg_vertex->has_color()) { + flt_vertex->set_color(egg_vertex->get_color()); + } + if (egg_vertex->has_normal()) { + flt_vertex->_normal = LCAST(float, egg_vertex->get_normal()); + flt_vertex->_has_normal = true; + } + if (egg_vertex->has_uv()) { + flt_vertex->_uv = LCAST(float, egg_vertex->get_uv()); + flt_vertex->_has_uv = true; + } + + if (frame != (const LMatrix4d *)NULL) { + flt_vertex->_pos = flt_vertex->_pos * (*frame); + flt_vertex->_normal = flt_vertex->_normal * LCAST(float, (*frame)); + } + + _flt_header->add_vertex(flt_vertex); + vertex_map[egg_vertex] = flt_vertex; + + return flt_vertex; +} + +//////////////////////////////////////////////////////////////////// +// Function: EggToFlt::get_flt_texture +// Access: Private +// Description: Returns a FltTexture corresponding to the indicated +// EggTexture. If the texture has not been seen before, +// creates a new one. +//////////////////////////////////////////////////////////////////// +FltTexture *EggToFlt:: +get_flt_texture(EggTexture *egg_texture) { + // We have to maintain this map based on the filename, not the egg + // pointer, because there may be multiple EggTextures with the same + // filename, and we have to collapse them together. + Filename filename = egg_texture->get_filename(); + TextureMap::iterator vi = _texture_map.find(filename); + if (vi != _texture_map.end()) { + return (*vi).second; + } + FltTexture *flt_texture = new FltTexture(_flt_header); + flt_texture->set_texture_filename(filename); + + switch (egg_texture->get_minfilter()) { + case EggTexture::FT_nearest: + flt_texture->_min_filter = FltTexture::MN_point; + break; + + case EggTexture::FT_linear: + flt_texture->_min_filter = FltTexture::MN_bilinear; + break; + + case EggTexture::FT_nearest_mipmap_nearest: + flt_texture->_min_filter = FltTexture::MN_mipmap_point; + break; + + case EggTexture::FT_nearest_mipmap_linear: + flt_texture->_min_filter = FltTexture::MN_mipmap_linear; + break; + + case EggTexture::FT_linear_mipmap_nearest: + flt_texture->_min_filter = FltTexture::MN_mipmap_bilinear; + break; + + case EggTexture::FT_linear_mipmap_linear: + flt_texture->_min_filter = FltTexture::MN_mipmap_trilinear; + break; + + default: + break; + } + + switch (egg_texture->get_magfilter()) { + case EggTexture::FT_nearest: + flt_texture->_mag_filter = FltTexture::MG_point; + break; + + case EggTexture::FT_linear: + flt_texture->_mag_filter = FltTexture::MG_bilinear; + break; + + default: + break; + } + + switch (egg_texture->get_wrap_mode()) { + case EggTexture::WM_repeat: + flt_texture->_repeat = FltTexture::RT_repeat; + break; + + case EggTexture::WM_clamp: + flt_texture->_repeat = FltTexture::RT_clamp; + break; + + default: + break; + } + + switch (egg_texture->get_wrap_u()) { + case EggTexture::WM_repeat: + flt_texture->_repeat_u = FltTexture::RT_repeat; + break; + + case EggTexture::WM_clamp: + flt_texture->_repeat_u = FltTexture::RT_clamp; + break; + + default: + break; + } + + switch (egg_texture->get_wrap_v()) { + case EggTexture::WM_repeat: + flt_texture->_repeat_v = FltTexture::RT_repeat; + break; + + case EggTexture::WM_clamp: + flt_texture->_repeat_v = FltTexture::RT_clamp; + break; + + default: + break; + } + + switch (egg_texture->get_env_type()) { + case EggTexture::ET_modulate: + flt_texture->_env_type = FltTexture::ET_modulate; + break; + + case EggTexture::ET_decal: + flt_texture->_env_type = FltTexture::ET_decal; + break; + + default: + break; + } + + switch (egg_texture->get_format()) { + case EggTexture::F_luminance_alpha: + case EggTexture::F_luminance_alphamask: + flt_texture->_internal_format = FltTexture::IF_ia_8; + break; + + case EggTexture::F_rgb5: + case EggTexture::F_rgb332: + flt_texture->_internal_format = FltTexture::IF_rgb_5; + break; + + case EggTexture::F_rgba4: + case EggTexture::F_rgba5: + flt_texture->_internal_format = FltTexture::IF_rgba_4; + break; + + case EggTexture::F_rgba8: + case EggTexture::F_rgba: + case EggTexture::F_rgbm: + case EggTexture::F_rgb: + case EggTexture::F_rgb8: + flt_texture->_internal_format = FltTexture::IF_rgba_8; + break; + + case EggTexture::F_rgba12: + flt_texture->_internal_format = FltTexture::IF_rgba_12; + break; + + case EggTexture::F_alpha: + flt_texture->_internal_format = FltTexture::IF_i_16; + flt_texture->_intensity_is_alpha = true; + break; + + case EggTexture::F_luminance: + flt_texture->_internal_format = FltTexture::IF_i_16; + break; + + case EggTexture::F_rgb12: + flt_texture->_internal_format = FltTexture::IF_rgb_12; + break; + + default: + break; + } + + _flt_header->add_texture(flt_texture); + _texture_map[filename] = flt_texture; + + return flt_texture; +} + + + +int main(int argc, char *argv[]) { + EggToFlt prog; + prog.parse_command_line(argc, argv); + prog.run(); + return 0; +} diff --git a/pandatool/src/fltprogs/eggToFlt.h b/pandatool/src/fltprogs/eggToFlt.h new file mode 100644 index 0000000000..e261bd56b6 --- /dev/null +++ b/pandatool/src/fltprogs/eggToFlt.h @@ -0,0 +1,77 @@ +// Filename: eggToFlt.h +// Created by: drose (01Oct03) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://www.panda3d.org/license.txt . +// +// To contact the maintainers of this program write to +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#ifndef EGGTOFLT_H +#define EGGTOFLT_H + +#include "pandatoolbase.h" + +#include "eggToSomething.h" +#include "fltHeader.h" +#include "fltGeometry.h" +#include "pointerTo.h" +#include "pmap.h" +#include "vector_string.h" + +class EggGroup; +class EggVertex; +class EggPrimitive; +class EggTexture; +class EggTransform3d; +class FltVertex; +class FltBead; +class FltTexture; + +//////////////////////////////////////////////////////////////////// +// Class : EggToFlt +// Description : A program to read an egg file and write a flt file. +//////////////////////////////////////////////////////////////////// +class EggToFlt : public EggToSomething { +public: + EggToFlt(); + + void run(); + +private: + static bool dispatch_attr(const string &opt, const string &arg, void *var); + + void traverse(EggNode *egg_node, FltBead *flt_node, + FltGeometry::BillboardType billboard); + void convert_primitive(EggPrimitive *egg_primitive, FltBead *flt_node, + FltGeometry::BillboardType billboard); + void convert_group(EggGroup *egg_group, FltBead *flt_node, + FltGeometry::BillboardType billboard); + void apply_transform(EggTransform3d *egg_transform, FltBead *flt_node); + void apply_egg_syntax(const string &egg_syntax, FltRecord *flt_record); + FltVertex *get_flt_vertex(EggVertex *egg_vertex, EggNode *context); + FltTexture *get_flt_texture(EggTexture *egg_texture); + + FltHeader::AttrUpdate _auto_attr_update; + + PT(FltHeader) _flt_header; + + typedef pmap VertexMap; + typedef pmap VertexMapPerFrame; + VertexMapPerFrame _vertex_map_per_frame; + + typedef pmap TextureMap; + TextureMap _texture_map; +}; + +#endif + diff --git a/pandatool/src/fltprogs/fltToEgg.cxx b/pandatool/src/fltprogs/fltToEgg.cxx index c014f3f5e8..6e69bac04e 100644 --- a/pandatool/src/fltprogs/fltToEgg.cxx +++ b/pandatool/src/fltprogs/fltToEgg.cxx @@ -18,8 +18,8 @@ #include "fltToEgg.h" -#include -#include +#include "fltToEggConverter.h" +#include "config_flt.h" //////////////////////////////////////////////////////////////////// // Function: FltToEgg::Constructor diff --git a/pandatool/src/fltprogs/fltToEgg.h b/pandatool/src/fltprogs/fltToEgg.h index 0763b833ca..aa28492096 100644 --- a/pandatool/src/fltprogs/fltToEgg.h +++ b/pandatool/src/fltprogs/fltToEgg.h @@ -15,16 +15,16 @@ // panda3d@yahoogroups.com . // //////////////////////////////////////////////////////////////////// - + #ifndef FLTTOEGG_H #define FLTTOEGG_H -#include +#include "pandatoolbase.h" -#include -#include +#include "somethingToEgg.h" +#include "fltToEggConverter.h" -#include +#include "dSearchPath.h" //////////////////////////////////////////////////////////////////// // Class : FltToEgg diff --git a/pandatool/src/progbase/Sources.pp b/pandatool/src/progbase/Sources.pp index c47a764361..f447117aeb 100644 --- a/pandatool/src/progbase/Sources.pp +++ b/pandatool/src/progbase/Sources.pp @@ -9,7 +9,8 @@ #define SOURCES \ programBase.I programBase.h \ - withOutputFile.h wordWrapStream.h wordWrapStreamBuf.I \ + withOutputFile.I withOutputFile.h \ + wordWrapStream.h wordWrapStreamBuf.I \ wordWrapStreamBuf.h #define INCLUDED_SOURCES \ @@ -18,7 +19,7 @@ #define INSTALL_HEADERS \ programBase.I programBase.h \ - withOutputFile.h \ + withOutputFile.I withOutputFile.h \ wordWrapStream.h wordWrapStreamBuf.I \ wordWrapStreamBuf.h diff --git a/pandatool/src/progbase/withOutputFile.I b/pandatool/src/progbase/withOutputFile.I new file mode 100644 index 0000000000..99817a74e3 --- /dev/null +++ b/pandatool/src/progbase/withOutputFile.I @@ -0,0 +1,29 @@ +// Filename: withOutputFile.I +// Created by: drose (01Oct03) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://www.panda3d.org/license.txt . +// +// To contact the maintainers of this program write to +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// Function: WithOutputFile::set_binary_output +// Access: Protected +// Description: Changes the flag specifying whether the output file +// is to be opened in binary mode or not. +//////////////////////////////////////////////////////////////////// +INLINE void WithOutputFile:: +set_binary_output(bool binary_output) { + _binary_output = binary_output; +} diff --git a/pandatool/src/progbase/withOutputFile.h b/pandatool/src/progbase/withOutputFile.h index 3b8d14eec3..53d3e5a6b9 100644 --- a/pandatool/src/progbase/withOutputFile.h +++ b/pandatool/src/progbase/withOutputFile.h @@ -45,6 +45,8 @@ public: Filename get_output_filename() const; protected: + INLINE void set_binary_output(bool binary_output); + bool check_last_arg(ProgramBase::Args &args, int minimum_args); bool verify_output_file_safe() const; @@ -61,6 +63,8 @@ private: ostream *_output_ptr; }; +#include "withOutputFile.I" + #endif