Listing 1

------------------------------------------------------------
--TraceRayOrSegment3D
------------------------------------------------------------
--Purpose: Traces a ray through the 3D world and returns --either no collision, or a
 collision with an object.
--Generally used for pt to light or pt to reflected point --calculations. Returns an array:
 the first element --is an integer: 0=no collision, 1= collision, the second --element of
  which is a vector describing the point hit, --the third is an array of the triangle hit,
   the forth is --an array of texture coordinates at the hit location, and --the final
    value is a reference to the model that was hit.
--
--a_3dWorld -- a 3D world in which to trace --a_mObstacles --a list of models that are
 valid obstacles --a_aOwnTri --the triangle the ray is cast from (ignored) --a_vStartPos
  --vector starting position of the ray/segment --a_vDir --vector direction of the
   ray/segment --a_vEndPos --end point of the segment (use int 0 for ray) --a_bQuickCheck
    --whether to use ModelsUnderRay for a quick --look at whether or not we hit a model
	 (ignored backfacing --collision and uses bounding sphere -- non accurate !!!!)
	  --a_bReturnFirst --returns the first hit found if true, --otherwise returns the hit
	   guarenteed closest to the --a_vStartPos vector in world space (a longer search)
	    --a_bVisualDebug --whether or not to use visual debug lines

--ONLY REQUIRED FOR DEBUG
--a_iX - X count of lumel in map
--a_iY - Y count of lumel in map
--a_iLC - which light pass this is
--a_shShader -- debug shader reference
--a_rgbColor1
--a_rgbColor2

--viscious HACKERY
--a_bReturnAll --return all hits along the vector

