...
One of the interesting things of these geometries is that they can be split into several subregions or subvolumes. This can increase the efficiency of the intersection tremendously. Instead of having an object with a huge bounding box, this can be divided into several regions, with much more smaller bounding boxes. These regions can be spatially connected or not, and each region could evaluate a different mathematical problem to calculate a point on its surface. Each region or subvolume has its own bounding box, which is calculated in getSubVolumeBoundingBox, and the number of subvolumes is returned in getNumSubVolumes. There is also a function that returns the bounding box of the whole object, getBoundingBox. One of the optional functions, isOverlappingBoundingBox, checks the intersection of two boxes, one sent by the render engine, and the other that ob the given subvolume, to optimize the rendering.
These extensions
Code Block | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
#include <math.h>
#include "extensionmanager.h"
#include "geometryextension.h"
#include "maxwell.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 )
{
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 );
}
};
EXPORT_GEOMETRY_PROCEDURAL_EXTENSION( SphereRenderExtension ) |