Panda3D

colladaInput.cxx

00001 // Filename: colladaInput.cxx
00002 // Created by:  rdb (23May11)
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 "colladaInput.h"
00016 #include "string_utils.h"
00017 #include "geomVertexArrayFormat.h"
00018 #include "geomVertexWriter.h"
00019 
00020 // Collada DOM includes.  No other includes beyond this point.
00021 #include "pre_collada_include.h"
00022 #include <dom/domAccessor.h>
00023 #include <dom/domP.h>
00024 #include <dom/domSource.h>
00025 #include <dom/domVertices.h>
00026 
00027 #if PANDA_COLLADA_VERSION >= 15
00028 #include <dom/domInput_local_offset.h>
00029 #include <dom/domInput_local.h>
00030 #else
00031 #include <dom/domInputLocalOffset.h>
00032 #include <dom/domInputLocal.h>
00033 #define domList_of_floats domListOfFloats
00034 #define domList_of_uints domListOfUInts
00035 #endif
00036 
00037 ////////////////////////////////////////////////////////////////////
00038 //     Function: ColladaInput::Constructor
00039 //  Description: Pretty obvious what this does.
00040 ////////////////////////////////////////////////////////////////////
00041 ColladaInput::
00042 ColladaInput(const string &semantic) :
00043   _column_name (NULL),
00044   _semantic (semantic),
00045   _offset (0),
00046   _have_set (false),
00047   _set (0) {
00048 
00049   if (semantic == "POSITION") {
00050     _column_name = InternalName::get_vertex();
00051     _column_contents = GeomEnums::C_point;
00052   } else if (semantic == "COLOR") {
00053     _column_name = InternalName::get_color();
00054     _column_contents = GeomEnums::C_color;
00055   } else if (semantic == "NORMAL") {
00056     _column_name = InternalName::get_normal();
00057     _column_contents = GeomEnums::C_vector;
00058   } else if (semantic == "TEXCOORD") {
00059     _column_name = InternalName::get_texcoord();
00060     _column_contents = GeomEnums::C_texcoord;
00061   } else if (semantic == "TEXBINORMAL") {
00062     _column_name = InternalName::get_binormal();
00063     _column_contents = GeomEnums::C_vector;
00064   } else if (semantic == "TEXTANGENT") {
00065     _column_name = InternalName::get_tangent();
00066     _column_contents = GeomEnums::C_vector;
00067   }
00068 }
00069 
00070 ////////////////////////////////////////////////////////////////////
00071 //     Function: ColladaInput::Constructor
00072 //  Description: Pretty obvious what this does.
00073 ////////////////////////////////////////////////////////////////////
00074 ColladaInput::
00075 ColladaInput(const string &semantic, unsigned int set) :
00076   _column_name (NULL),
00077   _semantic (semantic),
00078   _offset (0),
00079   _have_set (true),
00080   _set (set) {
00081 
00082   ostringstream setstr;
00083   setstr << _set;
00084 
00085   if (semantic == "POSITION") {
00086     _column_name = InternalName::get_vertex();
00087     _column_contents = GeomEnums::C_point;
00088   } else if (semantic == "COLOR") {
00089     _column_name = InternalName::get_color();
00090     _column_contents = GeomEnums::C_color;
00091   } else if (semantic == "NORMAL") {
00092     _column_name = InternalName::get_normal();
00093     _column_contents = GeomEnums::C_vector;
00094   } else if (semantic == "TEXCOORD") {
00095     _column_name = InternalName::get_texcoord_name(setstr.str());
00096     _column_contents = GeomEnums::C_texcoord;
00097   } else if (semantic == "TEXBINORMAL") {
00098     _column_name = InternalName::get_binormal_name(setstr.str());
00099     _column_contents = GeomEnums::C_vector;
00100   } else if (semantic == "TEXTANGENT") {
00101     _column_name = InternalName::get_tangent_name(setstr.str());
00102     _column_contents = GeomEnums::C_vector;
00103   }
00104 }
00105 
00106 ////////////////////////////////////////////////////////////////////
00107 //     Function: ColladaInput::from_dom
00108 //  Description: Returns the ColladaInput object that represents
00109 //               the provided DOM input element.
00110 ////////////////////////////////////////////////////////////////////
00111 ColladaInput *ColladaInput::
00112 from_dom(domInput_local_offset &input) {
00113   // If we already loaded it before, use that.
00114   if (input.getUserData() != NULL) {
00115     return (ColladaInput *) input.getUserData();
00116   }
00117 
00118   ColladaInput *new_input = new ColladaInput(input.getSemantic(), input.getSet());
00119   new_input->_offset = input.getOffset();
00120 
00121   // If this has the VERTEX semantic, it points to a <vertices> element.
00122   if (new_input->is_vertex_source()) {
00123     domVertices *verts = daeSafeCast<domVertices> (input.getSource().getElement());
00124     nassertr(verts != NULL, NULL);
00125     daeTArray<domInput_localRef> &inputs = verts->getInput_array();
00126 
00127     // Iterate over the <input> elements in <vertices>.
00128     for (size_t i = 0; i < inputs.getCount(); ++i) {
00129       PT(ColladaInput) vtx_input = ColladaInput::from_dom(*inputs[i]);
00130       new_input->_vertex_inputs.push_back(vtx_input);
00131     }
00132   } else {
00133     domSource *source = daeSafeCast<domSource> (input.getSource().getElement());
00134     nassertr(source != NULL, NULL);
00135     new_input->read_data(*source);
00136   }
00137 
00138   return new_input;
00139 }
00140 
00141 ////////////////////////////////////////////////////////////////////
00142 //     Function: ColladaInput::from_dom
00143 //  Description: Returns the ColladaInput object that represents
00144 //               the provided DOM input element.
00145 ////////////////////////////////////////////////////////////////////
00146 ColladaInput *ColladaInput::
00147 from_dom(domInput_local &input) {
00148   // If we already loaded it before, use that.
00149   if (input.getUserData() != NULL) {
00150     return (ColladaInput *) input.getUserData();
00151   }
00152 
00153   ColladaInput *new_input = new ColladaInput(input.getSemantic());
00154   new_input->_offset = 0;
00155 
00156   nassertr (!new_input->is_vertex_source(), NULL);
00157 
00158   domSource *source = daeSafeCast<domSource> (input.getSource().getElement());
00159   nassertr(source != NULL, NULL);
00160   new_input->read_data(*source);
00161 
00162   return new_input;
00163 }
00164 
00165 ////////////////////////////////////////////////////////////////////
00166 //     Function: ColladaInput::make_vertex_columns
00167 //  Description: Takes a semantic and source URI, and adds a new
00168 //               column to the format.  If this is a vertex source,
00169 //               adds all of the inputs from the corresponding
00170 //               <vertices> element.  Returns the number of
00171 //               columns added to the format.
00172 ////////////////////////////////////////////////////////////////////
00173 int ColladaInput::
00174 make_vertex_columns(GeomVertexArrayFormat *format) const {
00175 
00176   if (is_vertex_source()) {
00177     int counter = 0;
00178     Inputs::const_iterator it;
00179     for (it = _vertex_inputs.begin(); it != _vertex_inputs.end(); ++it) {
00180       counter += (*it)->make_vertex_columns(format);
00181     }
00182     return counter;
00183   }
00184 
00185   nassertr(_column_name != NULL, 0);
00186 
00187   format->add_column(_column_name, _num_bound_params, GeomEnums::NT_stdfloat, _column_contents);
00188   return 1;
00189 }
00190 
00191 ////////////////////////////////////////////////////////////////////
00192 //     Function: ColladaInput::read_data
00193 //  Description: Reads the data from the source and fills in _data.
00194 ////////////////////////////////////////////////////////////////////
00195 bool ColladaInput::
00196 read_data(domSource &source) {
00197   _data.clear();
00198 
00199   // Get this, get that
00200   domFloat_array* float_array = source.getFloat_array();
00201   if (float_array == NULL) {
00202     return false;
00203   }
00204 
00205   domList_of_floats &floats = float_array->getValue();
00206   domAccessor &accessor = *source.getTechnique_common()->getAccessor();
00207   domParam_Array &params = accessor.getParam_array();
00208 
00209   // Count the number of params that have a name attribute.
00210   _num_bound_params = 0;
00211   for (size_t p = 0; p < params.getCount(); ++p) {
00212     if (params[p]->getName()) {
00213       ++_num_bound_params;
00214     }
00215   }
00216 
00217   _data.reserve(accessor.getCount());
00218 
00219   domUint pos = accessor.getOffset();
00220   for (domUint a = 0; a < accessor.getCount(); ++a) {
00221     domUint c = 0;
00222     // Yes, the last component defaults to 1 to work around a
00223     // perspective divide that Panda3D does internally for points.
00224     LVecBase4f v (0, 0, 0, 1);
00225     for (domUint p = 0; p < params.getCount(); ++p) {
00226       if (params[c]->getName()) {
00227         v[c++] = floats[pos + p];
00228       }
00229     }
00230     _data.push_back(v);
00231     pos += accessor.getStride();
00232   }
00233 
00234   return true;
00235 }
00236 
00237 ////////////////////////////////////////////////////////////////////
00238 //     Function: ColladaInput::write_data
00239 //  Description: Writes data to the indicated GeomVertexData using
00240 //               the given indices.
00241 ////////////////////////////////////////////////////////////////////
00242 void ColladaInput::
00243 write_data(GeomVertexData *vdata, int start_row, domP &p, unsigned int stride) const {
00244   if (is_vertex_source()) {
00245     Inputs::const_iterator it;
00246     for (it = _vertex_inputs.begin(); it != _vertex_inputs.end(); ++it) {
00247       (*it)->write_data(vdata, start_row, p, stride, _offset);
00248     }
00249 
00250   } else {
00251     write_data(vdata, start_row, p, stride, _offset);
00252   }
00253 }
00254 
00255 ////////////////////////////////////////////////////////////////////
00256 //     Function: ColladaInput::write_data
00257 //  Description: Called internally by the other write_data.
00258 ////////////////////////////////////////////////////////////////////
00259 void ColladaInput::
00260 write_data(GeomVertexData *vdata, int start_row, domP &p, unsigned int stride, unsigned int offset) const {
00261   nassertv(_column_name != NULL);
00262   GeomVertexWriter writer (vdata, _column_name);
00263   writer.set_row_unsafe(start_row);
00264 
00265   domList_of_uints &indices = p.getValue();
00266 
00267   // Allocate space for all the rows we're going to write.
00268   int min_length = start_row + indices.getCount() / stride;
00269   if (vdata->get_num_rows() < min_length) {
00270     vdata->unclean_set_num_rows(start_row);
00271   }
00272 
00273   for (size_t i = 0; i < indices.getCount(); i += stride) {
00274     size_t index = indices[i + offset];
00275     writer.add_data4f(_data[index]);
00276   }
00277 }
 All Classes Functions Variables Enumerations