need help with automatic normal calculation

  • Follow


Hi,
I wrote normal calculator for IndexTriangleFanStrip, but it calculates
partially wrong normals, can anyone help me with that ?

    public static Vector3f[] computeNormals(Point3f[] coords, int[]
coordIndices, int[] stripCounts) {
        Vector3f[] normals = new Vector3f[coords.length];
        for (int i = 0; i < normals.length; ++i) {
            normals[i] = new Vector3f();
        }
        Vector3f[] coordVs = new Vector3f[coords.length];
        for (int i = 0; i < coordVs.length; ++i) {
            coordVs[i] = new Vector3f(coords[i]);
        }

        int stripStart = 0;
        for (int i = 0; i < stripCounts.length; ++i) {
            Vector3f x0 = coordVs[coordIndices[stripStart]];
            for (int j = 2; j < stripCounts[i]; ++j) {
                Vector3f x1 = coordVs[coordIndices[stripStart + j]];
                Vector3f x2 = coordVs[coordIndices[stripStart + j - 1]];
                Vector3f d1 = new Vector3f();
                Vector3f d2 = new Vector3f();
                Vector3f cp = new Vector3f();
                d1.sub(x1, x0);
                d2.sub(x2, x0);
                cp.cross(d1, d2);
                normals[coordIndices[stripStart]].add(cp);
                normals[coordIndices[stripStart + j]].add(cp);
                normals[coordIndices[stripStart + j - 1]].add(cp);
            }
            stripStart += stripCounts[i];
        }

        for (int i = 0; i < normals.length; ++i) {
            normals[i].normalize();
        }

        return normals;
    }


Best Wishes
Thorsten
0
Reply Thorsten 6/24/2009 3:00:50 PM

"Thorsten Kiefer" <cylinder@news.cnntp.org> wrote in message 
news:4a423fa2$0$29140$6e1ede2f@read.cnntp.org...
> Hi,
> I wrote normal calculator for IndexTriangleFanStrip, but it calculates
> partially wrong normals, can anyone help me with that ?
>
> public static Vector3f[] computeNormals(Point3f[] coords, int[]
> coordIndices, int[] stripCounts) {
> Vector3f[] normals = new Vector3f[coords.length];
> for (int i = 0; i < normals.length; ++i) {
> normals[i] = new Vector3f();
> }
> Vector3f[] coordVs = new Vector3f[coords.length];
> for (int i = 0; i < coordVs.length; ++i) {
> coordVs[i] = new Vector3f(coords[i]);
> }
>
> int stripStart = 0;
> for (int i = 0; i < stripCounts.length; ++i) {
> Vector3f x0 = coordVs[coordIndices[stripStart]];
> for (int j = 2; j < stripCounts[i]; ++j) {
> Vector3f x1 = coordVs[coordIndices[stripStart + j]];
> Vector3f x2 = coordVs[coordIndices[stripStart + j - 1]];
> Vector3f d1 = new Vector3f();
> Vector3f d2 = new Vector3f();
> Vector3f cp = new Vector3f();
> d1.sub(x1, x0);
> d2.sub(x2, x0);
> cp.cross(d1, d2);
> normals[coordIndices[stripStart]].add(cp);
> normals[coordIndices[stripStart + j]].add(cp);
> normals[coordIndices[stripStart + j - 1]].add(cp);
> }
> stripStart += stripCounts[i];
> }
>
> for (int i = 0; i < normals.length; ++i) {
> normals[i].normalize();
> }
>
> return normals;
> }
>
>
> Best Wishes
> Thorsten


and what's wrong with the normals?  Are the triangles all "wound" in the 
same direction ?

jbw 


0
Reply jbwest 6/25/2009 12:53:51 AM


jbwest wrote:

