The Pure Perl RayCaster

Index

The API

About the Pure Perl Renderer API

Ok. Here are some notes on the existing code. The idea is to have available an easy to use API in order to apply typical 3D Computer Graphics techniques in Perl.

THIS IS NO COMPLETE DOCUMENTATION BY ANY MEANS. No every aspect is covered, just some basic notes to help you study, tweak, make use of the RayCaster and get you started. Do not expect a complete API for doing 3D CG (Computer Graphics) in Pure Perl RayCaster, but just a set of classes to perform many fundamental 3D CG operations. I suggest to study the source after these notes so as to have a better understanding of all you may need. There are several things on the existing source that can be improved.


ObjectReader::FileRaw Class

This class is used by RendererCanvas constructor (RendererCanvas is instantiated by the .pl script) in order to read the vertices from the RAW File. The class is responsible for setting up and returning an Object3D class with its Polygons and Vertices. Vertices normals are also calculated in this class (the rest of the application expects a ready to use object). The last step before returning the object to reader is to call Object's InitObjectScene(). You can create other Classes in ObjectReader directory for reading other formats if you want (especially plain text files are very easy to be parsed using Perl). If you want you may contribute any new ObjectReader (for other formats) you have written.


AffineTransform Class

This is a class to handle Affine Transformations. You get a 4x4 matrix that can be applied on Vertices, Vectors etc.

Typical usage:

    my AffineTransform $newTransform = new AffineTransform;
    
    #Transformations follow (they are stacked in the newTransform object)
    $newTransform->rotateX($theta);
    $newTransform->rotateZ($phi);
    $newTransform->rotateY(-$theta);
    
    #$aVertex is a Vertex Object, translate to its (x,y,z) values
    $newTransform->translate(-10,300,20);  #coordinates
    $newTransform->translate2Vertex($aVertex);  
    $newTransform->scale($zoom);
    
    #stacks an arbitrary matrix ($myMatrix is an array ref.) to $newTransform
    $newTransform->arbitraryMatrix($myMatrix);
    
    #combine all requested transformations (in reverse order)
    #and create the  final 4x4 matrix (as an array ref.) that represents all 
    #requested transformations
    my  $T = $newTranform->getFinalTransformMatrix();  
    
    #apply the matrix $T...
    #to vertices
    $myObject->transformVertices($T);
    
    #to faces normals
    $myObject->transformFacesNormals($T);
    
    #to visible vertices (after back face culling)
    $myObject->transformVisible($T);
    
    #to vertices normals
    $myObject->transformVerticesNormals($T);
           

Polygon, Vertex and Object3D Classes

Implement the Polygons (triangles in the application), the Vertices and the 3D Objects.

Typical usage:

 
    #create three 3D points (Vertices) from simple scalars
    my Vertex $point1 = new Vertex ($p1x,$p1y,$p1z);
    my Vertex $point2 = new Vertex ($p2x,$p2y,$p2z);
    my Vertex $point3 = new Vertex ($p3x,$p3y,$p3z);
    
    #create a new vertex based on those three 3D points
    my Polygon $aPolygon = new Polygon ($point1,$point2,$point3);
    #add this polygon to our object
    my Object3D $obj = $Object3D->addPolygon($aPolygon);
    
    #After adding vertices and polygons to an object, 
    #call the following method to initialize it.
    #In this method we position lights and the camera to 
    #our scene and we make copies of all vertices and lights
    #to be able to restore everything in their initial state
    #Right now, you must change the source in this method to add 
    #or move lights and your camera position
    $anotherObj->initObjectScene();
    
    #apply a 4x4 transform (created by AffineTransform)
    #to a vertex
    $point1->transform($T);
    #to its normal
    $point1->transformNormal($T);
    
    #to all vertices of face
    $aPolygon->transform($T);
    
    #to face normal
    $aPolygon->transformNormal($T);
    
    #apply $T only if face is not hidden
    $aPolygon->transformVisible($T);
    
    #to all vertices
    $Object3D->transformVertices($T);
    
    
    #strigification of our objects
    print "Vertex \$point1 is: $point1\n"
    print "Polygon \$aPolygon (all vertices) is: $aPolygon\n"
    print "Object3D \$obj (all polygons with their vertices) is: $obj\n"
    
    
    #add,subtract and calc. product with a scalar of 2 vertices
    $point2->add($point1);        #p2 = p2 + p1
    $point3->subtract($point1);   #p3 = p3 - p1
    $point1->product(34.2);       #p1 = p1 * 34.2
    
    #get distance between $point2 and $point1:
    my $dist_21 = $point2->distance($point1);
    
    #add one vertex to $anotherPolygon
    $aPolygon->addVertices($anotherVertex);
    
    #compute polygon normal
    $anotherPolygon->computeNormal();
    
    #transform only tagged as non 'hidden' vertices by 4x4 Matrix ref. $T
    $anotherPolygon->transformVisible($T);
    
    #transform a polygon's normal by 4x4 Matrix array ref. $T 
    #(yours or returned by an AffineTransform)
    $aPolygon->transformNormal($T);
    
    #get a reference to all vertices of a polygon.
    my $polyVertices = $anotherPolygon->getVertices();
    
    #test and set the hidden attribute of a polygon 
    #(if polygon is not visible to current view)
    $anotherPolygon->checkIfHidden();
    
    #test and set the hidden attribute of all object's polygons 
    #(if polygon is not visible to current view)
    $anotherObject->hidePolygons();
    
    #calculates and stores as object fields the following scalars 
    #x_max, y_max, z_max, x_min, y_min, z_min and x_center,y_center,z_center
    $anotherObj->getBoundingBoxAndCenter();
    
    
    #Resets all polygons vertices to original polygons vertices 
    #which were copied when object was initialized.
    #Use it after transformations to get Object at initial state            
    $anotherObj->resetObject();
    
    
    #do the raycasting drawing on 2 Device Context objects (DCs) 
    #passed as arguments to the method
    #$app reference is used just to Yield() in our tight time consuming loop
    #to avoid "not-responding" windows.
    #We draw on 2 device contexts now (one in memory), 
    #(implementing double buffering, 'blitting' memory to 
    #real one on request
    $anotherObj->render($memoryDC, $dc, $app);
    
    #draw the wireframe on device context $dc
    $anotherObj->drawWireframe($dc);
    

Ray Class

Simple class representing rays. Rays have the following fields, which you can set/get. Rays can be stringified:

Camera Class

Represents the camera in our World.

Important fields are: Important Methods:

RayCast Class

Represents and Implements the RayCasting.

Important methods:

Other info


The WxPerl side

WxPerl is being used to create the GUI of the application. WxWindows (wxPerl) components are being used in the following places:

Valid XHTML 1.0 Transitional