  AC3D Forums How are AC3D Normal Calculations done?
 User Name Remember Me? Password
 Register FAQ Members List Calendar Search Today's Posts Mark Forums Read

 Thread Tools Display Modes 29th August 2005, 12:23 PM #1 Gary E Sanders Junior Member Member   Join Date: Nov 2003 Posts: 12 How are AC3D Normal Calculations done? I'm using ac3d files directly in an OpenGL program. In doing the normal calculations I notice a couple of things. 1) My method is significantly slower than AC3D 2) I smooth over adjacent surfaces that AC3D doesn't. Basically for each surface set to smooth I check for a shared vertex with any other surface in that object, then calculate the average of the surface normals of all smooth surfaces joining at that vertex to get the vertex normal. An illustration of the problem is a box drawn in ac3d and set to smooth surfaces doesn't look any different than the same box with the surfaces set to flat when viewed in AC3D. Using the normal calculation methodology above it looks like a poor sphere. What I would like to do is duplicate the surface normal calculation done in ac3d ( I know I can export normals, but I want to use the .ac file directly) Perhaps someone, (Andy?) can give a hint on determining which surfaces need to be included in the vertex normal calculation. thanks ges   29th August 2005, 01:47 PM #2 Dennis Senior Member Professional user   Join Date: Jul 2003 Posts: 899 I believe AC3D does vertex smooth using all shared surfaces of a vertex. You won't see the smoothing on a cube, however, because of the crease angle - you'll have to open the cube's object properties and push the Crease angle above 90 to see vertex smoothing in action. Sounds like your base calculation is fine, you'll just have to account for the surface angle. Also, you won't be able to get away with a single vertex normal where you have mixed smooth/flat angles due to crease (i.e., the vertices at the edge of a cylinder where the top is flat-shaded and the sides are smooth). Good luck Dennis   29th August 2005, 03:06 PM #3 Gary E Sanders Junior Member Member   Join Date: Nov 2003 Posts: 12 I guess I was unfamiliar with the crease angle. I took your advice on the cube properties and that is indeed what I see in my OpenGL code. Let's see if I understand the concept. If the angle between an adjacent surface and the surface for which I am calculating normals is greater than the crease angle I ignore that surface when calculating the per vertex normal. That makes sense, but, this adds another calculation in the loop for normals. I suppose I have a code optimisation problem, its at least an order of magnitude slower than AC3D for an object with 20000 verticies. I was certainly hoping there was a magic pill that would solve my problem. thanks ges   29th August 2005, 03:32 PM #4 Andy Administrator Professional user   Join Date: Jun 2003 Posts: 4,366 You have the right concept. Here's AC3D's internal code that calculates the normals. Code: ``` // get the crease angle in radians float rad_angle = cos(ob->crease_angle * M_PI / 180.0f); ... { // vertex index will hold a list of each surface that references the vertex // first, clear the lists for (List *p = ob->pointlist; p != NULL; p = p->next) { Vertex *v = (Vertex *)p->data; vertex_set_index(v, NULL); } // for each sv, add the surface to the list of surfaces in each vertex for (List *spp = ob->surfacelist; spp != NULL; spp = spp->next) { Surface *s = (Surface *)spp->data; for (List *svp = s->vertlist; svp != NULL; svp = svp->next) { SVertex *sv = (SVertex *)svp->data; list_add_item_head((List **)&(sv->v->index), s); } } for (List *sp = ob->surfacelist; sp != NULL; sp = sp->next) { Surface *s = (Surface *)sp->data; for (List *svp = s->vertlist; svp != NULL; svp = svp->next) { SVertex *sv = (SVertex *)svp->data; sv->normal = s->normal; if ((vertex_get_index(sv->v) == 0)) { continue; // next please } // so, surface is shaded // fl is list of faces that refer to this vertex List *fl = (List *)vertex_get_index(sv->v); for (List *flp = fl; flp != NULL; flp = flp->next) { Surface *os = (Surface *)flp->data; // ignore if the same surface if (s != os) { // even if the surface is flat, we still calculate the normals // the shading may change and this saves recalulating normals again // calc dot product of this surface plus attached float dot = (DOTPRODUCT(&s->normal, &os->normal)); if (dot > rad_angle) { ADDPOINTS(&os->normal, &sv->normal); } } } normalize_point(&sv->normal); } } for (List *vp = ob->pointlist; vp != NULL; vp = vp->next) { Vertex *v = (Vertex *)vp->data; list_free((List **)&vertex_get_index(v)); } }``` Notes: 1) that the vertex_index stuff is internal and you'll need to use another way of storing the vertex info. 2) The surface flag for shading is used when drawing the model - if a surface is 'smooth', the vertex normals are used. If a surface is 'flat', the surface-normal is used for each vertex. 3) the above code calculates the all normals in an object (not just those changed recently). Some bits of internal code have been removed but I've hopefully left the important stuff. If the crease angle is 0 or 180, you can optimize a bit.   29th August 2005, 04:50 PM #5 Gary E Sanders Junior Member Member   Join Date: Nov 2003 Posts: 12 Thanks Andy! You are without a doubt the most responsive code developer I've ever dealt with. Thanks again. ges   30th August 2005, 10:14 AM #6 Gary E Sanders Junior Member Member   Join Date: Nov 2003 Posts: 12 Just a follow up. Thanks Andy, the code snippit above did provide the speedup I was looking for. I implemented the prefiltering of surfaces referencing each vertex using the STL as a vector of lists which is populated as I read in the file. This step is so obvious in retrospect I'm ashamed I didn't think of it. Thanks again. ges  Thread Tools Show Printable Version Email this Page Display Modes Linear Mode Switch to Hybrid Mode Switch to Threaded Mode Posting Rules You may not post new threads You may not post replies You may not post attachments You may not edit your posts BB code is On Smilies are On [IMG] code is On HTML code is Off Forum Rules

All times are GMT -4. The time now is 01:50 PM.

 Archive - Top

AC3D Forum (C) Inivis Limited 2020