Panda3D
|
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 }