183 lines
4.4 KiB
Plaintext
Executable File
183 lines
4.4 KiB
Plaintext
Executable File
--
|
|
-- File:: pipeline/util/MeshUtil.ms
|
|
-- Description:: Set of functions for interacting with meshes
|
|
--
|
|
-- 23/6/2004
|
|
-- by Greg Smith <greg.smith@rockstarnorth.com>
|
|
--
|
|
-----------------------------------------------------------------------------
|
|
|
|
-- Returns lowest vert (in world-space) in obj:
|
|
fn RsGetLowestVert obj =
|
|
(
|
|
local copiedMesh = not isKindOf obj EditableMesh
|
|
local objMesh = if copiedMesh then (copy obj.mesh) else obj.mesh
|
|
|
|
local minZ
|
|
local minVert = dataPair idx:undefined pos:undefined
|
|
|
|
for n = 1 to getNumVerts objMesh do
|
|
(
|
|
local vertPos = getVert objMesh n
|
|
|
|
if copiedMesh do
|
|
(
|
|
vertPos *= obj.transform
|
|
)
|
|
|
|
if (minZ == undefined) or (vertPos.z < minZ) do
|
|
(
|
|
minZ = vertPos.z
|
|
minVert.pos = vertPos
|
|
minVert.idx = n
|
|
)
|
|
)
|
|
|
|
return minVert
|
|
)
|
|
|
|
mapped fn RSmoveToGround objA objB percentMin percentMax =
|
|
(
|
|
if (not isProperty objA "mesh") or (not isProperty objB "mesh") do (return False)
|
|
|
|
local objAMesh = if (isKindOf objA EditableMesh) then objA.mesh else (copy objA.mesh)
|
|
local objBMesh = if (isKindOf objB EditableMesh) then objB.mesh else (copy objB.mesh)
|
|
|
|
local lowestVert = RsGetLowestVert objA
|
|
|
|
local testRay = ray lowestVert.pos [0,0,-1]
|
|
local intersect = intersectRay objB testRay
|
|
|
|
if (intersect != undefined) do
|
|
(
|
|
local rand_offset = random percentMin percentMax
|
|
|
|
local startRot = objA.rotation
|
|
local objRotZ = (startRot as eulerangles).z
|
|
|
|
-- MATCH THE DIRECTION
|
|
local directionOffset = intersect.dir - objA.dir
|
|
-- PERCENT OF ANGLE MATCH * GROUND ANGLE
|
|
objA.dir = intersect.dir - (directionOffset * ((100-rand_offset)/100.0))
|
|
|
|
local newRot = objA.rotation as eulerangles
|
|
newRot.z = objRotZ
|
|
objA.rotation = newRot
|
|
|
|
-- Update lowest-vert pos to rotated position:
|
|
lowestVert.pos = (getVert objA.mesh lowestVert.idx) * objA.transform
|
|
|
|
local moveVec = intersect.pos - lowestVert.pos
|
|
local setPos = objA.pos + moveVec
|
|
|
|
objA.pos = setPos
|
|
)
|
|
)
|
|
|
|
--
|
|
--fn: RSFindFacesWithZeroArea
|
|
--desc: Finds any faces on a editable mesh or poly with 0 area
|
|
-- and deletes them (which deletes the verts)
|
|
--
|
|
-- returns true if the faces are deleted, or the array of faces
|
|
-- with zero area if deleteFaces is false.
|
|
--
|
|
fn RSFindFacesWithZeroArea obj deleteFaces:false = (
|
|
|
|
facesToDelete = #()
|
|
|
|
if ( Editable_Mesh == classof obj ) then
|
|
(
|
|
for f = ( meshop.getNumFaces obj ) to 1 by -1 do
|
|
(
|
|
if ( meshop.getFaceArea obj f == 0 ) do
|
|
(
|
|
append facesToDelete f
|
|
)
|
|
)
|
|
|
|
if ( true == deleteFaces) then
|
|
(
|
|
meshop.deleteFaces obj facesToDelete
|
|
true
|
|
)
|
|
else
|
|
(
|
|
facesToDelete
|
|
)
|
|
)
|
|
else if ( Editable_Poly == classof obj ) do
|
|
(
|
|
for f = ( polyop.getNumFaces obj ) to 1 by -1 do
|
|
(
|
|
if ( polyop.getFaceArea obj f == 0 ) do
|
|
(
|
|
append facesToDelete f
|
|
)
|
|
)
|
|
|
|
if ( true == deleteFaces) then
|
|
(
|
|
polyop.deleteFaces obj facesToDelete
|
|
true
|
|
)
|
|
else
|
|
(
|
|
facesToDelete
|
|
)
|
|
)
|
|
)
|
|
|
|
fn RsTestFaceForVertIndex face index =
|
|
(
|
|
case index of
|
|
(
|
|
(face[1]):1
|
|
(face[2]):2
|
|
(face[3]):3
|
|
default:0
|
|
)
|
|
)
|
|
|
|
fn RsGetColourAverageForMeshVertIndex theMesh theChannel meshVertIndex =
|
|
(
|
|
local faces = (meshop.getFacesUsingVert theMesh #{meshVertIndex}) as array
|
|
local indeces = #()
|
|
local mapindeces = #()
|
|
local averagedValue = [0,0,0]
|
|
for f in faces do
|
|
(
|
|
append indeces (getFace theMesh f)
|
|
append mapindeces (meshop.getMapFace theMesh theChannel f)
|
|
)
|
|
|
|
for index=1 to 3 do
|
|
(
|
|
-- local vertindex = indeces[1][index]
|
|
local meshVertIndeces = #()
|
|
local isShared = true
|
|
for indexVectorIndex=1 to indeces.count do
|
|
(
|
|
local indexVector = indeces[indexVectorIndex]
|
|
local sharedvertFaceIndex = RsTestFaceForVertIndex indexVector meshVertIndex
|
|
append meshVertIndeces sharedvertFaceIndex
|
|
if 0 == sharedvertFaceIndex then
|
|
isShared = false
|
|
)
|
|
-- We found the shared index in the faces
|
|
-- Now take face indeces and get map verteces with those
|
|
if isShared then
|
|
(
|
|
for indexVectorIndex=1 to mapindeces.count do
|
|
(
|
|
local sharedvertindex = meshVertIndeces[indexVectorIndex]
|
|
local index = mapindeces[indexVectorIndex][sharedvertindex]
|
|
local vertValue = meshop.getMapVert theMesh theChannel index
|
|
averagedValue = averagedValue + vertValue
|
|
)
|
|
averagedValue /= mapindeces.count
|
|
exit
|
|
)
|
|
)
|
|
return averagedValue
|
|
) |