public void MouseMove(System.Windows.Forms.MouseEventArgs e, GLCamera camera) { if (e.Button == System.Windows.Forms.MouseButtons.Right) { // Update the mouse location. mouseTranslation = Intersect(e.X, e.Y, camera) - mouseTranslationOrigin; } }
public void MouseButtonDown(System.Windows.Forms.MouseEventArgs e, GLCamera camera) { if (e.Button == System.Windows.Forms.MouseButtons.Right) { // Store the origin of the mouse. mouseTranslationOrigin = Intersect(e.X, e.Y, camera); mouseTranslation = Vector3.Zero; } }
public void MouseButtonUp(System.Windows.Forms.MouseEventArgs e, GLCamera camera) { if (e.Button == System.Windows.Forms.MouseButtons.Right) { // Get the current location of the mouse. mouseTranslation = Intersect(e.X, e.Y, camera) - mouseTranslationOrigin; // Compute the new model location. modelTranslation += mouseTranslation; // Clear the mouse origin. mouseTranslationOrigin = Vector3.Zero; mouseTranslation = Vector3.Zero; } }
/// <summary> /// Computes the intersection point between the mouse coordinate vector and the plane /// formed by the model's location and the camera's eye. /// </summary> /// <param name="x">The X mouse coordinate.</param> /// <param name="y">The Y mouse coordinate.</param> /// <param name="camera">The camera.</param> private Vector3 Intersect(int x, int y, GLCamera camera) { // Invert the transformation pipeline. Matrix4 inverseProjectionView = camera.View * camera.Projection; inverseProjectionView.Invert(); // Transform mouse coordinates into world space. // We are "mouse" space. Need to convert into screen space. Vector4 worldMouse = new Vector4(x, y, 1, 1); int[] viewport = new int[4]; GL.GetInteger(GetPName.Viewport, viewport); worldMouse.X = (2.0f * (worldMouse.X - viewport[0]) / viewport[2]) - 1.0f; worldMouse.Y = -((2.0f * (worldMouse.Y - viewport[1]) / viewport[3]) - 1.0f); // We are in screen space. Need to convert into view space and then world space. worldMouse = Vector4.Transform(worldMouse, inverseProjectionView); if (worldMouse.W > float.Epsilon || worldMouse.W < float.Epsilon) { worldMouse.X /= worldMouse.W; worldMouse.Y /= worldMouse.W; worldMouse.Z /= worldMouse.W; } // The model translation is applied in VIEW space. So, we need to project it back // into world space for these calculations. We need to remove the translation components of the view // matrix. Matrix4 viewRotation = camera.View; viewRotation.M41 = 0; viewRotation.M42 = 0; viewRotation.M43 = 0; Matrix4 inverseViewRotation = Matrix4.Invert(viewRotation); Vector3 worldModelTranslation = Vector3.Transform(modelTranslation, inverseViewRotation); // Get the world location of the model. This is the point on the plane. Vector3 planePoint = worldModelTranslation; // Get the camera eye. This is the line origin. Vector3 lineOrigin = camera.Eye; // Create the normal of the plane. Vector3 planeNormal = lineOrigin - planePoint; planeNormal.Normalize(); // Create the direction of the line intersecting the plane. Vector3 lineDirection = new Vector3(worldMouse); lineDirection -= lineOrigin; lineDirection.Normalize(); // Computes the distance along the line until it intersects the plane. // Note: In pure math, there are three possible solutions. // 1.) The line intersects the plane once. Normal solution. // 2.) The line is outside and parallel to the plane. Denom -> 0 -> Undefined solution. // 3.) The line is contained inside the plane. Denom & Num -> 0 -> Indeterminate solution. // However, in the scope of this problem, only solution 1.) is possible because of the constraints of the camera class. // So, we assume nothing crazy can happen with this computation (which is probably a terrible assumption but oh well). float distance = Vector3.Dot(planePoint - lineOrigin, planeNormal) / Vector3.Dot(lineDirection, planeNormal); // Calculate the new model location. Vector3 result = lineOrigin + lineDirection * distance; // Convert back into view space. result = Vector3.Transform(result, viewRotation); return(result); }
/// <summary> /// Draws the scene. /// </summary> /// <param name="camera">The camera for the scene.</param> public void Render(GLCamera camera) { // Clear back buffers. GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit | ClearBufferMask.StencilBufferBit); // Enable a normal depth test without stenciling. GL.Enable(EnableCap.DepthTest); GL.Disable(EnableCap.StencilTest); GL.DepthFunc(DepthFunction.Less); GLShaderProgram program = null; // Add the translation in view space. This allows the model to rotate around // itself instead of the origin in world space. Matrix4 view = camera.View; view.M41 += modelTranslation.X + mouseTranslation.X; view.M42 += modelTranslation.Y + mouseTranslation.Y; view.M43 += modelTranslation.Z + mouseTranslation.Z; // // Load shaders for Phong lit static models. // program = programs["phong"]; program.Load(); // // Update parameters for phong lighting. // // Vertex Shader Uniforms program.UpdateUniform("u_WorldView", world * view); program.UpdateUniform("u_WorldViewProjection", world * view * camera.Projection); // Fragment Shader Uniforms program.UpdateUniform("u_LightDirection", new Vector3(0.0f, 0.0f, 1.0f)); program.UpdateUniform("u_LightDiffuse", new Vector4(1.0f, 1.0f, 1.0f, 1.0f)); program.UpdateUniform("u_KA", 0.85f); program.UpdateUniform("u_KD", 0.1f); program.UpdateUniform("u_KS", 0.05f); program.UpdateUniform("u_SExponent", 8.0f); // Draw Static Model // Load the model's texture for the shader. GL.ActiveTexture(TextureUnit.Texture0); program.UpdateUniform("u_Texture", 0); if (staticModel.TextureName != String.Empty) { textures[staticModel.TextureName].Bind(); // not checking return value } staticModel.Draw(); GL.UseProgram(0); // // Load shaders for Phong lit rigged models. // program = programs["phongRigged"]; program.Load(); // // Update parameters for phong lighting. // // Fragment Shader Uniforms program.UpdateUniform("u_LightDirection", new Vector3(0.0f, 0.0f, 1.0f)); program.UpdateUniform("u_LightDiffuse", new Vector4(1.0f, 1.0f, 1.0f, 1.0f)); program.UpdateUniform("u_KA", 0.85f); program.UpdateUniform("u_KD", 0.1f); program.UpdateUniform("u_KS", 0.05f); program.UpdateUniform("u_SExponent", 8.0f); // Draw Rigged Model // // Update the uniforms. // // Textures vary. GL.ActiveTexture(TextureUnit.Texture0); program.UpdateUniform("u_Texture", 0); if (riggedModel.TextureName != String.Empty) { textures[riggedModel.TextureName].Bind(); // not checking return value } // // Bone Transforms // if (IsSkinning == true) { // Get the transformations from the rig. boneTransforms = riggedModel.GetBoneTransformations(ref boneTransforms); } program.UpdateUniform("u_BoneTransform", boneTransforms); // // World Transform. // Matrix4 worldView = world * view; // Vertex Shader Uniforms program.UpdateUniform("u_WorldView", worldView); program.UpdateUniform("u_WorldViewProjection", worldView * camera.Projection); riggedModel.Draw(); // Unload shaders. GL.UseProgram(0); }