/// <summary> /// Build a look at view matrix. /// transform object's coordinate from world's space to camera's space. /// </summary> /// <param name="eye">The eye.</param> /// <param name="center">The center.</param> /// <param name="up">Up.</param> /// <returns></returns> public static mat4 lookAt(vec3 eye, vec3 center, vec3 up) { // camera's back in world space coordinate system vec3 back = (eye - center).normalize(); // camera's right in world space coordinate system vec3 right = up.cross(back).normalize(); // camera's up in world space coordinate system vec3 standardUp = back.cross(right); mat4 viewMat = new mat4(1); viewMat.col0.x = right.x; viewMat.col1.x = right.y; viewMat.col2.x = right.z; viewMat.col0.y = standardUp.x; viewMat.col1.y = standardUp.y; viewMat.col2.y = standardUp.z; viewMat.col0.z = back.x; viewMat.col1.z = back.y; viewMat.col2.z = back.z; // Translation in world space coordinate system viewMat.col3.x = -eye.dot(right); viewMat.col3.y = -eye.dot(standardUp); viewMat.col3.z = -eye.dot(back); return(viewMat); }
/// <summary> /// Build a look at view matrix. /// transform object's coordinate from world's space to camera's space. /// </summary> /// <param name="eye">The eye.</param> /// <param name="center">The center.</param> /// <param name="up">Up.</param> /// <returns></returns> public static mat4 lookAt(vec3 eye, vec3 center, vec3 up) { vec3 forward = (center - eye).normalize(); vec3 right = forward.cross(up).normalize(); vec3 standardUp = right.cross(forward); mat4 Result = new mat4(1); // Left (X) Axis Result[0, 0] = right.x; Result[0, 1] = standardUp.x; Result[0, 2] = -forward.x; // Up (Y) Axis Result[1, 0] = right.y; Result[1, 1] = standardUp.y; Result[1, 2] = -forward.y; // Forward (Z) Axis Result[2, 0] = right.z; Result[2, 1] = standardUp.z; Result[2, 2] = -forward.z; // Translation Result[3, 0] = -right.dot(eye); // dot(s, eye); Result[3, 1] = -standardUp.dot(eye); // dot(u, eye); Result[3, 2] = forward.dot(eye); // dot(f, eye); return(Result); }
void IMouseHandler.canvas_MouseMove(object sender, GLMouseEventArgs e) { if (this.mouseDownFlag && ((e.Button & this.lastBindingMouseButtons) != GLMouseButtons.None) && (e.X != lastPosition.x || e.Y != lastPosition.y)) { IViewCamera camera = this.camera; if (camera == null) { return; } vec3 back = this.back; vec3 right = this.right; vec3 up = this.up; GUISize bound = this.bound; ivec2 downPosition = this.lastPosition; { float deltaX = -this.HorizontalRotationFactor * (e.X - downPosition.x) / (float)bound.Width; float cos = (float)Math.Cos(deltaX); float sin = (float)Math.Sin(deltaX); vec3 newBack = new vec3( back.x * cos + right.x * sin, back.y * cos + right.y * sin, back.z * cos + right.z * sin); back = newBack; right = up.cross(back); back = back.normalize(); right = right.normalize(); } { float deltaY = this.VerticalRotationFactor * (e.Y - downPosition.y) / (float)bound.Height; float cos = (float)Math.Cos(deltaY); float sin = (float)Math.Sin(deltaY); vec3 newBack = new vec3( back.x * cos - up.x * sin, back.y * cos - up.y * sin, back.z * cos - up.z * sin); back = newBack; up = back.cross(right); back = back.normalize(); up = up.normalize(); } //camera.Position = camera.Target + // back * (float)((camera.Position - camera.Target).length()); rootNode.RotationAxis = up; camera.UpVector = up; this.back = back; this.right = right; this.up = up; this.lastPosition = e.Location; IGLCanvas canvas = this.canvas; if (canvas != null && canvas.RenderTrigger == RenderTrigger.Manual) { canvas.Repaint(); } } }
/// <summary> /// Get left vector in world space. /// </summary> /// <returns></returns> public static vec3 GetLeft(this IViewCamera camera) { vec3 back = camera.Position - camera.Target; vec3 result = back.cross(camera.UpVector); return(result); }
void IMouseHandler.canvas_MouseMove(object sender, MouseEventArgs e) { if (mouseDownFlag && ((e.Button & this.lastBindingMouseButtons) != MouseButtons.None)) { if (!cameraState.IsSameState(this.camera)) { SetCamera(this.camera.Position, this.camera.Target, this.camera.UpVector); } this._endPosition = GetArcBallPosition(e.X, e.Y); var cosAngle = _startPosition.dot(_endPosition) / (_startPosition.length() * _endPosition.length()); if (cosAngle > 1.0f) { cosAngle = 1.0f; } else if (cosAngle < -1) { cosAngle = -1.0f; } var angle = MouseSensitivity * (float)(Math.Acos(cosAngle) / Math.PI * 180); _normalVector = _startPosition.cross(_endPosition).normalize(); if (! ((_normalVector.x == 0 && _normalVector.y == 0 && _normalVector.z == 0) || float.IsNaN(_normalVector.x) || float.IsNaN(_normalVector.y) || float.IsNaN(_normalVector.z))) { _startPosition = _endPosition; mat4 newRotation = glm.rotate(angle, _normalVector); this.totalRotation = newRotation * totalRotation; } } }
void IKeyboardHandler.canvas_KeyPress(object sender, GLKeyPressEventArgs e) { bool updated = false; if (e.KeyChar == frontKey || e.KeyChar == upcaseFrontKey) { vec3 right = this.camera.GetRight(); vec3 standardFront = this.camera.UpVector.cross(right).normalize(); this.camera.Position += standardFront * this.StepLength; this.camera.Target += standardFront * this.StepLength; updated = true; } else if (e.KeyChar == backKey || e.KeyChar == upcaseBackKey) { vec3 right = this.camera.GetRight(); vec3 standardBack = right.cross(this.camera.UpVector).normalize(); this.camera.Position += standardBack * this.StepLength; this.camera.Target += standardBack * this.StepLength; updated = true; } else if (e.KeyChar == leftKey || e.KeyChar == upcaseLeftKey) { vec3 right = this.camera.GetRight(); vec3 left = (-right).normalize(); this.camera.Position += left * this.StepLength; this.camera.Target += left * this.StepLength; updated = true; } else if (e.KeyChar == rightKey || e.KeyChar == upcaseRightKey) { vec3 right = this.camera.GetRight().normalize(); this.camera.Position += right * this.StepLength; this.camera.Target += right * this.StepLength; updated = true; } else if (e.KeyChar == upKey || e.KeyChar == upcaseUpKey) { vec3 up = this.camera.UpVector.normalize(); this.camera.Position += up * this.StepLength; this.camera.Target += up * this.StepLength; updated = true; } else if (e.KeyChar == downKey || e.KeyChar == upcaseDownKey) { vec3 down = -this.camera.UpVector.normalize(); this.camera.Position += down * this.StepLength; this.camera.Target += down * this.StepLength; updated = true; } if (updated) { IGLCanvas canvas = this.canvas; if (canvas.RenderTrigger == RenderTrigger.Manual) { canvas.Repaint(); } } }
/// <summary> /// Gets standard down. /// </summary> /// <param name="camera"></param> /// <returns></returns> public static vec3 GetDown(this IViewCamera camera) { vec3 back = camera.Position - camera.Target; vec3 right = camera.UpVector.cross(back); vec3 down = right.cross(back); return(down); }
/// <summary> /// Gets standard up. /// </summary> /// <param name="camera"></param> /// <returns></returns> public static vec3 GetUp(this IViewCamera camera) { vec3 back = camera.Position - camera.Target; vec3 right = camera.UpVector.cross(back); vec3 up = back.cross(right); return(up); }
void IMouseHandler.canvas_MouseMove(object sender, MouseEventArgs e) { if (this.mouseDownFlag && ((e.Button & this.lastBindingMouseButtons) != MouseButtons.None) && (e.X != lastPosition.X || e.Y != lastPosition.Y)) { IViewCamera camera = this.camera; if (camera == null) { return; } vec3 back = this.back; vec3 right = this.right; vec3 up = this.up; Size bound = this.bound; Point downPosition = this.lastPosition; { float deltaX = -this.HorizontalRotationFactor * (e.X - downPosition.X) / bound.Width; float cos = (float)Math.Cos(deltaX); float sin = (float)Math.Sin(deltaX); vec3 newBack = new vec3( back.x * cos + right.x * sin, back.y * cos + right.y * sin, back.z * cos + right.z * sin); back = newBack; right = up.cross(back); back = back.normalize(); right = right.normalize(); } { float deltaY = this.VerticalRotationFactor * (e.Y - downPosition.Y) / bound.Height; float cos = (float)Math.Cos(deltaY); float sin = (float)Math.Sin(deltaY); vec3 newBack = new vec3( back.x * cos + up.x * sin, back.y * cos + up.y * sin, back.z * cos + up.z * sin); back = newBack; up = back.cross(right); back = back.normalize(); up = up.normalize(); } camera.Position = camera.Target + back * (float)((camera.Position - camera.Target).length()); camera.UpVector = up; this.back = back; this.right = right; this.up = up; this.lastPosition = e.Location; if (this.canvas.RenderTrigger == RenderTrigger.Manual) { this.canvas.Invalidate(); } } }
private static void GenNormals() { var faceNormals = new vec3[faceData.Length / 3]; for (int i = 0; i < faceData.Length / 3; i++) { ushort vertexId1 = faceData[i * 3 + 0]; ushort vertexId2 = faceData[i * 3 + 1]; ushort vertexId3 = faceData[i * 3 + 2]; vec3 vertex0 = new vec3( positionData[(vertexId1 - 1) * 3 + 0], positionData[(vertexId1 - 1) * 3 + 1], positionData[(vertexId1 - 1) * 3 + 2]); vec3 vertex1 = new vec3( positionData[(vertexId2 - 1) * 3 + 0], positionData[(vertexId2 - 1) * 3 + 1], positionData[(vertexId2 - 1) * 3 + 2]); vec3 vertex2 = new vec3( positionData[(vertexId3 - 1) * 3 + 0], positionData[(vertexId3 - 1) * 3 + 1], positionData[(vertexId3 - 1) * 3 + 2]); vec3 v1 = vertex0 - vertex2; vec3 v2 = vertex2 - vertex1; faceNormals[i] = v2.cross(v1).normalize(); } var normals = new float[positionData.Length]; for (int i = 0; i < positionData.Length / 3; i++) { vec3 sum = new vec3(); int shared = 0; for (int j = 0; j < faceData.Length / 3; j++) { ushort vertexId1 = faceData[j * 3 + 0]; ushort vertexId2 = faceData[j * 3 + 1]; ushort vertexId3 = faceData[j * 3 + 2]; if (vertexId1 - 1 == i || vertexId2 - 1 == i || vertexId3 - 1 == i) { sum = sum + faceNormals[j]; shared++; } } if (shared > 0) { sum = (sum / shared).normalize(); } normals[i * 3 + 0] = sum.x; normals[i * 3 + 1] = sum.y; normals[i * 3 + 2] = sum.z; } TeapotModel.normals = normals; }
private void SetCamera(vec3 position, vec3 target, vec3 up) { _vectorBack = (position - target).normalize(); _vectorRight = up.cross(_vectorBack).normalize(); _vectorUp = _vectorBack.cross(_vectorRight).normalize(); this.cameraState.position = position; this.cameraState.target = target; this.cameraState.up = up; }
public void MouseMove(int x, int y) { if (MouseDownFlag) { Debug.WriteLine(" =================>MouseMove:", listenerName); if (!cameraState.IsSameState(this.Camera)) { SetCamera(this.Camera.Position, this.Camera.Target, this.Camera.UpVector); Debug.WriteLine(string.Format( " update camera state: {0}, {1}, {2}", this.cameraState.position, this.cameraState.target, this.cameraState.up), listenerName); } this._endPosition = GetArcBallPosition(x, y); Debug.WriteLine(string.Format( " End position: {0}", this._endPosition), listenerName); var cosAngle = _startPosition.dot(_endPosition) / (_startPosition.Magnitude() * _endPosition.Magnitude()); if (cosAngle > 1) { cosAngle = 1; } else if (cosAngle < -1) { cosAngle = -1; } Debug.Write(string.Format(" cos angle: {0}", cosAngle), listenerName); var angle = mouseSensitivity * (float)(Math.Acos(cosAngle) / Math.PI * 180); Debug.WriteLine(string.Format( ", angle: {0}", angle), listenerName); _normalVector = _startPosition.cross(_endPosition).normalize(); if ((_normalVector.x == 0 && _normalVector.y == 0 && _normalVector.z == 0) || float.IsNaN(_normalVector.x) || float.IsNaN(_normalVector.y) || float.IsNaN(_normalVector.z)) { Debug.WriteLine(" no movement recorded.", listenerName); } else { Debug.WriteLine(string.Format( " normal vector: {0}", _normalVector), listenerName); _startPosition = _endPosition; mat4 newRotation = glm.rotate(angle, _normalVector); Debug.WriteLine(string.Format( " new rotation matrix: {0}", newRotation), listenerName); this.totalRotation = newRotation * totalRotation; Debug.WriteLine(string.Format( " total rotation matrix: {0}", totalRotation), listenerName); } Debug.WriteLine(" -------------------MouseMove end.", listenerName); } }
private void PrepareCamera() { var camera = this.camera; if (camera != null) { vec3 back = camera.Position - camera.Target; vec3 right = camera.UpVector.cross(back); vec3 up = back.cross(right); this.back = back.normalize(); this.right = right.normalize(); this.up = up.normalize(); } }
/// <summary> /// /// </summary> /// <param name="x"></param> /// <param name="y"></param> public void MouseMove(int x, int y) { if (this.MouseDownFlag) { IViewCamera camera = this.Camera; if (camera == null) { return; } vec3 back = this.back; vec3 right = this.right; vec3 up = this.up; Size bound = this.bound; Point downPosition = this.downPosition; { float deltaX = -horizontalRotationFactor * (x - downPosition.X) / bound.Width; float cos = (float)Math.Cos(deltaX); float sin = (float)Math.Sin(deltaX); vec3 newBack = new vec3( back.x * cos + right.x * sin, back.y * cos + right.y * sin, back.z * cos + right.z * sin); back = newBack.normalize(); right = up.cross(back).normalize(); } { float deltaY = verticalRotationFactor * (y - downPosition.Y) / bound.Height; float cos = (float)Math.Cos(deltaY); float sin = (float)Math.Sin(deltaY); vec3 newBack = new vec3( back.x * cos + up.x * sin, back.y * cos + up.y * sin, back.z * cos + up.z * sin); back = newBack.normalize(); up = back.cross(right).normalize(); } camera.Position = camera.Target + back * (float)((camera.Position - camera.Target).Magnitude()); camera.UpVector = up; this.back = back; this.right = right; this.up = up; this.downPosition.X = x; this.downPosition.Y = y; } }
private void PrepareCamera() { var camera = this.Camera; if (camera != null) { vec3 back = (camera.Position - camera.Target).normalize(); vec3 right = Camera.UpVector.cross(back).normalize(); vec3 up = back.cross(right).normalize(); this.back = back; this.right = right; this.up = up; if (this.originalCamera == null) { this.originalCamera = new Camera(); } this.originalCamera.Position = camera.Position; this.originalCamera.UpVector = camera.UpVector; } }
private static void GenNormals(TeapotModel model) { var faceNormals = new vec3[model.faces.Count]; model.normals.AddRange(new vec3[model.positions.Count]); for (int i = 0; i < model.faces.Count; i++) { var face = model.faces[i]; vec3 vertex0 = model.positions[face.Item1 - 1]; vec3 vertex1 = model.positions[face.Item2 - 1]; vec3 vertex2 = model.positions[face.Item3 - 1]; vec3 v1 = vertex0 - vertex2; vec3 v2 = vertex2 - vertex1; faceNormals[i] = v2.cross(v1).normalize(); } for (int i = 0; i < model.positions.Count; i++) { vec3 sum = new vec3(); int shared = 0; for (int j = 0; j < model.faces.Count; j++) { var face = model.faces[j]; if (face.Item1 - 1 == i || face.Item2 - 1 == i || face.Item3 - 1 == i) { sum = sum + faceNormals[j]; shared++; } } if (shared > 0) { sum = (sum / shared).normalize(); } model.normals[i] = sum; } }
// https://www.cnblogs.com/bitzhuwei/p/opengl-Computing-Tangent-Space-Basis-Vectors.html public override void Parse(ObjVNFContext context) { ObjVNFMesh mesh = context.Mesh; vec3[] vertexes = mesh.vertexes;// positions vec2[] texCoords = mesh.texCoords; vec3[] normals = mesh.normals; if (vertexes == null || texCoords == null || normals == null) { return; } if (vertexes.Length != texCoords.Length || vertexes.Length != normals.Length) { return; } ObjVNFFace[] faces = mesh.faces; if (faces == null || faces.Length == 0) { return; } // if (not triangles) { return; } if (faces[0].VertexIndexes().Count() != 3) { return; } var tangents = new vec3[normals.Length]; var biTangents = new vec3[normals.Length]; for (int i = 0; i < faces.Length; i++) { var face = faces[i] as ObjVNFTriangle; if (face == null) { return; } // no dealing with quad. uint[] vertexIndexes = face.VertexIndexes(); uint i0 = vertexIndexes[0]; uint i1 = vertexIndexes[1]; uint i2 = vertexIndexes[2]; vec3 p0 = vertexes[i0]; vec3 p1 = vertexes[i1]; vec3 p2 = vertexes[i2]; vec2 uv0 = texCoords[i0]; vec2 uv1 = texCoords[i1]; vec2 uv2 = texCoords[i2]; float x1 = p1.x - p0.x; float y1 = p1.y - p0.y; float z1 = p1.z - p0.z; float x2 = p2.x - p0.x; float y2 = p2.y - p0.y; float z2 = p2.z - p0.z; float s1 = uv1.x - uv0.x; float t1 = uv1.y - uv0.y; float s2 = uv2.x - uv0.x; float t2 = uv2.y - uv0.y; float r = 1.0F / (s1 * t2 - s2 * t1); var sdir = new vec3((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r); var tdir = new vec3((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r); //tangents[i0] += sdir; tangents[i0] = (float)i / (float)(i + 1) * tangents[i0] + sdir / (float)(i + 1); //tangents[i1] += sdir; tangents[i1] = (float)i / (float)(i + 1) * tangents[i1] + sdir / (float)(i + 1); //tangents[i2] += sdir; tangents[i2] = (float)i / (float)(i + 1) * tangents[i2] + sdir / (float)(i + 1); //biTangents[i0] += tdir; biTangents[i0] = (float)i / (float)(i + 1) * biTangents[i0] + sdir / (float)(i + 1); //biTangents[i1] += tdir; biTangents[i1] = (float)i / (float)(i + 1) * biTangents[i1] + sdir / (float)(i + 1); //biTangents[i2] += tdir; biTangents[i2] = (float)i / (float)(i + 1) * biTangents[i2] + sdir / (float)(i + 1); } var finalTangents = new vec4[normals.Length]; for (long a = 0; a < normals.Length; a++) { vec3 n = normals[a]; vec3 t = tangents[a]; // Calculate handedness float w = (n.cross(t).dot(biTangents[a]) < 0.0F) ? -1.0F : 1.0F; // Gram-Schmidt orthogonalize finalTangents[a] = new vec4((t - n * n.dot(t)).normalize(), w); } mesh.tangents = finalTangents; }