Points and normals

I understand the one-normal-per-one-vertex-entry will result in a smooth, rounded appearance. This is why the simple cube example requires 24 vertex entries. Each physical vertex is entered three times in the list with identical spatial co-ordinates, but different normals. Using object.GetNormalCount returns 24 (which is good). On a 12-sided cylinder, it returns 24 (one per vertex, which is also good as it is smooth). On the same cylinder after it is creased, it returns 12, which is one per face, and not what I was expecting.

GenerateNormals might work on the cylinder example (I haven’t had time to try it yet), but from what I can make out of it, I have to enter an angle, and this would be problematic if I had to use this approach on a complex shape with both smooth and hard edges.

You have, however, triggered a few of my gray cells into motion, and I think I can approach this from a slightly different tack. Unfortunately, some Real Work(TM) has popped up and interferes with all things fun, so it may take a few days before I get to try anything. More time for the little gray cells to percolate.

Cheers, and thanks again for your time.

Greetings, fellow 3DCeers. Nice place you have here.

I have been looking at and modifying the andquot;Export DirectXandquot; script to create another export filter. The format I need has a vertex list and a triangle list (plus other things, of course, but not relevant at the moment). Easy enough, but the vertex list I need has up to eight elements per line: the x, y and z co-ords.; the x, y and z normals; and the U and V texture co-ords.

Still easy enough, build the triangle list with GetNormal instead of GetPoint (there may be more normals than points in an object, but there will never be fewer).

My question is, rather than writing some complex code (the last time I did any serious programming was with 6502 assembly!), is it possible to retrieve the x, y and z co-ordinate of a given normal with a simple function that I may have overlooked?

Thanks for any help.


Aha. I think I see. What I missed was this: (from the help file)


Gets the specified normal.


object.GetNormal(Index As Variant,
X As Variant,
Y As Variant,
Z As Variant)

I assume this returns the actual spatial x, y and z coordinates of the normal specified by Index. (Sorry, I’m a real OOP doofus.)

So instead of using the GetPointCount method (which would have been very simple), I have to start with individual faces and work my backwards. Okay, I can do that.

Hmmm, just realized if I wrap a texture around it, I’ll have to add more vertex entries with identical z, y, and z co-ords, x, y and z normals, but different UV, just to complete the wrap.

Okay, thanks again. I have something to work with now. I’ll let you know how I get along with this.


I believe so.

Assuming you have a 3DCObject, one of its faces (a 3DCFace) you can get the index into the 3DCObject’s normals list by using 3DCFace’s GetNormal method. Then you can get the coordinates using this index with the 3DCObject’s GetNormal method.


Okay, I came up with the following routine. It may not be pretty, but it does the job. Mostly.

andnbsp;’get face index
andnbsp; andnbsp;For FaceIndex = 0 to FaceCount -1

andnbsp; andnbsp; andnbsp; andnbsp;’get the face
andnbsp; andnbsp; andnbsp; andnbsp;Set Face = Object.GetFace(FaceIndex)

andnbsp; andnbsp; andnbsp; andnbsp;’get the number of normals in the face
andnbsp; andnbsp; andnbsp; andnbsp;FaceNormalCount = Face.GetNormalCount andnbsp; andnbsp; andnbsp; andnbsp;

andnbsp; andnbsp; andnbsp; andnbsp;’run through the normals
andnbsp; andnbsp; andnbsp; andnbsp;For NormalIndex = 0 To FaceNormalCount – 1

andnbsp; andnbsp; andnbsp; andnbsp; andnbsp; andnbsp;’get the normal and point index
andnbsp; andnbsp; andnbsp; andnbsp; andnbsp; andnbsp;Normal = Face.GetNormal(NormalIndex)
andnbsp; andnbsp; andnbsp; andnbsp; andnbsp; andnbsp;Point = Face.GetPoint(NormalIndex)

andnbsp; andnbsp; andnbsp; andnbsp; andnbsp; andnbsp;’cross-reference point to normal
andnbsp; andnbsp; andnbsp; andnbsp; andnbsp; andnbsp;Vertex (Normal) = Point
andnbsp; andnbsp; andnbsp; andnbsp;Next
andnbsp; andnbsp;Next

