Survivalcraft API 1.8.2.3 v1.8.2.3
Survivalcraft 2.4
载入中...
搜索中...
未找到
Model.cs
浏览该文件的文档.
1using Engine.Media;
2
3namespace Engine.Graphics {
4 public class Model : IDisposable {
6
7 public List<ModelBone> m_bones = [];
8
9 public List<ModelMesh> m_meshes = [];
10
12
13 public ReadOnlyList<ModelBone> Bones => new(m_bones);
14
15 public ReadOnlyList<ModelMesh> Meshes => new(m_meshes);
16
17 public ModelData ModelData { get; set; }
18
19 public ModelBone FindBone(string name, bool throwIfNotFound = true) {
20 foreach (ModelBone bone in m_bones) {
21 if (bone.Name == name) {
22 return bone;
23 }
24 }
25 return throwIfNotFound ? throw new InvalidOperationException("ModelBone not found.") : null;
26 }
27
28 public ModelMesh FindMesh(string name, bool throwIfNotFound = true) {
29 foreach (ModelMesh mesh in m_meshes) {
30 if (mesh.Name == name) {
31 return mesh;
32 }
33 }
34 return throwIfNotFound ? throw new InvalidOperationException("ModelMesh not found.") : null;
35 }
36
37 public ModelBone NewBone(string name, Matrix transform, ModelBone parentBone) {
38 ArgumentNullException.ThrowIfNull(name);
39 if (parentBone == null
40 && m_bones.Count > 0) {
41 throw new InvalidOperationException("There can be only one root bone.");
42 }
43 if (parentBone != null
44 && parentBone.Model != this) {
45 throw new InvalidOperationException("Parent bone must belong to the same model.");
46 }
47 ModelBone modelBone = new() { Model = this, Index = m_bones.Count };
48 m_bones.Add(modelBone);
49 modelBone.Name = name;
50 modelBone.Transform = transform;
51 if (parentBone != null) {
52 modelBone.ParentBone = parentBone;
53 parentBone.m_childBones.Add(modelBone);
54 }
55 else {
56 m_rootBone = modelBone;
57 }
58 return modelBone;
59 }
60
61 public void AddMesh(ModelMesh mesh) {
62 m_meshes.Add(mesh);
63 }
64
65 public ModelMesh NewMesh(string name, ModelBone parentBone, BoundingBox boundingBox) {
66 ArgumentNullException.ThrowIfNull(name);
67 ArgumentNullException.ThrowIfNull(parentBone);
68 return parentBone.Model != this
69 ? throw new InvalidOperationException("Parent bone must belong to the same model.")
70 : new ModelMesh { Name = name, ParentBone = parentBone, BoundingBox = boundingBox };
71 }
72
73 public void CopyAbsoluteBoneTransformsTo(Matrix[] absoluteTransforms) {
74 ArgumentNullException.ThrowIfNull(absoluteTransforms);
75 if (absoluteTransforms.Length < m_bones.Count) {
76 throw new ArgumentOutOfRangeException(nameof(absoluteTransforms));
77 }
78 for (int i = 0; i < m_bones.Count; i++) {
79 ModelBone modelBone = m_bones[i];
80 if (modelBone.ParentBone == null) {
81 absoluteTransforms[i] = modelBone.Transform;
82 }
83 else {
85 ref modelBone.m_transform,
86 ref absoluteTransforms[modelBone.ParentBone.Index],
87 out absoluteTransforms[i]
88 );
89 }
90 }
91 }
92
93 public void CopyAbsoluteBoneTransformsTo(Matrix[] absoluteTransforms, Matrix matrix) {
94 if (absoluteTransforms == null) {
95 throw new ArgumentNullException(nameof(absoluteTransforms));
96 }
97 if (absoluteTransforms.Length < m_bones.Count) {
98 throw new ArgumentOutOfRangeException(nameof(absoluteTransforms));
99 }
100 for (int i = 0; i < m_bones.Count; i++) {
101 ModelBone modelBone = m_bones[i];
102 if (modelBone.ParentBone == null) {
103 Matrix.MultiplyRestricted(ref modelBone.m_transform, ref matrix, out absoluteTransforms[i]);
104 }
105 else {
107 ref modelBone.m_transform,
108 ref absoluteTransforms[modelBone.ParentBone.Index],
109 out absoluteTransforms[i]
110 );
111 }
112 }
113 }
114
115 public BoundingBox CalculateAbsoluteBoundingBox(Matrix[] absoluteTransforms) {
116 ArgumentNullException.ThrowIfNull(absoluteTransforms);
117 if (absoluteTransforms.Length < m_bones.Count) {
118 throw new ArgumentOutOfRangeException(nameof(absoluteTransforms));
119 }
120 BoundingBox result = default;
121 bool flag = false;
122 foreach (ModelMesh mesh in Meshes) {
123 if (flag) {
124 BoundingBox.Transform(ref mesh.m_boundingBox, ref absoluteTransforms[mesh.ParentBone.Index], out BoundingBox result2);
125 result = BoundingBox.Union(result, result2);
126 }
127 else {
128 BoundingBox.Transform(ref mesh.m_boundingBox, ref absoluteTransforms[mesh.ParentBone.Index], out result);
129 flag = true;
130 }
131 }
132 return result;
133 }
134
135 public void Dispose() {
137 }
138
139 public static Model Load(ModelData modelData, bool keepSourceVertexDataInTags = false) {
140 Model model = new();
141 model.Initialize(modelData, keepSourceVertexDataInTags);
142 return model;
143 }
144
145 public static Model Load(Stream stream, bool keepSourceVertexDataInTags = false) => Load(ModelData.Load(stream), keepSourceVertexDataInTags);
146
147 public static Model Load(string fileName, bool keepSourceVertexDataInTags = false) =>
148 Load(ModelData.Load(fileName), keepSourceVertexDataInTags);
149
150 internal void Initialize(ModelData modelData, bool keepSourceVertexDataInTags) {
151 ModelData = modelData;
152 ArgumentNullException.ThrowIfNull(modelData);
154 VertexBuffer[] array = new VertexBuffer[modelData.Buffers.Count];
155 IndexBuffer[] array2 = new IndexBuffer[modelData.Buffers.Count];
156 for (int i = 0; i < modelData.Buffers.Count; i++) {
157 ModelBuffersData modelBuffersData = modelData.Buffers[i];
158 array[i] = new VertexBuffer(
159 modelBuffersData.VertexDeclaration,
160 modelBuffersData.Vertices.Length / modelBuffersData.VertexDeclaration.VertexStride
161 );
162 array[i].SetData(modelBuffersData.Vertices, 0, modelBuffersData.Vertices.Length);
163 array2[i] = new IndexBuffer(IndexFormat.ThirtyTwoBits, modelBuffersData.Indices.Length / 4);
164 array2[i].SetData(modelBuffersData.Indices, 0, modelBuffersData.Indices.Length);
165 if (keepSourceVertexDataInTags) {
166 array[i].Tag = modelBuffersData.Vertices;
167 array2[i].Tag = modelBuffersData.Indices;
168 }
169 }
170 foreach (ModelBoneData bone in modelData.Bones) {
171 NewBone(bone.Name, bone.Transform, bone.ParentBoneIndex >= 0 ? m_bones[bone.ParentBoneIndex] : null);
172 }
173 foreach (ModelMeshData mesh in modelData.Meshes) {
174 ModelMesh modelMesh = NewMesh(mesh.Name, m_bones[mesh.ParentBoneIndex], mesh.BoundingBox);
175 m_meshes.Add(modelMesh);
176 foreach (ModelMeshPartData meshPart in mesh.MeshParts) {
177 modelMesh.NewMeshPart(
178 array[meshPart.BuffersDataIndex],
179 array2[meshPart.BuffersDataIndex],
180 meshPart.StartIndex,
181 meshPart.IndicesCount,
182 meshPart.BoundingBox
183 );
184 }
185 }
186 }
187
189 m_rootBone = null;
190 m_bones.Clear();
191 Utilities.DisposeCollection(m_meshes);
192 }
193 }
194}
List< ModelBone > m_childBones
BoundingBox CalculateAbsoluteBoundingBox(Matrix[] absoluteTransforms)
static Model Load(string fileName, bool keepSourceVertexDataInTags=false)
ModelBone NewBone(string name, Matrix transform, ModelBone parentBone)
static Model Load(Stream stream, bool keepSourceVertexDataInTags=false)
ModelMesh FindMesh(string name, bool throwIfNotFound=true)
List< ModelMesh > m_meshes
定义 Model.cs:9
ModelMesh NewMesh(string name, ModelBone parentBone, BoundingBox boundingBox)
ReadOnlyList< ModelBone > Bones
void AddMesh(ModelMesh mesh)
List< ModelBone > m_bones
定义 Model.cs:7
ModelBone FindBone(string name, bool throwIfNotFound=true)
void Initialize(ModelData modelData, bool keepSourceVertexDataInTags)
static Model Load(ModelData modelData, bool keepSourceVertexDataInTags=false)
void CopyAbsoluteBoneTransformsTo(Matrix[] absoluteTransforms, Matrix matrix)
void CopyAbsoluteBoneTransformsTo(Matrix[] absoluteTransforms)
ReadOnlyList< ModelMesh > Meshes
List< ModelBuffersData > Buffers
List< ModelMeshPartData > MeshParts
static BoundingBox Transform(BoundingBox b, Matrix m)
static BoundingBox Union(BoundingBox b1, BoundingBox b2)
static void MultiplyRestricted(ref Matrix m1, ref Matrix m2, out Matrix result)