render-primitive (macro)
Package: CURL.GRAPHICS.RENDERER3D

Performs a specified sequence of rendering operations.

Description

render-primitive renders the type of primitive you specify, using a given Renderer3d and a sequence of method calls on the implicitly created Primitive object. Note that you do not supply the Primitive object; instead, you supply a name, and it is bound to a Primitive whose scope is limited to this code block.

Initially, it may seem awkward that you must wrap render-primitive around your rendering calls to Primitive. However, this eliminates a major source of bugs. The alternative would be the standard OpenGL/DirectX model, in which you must explicitly begin a primitive and end it. In that model, to avoid corrupting the graphics system, you must always catch any exceptions that may occur and ensure that you explicitly end the primitive even when exceptions do occur. Programmers seldom do this. However, in Curl, it is done for you through render-primitive, and you may be certain that no other application can corrupt your graphics environment. This is the reason that the Primitive calls must occur within render-primitive.

Syntax

{render-primitive
        p[:Primitive],
        type=type
        on renderer do
        primitive methods list
    }


or

{render-primitive
        type=type,
        p[:Primitive]
        on renderer do
        primitive methods list
    }


where:

Notes

You must not change any of the Renderer3d's state (such as texture or lighting parameters) inside the render-primitive code block!

Example

There are several ways to set up a low-level rendering system in which you can use render-primitive. You might use a Renderer3dGraphic, you might call Drawable.create-offscreen, or you might even simply create your own Window though Window.create-window#factory. See also the chapter on 3D rendering in the Developer's Guide.

For this example, Renderer3dGraphic is used, as it is relatively easy to use.


Example: Using render-primitive
{import * from CURL.GRAPHICS.RENDERER3D}

{Renderer3dGraphic
    width = 3in, 
    height = 2.6in,
    repaint-handler = 
        {proc {graphic:Renderer3dGraphic,
               renderer:Renderer3d, area:#RectangleSet}:void 
            let drawable:Drawable = {non-null
                                        graphic.drawable} 
            
            let vertices:{Array-of Distance2d} = 
                {{Array-of Distance2d}
                    {Distance2d 0.0in, 0.1in},
                    {Distance2d 0.1in, 2.2in},
                    {Distance2d 1.5in, 0.7in},
                    {Distance2d 1.3in, 2.5in},
                    {Distance2d 3.0in, 0.1in},
                    {Distance2d 2.9in, 2.2in}
                }

            let colors:{Array-of Fraction3d} =
                {{Array-of Fraction3d}
                    {Fraction3d 1.0, 0.0, 0.0}, || red
                    {Fraction3d 1.0, 0.0, 0.0},
                    {Fraction3d 0.0, 0.0, 1.0}, || blue
                    {Fraction3d 0.0, 0.0, 1.0}, || blue
                    {Fraction3d 0.0, 1.0, 0.0}, || green
                    {Fraction3d 0.7, 0.0, 1.0}  || purple
                }

            || clear the drawable
            {renderer.clear}
            
            || render a polygon
            {render-primitive
                primitive:Primitive,
                type = "triangle-strip"
                on renderer do

                {for idx:int = 0 below vertices.size do
                    {primitive.color3v colors[idx]}
                    {primitive.vertex2v vertices[idx]}
                }
            }
        }
}