diff --git a/BinaryFile.cpp b/BinaryFile.cpp index 3ed3914..cfd5358 100644 --- a/BinaryFile.cpp +++ b/BinaryFile.cpp @@ -15,4 +15,14 @@ BinaryFile::~BinaryFile() { if (filestream.is_open()) { filestream.close(); } +} + +CompressedBinaryFile::CompressedBinaryFile(const char *fname) : BinaryFile(fname) { + +} + +CompressedBinaryFile::~CompressedBinaryFile() { + if (filestream.is_open()) { + filestream.close(); + } } \ No newline at end of file diff --git a/BinaryFile.h b/BinaryFile.h index 78634dc..6b08912 100644 --- a/BinaryFile.h +++ b/BinaryFile.h @@ -14,7 +14,7 @@ class BinaryFile { public: BinaryFile(const char *fname); - ~BinaryFile(); + virtual ~BinaryFile(); template std::ostream &write(const T &data) { @@ -27,25 +27,153 @@ class BinaryFile { return filestream.write((char *)data, sizeof(T)); } - std::ostream &write(const size_t &size) { - uint64_t size_s = size; - return filestream.write((char *)&size_s, sizeof(uint64_t)); - } + std::ostream &write(const char *str) { + assert(str != nullptr); + return filestream.write(str, strlen(str)); + } - std::ostream &write(const char *str) { - assert(str != nullptr); - return filestream.write(str, strlen(str)); - } + std::ostream &write(char *const &str) { + assert(str != nullptr); + return filestream.write(str, strlen(str)); + } - std::ostream &write(char *const &str) { - assert(str != nullptr); - return filestream.write(str, strlen(str)); - } + std::ostream &write(const std::string &str) { + return filestream.write(str.c_str(), str.size()); + } - std::ostream &write(const std::string &str) { - return filestream.write(str.c_str(), str.size()); - } + // We need some explict write functions for some things. + // This includes integers because they can implictly cast to one another. - private: + virtual std::ostream &write_int16(const int16_t &value) { + return write(value); + } + + virtual std::ostream &write_uint16(const uint16_t &value) { + return write(value); + } + + virtual std::ostream &write_int32(const int32_t &value) { + return write(value); + } + + virtual std::ostream &write_uint32(const uint32_t &value) { + return write(value); + } + + virtual std::ostream &write_int64(const int64_t &value) { + return write(value); + } + + virtual std::ostream &write_uint64(const uint64_t &value) { + return write(value); + } + + protected: std::fstream filestream; +}; + +class CompressedBinaryFile : public BinaryFile { + public: + CompressedBinaryFile(const char *fname); + virtual ~CompressedBinaryFile(); + + // For these in particular, Compress the data. + // It can save some space, But we don't force compression on principle. + // In future it should be a toggable option. + + std::ostream &write(const uint64_t &value) { + uint64_t c = value & 0xFFFFFFFFFFFFFFFF; + + if (c == (uint64_t)-1) { + char max_value_bytes[] = { '\xFF', '\xFF', '\xFF', '\xFF', '\x0F' }; + return filestream.write(max_value_bytes, sizeof(max_value_bytes)); + } else if (c == 0) { + uint8_t s = 0; + return filestream.write((char *)&s, sizeof(uint8_t)); + } + + while (true) { + uint8_t b = (uint8_t)(c & 0x7fL); + c >>= 7L; + if (c > 0L) b |= 128L; + std::ostream &stream = filestream.write((char *)&b, sizeof(uint8_t)); + if (c == 0) return stream; + } + } + + std::ostream &write(const uint32_t &value) { + return write((uint64_t)(value & 0xFFFFFFFF)); + } + + std::ostream &write(const float &value) { + FourByteUnion cval; + cval.fval = value; + + return write(cval.uval); + } + + std::ostream &write(const double &value) { + EightByteUnion cval; + cval.fval = value; + + return write(cval.uval); + } + + std::ostream &write(const Vector3f &value) { + write(value.x); + write(value.y); + return write(value.z); + } + + std::ostream& write(const Vector3d &value) { + write(value.x); + write(value.y); + return write(value.z); + } + + std::ostream& write(const Vector4f &value) { + write(value.x); + write(value.y); + write(value.z); + return write(value.w); + } + + std::ostream &write(const Vector4d &value) { + write(value.x); + write(value.y); + write(value.z); + return write(value.w); + } + + std::ostream &write(const Matrix4f &value) { + std::ostream *stream = nullptr; + + for (uint8_t i = 0; i < 4; i++) { + for (uint8_t j = 0; j < 4; j++) { + stream = &write(value.mat[i][j]); + } + } + return *stream; + } + + std::ostream &write(const Matrix4d &value) { + std::ostream *stream = nullptr; + + for (uint8_t i = 0; i < 4; i++) { + for (uint8_t j = 0; j < 4; j++) { + stream = &write(value.mat[i][j]); + } + } + return *stream; + } + + // Direct types to write compressed. + + virtual std::ostream &write_uint32(const uint32_t &value) { + return write(value); + } + + virtual std::ostream &write_uint64(const uint64_t &value) { + return write(value); + } }; \ No newline at end of file diff --git a/Constraint.cpp b/Constraint.cpp new file mode 100644 index 0000000..6e67478 --- /dev/null +++ b/Constraint.cpp @@ -0,0 +1,205 @@ +#include "Constraint.h" + +#include + +Constraint::Constraint(Constraint::Type ctype) { + type = ctype; + switch (type) { + case POSITION_LIMIT: + position_limits = new PositionLimits; + break; + default: + break; + } +} + +Constraint::~Constraint() { + if (active_elements) { + delete[] active_elements; + active_elements = nullptr; + } + if (active_element_indicies) { + delete[] active_element_indicies; + active_element_indicies = nullptr; + } + + // Constraint Attributes + + if (position_limits) { + delete position_limits; + position_limits = nullptr; + } +} + +Constraint::Type Constraint::get_type() { + return type; +} + +void Constraint::set_passive_element(Element *element) { + assert(element != nullptr); + passive_element = element; +} + +Element *Constraint::get_passive_element() { + return passive_element; +} + +void Constraint::prepare_active_elements(uint32_t count) { + if (count <= 0) { return; } + + // Free the buffer if it's already in use. + if (active_elements) { + delete[] active_elements; + active_elements = nullptr; + } + + active_elements_count = count; + active_elements = new Element *[active_elements_count + 1]; + memset(active_elements, 0, sizeof(Element *) * active_elements_count); +} + +Element **Constraint::get_active_elements() { + assert(active_elements != nullptr); + return active_elements; +} + +uint32_t Constraint::get_active_elements_count() { + return active_elements_count; +} + +void Constraint::set_passive_element_index(SIZE index) { + passive_element_index = index; +} + +SIZE Constraint::get_passive_element_index() { + return passive_element_index; +} + +void Constraint::prepare_active_element_indicies() { + if (active_elements_count <= 0) { return; } + + // Free the buffer if it's already in use. + if (active_element_indicies) { + delete[] active_element_indicies; + active_element_indicies = nullptr; + } + + active_element_indicies = new SIZE[active_elements_count + 1]; + memset(active_element_indicies, 0, sizeof(SIZE) * active_elements_count); +} + +SIZE *Constraint::get_active_element_indicies() { + assert(active_element_indicies != nullptr); + return active_element_indicies; +} + +PositionLimits *Constraint::get_position_limits() { + assert(position_limits != nullptr); + return position_limits; +} + +void Constraint::write(BinaryFile &file) { + file.write(type); + file.write(passive_element_index); + file.write(active_elements_count); + assert(active_element_indicies != nullptr); + for (uint32_t i = 0; i < active_elements_count; i++) { + SIZE active_element_index = active_element_indicies[i]; + file.write(active_element_index); + } + if (position_limits) { + position_limits->write(file); + } +} + +void PositionLimits::set_coordinate_system(CoordinateSystem system) { + coordinate_system = system; +} + +CoordinateSystem PositionLimits::get_coordinate_system() { + return coordinate_system; +} + +void PositionLimits::set_shape_type(PositionLimits::ShapeType type) { + shape_type = type; +} + +PositionLimits::ShapeType PositionLimits::get_shape_type() { + return shape_type; +} + +void PositionLimits::set_damping(float width, float strength) { + damping_width = width; + damping_strength = strength; +} + +float PositionLimits::get_damping_width() { + return damping_width; +} + +float PositionLimits::get_damping_strength() { + return damping_strength; +} + +void PositionLimits::set_radius(float rad) { + radius = rad; +} + +float PositionLimits::get_radius() { + return radius; +} + +void PositionLimits::set_max_pos(float x, float y, float z) { + max_pos.x = x; + max_pos.y = y; + max_pos.z = z; +} + +Vector3f &PositionLimits::get_max_pos() { + return max_pos; +} + +void PositionLimits::set_min_pos(float x, float y, float z) { + min_pos.x = x; + min_pos.y = y; + min_pos.z = z; +} + +Vector3f &PositionLimits::get_min_pos() { + return min_pos; +} + +void PositionLimits::set_max_pos_active(bool active_x, bool active_y, bool active_z) { + max_pos_active.x = active_x; + max_pos_active.y = active_y; + max_pos_active.z = active_z; +} + +Vector3b &PositionLimits::get_max_pos_active() { + return max_pos_active; +} + +void PositionLimits::set_min_pos_active(bool active_x, bool active_y, bool active_z) { + min_pos_active.x = active_x; + min_pos_active.y = active_y; + min_pos_active.z = active_z; +} + +Vector3b &PositionLimits::get_min_pos_active() { + return min_pos_active; +} + +void PositionLimits::write(BinaryFile &file) { + file.write(coordinate_system); // Coordinate System + file.write(shape_type); // Shape Type + + // Damping + file.write(damping_width); + file.write(damping_strength); + + file.write(radius); // Radius + file.write(max_pos); // Maximum Values + file.write(min_pos); // Minimum Values + file.write(max_pos_active); // Maximum Values Active + file.write(min_pos_active); // Minimum Values Active +} \ No newline at end of file diff --git a/Constraint.h b/Constraint.h new file mode 100644 index 0000000..33f2dbf --- /dev/null +++ b/Constraint.h @@ -0,0 +1,119 @@ +#pragma once +#include + +#include "BinaryFile.h" +#include "Element.h" +#include "Types.h" + +class PositionLimits; + +class Constraint { + public: + enum Type: uint8_t { + INVALID, + POSITION, + ORIENTATION, + SCALE, + POSITION_LIMIT, + ROTATION_LIMIT, + }; + + public: + Constraint(Type ctype); + ~Constraint(); + + Type get_type(); + + void set_passive_element(Element *element); + Element *get_passive_element(); + + void prepare_active_elements(uint32_t count); + Element **get_active_elements(); + + uint32_t get_active_elements_count(); + + void set_passive_element_index(SIZE index); + SIZE get_passive_element_index(); + + void prepare_active_element_indicies(); + SIZE *get_active_element_indicies(); + + // Constraint Attribute Functions + PositionLimits *get_position_limits(); + + // Read/Write Functions + void write(BinaryFile &file); + + private: + // The type of constraint this is, INVALID means there is no valid type set. + Type type = INVALID; + + // The 'passive' element, This is the target of the constraint and what the constraints, well constrain. + Element *passive_element = nullptr; + + // The 'active' elements, The are the elements that the constraint will constrain the passive element (target) from. + Element **active_elements = nullptr; + uint32_t active_elements_count = 0; + + // Constraint Attributes + PositionLimits *position_limits = nullptr; + + // Read/Write specfic information + SIZE passive_element_index = 0; + + SIZE *active_element_indicies = nullptr; +}; + +class PositionLimits { + public: + enum ShapeType : uint8_t { + SPHERE, + BOX, + }; + + PositionLimits() {}; + ~PositionLimits() {}; + + void set_coordinate_system(CoordinateSystem system); + CoordinateSystem get_coordinate_system(); + + void set_shape_type(ShapeType type); + ShapeType get_shape_type(); + + void set_damping(float width, float strength); + float get_damping_width(); + float get_damping_strength(); + + void set_radius(float rad); + float get_radius(); + + void set_max_pos(float x, float y, float z); + Vector3f &get_max_pos(); + + void set_min_pos(float x, float y, float z); + Vector3f &get_min_pos(); + + void set_max_pos_active(bool active_x, bool active_y, bool active_z); + Vector3b &get_max_pos_active(); + + void set_min_pos_active(bool active_x, bool active_y, bool active_z); + Vector3b &get_min_pos_active(); + + void write(BinaryFile &file); + + private: + CoordinateSystem coordinate_system = CoordinateSystem::GLOBAL; + + ShapeType shape_type = SPHERE; + + float damping_width = 0.0f; + float damping_strength = 0.0f; + + float radius = 0.0f; + + Vector3f max_pos = { 0.0f }; + Vector3f min_pos = { 0.0f }; + + Vector3b max_pos_active = { false }; + Vector3b min_pos_active = { false }; +}; \ No newline at end of file diff --git a/Element.cpp b/Element.cpp index d51b6d2..28f4ead 100644 --- a/Element.cpp +++ b/Element.cpp @@ -127,38 +127,38 @@ uint64_t Element::get_flags() { return flags; } -void Element::set_array_position(size_t index) { +void Element::set_array_position(SIZE index) { array_index = index; } -size_t Element::get_array_position() { +SIZE Element::get_array_position() { return array_index; } -void Element::set_parent_position(size_t index) { +void Element::set_parent_position(SIZE index) { parent_index = index; } -size_t Element::get_parent_position() { +SIZE Element::get_parent_position() { return parent_index; } -void Element::prepare_children_indexes() { +void Element::prepare_children_indicies() { if (children_indexes) { delete[] children_indexes; children_indexes = nullptr; } - children_indexes = new size_t[children_count + 1]; - memset(children_indexes, NULL, sizeof(size_t) * children_count); + children_indexes = new SIZE[children_count + 1]; + memset(children_indexes, NULL, sizeof(SIZE) * children_count); } -size_t *Element::get_children_indexes() { +SIZE *Element::get_children_indicies() { return children_indexes; } void Element::write(BinaryFile &file) { - file.write(name.size()); + file.write_uint64(name.size()); file.write(name); file.write(flags); file.write(matrix); @@ -170,7 +170,7 @@ void Element::write(BinaryFile &file) { file.write(parent_index); file.write(children_count); for (uint32_t i = 0; i < children_count; i++) { - size_t child_index = children_indexes[i]; + SIZE child_index = children_indexes[i]; file.write(child_index); } if (flags & Element::InfoTypes::Mesh) { @@ -335,7 +335,8 @@ uint32_t MeshInfo::get_normals_count() { return normals_count; } -void MeshInfo::prepare_uvs_and_textures(uint32_t new_texture_count, uint32_t tri_count) { +void MeshInfo::prepare_uvs_and_textures(uint32_t new_uv_coords_count, uint32_t new_uv_scales_count, uint32_t new_uv_offsets_count, + uint32_t new_texture_names_count, uint32_t new_texture_count) { // Free arrays if they're already allocated. if (u_coords) { delete[] u_coords; @@ -366,24 +367,33 @@ void MeshInfo::prepare_uvs_and_textures(uint32_t new_texture_count, uint32_t tri texture_names = nullptr; } - // Store our texture count; + // Store our counts. + uv_coords_count = new_uv_coords_count; + uv_scales_count = new_uv_scales_count; + uv_offsets_count = new_uv_offsets_count; + texture_names_count = new_texture_names_count; texture_count = new_texture_count; // Allocate arrays for uv coordinates. - uv_coords_count = tri_count * texture_count * 3; u_coords = new float[uv_coords_count + 1]; + memset(u_coords, 0, sizeof(float) * uv_coords_count); + v_coords = new float[uv_coords_count + 1]; + memset(v_coords, 0, sizeof(float) * uv_coords_count); // Allocate arrays of texture info. - uv_scales_count = tri_count; u_scales = new float[uv_scales_count + 1]; + memset(u_scales, 0, sizeof(float) * uv_scales_count); + v_scales = new float[uv_scales_count + 1]; + memset(v_scales, 0, sizeof(float) * uv_scales_count); - uv_offsets_count = tri_count; u_offsets = new float[uv_offsets_count + 1]; - v_offsets = new float[uv_offsets_count + 1]; + memset(u_offsets, 0, sizeof(float) * uv_offsets_count); + + v_offsets = new float[uv_offsets_count + 1]; + memset(v_offsets, 0, sizeof(float) * uv_offsets_count); - texture_names_count = tri_count; texture_names = new char *[texture_names_count + 1]; memset(texture_names, 0, sizeof(char *) * texture_names_count); } @@ -481,7 +491,7 @@ void MeshInfo::write(BinaryFile &file) { for (uint32_t i = 0; i < texture_names_count; i++) { char *&texture_name = texture_names[i]; if (texture_name == nullptr) { continue; } - file.write(strlen(texture_name)); + file.write_uint64(strlen(texture_name)); file.write(texture_name); } } \ No newline at end of file diff --git a/Element.h b/Element.h index 25613a4..4b99a17 100644 --- a/Element.h +++ b/Element.h @@ -31,7 +31,8 @@ class MeshInfo { Vector4d *get_normals(); uint32_t get_normals_count(); - void prepare_uvs_and_textures(uint32_t new_texture_count, uint32_t tri_count); + void prepare_uvs_and_textures(uint32_t new_uv_coords_count, uint32_t new_uv_scales_count, uint32_t new_uv_offsets_count, + uint32_t new_texture_names_count, uint32_t new_texture_count); int32_t &get_u_repeat(); int32_t &get_v_repeat(); @@ -139,14 +140,14 @@ class Element { void set_flags(uint64_t nflags); uint64_t get_flags(); - void set_array_position(size_t index); - size_t get_array_position(); + void set_array_position(SIZE index); + SIZE get_array_position(); - void set_parent_position(size_t index); - size_t get_parent_position(); + void set_parent_position(SIZE index); + SIZE get_parent_position(); - void prepare_children_indexes(); - size_t *get_children_indexes(); + void prepare_children_indicies(); + SIZE *get_children_indicies(); void write(BinaryFile &file); @@ -179,11 +180,11 @@ class Element { uint64_t flags = 0; // Used to resolve position in Element array. - size_t array_index = 0; + SIZE array_index = 0; // Position of parent in Element array. - size_t parent_index = 0; + SIZE parent_index = 0; // Array of indexes to all of our children. - size_t *children_indexes = nullptr; + SIZE *children_indexes = nullptr; }; \ No newline at end of file diff --git a/Types.h b/Types.h index 5853843..d9f1ebb 100644 --- a/Types.h +++ b/Types.h @@ -2,11 +2,37 @@ #include +#define SIZE uint64_t + +union FourByteUnion { + int32_t ival; + uint32_t uval; + float fval; +}; + +union EightByteUnion { + int64_t ival; + uint64_t uval; + double fval; +}; + +enum CoordinateSystem : uint8_t { + LOCAL, + GLOBAL +}; struct Matrix4f { float mat[4][4]; }; +struct Matrix4d { + double mat[4][4]; +}; + +struct Vector3b { + bool x, y, z; +}; + struct Vector3f { float x, y, z; }; @@ -15,6 +41,10 @@ struct Vector3d { double x, y, z; }; +struct Vector4b { + bool x, y, z, w; +}; + struct Vector4f { float x, y, z, w; }; diff --git a/soft2scene.cpp b/soft2scene.cpp index 570f3c8..0084845 100644 --- a/soft2scene.cpp +++ b/soft2scene.cpp @@ -13,12 +13,14 @@ #include #include "BinaryFile.h" +#include "Constraint.h" #include "Element.h" //// Global Variables //// // Global tables static std::vector elements; +static std::vector constraints; // Global strings. static char default_scene_name[] = "suitA-zero.1-0"; @@ -105,7 +107,7 @@ char *GetFullName(SAA_Scene *scene, SAA_Elem *element) { name[--name_len] = 0; // Construct the full name from both the prefix and name. - size_t fullname_len = name_len + prefix_len + 1; + int fullname_len = name_len + prefix_len + 1; char *fullname = new char[fullname_len + 1]; strncpy_s(fullname, fullname_len, prefix, prefix_len); strncpy_s(fullname + prefix_len + 1, fullname_len - prefix_len, name, name_len); @@ -175,6 +177,247 @@ int *MakeIndexMap(int *indices, int num_indices, int map_size) { return map; } +Element *SAAElemToElement(SAA_Scene *scene, SAA_Elem *model) { + std::string name; + { + // Get the name of the element. + char* namebuffer = nullptr; + if (true) { // use_prefix + // Get the FULL name of the trim curve + namebuffer = GetFullName(scene, model); + } else { + // Get the name of the trim curve + namebuffer = GetName(scene, model); + } + + name = std::string(namebuffer); + + // Free the copy of the name. We no longer need it. + delete[] namebuffer; + } + + for (size_t i = 0; i < elements.size(); i++) { + Element *element = elements[i]; + std::string &element_name = element->get_name(); + if (element_name.compare(name) == 0) { return element; } + } + + lprintf("ERROR: Couldn't find matching Element for SAA Element.", 0); + return nullptr; +} + +void CreateConstraints(SAA_Scene *scene, SAA_Elem *model) { + Element *element = SAAElemToElement(scene, model); + + void *rel_info = nullptr; + SAA_Elem *elements = nullptr; + int active_element_count = 0; + int passive_element_count = 0; + int total_element_count = 0; + + // Constrains the centers of the passive elements to the center of the active element. + SAA_modelRelationGetCnsPosNbElements(scene, model, 0, (const void **)&rel_info, &passive_element_count); + SAA_modelRelationGetCnsPosNbElements(scene, model, 1, (const void **)&rel_info, &active_element_count); + dprintf("Passive Pos Constraint Elements: %d\n", passive_element_count); + dprintf("Active Pos Constraint Elements: %d\n", active_element_count); + + // Only save a contraint if we have active elements. + if (active_element_count > 0) { + // Allocate buffer for all of the SAA Elements. + elements = new SAA_Elem[active_element_count + 1]; + + // Extract all of the active elements into the buffer. + SAA_modelRelationGetCnsPosElements(scene, model, rel_info, active_element_count, elements); + + // Allocate our constraint. + Constraint *pos_constraint = new Constraint(Constraint::Type::POSITION); + // Set the passive element to the element we're checking for constraints on. + pos_constraint->set_passive_element(element); + // Prepare the buffer for all of the active elements. + pos_constraint->prepare_active_elements(active_element_count); + // Get the buffer to act upon. + Element **active_constraint_elements = pos_constraint->get_active_elements(); + + // Iterate all of the active elements. + for (int i = 0; i < active_element_count; i++) { + // Get the active element. + SAA_Elem &saa_element = elements[i]; + // Convert from a Softimage Element to our own Element type. + Element *active_element = SAAElemToElement(scene, &saa_element); + printf("Active Pos Constraint Element <%s> for Element <%s>\n", active_element->get_name().c_str(), element->get_name().c_str()); + // Add the active element we found to the buffer. + active_constraint_elements[i] = active_element; + } + constraints.push_back(pos_constraint); + + delete[] elements; + } + + // Constrains the rotation of the passive elements to the rotation of the active element. + SAA_modelRelationGetCnsOriNbElements(scene, model, 0, (const void **)&rel_info, &passive_element_count); + SAA_modelRelationGetCnsOriNbElements(scene, model, 1, (const void **)&rel_info, &active_element_count); + dprintf("Passive Ori Constraint Elements: %d\n", passive_element_count); + dprintf("Active Ori Constraint Elements: %d\n", active_element_count); + + // Only save a contraint if we have active elements. + if (active_element_count > 0) { + // Allocate buffer for all of the SAA Elements. + elements = new SAA_Elem[active_element_count + 1]; + + // Extract all of the active elements into the buffer. + SAA_modelRelationGetCnsOriElements(scene, model, rel_info, active_element_count, elements); + + // Allocate our constraint. + Constraint *ori_constraint = new Constraint(Constraint::Type::ORIENTATION); + // Set the passive element to the element we're checking for constraints on. + ori_constraint->set_passive_element(element); + // Prepare the buffer for all of the active elements. + ori_constraint->prepare_active_elements(active_element_count); + // Get the buffer to act upon. + Element **active_constraint_elements = ori_constraint->get_active_elements(); + + // Iterate all of the active elements. + for (int i = 0; i < active_element_count; i++) { + // Get the active element + SAA_Elem &saa_element = elements[i]; + // Convert from a Softimage Element to our own Element type. + Element *active_element = SAAElemToElement(scene, &saa_element); + printf("Active Ori Constraint Element <%s> for Element <%s>\n", active_element->get_name().c_str(), element->get_name().c_str()); + // Add the active element we found to the buffer. + active_constraint_elements[i] = active_element; + } + constraints.push_back(ori_constraint); + + delete[] elements; + } + + // Constrains the scaling of the passive elements to the same scaling as the active element. + SAA_modelRelationGetCnsSclNbElements(scene, model, 0, (const void **)&rel_info, &passive_element_count); + SAA_modelRelationGetCnsSclNbElements(scene, model, 1, (const void **)&rel_info, &active_element_count); + dprintf("Passive Scl Constraint Elements: %d\n", passive_element_count); + dprintf("Active Scl Constraint Elements: %d\n", active_element_count); + + // Only save a contraint if we have active elements. + if (active_element_count > 0) { + // Allocate buffer for all of the SAA Elements. + elements = new SAA_Elem[active_element_count + 1]; + + // Extract all of the active elements into the buffer. + SAA_modelRelationGetCnsSclElements(scene, model, rel_info, active_element_count, elements); + + // Allocate our constraint. + Constraint *scl_constraint = new Constraint(Constraint::Type::SCALE); + // Set the passive element to the element we're checking for constraints on. + scl_constraint->set_passive_element(element); + // Prepare the buffer for all of the active elements. + scl_constraint->prepare_active_elements(active_element_count); + // Get the buffer to act upon. + Element **active_constraint_elements = scl_constraint->get_active_elements(); + + // Iterate all of the active elements. + for (int i = 0; i < active_element_count; i++) { + // Get the active element + SAA_Elem &saa_element = elements[i]; + // Convert from a Softimage Element to our own Element type. + Element *active_element = SAAElemToElement(scene, &saa_element); + printf("Active Scl Constraint Element <%s> for Element <%s>\n", active_element->get_name().c_str(), element->get_name().c_str()); + // Add the active element we found to the buffer. + active_constraint_elements[i] = active_element; + } + constraints.push_back(scl_constraint); + + delete[] elements; + } + + // Constrains the range of position of the passive element relative to the active element. + SAA_modelRelationGetCnsPosLimNbElements(scene, model, 0, (const void **)&rel_info, &passive_element_count); + SAA_modelRelationGetCnsPosLimNbElements(scene, model, 1, (const void **)&rel_info, &active_element_count); + dprintf("Passive Pos Limit Constraint Elements: %d\n", passive_element_count); + dprintf("Active Pos Limit Constraint Elements: %d\n", active_element_count); + + // Only save a contraint if we have a active and passive element (1) + if (passive_element_count == 1 && active_element_count == 1) { + // Allocate buffer for all of the SAA Elements. + elements = new SAA_Elem[active_element_count + 1]; + + // Extract all of the active elements into the buffer. + SAA_modelRelationGetCnsPosLimElements(scene, model, rel_info, active_element_count, elements); + + // Allocate our constraint. + Constraint *pos_limit_constraint = new Constraint(Constraint::Type::POSITION_LIMIT); + // Set the passive element to the element we're checking for constraints on. + pos_limit_constraint->set_passive_element(element); + // Prepare the buffer for all of the active elements. + pos_limit_constraint->prepare_active_elements(active_element_count); + // Get the buffer to act upon. + Element **active_constraint_elements = pos_limit_constraint->get_active_elements(); + + // Get the active element + SAA_Elem &saa_element = elements[0]; + // Convert from a Softimage Element to our own Element type. + Element *active_element = SAAElemToElement(scene, &saa_element); + printf("Active Pos Limit Constraint Element <%s> for Element <%s>\n", active_element->get_name().c_str(), element->get_name().c_str()); + // Add the active element we found to the buffer. + active_constraint_elements[0] = active_element; + + // Handle constraint attributes + PositionLimits *limits = pos_limit_constraint->get_position_limits(); + + // Get and store the coordinate system. + SAA_CoordSys system = SAA_COORDSYS_GLOBAL; + SAA_modelRelationGetCnsPosLimCoordSys(scene, &saa_element, model, &system); + limits->set_coordinate_system((CoordinateSystem)system); + + // Get and store the shape type. + SAA_CnsPosLimType type = SAA_CNSPOSLIM_SPHERE; + SAA_modelRelationGetCnsPosLimType(scene, &saa_element, model, &type); + limits->set_shape_type((PositionLimits::ShapeType)type); + + // Get and store our damping attributes. + float width, strength; + SAA_modelRelationGetCnsPosLimDamping(scene, &saa_element, model, &width, &strength); + limits->set_damping(width, strength); + + // Get and store our radius. + float radius; + SAA_modelRelationGetCnsPosLimRadius(scene, &saa_element, model, &radius); + limits->set_radius(radius); + + // Get and store the maximum position. + Vector3f &max_pos = limits->get_max_pos(); + SAA_modelRelationGetCnsPosLimMax(scene, &saa_element, model, &max_pos.x, &max_pos.y, &max_pos.z); + + // Get and store the minimum position. + Vector3f &min_pos = limits->get_min_pos(); + SAA_modelRelationGetCnsPosLimMin(scene, &saa_element, model, &min_pos.x, &min_pos.y, &min_pos.z); + + // Active booleans. + SAA_Boolean x_active = FALSE; + SAA_Boolean y_active = FALSE; + SAA_Boolean z_active = FALSE; + + // Get and store the maximum position activeness. + SAA_modelRelationGetCnsPosLimMaxActive(scene, &saa_element, model, &x_active, &y_active, &z_active); + limits->set_max_pos_active(x_active != FALSE, y_active != FALSE, z_active != FALSE); + + // Get and store the minimum position activeness. + SAA_modelRelationGetCnsPosLimMinActive(scene, &saa_element, model, &x_active, &y_active, &z_active); + limits->set_min_pos_active(x_active != FALSE, y_active != FALSE, z_active != FALSE); + + // We're done, Add the constraint to the vector. + constraints.push_back(pos_limit_constraint); + + // Free the allocated element space. + delete[] elements; + } + + // Constrains the range of rotation of a model (which is both the passive and active element). + SAA_modelRelationGetCnsRotLimNbElements(scene, model, 0, (const void **)&rel_info, &passive_element_count); + SAA_modelRelationGetCnsRotLimNbElements(scene, model, 1, (const void **)&rel_info, &active_element_count); + dprintf("Passive Rot Limit Constraint Elements: %d\n", passive_element_count); + dprintf("Active Rot Limit Constraint Elements: %d\n", active_element_count); +} + void HandleElementChildren(SAA_Scene *scene, SAA_Elem *model, Element *new_element, Element *new_joint) { // Check for children. int num_children = 0; @@ -490,7 +733,7 @@ Element *HandleMesh(SAA_Scene* scene, SAA_Elem* model, Element* last_element = n SAA_modelGetNbShapes(scene, model, &num_shapes); lfprintf(log_file, "Amount of shapes: %d\n", 1, num_shapes); - // TODO: Process all of our shapes. + // Process all of our shapes. //for (int i = 0; i < num_shapes; i++) { //} @@ -679,7 +922,7 @@ Element *HandleMesh(SAA_Scene* scene, SAA_Elem* model, Element* last_element = n if (num_tex_loc) { dprintf("DEBUG: Processing local textures (%d) for Element <%s>.\n", num_tex_loc, new_element->get_name().c_str()); // Allocate arrays for u & v coords and texture info - new_element->mesh_info->prepare_uvs_and_textures(num_tex_loc, num_tri); + new_element->mesh_info->prepare_uvs_and_textures(num_tex_loc * num_tri * 3, num_tri, num_tri, num_tri, num_tex_loc); float *u_coords = new_element->mesh_info->get_u_coords(); float *v_coords = new_element->mesh_info->get_v_coords(); @@ -769,7 +1012,7 @@ Element *HandleMesh(SAA_Scene* scene, SAA_Elem* model, Element* last_element = n } // Allocate arrays for u & v coords and texture info - new_element->mesh_info->prepare_uvs_and_textures(num_tex_glb, num_tri); + new_element->mesh_info->prepare_uvs_and_textures(num_tex_glb * num_tri * 3, 1, 1, 1, num_tex_glb); float *u_coords = new_element->mesh_info->get_u_coords(); float *v_coords = new_element->mesh_info->get_v_coords(); @@ -1148,22 +1391,57 @@ int ProcessScene(SAA_Database *database, SAA_Scene *scene, const char *scene_nam dprintf("DEBUG: Storing processed element %s with index %d!\n", element->get_name().c_str(), elements.size()); if (element) { elements.push_back(element); } } + + // Handle of these seperately from the elements. + // They can overlap with each other if take Elements into + // consideration. + for (int i = 0; i < num_models; i++) { + CreateConstraints(scene, &models[i]); + } - // First setup all of element indexes. This is setup for resolving + // First setup all of element indicies. This is setup for resolving // parents and children when written. for (size_t i = 0; i < elements.size(); i++) { Element *element = elements[i]; assert(element != nullptr); - element->prepare_children_indexes(); + element->prepare_children_indicies(); element->set_array_position(i); } + // Create the arrays for element indicies in constraints. + for (size_t i = 0; i < constraints.size(); i++) { + // Get our current constraint. + Constraint *constraint = constraints[i]; + assert(constraint != nullptr); + + // Set the passive element array index for our constraint. + Element *passive_element = constraint->get_passive_element(); + assert(passive_element != nullptr); + constraint->set_passive_element_index(passive_element->get_array_position()); + + // Prepare the array for all of the active element array indicies. + constraint->prepare_active_element_indicies(); + + // Get all of our active elements for the constraint. + Element **active_elements = constraint->get_active_elements(); + assert(active_elements != nullptr); + + // Get the array of active element indicies. + SIZE *active_element_indicies = constraint->get_active_element_indicies(); + assert(active_element_indicies != nullptr); + + // Set the active element index from all of our active elements. + for (uint32_t j = 0; j < constraint->get_active_elements_count(); j++) { + active_element_indicies[j] = active_elements[j]->get_array_position(); + } + } + // Setup the children positions and the parent position for all of the children. for (size_t i = 0; i < elements.size(); i++) { Element *element = elements[i]; assert(element != nullptr); uint32_t children_count = element->get_children_amount(); - size_t *chidren_indexes = element->get_children_indexes(); + SIZE *chidren_indexes = element->get_children_indicies(); for (uint32_t j = 0; j < children_count; j++) { Element *child = element->get_child(j); assert(child != nullptr); @@ -1172,18 +1450,35 @@ int ProcessScene(SAA_Database *database, SAA_Scene *scene, const char *scene_nam } } - // Write all of the elements. + // Open our binary file for writing. std::string filename(scene_name); - std::string file_ext(".scene"); - filename += file_ext; + { + std::string file_ext(".siscene"); + filename += file_ext; + } dprintf("Writing scene '%s' to file '%s'.\n", scene_name, filename.c_str()); BinaryFile file(filename.c_str()); - file.write(elements.size()); + + // Write the name of our scene. + file.write_uint64(strlen(scene_name)); + file.write(scene_name); + + // Write out all of our elements. + file.write_uint64(elements.size()); for (size_t i = 0; i < elements.size(); i++) { Element *element = elements[i]; + assert(element != nullptr); element->write(file); } + // Write out all of our constraints. + file.write_uint64(constraints.size()); + for (size_t i = 0; i < constraints.size(); i++) { + Constraint *constraint = constraints[i]; + assert(constraint != nullptr); + constraint->write(file); + } + // Free all of our elements. for (size_t i = 0; i < elements.size(); i++) { Element *element = elements[i]; @@ -1193,6 +1488,15 @@ int ProcessScene(SAA_Database *database, SAA_Scene *scene, const char *scene_nam // Clear the elements. elements.clear(); + // Free all of our constraints. + for (size_t i = 0; i < constraints.size(); i++) { + Constraint *constraint = constraints[i]; + constraints[i] = nullptr; + delete constraint; + } + // Clear the constraints. + constraints.clear(); + // Free the array of models. delete[] models; diff --git a/soft2scene.vcxproj b/soft2scene.vcxproj index 903c999..985c35b 100644 --- a/soft2scene.vcxproj +++ b/soft2scene.vcxproj @@ -160,11 +160,13 @@ + + diff --git a/soft2scene.vcxproj.filters b/soft2scene.vcxproj.filters index c0cda44..b993c03 100644 --- a/soft2scene.vcxproj.filters +++ b/soft2scene.vcxproj.filters @@ -24,6 +24,9 @@ Source Files + + Source Files + @@ -35,5 +38,8 @@ Header Files + + Header Files + \ No newline at end of file