private static void readVertexWeights(StreamReader stream, ModelData model) { // Bone Weights model.bone_weights = new ModelData.BoneConnection[model.num_lvertices]; int[] index = new int[4]; for (UInt32 i = 0; i < model.num_lvertices; ++i) { ASSERT_DELIMETER( stream, "("); index[0] = Convert.ToInt32(readWord(stream)); model.bone_weights[i].boneweight_1 = Convert.ToSingle(readWord(stream)); index[1] = Convert.ToInt32(readWord(stream)); model.bone_weights[i].boneweight_1 = Convert.ToSingle(readWord(stream)); index[2] = Convert.ToInt32(readWord(stream)); model.bone_weights[i].boneweight_1 = Convert.ToSingle(readWord(stream)); index[3] = Convert.ToInt32(readWord(stream)); model.bone_weights[i].boneweight_1 = Convert.ToSingle(readWord(stream)); model.bone_weights[i].boneid_1 = (byte)index[0]; model.bone_weights[i].boneid_2 = (byte)index[1]; model.bone_weights[i].boneid_3 = (byte)index[2]; model.bone_weights[i].boneid_4 = (byte)index[3]; ASSERT_DELIMETER( stream, ")"); } }
private static void readVertexLightNormals(StreamReader stream, ModelData model) { // Lighting Normals model.lighting_normal = new ModelData.Vector3[model.num_dvertices]; for (uint i = 0; i < model.num_dvertices; ++i) { ASSERT_DELIMETER(stream, "("); model.lighting_normal[i].x = Convert.ToSingle(readWord(stream)); model.lighting_normal[i].y = Convert.ToSingle(readWord(stream)); model.lighting_normal[i].z = Convert.ToSingle(readWord(stream)); ASSERT_DELIMETER(stream, ")"); } }
private static void readVertexUvs(StreamReader stream, ModelData model) { // Texture UVs model.texture_uvs = new ModelData.Vector2[model.num_dvertices]; for (uint i = 0; i < model.num_dvertices; ++i) { ASSERT_DELIMETER(stream, "("); model.texture_uvs[i].u = Convert.ToSingle(readWord(stream)); model.texture_uvs[i].v = Convert.ToSingle(readWord(stream)); ASSERT_DELIMETER(stream, ")"); } }
// ----==== Logical Vertex Data ====---- // private static void readVertexGeometry(StreamReader stream, ModelData model) { // Position Data model.position = new ModelData.Vector3[model.num_lvertices]; for (UInt32 i = 0; i < model.num_lvertices; ++i) { ASSERT_DELIMETER(stream, "("); model.position[i].x = Convert.ToSingle(readWord(stream)); model.position[i].y = Convert.ToSingle(readWord(stream)); model.position[i].z = Convert.ToSingle(readWord(stream)); ASSERT_DELIMETER(stream, ")"); } }
// ----==== Drawing Vertex Data ====---- // private static void readVertexIds(StreamReader stream, ModelData model) { // Indexes of the Logical Vertex the Drawn Vertices are linked to model.drawn_index = new UInt16[model.num_dvertices]; for (uint i = 0; i < model.num_dvertices; ++i) model.drawn_index[i] = Convert.ToUInt16(readWord(stream)); }
private static void readTriangleData(StreamReader stream, ModelData model) { // Triangle indices and normals uint i; i = Convert.ToUInt32( readWord(stream)); if (i > 0xffff) throw new Exception("Too many Triangles: " + i); model.num_triangles = (UInt16)i; model.drawn_triangles = new ModelData.Triangle[model.num_triangles]; model.collision_triangles = new ModelData.Triangle[model.num_triangles]; model.ctriangle_normals = new ModelData.Vector3[model.num_triangles]; for( i = 0; i < model.num_triangles; ++i) { ASSERT_DELIMETER(stream, "("); model.drawn_triangles[i].id_1 = Convert.ToUInt16(readWord(stream)); model.drawn_triangles[i].id_2 = Convert.ToUInt16(readWord(stream)); model.drawn_triangles[i].id_3 = Convert.ToUInt16(readWord(stream)); ASSERT_DELIMETER(stream, ")"); ASSERT_DELIMETER(stream, "("); model.ctriangle_normals[i].x = Convert.ToSingle(readWord(stream)); model.ctriangle_normals[i].y = Convert.ToSingle(readWord(stream)); model.ctriangle_normals[i].z = Convert.ToSingle(readWord(stream)); ASSERT_DELIMETER(stream, ")"); // Fill the collision triangles with appropriate data model.collision_triangles[i].id_1 = model.drawn_index[model.drawn_triangles[i].id_1]; model.collision_triangles[i].id_2 = model.drawn_index[model.drawn_triangles[i].id_2]; model.collision_triangles[i].id_3 = model.drawn_index[model.drawn_triangles[i].id_3]; } }
private static void readVertexCollisionNormals(StreamReader stream, ModelData model) { // Collision Normals model.collision_normal = new ModelData.Vector3[model.num_lvertices]; for (UInt32 i = 0; i < model.num_lvertices; ++i) { ASSERT_DELIMETER(stream, "("); model.collision_normal[i].x = Convert.ToSingle(readWord(stream)); model.collision_normal[i].y = Convert.ToSingle(readWord(stream)); model.collision_normal[i].z = Convert.ToSingle(readWord(stream)); ASSERT_DELIMETER(stream, ")"); } }
/// <summary> /// Load the Bone structure from the stream (bone structure contains /// Bone tree hierarchy and the transformation matrix corresponding /// to the bone's default position/orientation). /// </summary> private static void loadBoneStructure(BinaryReader stream, ModelData model) { model.inv_bone_matrices = new ModelData.BoneMatrix[model.num_bones]; model.bone_parents = new byte[model.num_bones]; for (byte i = 0; i < model.num_bones; ++i) model.bone_parents[i] = stream.ReadByte(); for (byte i = 0; i < model.num_bones; ++i) { model.inv_bone_matrices[i].a = new float[4, 4]; for (byte col = 0; col < 4; ++col) for (byte row = 0; row < 4; ++row) model.inv_bone_matrices[i].a[row, col] = stream.ReadSingle(); } }
private static void readFCurve(StreamReader stream, ModelData.Animation animation, byte bone, string id) { int index; ASSERT_DELIMETER(stream, id); index = Array.IndexOf(anim_types, id); for (int j = 0; j < animation.num_keys; ++j) { ASSERT_DELIMETER(stream, "("); animation.bone_animations[bone].key_states[j].handles[index].center = Convert.ToSingle(readWord(stream)); readWord(stream); // Ignored animation.bone_animations[bone].key_states[j].handles[index].left = Convert.ToSingle(readWord(stream)); readWord(stream); // Ignored animation.bone_animations[bone].key_states[j].handles[index].right= Convert.ToSingle(readWord(stream)); ASSERT_DELIMETER(stream, ")"); } }
/// <summary> /// Loads a single animation from the stream (an animation contains /// a timeline containing key frames, and keys at each point for each /// bone corresponding to their position and rotation at that frame). /// </summary> private static void loadAnimation(BinaryReader stream, ModelData model) { ModelData.Animation animation = model.animations.Last(); // Read the number of keys in the animation, and set up the structures animation.num_keys = stream.ReadUInt16(); animation.keyframes = new float[animation.num_keys]; animation.bone_animations = new ModelData.BoneAnimation[model.num_bones]; for (uint i = 0; i < model.num_bones; ++i) { animation.bone_animations[i].key_states = new ModelData.AnimationKey[animation.num_keys]; for( uint j = 0; j < animation.num_keys; ++j) animation.bone_animations[i].key_states[j].handles = new ModelData.BezierHandle[10]; } // Read the time frames for each key frame. for (uint key = 0; key < animation.num_keys; ++key) animation.keyframes[key] = stream.ReadSingle(); // Read the keys for each bone and each key type // 10 Key types are position (x,y,z), rotation (w,x,y,z), and scale (x,y,z) foreach(ModelData.BoneAnimation bone in animation.bone_animations) { foreach(ModelData.AnimationKey key in bone.key_states) { for( int i = 0; i < 10; ++i) { key.handles[i].center = stream.ReadSingle(); key.handles[i].left = stream.ReadSingle(); key.handles[i].right = stream.ReadSingle(); } } } }
// ----==== Bone Structure ====---- // private static void loadBoneStructure(StreamReader stream, ModelData model) { uint i, row, col; model.bone_parents = new byte[model.num_bones]; model.inv_bone_matrices = new ModelData.BoneMatrix[model.num_bones]; for (i = 0; i < model.num_bones; ++i) { ASSERT_DELIMETER(stream, "["); readWord(stream); // ignored ASSERT_DELIMETER(stream, "<-"); model.bone_parents[i] = Convert.ToByte(readWord(stream)); ASSERT_DELIMETER(stream, "]"); } for (i = 0; i < model.num_bones; ++i) { // Really, just a terrible language model.inv_bone_matrices[i].a = new float[4, 4]; ASSERT_DELIMETER(stream, "["); for (col = 0; col < 4; ++col) for (row = 0; row < 4; ++row) model.inv_bone_matrices[i].a[row, col] = Convert.ToSingle(readWord(stream)); ASSERT_DELIMETER(stream, "]"); } }
private static void loadAnimation(StreamReader stream, ModelData model) { byte current_bone; uint i,j; ModelData.Animation current_animation = model.animations.Last(); current_animation.num_keys = Convert.ToUInt16(readWord(stream)); current_animation.keyframes = new float[current_animation.num_keys]; current_animation.bone_animations = new ModelData.BoneAnimation[model.num_bones]; for (i = 0; i < model.num_bones; ++i) current_animation.bone_animations[i].key_states = new ModelData.AnimationKey[current_animation.num_keys]; // Read the keyframe positions ASSERT_DELIMETER(stream, "{"); for (i = 0; i < current_animation.num_keys; ++i) { current_animation.keyframes[i] = Convert.ToSingle(readWord(stream)); for (j = 0; j < model.num_bones; ++j) current_animation.bone_animations[j].key_states[i].handles = new ModelData.BezierHandle[10]; } ASSERT_DELIMETER(stream, "}"); // Read fcurve data for (i = 0; i < model.num_bones; ++i) { current_bone = Convert.ToByte( readWord(stream)); // Does it really matter if it's unnordered? // For now I will trust past me and not mess with it if( current_bone != i) throw new Exception(ControlStrings.ErrorBoneMissing); // Forced Order foreach( string anim_type in anim_types) readFCurve(stream, current_animation, current_bone, anim_type); } }
/// <summary> /// Imports a Model stored in RSM Verbose format. Assumes that the stream /// has already seeked past the first 8 bytes and validated the header. /// </summary> private static ModelData importVerboseModel(StreamReader stream) { ModelData model = new ModelData(); try { string word; int int_buffer; // Initialize default model.has_uvs = true; model.num_animations = 0; // Read Header int_buffer = Convert.ToInt32(readWord(stream)); if (int_buffer > 0x9999) throw new Exception("" + int_buffer); model.num_lvertices = (UInt16)int_buffer; int_buffer = Convert.ToInt32(readWord(stream)); if (int_buffer > 0x9999) throw new Exception(ControlStrings.ErrorNumVerts + int_buffer); model.num_dvertices = (UInt16)int_buffer; int_buffer = Convert.ToInt32(readWord(stream)); if (int_buffer > ModelData.MAX_BONES) throw new Exception(ControlStrings.ErrorNumBones + int_buffer); model.num_bones = (byte)int_buffer; // Go through each segment, determine what it is, and load it. while (true) { word = readWord(stream); if (stream.EndOfStream) break; if (word == "") MessageBox.Show(ControlStrings.WarnEmptyString); if (word == "vertex_geometry") readVertexGeometry(stream, model); else if (word == "vertex_collision_normals") readVertexCollisionNormals(stream, model); else if (word == "vertex_weights") readVertexWeights(stream, model); else if (word == "vertex_ids") readVertexIds(stream, model); else if (word == "vertex_light_normals") readVertexLightNormals(stream, model); else if (word == "vertex_uvs") { model.has_uvs = true; readVertexUvs(stream, model); } else if (word == "bone_structure") loadBoneStructure(stream, model); else if (word == "triangle_data") readTriangleData(stream, model); else if (word == "animation_data") { model.animations.Add(new ModelData.Animation()); ++model.num_animations; loadAnimation(stream, model); } else throw new Exception( ControlStrings.ErrorFlag + word); } stream.Close(); } catch (Exception ex) { MessageBox.Show(ex.Message); model = null; } finally { stream.Close(); } return model; }
/// <summary> /// Imports a Model stored in RSM Compressed format. Assumes that the stream /// has already seeked past the first 8 bytes and validated the header. /// </summary> /// <remarks> /// For more information on the RSMc format, see documentation. /// </remarks> private static ModelData importCompressedModel(BinaryReader stream) { ModelData model = new ModelData(); try { // :::: Header Data byte flags = stream.ReadByte(); model.has_uvs = ((flags & 0x01) != 0); model.drawn = ((flags & 0x02) != 0); model.collision = ((flags & 0x04) != 0); model.num_lvertices = stream.ReadUInt16(); if (model.drawn) { model.num_dvertices = stream.ReadUInt16(); model.num_bones = stream.ReadByte(); model.num_animations = stream.ReadUInt16(); // Bone Structure loadBoneStructure( stream, model); } // :::: Logical (geometric) model data if ( model.collision) { model.position = new ModelData.Vector3[model.num_lvertices]; model.collision_normal = new ModelData.Vector3[model.num_lvertices]; for (uint i = 0; i < model.num_lvertices; ++i) { model.position[i].x = stream.ReadSingle(); model.position[i].y = stream.ReadSingle(); model.position[i].z = stream.ReadSingle(); model.collision_normal[i].x = stream.ReadSingle(); model.collision_normal[i].y = stream.ReadSingle(); model.collision_normal[i].z = stream.ReadSingle(); } } else { model.num_lvertices = model.num_dvertices; model.position = new ModelData.Vector3[model.num_dvertices]; } // :::: Drawing model data if (model.drawn) { model.drawn_index = new UInt16[model.num_dvertices]; model.lighting_normal = new ModelData.Vector3[model.num_dvertices]; if (model.has_uvs) model.texture_uvs = new ModelData.Vector2[model.num_dvertices]; if (model.num_bones > 0) model.bone_weights = new ModelData.BoneConnection[model.num_dvertices]; for (uint i = 0; i < model.num_dvertices; ++i) { if (!model.collision) { // Read position from drawn vertex data (only if there // is no collision data) model.position[i].x = stream.ReadSingle(); model.position[i].y = stream.ReadSingle(); model.position[i].z = stream.ReadSingle(); model.drawn_index[i] = (ushort)i; } else { // Read the index which the drawn vertex is linked to model.drawn_index[i] = stream.ReadUInt16(); } model.lighting_normal[i].x = stream.ReadSingle(); model.lighting_normal[i].y = stream.ReadSingle(); model.lighting_normal[i].z = stream.ReadSingle(); if (model.has_uvs) { // Texture coordinates model.texture_uvs[i].u = stream.ReadSingle(); model.texture_uvs[i].v = stream.ReadSingle(); } if (model.num_bones != 0) { // Bone Weights int index = model.drawn_index[i]; model.bone_weights[index].boneid_1 = stream.ReadByte(); model.bone_weights[index].boneid_2 = stream.ReadByte(); model.bone_weights[index].boneid_3 = stream.ReadByte(); model.bone_weights[index].boneid_4 = stream.ReadByte(); model.bone_weights[index].boneweight_1 = stream.ReadSingle(); model.bone_weights[index].boneweight_2 = stream.ReadSingle(); model.bone_weights[index].boneweight_3 = stream.ReadSingle(); model.bone_weights[index].boneweight_4 = stream.ReadSingle(); } } } // :::: Index Data model.num_triangles = stream.ReadUInt16(); if (model.collision) { model.collision_triangles = new ModelData.Triangle[model.num_triangles]; model.ctriangle_normals = new ModelData.Vector3[model.num_triangles]; } if (model.drawn) model.drawn_triangles = new ModelData.Triangle[model.num_triangles]; for (uint i = 0; i < model.num_triangles; ++i) { if (model.collision) { // Collision Triangles model.collision_triangles[i].id_1 = stream.ReadUInt16(); model.collision_triangles[i].id_2 = stream.ReadUInt16(); model.collision_triangles[i].id_3 = stream.ReadUInt16(); model.ctriangle_normals[i].x = stream.ReadSingle(); model.ctriangle_normals[i].y = stream.ReadSingle(); model.ctriangle_normals[i].z = stream.ReadSingle(); } if (model.drawn) { // Drawn Triangles model.drawn_triangles[i].id_1 = stream.ReadUInt16(); model.drawn_triangles[i].id_2 = stream.ReadUInt16(); model.drawn_triangles[i].id_3 = stream.ReadUInt16(); } } // :::: Animation Data if (model.drawn) { for (uint i = 0; i < model.num_animations; ++i) { model.animations.Add(new ModelData.Animation()); loadAnimation( stream, model); } } stream.Close(); } catch (ArithmeticException ex) { model = null; MessageBox.Show(ex.Message); stream.Close(); } return model; }
/// <summary> /// Throws the model data away and clear the statistics. /// </summary> public void disassosiateData() { data = null; collision = false; drawn = false; num_animations = 0; num_bones = 0; num_dvertices = 0; num_lvertices = 0; num_triangles = 0; }
/// <summary> /// Assosciates an already-loaded Model with the given Model container. /// </summary> public void assosciateData( ModelData model_data) { if (data != model_data) context.file_changed = true; data = model_data; checkCapabilities(); collision = model_data.collision; drawn = model_data.drawn; num_animations = model_data.num_animations; num_bones = model_data.num_bones; num_dvertices = model_data.num_dvertices; num_lvertices = model_data.num_lvertices; num_triangles = model_data.num_triangles; if (data != null) data_location = DataLocation.Memory; }