public void BasicMeshSerializationTest() { const int VERTICES = 499; const int INDICES = 1009; BasicMesh mesh = new BasicMesh(); mesh.Volume = 42f; mesh.Vertices = new Vector3[VERTICES]; for (int i = 0; i < VERTICES; i++) mesh.Vertices[i] = RandomVector(); mesh.Indices = new ushort[INDICES]; for (int i = 0; i < INDICES; i++) mesh.Indices[i] = (ushort)m_rng.Next(VERTICES); byte[] data = mesh.Serialize(); BasicMesh mesh2 = BasicMesh.Deserialize(data); Assert.AreEqual(mesh.Volume, mesh2.Volume); Assert.AreEqual(mesh.Vertices.Length, mesh2.Vertices.Length); Assert.AreEqual(mesh.Indices.Length, mesh2.Indices.Length); for (int i = 0; i < mesh.Vertices.Length; i++) Assert.AreEqual(mesh.Vertices[i], mesh2.Vertices[i]); for (int i = 0; i < mesh.Indices.Length; i++) Assert.AreEqual(mesh.Indices[i], mesh2.Indices[i]); }
public static BasicMesh Deserialize(byte[] data) { int pos = 0; BasicMesh mesh = new BasicMesh(); mesh.Volume = Utils.BytesToFloat(data, pos); pos += 4; ushort vertexCount = Utils.BytesToUInt16(data, pos); pos += 2; mesh.Vertices = new Vector3[vertexCount]; for (int j = 0; j < vertexCount; j++) { Vector3 v = new Vector3(data, pos); pos += 12; mesh.Vertices[j] = v; } ushort indexCount = Utils.BytesToUInt16(data, pos); pos += 2; mesh.Indices = new ushort[indexCount]; Buffer.BlockCopy(data, pos, mesh.Indices, 0, indexCount * 2); pos += indexCount * 2; return(mesh); }
public void StoreBasicMesh(ulong meshKey, DetailLevel lod, BasicMesh mesh) { UUID dataID = new UUID(meshKey); string contentType = BASIC_MESH_BASE_CONTENT_TYPE + "-" + lod.ToString().ToLower(); byte[] data = mesh.Serialize(); m_dataStore.AddOrUpdateAsset(dataID, contentType, data, true); }
/// <summary> /// Calculates the approximate volume of a scaled mesh /// </summary> /// <param name="mesh">Mesh data</param> /// <param name="scale">Object scale</param> /// <returns>Approximate volume of the mesh</returns> public static float GetMeshVolume(BasicMesh mesh, Vector3 scale) { const float OO_SIX = 1f / 6f; double volume = 0.0f; // Formula adapted from Stan Melax's algorithm: <http://www.melax.com/volint.html> for (int i = 0; i < mesh.Indices.Length; i += 3) { Vector3 v0 = mesh.Vertices[mesh.Indices[i + 0]]; Vector3 v1 = mesh.Vertices[mesh.Indices[i + 1]]; Vector3 v2 = mesh.Vertices[mesh.Indices[i + 2]]; volume += Determinant3x3(v0, v1, v2); } return((float)(volume * OO_SIX) * scale.X * scale.Y * scale.Z); }
public static bool CollisionTest(Ray ray, IPhysical obj, BasicMesh mesh, out float dist) { Vector3 start = new Vector3(ray.X, ray.Y, ray.Z); Vector3 direction = new Vector3(ray.I, ray.J, ray.K); dist = Single.MaxValue; // Construct a matrix to transform to scene space Matrix4 transform = Matrix4.Identity; transform *= Matrix4.CreateScale(obj.Scale); transform *= Matrix4.CreateFromQuaternion(obj.RelativeRotation); transform *= Matrix4.CreateTranslation(obj.RelativePosition); ILinkable parent = obj.Parent; if (parent != null) { // Apply parent rotation and translation transform *= Matrix4.CreateFromQuaternion(parent.RelativeRotation); transform *= Matrix4.CreateTranslation(parent.RelativePosition); } // Iterate through all of the triangles in the mesh, doing a ray-triangle intersection for (int i = 0; i < mesh.Indices.Length; i += 3) { Vector3 point0 = mesh.Vertices[mesh.Indices[i + 0]] * transform; Vector3 point1 = mesh.Vertices[mesh.Indices[i + 1]] * transform; Vector3 point2 = mesh.Vertices[mesh.Indices[i + 2]] * transform; float thisDist; if (RayTriangle.CollisionTestCull(start, direction, point0, point1, point2, out thisDist)) { if (thisDist < dist) { dist = thisDist; } } } return(dist < Single.MaxValue); }
public bool TryGetBasicMesh(ulong meshKey, DetailLevel lod, out BasicMesh mesh) { UUID dataID = new UUID(meshKey); string contentType = BASIC_MESH_BASE_CONTENT_TYPE + "-" + LOD_NAMES[(int)lod]; mesh = null; byte[] meshData; if (m_dataStore.TryGetAsset(dataID, contentType, out meshData)) { try { mesh = BasicMesh.Deserialize(meshData); } catch (Exception ex) { m_log.WarnFormat("Failed to deserialize basic mesh {0} ({1}): {2}", dataID, contentType, ex.Message); } } return(mesh != null); }
public static bool CollisionTest(Ray ray, IPhysical obj, BasicMesh mesh, out float dist) { Vector3 start = new Vector3(ray.X, ray.Y, ray.Z); Vector3 direction = new Vector3(ray.I, ray.J, ray.K); dist = Single.MaxValue; // Construct a matrix to transform to scene space Matrix4 transform = Matrix4.Identity; transform *= Matrix4.CreateScale(obj.Scale); transform *= Matrix4.CreateFromQuaternion(obj.RelativeRotation); transform *= Matrix4.CreateTranslation(obj.RelativePosition); ILinkable parent = obj.Parent; if (parent != null) { // Apply parent rotation and translation transform *= Matrix4.CreateFromQuaternion(parent.RelativeRotation); transform *= Matrix4.CreateTranslation(parent.RelativePosition); } // Iterate through all of the triangles in the mesh, doing a ray-triangle intersection for (int i = 0; i < mesh.Indices.Length; i += 3) { Vector3 point0 = mesh.Vertices[mesh.Indices[i + 0]] * transform; Vector3 point1 = mesh.Vertices[mesh.Indices[i + 1]] * transform; Vector3 point2 = mesh.Vertices[mesh.Indices[i + 2]] * transform; float thisDist; if (RayTriangle.CollisionTestCull(start, direction, point0, point1, point2, out thisDist)) { if (thisDist < dist) dist = thisDist; } } return dist < Single.MaxValue; }
/// <summary> /// Calculates the approximate volume of a scaled mesh /// </summary> /// <param name="mesh">Mesh data</param> /// <param name="scale">Object scale</param> /// <returns>Approximate volume of the mesh</returns> public static float GetMeshVolume(BasicMesh mesh, Vector3 scale) { const float OO_SIX = 1f / 6f; double volume = 0.0f; // Formula adapted from Stan Melax's algorithm: <http://www.melax.com/volint.html> for (int i = 0; i < mesh.Indices.Length; i += 3) { Vector3 v0 = mesh.Vertices[mesh.Indices[i + 0]]; Vector3 v1 = mesh.Vertices[mesh.Indices[i + 1]]; Vector3 v2 = mesh.Vertices[mesh.Indices[i + 2]]; volume += Determinant3x3(v0, v1, v2); } return (float)(volume * OO_SIX) * scale.X * scale.Y * scale.Z; }
public static BasicMesh Deserialize(byte[] data) { int pos = 0; BasicMesh mesh = new BasicMesh(); mesh.Volume = Utils.BytesToFloat(data, pos); pos += 4; ushort vertexCount = Utils.BytesToUInt16(data, pos); pos += 2; mesh.Vertices = new Vector3[vertexCount]; for (int j = 0; j < vertexCount; j++) { Vector3 v = new Vector3(data, pos); pos += 12; mesh.Vertices[j] = v; } ushort indexCount = Utils.BytesToUInt16(data, pos); pos += 2; mesh.Indices = new ushort[indexCount]; Buffer.BlockCopy(data, pos, mesh.Indices, 0, indexCount * 2); pos += indexCount * 2; return mesh; }
public bool TryGetBasicMesh(ulong meshKey, DetailLevel lod, out BasicMesh mesh) { UUID dataID = new UUID(meshKey); string contentType = BASIC_MESH_BASE_CONTENT_TYPE + "-" + LOD_NAMES[(int)lod]; mesh = null; byte[] meshData; if (m_dataStore.TryGetAsset(dataID, contentType, out meshData)) { try { mesh = BasicMesh.Deserialize(meshData); } catch (Exception ex) { m_log.WarnFormat("Failed to deserialize basic mesh {0} ({1}): {2}", dataID, contentType, ex.Message); } } return (mesh != null); }