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
        public static bool CalcClippingPlanes(ViewportInfo vp, ClippingInfo m_Clipping)
        {
            // Initialize m_Clipping frustum info.
            // (left,right,top,bottom are not used but should be initialized).
            //const ON::view_projection projection = vp.Projection();

            vp.GetFrustum(out m_Clipping.left,
                          out m_Clipping.right,
                          out m_Clipping.bottom,
                          out m_Clipping.top,
                          out m_Clipping.bbox_near,
                          out m_Clipping.bbox_far);

            m_Clipping.min_near_dist     = 0.000100;
            m_Clipping.min_near_over_far = 0.000100;
            m_Clipping.target_dist = (vp.CameraLocation - vp.TargetPoint)*vp.CameraZ;

            // Call virtual function that looks at m_Clipping.bbox and sets
            // m_Clipping.bbox_near and m_Clipping.bbox_far
            if ( !CalcClippingPlanesInternal( vp, m_Clipping ) )
                return false;

            if ( double.IsNaN(m_Clipping.bbox_far)
                || double.IsNaN(m_Clipping.bbox_near)
                || m_Clipping.bbox_far <= m_Clipping.bbox_near
                || (vp.IsPerspectiveProjection && m_Clipping.bbox_near <= 1.0e-12)
                || (vp.IsPerspectiveProjection  && m_Clipping.bbox_far > 1.0e16*m_Clipping.bbox_near)
                || m_Clipping.bbox_near > 1.0e30
                || m_Clipping.bbox_far  > 1.0e30
                )
            {

                // Restore settings to something more sane
                vp.GetFrustum(out m_Clipping.left,
                              out m_Clipping.right,
                              out m_Clipping.bottom,
                              out m_Clipping.top,
                              out m_Clipping.bbox_near,
                              out m_Clipping.bbox_far);

                m_Clipping.min_near_dist     =  0.000100;
                m_Clipping.min_near_over_far =  0.000100;
                m_Clipping.target_dist = (vp.CameraLocation - vp.TargetPoint)*vp.CameraZ;
            }

            return true;
        }
Esempio n. 3
0
        /// <summary>
        /// StartRestoreViewTo is a helper method that is called by ZoomExtentsWithGesture to
        /// return the viewport back to it's "home" view.
        /// </summary>
        private void StartRestoreViewTo(Rhino.DocObjects.ViewportInfo targetPosition)
        {
            if (Camera == null)
            {
                return;
            }

            IsInAnimatedRestoreView = true;

            View.UserInteractionEnabled = false;
            RestoreViewStartTime        = DateTime.Now;
            RestoreViewTotalTime        = new TimeSpan(0, 0, 0, 0, 500);

            RestoreViewStartViewport  = new ViewportInfo(Camera);            // start from current position
            RestoreViewFinishViewport = new ViewportInfo(targetPosition);    // end on the target position

            // fix frustum aspect to match current screen aspect
            RestoreViewFinishViewport.FrustumAspect = Camera.FrustumAspect;

            AnimationTimer = NSTimer.CreateScheduledTimer(0.0, this, new Selector("AnimateRestoreView"), null, true);
            AnimationTimer.Fire();
        }
Esempio n. 4
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);
            }
        }
Esempio n. 5
0
        /// <summary>
        /// Creates a default light and enables the active shader
        /// </summary>
        private void SetupShader(RhGLShaderProgram shader, RMModel model, ViewportInfo viewport)
        {
            // Check to make sure we actually have an active shader...
            if (shader != null) {

                // Enable...
                shader.Enable ();

                // Now setup and initialize frustum and lighting...
                int near, far;
                viewport.GetScreenPort (out near, out far);
                viewport.SetScreenPort ((int)Frame.Left, (int)Frame.Right, (int)Frame.Bottom, (int)Frame.Top, near, far);
                shader.SetupViewport (viewport);
                Rhino.Geometry.Light light = CreateDefaultLight ();
                shader.SetupLight (light);
                light.Dispose ();
            }
        }
