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> /// Builds a rotation 4 * 4 matrix created from an axis vector and an angle. /// </summary> /// <param name="m">The m.</param> /// <param name="angleDegree">Angle in Degree.</param> /// <param name="v">The v.</param> /// <returns></returns> public static mat4 rotate(mat4 m, float angleDegree, vec3 v) { float c = (float)Math.Cos(angleDegree * Math.PI / 180.0); float s = (float)Math.Sin(angleDegree * Math.PI / 180.0); vec3 axis = v.normalize(); vec3 temp = (1.0f - c) * axis; mat4 rotate = mat4.identity(); rotate[0, 0] = c + temp[0] * axis[0]; rotate[0, 1] = 0 + temp[0] * axis[1] + s * axis[2]; rotate[0, 2] = 0 + temp[0] * axis[2] - s * axis[1]; rotate[1, 0] = 0 + temp[1] * axis[0] - s * axis[2]; rotate[1, 1] = c + temp[1] * axis[1]; rotate[1, 2] = 0 + temp[1] * axis[2] + s * axis[0]; rotate[2, 0] = 0 + temp[2] * axis[0] + s * axis[1]; rotate[2, 1] = 0 + temp[2] * axis[1] - s * axis[0]; rotate[2, 2] = c + temp[2] * axis[2]; mat4 result = mat4.identity(); result[0] = m[0] * rotate[0][0] + m[1] * rotate[0][1] + m[2] * rotate[0][2]; result[1] = m[0] * rotate[1][0] + m[1] * rotate[1][1] + m[2] * rotate[1][2]; result[2] = m[0] * rotate[2][0] + m[1] * rotate[2][1] + m[2] * rotate[2][2]; result[3] = m[3]; return(result); }
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 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; } }
/// <summary> /// Quaternion from a rotation angle and axis. /// </summary> /// <param name="angleDegree"></param> /// <param name="axis"></param> public Quaternion(float angleDegree, vec3 axis) { if (axis.x == 0.0f && axis.y == 0.0f && axis.z == 0.0f) { Debug.WriteLine("Quaternion with axis not well defined!"); } vec3 normalized = axis.normalize(); double radian = angleDegree * Math.PI / 180.0; double halfRadian = radian / 2.0; this.w = (float)Math.Cos(halfRadian); float sin = (float)Math.Sin(halfRadian); this.x = sin * normalized.x; this.y = sin * normalized.y; this.z = sin * normalized.z; }
public AnnulusModel(float radius, float thickness, uint sliceCount, uint secondSliceCount) { { var positions = new vec3[sliceCount * secondSliceCount]; int t = 0; var y = new vec3(0, 1, 0); for (int i = 0; i < sliceCount; i++) { double di = 2 * Math.PI * i / sliceCount; var center = new vec3(radius * (float)Math.Sin(di), 0, radius * (float)Math.Cos(di)); float length = center.length(); center = center.normalize(); for (int j = 0; j < secondSliceCount; j++) { double dj = 2 * Math.PI * j / secondSliceCount; positions[t++] = center * (length - thickness * (float)Math.Cos(dj)) + y * (thickness * (float)Math.Sin(dj)); } } BoundingBox box = positions.Move2Center(); this.positions = positions; this.modelSize = box.MaxPosition - box.MinPosition; } { var indexes = new uint[sliceCount * (secondSliceCount * 3 + secondSliceCount * 3)]; uint t = 0; for (uint i = 0; i < sliceCount; i++) { for (uint j = 0; j < secondSliceCount; j++) { indexes[t++] = i * secondSliceCount + j; indexes[t++] = i * secondSliceCount + (j + 1) % secondSliceCount; indexes[t++] = (i * secondSliceCount + secondSliceCount + (j + 1) % secondSliceCount) % (sliceCount * secondSliceCount); indexes[t++] = i * secondSliceCount + j; indexes[t++] = (i * secondSliceCount + secondSliceCount + (j + 1) % secondSliceCount) % (sliceCount * secondSliceCount); indexes[t++] = (i * secondSliceCount + secondSliceCount + j) % (sliceCount * secondSliceCount); } } this.indexes = indexes; } }
/// <summary> /// /// </summary> /// <param name="radius"></param> /// <param name="latitudeParts">用纬线把地球切割为几块。</param> /// <param name="longitudeParts">用经线把地球切割为几块。</param> /// <returns></returns> internal SphereModel(float radius = 1.0f, int latitudeParts = 10, int longitudeParts = 40) { if (radius <= 0.0f || latitudeParts < 2 || longitudeParts < 3) { throw new Exception(); } int vertexCount = (latitudeParts + 1) * (longitudeParts + 1); this.positions = new vec3[vertexCount]; this.normals = new vec3[vertexCount]; this.colors = new vec3[vertexCount]; this.uv = new vec2[vertexCount]; int indexCount = (latitudeParts) * (2 * (longitudeParts + 1) + 1); this.indexes = new uint[indexCount]; int index = 0; //// 把星球平铺在一个平面上 //for (int i = 0; i < latitudeParts + 1; i++) //{ // double theta = (latitudeParts - i * 2) * Math.PI / 2 / latitudeParts; // double y = radius * Math.Sin(theta); // for (int j = 0; j < longitudeParts + 1; j++) // { // double x = radius * (i - latitudeParts / 2); // double z = radius * (j - longitudeParts / 2); // vec3 position = new vec3((float)x, (float)y, (float)z); // this.positions[index] = position; // this.normals[index] = position.normalize(); // this.colors[index] = colorGenerator(i, j); // index++; // } //} for (int i = 0; i < latitudeParts + 1; i++) { double theta = (latitudeParts - i * 2) * Math.PI / 2 / latitudeParts; double y = radius * Math.Sin(theta); for (int j = 0; j < longitudeParts + 1; j++) { double x = radius * Math.Cos(theta) * Math.Sin(j * Math.PI * 2 / longitudeParts); double z = radius * Math.Cos(theta) * Math.Cos(j * Math.PI * 2 / longitudeParts); vec3 position = new vec3((float)x, (float)y, (float)z); this.positions[index] = position; this.normals[index] = position.normalize(); vec3 color = position.normalize(); if (color.x < 0) { color.x = -(color.x / 2); } if (color.y < 0) { color.y = -(color.y / 2); } if (color.z < 0) { color.z = -(color.z / 2); } this.colors[index] = color; this.uv[index] = new vec2((float)j / (float)longitudeParts, (float)i / (float)latitudeParts); index++; } } // 索引 index = 0; for (int i = 0; i < latitudeParts; i++) { for (int j = 0; j < longitudeParts + 1; j++) { this.indexes[index++] = (uint)((longitudeParts + 1) * (i + 0) + j); this.indexes[index++] = (uint)((longitudeParts + 1) * (i + 1) + j); } // use // GL.Enable(GL.GL_PRIMITIVE_RESTART); // GL.PrimitiveRestartIndex(uint.MaxValue); // GL.Disable(GL.GL_PRIMITIVE_RESTART); this.indexes[index++] = uint.MaxValue; } }
public DiskModel(float radius, float holeRadius, float halfThickness, uint sliceCount, uint secondSliceCount) { float planeRadius = radius - holeRadius - halfThickness; uint[] outUpSphere = new uint[sliceCount]; uint[] outDownSphere = new uint[sliceCount]; uint[] inUpSphere = new uint[sliceCount]; uint[] inDownSphere = new uint[sliceCount]; { var positions = new vec3[sliceCount * ((secondSliceCount + 1) * 2)]; uint t = 0; var y = new vec3(0, 1, 0); for (int i = 0; i < sliceCount; i++) { outUpSphere[i] = t; double di = 2 * Math.PI * i / sliceCount; var center = new vec3(radius * (float)Math.Sin(di), 0, radius * (float)Math.Cos(di)); center = center.normalize(); for (int j = 0; j < (secondSliceCount + 1); j++) { double dj = Math.PI / 2 + Math.PI * j / (secondSliceCount); positions[t++] = center * ((radius + planeRadius) - halfThickness * (float)Math.Cos(dj)) + y * (halfThickness * (float)Math.Sin(dj)); } outDownSphere[i] = t - 1; } for (int i = 0; i < sliceCount; i++) { inDownSphere[i] = t; double di = 2 * Math.PI * i / sliceCount; var center = new vec3(radius * (float)Math.Sin(di), 0, radius * (float)Math.Cos(di)); center = center.normalize(); for (int j = 0; j < (secondSliceCount + 1); j++) { double dj = Math.PI / 2 + Math.PI + Math.PI * j / (secondSliceCount); positions[t++] = center * ((radius - planeRadius) - halfThickness * (float)Math.Cos(dj)) + y * (halfThickness * (float)Math.Sin(dj)); } inUpSphere[i] = t - 1; } BoundingBox box = positions.Move2Center(); this.positions = positions; this.modelSize = box.MaxPosition - box.MinPosition; } { var indexes = new uint[(sliceCount * (secondSliceCount) * 2 * 3 * 2) + sliceCount * 2 * 3 + sliceCount * 2 * 3]; uint t = 0; for (uint i = 0; i < sliceCount; i++) { for (uint j = 0; j < secondSliceCount; j++) { indexes[t++] = outUpSphere[i] + j; indexes[t++] = outUpSphere[i] + (j + 1); indexes[t++] = outUpSphere[(i + 1) % sliceCount] + j + 1; indexes[t++] = outUpSphere[i] + j; indexes[t++] = outUpSphere[(i + 1) % sliceCount] + j + 1; indexes[t++] = outUpSphere[(i + 1) % sliceCount] + j; } } for (uint i = 0; i < sliceCount; i++) { for (uint j = 0; j < secondSliceCount; j++) { indexes[t++] = inDownSphere[i] + j; indexes[t++] = inDownSphere[i] + (j + 1); indexes[t++] = inDownSphere[(i + 1) % sliceCount] + j + 1; indexes[t++] = inDownSphere[i] + j; indexes[t++] = inDownSphere[(i + 1) % sliceCount] + j + 1; indexes[t++] = inDownSphere[(i + 1) % sliceCount] + j; } } for (uint i = 0; i < sliceCount; i++) { indexes[t++] = inUpSphere[i]; indexes[t++] = outUpSphere[i]; indexes[t++] = outUpSphere[(i + 1) % sliceCount]; indexes[t++] = inUpSphere[i]; indexes[t++] = outUpSphere[(i + 1) % sliceCount]; indexes[t++] = inUpSphere[(i + 1) % sliceCount]; } for (uint i = 0; i < sliceCount; i++) { indexes[t++] = inDownSphere[i]; indexes[t++] = outDownSphere[(i + 1) % sliceCount]; indexes[t++] = outDownSphere[i]; indexes[t++] = inDownSphere[i]; indexes[t++] = inDownSphere[(i + 1) % sliceCount]; indexes[t++] = outDownSphere[(i + 1) % sliceCount]; } this.indexes = indexes; } }
/// <summary> /// /// </summary> /// <param name="radius"></param> /// <param name="latitudeParts">用纬线把地球切割为几块。</param> /// <param name="longitudeParts">用经线把地球切割为几块。</param> /// <param name="colorGenerator"></param> /// <returns></returns> internal SphereModel(float radius = 1.0f, int latitudeParts = 10, int longitudeParts = 40, Func <int, int, vec3> colorGenerator = null) { if (radius <= 0.0f || latitudeParts < 2 || longitudeParts < 3) { throw new Exception(); } if (colorGenerator == null) { colorGenerator = defaultColorGenerator; } int vertexCount = (latitudeParts + 1) * (longitudeParts); this.positions = new vec3[vertexCount]; this.normals = new vec3[vertexCount]; this.colors = new vec3[vertexCount]; int indexCount = (latitudeParts) * (2 * (longitudeParts + 1) + 1); this.indexes = new uint[indexCount]; int index = 0; for (int i = 0; i < latitudeParts + 1; i++) { double theta = (latitudeParts - i * 2) * Math.PI / 2 / latitudeParts; double y = radius * Math.Sin(theta); for (int j = 0; j < longitudeParts; j++) { double x = radius * Math.Cos(theta) * Math.Sin(j * Math.PI * 2 / longitudeParts); double z = radius * Math.Cos(theta) * Math.Cos(j * Math.PI * 2 / longitudeParts); vec3 position = new vec3((float)x, (float)y, (float)z); this.positions[index] = position; this.normals[index] = position.normalize(); this.colors[index] = colorGenerator(i, j); index++; } } // 索引 index = 0; for (int i = 0; i < latitudeParts; i++) { for (int j = 0; j < (longitudeParts); j++) { this.indexes[index++] = (uint)((longitudeParts) * (i + 0) + j); this.indexes[index++] = (uint)((longitudeParts) * (i + 1) + j); } { this.indexes[index++] = (uint)((longitudeParts) * (i + 0) + 0); this.indexes[index++] = (uint)((longitudeParts) * (i + 1) + 0); } // use // GL.Enable(GL.GL_PRIMITIVE_RESTART); // GL.PrimitiveRestartIndex(uint.MaxValue); // GL.Disable(GL.GL_PRIMITIVE_RESTART); this.indexes[index++] = uint.MaxValue; } }
public DiskModel(float radius, float holeRadius, float thickness, uint sliceCount, uint secondSliceCount) { uint upPlane, downPlane; uint[] upSphere = new uint[sliceCount]; uint[] downSphere = new uint[sliceCount]; { var positions = new vec3[sliceCount * secondSliceCount + sliceCount + sliceCount]; uint t = 0; var y = new vec3(0, 1, 0); for (int i = 0; i < sliceCount; i++) { upSphere[i] = t; double di = 2 * Math.PI * i / sliceCount; var center = new vec3(radius * (float)Math.Sin(di), 0, radius * (float)Math.Cos(di)); float length = center.length(); center = center.normalize(); for (int j = 0; j < secondSliceCount; j++) { double dj = Math.PI / 2 + Math.PI * j / (secondSliceCount - 1); positions[t++] = center * (length - thickness * (float)Math.Cos(dj)) + y * (thickness * (float)Math.Sin(dj)); } downSphere[i] = t - 1; } upPlane = t; for (int i = 0; i < sliceCount; i++) { double di = 2 * Math.PI * i / sliceCount; positions[t++] = new vec3(holeRadius * (float)Math.Sin(di), thickness, holeRadius * (float)Math.Cos(di)); } downPlane = t; for (int i = 0; i < sliceCount; i++) { double di = 2 * Math.PI * i / sliceCount; positions[t++] = new vec3(holeRadius * (float)Math.Sin(di), -thickness, holeRadius * (float)Math.Cos(di)); } BoundingBox box = positions.Move2Center(); this.positions = positions; this.modelSize = box.MaxPosition - box.MinPosition; } { var indexes = new uint[sliceCount * (secondSliceCount - 1) * 2 * 3 + sliceCount * 2 * 3 + sliceCount * 2 * 3 + sliceCount * 2 * 3]; uint t = 0; for (uint i = 0; i < sliceCount; i++) { for (uint j = 0; j < secondSliceCount - 1; j++) { indexes[t++] = i * secondSliceCount + j; indexes[t++] = i * secondSliceCount + (j + 1) % secondSliceCount; indexes[t++] = (i * secondSliceCount + secondSliceCount + (j + 1) % secondSliceCount) % (sliceCount * secondSliceCount); indexes[t++] = i * secondSliceCount + j; indexes[t++] = (i * secondSliceCount + secondSliceCount + (j + 1) % secondSliceCount) % (sliceCount * secondSliceCount); indexes[t++] = (i * secondSliceCount + secondSliceCount + j) % (sliceCount * secondSliceCount); } } for (uint i = 0; i < sliceCount; i++) { indexes[t++] = upPlane + i; indexes[t++] = upSphere[i]; indexes[t++] = upPlane + (i + 1) % sliceCount; indexes[t++] = upPlane + (i + 1) % sliceCount; indexes[t++] = upSphere[i]; indexes[t++] = upSphere[(i + 1) % sliceCount]; } for (uint i = 0; i < sliceCount; i++) { indexes[t++] = downPlane + i; indexes[t++] = downPlane + (i + 1) % sliceCount; indexes[t++] = downSphere[i]; indexes[t++] = downPlane + (i + 1) % sliceCount; indexes[t++] = downSphere[(i + 1) % sliceCount]; indexes[t++] = downSphere[i]; } for (uint i = 0; i < sliceCount; i++) { indexes[t++] = upPlane + i; indexes[t++] = upPlane + (i + 1) % sliceCount; indexes[t++] = downPlane + i; indexes[t++] = downPlane + i; indexes[t++] = upPlane + (i + 1) % sliceCount; indexes[t++] = downPlane + (i + 1) % sliceCount; } this.indexes = indexes; } }