andnbsp; andnbsp;’write the vertex list
andnbsp; andnbsp;For NormalIndex = 0 To NormalCount – 1

andnbsp; andnbsp; andnbsp; andnbsp;’get the normal, point andamp; UV
andnbsp; andnbsp; andnbsp; andnbsp;Object.GetNormal NormalIndex, Xn, Yn, Zn
andnbsp; andnbsp; andnbsp; andnbsp;Object.GetPoint Vertex (NormalIndex), X, Y, Z
andnbsp; andnbsp; andnbsp; andnbsp;Object.GetPointTextureCoordinate Vertex (NormalIndex), U, V

andnbsp; andnbsp; andnbsp; andnbsp;FileObject.WriteLine m3DCApp.FormatScientific(X) andamp; andquot; andquot; andamp; m3DCApp.FormatScientific(Y) andamp; andquot; andquot; andamp; m3DCApp.FormatScientific(Z) andamp; andquot; andquot; andamp; m3DCApp.FormatScientific(Xn) andamp; andquot; andquot; andamp; m3DCApp.FormatScientific(Yn) andamp; andquot; andquot; andamp; m3DCApp.FormatScientific(Zn) andamp; andquot; andquot; andamp; CStr(CSng(1+U)) andamp; andquot; andquot; andamp; CStr(CSng(1+V))

andnbsp; andnbsp;Next

However, I get strange and unusable results after performing a crease operation on an object (make hard edges). The number of total points (normals) seems to decrease, and the triangle list gets messed up. Instead of the usual:

0 1 2
0 2 3

I get things like:

0 1 1
2 2 2

Have I missed something obvious again?

I think I’ve figured out what’s going on with the crease operation. If I take a 12-sided cylinder (open-ended for simplicity) and export it, I get 24 points and 24 normals. Good so far.

If I crease it to make 12 flat sides and export it, I get 24 points but only 12 normals instead of the 48 I was expecting.

Rather than adding a normal to each point for each face, it seems 3DC has determined that the face is flat and all points on that face can share the same normal. Would this be correct?

If that’s the case, I’m stumped on how to get around it. Fixing a cylinder would be easy, but how about a more complex shape with a few thousand triangles and a combination of hard and soft edges?

Well, my brain is starting to hurt, so I’m going to spend some time building something instead of trying to figure out code.



Formats that require one normal per vertex are incapable of showing creases. So, you would want to move the Crease operation’s slider all the way to the andquot;leftandquot;. I forget off hand what this translates to in parameters for the andquot;GenerateNormalsandquot; method.

If GenerateNormals doesn’t work, you could find all of the faces that use a particular vertex and average their vertex normals. But, GenerateNormals should work. Remember though that the normals may NOT be in the same order as the vertices even if there are the same number. So, you may have to match them up by running through the faces to determine the normals used by each vertex. I can’t say with 100% certainty.

PS There is a way to show creases with these formats, but it requires splitting vertices along the crease lines.

I assume that your target format only permits one normal per vertex?

If so, you may be able to use the andquot;generatenormalsandquot; method with a large crease angle to re-generate normals to ensure that you get only one normal per vertex. It think a small crease angle should do it (or is it a large crease angle?).


Yes, target format has xyz spatial co-ordinates, xyz normals and UV co-ordinates all on one line. So a simple cube would have 24 lines of vertex data and 12 lines of triangle data. A simple cube does export as expected.

A smooth open-ended, 12-sided cylinder would have 24 lines of vertex data (one normal per vertex, pointing away from the axis). This also exports as expected.

I tried using the crease operation in 3DC (just experimenting with basic shapes to test the code) to make it flat sided. Instead of getting two normals per vertex, I get one normal per face. Instead of the 48 normals I was expecting, I only get 12.

I confess, at this point I have only tried the crease operation by cranking the slider all the way to the right. I will experiment with less severe settings, but enough to make flat sides. Maybe that will make a difference.

Sorry about the code format, I will strive to be more dilligent in my posting etiquette in the future. If you like, I would be more than happy to email you the entire script if you like, though it is mostly just modified bits and pieces of the andquot;Export DirectXandquot; script.



Just make the GenerateNormals angle very large (]pi radians) and it should work.


You must be logged in to reply in this thread.