Esempio n. 6
0
        /// <summary>
        /// Sets up and initializes the viewport by setting the Uniforms
        /// </summary>
        public void SetupViewport(ViewportInfo viewport)
        {
            Transform mv = new Transform();
            bool haveModelView = false;

            if (m_Uniforms.rglModelViewProjectionMatrix >= 0) {
                Transform mvp = viewport.GetXform (CoordinateSystem.World, CoordinateSystem.Clip);

                m_MVPXform = mvp;

                float[] modelViewProjection = mvp.ToFloatArray(false);
                GL.UniformMatrix4 (m_Uniforms.rglModelViewProjectionMatrix, 1, false, modelViewProjection);
            }

            if (m_Uniforms.rglModelViewMatrix >= 0) {
                mv = viewport.GetXform (CoordinateSystem.World, CoordinateSystem.Camera);

                m_MVXform = mv;
                haveModelView = true;

                float[] modelView = mv.ToFloatArray(false);
                GL.UniformMatrix4 (m_Uniforms.rglModelViewMatrix, 1, false, modelView);
            }

            if (m_Uniforms.rglProjectionMatrix >= 0) {
                Transform pr = viewport.GetXform (CoordinateSystem.Camera, CoordinateSystem.Clip);

                float[] projection = pr.ToFloatArray(false);
                GL.UniformMatrix4 (m_Uniforms.rglProjectionMatrix, 1, false, projection);
            }

            if (m_Uniforms.rglNormalMatrix >= 0) {

                float[] normalMatrix = new float[9];

                if (!haveModelView) {
                    mv = viewport.GetXform (CoordinateSystem.World, CoordinateSystem.Camera);
                    m_MVXform = mv;
                }

                Matrix4Dto3F (mv, ref normalMatrix, false);
                GL.UniformMatrix3 (m_Uniforms.rglNormalMatrix, 1, false, normalMatrix);
            }
        }
    /// <summary>
    /// Returns a bounding box for the custom render meshes for the given object.
    /// </summary>
    /// <param name="vp">The viewport being rendered.</param>
    /// <param name="obj">The Rhino object of interest.</param>
    /// <param name="requestingPlugIn">UUID of the RDK plug-in requesting the meshes.</param>
    /// <param name="preview">Type of mesh to build.</param>
    /// <returns>A bounding box value.</returns>
    public virtual BoundingBox BoundingBox(ViewportInfo vp, RhinoObject obj, Guid requestingPlugIn, bool preview)
    {
      var min = new Point3d();
      var max = new Point3d();

      if (UnsafeNativeMethods.Rdk_RMPBoundingBoxImpl(m_runtime_serial_number, vp.ConstPointer(), obj.ConstPointer(), requestingPlugIn, preview ? 1 : 0, ref min, ref max))
        return new BoundingBox(min, max);

      return new BoundingBox();
    }
Esempio n. 8
0
 private static bool AdjustFrustum(ViewportInfo vp, ClippingInfo clipping)
 {
     vp.SetFrustumNearFar (vp.FrustumNear * 0.1, vp.FrustumFar * 10);
     return true;
 }
 /// <summary>
 /// Determines if custom render meshes will be built for a particular object.
 /// </summary>
 /// <param name="vp">The viewport being rendered.</param>
 /// <param name="obj">The Rhino object of interest.</param>
 /// <param name="requestingPlugIn">UUID of the RDK plug-in requesting the meshes.</param>
 /// <param name="preview">Type of mesh to build.</param>
 /// <returns>true if custom meshes will be built.</returns>
 public abstract bool WillBuildCustomMeshes(ViewportInfo vp, RhinoObject obj, Guid requestingPlugIn, bool preview);
