258 lines
9.6 KiB
Plaintext
Executable File
258 lines
9.6 KiB
Plaintext
Executable File
--SeamFixer.ms
|
|
filein (RsConfigGetWildWestDir() + "script/3dsMax/_config_files/Wildwest_header.ms") --wildwest header
|
|
filein (RsConfigGetWildWestDir() + "script/3dsMax/_common_functions/RSL_dotNetUIOps.ms") --RS_dotNetPreset structure
|
|
filein (RsConfigGetWildWestDir() + "script/3dsMax/_common_functions/COVERT.ms") --coincident vertex functions
|
|
|
|
RsCollectToolUsageData (getThisScriptFilename())
|
|
|
|
global SeamFixer
|
|
|
|
struct NormalData
|
|
(
|
|
vertID,
|
|
normals = #(),
|
|
vectors = #()
|
|
)
|
|
|
|
struct ObjectNormalSettings
|
|
(
|
|
obj,
|
|
normalSettingList = #()
|
|
)
|
|
|
|
struct NormalSetting
|
|
(
|
|
vector,
|
|
vertList = #{}
|
|
)
|
|
|
|
struct SeamFixerStruct
|
|
(
|
|
Form,
|
|
ToolTip,
|
|
InfoPanel,
|
|
PositionThreshold,
|
|
AngleThreshold,
|
|
ProgBar,
|
|
ProgressValue = 0,
|
|
SeamFixerButton,
|
|
PreserveCheckBox,
|
|
IniFilePath = (RsConfigGetWildWestDir() + "script/3dsMax/_config_files/RSL_Tools.ini"),
|
|
NormalList = #(),
|
|
|
|
------------------------------------------------------------------------------------------------------------------------------------------
|
|
--GENERAL FUNCTIONS
|
|
------------------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
fn FixSeam s e =
|
|
(
|
|
local infoString = ""
|
|
local meshObjects = for this in selection where superClassOf this == GeometryClass collect this
|
|
local originalSelection = selection as array
|
|
|
|
if (meshObjects.Count > 1) then
|
|
(
|
|
local thistime = timestamp()
|
|
local objectProcessingList = #() --array of values to set normals to on a per object level
|
|
local editNorms = Edit_Normals() --edit normals modifier
|
|
rollout temprollout "Finding matching vertices"
|
|
(
|
|
label myLabel "Processing"
|
|
)
|
|
|
|
--find the border vertices
|
|
theNewFloater = createDialog temprollout 200 30
|
|
COVERT = COVERT_List tolerance:(SeamFixer.PositionThreshold.Text as float)
|
|
COVERT.InitCOVERT_List meshObjects
|
|
destroyDialog temprollout
|
|
meshObjects = COVERT.objList --reduced set of objects that have coincident vertices
|
|
infoString = "Coincident vertices found on " + meshObjects.count as string + " objects."
|
|
addModifier meshObjects editNorms
|
|
|
|
max modify mode --neccessary or the modifier operations have no effect
|
|
select meshObjects --required to refresh the scene
|
|
|
|
for match in COVERT.matchList do
|
|
(
|
|
--get the average vector
|
|
local vector = [0,0,0]
|
|
|
|
for object in match.objectList do
|
|
(
|
|
for vert in object.vertList do
|
|
(
|
|
local normal = RSNorm_GetVertexNormal object.obj vert
|
|
vector += normal
|
|
)
|
|
)
|
|
|
|
local averageVector = (normalize vector)
|
|
|
|
--set the vectors to the average value
|
|
for object in match.objectList do
|
|
(
|
|
local normalIDs = #{}
|
|
|
|
editNorms.ConvertVertexSelection object.vertList normalIDs node:object.obj
|
|
|
|
--adjust the averageVector to account for objects with rotaton values
|
|
local outputVector = averageVector * (object.obj.rotation as matrix3)
|
|
|
|
for normalID in normalIDs as array do
|
|
editNorms.SetNormal normalID outputVector node:object.obj
|
|
|
|
--make normals explicit to preserve the normals after stack collapse
|
|
editNorms.MakeExplicit selection:normalIDs node:object.obj true
|
|
)
|
|
|
|
SeamFixer.ProgressValue += 100.0 / COVERT.matchList.count
|
|
SeamFixer.ProgBar.Value = SeamFixer.ProgressValue as integer
|
|
)
|
|
|
|
if (not SeamFixer.PreserveCheckBox.Checked) then convertToPoly meshObjects
|
|
|
|
infoString = "Normals averaged at " + (COVERT.matchList.count as string) + " locations."
|
|
)
|
|
else
|
|
(
|
|
infoString = "Please select two or more objects for seam matching."
|
|
)
|
|
|
|
SeamFixer.InfoPanel.Text = infoString
|
|
SeamFixer.ProgressValue = 0
|
|
SeamFixer.ProgBar.Value = 0
|
|
|
|
local finalTime = timeStamp() - thisTime
|
|
local timeString = ("Operation took " + (finalTime/1000.0) as string + " seconds")
|
|
|
|
format "%\n" timeString
|
|
select originalSelection
|
|
),
|
|
|
|
------------------------------------------------------------------------------------------------------------------------------------------
|
|
--LOAD/SAVE FUNCTIONS
|
|
------------------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
fn SaveIniFile =
|
|
(
|
|
setINISetting SeamFixer.IniFilePath "SeamFixer" "WinLocX" (SeamFixer.Form.Location.x as string)
|
|
setINISetting SeamFixer.IniFilePath "SeamFixer" "WinLocY" (SeamFixer.Form.Location.y as string)
|
|
setINISetting SeamFixer.IniFilePath "SeamFixer" "WinWidth" (SeamFixer.Form.Width as string)
|
|
setINISetting SeamFixer.IniFilePath "SeamFixer" "WinHeight" (SeamFixer.Form.Height as string)
|
|
setINISetting SeamFixer.IniFilePath "SeamFixer" "PositionThreshold" (SeamFixer.PositionThreshold.Text as string)
|
|
setINISetting SeamFixer.IniFilePath "SeamFixer" "PreserveCheckState" (SeamFixer.PreserveCheckBox.Checked as string)
|
|
|
|
--nb: have to use .Text property for numericUpDown controls because of http://forums.cgsociety.org/archive/index.php/t-763277.html
|
|
--max converts the numeric values to floats, so we have to grab the .Text value instead of .Value
|
|
),
|
|
|
|
fn LoadIniFile =
|
|
(
|
|
--default values
|
|
local WinLocX = 0
|
|
local WinLocY = 40
|
|
local WinWidth = 230
|
|
local WinHeight = 210
|
|
local PThresh = 0.001
|
|
local PreserveCheckState = false
|
|
|
|
try
|
|
(
|
|
WinLocX = getINISetting SeamFixer.IniFilePath "SeamFixer" "WinLocX" as integer
|
|
WinLocY = getINISetting SeamFixer.IniFilePath "SeamFixer" "WinLocY" as integer
|
|
WinWidth = getINISetting SeamFixer.IniFilePath "SeamFixer" "WinWidth" as integer
|
|
WinHeight = getINISetting SeamFixer.IniFilePath "SeamFixer" "WinHeight" as integer
|
|
PThresh = getINISetting SeamFixer.IniFilePath "SeamFixer" "PositionThreshold" as float
|
|
PreserveCheckState = getINISetting SeamFixer.IniFilePath "SeamFixer" "PreserveCheckState" as BooleanClass
|
|
)
|
|
|
|
catch()
|
|
|
|
SeamFixer.Form.Location = dotNetObject "system.drawing.point" WinLocX WinLocY
|
|
SeamFixer.Form.Size = dotNetObject "System.Drawing.Size" WinWidth WinHeight
|
|
SeamFixer.PositionThreshold.Value = PThresh
|
|
SeamFixer.PreserveCheckBox.Checked = PreserveCheckState
|
|
),
|
|
|
|
------------------------------------------------------------------------------------------------------------------------------------------
|
|
--UI
|
|
------------------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
fn CreateUI =
|
|
(
|
|
-- form setup
|
|
Form = dotNetObject "maxCustomControls.maxForm"
|
|
Form.Text = "Seam Fixer"
|
|
Form.StartPosition = (dotNetClass "System.Windows.Forms.FormStartPosition").manual
|
|
Form.Location = dotNetObject "system.drawing.point" 0 80
|
|
Form.MaximumSize = dotNetObject "System.Drawing.Size" 1600 1200
|
|
Form.MinimumSize = dotNetObject "System.Drawing.Size" 230 210
|
|
Form.FormBorderStyle = RS_dotNetPreset.FBS.Sizable
|
|
dotNet.AddEventHandler Form "Load" LoadIniFile
|
|
dotNet.AddEventHandler Form "Closing" SaveIniFile
|
|
|
|
--content
|
|
ToolTip = dotnetobject "ToolTip"
|
|
Table = dotNetObject "TableLayoutPanel"
|
|
Table.Dock = RS_dotNetPreset.DS.Fill
|
|
Table.RowCount = 6
|
|
Table.RowStyles.add (RS_dotNetObject.rowStyleObject "absolute" 40) --banner
|
|
Table.RowStyles.add (RS_dotNetObject.rowStyleObject "absolute" 32) --input table
|
|
Table.RowStyles.add (RS_dotNetObject.rowStyleObject "absolute" 30) --preserve modifier stack
|
|
Table.RowStyles.add (RS_dotNetObject.rowStyleObject "absolute" 30) --SeamFixer button
|
|
Table.RowStyles.add (RS_dotNetObject.rowStyleObject "percent" 100) --infoPanel
|
|
Table.RowStyles.add (RS_dotNetObject.rowStyleObject "absolute" 20) --progress bar
|
|
Table.ColumnCount = 1
|
|
Table.ColumnStyles.add (RS_dotNetObject.columnStyleObject "percent" 100)
|
|
Form.Controls.Add Table
|
|
|
|
RSBannerPanel = dotNetObject "System.Windows.Forms.Panel"
|
|
RSBannerPanel.BorderStyle = (dotnetClass "System.Windows.Forms.BorderStyle").FixedSingle
|
|
RSBannerPanel.Dock = RS_dotNetPreset.DS.Fill
|
|
local banner = makeRsBanner dn_Panel:RSBannerPanel width:395 studio:"london" mail:"andy.davis@rockstarlondon.com" wiki:"Map_Art_Tech"
|
|
banner.setup()
|
|
Table.Controls.Add RSBannerPanel 0 0
|
|
|
|
InputTable = dotNetObject "TableLayoutPanel"
|
|
InputTable.Dock = RS_dotNetPreset.DS.Fill
|
|
InputTable.RowCount = 1
|
|
InputTable.RowStyles.add (RS_dotNetObject.rowStyleObject "percent" 100)
|
|
InputTable.ColumnCount = 2
|
|
InputTable.ColumnStyles.add (RS_dotNetObject.columnStyleObject "absolute" 150)
|
|
InputTable.ColumnStyles.add (RS_dotNetObject.columnStyleObject "percent" 100)
|
|
Table.Controls.Add InputTable 0 1
|
|
|
|
PositionLabel = RS_dotNetUI.InitLabel "Vertex position threshold:" RS_dotNetPreset.TA_Left
|
|
InputTable.Controls.Add PositionLabel 0 0
|
|
|
|
PositionThreshold = RS_dotNetUI.InitNumericUpDown 0 1.0 0.001
|
|
PositionThreshold.Increment = 0.001
|
|
PositionThreshold.DecimalPlaces = 3
|
|
InputTable.Controls.Add PositionThreshold 1 0
|
|
|
|
PreserveCheckBox = RS_dotNetUI.InitCheckBox "Preserve modifier stack"
|
|
Table.Controls.Add PreserveCheckBox 0 2
|
|
|
|
SeamFixerButton = RS_dotNetUI.InitButton "Fix Seam"
|
|
dotNet.AddEventHandler SeamFixerButton "Click" FixSeam
|
|
Table.Controls.Add SeamFixerButton 0 3
|
|
|
|
InfoPanel = RS_dotNetUI.InitLabel "Select two objects for seam fixing." RS_dotNetPreset.TA.MiddleLeft
|
|
Table.Controls.Add InfoPanel 0 4
|
|
|
|
ProgBar = RS_dotNetUI.InitProgressBar()
|
|
Table.Controls.Add ProgBar 0 5
|
|
|
|
--draw form
|
|
Form.ShowModeless()
|
|
Form
|
|
)
|
|
)
|
|
|
|
if SeamFixer != undefined then
|
|
(
|
|
SeamFixer.Form.Close()
|
|
)
|
|
|
|
SeamFixer = SeamFixerStruct()
|
|
SeamFixer.CreateUI() |