/// <summary> /// Set the heading of the camera as an angle in degrees. /// </summary> /// <param name="angle">The camera's new heading (clamped -90 to 90).</param> public void RotateHeadingTo(float angle) { heading = angle; //heading constraints of (-90 <= heading <= 90) if (heading >= 90) { heading = 90; } if (heading <= -90) { heading = -90; } //the radius of the circle that the up axis will have to lie on - think of a unit sphere as differently sized circles stacked vertically. float headingRad = heading * (MathHelper.Pi / 180f); float radius = (float)Math.Sin(headingRad); //The cos of the heading will get us the height of the up axis. upAxis.Y = (float)Math.Cos(headingRad); //X and Z: rotate right axis 90 degrees for the direction of upAxis on the X/Z plane, //use cos/sin to get the X and Z coordinates in the unit circle in the middle of the sphere (think of stacked circles again), //scale by our new radius to get X and Z coordinates on the circle that upAxis.Y is on (multiply by radius) float headingDirection = (pitch + 90) * (MathHelper.Pi / 180f); upAxis.X = radius * (float)Math.Cos(headingDirection); upAxis.Z = radius * (float)Math.Sin(headingDirection); //update the lookAxis lookAxis = Vector3.Normalize(Vector3.Cross(rightAxis, upAxis)); //update the view matrix so our changes are reflected in the world RebuildView(); }
public void PreviewMesh(Mesh mesh) { _mesh = mesh; viewMatrixData = Matrix4.CreateRotationY(-(float)Math.PI / 4) * Matrix4.CreateRotationX(-(float)Math.PI / 6); if (_vaoModel != 0) { GL.DeleteVertexArray(_vaoModel); GL.DeleteBuffer(_indexBufferObject); GL.DeleteBuffer(_vertexBufferObject); } Visible = true; // Vertices verticeData = new float[mesh.m_Vertices.Length * 2]; for (int v = 0; v < mesh.m_Vertices.Length; v += 3) { for (int i = 0; i < 3; i++) { verticeData[v * 2 + i] = mesh.m_Vertices[v + i]; } } // Calculate Bounding float[] min = new float[3]; float[] max = new float[3]; for (int i = 0; i < 3; i++) { min[i] = verticeData[i]; max[i] = verticeData[i]; } for (int v = 0; v < verticeData.Length; v += 6) { for (int i = 0; i < 3; i++) { min[i] = Math.Min(min[i], verticeData[v + i]); max[i] = Math.Max(max[i], verticeData[v + i]); } } // Calculate modelMatrix Vector3 dist = Vector3.One, offset = Vector3.Zero; for (int i = 0; i < 3; i++) { dist[i] = max[i] - min[i]; offset[i] = (max[i] + min[i]) / 2; } float d = Math.Max(1e-5f, dist.Length); modelMatrixData = Matrix4.CreateTranslation(-offset) * Matrix4.CreateScale(2f / d); // Indicies indiceData = mesh.m_SubMeshes.SelectMany(m => m.indices).ToArray(); // calculate normal by ourself int[] normalCalculatedCount = new int[verticeData.Length / 6]; for (int i = 0; i < indiceData.Length; i += 3) { Vector3 vertex0 = new Vector3(verticeData[indiceData[i + 0] * 6], verticeData[indiceData[i + 0] * 6 + 1], verticeData[indiceData[i + 0] * 6 + 2]); Vector3 vertex1 = new Vector3(verticeData[indiceData[i + 1] * 6], verticeData[indiceData[i + 1] * 6 + 1], verticeData[indiceData[i + 1] * 6 + 2]); Vector3 vertex2 = new Vector3(verticeData[indiceData[i + 2] * 6], verticeData[indiceData[i + 2] * 6 + 1], verticeData[indiceData[i + 2] * 6 + 2]); Vector3 normal = Vector3.Cross(vertex1 - vertex0, vertex2 - vertex0); normal.Normalize(); for (int j = 0; j < 3; j++) { verticeData[indiceData[i + j] * 6 + 3] += normal.X; verticeData[indiceData[i + j] * 6 + 4] += normal.Y; verticeData[indiceData[i + j] * 6 + 5] += normal.Z; normalCalculatedCount[indiceData[i + j]]++; } } for (int i = 0; i < normalCalculatedCount.Length; i++) { if (normalCalculatedCount[i] == 0) { verticeData[i * 6 + 3] = 0; verticeData[i * 6 + 4] = 1; verticeData[i * 6 + 5] = 0; } else { verticeData[i * 6 + 3] /= normalCalculatedCount[i]; verticeData[i * 6 + 4] /= normalCalculatedCount[i]; verticeData[i * 6 + 5] /= normalCalculatedCount[i]; } } _vertexBufferObject = GL.GenBuffer(); GL.BindBuffer(BufferTarget.ArrayBuffer, _vertexBufferObject); GL.BufferData(BufferTarget.ArrayBuffer, verticeData.Length * sizeof(float), verticeData, BufferUsageHint.StaticDraw); _indexBufferObject = GL.GenBuffer(); GL.BindBuffer(BufferTarget.ElementArrayBuffer, _indexBufferObject); GL.BufferData(BufferTarget.ElementArrayBuffer, indiceData.Length * sizeof(uint), indiceData, BufferUsageHint.StaticDraw); _vaoModel = GL.GenVertexArray(); GL.BindVertexArray(_vaoModel); var positionLocation = _shader.GetAttribLocation("aPos"); GL.EnableVertexAttribArray(positionLocation); GL.VertexAttribPointer(positionLocation, 3, VertexAttribPointerType.Float, false, 6 * sizeof(float), 0); var normalLocation = _shader.GetAttribLocation("aNormal"); GL.EnableVertexAttribArray(normalLocation); GL.VertexAttribPointer(normalLocation, 3, VertexAttribPointerType.Float, false, 6 * sizeof(float), 3 * sizeof(float)); ChangeGLSize(Size); Invalidate(); }