public static SphericalDirection Multiply(SphericalDirection d, Quaternion q) { SphericalDirection result; Multiply(ref d, ref q, out result); return(result); }
public static SphericalDirection Negate(SphericalDirection v) { SphericalDirection result; Negate(ref v, out result); return(result); }
public static SphericalDirection Add(SphericalDirection v1, SphericalDirection v2) { SphericalDirection result; Add(ref v1, ref v2, out result); return(result); }
public static SphericalDirection Subtract(SphericalDirection v1, SphericalDirection v2) { SphericalDirection result; Subtract(ref v1, ref v2, out result); return(result); }
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 FromVector(ref Vector3 dir, out SphericalDirection result) { result.Horizontal = Math.Atan2(dir.Y, dir.X); double dir2Length = Math.Sqrt(dir.X * dir.X + dir.Y * dir.Y); result.Vertical = Math.Atan2(dir.Z, dir2Length); }
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); }
public bool Equals(SphericalDirection v, double epsilon) { if (Math.Abs(Horizontal - v.Horizontal) > epsilon) { return(false); } if (Math.Abs(Vertical - v.Vertical) > epsilon) { return(false); } return(true); }
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()); } } }
protected override void OnUpdate(float delta) { base.OnUpdate(delta); //moving free camera by keys if (FreeCamera && !EngineConsole.Active && InputEnabled) { double cameraVelocity = IsKeyPressed(EKeys.Shift) ? FreeCameraSpeedFast : FreeCameraSpeedNormal; var step = cameraVelocity * delta; var pos = freeCameraPosition; var dir = freeCameraDirection; if (IsKeyPressed(EKeys.W) || IsKeyPressed(EKeys.Up) || IsKeyPressed(EKeys.NumPad8)) { pos += dir.GetVector() * step; } if (IsKeyPressed(EKeys.S) || IsKeyPressed(EKeys.Down) || IsKeyPressed(EKeys.NumPad2)) { pos -= dir.GetVector() * step; } if (IsKeyPressed(EKeys.A) || IsKeyPressed(EKeys.Left) || IsKeyPressed(EKeys.NumPad4)) { pos += new SphericalDirection(dir.Horizontal + Math.PI / 2, 0).GetVector() * step; } if (IsKeyPressed(EKeys.D) || IsKeyPressed(EKeys.Right) || IsKeyPressed(EKeys.NumPad6)) { pos += new SphericalDirection(dir.Horizontal - Math.PI / 2, 0).GetVector() * step; } if (IsKeyPressed(EKeys.E)) { pos += new SphericalDirection(dir.Horizontal, dir.Vertical + Math.PI / 2).GetVector() * step; } if (IsKeyPressed(EKeys.Q)) { pos += new SphericalDirection(dir.Horizontal, dir.Vertical - Math.PI / 2).GetVector() * step; } freeCameraPosition = pos; } if (freeCameraMouseRotating && !FreeCamera) { freeCameraMouseRotating = false; freeCameraMouseRotatingActivated = false; } }
public static void Subtract(ref SphericalDirection v1, ref SphericalDirection v2, out SphericalDirection result) { result.Horizontal = v1.Horizontal - v2.Horizontal; result.Vertical = v1.Vertical - v2.Vertical; }
public SphericalDirection(SphericalDirection source) { Horizontal = source.Horizontal; Vertical = source.Vertical; }
public virtual Viewport.CameraSettingsClass GetCameraSettings(Viewport viewport, Component_Camera cameraDefault) { Viewport.CameraSettingsClass result = null; GetCameraSettingsEvent?.Invoke(this, viewport, cameraDefault, ref result); if (result == null) { if (FreeCamera) { //free camera result = new Viewport.CameraSettingsClass(viewport, cameraDefault.AspectRatio, cameraDefault.FieldOfView, cameraDefault.NearClipPlane, cameraDefault.FarClipPlane, freeCameraPosition, freeCameraDirection.GetVector(), Vector3.ZAxis, ProjectionType.Perspective, 1, cameraDefault.Exposure, cameraDefault.EmissiveFactor); } else if (UseBuiltInCamera.Value == BuiltInCameraEnum.FirstPerson) { //first person camera //Character var character = ObjectControlledByPlayer.Value as Component_Character; if (character != null) { character.GetFirstPersonCameraPosition(out var position, out var forward, out var up); var eyePosition = character.TransformV * character.EyePosition.Value; var direction = character.LookToDirection.GetVector(); result = new Viewport.CameraSettingsClass(viewport, cameraDefault.AspectRatio, cameraDefault.FieldOfView, cameraDefault.NearClipPlane, cameraDefault.FarClipPlane, eyePosition, direction, up, ProjectionType.Perspective, 1, cameraDefault.Exposure, cameraDefault.EmissiveFactor); } } else if (UseBuiltInCamera.Value == BuiltInCameraEnum.ThirdPerson) { //third person camera //Character if (Scene.Mode.Value == Component_Scene.ModeEnum._3D) { var character = ObjectControlledByPlayer.Value as Component_Character; if (character != null) { var lookAt = character.TransformV.Position; var d = new SphericalDirection(MathEx.DegreeToRadian(ThirdPersonCameraHorizontalAngle.Value), MathEx.DegreeToRadian(ThirdPersonCameraVerticalAngle.Value)); var direction = -d.GetVector(); var from = lookAt - direction * ThirdPersonCameraDistance.Value; result = new Viewport.CameraSettingsClass(viewport, cameraDefault.AspectRatio, cameraDefault.FieldOfView, cameraDefault.NearClipPlane, cameraDefault.FarClipPlane, from, direction, Vector3.ZAxis, ProjectionType.Perspective, 1, cameraDefault.Exposure, cameraDefault.EmissiveFactor); } } //Character2D if (Scene.Mode.Value == Component_Scene.ModeEnum._2D) { var character = ObjectControlledByPlayer.Value as Component_Character2D; if (character != null) { var lookAt = character.TransformV.Position; var from = lookAt + new Vector3(0, 0, 10); result = new Viewport.CameraSettingsClass(viewport, cameraDefault.AspectRatio, cameraDefault.FieldOfView, cameraDefault.NearClipPlane, cameraDefault.FarClipPlane, from, -Vector3.ZAxis, Vector3.YAxis, ProjectionType.Orthographic, cameraDefault.Height, cameraDefault.Exposure, cameraDefault.EmissiveFactor); } } } } //Component_CameraManagement if (result == null) { var m = GetCurrentCameraManagement(); if (m != null) { result = m.GetCameraSettings(this, viewport, cameraDefault); } } return(result); }
bool ProcessInputMessageBefore(UIControl playScreen, InputMessage message) { //input enabled changed { var m = message as InputMessageInputEnabledChanged; if (m != null) { inputEnabled = m.Value; } } //key down { var m = message as InputMessageKeyDown; if (m != null) { //lock( lockerKeysMouse ) //{ if (keys == null) { keys = new bool[GetEKeysMaxIndex() + 1]; } keys[(int)m.Key] = true; //} } } //key up { var m = message as InputMessageKeyUp; if (m != null) { //lock( lockerKeysMouse ) //{ if (keys == null) { keys = new bool[GetEKeysMaxIndex() + 1]; } if (keys[(int)m.Key]) { keys[(int)m.Key] = false; } //} } } //mouse button down { var m = message as InputMessageMouseButtonDown; if (m != null) { //lock( lockerKeysMouse ) //{ mouseButtons[(int)m.Button] = true; //} } } //mouse button up { var m = message as InputMessageMouseButtonUp; if (m != null) { //lock( lockerKeysMouse ) //{ mouseButtons[(int)m.Button] = false; //} } } //mouse move { var m = message as InputMessageMouseMove; if (m != null) { //lock( lockerKeysMouse ) //{ mousePosition = m.Position; //} } } //mouse relative mode { var m = message as InputMessageMouseRelativeModeChanged; if (m != null) { mouseRelativeMode = m.Value; } } var keyDown = message as InputMessageKeyDown; if (keyDown != null && FreeCameraHotKey && FreeCameraHotKeyValue.Value == keyDown.Key) { //all keys and mouse buttons up var viewport = playScreen.ParentContainer.Viewport; viewport.KeysAndMouseButtonUpAll(); //change free camera FreeCamera = !FreeCamera; //show screen message if (FreeCamera) { ScreenMessages.Add($"Free camera is activated."); } else { ScreenMessages.Add($"Free camera is deactivated."); } return(true); } var mouseDown = message as InputMessageMouseButtonDown; if (mouseDown != null) { //free camera rotating if (mouseDown.Button == EMouseButtons.Right && FreeCamera) { freeCameraMouseRotating = true; freeCameraMouseRotatingActivated = false; freeCameraRotatingStartPos = MousePosition; } } var mouseUp = message as InputMessageMouseButtonUp; if (mouseUp != null) { //free camera rotating if (mouseUp.Button == EMouseButtons.Right && freeCameraMouseRotating) { var viewport = playScreen.ParentContainer.Viewport; //viewport.MouseRelativeMode = false; freeCameraMouseRotating = false; freeCameraMouseRotatingActivated = false; } } var mouseMove = message as InputMessageMouseMove; if (mouseMove != null) { //free camera rotating if (FreeCamera && freeCameraMouseRotating) { var viewport = playScreen.ParentContainer.Viewport; if (!viewport.MouseRelativeMode) { var diffPixels = (MousePosition - freeCameraRotatingStartPos) * viewport.SizeInPixels.ToVector2(); if (Math.Abs(diffPixels.X) >= 3 || Math.Abs(diffPixels.Y) >= 3) { freeCameraMouseRotatingActivated = true; //viewport.MouseRelativeMode = true; } } else { var dir = freeCameraDirection; dir.Horizontal -= MousePosition.X; // * cameraRotateSensitivity; dir.Vertical -= MousePosition.Y; // * cameraRotateSensitivity; dir.Horizontal = MathEx.RadianNormalize360(dir.Horizontal); const double vlimit = Math.PI / 2 - .01f; if (dir.Vertical > vlimit) { dir.Vertical = vlimit; } if (dir.Vertical < -vlimit) { dir.Vertical = -vlimit; } freeCameraDirection = dir; } } } if (FreeCamera && !EngineConsole.Active && InputEnabled) { //key down { var m = message as InputMessageKeyDown; if (m != null) { if (m.Key == EKeys.W || m.Key == EKeys.Up || m.Key == EKeys.S || m.Key == EKeys.Down || m.Key == EKeys.A || m.Key == EKeys.Left || m.Key == EKeys.D || m.Key == EKeys.Right || m.Key == EKeys.E || m.Key == EKeys.Q) { return(true); } } } //up down { var m = message as InputMessageKeyUp; if (m != null) { if (m.Key == EKeys.W || m.Key == EKeys.Up || m.Key == EKeys.S || m.Key == EKeys.Down || m.Key == EKeys.A || m.Key == EKeys.Left || m.Key == EKeys.D || m.Key == EKeys.Right || m.Key == EKeys.E || m.Key == EKeys.Q) { return(true); } } } } return(false); }
protected virtual void Scene_ViewportUpdateGetCameraSettings(Component_Scene scene, Viewport viewport, ref bool processed) { //copy from Mesh document window code //var camera = scene.CameraEditor.Value; var bounds = scene.CalculateTotalBoundsOfObjectsInSpace(); var cameraLookTo = bounds.GetCenter(); double maxGararite = Math.Max(Math.Max(bounds.GetSize().X, bounds.GetSize().Y), bounds.GetSize().Z); double distance = maxGararite * 2; // 2.3; if (distance < 2) { distance = 2; } double cameraZoomFactor = 1; SphericalDirection cameraDirection = new SphericalDirection(-3.83, -.47); var cameraPosition = cameraLookTo - cameraDirection.GetVector() * distance * cameraZoomFactor; var center = cameraLookTo; // GetSceneCenter(); Vector3 from = cameraPosition; //center + cameraDirection.GetVector() * cameraDistance; Vector3 to = center; Degree fov = 65; // 75; var camera = new Component_Camera(); //camera.AspectRatio = (double)ViewportControl.Viewport.SizeInPixels.X / (double)ViewportControl.Viewport.SizeInPixels.Y; camera.FieldOfView = fov; camera.NearClipPlane = Math.Max(distance / 10000, 0.01); //.1; camera.FarClipPlane = Math.Max(1000, distance * 2); if (mesh.EditorCameraTransform != null) { camera.Transform = mesh.EditorCameraTransform; } else { camera.Transform = new Transform(from, Quaternion.LookAt((to - from).GetNormalize(), Vector3.ZAxis)); } camera.FixedUp = Vector3.ZAxis; viewport.CameraSettings = new Viewport.CameraSettingsClass(viewport, camera); //if( !cameraMode2D ) //{ //var cameraPosition = cameraLookTo - cameraDirection.GetVector() * cameraDistance; //var center = cameraLookTo; //Vector3 from = cameraPosition;//center + cameraDirection.GetVector() * cameraDistance; //Vector3 to = center; //Degree fov = 40;//!!!! 65;// 75; ////!!!! //Component_Camera camera = new Component_Camera(); //camera.AspectRatio = (double)viewport.SizeInPixels.X / (double)viewport.SizeInPixels.Y; //camera.FieldOfView = fov; //camera.NearClipPlane = Math.Max( cameraDistance / 10000, 0.01 );//.1; //camera.FarClipPlane = Math.Max( 1000, cameraDistance * 2 ); //camera.Transform = new Transform( from, Quaternion.LookAt( ( to - from ).GetNormalize(), Vector3.ZAxis ) ); ////camera.Position = from; ////camera.Direction = ( to - from ).GetNormalize(); //camera.FixedUp = Vector3.ZAxis; //viewport.CameraSettings = new Viewport.CameraSettingsClass( viewport, camera ); ////!!!!в методе больше параметров //double aspect = (double)viewport.SizeInPixels.X / (double)viewport.SizeInPixels.Y; //var settings = new Viewport.CameraSettingsClass( viewport, aspect, fov, .1f, 1000, from, ( to - from ).GetNormalize(), Vec3.ZAxis ); //viewport.CameraSettings = settings; //} //else //{ // var from = cameraLookTo + new Vector3( 0, 0, scene.CameraEditor2DPositionZ ); // var to = cameraLookTo; // Component_Camera camera = new Component_Camera(); // camera.AspectRatio = (double)viewport.SizeInPixels.X / (double)viewport.SizeInPixels.Y; // camera.NearClipPlane = 0.01;// Math.Max( cameraInitialDistance / 10000, 0.01 );//.1; // camera.FarClipPlane = 1000;// Math.Max( 1000, cameraInitialDistance * 2 ); // camera.Transform = new Transform( from, Quaternion.LookAt( ( to - from ).GetNormalize(), Vector3.YAxis ) ); // camera.Projection = ProjectionType.Orthographic; // camera.FixedUp = Vector3.YAxis; // //!!!!need consider size by X // camera.Height = cameraInitBounds.GetSize().Y * 1.4; // viewport.CameraSettings = new Viewport.CameraSettingsClass( viewport, camera ); //} processed = true; }
public static void GenerateCapsule(int axis, double radius, double height, int hSegments, int vSegments, out Vector3[] positions, out Vector3[] normals, out Vector4[] tangents, out Vector2[] texCoords, out int[] indices, out Face[] faces) { if (axis < 0 || axis > 2) { Log.Fatal("SimpleMeshGenerator: GenerateCapsule: axis < 0 || axis > 2."); } //if( radius < 0 ) // Log.Fatal( "SimpleMeshGenerator: GenerateCapsule: radius < 0." ); //if( height < 0 ) // Log.Fatal( "SimpleMeshGenerator: GenerateCapsule: height < 0." ); if (hSegments < 3) { Log.Fatal("SimpleMeshGenerator: GenerateCapsule: hSegments < 3."); } if (vSegments < 3) { Log.Fatal("SimpleMeshGenerator: GenerateCapsule: vSegments < 3."); } if (vSegments % 2 != 1) { Log.Fatal("SimpleMeshGenerator: GenerateCapsule: vSegments % 2 != 1."); } double[] cosTable = new double[hSegments]; double[] sinTable = new double[hSegments]; { double angleStep = Math.PI * 2 / hSegments; for (int n = 0; n < hSegments; n++) { double angle = angleStep * n; cosTable[n] = Math.Cos(angle); // *radius; sinTable[n] = Math.Sin(angle); // *radius; } } //positions { int vertexCount = (hSegments + 1) * (vSegments + 1); positions = new Vector3[vertexCount]; normals = new Vector3[vertexCount]; tangents = new Vector4[vertexCount]; texCoords = new Vector2[vertexCount]; int currentPosition = 0; for (int v = 0; v < vSegments + 1; v++) { for (int n = 0; n < hSegments + 1; n++) { bool up = v < (vSegments + 1) / 2; double vCoef; if (up) { vCoef = ((double)v / (double)(vSegments - 1)); } else { vCoef = (double)(v - 1) / (double)(vSegments - 1); } SphericalDirection dir = new SphericalDirection( (double)n / (double)hSegments * Math.PI * 2, (vCoef - 0.5) * Math.PI); var p = dir.GetVector() * radius; var posNoOffset = new Vector3(p.Z, p.Y, -p.X); var posResult = posNoOffset; if (up) { posResult.X -= height / 2; } else { posResult.X += height / 2; } positions[currentPosition] = posResult; //normals normals[currentPosition] = posNoOffset.GetNormalize(); if (radius < 0) { normals[currentPosition] = -normals[currentPosition]; } //tangents { Matrix3 rotationMatrix = Matrix3.FromRotateByX(-Math.PI / 2); var dir2 = new SphericalDirection((double)n / (double)hSegments * Math.PI * 2, 0).GetVector(); dir2 = new Vector3(0, dir2.Y, -dir2.X); tangents[currentPosition] = new Vector4((rotationMatrix * dir2).GetNormalize(), -1); } //texCoords texCoords[currentPosition] = new Vector2( dir.Horizontal / (MathEx.PI * 2) * 2, -dir.Vertical / MathEx.PI + 0.5); if (!up) { texCoords[currentPosition] = texCoords[currentPosition] - new Vector2(0, 1); } if (radius < 0 || height < 0) { texCoords[currentPosition] = -texCoords[currentPosition]; } currentPosition++; } } if (positions.Length != currentPosition) { Log.Fatal("SimpleMeshGenerator: GenerateCapsule: positions.Length != currentPosition."); } } //indices { int indexCount = vSegments * hSegments * 6; indices = new int[indexCount]; int currentIndex = 0; for (int v = 0; v < vSegments; v++) { for (int n = 0; n < hSegments; n++) { int index = v * (hSegments + 1) + n; indices[currentIndex++] = index; indices[currentIndex++] = index + 1; indices[currentIndex++] = index + hSegments + 1; indices[currentIndex++] = index + hSegments + 1; indices[currentIndex++] = index + 1; indices[currentIndex++] = index + hSegments + 1 + 1; } } if (indices.Length != currentIndex) { Log.Fatal("SimpleMeshGenerator: GenerateCapsule: indices.Length != currentIndex."); } } positions = RotateByAxis(axis, positions); normals = RotateByAxis(axis, normals); tangents = RotateByAxis(axis, tangents); //??? Если нужно каждый фейс сделать прямоугольником то задать: rawVerticesInFace = rawVerticesInFaceForMiddle = 6 faces = BuildFacesForGeoSphere(hSegments, vSegments, 3, 6, indices); ////positions //{ // int vertexCount = hSegments * ( vSegments - 1 ) + 2; // positions = new Vec3[ vertexCount ]; // normals = new Vec3[ vertexCount ]; // tangents = new Vec4[ vertexCount ]; // texCoords = new Vec2[ vertexCount ]; // double[] cosTable = new double[ hSegments ]; // double[] sinTable = new double[ hSegments ]; // { // double angleStep = Math.PI * 2 / hSegments; // for( int n = 0; n < hSegments; n++ ) // { // double angle = angleStep * n; // cosTable[ n ] = Math.Cos( angle ); // sinTable[ n ] = Math.Sin( angle ); // } // } // int levelCount = vSegments + 1; // int currentPosition = 0; // for( int v = 0; v < levelCount; v++ ) // { // if( v == 0 ) // { // positions[ currentPosition ] = new Vec3( radius + height * .5, 0, 0 ); // normals[ currentPosition ] = new Vec3( 1, 0, 0 ); // currentPosition++; // } // else if( v == vSegments ) // { // positions[ currentPosition ] = new Vec3( -radius - height * .5, 0, 0 ); // normals[ currentPosition ] = new Vec3( -1, 0, 0 ); // currentPosition++; // } // else // { // bool top = v <= vSegments / 2; // double c; // if( top ) // c = ( (double)v / (double)( vSegments - 1 ) ); // else // c = ( (double)( v - 1 ) / (double)( vSegments - 1 ) ); // double angle = -( c * 2 - 1 ) * Math.PI / 2; // double hRadius = Math.Cos( angle ) * radius; // double h = Math.Sin( angle ) * radius + ( top ? height * .5 : -height * .5 ); // for( int n = 0; n < hSegments; n++ ) // { // positions[ currentPosition ] = new Vec3( h, cosTable[ n ] * hRadius, sinTable[ n ] * hRadius ); // normals[ currentPosition ] = new Vec3( // Math.Sin( angle ) * radius, cosTable[ n ] * hRadius, sinTable[ n ] * hRadius ).GetNormalize(); // if( radius < 0 ) // normals[ currentPosition ] = -normals[ currentPosition ]; // currentPosition++; // } // } // } // if( positions.Length != currentPosition ) // Log.Fatal( "SimpleMeshGenerator: GenerateCapsule: positions.Length != currentPosition." ); //} ////indices //{ // int indexCount = hSegments * ( vSegments - 2 ) * 2 * 3 + hSegments * 3 + hSegments * 3; // indices = new int[ indexCount ]; // int levelCount = vSegments + 1; // int currentIndex = 0; // for( int v = 0; v < levelCount - 1; v++ ) // { // int index; // int nextIndex; // if( v != 0 ) // { // index = 1 + ( v - 1 ) * hSegments; // nextIndex = index + hSegments; // } // else // { // index = 0; // nextIndex = 1; // } // for( int n = 0; n < hSegments; n++ ) // { // int start = n; // int end = ( n + 1 ) % hSegments; // if( v == 0 ) // { // indices[ currentIndex++ ] = index; // indices[ currentIndex++ ] = nextIndex + start; // indices[ currentIndex++ ] = nextIndex + end; // } // else if( v == vSegments - 1 ) // { // indices[ currentIndex++ ] = index + end; // indices[ currentIndex++ ] = index + start; // indices[ currentIndex++ ] = nextIndex; // } // else // { // indices[ currentIndex++ ] = index + end; // indices[ currentIndex++ ] = index + start; // indices[ currentIndex++ ] = nextIndex + end; // indices[ currentIndex++ ] = nextIndex + start; // indices[ currentIndex++ ] = nextIndex + end; // indices[ currentIndex++ ] = index + start; // } // } // } // if( indices.Length != currentIndex ) // Log.Fatal( "SimpleMeshGenerator: GenerateCapsule: indices.Length != currentIndex." ); //} //positions = RotateByAxis( axis, positions ); //normals = RotateByAxis( axis, normals ); //tangents = RotateByAxis( axis, tangents ); }
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; // } //} }
public static void GenerateSphere(double radius, int hSegments, int vSegments, bool insideOut, out Vector3[] positions, out Vector3[] normals, out Vector4[] tangents, out Vector2[] texCoords, out int[] indices, out Face[] faces) { var radius2 = radius; if (insideOut) { radius2 = -radius2; } //if( radius < 0 ) // Log.Fatal( "SimpleMeshGenerator: GenerateSphere: radius < 0." ); if (hSegments < 3) { Log.Fatal("SimpleMeshGenerator: GenerateSphere: hSegments < 3."); } if (vSegments < 2) { Log.Fatal("SimpleMeshGenerator: GenerateSphere: vSegments < 2."); } //positions { int vertexCount = (hSegments + 1) * (vSegments + 1); positions = new Vector3[vertexCount]; normals = new Vector3[vertexCount]; tangents = new Vector4[vertexCount]; texCoords = new Vector2[vertexCount]; int currentPosition = 0; for (int v = 0; v < vSegments + 1; v++) { for (int n = 0; n < hSegments + 1; n++) { SphericalDirection dir = new SphericalDirection( (double)n / (double)hSegments * Math.PI * 2, ((double)v / (double)vSegments - 0.5) * Math.PI); positions[currentPosition] = dir.GetVector() * radius2; texCoords[currentPosition] = new Vector2( dir.Horizontal / (MathEx.PI * 2) * 2, -dir.Vertical / MathEx.PI + 0.5); if (radius2 < 0) { texCoords[currentPosition] = new Vector2(1.0f - texCoords[currentPosition].X, 1.0f - texCoords[currentPosition].Y); } currentPosition++; } } if (positions.Length != currentPosition) { Log.Fatal("SimpleMeshGenerator: GenerateSphere: positions.Length != currentPosition."); } } //normals { for (int n = 0; n < positions.Length; n++) { normals[n] = positions[n].GetNormalize(); if (radius2 < 0) { normals[n] = -normals[n]; } } } //tangents { Matrix3 rotationMatrix = new Matrix3(0, -1, 0, 1, 0, 0, 0, 0, 1); for (int n = 0; n < positions.Length; n++) { var p = positions[n]; var rot = Quaternion.FromDirectionZAxisUp(p.GetNormalize()).ToMatrix3() * rotationMatrix; if (radius2 < 0) { tangents[n] = new Vector4(rot * Vector3.XAxis, -1); } else { tangents[n] = new Vector4(rot * -Vector3.XAxis, -1); } } } //indices { int indexCount = vSegments * hSegments * 6; indices = new int[indexCount]; int currentIndex = 0; for (int v = 0; v < vSegments; v++) { for (int n = 0; n < hSegments; n++) { int index = v * (hSegments + 1) + n; indices[currentIndex++] = index; indices[currentIndex++] = index + 1; indices[currentIndex++] = index + hSegments + 1; indices[currentIndex++] = index + hSegments + 1; indices[currentIndex++] = index + 1; indices[currentIndex++] = index + hSegments + 1 + 1; } } if (indices.Length != currentIndex) { Log.Fatal("SimpleMeshGenerator: GenerateSphere: indices.Length != currentIndex."); } } //??? Если нужно каждый фейс сделать прямоугольником то задать: rawVerticesInFace = rawVerticesInFaceForMiddle = 6 faces = BuildFacesForGeoSphere(hSegments, vSegments, 3, 3, indices); }
public void Write(SphericalDirection source) { Write(source.Horizontal); Write(source.Vertical); }
public static void Negate(ref SphericalDirection v, out SphericalDirection result) { result.Horizontal = -v.Horizontal; result.Vertical = -v.Vertical; }
// static SimpleTypes() { //string RegisterType(typeof(string), delegate(string value) { if (value == null) { return(""); //throw new Exception( "GetSimpleTypeValue: string type, value = null" ); } return(value); }, ""); //bool RegisterType(typeof(bool), delegate(string value) { string lower = value.ToLower(); if (value == "1" || lower == "yes" || lower == "true") { return(true); } else if (value == "0" || lower == "no" || lower == "false") { return(false); } else { return(bool.Parse(value)); } }, false); //sbyte RegisterType(typeof(sbyte), delegate(string value) { return(sbyte.Parse(value)); }, 0); //byte RegisterType(typeof(byte), delegate(string value) { return(byte.Parse(value)); }, 0); //char RegisterType(typeof(char), delegate(string value) { return(char.Parse(value)); }, 0); //short RegisterType(typeof(short), delegate(string value) { return(short.Parse(value)); }, 0); //ushort RegisterType(typeof(ushort), delegate(string value) { return(ushort.Parse(value)); }, 0); //int RegisterType(typeof(int), delegate(string value) { return(int.Parse(value)); }, 0); //uint RegisterType(typeof(uint), delegate(string value) { return(uint.Parse(value)); }, (uint)0); //long RegisterType(typeof(long), delegate(string value) { return(long.Parse(value)); }, (long)0); //ulong RegisterType(typeof(ulong), delegate(string value) { return(ulong.Parse(value)); }, (ulong)0); //float RegisterType(typeof(float), delegate(string value) { return(float.Parse(value)); }, 0.0f); //double RegisterType(typeof(double), delegate(string value) { return(double.Parse(value)); }, 0.0); //decimal RegisterType(typeof(decimal), delegate(string value) { return(decimal.Parse(value)); }, (decimal)0.0); //Vec2 RegisterType(typeof(Vector2F), delegate(string value) { return(Vector2F.Parse(value)); }, Vector2F.Zero); //Range RegisterType(typeof(RangeF), delegate(string value) { return(RangeF.Parse(value)); }, RangeF.Zero); //Vec3 RegisterType(typeof(Vector3F), delegate(string value) { return(Vector3F.Parse(value)); }, Vector3F.Zero); //Vec4 RegisterType(typeof(Vector4F), delegate(string value) { return(Vector4F.Parse(value)); }, Vector4F.Zero); //Bounds RegisterType(typeof(BoundsF), delegate(string value) { return(BoundsF.Parse(value)); }, BoundsF.Zero); //Quat RegisterType(typeof(QuaternionF), delegate(string value) { return(QuaternionF.Parse(value)); }, QuaternionF.Identity); //ColorValue RegisterType(typeof(ColorValue), delegate(string value) { return(ColorValue.Parse(value)); }, ColorValue.Zero); //ColorValuePowered RegisterType(typeof(ColorValuePowered), delegate(string value) { return(ColorValuePowered.Parse(value)); }, ColorValuePowered.Zero); //ColorPacked RegisterType(typeof(ColorByte), delegate(string value) { return(ColorByte.Parse(value)); }, ColorByte.Zero); //SphereDir RegisterType(typeof(SphericalDirectionF), delegate(string value) { return(SphericalDirectionF.Parse(value)); }, SphericalDirectionF.Zero); //Vec2I RegisterType(typeof(Vector2I), delegate(string value) { return(Vector2I.Parse(value)); }, Vector2I.Zero); //Vec3I RegisterType(typeof(Vector3I), delegate(string value) { return(Vector3I.Parse(value)); }, Vector3I.Zero); //Vec4I RegisterType(typeof(Vector4I), delegate(string value) { return(Vector4I.Parse(value)); }, Vector4I.Zero); //Rect RegisterType(typeof(RectangleF), delegate(string value) { return(RectangleF.Parse(value)); }, RectangleF.Zero); //RectI RegisterType(typeof(RectangleI), delegate(string value) { return(RectangleI.Parse(value)); }, RectangleI.Zero); //Degree RegisterType(typeof(DegreeF), delegate(string value) { return(DegreeF.Parse(value)); }, DegreeF.Zero); //Radian RegisterType(typeof(RadianF), delegate(string value) { return(RadianF.Parse(value)); }, RadianF.Zero); //Vec2D RegisterType(typeof(Vector2), delegate(string value) { return(Vector2.Parse(value)); }, Vector2.Zero); //RangeD RegisterType(typeof(Range), delegate(string value) { return(Range.Parse(value)); }, Range.Zero); //RangeI RegisterType(typeof(RangeI), delegate(string value) { return(RangeI.Parse(value)); }, RangeI.Zero); //Vec3D RegisterType(typeof(Vector3), delegate(string value) { return(Vector3.Parse(value)); }, Vector3.Zero); //Vec4D RegisterType(typeof(Vector4), delegate(string value) { return(Vector4.Parse(value)); }, Vector4.Zero); //BoundsD RegisterType(typeof(Bounds), delegate(string value) { return(Bounds.Parse(value)); }, Bounds.Zero); //QuatD RegisterType(typeof(Quaternion), delegate(string value) { return(Quaternion.Parse(value)); }, Quaternion.Identity); //SphereDirD RegisterType(typeof(SphericalDirection), delegate(string value) { return(SphericalDirection.Parse(value)); }, SphericalDirection.Zero); //RectD RegisterType(typeof(Rectangle), delegate(string value) { return(Rectangle.Parse(value)); }, Rectangle.Zero); //DegreeD RegisterType(typeof(Degree), delegate(string value) { return(Degree.Parse(value)); }, Degree.Zero); //RadianD RegisterType(typeof(Radian), delegate(string value) { return(Radian.Parse(value)); }, Radian.Zero); //Angles RegisterType(typeof(AnglesF), delegate(string value) { return(AnglesF.Parse(value)); }, AnglesF.Zero); //AnglesD RegisterType(typeof(Angles), delegate(string value) { return(Angles.Parse(value)); }, Angles.Zero); //Mat2F RegisterType(typeof(Matrix2F), delegate(string value) { return(Matrix2F.Parse(value)); }, Matrix2F.Zero); //Mat2D RegisterType(typeof(Matrix2), delegate(string value) { return(Matrix2.Parse(value)); }, Matrix2.Zero); //Mat3F RegisterType(typeof(Matrix3F), delegate(string value) { return(Matrix3F.Parse(value)); }, Matrix3F.Zero); //Mat3D RegisterType(typeof(Matrix3), delegate(string value) { return(Matrix3.Parse(value)); }, Matrix3.Zero); //Mat4F RegisterType(typeof(Matrix4F), delegate(string value) { return(Matrix4F.Parse(value)); }, Matrix4F.Zero); //Mat4D RegisterType(typeof(Matrix4), delegate(string value) { return(Matrix4.Parse(value)); }, Matrix4.Zero); //PlaneF RegisterType(typeof(PlaneF), delegate(string value) { return(PlaneF.Parse(value)); }, PlaneF.Zero); //PlaneD RegisterType(typeof(Plane), delegate(string value) { return(Plane.Parse(value)); }, Plane.Zero); //Transform RegisterType(typeof(Transform), delegate(string value) { return(Transform.Parse(value)); }, Transform.Identity); //UIMeasureValueDouble RegisterType(typeof(UIMeasureValueDouble), delegate(string value) { return(UIMeasureValueDouble.Parse(value)); }, new UIMeasureValueDouble()); //UIMeasureValueVec2 RegisterType(typeof(UIMeasureValueVector2), delegate(string value) { return(UIMeasureValueVector2.Parse(value)); }, new UIMeasureValueVector2()); //UIMeasureValueRect RegisterType(typeof(UIMeasureValueRectangle), delegate(string value) { return(UIMeasureValueRectangle.Parse(value)); }, new UIMeasureValueRectangle()); RegisterType(typeof(RangeVector3F), delegate(string value) { return(RangeVector3F.Parse(value)); }, RangeVector3F.Zero); RegisterType(typeof(RangeColorValue), delegate(string value) { return(RangeColorValue.Parse(value)); }, RangeColorValue.Zero); //no Parse methods. This is complex structures. This is not simple types? or just can't parse? //Box //Capsule //Cone //Line3 //Line2 //Ray //Frustum? RegisterConvertDoubleToFloatTypes(); }