Esempio n. 10
0
        public override bool StartRenderer(int w, int h, RhinoDoc doc, ViewInfo rhinoView, ViewportInfo viewportInfo, bool forCapture, RenderWindow renderWindow)
        {
            _started = true;
            if (forCapture)
            {
                ModalRenderEngine mre = new ModalRenderEngine(doc, PlugIn.IdFromName("RhinoCycles"), rhinoView, viewportInfo);
                _cycles = null;
                _modal = mre;

                mre.Settings = RcCore.It.EngineSettings;
                mre.Settings.UseInteractiveRenderer = false;
                mre.Settings.SetQuality(doc.RenderSettings.AntialiasLevel);

                var rs = new Size(w, h);

                mre.RenderWindow = renderWindow;

                mre.RenderDimension = rs;
                mre.Database.RenderDimension = rs;

                mre.Settings.Verbose = true;

                mre.StatusTextUpdated += Mre_StatusTextUpdated;

                mre.Database.LinearWorkflowChanged += DatabaseLinearWorkflowChanged;

                mre.SetFloatTextureAsByteTexture(false); // mre.Settings.RenderDeviceIsOpenCl);

                mre.CreateWorld(); // has to be done on main thread, so lets do this just before starting render session

                _modalThread = new Thread(RenderOffscreen)
                {
                    Name = $"Cycles offscreen viewport rendering with ModalRenderEngine {_serial}"
                };
                _modalThread.Start(mre);

                return true;
            }

            _available = false; // the renderer hasn't started yet. It'll tell us when it has.
            _frameAvailable = false;

            _cycles = new ViewportRenderEngine(doc.RuntimeSerialNumber, PlugIn.IdFromName("RhinoCycles"), rhinoView);

            _cycles.StatusTextUpdated += CyclesStatusTextUpdated; // render engine tells us status texts for the hud
            _cycles.RenderStarted += CyclesRenderStarted; // render engine tells us when it actually is rendering
            _cycles.StartSynchronizing += CyclesStartSynchronizing;
            _cycles.Synchronized += CyclesSynchronized;
            _cycles.PassRendered += CyclesPassRendered;
            _cycles.Database.LinearWorkflowChanged += DatabaseLinearWorkflowChanged;
            _cycles.SamplesChanged += CyclesSamplesChanged;

            _cycles.Settings = RcCore.It.EngineSettings;
            _cycles.Settings.SetQuality(doc.RenderSettings.AntialiasLevel);

            var renderSize = Rhino.Render.RenderPipeline.RenderSize(doc);

            _cycles.RenderWindow = renderWindow;
            _cycles.RenderDimension = renderSize;

            _cycles.Settings.Verbose = true;

            _maxSamples = _cycles.Settings.Samples;

            _cycles.SetFloatTextureAsByteTexture(false); // m_cycles.Settings.RenderDeviceIsOpenCl);

            _cycles.CreateWorld(); // has to be done on main thread, so lets do this just before starting render session

            _startTime = DateTime.UtcNow;

            _cycles.StartRenderThread(_cycles.Renderer, $"A cool Cycles viewport rendering thread {_serial}");

            return true;
        }
Esempio n. 11
0
        public RenderEngine(Guid pluginId, uint docRuntimeSerialnumber, ViewInfo view, ViewportInfo vp, bool interactive)
        {
            PluginId = pluginId;
            m_doc_serialnumber = docRuntimeSerialnumber;
            m_view = view;
            m_vp = vp;
            m_interactive = interactive;
            Database = new ChangeDatabase(PluginId, this, m_doc_serialnumber, m_view, !m_interactive);

            RegisterEventHandler();
        }
Esempio n. 12
0
        private static void NegativeNearClippingHelper(double near_dist, double far_dist, ViewportInfo vp)
        {
            double n = near_dist;
            double f = far_dist;

            double min_near_dist = 0.000100;
            if ( double.IsNaN(min_near_dist) || min_near_dist < 1.0e-6 )
                min_near_dist = 1.0e-6;
            if ( vp.IsParallelProjection && n < min_near_dist )
            {
                // move camera back in ortho projection so everything shows
                double d = 1.00001*min_near_dist - n;
                if ( d < 0.005 )
                    d = 0.005;
                n += d;
                f  += d;
                if (   double.IsNaN(d)
                    || d <= 0.0
                    || double.IsNaN(n)
                    || double.IsNaN(f)
                    || n < min_near_dist
                    || f <= n
                    )
                {
                    // Just give up but ... refuse to accept garbage
                    n = 0.005;
                    f = 1000.0;
                }
                else
                {
                    Rhino.Geometry.Point3d new_loc = vp.CameraLocation + d*vp.CameraZ;
                    vp.SetCameraLocation( new_loc );
                }
                near_dist = n;
                far_dist = f;
            }
        }
