Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

The actual work of this extension is done in intersect. This is the speed critical routine. Make every effort to optimize this function. Do not allocate memory in it. Avoid any OS and/or SDK function calls in this critical routine. Most of the memory and extension data structures whic which will be used during the render can be pre-allocated in initializeForRendering. If you want to access the global scene pointer, store it in initializeForRendering and use it later. This can save a huge amount of time.

...

These extensions can also have their own custom UV generators. These generators are declared using getNumberOfUVGenerators and getUVGeneratorNameusing getNumberOfUVGenerators and getUVGeneratorName. Once declared, they can be used normally with Cmaxwell::Cobject::addChannelUVW( dword uvIndex ) and Cmaxwell::Cobject::generateCustomUVW( dword iChannel, dword iGeneratorType ).The generators are implemented in getUVForChannel. This is also a speed critical function, so it must be optimized very carefully (no file I/O, no OS calls, no SDK calls...).

...

true on success, false otherwise. false aborts the render.

 

initializePreview

virtual bool initializePreview( Cmaxwell* pMaxwell );

Reset all the pointers allocated in getProxyDisplay* and make them ready for reuse.

Arguments

Cmaxwell* pMaxwell : input, pointer to the scene.

Returns

true on success, false otherwise.

intersect

virtual bool intersect( Cmaxwell::Cobject* object, const Cpoint& rayOrigin, const Cvector& rayDir, real time, const dword subVolumeIndex, Cvector* pNormal, Cvector* pLocalImpact, CfVector& data, Cvector& parametricUVW, Cvector& tangentU, Cvector& tangentV ) = 0;

Given a ray (direction and origin), calculate and return a point and normal on the surface of the object. If the tangential base cannot be calculated, leave the input vectors tangentU and tangentV as they are.

Arguments

Cmaxwell::Cobject& object : input, reference to the extension object.

...

Cvector& tangentU, tangentV : output, tangent vectors to the surface. If P=p(u,v), then tu = dP/du and tv = dP/dv;

Returns

true on intersection, false otherwise.

...

The ordering of the box points is as follows:

...

 Image Added

In the image, points 0 and 6 would be bbmin and bbmax respectively in an axis-aligned bounding box.

The points must be in local coordinates of the extension object.

Arguments

Cpoint* bboxPoints: output, 0-based array of eight points.

float time : input, time of evaluation of the box.

Returns

Nothing.

getNumSubVolumes

virtual dword getNumSubVolumes( void );

Return the number of subvolumes that the object is subdivided into.

Arguments

None

Returns

Number of subvolumes.

getSubVolumeBoundingBox

...

Return the bounding box of the subvolume, in local coordinates of the extension object, as a 0-based array of eight points, at the given time.

Arguments

Cpoint* bboxPoints : output, 0-based array of eight points. See getBoundingBox for the point ordering.

...

float time : input, time of evaluation of the box.

Returns

Nothing.

getNumberOfUVGenerators

...

Returns the number of implemented custom UV generators.

Arguments

None.

Returns

Number of UV generators. Max 255.

...

Return a string with the name of the UV generator.

Arguments

byte index : input, index of the generator, max 255.

Returns

String with the generator name. If index > numberOfUVGenerators or index < 0, return NULL.

...

Calculates the UV texture coordinates for the given point "point". When dealing with analytical surfaces, it's often more convenient to use "parametricUVW" as input data. "normal" is the normal at the intersection point.

Arguments

CfVector& uvw : output, calculated texture coordinates, values range from 0.0 to 1.0.

...

const Cvector& parametricUVW : input, natural parametric coordinates of the surface, calculated in intersect.

Returns

1 on success, 0 otherwise.

...

Helper function for the render engine. Tests whether the box given by "bboxPoints" and that of the subvolume indexed by "subVolumeIndex" overlap.

Arguments

Cpoint* bboxPoints : input, 0-based array of eight points. See getBoundingBox for the point ordering.

...

bool forceHalfTime : input, type of subvolume box for evaluation. If forceHalfTime is true, the subvolume box to comapre is at time 0.5. If true, it is the smallest box that encloses the swept space of the object in the subvolume from time 0.0 to time 1.0.

Returns

true on intersection, otherwise false;

...

Helper function for the render engine. Returns the surface area of the given subVolume indexed by "subVolumeIndex".

Arguments

dword subVolumeIndex : input, index of the subvolume to compare its box to.

const Cbase* transformationBase : input, transform the geometry with this base and then calculate the area.

Returns

area of the subVolume;

getSubVolumePointAndNormal

...

Helper function for the render engine. Returns the surface area of the given subVolume indexed by "subVolumeIndex".

Arguments

dword subVolumeIndex : input, index of the subvolume to compare its box to.

...

real rndTime : time of evaluation of the ray, to take into account motion blur.

Returns

nothing.

getProxyDisplayPoints

...