> 
> "Thorsten Kiefer" <cylinder@news.cnntp.org> wrote in message
> news:4a423fa2$0$29140$6e1ede2f@read.cnntp.org...
>> Hi,
>> I wrote normal calculator for IndexTriangleFanStrip, but it calculates
>> partially wrong normals, can anyone help me with that ?
>>
>> public static Vector3f[] computeNormals(Point3f[] coords, int[]
>> coordIndices, int[] stripCounts) {
>> Vector3f[] normals = new Vector3f[coords.length];
>> for (int i = 0; i < normals.length; ++i) {
>> normals[i] = new Vector3f();
>> }
>> Vector3f[] coordVs = new Vector3f[coords.length];
>> for (int i = 0; i < coordVs.length; ++i) {
>> coordVs[i] = new Vector3f(coords[i]);
>> }
>>
>> int stripStart = 0;
>> for (int i = 0; i < stripCounts.length; ++i) {
>> Vector3f x0 = coordVs[coordIndices[stripStart]];
>> for (int j = 2; j < stripCounts[i]; ++j) {
>> Vector3f x1 = coordVs[coordIndices[stripStart + j]];
>> Vector3f x2 = coordVs[coordIndices[stripStart + j - 1]];
>> Vector3f d1 = new Vector3f();
>> Vector3f d2 = new Vector3f();
>> Vector3f cp = new Vector3f();
>> d1.sub(x1, x0);
>> d2.sub(x2, x0);
>> cp.cross(d1, d2);
>> normals[coordIndices[stripStart]].add(cp);
>> normals[coordIndices[stripStart + j]].add(cp);
>> normals[coordIndices[stripStart + j - 1]].add(cp);
>> }
>> stripStart += stripCounts[i];
>> }
>>
>> for (int i = 0; i < normals.length; ++i) {
>> normals[i].normalize();
>> }
>>
>> return normals;
>> }
>>
>>
>> Best Wishes
>> Thorsten
> 
> 
> and what's wrong with the normals?  Are the triangles all "wound" in the
> same direction ?
> 
> jbw

I read the triangles form an x3d file, and there the value of "direction"
is "ccw". But I guess I must do some manual investigation. I doubt that
the triangles are all wound in the same direction. But does my algo seem
ok so far ??

tk

0
Reply Thorsten 6/25/2009 8:50:08 AM

Thorsten Kiefer wrote:

> jbwest wrote:
> 
>> 
>> "Thorsten Kiefer" <cylinder@news.cnntp.org> wrote in message
>> news:4a423fa2$0$29140$6e1ede2f@read.cnntp.org...
>>> Hi,
>>> I wrote normal calculator for IndexTriangleFanStrip, but it calculates
>>> partially wrong normals, can anyone help me with that ?
>>>
>>> public static Vector3f[] computeNormals(Point3f[] coords, int[]
>>> coordIndices, int[] stripCounts) {
>>> Vector3f[] normals = new Vector3f[coords.length];
>>> for (int i = 0; i < normals.length; ++i) {
>>> normals[i] = new Vector3f();
>>> }
>>> Vector3f[] coordVs = new Vector3f[coords.length];
>>> for (int i = 0; i < coordVs.length; ++i) {
>>> coordVs[i] = new Vector3f(coords[i]);
>>> }
>>>
>>> int stripStart = 0;
>>> for (int i = 0; i < stripCounts.length; ++i) {
>>> Vector3f x0 = coordVs[coordIndices[stripStart]];
>>> for (int j = 2; j < stripCounts[i]; ++j) {
>>> Vector3f x1 = coordVs[coordIndices[stripStart + j]];
>>> Vector3f x2 = coordVs[coordIndices[stripStart + j - 1]];
>>> Vector3f d1 = new Vector3f();
>>> Vector3f d2 = new Vector3f();
>>> Vector3f cp = new Vector3f();
>>> d1.sub(x1, x0);
>>> d2.sub(x2, x0);
>>> cp.cross(d1, d2);
>>> normals[coordIndices[stripStart]].add(cp);
>>> normals[coordIndices[stripStart + j]].add(cp);
>>> normals[coordIndices[stripStart + j - 1]].add(cp);
>>> }
>>> stripStart += stripCounts[i];
>>> }
>>>
>>> for (int i = 0; i < normals.length; ++i) {
>>> normals[i].normalize();
>>> }
>>>
>>> return normals;
>>> }
>>>
>>>
>>> Best Wishes
>>> Thorsten
>> 
>> 
>> and what's wrong with the normals?  Are the triangles all "wound" in the
>> same direction ?
>> 
>> jbw
> 
> I read the triangles form an x3d file, and there the value of "direction"
> is "ccw". But I guess I must do some manual investigation. I doubt that
> the triangles are all wound in the same direction. But does my algo seem
> ok so far ??
> 
> tk

OK I think i found the problem, I'm confused.
In an IndexedTriangleFanStrip are the normals supplied per Vertex
or per Index ? e.g a cube has 8 Vertices, but 24 indices with 4 indices per
Triangle Fan.
Now do I have to compute 8 Normals or 24 ???

tk

0
Reply Thorsten 6/25/2009 12:43:10 PM

Hi Thorsten,

> OK I think i found the problem, I'm confused.
> In an IndexedTriangleFanStrip are the normals supplied per Vertex
> or per Index ? e.g a cube has 8 Vertices, but 24 indices with 4 indices per
> Triangle Fan.
> Now do I have to compute 8 Normals or 24 ???

