ПрограммированиеПодсказкиГрафика

MAX Script: Разделение 3D модели на элементы по группам нормаль векторов.

Автор:

Здесь представлен скрипт 3D Studio MAX, при помощи которого можно разделить 3D модели на элементы по группам нормалей, также смотрите «MAX Script: Разделение 3D модели на элементы по группам сглаживания».

Как мы знаем в идеале каждый, треугольник который должен быть отрисован должен делить вершину или вершины с другими треугольниками. Но не всегда это возможно, поскольку нормаль, векторы треугольников меняются в разных плоскостях.

Проблема:
Panels With Artifacts | MAX Script: Разделение 3D модели на элементы по группам нормаль векторов.

Решение:
Panels No Artifacts | MAX Script: Разделение 3D модели на элементы по группам нормаль векторов.

Есть два варианта разделение треугольников на элементы, разделять всё треугольники на отдельные элементы, или же разделять по группам нормальев.
В первом случаи множество вершин будет продублировано, во втором варианте некое минимальное количество вершин будет продублировано.

Примечание:
Данный скрипт работает только в режиме "Editable Poly", если применены группы сглаживания они не будут обрабатываться, также важно заметить что "отмена" не будет работать после обработки модели скриптом, так что будьте аккуратны!

/*
Notes:
This script must be used in Editable Poly mode.
After the script is applied there will be no possibility to undo.
*/

fn splitSmoothingGroupsIntoElements tmesh =
(
  if classof tmesh == Editable_Poly do
  (
    local groupIDsUsed = #()
    local faceCount = tmesh.getNumFaces()
    for f = 1 to faceCount  do 
    (
      local groupID  = (polyop.getFaceSmoothGroup tmesh f)
      appendIfUnique groupIDsUsed groupID
    )

    for g = 1 to groupIDsUsed.count do 
    (
      local faceGroup = #()
      for i = 1 to faceCount do
      (
      local polygonGroupID  = (polyop.getFaceSmoothGroup tmesh i) as integer
      if polygonGroupID == (groupIDsUsed[g] as integer) do
      (
        append faceGroup i
      )
      )
      polyop.detachFaces tmesh faceGroup asNode:false
    )
    groupIDsUsed = #()
  )
)  

struct FaceNormalType
(
  normal,
  faces = #()
)

fn compareNormals normal1 normal2=
(
  deltaX = abs(normal1.x - normal2.x);
  deltaY = abs(normal1.y - normal2.y);
  deltaZ = abs(normal1.z - normal2.z);
    
  if deltaX < 0.001 and deltaY < 0.001 and deltaZ < 0.001 then
  (
    return true;
  )
  return false;
)

fn smarpSplitFn =
(
  ClearListener()
  tmesh = selection[1]
  FaceNormalGroups = #()
  
  if classof tmesh == Editable_Poly do
  (
    local faceCount = tmesh.getNumFaces()
    for i = 1 to faceCount  do 
    (
      local groupID  = (polyop.getFaceSmoothGroup tmesh i)
      
      --Here we may add a check if the groupID == 0, that means that the face doesn't belong to any
      --smoothing group and therefore may be splitted, otherwise ignoore
      if groupID == 0 do
      (
        faceNormal = polyop.getFaceNormal tmesh i
      
        --Look for similar normal groups
        foundGroup = false
        for n = 1 to FaceNormalGroups.count do
        (
          if (compareNormals FaceNormalGroups[n].normal faceNormal) == true do
          (
            appendifUnique FaceNormalGroups[n].faces i
            foundGroup = true
          )
        )
        
        --If not found create a new group
        if foundGroup == false do
        (
          faceNormalGrp = FaceNormalType normal:faceNormal faces:#(i)
          append FaceNormalGroups faceNormalGrp
        )
      )
    )  
    
    --Split the faces
    for i = 1 to FaceNormalGroups.count do
    (
      polyop.detachFaces tmesh FaceNormalGroups[i].faces asNode:false
    )  
    
    MessageBox "Done!" title:"Information"
  )  
)

fn dumbSplitFn =
(
  --This function will split all faces into seperate elements
  ClearListener()
  tmesh = selection[1]
  if classof tmesh == Editable_Poly do
  (
    local faceCount = tmesh.getNumFaces()
    for i = 1 to faceCount  do 
    (
      polyop.detachFaces tmesh #((i as integer)) asNode:false
    )    
    MessageBox "Done!" title:"Information"
  )
)

fn splitSmoothGroupsFn =
(
  --This function will split faces into their smoothing groups
  ClearListener()
  tmesh = selection[1]
  if tmesh != undefined do
  (
    splitSmoothingGroupsIntoElements tmesh
    MessageBox "Done!" title:"Information"    
  )
)

rollout eSplitFacesIntoElements "Splitter" width:140 height:100
(
  button 'btn1' "Smart Split" pos:[10,10] width:120 height:25 align:#left \
    tooltip:"Groups faces by their normal vectors and splits into separate elements."
  
  button 'btn2' "Dumb Split" pos:[10,40] width:120 height:25 align:#left \
    tooltip:"Splits all faces into separate unique elements."
  
  button 'btn3' "Split Sm. Groups" pos:[10,70] width:120 height:25 align:#left \
    tooltip:"Splits all faces into separate smoothing groups."
  
  on btn1 pressed do
  (
    smarpSplitFn()
  )
  
  on btn2 pressed do
  (
    dumbSplitFn()
  )
  
  on btn3 pressed do
  (
    splitSmoothGroupsFn()
  )
)
createDialog eSplitFacesIntoElements
script_2 | MAX Script: Разделение 3D модели на элементы по группам нормаль векторов.

#3D Studio MAX, #groups, #MAX Script, #normals, #vectors, #скрипты

10 мая 2020