Esempio n. 1
0
        /// <summary>
        /// IRenderer interface method
        /// Renders a model in a viewport
        /// </summary>
        public bool RenderModel(RMModel model, Rhino.DocObjects.ViewportInfo viewport)
        {
            if (null == model || null == viewport || !model.IsReadyForRendering)
            {
                return(false);
            }

            Model = model;

            CheckGLError("intro call"); //HACK: necessary on some Android GPUs (don't delete this check)

            viewport.SetFrustumNearFar(model.BBox);

            // Disable Blending and set the depth function
            GL.DepthFunc(DepthFunction.Gequal);
            GL.Disable(EnableCap.Blend);

            // Get the shader...
            ActiveShader = FastDrawing ? GetShader("PerVertexLighting") : GetShader("PerPixelLighting");

            // Render calls...
            if (model != null)
            {
                // First, render all opaque objects that are not instances
                foreach (var obj in model.DisplayMeshes)
                {
                    if (obj != null)
                    {
                        RenderObject(obj, viewport, false);
                    }
                }

                // Second, render all opaque objects that are instances
                foreach (var obj in model.DisplayInstanceMeshes)
                {
                    if (obj != null)
                    {
                        RenderObject(obj, viewport, true);
                    }
                }

                // Third, we're done drawing our instances, so set the ModelViewMatrix's XForm back to the identity matrix.
                ActiveShader.SetModelViewMatrix(Rhino.Geometry.Transform.Identity);

                // Fourth, render all transparent meshes...
                RenderTransparentObjects(model);
            }

            // Disable the shader
            ActiveShader.Disable();

            return(true);
        }
Esempio n. 2
0
        /// <summary>
        /// For derived class implementers.
        /// <para>This method is called with argument true when class user calls Dispose(), while with argument false when
        /// the Garbage Collector invokes the finalizer, or Finalize() method.</para>
        /// <para>You must reclaim all used unmanaged resources in both cases, and can use this chance to call Dispose on disposable fields if the argument is true.</para>
        /// <para>Also, you must call the base virtual method within your overriding method.</para>
        /// </summary>
        /// <param name="disposing">true if the call comes from the Dispose() method; false if it comes from the Garbage Collector finalizer.</param>
        protected virtual void Dispose(bool disposing)
        {
            // Free unmanaged resources...

            // Free managed resources...but only if called from Dispose
            // (If called from Finalize then the objects might not exist anymore)
            if (disposing)
            {
                if (Model != null)
                {
                    Model.Dispose();
                    Model = null;
                }

                Frame = System.Drawing.RectangleF.Empty;

                if (Viewport != null)
                {
                    Viewport.Dispose();
                    Viewport = null;
                }

                CurrentMaterial = null;

                if (ActiveShader != null)
                {
                    GL.DeleteProgram(ActiveShader.Handle);
                    ActiveShader.Disable();
                    m_activeShader = null;
                }

                if (Shaders != null)
                {
                    Shaders.Clear();
                    Shaders = null;
                }
            }
        }
