xFileMaterial.cxx 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. /**
  2. * PANDA 3D SOFTWARE
  3. * Copyright (c) Carnegie Mellon University. All rights reserved.
  4. *
  5. * All use of this software is subject to the terms of the revised BSD
  6. * license. You should have received a copy of this license along
  7. * with this source code in a file named "LICENSE."
  8. *
  9. * @file xFileMaterial.cxx
  10. * @author drose
  11. * @date 2001-06-19
  12. */
  13. #include "xFileMaterial.h"
  14. #include "xFileToEggConverter.h"
  15. #include "xFileDataNode.h"
  16. #include "eggMaterial.h"
  17. #include "eggTexture.h"
  18. #include "eggPrimitive.h"
  19. #include "datagram.h"
  20. #include "config_xfile.h"
  21. #include <string.h> // for strcmp, strdup
  22. /**
  23. *
  24. */
  25. XFileMaterial::
  26. XFileMaterial() {
  27. _face_color.set(1.0, 1.0, 1.0, 1.0);
  28. _specular_color.set(0.0, 0.0, 0.0);
  29. _emissive_color.set(0.0, 0.0, 0.0);
  30. _power = 64.0;
  31. _has_material = false;
  32. _has_texture = false;
  33. }
  34. /**
  35. *
  36. */
  37. XFileMaterial::
  38. ~XFileMaterial() {
  39. }
  40. /**
  41. * Sets the structure up from the indicated egg data.
  42. */
  43. void XFileMaterial::
  44. set_from_egg(EggPrimitive *egg_prim) {
  45. // First, determine the face color.
  46. if (egg_prim->has_color()) {
  47. _face_color = egg_prim->get_color();
  48. _has_material = true;
  49. }
  50. // Do we have an actual EggMaterial, to control lighting effects?
  51. if (egg_prim->has_material()) {
  52. _has_material = true;
  53. EggMaterial *egg_mat = egg_prim->get_material();
  54. if (egg_mat->has_diff()) {
  55. _face_color = egg_mat->get_diff();
  56. }
  57. if (egg_mat->has_spec()) {
  58. const LColor &spec = egg_mat->get_spec();
  59. _specular_color.set(spec[0], spec[1], spec[2]);
  60. }
  61. if (egg_mat->has_emit()) {
  62. const LColor &emit = egg_mat->get_emit();
  63. _emissive_color.set(emit[0], emit[1], emit[2]);
  64. }
  65. if (egg_mat->has_shininess()) {
  66. _power = egg_mat->get_shininess();
  67. }
  68. }
  69. // Finally, if we also have a texture, record that.
  70. if (egg_prim->has_texture()) {
  71. _has_material = true;
  72. _has_texture = true;
  73. EggTexture *egg_tex = egg_prim->get_texture();
  74. _texture = egg_tex->get_filename();
  75. }
  76. }
  77. /**
  78. * Applies the properties in the material to the indicated egg primitive.
  79. */
  80. void XFileMaterial::
  81. apply_to_egg(EggPrimitive *egg_prim, XFileToEggConverter *converter) {
  82. // Is there a texture?
  83. if (_has_texture) {
  84. Filename texture = converter->convert_model_path(_texture);
  85. EggTexture temp("", texture);
  86. EggTexture *egg_tex = converter->create_unique_texture(temp);
  87. egg_prim->set_texture(egg_tex);
  88. }
  89. // Are there any fancy lighting effects?
  90. bool got_spec = (_specular_color != LRGBColor::zero());
  91. bool got_emit = (_emissive_color != LRGBColor::zero());
  92. if (got_spec || got_emit) {
  93. EggMaterial temp("");
  94. temp.set_diff(_face_color);
  95. if (got_spec) {
  96. temp.set_shininess(_power);
  97. temp.set_spec(LColor(_specular_color[0], _specular_color[1],
  98. _specular_color[2], 1.0));
  99. }
  100. if (got_emit) {
  101. temp.set_emit(LColor(_emissive_color[0], _emissive_color[1],
  102. _emissive_color[2], 1.0));
  103. }
  104. EggMaterial *egg_mat = converter->create_unique_material(temp);
  105. egg_prim->set_material(egg_mat);
  106. }
  107. // Also apply the face color.
  108. egg_prim->set_color(_face_color);
  109. }
  110. /**
  111. *
  112. */
  113. int XFileMaterial::
  114. compare_to(const XFileMaterial &other) const {
  115. int ct;
  116. ct = _face_color.compare_to(other._face_color);
  117. if (ct == 0) {
  118. ct = (_power == other._power) ? 0 : ((_power < other._power) ? -1 : 1);
  119. }
  120. if (ct == 0) {
  121. ct = _specular_color.compare_to(other._specular_color);
  122. }
  123. if (ct == 0) {
  124. ct = _emissive_color.compare_to(other._emissive_color);
  125. }
  126. if (ct == 0) {
  127. ct = strcmp(_texture.c_str(), other._texture.c_str());
  128. }
  129. return ct;
  130. }
  131. /**
  132. * Returns true if this material represents something meaningful, or false if
  133. * the default material is sufficient.
  134. */
  135. bool XFileMaterial::
  136. has_material() const {
  137. return _has_material;
  138. }
  139. /**
  140. * Returns true if this material includes a texture map, false otherwise.
  141. */
  142. bool XFileMaterial::
  143. has_texture() const {
  144. return _has_texture;
  145. }
  146. /**
  147. * Creates a Material object for the material list.
  148. */
  149. XFileDataNode *XFileMaterial::
  150. make_x_material(XFileNode *x_meshMaterials, const std::string &suffix) {
  151. XFileDataNode *x_material =
  152. x_meshMaterials->add_Material("material" + suffix,
  153. _face_color, _power,
  154. _specular_color, _emissive_color);
  155. if (has_texture()) {
  156. x_material->add_TextureFilename("texture" + suffix, _texture);
  157. }
  158. return x_material;
  159. }
  160. /**
  161. * Fills the structure based on the raw data from the X file's Material
  162. * object.
  163. */
  164. bool XFileMaterial::
  165. fill_material(XFileDataNode *obj) {
  166. _face_color = LCAST(PN_stdfloat, (*obj)["faceColor"].vec4());
  167. _power = (*obj)["power"].d();
  168. _specular_color = LCAST(PN_stdfloat, (*obj)["specularColor"].vec3());
  169. _emissive_color = LCAST(PN_stdfloat, (*obj)["emissiveColor"].vec3());
  170. _has_material = true;
  171. // Walk through the children of the material. If there are any, there
  172. // should be only one, and it should be just a Texture.
  173. int num_objects = obj->get_num_objects();
  174. for (int i = 0; i < num_objects; i++) {
  175. XFileDataNode *child = obj->get_object(i);
  176. if (child->is_standard_object("TextureFilename")) {
  177. _texture = Filename::from_os_specific((*child)["filename"].s());
  178. _has_texture = true;
  179. } else {
  180. if (xfile_cat.is_debug()) {
  181. xfile_cat.debug()
  182. << "Ignoring material object of unknown type: "
  183. << child->get_template_name() << "\n";
  184. }
  185. }
  186. }
  187. return true;
  188. }