PDA

View Full Version : Averaging vertex normals (by smoothing group)


PpHammer
12-13-2006, 08:47 PM
Hi guys,

Still trying to get around to learn some max scripting in my spare time.
I am working on a "exporter"-like script. It works decently at the moment, but there are still some issues I'd like to solve. At the moment I am kind of stuck and perhaps someone can help me.

To cut a long story short; at one point in my script all vertices of a single object are broken. Although this doesn't modify the smoothing groups, all vertices are assigned a "general" normal. This results in a flat-shaded looking object. I would like to average those normals, just like it is possible with the edit normals modifier. And preferably even based upon smoothing group. It doesn't need to be 100% perfect. So for example I select all faces with smoothing group 1, use the edit normal modifier to average these vertexnormals, select all faces of smoothing group 2 etc. Only automated in a nice way :)

One of the issues I encountered is that I can't assign the edit normals modifier to a specificly selected amount of faces. It is all or nothing, it seems. Is it possible to select the faces of SG 1 in edit poly, put those in a list, add the edit normals modifier and use the list to select the faces and then average the normals? Is this a valid way to go or are there any easier/better solutions.

I hope I made myself a bit clear in the above. Feel free to ask anything if I wasn't clear enough. I am absolutely no advanced max scripter so I am kind of confused on how to continue. Any tips?

Thanx in advance!
Pieter

HalfVector
12-13-2006, 11:05 PM
Hi.

This function should calculate the averaged vertex normal taking into account the smoothing groups.

fn getVertexNormal polyObj faceIndex vertexNum = (

local normal = [0,0,0]

local faceSG = polyOp.getFaceSmoothGroup polyObj faceIndex

if faceSG == 0 then (
normal = polyOp.getFaceNormal polyObj faceIndex
)
else (
local indices = polyOp.getFaceVerts polyObj faceIndex
local vertexIndex = indices[vertexNum]

local sharedFaces = polyOp.getFacesUsingVert polyObj vertexIndex

for sharedFace in sharedFaces do (
local sharedFaceSG = polyOp.getFaceSmoothGroup polyObj sharedFace

if (bit.and sharedFaceSG faceSG) != 0 do
normal += (polyOp.getFaceNormal polyObj sharedFace)
)
)

normalize normal
)

Now, if you want to gather all vertex normals (for the selected object that should be an editable poly):

for f = 1 to $.numFaces do (
local face = polyOp.getFaceVerts $ f

for v = 1 to face.count do (
local normal = getVertexNormal $ f v
format "Normal for vertex % / face % = %\n" v f normal
)
)

I think it works fine!...

PpHammer
12-19-2006, 08:47 AM
Hi Halfvector

Thanks for your reply and sorry for my slow response.
I took a spin with your code, but it doesn't really seem to do what I want. I think I wasn't clear enough in my initial post. If I got things right; your code averages vertexnormals PER face based upon smoothing group. I am looking for a solution to average all vertexnormals of vertices that shares the exact same worldposition. When a vertex is broken; N amounts of new vertices are created. Those vertices all get a new vertexnormal, but are on the exact same position. I thought using smoothing groups for selections and the average function of the "edit normals" modifier would be a way to go.
I did learn some tricks from your code that got me a bit further! Thanks!

Is there another solution or option?

Pieter

CGTalk Moderation
12-19-2006, 08:47 AM
This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.