--returns:
--[TRUE/FALSE,vHitPosition,aTriangleHit,aTexCoords, mModel]
------------------------------------------------------------
on ghTraceRayOrSegment3D a_3dWorld, a_mObstacles, \  a_aOwnTri, a_vStartPos, a_vDir,
 a_vEndPos, a_bQuickCheck,\  a_bReturnFirst, a_bVisualDebug, a_iX, a_iY, a_iLc, \ 
  a_shShader, a_mModel, a_rgbColor1, a_rgbColor2, \  a_bReturnAll
 
 --use models under ray for a quick look at collision  if a_bQuickCheck then
   plOptions = [#maxNumberOfModels: 1, #levelOfDetail: \
         #simple ]
  
  aHitModels = a_3DWorld.modelsUnderRay(a_vStartPos, \
      a_vDir, plOptions)
  
  if aHitModels.count = 0 then return [false]  end if
 
 --initialize flags
 bHitAFace = false
 vHitPosition = vector(0,0,0)
 aHitList = []
 
 --calculate ray end if non-segment
 if a_vEndPos = 0 then a_vEndPos = a_vStartPos + \
            (a_vDir * _global.g_fRayLengthCap)
 
 
 repeat with iObj = 1 to a_mObstacles.count
  repeat with iFace = 1 to a_mObstacles[iObj\
            ].meshDeform.face.count
   
   --get information about this face
   aIndicies = a_mObstacles[iObj\
   ].meshDeform.mesh[1\
         ].face[iFace]
   
   --get the verticies of this face
   vA = a_mObstacles[iObj\
         ].meshDeform.mesh[1\
         ].vertexList[aIndicies[1]]
   
   vB = a_mObstacles[iObj\
         ].meshDeform.mesh[1\
   ].vertexList[aIndicies[2]]
   
   vC = a_mObstacles[iObj\
         ].meshDeform.mesh[1\
         ].vertexList[aIndicies[3]]
   
   
   --convert this triangle to world space
   vP1 = a_mObstacles[iObj].getWorldTransform() * vA
   vP2 = a_mObstacles[iObj].getWorldTransform() * vB
   vP3 = a_mObstacles[iObj].getWorldTransform() * vC
   
   aTri = [vP1, vP2, vP3]
   if aTri <> a_aOwnTri then --dont collide with own face
    
    --check for collision using custom maths
    aTriCol = ghTriangleRayCollision([a_vStartPos, \
            a_vEndPos], aTri)
    
    if (aTriCol[1] = 1) then --hit something
     --set flags and store this triangle
     bHitAFace = true
     vHitPosition = aTriCol[2]
     aTriangleHit = aTri
     
     --get texture infos from this triangle
     aUV1 = a_mObstacles[iObj\
         ].meshDeform.mesh[1\
         ].textureLayer[1\
         ].textureCoordinateList[\
         aIndicies[1]]
     
     aUV2 = a_mObstacles[iObj\
         ].meshDeform.mesh[1\
         ].textureLayer[1\
         ].textureCoordinateList[\
         aIndicies[2]]
     
     aUV3 = a_mObstacles[iObj\
         ].meshDeform.mesh[1\
         ].textureLayer[1\
         ].textureCoordinateList[\
         aIndicies[3]]
     
     aTexCoords = [aUV1, aUV2, aUV3]
     
     mModel = a_mObstacles[iObj]
     
     --debug marker
     if _global.g_bDebugMarkRayTriangleCollisions then
      put "HIT A TRIANGLE on model " & mModel.name
     end if
     
     if a_bReturnFirst = true then
      --we are about to return, so debug this path
      --if debugging is on
      if a_bVisualDebug then
       sName = "connector " & a_iX & a_iY & \
           a_iLC & iFace & a_mModel.name
       
       ghDebugRay(a_3dWorld, sName, a_rgbColor1, \
        a_rgbColor2, a_vStartPos, a_vEndPos, \
        a_shShader)
       
      end if
      
      --we hit something not ourselves, so return
      return [true, vHitPosition, aTriangleHit, \
         aTexCoords, mModel]
     else
      
      --store this hit in the list of all hits
      --along this ray for later determination
      --of the closest hit
      aHitList.add([true, vHitPosition, \
        aTriangleHit, aTexCoords, mModel])
      
     end if
     
    else
     --self face intersection or blank pass
    end if
    
   end if
   
  end repeat
 end repeat
 
 --debug this useless pass debugging is on  if a_bVisualDebug then
  sName = "connector " & a_iX & a_iY & a_iLC & iFace \
      & a_mModel.name
  
  ghDebugRay(a_3dWorld, sName, a_rgbColor1, a_rgbColor2, \
        a_vStartPos, a_vEndPos, a_shShader)
  
 end if
 
 --if we are storing all hits, calculate the closest one  --and return it
 
 if a_bReturnFirst = false and a_bReturnAll = false then
  if aHitList.count > 1 then
   
   aClosest = aHitList[1]
   fDist = (a_vStartPos - aHitList[1][2]).magnitude
   
   repeat with iC = 2 to aHitList.count
    
    fNewDist = (a_vStartPos - \
          aHitList[iC][2]).magnitude
    
    if fNewDist < fDist then
     fDist = fNewDist
     aClosest = aHitList[iC]
    end if
    
   end repeat
   
   return aClosest
   
  else if aHitList.count = 1 then
   return aHitList[1]
  end if
  
 end if
 
 if a_bReturnAll = true then
  if aHitList.count >= 1 then
   
   --order the hitlist from closest
   --to farthest. total pain.
   
   aOrderedList = []
   
   repeat while aHitList.count > 0
    
    aClosest = aHitList[1]
    fDist = (a_vStartPos - aHitList[1][2]).magnitude
    iPos = 1
    
    repeat with iC = 2 to aHitList.count
     
     fNewDist = (a_vStartPos - \
          aHitList[iC][2]).magnitude
     
     if fNewDist < fDist then
      fDist = fNewDist
      iPos = iC
      aClosest = aHitList[iC]
     end if
     
    end repeat
    
    aOrderedList[aOrderedList.count+1] = aClosest
    aHitList.deleteAt(iPos)
    
   end repeat
   
   return aOrderedList
  else
   return [[false]]
  end if
 end if
 
 --return no collision
 return [false]
 
end ghTraceRayOrSegment3D


Listing 2

------------------------------------------------------------
------------------------------------------------------------
--GetTriangleRayCollision
------------------------------------------------------------
--Purpose: 
--a_aRay - an Array of 2 vectors, representing the start and --end points of a ray in 3D
 space --a_aTrangle - an array of vectors representing the --points of the triangle in 3D
  world coordinates --returns an array where the first element represents --collision (1 if
   collide, 2, -1, or 0 if no collision) and --the second element (if present) is the point
    of collision --as a world-space vector
------------------------------------------------------------
on ghTriangleRayCollision a_aRay, a_aTriangle 
 --http://softsurfer.com/Archive/algorithm_0105/
  --algorithm_0105.htm#intersect_RayTriangle()
 
 --triangle vectors
 vU = a_aTriangle[2] - a_aTriangle[1]
 vV = a_aTriangle[3] - a_aTriangle[1]
 vN = ghGet3DTriangleFaceNormal(a_aTriangle)
 
 --test for degenerate triangle
 if (vN = vector(0,0,0)) then return [-1]
 
 --ray vectors
 vDir = a_aRay[2] - a_aRay[1]
 vW0 = a_aRay[1] - a_aTriangle[1]
 
 fA = -vN.dot(vW0)
 fB = vN.dot(vDir)
 if (abs(fB) < 0.00001) then --ray is parallel to triangle
  if (fA = 0) then
   return [2] --ray is on the triangle plane
  else
   return [0] --ray is disjoint from plane
  end if
 end if
 
 --get intersection point of ray with triangle plane  fR = fA / fB  if (fR < 0.0) then
  return [0]  if (fR > 1.0) then return [0]
 
 --intersection point of ray and plane
  vI = a_aRay[1] + fR * vDir
 
 --is I inside T ??
 fUu = vU.dot(vU)
 fUv = vU.dot(vV)
 fVv = vV.dot(vV)
 
 vW = vI - a_aTriangle[1]
 fWu = vW.dot(vU)
 fWv = vW.dot(vV)
 fD = fUv * fUv - fUu * fVv
 
 --get and test parametric coordinates (s,t)  fS = (fUv * fWv - fVv * fWu) / fD  --I is
  outside T ?
 if (fS < 0.0) or (fS > 1.0) then return [0]
 
 fT = (fUv * fWu - fUu * fWv) / fD
 --I is outside T ?
 if (fT < 0.0) or ((fS + fT) > 1.0) then return [0]
 
 return [1, vI] -- I is in T
 
end ghTriangleRayCollision
------------------------------------------------------------

Listing 3

------------------------------------------------------------
--GetBarycentricCoordinates3D
------------------------------------------------------------
--Purpose: Solves for barycentric coords given a 3D triangle --and a vector/point within
 that triangle. Returns a non- --normalized vector --a_aTriPts - array of 3 vectors that
  form the triangle --a_vP - point that is inside the triangle on on its plane
------------------------------------------------------------
on ghGetBarycentricCoords3D a_aTriPts, a_vP
 
 fU = a_aTriPts[2] - a_aTriPts[1]
 fV = a_aTriPts[3] - a_aTriPts[1]
 fW = a_vP - a_aTriPts[1]
 
 fD = (power(fU.dot(fV), 2) - (fU.dot(fU))*(fV.dot(fV)))  fS =
 ((fU.dot(fV))*(fw.dot(fV))- \
    (fV.dot(fV))*(fw.dot(fU))) / fD
 fT = ((fU.dot(fV))*(fw.dot(fU))- \
    (fU.dot(fU))*(fw.dot(fV))) / fD
 
 fW = fS*fU + fT*fV --unique if P lies within the plane  fB0 = (1-fS-fT)
 fB1 = fS
 fB2 = fT
 
 vBaryC = vector(fB0, fB1, fB2)
 return vBaryC
 
end ghGetBarycentricCoords3D
------------------------------------------------------------

Listing 4

------------------------------------------------------------
--GetTexelValues
------------------------------------------------------------
--Purpose:
--a_aValues - array of 2D points, 3D points, or normals that --are representative of values
 at the 3 points of a --triangle.
--a_a_Weights - barycentric coordinates of the point --to solve for relative to vertex
 values
------------------------------------------------------------
on ghGetTexelValues a_aValues, a_aWeights
 
 --compute X and Y averages based on barycentric coords
 fR1 = (a_aWeights[1]*a_aValues[1][1]) +  \
    (a_aWeights[2]*a_aValues[2][1]) +  \
    (a_aWeights[3]*a_aValues[3][1])
 
 fR2 = (a_aWeights[1]*a_aValues[1][2]) +  \
    (a_aWeights[2]*a_aValues[2][2]) +  \
    (a_aWeights[3]*a_aValues[3][2])
 
 --if there is a third value, then calculate it also  if a_aValues[1].ilk() = #vector then
  fR3 = (a_aWeights[1]*a_aValues[1][3]) + \
     (a_aWeights[2]*a_aValues[2][3]) + \
     (a_aWeights[3]*a_aValues[3][3])
  
  --return a vector if 3D triangle
  vReturn = vector(fR1, fR2, fR3)
  return vReturn
 end if
 
 --reutrn 2D coord if 2D inputs
 aReturn = [fR1, fR2]
 return aReturn
 
end ghGetTexelValues
------------------------------------------------------------