'// http://vbfibre.digitalrice.com (Many VB speed tricks with benchmarks)
'//This code is highly optimized. If you manage to gain some more FPS
'//I'm always interested =-)
'//Finished @ 01/04/2002
'//Feel free to post this code anywhere, but please leave the above info
'//and author info intact. Thank you.
'//Vector
Public Type Vector3D
x As Single
y As Single
z As Single
End Type
'//1 Ray
Public Type Ray
Origin As Vector3D
Direction As Vector3D
End Type
'//Color
Public Type ColorFloat
R As Single
G As Single
b As Single
End Type
'//Result of raytrace (for one ray)
Public Type TraceResult
Hit As Boolean
Distance As Single
End Type
'//Surface properties
Public Type udtSurface
BaseColor As ColorFloat
sngReflectivity As Single
End Type
'//Light source
Public Type LightSource
location As Vector3D
Color As ColorFloat
End Type
'-------------------------------
'//Primitives
Public Enum EnumAxis
X_INFINITE
Y_INFINITE
Z_INFINITE
End Enum
Public Type udtCylinder
Axis As EnumAxis
Center As Vector3D
sngRadius As Single
End Type
Public Type udtPlane
sngDisplacement As Single
vecNormal As Vector3D
End Type
Public Type udtSphere
vecCenter As Vector3D
sngRadius As Single
End Type
Public Type udtTriangle
v1 As Vector3D
v2 As Vector3D
v3 As Vector3D
End Type
'\\
'-------------------------------
'//Collection of primitives
Public Enum EnumPrimitives
SPHERE_TYPE = 0
PLANE_TYPE = 1
CYLINDER_TYPE = 2
TRIANGLE_TYPE = 3
End Enum
Public Type Primitive
Cilinder As udtCylinder
Plane As udtPlane
Sphere As udtSphere
Triangle As udtTriangle
Surface As udtSurface
Type As EnumPrimitives
End Type
'\\
'//Math
Public Function CylinderNormal(Cylinder As udtCylinder, Intersection As Vector3D) As Vector3D
Dim Normal As Vector3D
Dim oneOverRadius As Single
oneOverRadius = 1 / Cylinder.sngRadius ' // might be faster to precalc this and store it in the sphere data structure, but also might be slower because it takes longer to load 32 bits of
Public Function PlaneNormal(Plane As udtPlane) As Vector3D
PlaneNormal = Plane.vecNormal
End Function
Public Function SphereNormal(Sphere As udtSphere, Intersection As Vector3D) As Vector3D
Dim Normal As Vector3D
Dim sngOneOverRadius As Single
'// calculate the normal of the sphere at the point of interesction
sngOneOverRadius = 1 / Sphere.sngRadius '// might be faster to precalc this and store it in the sphere data structure, but also might be slower because it takes longer to load 32 bits of
'// data than to calculate 1 division (i think)
With Sphere.vecCenter
Normal.x = (Intersection.x - .x) * sngOneOverRadius ' // same as ( intersection.x - sphere.center.x ) / sphere.radiu
lengthRTSC2 = VectorDot(rayToSphereCenter, rayToSphereCenter) ' // lengthRTSC2 = length of the ray from the ray's origin to the sphere's center squared
If closestApproach < 0 Then '// the intersection is behind the ray
myTraceResult.Hit = False
IntersectSphere = myTraceResult
Exit Function
End If
'// halfCord2 = the distance squared from the closest approach of the ray to a perpendicular to the ray through the center of the sphere to the place where the ray actually intersects the sphere
halfCord2 = (Sphere.sngRadius * Sphere.sngRadius) - lengthRTSC2 + (closestApproach * closestApproach) '// sphere.radius * sphere.radius could be precalced, but it might take longer to load it
'// than to calculate it
If halfCord2 < 0 Then '// the ray misses the sphere