Allocates and fills the "points" array with the coordinates of points to be drawn in Studio viewports. Also sets "nPoints" to the actual number of points filled.

Arguments

const dword& percent : input, goes from 0 to 100, indicating the degree of desired precision to draw the proxy.

...

 float*& points : output, array with the points, x0y0z0x1y1z1x2y2z2....

Returns

true on success, otherwise false;

...

Allocates and fills the "points" array and "pointsPerLine" array with with the coordinates of points, and number of points per line to be drawn in Studio. Also sets "nPoints" to the actual number of points created and nLines to the actual number of lines created.

Arguments

const dword& percent : input, goes from 0 to 100, indicating the degree of desired precision to draw the proxy.

...

dword*& pointsPerLine : output, array with the number of points per line, n0n1n2.... If this array is NULL, then the number of points per line is constant, and is nPoints/nLines.

Returns

true on success, otherwise false;

...

Allocates and fills the "points" array and "faces" array with with the coordinates of points, and indexes to vertices to be drawn in Studio. Also sets "nPoints" to the actual number of points created and "nFaces" to the actual number of triangles created.

Arguments

const dword& percent : input, goes from 0 to 100, indicating the degree of desired precision to draw the proxy.

...

dword*& faces : output, array with the indices to vertices in the "points" array  v00v01v02v10v11v12v20v21v22....

Returns

true on success, otherwise false.

...

Code Block
languagecpp
titleAnalytical Sphere Example
firstline1
linenumberstrue
#include <math.h>
#include "extensionmanager.h"
#include "geometryextension.h"
#include "maxwell.h"
#include "maxwellversions.h"
#ifndef DEG2RAD
#define DEG2RAD(d) ((d) * 3.14159265358979323846 / 180.0)
#endif

class SphereRenderExtension : public CgeometryProceduralExtension
{
	DECLARE_EXTENSION_METHODS( "SphereRenderExample", SphereRenderExtension, 1 )
	Cmaxwell* pMaxwellLocal;
	double radius;

public:
	SphereRenderExtension()
	{
		getExtensionData()->createDouble( "Radius", 1.00, 0, 1000000 );
	}
	~SphereRenderExtension()
	{
	}

    bool initializeForRendering ( Cmaxwell* pMaxwell, Cmaxwell::Cobject& proceduralObject )    
    {
        pMaxwellLocal = pMaxwell;
		getExtensionData()->getDouble( "Radius", radius );
        return true;
    }

    //Helper function to spit messages to maxwell.
    void printMessage( const char* text, const int code )
    {
        if( pMaxwellLocal != NULL ) 
        {
            char pMessage[ 1024 ];
            sprintf ( pMessage, "[Extension %s] %s", getName(), text );
            pMaxwellLocal->printMessage( pMessage, code );
        }
    }

    dword getNumSubVolumes( void )
    {
        return 1;//We just have one region surrounding the whole sphere
    };

	bool intersect( Cmaxwell::Cobject* object, const Cpoint& origin, const Cvector& dir, 
			real time, const dword subVolumeIndex, Cvector* pNormal, Cvector* pLocalImpact, 
			CfVector &data, Cvector& parametricUVW, Cvector& tangentU, Cvector& tangentV )
	{
		real dist, a, b, disc, t0, t1, sqr;
		dist = -1.0;
		//Assume sphere centered in ( 0, 0, 0 ) in local coordinates
		a = 2*( dir.x*origin.x + dir.y*origin.y + dir.z*origin.z );
		b = origin.x*origin.x + origin.y*origin.y + origin.z*origin.z - radius*radius;
		disc = a*a - 4*b;
		if ( disc < 0.0 )
		{
			return false;
		}
		sqr = sqrt ( disc );
		t0 = ( -a - sqr ) * 0.5;
		t1 = ( -a + sqr ) * 0.5;
		if ( t0 <= 0.0 )
		{
			if ( t1 > 0.0 )
			{
				dist = t1;
			}
			else
			{
				return false;
			}
		}
		else
		{
			if ( t0 < t1 ) dist = t0;
			else dist = t1;
		}
		Cvector p;
		p.assign( origin + dir * dist );//Point of intersection in local coordinates
		pLocalImpact->assign( p );
		Cvector normal;
		normal.assign( p );
		pNormal->assign( normal );//No need to normalize. Done later on demand.
		return true;
	}
	void getBoundingBox( Cvector& bmin, Cvector& bmax, float time )
	{
		bmin.assign( -radius, -radius, -radius );
		bmax.assign( radius, radius, radius );
	}
};

extern "C" ALWAYSEXPORT int getSdkVersion()
{
    return MAXWELL_SDK_VERSION;
}

extern "C" ALWAYSEXPORT int StartExtension( CextensionManager& extensionManager )
{
    int i = 0;
    if ( extensionManager.registerGeometryProceduralExtension( new SphereRenderExtension ) ) i++;
    return i;
}