/// <summary> /// 把连续16个float值按照列优先的顺序转换为mat4 /// </summary> /// <param name="values"></param> /// <param name="startIndex"></param> /// <returns></returns> public static mat4 ToMat4(this float[] values, int startIndex = 0) { mat4 result; result = new mat4( values.ToVec4(startIndex + 0), values.ToVec4(startIndex + 4), values.ToVec4(startIndex + 8), values.ToVec4(startIndex + 12)); return result; }
void element_BeforeRendering(object sender, Objects.RenderEventArgs e) { rotation += 3.0f; modelMatrix = glm.rotate(rotation, new vec3(0, 1, 0)); viewMatrix = this.camera.GetViewMat4(); projectionMatrix = this.camera.GetProjectionMat4(); mat4 mvp = projectionMatrix * viewMatrix * modelMatrix; IMVP element = sender as IMVP; element.SetShaderProgram(mvp); }
void glCanvas1_OpenGLDraw(object sender, PaintEventArgs e) { rotation += 3.0f; modelMatrix = glm.rotate(rotation, new vec3(0, 1, 0)); viewMatrix = this.camera.GetViewMat4(); projectionMatrix = this.camera.GetProjectionMat4(); mat4 mvp = projectionMatrix * viewMatrix * modelMatrix; element.mvp = mvp; //GL.ClearColor(0x87 / 255.0f, 0xce / 255.0f, 0xeb / 255.0f, 0xff / 255.0f); GL.Clear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); var arg = new RenderEventArgs(RenderModes.Render, this.camera); element.Render(arg); }
private void glCanvas1_OpenGLDraw(object sender, PaintEventArgs e) { rotation += 3.0f; mat4 modelMatrix = glm.rotate(rotation, new vec3(0, 1, 0)); const float distance = 0.7f; viewMatrix = glm.lookAt(new vec3(-distance, distance, -distance), new vec3(0, 0, 0), new vec3(0, -1, 0)); int[] viewport = new int[4]; GL.GetInteger(GetTarget.Viewport, viewport); projectionMatrix = glm.perspective(60.0f, (float)viewport[2] / (float)viewport[3], 0.01f, 100.0f); mat4 mvp = projectionMatrix * viewMatrix * modelMatrix; pyramidElement.mvp = mvp; GL.Clear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); var arg = new RenderEventArgs(RenderModes.Render, null); pyramidElement.Render(arg); }
/// <summary> /// Creates a matrix for a symmetric perspective-view frustum with far plane at infinite. /// </summary> /// <param name="fovy">The fovy.</param> /// <param name="aspect">The aspect.</param> /// <param name="zNear">The z near.</param> /// <returns></returns> public static mat4 infinitePerspective(float fovy, float aspect, float zNear) { float range = tan(fovy / (2f)) * zNear; float left = -range * aspect; float right = range * aspect; float bottom = -range; float top = range; var result = new mat4(0); result[0, 0] = ((2f) * zNear) / (right - left); result[1, 1] = ((2f) * zNear) / (top - bottom); result[2, 2] = -(1f); result[2, 3] = -(1f); result[3, 2] = -(2f) * zNear; return result; }
void pyramidElement_BeforeRendering(object sender, Objects.RenderEventArgs e) { rotation += 3.0f; mat4 modelMatrix = glm.rotate(rotation, new vec3(0, 1, 0)); const float distance = 0.7f; viewMatrix = glm.lookAt(new vec3(-distance, distance, -distance), new vec3(0, 0, 0), new vec3(0, -1, 0)); int[] viewport = new int[4]; GL.GetInteger(GetTarget.Viewport, viewport); projectionMatrix = glm.perspective(60.0f, (float)viewport[2] / (float)viewport[3], 0.01f, 100.0f); mat4 mvp = projectionMatrix * viewMatrix * modelMatrix; IMVP element = sender as IMVP; element.SetShaderProgram(mvp); }
/// <summary> /// Build a look at view matrix. /// </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 f = (center - eye); f.Normalize(); vec3 s = f.cross(up); s.Normalize(); vec3 u = s.cross(f); mat4 Result = new mat4(1); Result[0, 0] = s.x; Result[1, 0] = s.y; Result[2, 0] = s.z; Result[0, 1] = u.x; Result[1, 1] = u.y; Result[2, 1] = u.z; Result[0, 2] = -f.x; Result[1, 2] = -f.y; Result[2, 2] = -f.z; Result[3, 0] = -s.dot(eye);// dot(s, eye); Result[3, 1] = -u.dot(eye);// dot(u, eye); Result[3, 2] = f.dot(eye);// dot(f, eye); return Result; }
/// <summary> /// Builds a perspective projection matrix based on a field of view. /// </summary> /// <param name="fov">The fov (in radians).</param> /// <param name="width">The width.</param> /// <param name="height">The height.</param> /// <param name="zNear">The z near.</param> /// <param name="zFar">The z far.</param> /// <returns></returns> /// <exception cref="System.ArgumentOutOfRangeException"></exception> public static mat4 perspectiveFov(float fov, float width, float height, float zNear, float zFar) { if (width <= 0 || height <= 0 || fov <= 0) { throw new ArgumentOutOfRangeException(); } var rad = fov; var h = glm.cos((0.5f) * rad) / glm.sin((0.5f) * rad); var w = h * height / width; var result = new mat4(0); result[0, 0] = w; result[1, 1] = h; result[2, 2] = -(zFar + zNear) / (zFar - zNear); result[2, 3] = -(1f); result[3, 2] = -((2f) * zFar * zNear) / (zFar - zNear); return(result); }
/// <summary> /// Define a picking region. /// </summary> /// <param name="center">The center.</param> /// <param name="delta">The delta.</param> /// <param name="viewport">The viewport.</param> /// <returns></returns> /// <exception cref="System.ArgumentOutOfRangeException"></exception> public static mat4 pickMatrix(vec2 center, vec2 delta, vec4 viewport) { if (delta.x <= 0 || delta.y <= 0) { throw new ArgumentOutOfRangeException(); } var Result = new mat4(1.0f); if (!(delta.x > (0f) && delta.y > (0f))) { return(Result); // Error } vec3 Temp = new vec3( ((viewport[2]) - (2f) * (center.x - (viewport[0]))) / delta.x, ((viewport[3]) - (2f) * (center.y - (viewport[1]))) / delta.y, (0f)); // Translate and scale the picked region to the entire window Result = translate(Result, Temp); return(scale(Result, new vec3((viewport[2]) / delta.x, (viewport[3]) / delta.y, (1)))); }
/// <summary> /// Build a look at view matrix. /// </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); Result[0, 0] = right.x; Result[1, 0] = right.y; Result[2, 0] = right.z; Result[0, 1] = standardUp.x; Result[1, 1] = standardUp.y; Result[2, 1] = standardUp.z; Result[0, 2] = -forward.x; Result[1, 2] = -forward.y; Result[2, 2] = -forward.z; 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); }
/// <summary> /// Build a look at view matrix. /// </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 f = (center - eye); f.Normalize(); vec3 s = f.cross(up); s.Normalize(); vec3 u = s.cross(f); mat4 Result = new mat4(1); Result[0, 0] = s.x; Result[1, 0] = s.y; Result[2, 0] = s.z; Result[0, 1] = u.x; Result[1, 1] = u.y; Result[2, 1] = u.z; Result[0, 2] = -f.x; Result[1, 2] = -f.y; Result[2, 2] = -f.z; Result[3, 0] = -s.dot(eye); // dot(s, eye); Result[3, 1] = -u.dot(eye); // dot(u, eye); Result[3, 2] = f.dot(eye); // dot(f, eye); return(Result); }
/// <summary> /// Map the specified object coordinates (obj.x, obj.y, obj.z) into window coordinates. /// </summary> /// <param name="obj">The object.</param> /// <param name="model">The model.</param> /// <param name="proj">The proj.</param> /// <param name="viewport">The viewport.</param> /// <returns></returns> public static vec3 project(vec3 obj, mat4 model, mat4 proj, vec4 viewport) { vec4 tmp = new vec4(obj, (1f)); tmp = model * tmp; tmp = proj * tmp; tmp /= tmp.w; tmp = tmp * 0.5f + new vec4(0.5f, 0.5f, 0.5f, 0.5f); tmp[0] = tmp[0] * viewport[2] + viewport[0]; tmp[1] = tmp[1] * viewport[3] + viewport[1]; return new vec3(tmp.x, tmp.y, tmp.z); }
void IMVP.SetShaderProgram(mat4 mvp) { IMVP element = this.element as IMVP; element.SetShaderProgram(mvp); }
/// <summary> /// Multiplies the <paramref name="lhs"/> matrix by the <paramref name="rhs"/> matrix. /// </summary> /// <param name="lhs">The LHS matrix.</param> /// <param name="rhs">The RHS matrix.</param> /// <returns>The product of <paramref name="lhs"/> and <paramref name="rhs"/>.</returns> public static mat4 operator *(mat4 lhs, mat4 rhs) { mat4 result = new mat4( new vec4( lhs[0][0] * rhs[0][0] + lhs[1][0] * rhs[0][1] + lhs[2][0] * rhs[0][2] + lhs[3][0] * rhs[0][3], lhs[0][1] * rhs[0][0] + lhs[1][1] * rhs[0][1] + lhs[2][1] * rhs[0][2] + lhs[3][1] * rhs[0][3], lhs[0][2] * rhs[0][0] + lhs[1][2] * rhs[0][1] + lhs[2][2] * rhs[0][2] + lhs[3][2] * rhs[0][3], lhs[0][3] * rhs[0][0] + lhs[1][3] * rhs[0][1] + lhs[2][3] * rhs[0][2] + lhs[3][3] * rhs[0][3] ), new vec4( lhs[0][0] * rhs[1][0] + lhs[1][0] * rhs[1][1] + lhs[2][0] * rhs[1][2] + lhs[3][0] * rhs[1][3], lhs[0][1] * rhs[1][0] + lhs[1][1] * rhs[1][1] + lhs[2][1] * rhs[1][2] + lhs[3][1] * rhs[1][3], lhs[0][2] * rhs[1][0] + lhs[1][2] * rhs[1][1] + lhs[2][2] * rhs[1][2] + lhs[3][2] * rhs[1][3], lhs[0][3] * rhs[1][0] + lhs[1][3] * rhs[1][1] + lhs[2][3] * rhs[1][2] + lhs[3][3] * rhs[1][3] ), new vec4( lhs[0][0] * rhs[2][0] + lhs[1][0] * rhs[2][1] + lhs[2][0] * rhs[2][2] + lhs[3][0] * rhs[2][3], lhs[0][1] * rhs[2][0] + lhs[1][1] * rhs[2][1] + lhs[2][1] * rhs[2][2] + lhs[3][1] * rhs[2][3], lhs[0][2] * rhs[2][0] + lhs[1][2] * rhs[2][1] + lhs[2][2] * rhs[2][2] + lhs[3][2] * rhs[2][3], lhs[0][3] * rhs[2][0] + lhs[1][3] * rhs[2][1] + lhs[2][3] * rhs[2][2] + lhs[3][3] * rhs[2][3] ), new vec4( lhs[0][0] * rhs[3][0] + lhs[1][0] * rhs[3][1] + lhs[2][0] * rhs[3][2] + lhs[3][0] * rhs[3][3], lhs[0][1] * rhs[3][0] + lhs[1][1] * rhs[3][1] + lhs[2][1] * rhs[3][2] + lhs[3][1] * rhs[3][3], lhs[0][2] * rhs[3][0] + lhs[1][2] * rhs[3][1] + lhs[2][2] * rhs[3][2] + lhs[3][2] * rhs[3][3], lhs[0][3] * rhs[3][0] + lhs[1][3] * rhs[3][1] + lhs[2][3] * rhs[3][2] + lhs[3][3] * rhs[3][3] ) ); return result; }
/// <summary> /// Define a picking region. /// </summary> /// <param name="center">The center.</param> /// <param name="delta">The delta.</param> /// <param name="viewport">The viewport.</param> /// <returns></returns> /// <exception cref="System.ArgumentOutOfRangeException"></exception> public static mat4 pickMatrix(vec2 center, vec2 delta, vec4 viewport) { if (delta.x <= 0 || delta.y <= 0) throw new ArgumentOutOfRangeException(); var Result = new mat4(1.0f); if (!(delta.x > (0f) && delta.y > (0f))) return Result; // Error vec3 Temp = new vec3( ((viewport[2]) - (2f) * (center.x - (viewport[0]))) / delta.x, ((viewport[3]) - (2f) * (center.y - (viewport[1]))) / delta.y, (0f)); // Translate and scale the picked region to the entire window Result = translate(Result, Temp); return scale(Result, new vec3((viewport[2]) / delta.x, (viewport[3]) / delta.y, (1))); }
void IMVP.SetShaderProgram(mat4 mvp) { ShaderProgram shaderProgram = this.currentShaderProgram; shaderProgram.Bind(); if (shaderProgram == this.pickingShaderProgram) { shaderProgram.SetUniform("pickingBaseID", ((IColorCodedPicking)this).PickingBaseID); shaderProgram.SetUniformMatrix4(strMVP, mvp.to_array()); } else { shaderProgram.SetUniformMatrix4(strMVP, mvp.to_array()); } }
/// <summary> /// Applies a translation transformation to matrix <paramref name="m"/> by vector <paramref name="v"/>. /// </summary> /// <param name="m">The matrix to transform.</param> /// <param name="v">The vector to translate by.</param> /// <returns><paramref name="m"/> translated by <paramref name="v"/>.</returns> public static mat4 translate(mat4 m, vec3 v) { mat4 result = m; result[3] = m[0] * v[0] + m[1] * v[1] + m[2] * v[2] + m[3]; return result; }
/// <summary> /// Builds a rotation 4 * 4 matrix created from an axis vector and an angle. /// </summary> /// <param name="m">The m.</param> /// <param name="angle">The angle.</param> /// <param name="v">The v.</param> /// <returns></returns> public static mat4 rotate(mat4 m, float angle, vec3 v) { float c = cos(angle); float s = sin(angle); vec3 axis = v; axis.Normalize();// normalize(v); 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; }
/// <summary> /// Map the specified window coordinates (win.x, win.y, win.z) into object coordinates. /// </summary> /// <param name="win">The win.</param> /// <param name="model">The model.</param> /// <param name="proj">The proj.</param> /// <param name="viewport">The viewport.</param> /// <returns></returns> public static vec3 unProject(vec3 win, mat4 model, mat4 proj, vec4 viewport) { mat4 Inverse = glm.inverse(proj * model); vec4 tmp = new vec4(win, (1f)); tmp.x = (tmp.x - (viewport[0])) / (viewport[2]); tmp.y = (tmp.y - (viewport[1])) / (viewport[3]); tmp = tmp * (2f) - new vec4(1, 1, 1, 1); vec4 obj = Inverse * tmp; obj /= obj.w; return new vec3(obj); }
/// <summary> /// Creates a matrix for a symmetric perspective-view frustum with far plane /// at infinite for graphics hardware that doesn't support depth clamping. /// </summary> /// <param name="fovy">The fovy.</param> /// <param name="aspect">The aspect.</param> /// <param name="zNear">The z near.</param> /// <returns></returns> public static mat4 tweakedInfinitePerspective(float fovy, float aspect, float zNear) { float range = tan(fovy / (2)) * zNear; float left = -range * aspect; float right = range * aspect; float bottom = -range; float top = range; mat4 Result = new mat4((0f)); Result[0, 0] = ((2) * zNear) / (right - left); Result[1, 1] = ((2) * zNear) / (top - bottom); Result[2, 2] = (0.0001f) - (1f); Result[2, 3] = (-1); Result[3, 2] = -((0.0001f) - (2)) * zNear; return Result; }
public static void TypicalScene() { const int count = 1000000; long startTick = 0; long interval, interval2; // 测试float类型 { var floatArray = new UnmanagedArray<float>(count); startTick = DateTime.Now.Ticks; for (int i = 0; i < count; i++) { floatArray[i] = i; } for (int i = 0; i < count; i++) { var item = floatArray[i]; if (item != i) { throw new Exception(); } } interval = DateTime.Now.Ticks - startTick; unsafe { startTick = DateTime.Now.Ticks; float* header = (float*)floatArray.FirstElement(); float* last = (float*)floatArray.LastElement(); float* tailAddress = (float*)floatArray.TailAddress(); int value = 0; for (float* ptr = header; ptr <= last/*or: ptr < tailAddress*/; ptr++) { *ptr = value++; } int i = 0; for (float* ptr = header; ptr <= last/*or: ptr < tailAddress*/; ptr++, i++) { var item = *ptr; if (item != i) { throw new Exception(); } } interval2 = DateTime.Now.Ticks - startTick; } Console.WriteLine("Ticks: safe: {0} vs unsafe: {1}", interval, interval2); } // 测试decimal类型 { var decimalArray = new UnmanagedArray<decimal>(count); startTick = DateTime.Now.Ticks; for (int i = 0; i < count; i++) { decimalArray[i] = i; } for (int i = 0; i < count; i++) { var item = decimalArray[i]; if (item != i) { throw new Exception(); } } interval = DateTime.Now.Ticks - startTick; unsafe { startTick = DateTime.Now.Ticks; decimal* header = (decimal*)decimalArray.FirstElement(); decimal* last = (decimal*)decimalArray.LastElement(); decimal* tailAddress = (decimal*)decimalArray.TailAddress(); int value = 0; for (decimal* ptr = header; ptr <= last/*or: ptr < tailAddress*/; ptr++) { *ptr = value++; } int i = 0; for (decimal* ptr = header; ptr <= last/*or: ptr < tailAddress*/; ptr++, i++) { var item = *ptr; if (item != i) { throw new Exception(); } } interval2 = DateTime.Now.Ticks - startTick; } Console.WriteLine("Ticks: safe: {0} vs unsafe: {1}", interval, interval2); } // 测试int类型 { var intArray = new UnmanagedArray<int>(count); startTick = DateTime.Now.Ticks; for (int i = 0; i < count; i++) { intArray[i] = i; } for (int i = 0; i < count; i++) { var item = intArray[i]; if (item != i) { throw new Exception(); } } interval = DateTime.Now.Ticks - startTick; unsafe { startTick = DateTime.Now.Ticks; int* header = (int*)intArray.FirstElement(); int* last = (int*)intArray.LastElement(); int* tailAddress = (int*)intArray.TailAddress(); int value = 0; for (int* ptr = header; ptr <= last/*or: ptr < tailAddress*/; ptr++) { *ptr = value++; } int i = 0; for (int* ptr = header; ptr <= last/*or: ptr < tailAddress*/; ptr++, i++) { var item = *ptr; if (item != i) { throw new Exception(); } } interval2 = DateTime.Now.Ticks - startTick; } Console.WriteLine("Ticks: safe: {0} vs unsafe: {1}", interval, interval2); } // 测试bool类型 { var boolArray = new UnmanagedArray<bool>(count); startTick = DateTime.Now.Ticks; for (int i = 0; i < count; i++) { boolArray[i] = i % 2 == 0; } for (int i = 0; i < count; i++) { var item = boolArray[i]; if (item != (i % 2 == 0)) { throw new Exception(); } } interval = DateTime.Now.Ticks - startTick; unsafe { startTick = DateTime.Now.Ticks; bool* header = (bool*)boolArray.FirstElement(); bool* last = (bool*)boolArray.LastElement(); bool* tailAddress = (bool*)boolArray.TailAddress(); int value = 0; for (bool* ptr = header; ptr <= last/*or: ptr < tailAddress*/; ptr++) { *ptr = (value % 2 == 0); value++; } int i = 0; for (bool* ptr = header; ptr <= last/*or: ptr < tailAddress*/; ptr++, i++) { var item = *ptr; if (item != (i % 2 == 0)) { throw new Exception(); } } interval2 = DateTime.Now.Ticks - startTick; } Console.WriteLine("Ticks: safe: {0} vs unsafe: {1}", interval, interval2); } // 测试vec3类型 { var vec3Array = new UnmanagedArray<vec3>(count); startTick = DateTime.Now.Ticks; for (int i = 0; i < count; i++) { vec3Array[i] = new vec3(i * 3 + 0, i * 3 + 1, i * 3 + 2); } for (int i = 0; i < count; i++) { var item = vec3Array[i]; var old = new vec3(i * 3 + 0, i * 3 + 1, i * 3 + 2); if (item.x != old.x || item.y != old.y || item.z != old.z) { throw new Exception(); } } interval = DateTime.Now.Ticks - startTick; unsafe { startTick = DateTime.Now.Ticks; vec3* header = (vec3*)vec3Array.FirstElement(); vec3* last = (vec3*)vec3Array.LastElement(); vec3* tailAddress = (vec3*)vec3Array.TailAddress(); int i = 0; for (vec3* ptr = header; ptr <= last/*or: ptr < tailAddress*/; ptr++) { *ptr = new vec3(i * 3 + 0, i * 3 + 1, i * 3 + 2); i++; } i = 0; for (vec3* ptr = header; ptr <= last/*or: ptr < tailAddress*/; ptr++, i++) { var item = *ptr; var old = new vec3(i * 3 + 0, i * 3 + 1, i * 3 + 2); if (item.x != old.x || item.y != old.y || item.z != old.z) { throw new Exception(); } } interval2 = DateTime.Now.Ticks - startTick; } Console.WriteLine("Ticks: safe: {0} vs unsafe: {1}", interval, interval2); } // 测试mat4类型 { var vec3Array = new UnmanagedArray<mat4>(count); startTick = DateTime.Now.Ticks; for (int i = 0; i < count; i++) { vec3Array[i] = new mat4(new vec4(i, i + 1, i + 2, i + 3), new vec4(i, i + 1, i + 2, i + 3), new vec4(i, i + 1, i + 2, i + 3), new vec4(i, i + 1, i + 2, i + 3)); } for (int i = 0; i < count; i++) { var item = vec3Array[i]; var old = new mat4(new vec4(i, i + 1, i + 2, i + 3), new vec4(i, i + 1, i + 2, i + 3), new vec4(i, i + 1, i + 2, i + 3), new vec4(i, i + 1, i + 2, i + 3)); for (int col = 0; col < 4; col++) { for (int row = 0; row < 4; row++) { if (item[col][row] != old[col][row]) { throw new Exception(); } } } } interval = DateTime.Now.Ticks - startTick; unsafe { startTick = DateTime.Now.Ticks; mat4* header = (mat4*)vec3Array.FirstElement(); mat4* last = (mat4*)vec3Array.LastElement(); mat4* tailAddress = (mat4*)vec3Array.TailAddress(); int i = 0; for (mat4* ptr = header; ptr <= last/*or: ptr < tailAddress*/; ptr++) { *ptr = new mat4(new vec4(i, i + 1, i + 2, i + 3), new vec4(i, i + 1, i + 2, i + 3), new vec4(i, i + 1, i + 2, i + 3), new vec4(i, i + 1, i + 2, i + 3)); i++; } i = 0; for (mat4* ptr = header; ptr <= last/*or: ptr < tailAddress*/; ptr++, i++) { var item = *ptr; var old = new mat4(new vec4(i, i + 1, i + 2, i + 3), new vec4(i, i + 1, i + 2, i + 3), new vec4(i, i + 1, i + 2, i + 3), new vec4(i, i + 1, i + 2, i + 3)); for (int col = 0; col < 4; col++) { for (int row = 0; row < 4; row++) { if (item[col][row] != old[col][row]) { throw new Exception(); } } } } interval2 = DateTime.Now.Ticks - startTick; } Console.WriteLine("Ticks: safe: {0} vs unsafe: {1}", interval, interval2); } // 立即释放所有非托管数组占用的内存,任何之前创建的UnmanagedBase数组都不再可用了。 UnmanagedArray<int>.FreeAll(); }
/// <summary> /// Applies a scale transformation to matrix <paramref name="m"/> by vector <paramref name="v"/>. /// </summary> /// <param name="m">The matrix to transform.</param> /// <param name="v">The vector to scale by.</param> /// <returns><paramref name="m"/> scaled by <paramref name="v"/>.</returns> public static mat4 scale(mat4 m, vec3 v) { mat4 result = m; result[0] = m[0] * v[0]; result[1] = m[1] * v[1]; result[2] = m[2] * v[2]; result[3] = m[3]; return result; }
protected override void DoRender(RenderEventArgs e) { mat4 projectionMatrix, viewMatrix, modelMatrix; { IUILayout element = this as IUILayout; element.GetMatrix(out projectionMatrix, out viewMatrix, out modelMatrix, e.Camera); } this.mvp = projectionMatrix * viewMatrix * modelMatrix; this.shaderProgram.Bind(); this.shaderProgram.SetUniformMatrix4(strMVP, mvp.to_array()); GL.BindVertexArray(vao[0]); GL.DrawArrays(this.axisPrimitiveMode, 0, this.axisVertexCount); GL.BindVertexArray(0); this.shaderProgram.Unbind(); }
void IMVP.SetShaderProgram(mat4 mvp) { this.tex.Bind(); IMVPHelper.SetMVP(this, mvp); }
void IMVP.SetShaderProgram(mat4 mvp) { GL.Enable(GL.GL_VERTEX_PROGRAM_POINT_SIZE); GL.Enable(GL.GL_POINT_SPRITE_ARB); //GL.TexEnv(GL.GL_POINT_SPRITE_ARB, GL.GL_COORD_REPLACE_ARB, GL.GL_TRUE);//TODO: test TexEnvi() GL.TexEnvf(GL.GL_POINT_SPRITE_ARB, GL.GL_COORD_REPLACE_ARB, GL.GL_TRUE); GL.Enable(GL.GL_POINT_SMOOTH); GL.Hint(GL.GL_POINT_SMOOTH_HINT, GL.GL_NICEST); GL.Enable(GL.GL_BLEND); GL.BlendEquation(GL.GL_FUNC_ADD_EXT); GL.BlendFuncSeparate(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA, GL.GL_ONE, GL.GL_ONE); GL.BindTexture(GL.GL_TEXTURE_2D, this.texture[0]); IMVPHelper.SetMVP(this, mvp); //int[] poinSizes = new int[2]; //GL.GetInteger(GetTarget.PointSizeRange, poinSizes); //if (this.textureWidth > poinSizes[1]) //{ // GL.PointParameter(GL.GL_POINT_SIZE_MAX_ARB, this.textureWidth); // GL.GetInteger(GetTarget.PointSizeRange, poinSizes); // Console.WriteLine("asf"); //} shaderProgram.SetUniform(PointSpriteStringElement.strpointSize, this.textureWidth + 0.0f); shaderProgram.SetUniform(PointSpriteStringElement.strtex, this.texture[0]); shaderProgram.SetUniform(PointSpriteStringElement.strtextColor, this.textColor.x, this.textColor.y, this.textColor.z); }
/// <summary> /// 获取此UI元素的投影矩阵、视图矩阵和模型矩阵 /// </summary> /// <param name="uiElement"></param> /// <param name="projectionMatrix"></param> /// <param name="viewMatrix"></param> /// <param name="modelMatrix"></param> /// <param name="camera">如果为null,会以glm.lookAt(new vec3(0, 0, 1), new vec3(0, 0, 0), new vec3(0, 1, 0))计算默认值。</param> /// <param name="maxDepth">UI元素的外接球半径的倍数。</param> public static void GetMatrix(this IUILayout uiElement, out mat4 projectionMatrix, out mat4 viewMatrix, out mat4 modelMatrix, IViewCamera camera = null, float maxDepth = 2.0f) { IUILayoutArgs args = uiElement.GetArgs(); float max = (float)Math.Max(args.UIWidth, args.UIHeight); { //projectionMatrix = glm.ortho((float)args.left, (float)args.right, (float)args.bottom, (float)args.top, // TODO: / 2后与legacy opengl的UI元素显示就完全一致了。为什么??? projectionMatrix = glm.ortho((float)args.left / 2, (float)args.right / 2, (float)args.bottom / 2, (float)args.top / 2, uiElement.Param.zNear, uiElement.Param.zFar); // 下面注释掉的代码是用来测试legacy OpenGL的matrix与GLM库计算的matrix是否相同用的。已经证明了两者完全相同,此处仅作留念+以防万一。 //{ // float[] matrix = new float[16]; // GL.MatrixMode(GL.GL_PROJECTION); // GL.PushMatrix(); // GL.GetFloat(GetTarget.ProjectionMatrix, matrix); // GL.LoadIdentity(); // GL.GetFloat(GetTarget.ProjectionMatrix, matrix); // GL.Ortho(args.left / 2, args.right / 2, args.bottom / 2, args.top / 2, uiElement.Param.zNear, uiElement.Param.zFar); // GL.GetFloat(GetTarget.ProjectionMatrix, matrix);// this equals projectionMatrix // GL.PopMatrix(); //} // 把UI元素移到ortho长方体的最靠近camera的地方,这样就可以把UI元素放到OpenGL最前方。 projectionMatrix = glm.translate(projectionMatrix, new vec3(0, 0, uiElement.Param.zFar - max / 2 * maxDepth)); } { // UI元素不在三维场景中,所以其Camera可以是null。 if (camera == null) { //viewMatrix = glm.lookAt(new vec3(0, 0, 1), new vec3(0, 0, 0), new vec3(0, 1, 0)); viewMatrix = glm.lookAt( Camera.defaultPosition, Camera.defaultTarget, Camera.defaultUpVector); } else { vec3 position = camera.Position - camera.Target; position.Normalize(); viewMatrix = glm.lookAt(position, new vec3(0, 0, 0), camera.UpVector); } // 下面注释掉的代码是用来测试legacy OpenGL的matrix与GLM库计算的matrix是否相同用的。已经证明了两者完全相同,此处仅作留念+以防万一。 //{ // float[] matrix = new float[16]; // GL.MatrixMode(GL.GL_MODELVIEW); // GL.PushMatrix(); // GL.GetFloat(GetTarget.ModelviewMatix, matrix); // GL.LoadIdentity(); // GL.GetFloat(GetTarget.ModelviewMatix, matrix); // if(camera==null) // { // GL.gluLookAt(0, 0, 1, 0, 0, 0, 0, 1, 0); // } // else // { // vec3 position = camera.Position - camera.Target; // position.Normalize(); // GL.gluLookAt(position.x, position.y, position.z, 0, 0, 0, camera.UpVector.x, camera.UpVector.y, camera.UpVector.z); // } // GL.GetFloat(GetTarget.ModelviewMatix, matrix);// this equals viewMatrix // GL.PopMatrix(); //} } { modelMatrix = glm.scale(mat4.identity(), new vec3(args.UIWidth / 2, args.UIHeight / 2, max / 2)); // 下面注释掉的代码是用来测试legacy OpenGL的matrix与GLM库计算的matrix是否相同用的。已经证明了两者完全相同,此处仅作留念+以防万一。 //{ // float[] matrix = new float[16]; // GL.MatrixMode(GL.GL_MODELVIEW); // GL.PushMatrix(); // GL.GetFloat(GetTarget.ModelviewMatix, matrix); // GL.LoadIdentity(); // GL.GetFloat(GetTarget.ModelviewMatix, matrix); // GL.Scale(args.UIWidth / 2, args.UIHeight / 2, max / 2); // GL.GetFloat(GetTarget.ModelviewMatix, matrix);// this equals modelMatrix // GL.PopMatrix(); //} } }
void IMVP.SetShaderProgram(mat4 mvp) { //this.tex.Bind(); GL.CullFace(GL.GL_FRONT_AND_BACK); GL.PolygonMode(PolygonModeFaces.FrontAndBack, PolygonModes.Filled); GL.Enable(GL.GL_ALPHA_TEST); GL.AlphaFunc(GL.GL_GREATER, alphaThreshold); bool blend = this.blend; if (blend) { GL.Enable(GL.GL_BLEND); GL.BlendFunc(sFactor, dFactor); } uint textureID = this.textureProcessor.GetTexture3D(); GL.BindTexture(GL.GL_TEXTURE_3D, textureID); this.shaderProgram.Bind(); this.shaderProgram.SetUniform("tex", textureID); IMVPHelper.SetMVP(this, mvp); }
/// <summary> /// 如果此矩阵是glm.perspective()的结果,那么返回glm.perspective()的各个参数值。 /// </summary> /// <param name="matrix"></param> /// <param name="fovy"></param> /// <param name="aspectRatio"></param> /// <param name="zNear"></param> /// <param name="zFar"></param> /// <returns></returns> public static bool TryParse(this mat4 matrix, out float fovy, out float aspectRatio, out float zNear, out float zFar) { /* * var result = mat4.identity(); * float tangent = (float)Math.Tan(fovy / 2.0f); * float height = zNear * tangent; * float width = height * aspect; * float l = -width, r = width, b = -height, t = height, n = zNear, f = zFar; * result[0, 0] = 2 * n / (r - l);// = 2 * zNear / (2 * zNear * tangent * aspect) * result[1, 1] = 2 * n / (t - b);// = 2 * zNear / (2 * zNear * tangent) * result[2, 0] = (r + l) / (r - l);// = 0 * result[2, 1] = (t + b) / (t - b);// = 0 * result[2, 2] = -(f + n) / (f - n); * result[2, 3] = -1; * result[3, 2] = -(2 * f * n) / (f - n); * result[3, 3] = 0; */ float tanHalfFovy = 1.0f / matrix[1, 1]; fovy = 2 * (float)(Math.Atan(tanHalfFovy)); if (fovy < 0) { fovy = -fovy; } //aspectRatio = 1.0f / matrix[0, 0] / tanHalfFovy; aspectRatio = matrix[1, 1] / matrix[0, 0]; if (matrix[2, 2] == 1.0f) { zFar = 0.0f; zNear = 0.0f; } else if (matrix[2, 2] == -1.0f) { zNear = 0.0f; zFar = float.PositiveInfinity; } else { zNear = matrix[3, 2] / (matrix[2, 2] - 1); zFar = matrix[3, 2] / (matrix[2, 2] + 1); } if (matrix[0, 0] == 0.0f || matrix[1, 1] == 0.0f || matrix[2, 2] == 0.0f) { return(false); } if (matrix[1, 0] != 0.0f || matrix[3, 0] != 0.0f || matrix[0, 1] != 0.0f || matrix[3, 1] != 0.0f || matrix[0, 2] != 0.0f || matrix[1, 2] != 0.0f || matrix[0, 3] != 0.0f || matrix[1, 3] != 0.0f || matrix[3, 3] != 0.0f) { return(false); } if (matrix[2, 3] != -1.0f) { return(false); } return(true); }
void IMVP.SetShaderProgram(mat4 mvp) { IMVPHelper.SetMVP(this, mvp); }
/// <summary> /// Builds a perspective projection matrix based on a field of view. /// </summary> /// <param name="fov">The fov (in radians).</param> /// <param name="width">The width.</param> /// <param name="height">The height.</param> /// <param name="zNear">The z near.</param> /// <param name="zFar">The z far.</param> /// <returns></returns> /// <exception cref="System.ArgumentOutOfRangeException"></exception> public static mat4 perspectiveFov(float fov, float width, float height, float zNear, float zFar) { if (width <= 0 || height <= 0 || fov <= 0) throw new ArgumentOutOfRangeException(); var rad = fov; var h = glm.cos((0.5f) * rad) / glm.sin((0.5f) * rad); var w = h * height / width; var result = new mat4(0); result[0, 0] = w; result[1, 1] = h; result[2, 2] = -(zFar + zNear) / (zFar - zNear); result[2, 3] = -(1f); result[3, 2] = -((2f) * zFar * zNear) / (zFar - zNear); return result; }