EG/pandatool/src/xfileegg/xFileMaterial.cxx

210 lines
5.4 KiB
C++

/**
* 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."
*
* @file xFileMaterial.cxx
* @author drose
* @date 2001-06-19
*/
#include "xFileMaterial.h"
#include "xFileToEggConverter.h"
#include "xFileDataNode.h"
#include "eggMaterial.h"
#include "eggTexture.h"
#include "eggPrimitive.h"
#include "datagram.h"
#include "config_xfile.h"
#include <string.h> // for strcmp, strdup
/**
*
*/
XFileMaterial::
XFileMaterial() {
_face_color.set(1.0, 1.0, 1.0, 1.0);
_specular_color.set(0.0, 0.0, 0.0);
_emissive_color.set(0.0, 0.0, 0.0);
_power = 64.0;
_has_material = false;
_has_texture = false;
}
/**
*
*/
XFileMaterial::
~XFileMaterial() {
}
/**
* Sets the structure up from the indicated egg data.
*/
void XFileMaterial::
set_from_egg(EggPrimitive *egg_prim) {
// First, determine the face color.
if (egg_prim->has_color()) {
_face_color = egg_prim->get_color();
_has_material = true;
}
// Do we have an actual EggMaterial, to control lighting effects?
if (egg_prim->has_material()) {
_has_material = true;
EggMaterial *egg_mat = egg_prim->get_material();
if (egg_mat->has_diff()) {
_face_color = egg_mat->get_diff();
}
if (egg_mat->has_spec()) {
const LColor &spec = egg_mat->get_spec();
_specular_color.set(spec[0], spec[1], spec[2]);
}
if (egg_mat->has_emit()) {
const LColor &emit = egg_mat->get_emit();
_emissive_color.set(emit[0], emit[1], emit[2]);
}
if (egg_mat->has_shininess()) {
_power = egg_mat->get_shininess();
}
}
// Finally, if we also have a texture, record that.
if (egg_prim->has_texture()) {
_has_material = true;
_has_texture = true;
EggTexture *egg_tex = egg_prim->get_texture();
_texture = egg_tex->get_filename();
}
}
/**
* Applies the properties in the material to the indicated egg primitive.
*/
void XFileMaterial::
apply_to_egg(EggPrimitive *egg_prim, XFileToEggConverter *converter) {
// Is there a texture?
if (_has_texture) {
Filename texture = converter->convert_model_path(_texture);
EggTexture temp("", texture);
EggTexture *egg_tex = converter->create_unique_texture(temp);
egg_prim->set_texture(egg_tex);
}
// Are there any fancy lighting effects?
bool got_spec = (_specular_color != LRGBColor::zero());
bool got_emit = (_emissive_color != LRGBColor::zero());
if (got_spec || got_emit) {
EggMaterial temp("");
temp.set_diff(_face_color);
if (got_spec) {
temp.set_shininess(_power);
temp.set_spec(LColor(_specular_color[0], _specular_color[1],
_specular_color[2], 1.0));
}
if (got_emit) {
temp.set_emit(LColor(_emissive_color[0], _emissive_color[1],
_emissive_color[2], 1.0));
}
EggMaterial *egg_mat = converter->create_unique_material(temp);
egg_prim->set_material(egg_mat);
}
// Also apply the face color.
egg_prim->set_color(_face_color);
}
/**
*
*/
int XFileMaterial::
compare_to(const XFileMaterial &other) const {
int ct;
ct = _face_color.compare_to(other._face_color);
if (ct == 0) {
ct = (_power == other._power) ? 0 : ((_power < other._power) ? -1 : 1);
}
if (ct == 0) {
ct = _specular_color.compare_to(other._specular_color);
}
if (ct == 0) {
ct = _emissive_color.compare_to(other._emissive_color);
}
if (ct == 0) {
ct = strcmp(_texture.c_str(), other._texture.c_str());
}
return ct;
}
/**
* Returns true if this material represents something meaningful, or false if
* the default material is sufficient.
*/
bool XFileMaterial::
has_material() const {
return _has_material;
}
/**
* Returns true if this material includes a texture map, false otherwise.
*/
bool XFileMaterial::
has_texture() const {
return _has_texture;
}
/**
* Creates a Material object for the material list.
*/
XFileDataNode *XFileMaterial::
make_x_material(XFileNode *x_meshMaterials, const std::string &suffix) {
XFileDataNode *x_material =
x_meshMaterials->add_Material("material" + suffix,
_face_color, _power,
_specular_color, _emissive_color);
if (has_texture()) {
x_material->add_TextureFilename("texture" + suffix, _texture);
}
return x_material;
}
/**
* Fills the structure based on the raw data from the X file's Material
* object.
*/
bool XFileMaterial::
fill_material(XFileDataNode *obj) {
_face_color = LCAST(PN_stdfloat, (*obj)["faceColor"].vec4());
_power = (*obj)["power"].d();
_specular_color = LCAST(PN_stdfloat, (*obj)["specularColor"].vec3());
_emissive_color = LCAST(PN_stdfloat, (*obj)["emissiveColor"].vec3());
_has_material = true;
// Walk through the children of the material. If there are any, there
// should be only one, and it should be just a Texture.
int num_objects = obj->get_num_objects();
for (int i = 0; i < num_objects; i++) {
XFileDataNode *child = obj->get_object(i);
if (child->is_standard_object("TextureFilename")) {
_texture = Filename::from_os_specific((*child)["filename"].s());
_has_texture = true;
} else {
if (xfile_cat.is_debug()) {
xfile_cat.debug()
<< "Ignoring material object of unknown type: "
<< child->get_template_name() << "\n";
}
}
}
return true;
}