/// <summary> /// Renders the simulated data from the special object. /// </summary> /// <param name="OGL">Current OpenGL state object.</param> /// <param name="data">Data to render.</param> /// <returns>Number of actually drawn primitives.</returns> public long Render(OpenglState OGL, MarblesRenderData data) { RenderInit(OGL); int marbles = data.Spheres.Count; int stride = sizeof(float) * 11; // float[2] txt, float[3] color, float[3] normal, float[3] position int triangles = SphereObject.TriangleCount * marbles; int vertexCount = triangles * 3; if (marbles != lastMarbles) { RenderInitializeBuffer(OGL, vertexCount, stride, triangles); lastMarbles = marbles; } // Refill vertex buffer. GL.BindBuffer(BufferTarget.ArrayBuffer, OGL.VBOid[0]); IntPtr videoMemoryPtr = GL.MapBuffer(BufferTarget.ArrayBuffer, BufferAccess.WriteOnly); unsafe { float *ptr = (float *)videoMemoryPtr.ToPointer(); for (int i = 0; i < marbles; i++) { data.Spheres[i].Render(ref ptr); } } RenderFinish(OGL, vertexCount, stride); return(triangles); }
/// <summary> /// Prime simulation init. /// </summary> private void InitSimulation(string param) { world = new MarblesWorld(param); renderer = new MarblesRenderer(param); data = null; ResetSimulation(param); }
/// <summary> /// Simulate one frame. /// </summary> private void Simulate() { /// <summary>New data to draw (or <code>null</code> if there is nothing to update).</summary> MarblesRenderData newData = null; if (world != null) { lock ( world ) { long nowTicks = DateTime.Now.Ticks; if (nowTicks > ticksLast) { if (world.Running) { // 1000Hz .. 1ms .. 10000 ticks long minTicks = 10000000L / world.maxSpeed; // min ticks between simulation steps if (nowTicks - ticksLast < (3 * minTicks) / 4) { // we are going too fast.. int sleepMs = (int)(((5 * minTicks) / 4 - nowTicks + ticksLast) / 10000L); Thread.Sleep(sleepMs); nowTicks = DateTime.Now.Ticks; } double timeScale = checkSlow.Checked ? MarblesWorld.slow : 1.0; timeLast += (nowTicks - ticksLast) * timeScale * 1.0e-7; newData = world.Simulate(timeLast); simCounter++; } ticksLast = nowTicks; } } } if (newData != null && renderer != null) { lock (renderer) data = newData; } }
/// <summary> /// OpenGL rendering code itself (separated for clarity). /// </summary> private void RenderScene() { // Simulation scene rendering. MarblesRenderData rdata = null; if (renderer != null && OGL.useShaders) { lock (renderer) rdata = data; } if (rdata != null) { OGL.FormData(); // Simulated scene. primitiveCounter += renderer.Render(OGL, rdata); // Light source. GL.PointSize(5.0f); GL.Begin(PrimitiveType.Points); GL.Color3(1.0f, 1.0f, 1.0f); GL.Vertex3(OGL.lightPosition); GL.End(); primitiveCounter++; primitiveCounter += rdata.Cube.Draw(); } else { CubeObject cube = new CubeObject(10); primitiveCounter += cube.Draw(); } }
/// <summary> /// Renders the simulated data from the special object. /// </summary> /// <param name="OGL">Current OpenGL state object.</param> /// <param name="data">Data to render.</param> /// <returns>Number of actually drawn primitives.</returns> public long Render(OpenglState OGL, MarblesRenderData data) { // {{ TODO: modify the rendering code! // Scene rendering from VBOs. OGL.SetVertexAttrib(true); // Using GLSL shaders. GL.UseProgram(OGL.activeProgram.Id); // Uniforms. // Camera, projection, .. Matrix4 modelView = OGL.GetModelView(); Matrix4 modelViewInv = OGL.GetModelViewInv(); Matrix4 projection = OGL.GetProjection(); Vector3 eye = OGL.GetEyePosition(); // Give matrices to shaders. GL.UniformMatrix4(OGL.activeProgram.GetUniform("matrixModelView"), false, ref modelView); GL.UniformMatrix4(OGL.activeProgram.GetUniform("matrixProjection"), false, ref projection); // Lighting constants. GL.Uniform3(OGL.activeProgram.GetUniform("globalAmbient"), ref OGL.globalAmbient); GL.Uniform3(OGL.activeProgram.GetUniform("lightColor"), ref OGL.whiteLight); GL.Uniform3(OGL.activeProgram.GetUniform("lightPosition"), ref OGL.lightPosition); GL.Uniform3(OGL.activeProgram.GetUniform("eyePosition"), ref eye); GL.Uniform3(OGL.activeProgram.GetUniform("Ka"), ref OGL.matAmbient); GL.Uniform3(OGL.activeProgram.GetUniform("Kd"), ref OGL.matDiffuse); GL.Uniform3(OGL.activeProgram.GetUniform("Ks"), ref OGL.matSpecular); GL.Uniform1(OGL.activeProgram.GetUniform("shininess"), OGL.matShininess); // Global color handling. bool useColors = !OGL.useGlobalColor; GL.Uniform1(OGL.activeProgram.GetUniform("globalColor"), useColors ? 0 : 1); // Use varying normals? bool useNormals = OGL.useNormals; GL.Uniform1(OGL.activeProgram.GetUniform("useNormal"), useNormals ? 1 : 0); GlInfo.LogError("set-uniforms"); // Texture handling. bool useTexture = OGL.useTexture; GL.Uniform1(OGL.activeProgram.GetUniform("useTexture"), useTexture ? 1 : 0); GL.Uniform1(OGL.activeProgram.GetUniform("texSurface"), 0); if (useTexture) { GL.ActiveTexture(TextureUnit.Texture0); GL.BindTexture(TextureTarget.Texture2D, OGL.texName); } GlInfo.LogError("set-texture"); // [txt] [colors] [normals] vertices GL.BindBuffer(BufferTarget.ArrayBuffer, OGL.VBOid[0]); GL.BindBuffer(BufferTarget.ElementArrayBuffer, OGL.VBOid[1]); int marbles = data.radii.Count; int stride = sizeof(float) * 11; // float[2] txt, float[3] color, float[3] normal, float[3] position int triangles = marbles; IntPtr videoMemoryPtr; if (marbles != lastMarbles) { // Relocate the buffers. // Vertex array: [ txt color coord ] GL.BindBuffer(BufferTarget.ArrayBuffer, OGL.VBOid[0]); int vertexBufferSize = (marbles * 3) * stride; // TODO: marble should be drawn as a SPHERE, not a triangle.. GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)vertexBufferSize, IntPtr.Zero, BufferUsageHint.DynamicDraw); GL.BindBuffer(BufferTarget.ArrayBuffer, 0); // Fill index array. GL.BindBuffer(BufferTarget.ElementArrayBuffer, OGL.VBOid[1]); GL.BufferData(BufferTarget.ElementArrayBuffer, (IntPtr)((triangles * 3) * sizeof(uint)), IntPtr.Zero, BufferUsageHint.StaticDraw); videoMemoryPtr = GL.MapBuffer(BufferTarget.ElementArrayBuffer, BufferAccess.WriteOnly); unsafe { uint *ptr = (uint *)videoMemoryPtr.ToPointer(); for (uint i = 0; i < triangles * 3; i++) { *ptr++ = i; } } GL.UnmapBuffer(BufferTarget.ElementArrayBuffer); GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0); lastMarbles = marbles; } // Refill vertex buffer. GL.BindBuffer(BufferTarget.ArrayBuffer, OGL.VBOid[0]); videoMemoryPtr = GL.MapBuffer(BufferTarget.ArrayBuffer, BufferAccess.WriteOnly); unsafe { float *ptr = (float *)videoMemoryPtr.ToPointer(); for (int i = 0; i < marbles; i++) { float rad = data.radii[i]; float r = data.colors[i].R / 255.0f; float g = data.colors[i].G / 255.0f; float b = data.colors[i].B / 255.0f; // txt[2], color[3], normal[3], position[3] *ptr++ = 0.3f; *ptr++ = 0.3f; *ptr++ = r; *ptr++ = g; *ptr++ = b; *ptr++ = 0.0f; *ptr++ = 0.0f; *ptr++ = 1.0f; *ptr++ = data.centers[i].X; *ptr++ = data.centers[i].Y; *ptr++ = data.centers[i].Z; // txt[2], color[3], normal[3], position[3] *ptr++ = 0.7f; *ptr++ = 0.3f; *ptr++ = r; *ptr++ = g; *ptr++ = b; *ptr++ = 0.0f; *ptr++ = 0.0f; *ptr++ = 1.0f; *ptr++ = data.centers[i].X + rad; *ptr++ = data.centers[i].Y; *ptr++ = data.centers[i].Z; // txt[2], color[3], normal[3], position[3] *ptr++ = 0.3f; *ptr++ = 0.7f; *ptr++ = r; *ptr++ = g; *ptr++ = b; *ptr++ = 0.0f; *ptr++ = 0.0f; *ptr++ = 1.0f; *ptr++ = data.centers[i].X; *ptr++ = data.centers[i].Y + rad; *ptr++ = data.centers[i].Z; } } GL.UnmapBuffer(BufferTarget.ArrayBuffer); // Index buffer. GL.BindBuffer(BufferTarget.ElementArrayBuffer, OGL.VBOid[1]); // Set attribute pointers. IntPtr p = IntPtr.Zero; if (OGL.activeProgram.HasAttribute("texCoords")) { GL.VertexAttribPointer(OGL.activeProgram.GetAttribute("texCoords"), 2, VertexAttribPointerType.Float, false, stride, p); } p += Vector2.SizeInBytes; if (OGL.activeProgram.HasAttribute("color")) { GL.VertexAttribPointer(OGL.activeProgram.GetAttribute("color"), 3, VertexAttribPointerType.Float, false, stride, p); } p += Vector3.SizeInBytes; if (OGL.activeProgram.HasAttribute("normal")) { GL.VertexAttribPointer(OGL.activeProgram.GetAttribute("normal"), 3, VertexAttribPointerType.Float, false, stride, p); } p += Vector3.SizeInBytes; GL.VertexAttribPointer(OGL.activeProgram.GetAttribute("position"), 3, VertexAttribPointerType.Float, false, stride, p); GlInfo.LogError("triangles-set-attrib-pointers"); // The drawing command itself. GL.DrawElements(PrimitiveType.Triangles, triangles * 3, DrawElementsType.UnsignedInt, IntPtr.Zero); GlInfo.LogError("triangles-draw-elements"); GL.BindBuffer(BufferTarget.ArrayBuffer, 0); GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0); GL.UseProgram(0); OGL.SetVertexAttrib(false); return(triangles); // }} }
/// <summary> /// OpenGL rendering code itself (separated for clarity). /// </summary> private void RenderScene() { // Simulation scene rendering. MarblesRenderData rdata = null; if (renderer != null && OGL.useShaders) { lock (renderer) rdata = data; } if (rdata != null) { OGL.FormData(); // Simulated scene. primitiveCounter += renderer.Render(OGL, rdata); // Light source. GL.PointSize(5.0f); GL.Begin(PrimitiveType.Points); GL.Color3(1.0f, 1.0f, 1.0f); GL.Vertex3(OGL.lightPosition); GL.End(); primitiveCounter++; } else { // color cube: GL.Begin(PrimitiveType.Quads); GL.Color3(0.0f, 1.0f, 0.0f); // Set The Color To Green GL.Vertex3(1.0f, 1.0f, -1.0f); // Top Right Of The Quad (Top) GL.Vertex3(-1.0f, 1.0f, -1.0f); // Top Left Of The Quad (Top) GL.Vertex3(-1.0f, 1.0f, 1.0f); // Bottom Left Of The Quad (Top) GL.Vertex3(1.0f, 1.0f, 1.0f); // Bottom Right Of The Quad (Top) GL.Color3(1.0f, 0.5f, 0.0f); // Set The Color To Orange GL.Vertex3(1.0f, -1.0f, 1.0f); // Top Right Of The Quad (Bottom) GL.Vertex3(-1.0f, -1.0f, 1.0f); // Top Left Of The Quad (Bottom) GL.Vertex3(-1.0f, -1.0f, -1.0f); // Bottom Left Of The Quad (Bottom) GL.Vertex3(1.0f, -1.0f, -1.0f); // Bottom Right Of The Quad (Bottom) GL.Color3(1.0f, 0.0f, 0.0f); // Set The Color To Red GL.Vertex3(1.0f, 1.0f, 1.0f); // Top Right Of The Quad (Front) GL.Vertex3(-1.0f, 1.0f, 1.0f); // Top Left Of The Quad (Front) GL.Vertex3(-1.0f, -1.0f, 1.0f); // Bottom Left Of The Quad (Front) GL.Vertex3(1.0f, -1.0f, 1.0f); // Bottom Right Of The Quad (Front) GL.Color3(1.0f, 1.0f, 0.0f); // Set The Color To Yellow GL.Vertex3(1.0f, -1.0f, -1.0f); // Bottom Left Of The Quad (Back) GL.Vertex3(-1.0f, -1.0f, -1.0f); // Bottom Right Of The Quad (Back) GL.Vertex3(-1.0f, 1.0f, -1.0f); // Top Right Of The Quad (Back) GL.Vertex3(1.0f, 1.0f, -1.0f); // Top Left Of The Quad (Back) GL.Color3(0.0f, 0.0f, 1.0f); // Set The Color To Blue GL.Vertex3(-1.0f, 1.0f, 1.0f); // Top Right Of The Quad (Left) GL.Vertex3(-1.0f, 1.0f, -1.0f); // Top Left Of The Quad (Left) GL.Vertex3(-1.0f, -1.0f, -1.0f); // Bottom Left Of The Quad (Left) GL.Vertex3(-1.0f, -1.0f, 1.0f); // Bottom Right Of The Quad (Left) GL.Color3(1.0f, 0.0f, 1.0f); // Set The Color To Violet GL.Vertex3(1.0f, 1.0f, -1.0f); // Top Right Of The Quad (Right) GL.Vertex3(1.0f, 1.0f, 1.0f); // Top Left Of The Quad (Right) GL.Vertex3(1.0f, -1.0f, 1.0f); // Bottom Left Of The Quad (Right) GL.Vertex3(1.0f, -1.0f, -1.0f); // Bottom Right Of The Quad (Right) GL.End(); primitiveCounter += 12; } }