/// <summary> /// Transforms a vector by a quaternion rotation. /// </summary> /// <param name="vec">The vector to transform.</param> /// <param name="quat">The quaternion to rotate the vector by.</param> /// <param name="result">The result of the operation.</param> public static void QuaternionTransform(ref Float3 vec, ref Float4 quat, out Float3 result) { // Since vec.W == 0, we can optimize quat * vec * quat^-1 as follows: // vec + 2.0 * cross(quat.xyz, cross(quat.xyz, vec) + quat.w * vec) Float3 xyz = quat.Xyz, temp, temp2; Float3.Cross(ref xyz, ref vec, out temp); Float3.Multiply(ref vec, quat.W, out temp2); Float3.Add(ref temp, ref temp2, out temp); Float3.Cross(ref xyz, ref temp, out temp); Float3.Multiply(ref temp, 2, out temp); Float3.Add(ref vec, ref temp, out result); }
public int GetLeaf(ref Float3 pos, int model) { int nodeId = this.Models[model].RootNode; float side; for (; nodeId >= 0;) { side = Float3.Dot(ref pos, ref this.Nodes[nodeId].N) - this.Nodes[nodeId].D; if (side > 0) { nodeId = this.Nodes[nodeId].PositiveNodeIndex; } else { nodeId = this.Nodes[nodeId].NegativeNodeIndex; } } return -1 - nodeId; }
/// <summary> /// Convert the current quaternion to axis angle representation /// </summary> /// <param name="axis">The resultant axis</param> /// <param name="angle">The resultant angle</param> public static void ToAxisAngle(Float4 quaternion, out Float3 axis, out float angle) { var q = quaternion; if (Math.Abs(q.W) > 1.0f) q.Normalize(); angle = 2.0f * (float)System.Math.Acos(q.W); // angle float den = (float)System.Math.Sqrt(1.0 - q.W * q.W); if (den > 0.0001f) { axis = MathHelper.Scale(q.Xyz, 1.0f / den); } else { // This occurs when the angle is zero. // Not a problem: just set an arbitrary normalized axis. axis = Float3.UnitX; } }
/// <summary> /// Caclulate the cross (vector) product of two vectors /// </summary> /// <param name="left">First operand</param> /// <param name="right">Second operand</param> /// <returns>The cross product of the two inputs</returns> public static Float3 Cross(Float3 left, Float3 right) { Float3 result; Cross(ref left, ref right, out result); return result; }
/// <summary> /// Creates a translation matrix. /// </summary> /// <param name="vector">The translation vector.</param> /// <returns>The resulting Matrix4 instance.</returns> public static Float4x4 CreateTranslation(Float3 vector) { Float4x4 result; CreateTranslation(vector.X, vector.Y, vector.Z, out result); return result; }
/// <summary> /// Creates a translation matrix. /// </summary> /// <param name="vector">The translation vector.</param> /// <param name="result">The resulting Matrix4 instance.</param> public static void CreateTranslation(ref Float3 vector, out Float4x4 result) { result = Identity; result.Row3 = new Float4(vector.X, vector.Y, vector.Z, 1); }
/// <summary> /// Build a rotation matrix from the specified axis/angle rotation. /// </summary> /// <param name="axis">The axis to rotate about.</param> /// <param name="angle">Angle in radians to rotate counter-clockwise (looking in the direction of the given axis).</param> /// <param name="result">A matrix instance.</param> public static void CreateFromAxisAngle(Float3 axis, float angle, out Float4x4 result) { float cos = (float)System.Math.Cos(-angle); float sin = (float)System.Math.Sin(-angle); float t = 1.0f - cos; axis.Normalize(); result = new Float4x4(t * axis.X * axis.X + cos, t * axis.X * axis.Y - sin * axis.Z, t * axis.X * axis.Z + sin * axis.Y, 0.0f, t * axis.X * axis.Y + sin * axis.Z, t * axis.Y * axis.Y + cos, t * axis.Y * axis.Z - sin * axis.X, 0.0f, t * axis.X * axis.Z - sin * axis.Y, t * axis.Y * axis.Z + sin * axis.X, t * axis.Z * axis.Z + cos, 0.0f, 0, 0, 0, 1); }
/// <summary> /// Build a rotation matrix from the specified axis/angle rotation. /// </summary> /// <param name="axis">The axis to rotate about.</param> /// <param name="angle">Angle in radians to rotate counter-clockwise (looking in the direction of the given axis).</param> /// <returns>A matrix instance.</returns> public static Float4x4 CreateFromAxisAngle(Float3 axis, float angle) { Float4x4 result; CreateFromAxisAngle(axis, angle, out result); return result; }
public BoundingBox(Float3 min, Float3 max) { this.min = min; this.max = max; }
/// <summary> /// Caclulate the cross (vector) product of two vectors /// </summary> /// <param name="left">First operand</param> /// <param name="right">Second operand</param> /// <returns>The cross product of the two inputs</returns> /// <param name="result">The cross product of the two inputs</param> public static void Cross(ref Float3 left, ref Float3 right, out Float3 result) { result = new Float3(left.Y * right.Z - left.Z * right.Y, left.Z * right.X - left.X * right.Z, left.X * right.Y - left.Y * right.X); }
public static void ReadFloat3(this Stream stream, out Float3 v) { v.X = stream.ReadSingle(); v.Y = stream.ReadSingle(); v.Z = stream.ReadSingle(); if (float.IsInfinity(v.X) || float.IsInfinity(v.Y) || float.IsInfinity(v.Z)) { throw new BspFormatException(string.Format("Wrong vertex data {{{0}, {1}, {2}}}", v.X, v.Y, v.Z)); } }
/// <summary> /// Transforms a vector by a quaternion rotation. /// </summary> /// <param name="vec">The vector to transform.</param> /// <param name="quat">The quaternion to rotate the vector by.</param> public static Float3 QuaternionTransform(Float3 vec, Float4 quat) { Float3 res; QuaternionTransform(ref vec, ref quat, out res); return res; }
private IMeshStream CreateMeshStream(ISource source, string semantic) { var floatArray = source as FloatArraySource; if (floatArray != null) { bool swapY = (semantic == Streams.TexCoord); if (source.GetStride() == 3) { var arrayMeshStream = new ArrayMeshStream<Float3>(source.GetCount(), streamConverterFactory); for (int i = 0; i < arrayMeshStream.Count; ++i) { var y = floatArray[i * 3 + 1]; if (swapY) y = 1.0f - y; arrayMeshStream[i] = new Float3(floatArray[i * 3 + 0], y, floatArray[i * 3 + 2]); } return arrayMeshStream; } else if (source.GetStride() == 2) { var arrayMeshStream = new ArrayMeshStream<Float2>(source.GetCount(), streamConverterFactory); for (int i = 0; i < arrayMeshStream.Count; ++i) { var y = floatArray[i * 2 + 1]; if (swapY) y = 1.0f - y; arrayMeshStream[i] = new Float2(floatArray[i * 2 + 0], y); } return arrayMeshStream; } else if (source.GetStride() == 4) { var arrayMeshStream = new ArrayMeshStream<Float4>(source.GetCount(), streamConverterFactory); for (int i = 0; i < arrayMeshStream.Count; ++i) { var y = floatArray[i * 4 + 1]; if (swapY) y = 1.0f - y; arrayMeshStream[i] = new Float4(floatArray[i * 4 + 0], y, floatArray[i * 4 + 2], floatArray[i * 4 + 3]); } return arrayMeshStream; } } else { throw new NotImplementedException(); } throw new NotImplementedException(); }
private Float3 ParseVec3EntityProperty(string val) { var v = val.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); Float3 res = new Float3(); res.X = float.Parse(v[0], CultureInfo.InvariantCulture); res.Y = float.Parse(v[1], CultureInfo.InvariantCulture); res.Z = float.Parse(v[2], CultureInfo.InvariantCulture); return res; }
private static Vertex BuildVertex(Float3[] vertices, int index0, FaceNormal[] normals, int faceIndex, int vertexAtFace, AseTFace[] tfaces, Color[] c, Float3[] tvertices, Tuple<int, int, int>[] colFaces, Float3 uv) { Vertex v = new Vertex { Position = vertices[index0] }; if (normals != null) { v.Normal = normals[faceIndex].GetNormal(index0); } if (colFaces != null) { switch (vertexAtFace) { case 0: v.Color = c[colFaces[faceIndex].Item1]; break; case 1: v.Color = c[colFaces[faceIndex].Item2]; break; case 2: v.Color = c[colFaces[faceIndex].Item3]; break; } } else { v.Color = Color.FromArgb(255, 255, 255, 255); } v.UV1 = v.UV0 = new Float3(uv.X, 1.0f - uv.Y, uv.Z); return v; }
private void ParsNormalList(AseParser parser, FaceNormal[] normals) { int faceIndex = 0; int faceVertexIndex = 0; parser.Consume("{"); for (;;) { var attr = parser.Consume(); if (attr == null || attr == "}") { break; } if (0 == string.Compare(attr, "*MESH_FACENORMAL", StringComparison.InvariantCultureIgnoreCase)) { faceIndex = parser.ConsumeInt(); var x = parser.ConsumeFloat(); var y = parser.ConsumeFloat(); var z = parser.ConsumeFloat(); normals[faceIndex].A.Normal = normals[faceIndex].B.Normal = normals[faceIndex].C.Normal = normals[faceIndex].Normal = new Float3(x, y, z); faceVertexIndex = 0; continue; } if (0 == string.Compare(attr, "*MESH_VERTEXNORMAL", StringComparison.InvariantCultureIgnoreCase)) { var index = parser.ConsumeInt(); var x = parser.ConsumeFloat(); var y = parser.ConsumeFloat(); var z = parser.ConsumeFloat(); Float3 v = new Float3(x, y, z); switch (faceVertexIndex) { case 0: normals[faceIndex].A.Index = index; normals[faceIndex].A.Normal = v; break; case 1: normals[faceIndex].B.Index = index; normals[faceIndex].B.Normal = v; break; case 2: normals[faceIndex].C.Index = index; normals[faceIndex].C.Normal = v; break; } ++faceVertexIndex; continue; } parser.UnknownLexemError(); } }
private void ParseVertexList(AseParser parser, IList<Float3> vertices) { parser.Consume("{"); for (;;) { var attr = parser.Consume(); if (attr == null || attr == "}") { break; } if (0 == string.Compare(attr, "*MESH_VERTEX", StringComparison.InvariantCultureIgnoreCase)) { var index = parser.ConsumeInt(); var x = parser.ConsumeFloat(); var y = parser.ConsumeFloat(); var z = parser.ConsumeFloat(); vertices[index] = new Float3(x, y, z); continue; } parser.UnknownLexemError(); } }
//private void BuildSubmeshes(int maxTextures) //{ // int[] textureToMaterial = new int[maxTextures]; // foreach (var quake3Face in this.faces) // { // ++textureToMaterial[this.texInfo[quake3Face.texinfo].texdata]; // } // for (int i = 0; i < maxTextures; ++i) // { // if (textureToMaterial[i] > 0) // { // int index = this.Scene.Materials.Count; // var baseFileName = this.GetMaterialFileName(i); // var imagePath = baseFileName; // var texture = new FileReferenceImage { Path = imagePath }; // this.Scene.Images.Add(texture); // var effect = new SceneEffect // { // //Diffuse = new ImageColorSource { Image = texture } // }; // this.Scene.Effects.Add(effect); // var sceneMaterial = new SceneMaterial { Effect = effect }; // this.Scene.Materials.Add(sceneMaterial); // submeshes[i].Material = sceneMaterial; // textureToMaterial[i] = index; // } // } //} //private void BuildVisibilityList() //{ // for (int i = 0; i < leaves.Length; ++i) // { // Dictionary<int, bool> map = new Dictionary<int, bool>(); // if (leaves[i].cluster >= 0) // foreach (var c in clusters[leaves[i].cluster].visiblity) // foreach (var l in clusters[c].lists) // map[l] = true; // leaves[i].VisibleLeaves = new List<int>(); // foreach (var j in map.Keys) // if (i != j) // leaves[i].VisibleLeaves.Add(j); // } //} private void BuildVertex(Float3 vector3, Float3 n, SourceFace f, ref SourceTexInfo surf, out Vertex res) { res = new Vertex { Position = vector3, Normal = n, Color = Color.White, UV0 = new Float3( Float3.Dot(surf.vectorS, vector3) + surf.distS, Float3.Dot(surf.vectorT, vector3) + surf.distT, 0.0f), UV1 = new Float3( Float3.Dot(surf.lm_vectorS, vector3) + surf.lm_distS - f.LightmapTextureMinsInLuxels[0], Float3.Dot(surf.lm_vectorT, vector3) + surf.lm_distT - f.LightmapTextureMinsInLuxels[1], 0.0f) }; //if (f.LightmapTextureSizeInLuxels[0] == 0) res.UV1.X = (res.UV1.X + this.safeOffset) / (f.LightmapTextureSizeInLuxels[0] + 1.0f + this.safeBorderWidth); res.UV1.Y = (res.UV1.Y + this.safeOffset) / (f.LightmapTextureSizeInLuxels[1] + 1.0f + this.safeBorderWidth); SourceTexData tex = this.textures[surf.texdata]; res.UV0 = new Float3( res.UV0.X / ((tex.width != 0) ? tex.width : 256.0f), res.UV0.Y / ((tex.height != 0) ? tex.height : 256.0f), 0.0f); }
public BoundingBox Union(Float3 vertex) { return new BoundingBox( new Float3(Math.Min(min.X, vertex.X), Math.Min(min.Y, vertex.Y), Math.Min(min.Z, vertex.Z)), new Float3(Math.Max(max.X, vertex.X), Math.Max(max.Y, vertex.Y), Math.Max(max.Z, vertex.Z)) ); }