|
@@ -24,27 +24,19 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
|
OTHER DEALINGS IN THE SOFTWARE.
|
|
OTHER DEALINGS IN THE SOFTWARE.
|
|
|
*/
|
|
*/
|
|
|
|
|
|
|
|
-#include <iostream>
|
|
|
|
|
-#include <sstream>
|
|
|
|
|
-#include <fstream>
|
|
|
|
|
#include "MeshCompiler.h"
|
|
#include "MeshCompiler.h"
|
|
|
#include "DynamicString.h"
|
|
#include "DynamicString.h"
|
|
|
#include "TempAllocator.h"
|
|
#include "TempAllocator.h"
|
|
|
#include "Filesystem.h"
|
|
#include "Filesystem.h"
|
|
|
-
|
|
|
|
|
-using tinyxml2::XMLDocument;
|
|
|
|
|
-using tinyxml2::XMLElement;
|
|
|
|
|
-using tinyxml2::XML_NO_ERROR;
|
|
|
|
|
-using tinyxml2::XML_NO_ATTRIBUTE;
|
|
|
|
|
-using std::vector;
|
|
|
|
|
-using std::cout;
|
|
|
|
|
-using std::endl;
|
|
|
|
|
|
|
+#include "JSONParser.h"
|
|
|
|
|
+#include "Log.h"
|
|
|
|
|
|
|
|
namespace crown
|
|
namespace crown
|
|
|
{
|
|
{
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//-----------------------------------------------------------------------------
|
|
|
MeshCompiler::MeshCompiler()
|
|
MeshCompiler::MeshCompiler()
|
|
|
|
|
+ : m_vertices(default_allocator()), m_indices(default_allocator())
|
|
|
{
|
|
{
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -56,583 +48,152 @@ MeshCompiler::~MeshCompiler()
|
|
|
//-----------------------------------------------------------------------------
|
|
//-----------------------------------------------------------------------------
|
|
|
size_t MeshCompiler::compile_impl(Filesystem& fs, const char* resource_path)
|
|
size_t MeshCompiler::compile_impl(Filesystem& fs, const char* resource_path)
|
|
|
{
|
|
{
|
|
|
- DAEModel model;
|
|
|
|
|
|
|
+ File* file = fs.open(resource_path, FOM_READ);
|
|
|
|
|
+ char* buf = (char*)default_allocator().allocate(file->size());
|
|
|
|
|
+ file->read(buf, file->size());
|
|
|
|
|
|
|
|
- TempAllocator256 temp;
|
|
|
|
|
- DynamicString path(temp);
|
|
|
|
|
- fs.get_absolute_path(resource_path, path);
|
|
|
|
|
- if (!parse_collada(path.c_str(), model))
|
|
|
|
|
- {
|
|
|
|
|
- return 0;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ JSONParser json(buf);
|
|
|
|
|
+ JSONElement root = json.root();
|
|
|
|
|
|
|
|
- // Check that polylist is composed of triangles
|
|
|
|
|
- const vector<uint32_t>& vcount = model.geometries[0].mesh.polylist.vcount;
|
|
|
|
|
- for (uint32_t i = 0; i < vcount.size(); i++)
|
|
|
|
|
- {
|
|
|
|
|
- if (vcount[i] != 3)
|
|
|
|
|
- {
|
|
|
|
|
- cout << "Bad polylist: only triangle primitives allowed." << endl;
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ // Read data arrays
|
|
|
|
|
+ JSONElement position = root.key_or_nil("position");
|
|
|
|
|
+ JSONElement normal = root.key_or_nil("normal");
|
|
|
|
|
+ JSONElement texcoord = root.key_or_nil("texcoord");
|
|
|
|
|
|
|
|
- // Find vertices
|
|
|
|
|
- DAESource vertex_source;
|
|
|
|
|
- if (!find_vertices(model.geometries[0].mesh, vertex_source))
|
|
|
|
|
- {
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ m_has_normal = false;
|
|
|
|
|
+ m_has_texcoord = false;
|
|
|
|
|
|
|
|
- const vector<float>& vertex_vertices = vertex_source.float_array.array;
|
|
|
|
|
- m_vertex_vertices = vertex_vertices;
|
|
|
|
|
-
|
|
|
|
|
- vector<uint16_t> vertex_indices;
|
|
|
|
|
- if (!extract_vertex_indices(model.geometries[0].mesh, vertex_indices))
|
|
|
|
|
|
|
+ if (position.is_nil())
|
|
|
{
|
|
{
|
|
|
- return false;
|
|
|
|
|
|
|
+ Log::e("Bad mesh: array 'position' not found.");
|
|
|
|
|
+ return 0;
|
|
|
}
|
|
}
|
|
|
|
|
+ List<float> position_array(default_allocator());
|
|
|
|
|
+ position.array_value(position_array);
|
|
|
|
|
|
|
|
- m_vertex_indices = vertex_indices;
|
|
|
|
|
|
|
|
|
|
- // cout << "Vertices: " << vertex_vertices.size() << endl;
|
|
|
|
|
- // cout << "Indices: " << vertex_indices.size() << endl;
|
|
|
|
|
-
|
|
|
|
|
- m_mesh_header.version = MESH_VERSION;
|
|
|
|
|
- m_mesh_header.mesh_count = 1;
|
|
|
|
|
- m_mesh_header.joint_count = 0;
|
|
|
|
|
- //m_mesh_header.padding[0] = 0xCECECECE;
|
|
|
|
|
-
|
|
|
|
|
- return sizeof(MeshHeader) +
|
|
|
|
|
- sizeof(uint32_t) + vertex_vertices.size() * sizeof(float) +
|
|
|
|
|
- sizeof(uint32_t) + vertex_indices.size() * sizeof(uint16_t);
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
|
|
-void MeshCompiler::write_impl(File* out_file)
|
|
|
|
|
-{
|
|
|
|
|
- out_file->write((char*) &m_mesh_header, sizeof(MeshHeader));
|
|
|
|
|
-
|
|
|
|
|
- uint32_t vertex_count = m_vertex_vertices.size();
|
|
|
|
|
- out_file->write((char*)&vertex_count, sizeof(uint32_t));
|
|
|
|
|
- out_file->write((char*) m_vertex_vertices.data(), m_vertex_vertices.size() * sizeof(float));
|
|
|
|
|
-
|
|
|
|
|
- uint32_t triangle_count = m_vertex_indices.size();
|
|
|
|
|
- out_file->write((char*)&triangle_count, sizeof(uint32_t));
|
|
|
|
|
- out_file->write((char*) m_vertex_indices.data(), m_vertex_indices.size() * sizeof(uint16_t));
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
|
|
-bool MeshCompiler::parse_collada(const char* path, DAEModel& m)
|
|
|
|
|
-{
|
|
|
|
|
- XMLDocument doc;
|
|
|
|
|
-
|
|
|
|
|
- if (doc.LoadFile(path) != XML_NO_ERROR)
|
|
|
|
|
|
|
+ List<float> normal_array(default_allocator());
|
|
|
|
|
+ if (!normal.is_nil())
|
|
|
{
|
|
{
|
|
|
- cout << "Unable to open '" << path << "'." << endl;
|
|
|
|
|
- return false;
|
|
|
|
|
|
|
+ m_has_normal = true;
|
|
|
|
|
+ normal.array_value(normal_array);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // Read root
|
|
|
|
|
- XMLElement* root_node = doc.FirstChildElement("COLLADA");
|
|
|
|
|
- if (root_node == NULL)
|
|
|
|
|
|
|
+ List<float> texcoord_array(default_allocator());
|
|
|
|
|
+ if (!texcoord.is_nil())
|
|
|
{
|
|
{
|
|
|
- cout << "Bad document: missing COLLADA root element." << endl;
|
|
|
|
|
- return false;
|
|
|
|
|
|
|
+ m_has_texcoord = true;
|
|
|
|
|
+ texcoord.array_value(texcoord_array);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // Read geometries
|
|
|
|
|
- XMLElement* library_geometries = root_node->FirstChildElement("library_geometries");
|
|
|
|
|
- if (library_geometries == NULL)
|
|
|
|
|
|
|
+ // Read index arrays
|
|
|
|
|
+ JSONElement index = root.key_or_nil("index");
|
|
|
|
|
+ if (index.is_nil())
|
|
|
{
|
|
{
|
|
|
- cout << "Bad document: missing geometries library." << endl;
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- XMLElement* geometry = library_geometries->FirstChildElement("geometry");
|
|
|
|
|
- if (geometry == NULL)
|
|
|
|
|
- {
|
|
|
|
|
- cout << "Bad document: no geometries found." << endl;
|
|
|
|
|
- return false;
|
|
|
|
|
|
|
+ Log::e("Bad mesh: array 'index' not found.");
|
|
|
|
|
+ return 0;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- for (; geometry != NULL; geometry = geometry->NextSiblingElement("geometry"))
|
|
|
|
|
- {
|
|
|
|
|
- DAEGeometry g;
|
|
|
|
|
- if (parse_geometry(geometry, g))
|
|
|
|
|
- {
|
|
|
|
|
- m.geometries.push_back(g);
|
|
|
|
|
- }
|
|
|
|
|
- else
|
|
|
|
|
- {
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ List<uint16_t> position_index(default_allocator());
|
|
|
|
|
+ List<uint16_t> normal_index(default_allocator());
|
|
|
|
|
+ List<uint16_t> texcoord_index(default_allocator());
|
|
|
|
|
|
|
|
- return true;
|
|
|
|
|
-}
|
|
|
|
|
|
|
+ index[0].array_value(position_index);
|
|
|
|
|
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
|
|
-bool MeshCompiler::parse_geometry(XMLElement* geometry, DAEGeometry& g)
|
|
|
|
|
-{
|
|
|
|
|
- // Read geometry id
|
|
|
|
|
- const char* geom_id = geometry->Attribute("id");
|
|
|
|
|
- if (geom_id == NULL)
|
|
|
|
|
|
|
+ if (m_has_normal)
|
|
|
{
|
|
{
|
|
|
- cout << "Bad geometry: missing 'id' attribute." << endl;
|
|
|
|
|
- return false;
|
|
|
|
|
|
|
+ index[1].array_value(normal_index);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- g.id = geom_id;
|
|
|
|
|
-
|
|
|
|
|
- // Read geometry name
|
|
|
|
|
- const char* geom_name = geometry->Attribute("name");
|
|
|
|
|
- if (geom_name == NULL)
|
|
|
|
|
|
|
+ if (m_has_texcoord)
|
|
|
{
|
|
{
|
|
|
- cout << "Bad geometry: missing 'name' attribute." << endl;
|
|
|
|
|
- return false;
|
|
|
|
|
|
|
+ index[2].array_value(texcoord_index);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- g.name = geom_name;
|
|
|
|
|
-
|
|
|
|
|
- // Read geometry mesh
|
|
|
|
|
- XMLElement* mesh = geometry->FirstChildElement("mesh");
|
|
|
|
|
- if (mesh == NULL)
|
|
|
|
|
|
|
+ // Generate vb/ib
|
|
|
|
|
+ uint32_t idx = 0;
|
|
|
|
|
+ for (uint32_t i = 0; i < position_index.size(); i++)
|
|
|
{
|
|
{
|
|
|
- cout << "Bad geometry: no meshes found." << endl;
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // Actually, there is more stuff to parse
|
|
|
|
|
- return parse_mesh(mesh, g.mesh);
|
|
|
|
|
-}
|
|
|
|
|
|
|
+ MeshVertex v;
|
|
|
|
|
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
|
|
-bool MeshCompiler::parse_mesh(XMLElement* mesh, DAEMesh& m)
|
|
|
|
|
-{
|
|
|
|
|
- /// Read sources
|
|
|
|
|
- XMLElement* source = mesh->FirstChildElement("source");
|
|
|
|
|
- if (source == NULL)
|
|
|
|
|
- {
|
|
|
|
|
- cout << "Bad mesh: no sources found." << endl;
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ uint16_t p_idx = position_index[i] * 3;
|
|
|
|
|
+ v.position = Vec3(position_array[p_idx], position_array[p_idx + 1], position_array[p_idx + 2]);
|
|
|
|
|
|
|
|
- for (; source != NULL; source = source->NextSiblingElement("source"))
|
|
|
|
|
- {
|
|
|
|
|
- DAESource s;
|
|
|
|
|
- if (parse_source(source, s))
|
|
|
|
|
|
|
+ if (m_has_normal)
|
|
|
{
|
|
{
|
|
|
- m.sources.push_back(s);
|
|
|
|
|
|
|
+ uint16_t n_idx = normal_index[i] * 3;
|
|
|
|
|
+ v.normal = Vec3(normal_array[n_idx], normal_array[n_idx + 1], normal_array[n_idx + 2]);
|
|
|
}
|
|
}
|
|
|
- else
|
|
|
|
|
- {
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // Read vertices
|
|
|
|
|
- XMLElement* vertices = mesh->FirstChildElement("vertices");
|
|
|
|
|
- if (vertices == NULL)
|
|
|
|
|
- {
|
|
|
|
|
- cout << "Bad mesh: no vertices found." << endl;
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (!parse_vertices(vertices, m.vertices))
|
|
|
|
|
- {
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // Read polylist
|
|
|
|
|
- XMLElement* polylist = mesh->FirstChildElement("polylist");
|
|
|
|
|
- if (polylist == NULL)
|
|
|
|
|
- {
|
|
|
|
|
- cout << "Bad mesh: no polylist found." << endl;
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- return parse_polylist(polylist, m.polylist);
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
|
|
-bool MeshCompiler::parse_source(XMLElement* source, DAESource& s)
|
|
|
|
|
-{
|
|
|
|
|
- // Read source id
|
|
|
|
|
- const char* source_id = source->Attribute("id");
|
|
|
|
|
- if (source_id == NULL)
|
|
|
|
|
- {
|
|
|
|
|
- cout << "Bad source: missing 'id' attribute." << endl;
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- s.id = source_id;
|
|
|
|
|
-
|
|
|
|
|
- // Read float array
|
|
|
|
|
- XMLElement* float_array = source->FirstChildElement("float_array");
|
|
|
|
|
- if (float_array == NULL)
|
|
|
|
|
- {
|
|
|
|
|
- cout << "Bad source: no 'float_array' found." << endl;
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (!parse_float_array(float_array, s.float_array))
|
|
|
|
|
- {
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // Read technique
|
|
|
|
|
- XMLElement* technique_common = source->FirstChildElement("technique_common");
|
|
|
|
|
- if (technique_common == NULL)
|
|
|
|
|
- {
|
|
|
|
|
- cout << "Bad source: no 'technique_common' found." << endl;
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (!parse_technique_common(technique_common, s.technique_common))
|
|
|
|
|
- {
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- return true;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
|
|
-bool MeshCompiler::parse_float_array(XMLElement* array, DAEFloatArray& a)
|
|
|
|
|
-{
|
|
|
|
|
- // Read float array id
|
|
|
|
|
- const char* float_array_id = array->Attribute("id");
|
|
|
|
|
- if (float_array_id == NULL)
|
|
|
|
|
- {
|
|
|
|
|
- cout << "Bad float array: missing 'id' attribute." << endl;
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- a.id = float_array_id;
|
|
|
|
|
-
|
|
|
|
|
- // Read number of floats
|
|
|
|
|
- uint32_t count = 0;
|
|
|
|
|
- if (array->QueryUnsignedAttribute("count", &count) != XML_NO_ERROR)
|
|
|
|
|
- {
|
|
|
|
|
- cout << "Bad float array: missing 'count' attribute." << endl;
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- std::istringstream floats(array->GetText());
|
|
|
|
|
- for (uint32_t i = 0; i < count; i++)
|
|
|
|
|
- {
|
|
|
|
|
- float out = 0.0f;
|
|
|
|
|
- floats >> out;
|
|
|
|
|
- a.array.push_back(out);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- return true;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
|
|
-bool MeshCompiler::parse_technique_common(XMLElement* technique, DAETechniqueCommon& t)
|
|
|
|
|
-{
|
|
|
|
|
- // Read accessor
|
|
|
|
|
- XMLElement* accessor = technique->FirstChildElement("accessor");
|
|
|
|
|
- if (accessor == NULL)
|
|
|
|
|
- {
|
|
|
|
|
- cout << "Bad technique: no accessors found." << endl;
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- return parse_accessor(accessor, t.accessor);
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
|
|
-bool MeshCompiler::parse_accessor(XMLElement* accessor, DAEAccessor& a)
|
|
|
|
|
-{
|
|
|
|
|
- // Read accessor source
|
|
|
|
|
- const char* accessor_source = accessor->Attribute("source");
|
|
|
|
|
- if (accessor_source == NULL)
|
|
|
|
|
- {
|
|
|
|
|
- cout << "Bad accessor: missing 'source' attribute." << endl;
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
|
|
|
|
|
- // First char is '#'
|
|
|
|
|
- a.source = &accessor_source[1];
|
|
|
|
|
-
|
|
|
|
|
- // Read accessor count
|
|
|
|
|
- if (accessor->QueryUnsignedAttribute("count", &a.count) != XML_NO_ERROR)
|
|
|
|
|
- {
|
|
|
|
|
- cout << "Bad accessor: missing 'count' attribute." << endl;
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // Read accessor stride
|
|
|
|
|
- if (accessor->QueryUnsignedAttribute("stride", &a.stride) != XML_NO_ERROR)
|
|
|
|
|
- {
|
|
|
|
|
- cout << "Bad accessor: missing 'stride' attribute." << endl;
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // Read params
|
|
|
|
|
- XMLElement* param = accessor->FirstChildElement("param");
|
|
|
|
|
- if (param == NULL)
|
|
|
|
|
- {
|
|
|
|
|
- cout << "Bad accessor: no params found." << endl;
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- for (; param != NULL; param = param->NextSiblingElement("param"))
|
|
|
|
|
- {
|
|
|
|
|
- DAEParam p;
|
|
|
|
|
- if (parse_param(param, p))
|
|
|
|
|
|
|
+ if (m_has_texcoord)
|
|
|
{
|
|
{
|
|
|
- a.params.push_back(p);
|
|
|
|
|
|
|
+ uint16_t t_idx = texcoord_index[i] * 2;
|
|
|
|
|
+ v.texcoord = Vec2(texcoord_array[t_idx], texcoord_array[t_idx + 1]);
|
|
|
}
|
|
}
|
|
|
- else
|
|
|
|
|
- {
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
|
|
|
|
|
- return true;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
|
|
-bool MeshCompiler::parse_param(XMLElement* param, DAEParam& p)
|
|
|
|
|
-{
|
|
|
|
|
- // Read param name
|
|
|
|
|
- const char* param_name = param->Attribute("name");
|
|
|
|
|
- if (param_name == NULL)
|
|
|
|
|
- {
|
|
|
|
|
- cout << "Bad param: missing 'name' attribute." << endl;
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- p.name = param_name;
|
|
|
|
|
|
|
|
|
|
- // Read param type
|
|
|
|
|
- const char* param_type = param->Attribute("type");
|
|
|
|
|
- if (param_type == NULL)
|
|
|
|
|
- {
|
|
|
|
|
- cout << "Bad param: missing 'type' attribute." << endl;
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- p.type = param_type;
|
|
|
|
|
-
|
|
|
|
|
- return true;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
|
|
-bool MeshCompiler::parse_vertices(XMLElement* vertices, DAEVertices& v)
|
|
|
|
|
-{
|
|
|
|
|
- // Read vertices id
|
|
|
|
|
- const char* vertices_id = vertices->Attribute("id");
|
|
|
|
|
- if (vertices_id == NULL)
|
|
|
|
|
- {
|
|
|
|
|
- cout << "Bad vertices: missing 'id' attribute." << endl;
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- v.id = vertices_id;
|
|
|
|
|
-
|
|
|
|
|
- // Read inputs
|
|
|
|
|
- XMLElement* input = vertices->FirstChildElement("input");
|
|
|
|
|
- if (input == NULL)
|
|
|
|
|
- {
|
|
|
|
|
- cout << "Bad vertices: no inputs found." << endl;
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- for (; input != NULL; input = input->NextSiblingElement("input"))
|
|
|
|
|
- {
|
|
|
|
|
- DAEInput i;
|
|
|
|
|
- if (parse_input(input, i))
|
|
|
|
|
|
|
+ uint32_t f_idx = 0;
|
|
|
|
|
+ bool found = false;
|
|
|
|
|
+ for (; f_idx < m_vertices.size(); f_idx++)
|
|
|
{
|
|
{
|
|
|
- v.inputs.push_back(i);
|
|
|
|
|
- }
|
|
|
|
|
- else
|
|
|
|
|
- {
|
|
|
|
|
- return false;
|
|
|
|
|
|
|
+ if (m_vertices[f_idx] == v)
|
|
|
|
|
+ {
|
|
|
|
|
+ found = true;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- return true;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
|
|
-bool MeshCompiler::parse_input(XMLElement* input, DAEInput& i)
|
|
|
|
|
-{
|
|
|
|
|
- // Read input semantic
|
|
|
|
|
- const char* input_semantic = input->Attribute("semantic");
|
|
|
|
|
- if (input_semantic == NULL)
|
|
|
|
|
- {
|
|
|
|
|
- cout << "Bad input: missing 'semantic' attribute." << endl;
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- i.semantic = input_semantic;
|
|
|
|
|
|
|
|
|
|
- // Read input source
|
|
|
|
|
- const char* input_source = input->Attribute("source");
|
|
|
|
|
- if (input_source == NULL)
|
|
|
|
|
- {
|
|
|
|
|
- cout << "Bad input: missing 'source' attribute." << endl;
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // First char is '#'
|
|
|
|
|
- i.source = &input_source[1];
|
|
|
|
|
-
|
|
|
|
|
- if (input->QueryUnsignedAttribute("offset", &i.offset) == XML_NO_ATTRIBUTE)
|
|
|
|
|
- {
|
|
|
|
|
- i.offset = 0;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- return true;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
|
|
-bool MeshCompiler::parse_polylist(XMLElement* polylist, DAEPolylist& p)
|
|
|
|
|
-{
|
|
|
|
|
- // Read polylist count
|
|
|
|
|
- if (polylist->QueryUnsignedAttribute("count", &p.count) != XML_NO_ERROR)
|
|
|
|
|
- {
|
|
|
|
|
- cout << "Bad polylist: missing 'count' attribute." << endl;
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // Read inputs
|
|
|
|
|
- XMLElement* input = polylist->FirstChildElement("input");
|
|
|
|
|
- if (input == NULL)
|
|
|
|
|
- {
|
|
|
|
|
- cout << "Bad polylist: no inputs found." << endl;
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- for (; input != NULL; input = input->NextSiblingElement("input"))
|
|
|
|
|
- {
|
|
|
|
|
- DAEInput i;
|
|
|
|
|
- if (parse_input(input, i))
|
|
|
|
|
|
|
+ if (found)
|
|
|
{
|
|
{
|
|
|
- p.inputs.push_back(i);
|
|
|
|
|
|
|
+ m_indices.push_back(f_idx);
|
|
|
}
|
|
}
|
|
|
else
|
|
else
|
|
|
{
|
|
{
|
|
|
- return false;
|
|
|
|
|
|
|
+ m_vertices.push_back(v);
|
|
|
|
|
+ m_indices.push_back(idx);
|
|
|
|
|
+ idx++;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // Read vcount
|
|
|
|
|
- XMLElement* vcount = polylist->FirstChildElement("vcount");
|
|
|
|
|
- if (vcount == NULL)
|
|
|
|
|
- {
|
|
|
|
|
- cout << "Bad polylist: no vcount found." << endl;
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- std::istringstream vcount_text(vcount->GetText());
|
|
|
|
|
- uint32_t vcount_item = 0;
|
|
|
|
|
- while (vcount_text >> vcount_item)
|
|
|
|
|
- {
|
|
|
|
|
- p.vcount.push_back(vcount_item);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // Read p
|
|
|
|
|
- XMLElement* p_element = polylist->FirstChildElement("p");
|
|
|
|
|
- if (p_element == NULL)
|
|
|
|
|
- {
|
|
|
|
|
- cout << "Bad polylist: no p found." << endl;
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- std::istringstream p_text(p_element->GetText());
|
|
|
|
|
- uint32_t p_item = 0;
|
|
|
|
|
- while (p_text >> p_item)
|
|
|
|
|
- {
|
|
|
|
|
- p.p.push_back(p_item);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- return true;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
|
|
-bool MeshCompiler::find_vertices(const DAEMesh& mesh, DAESource& source_out)
|
|
|
|
|
-{
|
|
|
|
|
- const vector<DAESource>& sources = mesh.sources;
|
|
|
|
|
- const vector<DAEInput>& inputs = mesh.vertices.inputs;
|
|
|
|
|
-
|
|
|
|
|
- for (uint32_t input_i = 0; input_i < inputs.size(); input_i++)
|
|
|
|
|
- {
|
|
|
|
|
- const DAEInput& input = inputs[input_i];
|
|
|
|
|
-
|
|
|
|
|
- for (uint32_t source_i = 0; source_i < sources.size(); source_i++)
|
|
|
|
|
- {
|
|
|
|
|
- const DAESource& source = sources[source_i];
|
|
|
|
|
|
|
+ m_mesh_header.version = MESH_VERSION;
|
|
|
|
|
+ m_mesh_header.num_meshes = 1;
|
|
|
|
|
+ m_mesh_header.num_joints = 0;
|
|
|
|
|
+ //m_mesh_header.padding[0] = 0xCECECECE;
|
|
|
|
|
|
|
|
- if (input.semantic == "POSITION" && input.source == source.id)
|
|
|
|
|
- {
|
|
|
|
|
- source_out = source;
|
|
|
|
|
- return true;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ default_allocator().deallocate(buf);
|
|
|
|
|
+ fs.close(file);
|
|
|
|
|
|
|
|
- cout << "Failed to find 'POSITION' source." << endl;
|
|
|
|
|
- return false;
|
|
|
|
|
|
|
+ return sizeof(MeshHeader) + sizeof(MeshData) +
|
|
|
|
|
+ m_vertices.size() * sizeof(MeshVertex) +
|
|
|
|
|
+ m_indices.size() * sizeof(uint16_t);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//-----------------------------------------------------------------------------
|
|
|
-bool MeshCompiler::find_normals(const DAEMesh& mesh, DAESource& source_out)
|
|
|
|
|
|
|
+void MeshCompiler::write_impl(File* out_file)
|
|
|
{
|
|
{
|
|
|
- const vector<DAESource>& sources = mesh.sources;
|
|
|
|
|
- const vector<DAEInput>& inputs = mesh.polylist.inputs;
|
|
|
|
|
-
|
|
|
|
|
- for (uint32_t input_i = 0; input_i < inputs.size(); input_i++)
|
|
|
|
|
- {
|
|
|
|
|
- const DAEInput& input = inputs[input_i];
|
|
|
|
|
|
|
+ MeshData data;
|
|
|
|
|
+ data.vertices.num_vertices = m_vertices.size();
|
|
|
|
|
+ data.vertices.format = VERTEX_P3_N3_T2;
|
|
|
|
|
+ data.vertices.offset = sizeof(MeshHeader) + sizeof(MeshData);
|
|
|
|
|
|
|
|
- for (uint32_t source_i = 0; source_i < sources.size(); source_i++)
|
|
|
|
|
- {
|
|
|
|
|
- const DAESource& source = sources[source_i];
|
|
|
|
|
-
|
|
|
|
|
- cout << input.semantic << " " << input.source << " " << source.id << endl;
|
|
|
|
|
- if (input.semantic == "NORMAL" && input.source == source.id)
|
|
|
|
|
- {
|
|
|
|
|
- source_out = source;
|
|
|
|
|
- return true;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- cout << "Failed to find 'NORMAL' source." << endl;
|
|
|
|
|
- return false;
|
|
|
|
|
-}
|
|
|
|
|
|
|
+ data.indices.num_indices = m_indices.size();
|
|
|
|
|
+ data.indices.offset = sizeof(MeshHeader) + sizeof(MeshData) + m_vertices.size() * sizeof(MeshVertex);
|
|
|
|
|
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
|
|
-bool MeshCompiler::extract_vertex_indices(const DAEMesh& mesh, vector<uint16_t>& indices_out)
|
|
|
|
|
-{
|
|
|
|
|
- // Find vertices
|
|
|
|
|
- DAESource vertex_source;
|
|
|
|
|
- if (!find_vertices(mesh, vertex_source))
|
|
|
|
|
- {
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ // Write header
|
|
|
|
|
+ out_file->write((char*)&m_mesh_header, sizeof(MeshHeader));
|
|
|
|
|
|
|
|
- // Read vertices
|
|
|
|
|
- const vector<uint32_t>& primitives = mesh.polylist.p;
|
|
|
|
|
- //const vector<float>& vertices = vertex_source.float_array.array;
|
|
|
|
|
|
|
+ // Write mesh metadata
|
|
|
|
|
+ out_file->write((char*)&data, sizeof(MeshData));
|
|
|
|
|
|
|
|
- // FIXME FIXME FIXME
|
|
|
|
|
- //uint32_t offset = 0;
|
|
|
|
|
- uint32_t attribs = mesh.polylist.inputs.size();
|
|
|
|
|
|
|
+ // Write vertices
|
|
|
|
|
+ out_file->write((char*) m_vertices.begin(), m_vertices.size() * sizeof(MeshVertex));
|
|
|
|
|
|
|
|
- uint32_t prims = 0;
|
|
|
|
|
- while(prims < primitives.size())
|
|
|
|
|
- {
|
|
|
|
|
- indices_out.push_back((uint16_t) primitives[prims]);
|
|
|
|
|
- prims += attribs;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ // Write indices
|
|
|
|
|
+ out_file->write((char*) m_indices.begin(), m_indices.size() * sizeof(uint16_t));
|
|
|
|
|
|
|
|
- return true;
|
|
|
|
|
|
|
+ // Cleanup
|
|
|
|
|
+ m_vertices.clear();
|
|
|
|
|
+ m_indices.clear();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
} // namespace crown
|
|
} // namespace crown
|