Files
gtav-src/tools_ng/dcc/debug/max2011/scripts/rockstar/helpers/extrude.ms
T
2025-09-29 00:52:08 +02:00

465 lines
14 KiB
Plaintext
Executable File

-- Rockstar Extrude Tool
-- Rockstar North
-- 6/12/2005
-- by Luke Openshaw
-- Extrude tool which accommodates for UV mapping of newly created faces
rollout RsExtrudeRoll "Extrude with Auto Texture"
(
--////////////////////////////////////////////////////////////
-- interface
--////////////////////////////////////////////////////////////
hyperlink lnkHelp "Help?" address:"https://devstar.rockstargames.com/wiki/index.php/Modelling_Toolkit#Extrude_with_Auto_Texture" align:#right color:(color 0 0 255) hoverColor:(color 0 0 255) visitedColor:(color 0 0 255)
button btnBeginExtrude "Begin Extrude" enabled:true width:100 pos:[140,15]
button btnEndExtrude "End Extrude" enabled:false width:100 pos:[140,48]
spinner spnU "U Scale" range:[0.0,1.0,0.05] type:#float scale:0.01 width:60 pos:[46,15]
spinner spnV "V Scale" range:[0.0,1.0,0.05] type:#float scale:0.01 width:60 pos:[46,48]
group "Flip Texture Coordinates"
(
button btnFlipU "Flip U" width:100 pos:[28,85]
button btnFlipV "Flip V" width:100 pos:[140,85]
)
global initFaceCount = 0
global classOfObj
global reversed = false
global xAligned = false
global zAligned = false
--////////////////////////////////////////////////////////////
-- methods
--////////////////////////////////////////////////////////////
--------------------------------------------------------------
-- Retrieve the texture IDs for a given face.
--------------------------------------------------------------
fn SimpleCalcTexIndices obj arrFace = (
-- Editable_mesh extruded faces must consist of two faces with
-- three vertices each while Editable_poly extruded faces
-- must consist of one face with four vertices
texVertIndex = #()
if classOfObj == Editable_mesh then (
face1 = getTVFace obj arrFace[1]
face2 = getTVFace obj arrFace[2]
texVertIndex = #(face1.x, face1.y, face1.z, face2.x, face2.y, face2.z)
)
else if classOfObj == Editable_poly then (
texVertIndex = #(((obj.GetMapFaceVertex 1 arrFace 1) + 1), ((obj.GetMapFaceVertex 1 arrFace 2) + 1), ((obj.GetMapFaceVertex 1 arrFace 3) + 1), ((obj.GetMapFaceVertex 1 arrFace 4) + 1))
)
return texVertIndex
)
--------------------------------------------------------------
-- Calculate the orientation of a face
--------------------------------------------------------------
fn CalcOrientation obj arrFace = (
-- Calculate the dot product of the current face's normal
-- and each of the axis.
if classOfObj == Editable_mesh then (
dpZ = dot (getFaceNormal obj arrFace[1]) [0,0,1]
dpX = dot (getFaceNormal obj arrFace[1]) [1,0,0]
dpY = dot (getFaceNormal obj arrFace[1]) [0,1,0]
)
else if classOfObj == Editable_poly then (
dpZ = dot (polyop.getFaceNormal obj arrFace) [0,0,1]
dpX = dot (polyop.getFaceNormal obj arrFace) [1,0,0]
dpY = dot (polyop.getFaceNormal obj arrFace) [0,1,0]
)
-- If the dot product of the face and the z-axis is greater then
-- 0.05 or less than -0.05 then the face is along the the z-axis
if dpZ > 0.05 then (
orientation = -1.0
zAligned = true
)
else if dpZ < -0.05 then (
orientation = 1.0
zAligned = true
)
-- Else if the determine the faces orientation based upon
-- Whether is is x-aligned and the direction it is facing.
else (
if xAligned == false then (
if dpX > 0 and reversed == true then (
orientation = -1.0
return orientation
)
else if dpX > 0 and reversed == false then (
orientation = 1.0
return orientation
)
else if dpX < 0 and reversed == true then (
orientation = 1.0
return orientation
)
else if dpX < 0 and reversed == false then (
orientation = -1.0
return orientation
)
)
else if xAligned == true then (
if dpY > 0 and reversed == true then (
orientation = 1.0
return orientation
)
else if dpY > 0 and reversed == false then (
orientation = -1.0
return orientation
)
else if dpY < 0 and reversed == true then (
orientation = -1.0
return orientation
)
else if dpY < 0 and reversed == false then (
orientation = 1.0
return orientation
)
)
)
return orientation
)
--------------------------------------------------------------
-- The function that moves the two vertices passed to it
--------------------------------------------------------------
fn MoveTexCoords index texVertIndex obj arrFace axis = (
-- Set the two vertex coordinate variables to the vertex position of two of the vertices
-- in the vertex index array passed in.
vertexCoord1 = $.modifiers[#unwrap_uvw].unwrap.getVertexPosition 0 texVertIndex[index]
vertexCoord2 = $.modifiers[#unwrap_uvw].unwrap.getVertexPosition 0 texVertIndex[index + 1]
refPoint = $.modifiers[#unwrap_uvw].unwrap.getVertexPosition 0 texVertIndex[index]
-- Calculate the offset value based on the faces orientation (to determine the direction)
-- and the offset scaling value provided by the user
if zAligned == true then (
offset = (CalcOrientation obj arrFace) * spnU.value
)
else (
offset = (CalcOrientation obj arrFace) * spnV.value
)
-- Update the texture vertex coordinates variable in either the x or y direction depending on
-- orientation. x and y refer to u and v in texture space.
if axis == "x" then (
vertexCoord1.x = refPoint.x + offSet
vertexCoord2.x = refPoint.x + offSet
)
else if axis == "y" then (
vertexCoord1.y = refPoint.y + offSet
vertexCoord2.y = refPoint.y + offSet
)
-- Update the texture coordinates.
$.modifiers[#unwrap_uvw].unwrap.setVertexPosition 0 texVertIndex[index] vertexCoord1
$.modifiers[#unwrap_uvw].unwrap.setVertexPosition 0 texVertIndex[index + 1] vertexCoord2
zAligned = false
)
--------------------------------------------------------------
-- Move the texture coordinates of two of texture vertices
-- in a direction dependant on face orientation
--------------------------------------------------------------
fn CorrectTexCoord texVertIndex obj arrFace = (
modPanel.addModToSelection (Unwrap_UVW ()) ui:on
--
if classOfObj == Editable_Mesh then (
-- If the current face is xAligned run a dot product against
-- the y-axis to determine how the tex-coords are generated.
-- Otherwise run the dot product against the x-axis.
if xAligned == false then (
dpX = dot (getFaceNormal obj arrFace[1]) [1,0,0]
if dpX > -0.5 and dpX < 0.5 then (
MoveTexCoords 4 texVertIndex obj arrFace "y"
)
else (
MoveTexCoords 1 texVertIndex obj arrFace "x"
)
)
else if xAligned == true then (
dpY = dot (getFaceNormal obj arrFace[1]) [0,1,0]
if dpY > -0.5 and dpY < 0.5 then (
MoveTexCoords 4 texVertIndex obj arrFace "y"
)
else (
MoveTexCoords 1 texVertIndex obj arrFace "x"
)
)
)
else if classOfObj == Editable_Poly then (
-- If the current face is xAligned run a dot product against
-- the y-axis to determine how the tex-coords are generated.
-- Otherwise run the dot product against the x-axis.
if xAligned == false then (
dpX = dot (polyOp.getFaceNormal obj arrFace) [1,0,0]
if dpX > -0.5 and dpX < 0.5 then (
MoveTexCoords 3 texVertIndex obj arrFace "y"
)
else (
MoveTexCoords 1 texVertIndex obj arrFace "x"
)
)
else if xAligned == true then (
dpY = dot (polyOp.getFaceNormal obj arrFace) [0,1,0]
if dpY > -0.5 and dpY < 0.5 then (
MoveTexCoords 3 texVertIndex obj arrFace "y"
)
else (
MoveTexCoords 1 texVertIndex obj arrFace "x"
)
)
)
return true
)
--------------------------------------------------------------
-- Load in the necessary variables prior to extrusion and
-- perform some basic validation
--------------------------------------------------------------
fn ExtrudeBegin = (
sel = selection as array
if sel.count < 1 then return false
-- Store the number of faces in the object prior to extrusion
initFaceCount = getNumFaces sel[1]
subObjectLevel = 4
-- Set mode to Extrude
classOfObj = classof sel[1]
if classOfObj == Editable_mesh then (
meshOps.startExtrude sel[1]
)
else if classOfObj == Editable_Poly then (
polyOps.startExtrudeFace sel[1]
)
return true
)
--------------------------------------------------------------
-- After the extrusion, collect the data about the newly
-- created faces and run the texture correction
--------------------------------------------------------------
fn ExtrudeEnd = (
sel = selection as array
if sel.count == 0 then (
messageBox "No object is selected. Bailing out."
return false
)
-- Store the new face count after the extrusion
newFaceCount = getNumFaces sel[1]
-- If there are no new faces, bail out.
if newFaceCount == initFacecount then (
messageBox "No extrusion has occured. Bailing out."
return false
)
arrExtFace = (getFaceSelection sel[1]) as array
-- Calculate the dot products of the extruded face normal with the x and y axis.
if classOfObj == Editable_Mesh then dpY = dot (getFaceNormal sel[1] arrExtFace[1]) [0,1,0]
else if classOfObj == Editable_Poly then dpY = dot (polyOp.getFaceNormal sel[1] arrExtFace[1]) [0,1,0]
if classOfObj == Editable_Mesh then dpX = dot (getFaceNormal sel[1] arrExtFace[1]) [1,0,0]
else if classOfObj == Editable_Poly then dpX = dot (polyOp.getFaceNormal sel[1] arrExtFace[1]) [1,0,0]
-- Determine whether the face is x-aligned and then determine the direction it is facing.
if dpX > -0.5 and dpX < 0.5 then (4
xAligned = false
if dpY < 0 then reversed = true
else reversed = false
)
else (
xAligned = true
if dpX < 0 then reversed = true
else reversed = false
)
faceIndexBegin = initFaceCount+1
bitArrFace = #{faceIndexBegin..newFaceCount}
-- Calculate the number of faces that need to be textured by
-- subtracting the new face count from the face count prior
-- to extrusion
faceCountDif = newFaceCount - initFaceCount
if classOfObj == Editable_Mesh then faceCountDif = faceCountDif / 2
j = faceIndexBegin
texVertIndex = #()
bitArrFace = #{}
arrFace = #()
-- Fo every new face that has been created, calculate the texture indices and
-- correct them depending on their orientation.
for i = 1 to (faceCountDif) do (
if classOfObj == Editable_Mesh then (
bitArrFace = #{j..(j + 1)}
arrFace = [j,(j + 1)]
j = j + 2
)
else if classOfObj == Editable_Poly then (
bitArrFace = #{j}
arrFace = j
j = j + 1
)
subObjectLevel = 4
setfaceselection sel[1] bitArrFace
texVertIndex = SimpleCalcTexIndices sel[1] arrFace
CorrectTexCoord texVertIndex sel[1] arrFace
if classOfObj == Editable_Mesh then convertToMesh sel[1]
else if classOfObj == Editable_Poly then convertToPoly sel[1]
)
return true
)
--------------------------------------------------------------
-- Flip the coordinates of the texture vertices either on the
-- U or V axis
--------------------------------------------------------------
fn Flip orientation arrFace texVertIndex obj = (
modPanel.addModToSelection (Unwrap_UVW ()) ui:on
-- Again because texture vertices are managed differently between a polygon and editable mesh,
-- they need different code.
if classOfObj == Editable_mesh then (
texBitVertIndex = texVertIndex as bitarray
$.modifiers[#unwrap_uvw].unwrap.selectVertices texBitVertIndex
if orientation == 1 then $.modifiers[#unwrap_uvw].mirrorh()
if orientation == 0 then $.modifiers[#unwrap_uvw].mirrorv()
convertToMesh obj
)
else if classOfObj == Editable_poly then (
texBitVertIndex = texVertIndex as bitarray
$.modifiers[#unwrap_uvw].unwrap.selectVertices texBitVertIndex
if orientation == 1 then $.modifiers[#unwrap_uvw].mirrorh()
if orientation == 0 then $.modifiers[#unwrap_uvw].mirrorv()
convertToPoly obj
)
)
--------------------------------------------------------------
-- Loop through all the selected faces and flip the coordinates
-- of the texture vertices
--------------------------------------------------------------
fn FlipPrepare orientation = (
sel = selection as array
if sel.count == 0 then (
messageBox "No object is selected. Bailing out."
return false
)
arrFace = (getFaceSelection sel[1]) as array
faceCount = arrFace.count
if classOfObj == Editable_mesh then faceCount = faceCount / 2
j = 1
for i = 1 to (faceCount) do (
if classOfObj == Editable_mesh then (
arrPairFace = #()
append arrPairFace arrFace[j]
append arrPairFace arrFace[j + 1]
texVertIndex = SimpleCalcTexIndices sel[1] arrPairFace
Flip orientation arrPairFace texVertIndex sel[1]
j = j + 2
)
else if classOfObj == Editable_poly then (
texVertIndex = SimpleCalcTexIndices sel[1] arrFace[i]
Flip orientation arrFace[i] texVertIndex sel[1]
)
)
)
--////////////////////////////////////////////////////////////
-- events
--////////////////////////////////////////////////////////////
on btnBeginExtrude pressed do (
btnBeginExtrude.enabled = false
btnEndExtrude.enabled = true
if ExtrudeBegin() == false then return false
return true
)
on btnEndExtrude pressed do (
btnBeginExtrude.enabled = true
btnEndExtrude.enabled = false
if classOfObj == Editable_mesh then (
if ExtrudeEnd() == false then return false
)
else if classOfObj == Editable_Poly then (
if ExtrudeEnd() == false then return false
)
return false
)
on btnFlipU pressed do (
if FlipPrepare 1 == false then return false
return true
)
on btnFlipV pressed do (
if FlipPrepare 0 == false then return false
return true
)
)