If you want a smooth surfce, an interpolation of the normals for each
face, you probably want to compute 8 normals and use the same normal
for a vertex in each of it's faces. You can compute 24, a different
normal for each of the faces a vertex is in, when you are looking for
hard edges. So just like rendering a cube or piramid.

Your indices should reflect your choise. So if you are depending the
choice on your input, not the desired visual output, this post is not
much of a help, dough.

Regards, Tom
0
Reply Tom 6/25/2009 1:31:38 PM

Tom Burger wrote:

> Hi Thorsten,
> 
>> OK I think i found the problem, I'm confused.
>> In an IndexedTriangleFanStrip are the normals supplied per Vertex
>> or per Index ? e.g a cube has 8 Vertices, but 24 indices with 4 indices
>> per Triangle Fan.
>> Now do I have to compute 8 Normals or 24 ???
> 
> If you want a smooth surfce, an interpolation of the normals for each
> face, you probably want to compute 8 normals and use the same normal
> for a vertex in each of it's faces. You can compute 24, a different
> normal for each of the faces a vertex is in, when you are looking for
> hard edges. So just like rendering a cube or piramid.
> 
> Your indices should reflect your choise. So if you are depending the
> choice on your input, not the desired visual output, this post is not
> much of a help, dough.
> 
> Regards, Tom

 Hi, 
thanks, your post reflects what I found out a few minutes ago.
One can have arbitrarily many normals. It's just important to
connect the right normal to the right vertex index. In deed I use
smooth normals, so I just compute as many normals as there are
vertices. My first mistake was that I didn't normalize the
cross product before adding, which lead to useless normal
weighting (do you know what i mean ?). My second mistake
was that I didn't connect the right vertex index to the right
normal index. I fixed this, and now it works fine.
Are you interested in a X3D loader for Java, which supports http ?
I wrote a pretty primitive one (no textures supported).

Regards
Thorsten

0
Reply Thorsten 6/25/2009 2:22:31 PM

On Jun 25, 2:43=A0pm, Thorsten Kiefer <cylin...@news.cnntp.org> wrote:
>
> OK I think i found the problem, I'm confused.
> In an IndexedTriangleFanStrip are the normals supplied per Vertex
> or per Index ? e.g a cube has 8 Vertices, but 24 indices with 4 indices p=
er
> Triangle Fan.
> Now do I have to compute 8 Normals or 24 ???
>

You have to compute 8.


But... a "vertex" in OpenGL is a combination of every value
needed at that position. There's 24 different combinations of
position+normal in a cube so you have to send 24 vertices,
one for each or those combinations.

--
<\___/>
/ O O \
\_____/  FTB.

http://www.topaz3d.com/  - New 3D editor for real time simulation
0
Reply fungus 6/25/2009 4:47:49 PM

On Jun 25, 5:22=A0pm, Thorsten Kiefer <cylin...@news.cnntp.org> wrote:
> Tom Burger wrote:
> > Hi Thorsten,
>
> >> OK I think i found the problem, I'm confused.
> >> In an IndexedTriangleFanStrip are the normals supplied per Vertex
> >> or per Index ? e.g a cube has 8 Vertices, but 24 indices with 4 indice=
s
> >> per Triangle Fan.
> >> Now do I have to compute 8 Normals or 24 ???
>
> > If you want a smooth surfce, an interpolation of the normals for each
> > face, you probably want to compute 8 normals and use the same normal
> > for a vertex in each of it's faces. You can compute 24, a different
> > normal for each of the faces a vertex is in, when you are looking for
> > hard edges. So just like rendering a cube or piramid.
>
> > Your indices should reflect your choise. So if you are depending the
> > choice on your input, not the desired visual output, this post is not
> > much of a help, dough.
>
> > Regards, Tom
>
> =A0Hi,
> thanks, your post reflects what I found out a few minutes ago.
> One can have arbitrarily many normals. It's just important to
> connect the right normal to the right vertex index. In deed I use
> smooth normals, so I just compute as many normals as there are
> vertices. My first mistake was that I didn't normalize the
> cross product before adding, which lead to useless normal
> weighting (do you know what i mean ?). My second mistake
> was that I didn't connect the right vertex index to the right
> normal index. I fixed this, and now it works fine.
> Are you interested in a X3D loader for Java, which supports http ?
> I wrote a pretty primitive one (no textures supported).
>
> Regards
> Thorsten- Hide quoted text -
>
> - Show quoted text -

Position and vertex are not the same thing. Position is just one
attribute of a vertex. Many modeling programs call position "vertex",
that causes confusion and was the root cause for your problem.

This thing pops up way too often, OGL FAQ would be in order here.>B)
0
Reply hanukas 6/26/2009 6:39:02 AM