Esempio n. 13
0
        private static bool CalcClippingPlanesInternal(ViewportInfo vp, ClippingInfo clipping)
        {
            bool isPerspective = vp.IsPerspectiveProjection;

            // iCalcBoundingBox() has set clipping.bbox and it cannot
            // be changed or ignored.
            GetBoundingBoxNearFarHelper (
                clipping.bbox,
                isPerspective,
                vp.CameraLocation,
                vp.CameraZ,
                clipping.bbox_near,
                clipping.bbox_far
            );

            // Do sanity checks and update ON_Viewport frustum if it uses
            // parallel projection and near <= 0.0
            CalcClippingPlanesHelper(clipping.bbox_near, clipping.bbox_far, vp);

            // Set target_dist
            clipping.target_dist = (vp.CameraLocation - vp.TargetPoint)* vp.CameraZ;
            if ( double.IsNaN(clipping.target_dist) )
                clipping.target_dist = 0.5*(clipping.bbox_near + clipping.bbox_far);

            return true;
        }
Esempio n. 14
0
        static void CalcClippingPlanesHelper(double near_dist, double far_dist, ViewportInfo vp)
        {
            // The only thing this function should do is make sure ortho cameras are
            // moved so near is > 0.  Everything else should be considered and emergency
            // fix for garbage input.
            double n = near_dist;
            double f = far_dist;
            double min_near_dist = 0.000100;
            if ( double.IsNaN(min_near_dist) || min_near_dist < 1.0e-6 )
                min_near_dist = 1.0e-6;

            if (!double.IsNaN(n) && !double.IsNaN(f) )
            {
                NegativeNearClippingHelper(n,f,vp);
                if ( n < min_near_dist )
                    n = min_near_dist;
                if ( f <= 1.00001*n )
                    f = 10.0 + 100.0*n;
            }
            else
            {
                // If being nice didn't work - refuse to accept garbage
                n = 0.005;
                f = 1000.0;
            }

            near_dist = n;
            far_dist = f;
        }
Esempio n. 15
0
 public ModalRenderEngine(RhinoDoc doc, Guid pluginId, ViewInfo view, ViewportInfo viewport)
     : base(pluginId, doc.RuntimeSerialNumber, view, viewport, false)
 {
     ModalRenderEngineCommonConstruct();
 }
 /// <summary>
 /// Build custom render mesh(es).
 /// </summary>
 /// <param name="vp">The viewport being rendered.</param>
 /// <param name="objMeshes">The meshes class to populate with custom meshes.</param>
 /// <param name="requestingPlugIn">UUID of the RDK plug-in requesting the meshes.</param>
 /// <param name="meshType">Type of mesh to build.</param>
 /// <returns>true if operation was successful.</returns>
 public abstract bool BuildCustomMeshes(ViewportInfo vp, RenderPrimitiveList objMeshes, Guid requestingPlugIn, bool meshType);
Esempio n. 17
0
 /// <summary>
 ///  Initializes a new instance by copying values from another instance.
 /// </summary>
 /// <param name="other">The other viewport info.</param>
 public ViewportInfo(ViewportInfo other)
 {
   IntPtr pOther = other.ConstPointer();
   m_pViewportPointer = UnsafeNativeMethods.ON_Viewport_New(pOther);
 }
Esempio n. 18
0
        public static bool SetupFrustum(ViewportInfo vp, ClippingInfo clipping)
        {
            double    n0 = vp.FrustumNear;
            double    f0 = vp.FrustumFar;

            // Because picking relies heavily on the projection, we first set the
            // viewport frustum here, capture and save it, then let the conduits
            // do what ever they want with it...eventually the viewport will be put
            // back to the captured state before leaving the pipeline...
            ClippingInfo m_SavedClipping = clipping;
            vp.SetFrustumNearFar(clipping.bbox_near, clipping.bbox_far,
                                 clipping.min_near_dist, clipping.min_near_over_far,
                                 clipping.target_dist
                                 );

            vp.GetFrustum(out m_SavedClipping.left,
                          out m_SavedClipping.right,
                          out m_SavedClipping.bottom,
                          out m_SavedClipping.top,
                          out m_SavedClipping.bbox_near,
                          out m_SavedClipping.bbox_far);

            // Next, set the values that the pipeline will actually use...
            if (!(AdjustFrustum(vp, clipping)))
                return false;

            return true;
        }