Esempio n. 3
0
        /// <summary>
        /// Renders the object in a viewport
        /// </summary>
        private void RenderObject(DisplayObject obj, Rhino.DocObjects.ViewportInfo viewport, bool isInstance)
        {
            // If the object is invisible, return.
            if (!obj.IsVisible)
            {
                return;
            }

            // If the layer that the object is on is turned off, return.
            if (!Model.LayerIsVisibleAtIndex(obj.LayerIndex))
            {
                return;
            }

            DisplayMesh displayMesh = isInstance ? ((DisplayInstanceMesh)obj).Mesh : (DisplayMesh)obj;

            if (displayMesh.WillFitOnGPU == false)
            {
                return;
            }

            uint vertex_buffer = 0;
            uint index_buffer  = 0;

            if (displayMesh != null)
            {
                // Material setup, if necessary...
                displayMesh.Material.AmbientColor = new [] { 0.0f, 0.0f, 0.0f, 1.0f };                 //We want to ignore the ambient color
                if (CurrentMaterial.RuntimeId != displayMesh.Material.RuntimeId)
                {
                    ActiveShader.SetupMaterial(displayMesh.Material);
                }
                CurrentMaterial = displayMesh.Material;

                if (displayMesh.IndexBufferHandle == Globals.UNSET_HANDLE)
                {
                    // Generate the Index VBO
                    GL.GenBuffers(1, out index_buffer);
                    GL.BindBuffer(BufferTarget.ElementArrayBuffer, index_buffer);
                    displayMesh.IndexBufferHandle = index_buffer;
                }

                if (displayMesh.VertexBufferHandle == Globals.UNSET_HANDLE)
                {
                    // Generate the VertexBuffer
                    GL.GenBuffers(1, out vertex_buffer);
                    GL.BindBuffer(BufferTarget.ArrayBuffer, vertex_buffer);
                    displayMesh.VertexBufferHandle = vertex_buffer;

                    displayMesh.LoadDataForVBOs(displayMesh.Mesh);

                    // If CheckGLError turns up an error (likely an OutOfMemory warning because the mesh won't fit on the GPU)
                    // we need to delete the buffers associated with that displayMesh and mark it as too big.
                    bool causesGLError = CheckGLError("GL.BufferData");
                    if (causesGLError)
                    {
                        GL.DeleteBuffers(1, ref vertex_buffer);
                        GL.DeleteBuffers(1, ref index_buffer);
                        displayMesh.WillFitOnGPU = false;
                        GC.Collect();
                    }
                    else
                    {
                        displayMesh.WillFitOnGPU = true;
                    }

                    // If we have drawn all the partitions associated with the underlying openNURBS mesh in the ModelFile, we can delete it...
                    if (displayMesh.Mesh.PartitionCount == displayMesh.PartitionIndex + 1)
                    {
                        Model.ModelFile.Objects.Delete(displayMesh.FileObjectId);
                    }

                    displayMesh.Mesh = null;
                }

                if (displayMesh.WillFitOnGPU == false)
                {
                    return;
                }

                // Vertices
                // ORDER MATTERS...if you don't do things in this order, you will get very frusterated.
                // First, enable the VertexAttribArray for positions
                int rglVertex = ActiveShader.RglVertexIndex;
                GL.EnableVertexAttribArray(rglVertex);
                // Second, Bind the ArrayBuffer
                GL.BindBuffer(BufferTarget.ArrayBuffer, displayMesh.VertexBufferHandle);
                // Third, tell GL where to look for the data...
                GL.VertexAttribPointer(rglVertex, 3, VertexAttribPointerType.Float, false, displayMesh.Stride, IntPtr.Zero);

                CheckGLError("GL.VertexAttribPointer");

                // Normals
                if (displayMesh.HasVertexNormals)
                {
                    int rglNormal = ActiveShader.RglNormalIndex;
                    GL.EnableVertexAttribArray(rglNormal);
                    GL.VertexAttribPointer(rglNormal, 3, VertexAttribPointerType.Float, false, displayMesh.Stride, (IntPtr)(Marshal.SizeOf(typeof(Rhino.Geometry.Point3f))));

                    CheckGLError("GL.VertexAttribPointer");
                }

                // Colors
                if (displayMesh.HasVertexColors)
                {
                    int rglColor = ActiveShader.RglColorIndex;
                    GL.EnableVertexAttribArray(rglColor);
                    GL.VertexAttribPointer(rglColor, 4, VertexAttribPointerType.Float, false, displayMesh.Stride, (IntPtr)(Marshal.SizeOf(typeof(Rhino.Display.Color4f))));

                    CheckGLError("GL.VertexAttribPointer");
                }

                if (isInstance)
                {
                    if (!FastDrawing)
                    {
                        // Check for inversions on transforms, but only if we are drawing the final "high-quality" frame
                        // (because our PerPixel shader does not flip normals based on modelView matrices).
                        if ((obj as DisplayInstanceMesh).XForm.Determinant < -Globals.ON_ZERO_TOLERANCE)
                        {
                            // an inversion (happens in mirrored instances, etc.)
                            // this means the transformation will turn the mesh
                            // inside out, so we have to reverse our front face
                            // convention.
                            GL.FrontFace(FrontFaceDirection.Cw);
                        }
                        else
                        {
                            GL.FrontFace(FrontFaceDirection.Ccw);
                        }
                    }

                    ActiveShader.SetModelViewMatrix((obj as DisplayInstanceMesh).XForm);
                }

                // Bind Indices
                GL.BindBuffer(BufferTarget.ElementArrayBuffer, displayMesh.IndexBufferHandle);

                CheckGLError("GL.BindBuffer");

                // Draw...
                                #if __ANDROID__
                GL.DrawElements(All.Triangles, displayMesh.IndexBufferLength, All.UnsignedShort, IntPtr.Zero);
                                #endif

                                #if __IOS__
                GL.DrawElements(BeginMode.Triangles, displayMesh.IndexBufferLength, DrawElementsType.UnsignedShort, IntPtr.Zero);
                                #endif

                // Disable any and all arrays and buffers we might have used...
                GL.BindBuffer(BufferTarget.ArrayBuffer, displayMesh.VertexBufferHandle);
                GL.DisableVertexAttribArray(ActiveShader.RglColorIndex);
                GL.DisableVertexAttribArray(ActiveShader.RglNormalIndex);
                GL.DisableVertexAttribArray(ActiveShader.RglVertexIndex);

                GL.BindBuffer(BufferTarget.ElementArrayBuffer, displayMesh.IndexBufferHandle);
                GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
                GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0);
            }
        }