On Jun 25, 5:22=A0pm, Thorsten Kiefer <cylin...@news.cnntp.org> wrote:
> Tom Burger wrote:
> > Hi Thorsten,
>
> >> OK I think i found the problem, I'm confused.
> >> In an IndexedTriangleFanStrip are the normals supplied per Vertex
> >> or per Index ? e.g a cube has 8 Vertices, but 24 indices with 4 indice=
s
> >> per Triangle Fan.
> >> Now do I have to compute 8 Normals or 24 ???
>
> > If you want a smooth surfce, an interpolation of the normals for each
> > face, you probably want to compute 8 normals and use the same normal
> > for a vertex in each of it's faces. You can compute 24, a different
> > normal for each of the faces a vertex is in, when you are looking for
> > hard edges. So just like rendering a cube or piramid.
>
> > Your indices should reflect your choise. So if you are depending the
> > choice on your input, not the desired visual output, this post is not
> > much of a help, dough.
>
> > Regards, Tom
>
> =A0Hi,
> thanks, your post reflects what I found out a few minutes ago.
> One can have arbitrarily many normals. It's just important to
> connect the right normal to the right vertex index. In deed I use
> smooth normals, so I just compute as many normals as there are
> vertices. My first mistake was that I didn't normalize the
> cross product before adding, which lead to useless normal
> weighting (do you know what i mean ?). My second mistake
> was that I didn't connect the right vertex index to the right
> normal index. I fixed this, and now it works fine.
> Are you interested in a X3D loader for Java, which supports http ?
> I wrote a pretty primitive one (no textures supported).

You need to think this thing from another point of view. Think of a
triangle. Triangles have three vertices. Each vertex has a position,
and a normal.

Now imagine this triangle in your mind. Three positions and each
position has a normal vector. This image should be CLEAR in your mind.
This is what the OpenGL uses for rendering.

You have more triangles. Each have their own positions and normal
vectors. That's nice, everything is good. If you have a mesh with
continuous surfaces where edges between triangles are shared, this
means that ideally the positions are same for the edge endpoints
(otherwise you will be cracks and discontinuity between the edges when
drawing).

OK, great, so some positions are same. Some of the normal vectors
might be same for the same position, that's COOL, this means you can
use one vertex instead of many to make the data more compact. This is
purely optimization.

If you got a position shared by two or more triangles, what normals
you want there depends on what you want. If you want smooth edge, you
can have same normal vector for all the points in the same coordinate.
If you want a hard edge, you have different normal vectors for all the
points in the same coordinate.

For a cube, you usually want the hard-edge look. What you want is that
you have 6 faces to a cube, each face having all the vertex normals
pointing to the direction of the face normal.

If you use triangles, not quads, that means you will have two
triagnles per face. Each triangle will have 3 vertices, so you will
have 6 vertices in total. But since two of the vertices are shared
between the two triangles, you only need four unique vertices: one for
each corner of the cube face.

6 faces to a cube, times four vertices per face, yup... 24 vertices.
If you want a cube which looks like shit when rendering, you can have
only 8 vertices .. the point here is that just computing smoothed
normals for a model doesn't go very far.

If you got some nice model, okay, fine, it might look "ok" when you
draw it.. but if you don't have ANY hard edges you're missing a lot of
artistic detail. If you modeling package does have some form of
control for normal computation, you should in one way or other get it
to your final render. I am nor familiar with the fileformat you are
using (probably a good thing for me ;), but the format *might* have
the data organized in a way that the hard edges can be preserved. At
least if the format's author had any clue whatsoever what he was
doing..

If the format is crap, don't let yourself to be fooled by some big
corporation name. Not everyone doing something even in fairly large
and/or famous organizations know what they are doing. You shouldn't be
surprised to learn that sometimes people are just assigned to a task
and they do research on the issue, solve a problem and move on. Often
the research is fairly high quality, but you just cannot know
*everything* essential without making mistakes first.

Knowing and understanding a problem are two different things. You can
learn to know things by reading, but you will understand only when you
been doing mistakes.. you have to work on the topic and make some
mistakes. That's why experience is valuable: it is very high cost
commodity to acquire. Knowledge is cheap, you read a book, few hours,
few days.. that's cheap. Doing 10 years of work is expensive, could
run into millions of USD of cost..!

Probably that format you use is just fine, I am just... sceptical
always until take look myself and wight the pros and cons (no, there
is no perfect file format).

0
Reply hanukas 6/26/2009 6:58:41 AM

8 Replies
201 Views

(page loaded in 0.355 seconds)

Similiar Articles:













7/25/2012 11:21:38 PM


Reply: