Panda3D

xFileMaterial.cxx

00001 // Filename: xFileMaterial.cxx
00002 // Created by:  drose (19Jun01)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #include "xFileMaterial.h"
00016 #include "xFileToEggConverter.h"
00017 #include "xFileDataNode.h"
00018 #include "eggMaterial.h"
00019 #include "eggTexture.h"
00020 #include "eggPrimitive.h"
00021 #include "datagram.h"
00022 
00023 #include <string.h>  // for strcmp, strdup
00024 
00025 ////////////////////////////////////////////////////////////////////
00026 //     Function: XFileMaterial::Constructor
00027 //       Access: Public
00028 //  Description:
00029 ////////////////////////////////////////////////////////////////////
00030 XFileMaterial::
00031 XFileMaterial() {
00032   _face_color.set(1.0, 1.0, 1.0, 1.0);
00033   _specular_color.set(0.0, 0.0, 0.0);
00034   _emissive_color.set(0.0, 0.0, 0.0);
00035   _power = 64.0;
00036 
00037   _has_material = false;
00038   _has_texture = false;
00039 }
00040 
00041 ////////////////////////////////////////////////////////////////////
00042 //     Function: XFileMaterial::Destructor
00043 //       Access: Public
00044 //  Description:
00045 ////////////////////////////////////////////////////////////////////
00046 XFileMaterial::
00047 ~XFileMaterial() {
00048 }
00049 
00050 ////////////////////////////////////////////////////////////////////
00051 //     Function: XFileMaterial::set_from_egg
00052 //       Access: Public
00053 //  Description: Sets the structure up from the indicated egg data.
00054 ////////////////////////////////////////////////////////////////////
00055 void XFileMaterial::
00056 set_from_egg(EggPrimitive *egg_prim) {
00057   // First, determine the face color.
00058   if (egg_prim->has_color()) {
00059     _face_color = egg_prim->get_color();
00060     _has_material = true;
00061   }
00062 
00063   // Do we have an actual EggMaterial, to control lighting effects?
00064   if (egg_prim->has_material()) {
00065     _has_material = true;
00066     EggMaterial *egg_mat = egg_prim->get_material();
00067     if (egg_mat->has_diff()) {
00068       _face_color = egg_mat->get_diff();
00069     }
00070     if (egg_mat->has_spec()) {
00071       const LColor &spec = egg_mat->get_spec();
00072       _specular_color.set(spec[0], spec[1], spec[2]);
00073     }
00074     if (egg_mat->has_emit()) {
00075       const LColor &emit = egg_mat->get_emit();
00076       _emissive_color.set(emit[0], emit[1], emit[2]);
00077     }
00078     if (egg_mat->has_shininess()) {
00079       _power = egg_mat->get_shininess();
00080     }
00081   }
00082 
00083   // Finally, if we also have a texture, record that.
00084   if (egg_prim->has_texture()) {
00085     _has_material = true;
00086     _has_texture = true;
00087     EggTexture *egg_tex = egg_prim->get_texture();
00088     _texture = egg_tex->get_filename();
00089   }
00090 }
00091 
00092 ////////////////////////////////////////////////////////////////////
00093 //     Function: XFileMaterial::apply_to_egg
00094 //       Access: Public
00095 //  Description: Applies the properties in the material to the
00096 //               indicated egg primitive.
00097 ////////////////////////////////////////////////////////////////////
00098 void XFileMaterial::
00099 apply_to_egg(EggPrimitive *egg_prim, XFileToEggConverter *converter) {
00100   // Is there a texture?
00101   if (_has_texture) {
00102     Filename texture = converter->convert_model_path(_texture);
00103     EggTexture temp("", texture);
00104     EggTexture *egg_tex = converter->create_unique_texture(temp);
00105     egg_prim->set_texture(egg_tex);
00106   }
00107 
00108   // Are there any fancy lighting effects?
00109   bool got_spec = (_specular_color != LRGBColor::zero());
00110   bool got_emit = (_emissive_color != LRGBColor::zero());
00111   if (got_spec || got_emit) {
00112     EggMaterial temp("");
00113     temp.set_diff(_face_color);
00114     if (got_spec) {
00115       temp.set_shininess(_power);
00116       temp.set_spec(LColor(_specular_color[0], _specular_color[1],
00117                            _specular_color[2], 1.0));
00118     }
00119     if (got_emit) {
00120       temp.set_emit(LColor(_emissive_color[0], _emissive_color[1],
00121                            _emissive_color[2], 1.0));
00122     }
00123     EggMaterial *egg_mat = converter->create_unique_material(temp);
00124     egg_prim->set_material(egg_mat);
00125   }
00126 
00127   // Also apply the face color.
00128   egg_prim->set_color(_face_color);
00129 }
00130 
00131 ////////////////////////////////////////////////////////////////////
00132 //     Function: XFileMaterial::compare_to
00133 //       Access: Public
00134 //  Description:
00135 ////////////////////////////////////////////////////////////////////
00136 int XFileMaterial::
00137 compare_to(const XFileMaterial &other) const {
00138   int ct;
00139   ct = _face_color.compare_to(other._face_color);
00140   if (ct == 0) {
00141     ct = (_power == other._power) ? 0 : ((_power < other._power) ? -1 : 1);
00142   }
00143   if (ct == 0) {
00144     ct = _specular_color.compare_to(other._specular_color);
00145   }
00146   if (ct == 0) {
00147     ct = _emissive_color.compare_to(other._emissive_color);
00148   }
00149   if (ct == 0) {
00150     ct = strcmp(_texture.c_str(), other._texture.c_str());
00151   }
00152   return ct;
00153 }
00154 
00155 ////////////////////////////////////////////////////////////////////
00156 //     Function: XFileMaterial::has_material
00157 //       Access: Public
00158 //  Description: Returns true if this material represents something
00159 //               meaningful, or false if the default material is
00160 //               sufficient.
00161 ////////////////////////////////////////////////////////////////////
00162 bool XFileMaterial::
00163 has_material() const {
00164   return _has_material;
00165 }
00166 
00167 ////////////////////////////////////////////////////////////////////
00168 //     Function: XFileMaterial::has_texture
00169 //       Access: Public
00170 //  Description: Returns true if this material includes a texture map,
00171 //               false otherwise.
00172 ////////////////////////////////////////////////////////////////////
00173 bool XFileMaterial::
00174 has_texture() const {
00175   return _has_texture;
00176 }
00177 
00178 ////////////////////////////////////////////////////////////////////
00179 //     Function: XFileMaterial::make_x_material
00180 //       Access: Public
00181 //  Description: Creates a Material object for the material list.
00182 ////////////////////////////////////////////////////////////////////
00183 XFileDataNode *XFileMaterial::
00184 make_x_material(XFileNode *x_meshMaterials, const string &suffix) {
00185   XFileDataNode *x_material = 
00186     x_meshMaterials->add_Material("material" + suffix,
00187                                   _face_color, _power,
00188                                   _specular_color, _emissive_color);
00189 
00190   if (has_texture()) {
00191     x_material->add_TextureFilename("texture" + suffix, _texture);
00192   }
00193 
00194   return x_material;
00195 }
00196 
00197 ////////////////////////////////////////////////////////////////////
00198 //     Function: XFileMaterial::fill_material
00199 //       Access: Public
00200 //  Description: Fills the structure based on the raw data from the
00201 //               X file's Material object.
00202 ////////////////////////////////////////////////////////////////////
00203 bool XFileMaterial::
00204 fill_material(XFileDataNode *obj) {
00205   _face_color = LCAST(PN_stdfloat, (*obj)["faceColor"].vec4());
00206   _power = (*obj)["power"].d();
00207   _specular_color = LCAST(PN_stdfloat, (*obj)["specularColor"].vec3());
00208   _emissive_color = LCAST(PN_stdfloat, (*obj)["emissiveColor"].vec3());
00209   _has_material = true;
00210 
00211   // Walk through the children of the material.  If there are any,
00212   // there should be only one, and it should be just a Texture.
00213   int num_objects = obj->get_num_objects();
00214   for (int i = 0; i < num_objects; i++) {
00215     XFileDataNode *child = obj->get_object(i);
00216     if (child->is_standard_object("TextureFilename")) {
00217       _texture = Filename::from_os_specific((*child)["filename"].s());
00218       _has_texture = true;
00219 
00220     } else {
00221       if (xfile_cat.is_debug()) {
00222         xfile_cat.debug()
00223           << "Ignoring material object of unknown type: "
00224           << child->get_template_name() << "\n";
00225       }
00226     }
00227   }
00228 
00229   return true;
00230 }
 All Classes Functions Variables Enumerations