210 lines
5.4 KiB
C++
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;
|
|
}
|