protected override void OnEnabledInHierarchyChanged() { base.OnEnabledInHierarchyChanged(); if (EnabledInHierarchy) { //get free camera initial settings if (EngineApp.ApplicationType == EngineApp.ApplicationTypeEnum.Simulation) { var scene = Parent as Component_Scene; if (scene != null) { Component_Camera camera = scene.CameraDefault; if (camera == null) { camera = scene.Mode.Value == Component_Scene.ModeEnum._2D ? scene.CameraEditor2D : scene.CameraEditor; } if (camera != null) { var tr = camera.TransformV; freeCameraPosition = tr.Position; freeCameraDirection = SphericalDirection.FromVector(tr.Rotation.GetForward()); } } } } }
public static void Multiply(ref SphericalDirection d, ref Quaternion q, out SphericalDirection result) { Vector3 vector; d.GetVector(out vector); Vector3 vector2; Quaternion.Multiply(ref vector, ref q, out vector2); SphericalDirection.FromVector(ref vector2, out result); }
protected override void OnEnabledInHierarchyChanged() { base.OnEnabledInHierarchyChanged(); if (EnabledInHierarchy) { var character = Character; if (character != null) { //get initial look direction lookDirection = SphericalDirection.FromVector(character.TransformV.Rotation.GetForward()); } } }
public static void GenerateIcoSphere(double radius, int subdivisions, bool insideOut, out Vector3[] positions, out Vector3[] normals, out Vector4[] tangents, out Vector2[] texCoords, out int[] indices, out Face[] faces) { var faceCount = 20; // 20 faces, icosahedronIndexes.Length / 3 var vCount = 12; // 12 vertices var divCount = subdivisions; /* /\ * / \ * /____\ * /\ /\ * / \ / \ * /____\/____\ */ while (divCount-- > 0) { // 3 new vetices for each face vCount += faceCount * 3; // subdivide each face by 4 new ones faceCount *= 4; } List <int> vertexIndexList; //viList.count == pList.Count (the vertex index of element in pList) var pList = new List <Vector3>(vCount); var nList = new List <Vector3>(vCount); var tList = new List <Vector4>(vCount); var txList = new List <Vector2>(vCount); var indexList = new List <int>(icosahedronIndexes); var t = (1.0 + Math.Sqrt(5.0)) / 2.0; //icosahedron nList.Add(new Vector3(-1, t, 0).GetNormalize()); nList.Add(new Vector3(1, t, 0).GetNormalize()); nList.Add(new Vector3(-1, -t, 0).GetNormalize()); nList.Add(new Vector3(1, -t, 0).GetNormalize()); nList.Add(new Vector3(0, -1, t).GetNormalize()); nList.Add(new Vector3(0, 1, t).GetNormalize()); nList.Add(new Vector3(0, -1, -t).GetNormalize()); nList.Add(new Vector3(0, 1, -t).GetNormalize()); nList.Add(new Vector3(t, 0, -1).GetNormalize()); nList.Add(new Vector3(t, 0, 1).GetNormalize()); nList.Add(new Vector3(-t, 0, -1).GetNormalize()); nList.Add(new Vector3(-t, 0, 1).GetNormalize()); foreach (var n in nList) { pList.Add(n * radius); } //!!!!GC var cache = new Dictionary <long, int>(); // Refine faces for (int iter = 0; iter < subdivisions; iter++) { var newindices = new List <int>(indexList.Count / 3 * 12); for (int i = 0; i < indexList.Count / 3; i++) { var i1 = indexList[i * 3]; var i2 = indexList[i * 3 + 1]; int i3 = indexList[i * 3 + 2]; // get mid points int a = CreateMiddlePoint(pList, i1, i2, cache, radius, nList); int b = CreateMiddlePoint(pList, i2, i3, cache, radius, nList); int c = CreateMiddlePoint(pList, i3, i1, cache, radius, nList); //Push 4 triangles newindices.Add(i1); newindices.Add(a); newindices.Add(c); newindices.Add(i2); newindices.Add(b); newindices.Add(a); newindices.Add(i3); newindices.Add(c); newindices.Add(b); newindices.Add(a); newindices.Add(b); newindices.Add(c); } indexList = newindices; } //tangents and texcoords { var rotationMatrix = new Matrix3(0, -1, 0, 1, 0, 0, 0, 0, 1); for (int n = 0; n < nList.Count; n++) { var p = nList[n]; var rot = Quaternion.FromDirectionZAxisUp(p).ToMatrix3() * rotationMatrix; Vector4 tan; if (insideOut) { tan = new Vector4(rot * Vector3.XAxis, -1); } else { tan = new Vector4(rot * -Vector3.XAxis, -1); } tList.Add(tan); var dir = SphericalDirection.FromVector(p); var tx = new Vector2( dir.Horizontal / (MathEx.PI * 2) * 2, // [-1..1] -dir.Vertical / MathEx.PI + 0.5); // [0..1] //var tx = new Vec2( // ( 0.5 - Math.Atan2( p.X, p.Z ) / Math.PI * 2 ), // ( 0.5 - Math.Asin( p.Y ) / Math.PI )); txList.Add(tx); } } bool upUsed = false; bool downUsed = false; //all the vertices in pList now have the unique positions. No more unique positions. vertexIndexList = new List <int>(pList.Count); for (int i = 0; i < pList.Count; i++) { vertexIndexList.Add(i); } // Correct poles. for (int i = 0; i < indexList.Count; i += 3) { var vidx1 = indexList[i]; var vidx2 = indexList[i + 1]; var vidx3 = indexList[i + 2]; var n1 = nList[vidx1]; var n2 = nList[vidx2]; var n3 = nList[vidx3]; if (Math.Abs(n1.Z) == 1) { var dirUp = SphericalDirection.FromVector(n1); var mid = (pList[vidx2] + pList[vidx3]) * .5; var dir = SphericalDirection.FromVector(Vector3.Normalize(mid)); dir.Vertical = dirUp.Vertical; var txt = new Vector2( dir.Horizontal / (MathEx.PI * 2) * 2, // [-1..1] -dir.Vertical / MathEx.PI + 0.5); // [0..1] var update = false; if (n1.Z == 1 && !upUsed) //up { update = true; upUsed = true; } if (n1.Z == -1 && !downUsed) //down { update = true; downUsed = true; } if (update) { txList[vidx1] = txt; } else { // vertex1 is new pole, duplicate it and update the face. //newVertexIndex = pList.Count; indexList[i] = pList.Count; pList.Add(pList[vidx1]); vertexIndexList.Add(vertexIndexList[vidx1]); nList.Add(nList[vidx1]); tList.Add(tList[vidx1]); txList.Add(txt); } } else if (Math.Abs(n2.Z) == 1) { var dirUp = SphericalDirection.FromVector(n2); var mid = (pList[vidx1] + pList[vidx3]) * .5; var dir = SphericalDirection.FromVector(Vector3.Normalize(mid)); dir.Vertical = dirUp.Vertical; var txt = new Vector2( dir.Horizontal / (MathEx.PI * 2) * 2, // [-1..1] -dir.Vertical / MathEx.PI + 0.5); // [0..1] var update = false; if (n1.Z == 1 && !upUsed) //up { update = true; upUsed = true; } if (n1.Z == -1 && !downUsed) //down { update = true; downUsed = true; } if (update) { txList[vidx2] = txt; } else { // vertex2 is new pole, duplicate it and update the face. //newVertexIndex = pList.Count; indexList[i + 1] = pList.Count; pList.Add(pList[vidx2]); vertexIndexList.Add(vertexIndexList[vidx2]); nList.Add(nList[vidx2]); tList.Add(tList[vidx2]); txList.Add(txt); } } else if (Math.Abs(n3.Z) == 1) { var dirUp = SphericalDirection.FromVector(n3); var mid = (pList[vidx1] + pList[vidx2]) * .5; var dir = SphericalDirection.FromVector(Vector3.Normalize(mid)); dir.Vertical = dirUp.Vertical; var txt = new Vector2( dir.Horizontal / (MathEx.PI * 2) * 2, // [-1..1] -dir.Vertical / MathEx.PI + 0.5); // [0..1] var update = false; if (n1.Z == 1 && !upUsed) //up { update = true; upUsed = true; } if (n1.Z == -1 && !downUsed) //down { update = true; downUsed = true; } if (update) { txList[vidx3] = txt; } else { // vertex3 is new pole, duplicate it and update the face. //newVertexIndex = pList.Count; indexList[i + 2] = pList.Count; pList.Add(pList[vidx3]); vertexIndexList.Add(vertexIndexList[vidx3]); nList.Add(nList[vidx3]); tList.Add(tList[vidx3]); txList.Add(txt); } } } //!!!!GC var correctionMap = new Dictionary <int, int>(); //correct seam for (int i = indexList.Count - 3; i >= 0; i -= 3) { var v0 = new Vector3(txList[indexList[i + 0]], 0); var v1 = new Vector3(txList[indexList[i + 1]], 0); var v2 = new Vector3(txList[indexList[i + 2]], 0); var cross = Vector3.Cross(v0 - v1, v2 - v1); if (cross.Z <= 0) //test if the face crosses a texture boundary. { for (var j = i; j < i + 3; j++) { var index = indexList[j]; var texCoord = txList[index]; var shift = 0.0; if (texCoord.X >= .8) { shift = -2; } //if( texCoord.X <= -.8 ) // shift = 2; if (shift == 0) { continue; } if (correctionMap.ContainsKey(index)) { indexList[j] = correctionMap[index]; } else { texCoord.X += shift; txList.Add(texCoord); pList.Add(pList[index]); vertexIndexList.Add(vertexIndexList[index]); nList.Add(nList[index]); tList.Add(tList[index]); var correctedVertexIndex = txList.Count - 1; correctionMap.Add(index, correctedVertexIndex); indexList[j] = correctedVertexIndex; } } } } positions = pList.ToArray(); normals = nList.ToArray(); tangents = tList.ToArray(); texCoords = txList.ToArray(); indices = indexList.ToArray(); if (insideOut) { var idx = 0; while (idx < indices.Length) { var temp = indices[idx + 1]; indices[idx + 1] = indices[idx + 2]; indices[idx + 2] = temp; idx += 3; } idx = 0; while (idx < normals.Length) { Vector3.Negate(ref normals[idx], out normals[idx]); idx++; } for (int n = 0; n < texCoords.Length; n++) { texCoords[n] = new Vector2(1.0f - texCoords[n].X, texCoords[n].Y); } } const int rawVerticesInFace = 3; faces = new Face[indices.Length / rawVerticesInFace]; for (int i = 0; i < indices.Length; i += rawVerticesInFace) { faces[i / 3] = new Face(new FaceVertex[] { new FaceVertex(vertexIndexList[indices[i]], indices[i]), new FaceVertex(vertexIndexList[indices[i + 1]], indices[i + 1]), new FaceVertex(vertexIndexList[indices[i + 2]], indices[i + 2]), }); } //faces = new Face[ indices.Length / rawVerticesInFace ]; //int curTriangle = 0; //int curFace = 0; //FaceVertex[] faceTriangles = null; //for( int i = 0; i < indices.Length; i++ ) //{ // if( faceTriangles == null ) // { // faceTriangles = new FaceVertex[ rawVerticesInFace ]; // curTriangle = 0; // } // faceTriangles[ curTriangle++ ] = new FaceVertex( vertexIndexList[ indices[ i ] ], indices[ i ] ); // if( curTriangle == rawVerticesInFace ) // { // faces[ curFace++ ] = new Face( faceTriangles ); // faceTriangles = null; // } //} }