sketchucation logo sketchucation
    • Login
    ℹ️ Licensed Extensions | FredoBatch, ElevationProfile, FredoSketch, LayOps, MatSim and Pic2Shape will require license from Sept 1st More Info

    [Code] How do you compute weighted vertex normals?

    Scheduled Pinned Locked Moved Developers' Forum
    26 Posts 4 Posters 5.6k Views 4 Watching
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • TIGT Offline
      TIG Moderator
      last edited by

      Well then try perhaps 'weight' by each face's surface area...
      faces = vertex.faces return nil if not faces[0] norm = faces[0].normal norm.length = faces[0].area faces.shift faces.each{|face| fnor = face.normal fnor.length = face.area norm = norm ****+**** fnor } norm.normalize! return norm
      OR get relative angles between the normals and make adjustments ???
      EDIT: typo fixed * >>> + TIG.

      TIG

      1 Reply Last reply Reply Quote 0
      • thomthomT Offline
        thomthom
        last edited by

        That snippet gave me zero length vectors for a vertex with three connected faces at an corner.

        Thomas Thomassen β€” SketchUp Monkey & Coding addict
        List of my plugins and link to the CookieWare fund

        1 Reply Last reply Reply Quote 0
        • Chris FullmerC Offline
          Chris Fullmer
          last edited by

          Wouldn't it have something to do with the angle between the 2 edges of the face at that vertex * that face's normal. Something so that a small sliver of a face - only 5 degrees for example, would get its normal * 5. Then a face with 90 degrees would get its normal weight * 90. Then combine all those normals, and the vector will be greater than 1, so normalize it to scale it back down.

          Would that give an appropriate weight to each face in the overall vertex normal?

          Lately you've been tan, suspicious for the winter.
          All my Plugins I've written

          1 Reply Last reply Reply Quote 0
          • thomthomT Offline
            thomthom
            last edited by

            @chris fullmer said:

            Wouldn't it have something to do with the angle between the 2 edges of the face at that vertex * that face's normal. Something so that a small sliver of a face - only 5 degrees for example, would get its normal * 5. Then a face with 90 degrees would get its normal weight * 90. Then combine all those normals, and the vector will be greater than 1, so normalize it to scale it back down.

            Would that give an appropriate weight to each face in the overall vertex normal?

            What you describe is one of the methods in the links in my OP. The problem is that I don't fully understand how to implement the weighting... 😞

            Thomas Thomassen β€” SketchUp Monkey & Coding addict
            List of my plugins and link to the CookieWare fund

            1 Reply Last reply Reply Quote 0
            • thomthomT Offline
              thomthom
              last edited by

              This appear to work:

              <span class="syntaxdefault"><br />def&nbsp;self</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">vertex_normal</span><span class="syntaxkeyword">(&nbsp;</span><span class="syntaxdefault">vertex&nbsp;</span><span class="syntaxkeyword">)<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="syntaxdefault">faces&nbsp;</span><span class="syntaxkeyword">=&nbsp;</span><span class="syntaxdefault">vertex</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">faces<br />&nbsp;&nbsp;&nbsp;&nbsp;edges&nbsp;</span><span class="syntaxkeyword">=&nbsp;</span><span class="syntaxdefault">vertex</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">edges<br />&nbsp;&nbsp;&nbsp;&nbsp;point&nbsp;</span><span class="syntaxkeyword">=&nbsp;</span><span class="syntaxdefault">vertex</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">position<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="syntaxkeyword">return&nbsp;</span><span class="syntaxdefault">nil&nbsp;</span><span class="syntaxkeyword">if&nbsp;</span><span class="syntaxdefault">faces</span><span class="syntaxkeyword">.empty?<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="syntaxdefault">normal&nbsp;</span><span class="syntaxkeyword">=&nbsp;</span><span class="syntaxdefault">Geom</span><span class="syntaxkeyword">;;</span><span class="syntaxdefault">Vector3d</span><span class="syntaxkeyword">.new(&nbsp;</span><span class="syntaxdefault">0</span><span class="syntaxkeyword">,&nbsp;</span><span class="syntaxdefault">0</span><span class="syntaxkeyword">,&nbsp;</span><span class="syntaxdefault">0&nbsp;</span><span class="syntaxkeyword">)<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="syntaxdefault">until&nbsp;faces</span><span class="syntaxkeyword">.empty?<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="syntaxdefault">face&nbsp;</span><span class="syntaxkeyword">=&nbsp;</span><span class="syntaxdefault">faces</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">shift<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e1</span><span class="syntaxkeyword">,&nbsp;</span><span class="syntaxdefault">e2&nbsp;</span><span class="syntaxkeyword">=&nbsp;</span><span class="syntaxdefault">face</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">edges&nbsp;</span><span class="syntaxkeyword">&&nbsp;</span><span class="syntaxdefault">edges<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pt1&nbsp;</span><span class="syntaxkeyword">=&nbsp;</span><span class="syntaxdefault">e1</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">other_vertex</span><span class="syntaxkeyword">(&nbsp;</span><span class="syntaxdefault">vertex&nbsp;</span><span class="syntaxkeyword">).</span><span class="syntaxdefault">position<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pt2&nbsp;</span><span class="syntaxkeyword">=&nbsp;</span><span class="syntaxdefault">e2</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">other_vertex</span><span class="syntaxkeyword">(&nbsp;</span><span class="syntaxdefault">vertex&nbsp;</span><span class="syntaxkeyword">).</span><span class="syntaxdefault">position<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;v1&nbsp;</span><span class="syntaxkeyword">=&nbsp;</span><span class="syntaxdefault">point</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">vector_to</span><span class="syntaxkeyword">(&nbsp;</span><span class="syntaxdefault">pt1&nbsp;</span><span class="syntaxkeyword">)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="syntaxdefault">v2&nbsp;</span><span class="syntaxkeyword">=&nbsp;</span><span class="syntaxdefault">point</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">vector_to</span><span class="syntaxkeyword">(&nbsp;</span><span class="syntaxdefault">pt2&nbsp;</span><span class="syntaxkeyword">)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="syntaxdefault">angle&nbsp;</span><span class="syntaxkeyword">=&nbsp;</span><span class="syntaxdefault">v1</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">angle_between</span><span class="syntaxkeyword">(&nbsp;</span><span class="syntaxdefault">v2&nbsp;</span><span class="syntaxkeyword">)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="syntaxdefault">face_normal&nbsp;</span><span class="syntaxkeyword">=&nbsp;</span><span class="syntaxdefault">face</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">normal<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;face_normal</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">length&nbsp;</span><span class="syntaxkeyword">=&nbsp;</span><span class="syntaxdefault">angle<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;normal&nbsp;</span><span class="syntaxkeyword">+=&nbsp;</span><span class="syntaxdefault">face_normal<br />&nbsp;&nbsp;&nbsp;&nbsp;end<br />&nbsp;&nbsp;&nbsp;&nbsp;normal</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">normalize</span><span class="syntaxkeyword">!<br />&nbsp;&nbsp;</span><span class="syntaxdefault">end<br /></span>
              

              Thomas Thomassen β€” SketchUp Monkey & Coding addict
              List of my plugins and link to the CookieWare fund

              1 Reply Last reply Reply Quote 0
              • thomthomT Offline
                thomthom
                last edited by

                Though, the linked article seem to also take into account the face area... wonder what importance that has...

                Thomas Thomassen β€” SketchUp Monkey & Coding addict
                List of my plugins and link to the CookieWare fund

                1 Reply Last reply Reply Quote 0
                • thomthomT Offline
                  thomthom
                  last edited by

                  hmm... it must be flawed. if a face is connected to the vertex then vector1.angle_between( vector2 ) won't give the correct angle, as it only return angles between 0 - 180 degrees. Either I need to deal with each triangle in each face, or I calculate the full angle.

                  Thomas Thomassen β€” SketchUp Monkey & Coding addict
                  List of my plugins and link to the CookieWare fund

                  1 Reply Last reply Reply Quote 0
                  • TIGT Offline
                    TIG Moderator
                    last edited by

                    Stupid typo is my code should be norm ****+**** fnor not ' *********'... I've corrected the original - it should now work as expected - weighting vertex-normals dependent on the face's areas!

                    TIG

                    1 Reply Last reply Reply Quote 0
                    • thomthomT Offline
                      thomthom
                      last edited by

                      This seem to account for wide angle corners:

                      <span class="syntaxdefault"><br />&nbsp;&nbsp;def&nbsp;self</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">vertex_normal</span><span class="syntaxkeyword">(&nbsp;</span><span class="syntaxdefault">vertex&nbsp;</span><span class="syntaxkeyword">)<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="syntaxdefault">faces&nbsp;</span><span class="syntaxkeyword">=&nbsp;</span><span class="syntaxdefault">vertex</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">faces<br />&nbsp;&nbsp;&nbsp;&nbsp;edges&nbsp;</span><span class="syntaxkeyword">=&nbsp;</span><span class="syntaxdefault">vertex</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">edges<br />&nbsp;&nbsp;&nbsp;&nbsp;point&nbsp;</span><span class="syntaxkeyword">=&nbsp;</span><span class="syntaxdefault">vertex</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">position<br />&nbsp;&nbsp;&nbsp;&nbsp;normal&nbsp;</span><span class="syntaxkeyword">=&nbsp;</span><span class="syntaxdefault">Geom</span><span class="syntaxkeyword">;;</span><span class="syntaxdefault">Vector3d</span><span class="syntaxkeyword">.new(&nbsp;</span><span class="syntaxdefault">0</span><span class="syntaxkeyword">,&nbsp;</span><span class="syntaxdefault">0</span><span class="syntaxkeyword">,&nbsp;</span><span class="syntaxdefault">0&nbsp;</span><span class="syntaxkeyword">)<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="syntaxdefault">until&nbsp;faces</span><span class="syntaxkeyword">.empty?<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="syntaxdefault">face&nbsp;</span><span class="syntaxkeyword">=&nbsp;</span><span class="syntaxdefault">faces</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">shift<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e1</span><span class="syntaxkeyword">,&nbsp;</span><span class="syntaxdefault">e2&nbsp;</span><span class="syntaxkeyword">=&nbsp;</span><span class="syntaxdefault">face</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">edges&nbsp;</span><span class="syntaxkeyword">&&nbsp;</span><span class="syntaxdefault">edges<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pt1&nbsp;</span><span class="syntaxkeyword">=&nbsp;</span><span class="syntaxdefault">e1</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">other_vertex</span><span class="syntaxkeyword">(&nbsp;</span><span class="syntaxdefault">vertex&nbsp;</span><span class="syntaxkeyword">).</span><span class="syntaxdefault">position<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pt2&nbsp;</span><span class="syntaxkeyword">=&nbsp;</span><span class="syntaxdefault">e2</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">other_vertex</span><span class="syntaxkeyword">(&nbsp;</span><span class="syntaxdefault">vertex&nbsp;</span><span class="syntaxkeyword">).</span><span class="syntaxdefault">position<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;v1&nbsp;</span><span class="syntaxkeyword">=&nbsp;</span><span class="syntaxdefault">point</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">vector_to</span><span class="syntaxkeyword">(&nbsp;</span><span class="syntaxdefault">pt1&nbsp;</span><span class="syntaxkeyword">)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="syntaxdefault">v2&nbsp;</span><span class="syntaxkeyword">=&nbsp;</span><span class="syntaxdefault">point</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">vector_to</span><span class="syntaxkeyword">(&nbsp;</span><span class="syntaxdefault">pt2&nbsp;</span><span class="syntaxkeyword">)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="syntaxdefault">angle&nbsp;</span><span class="syntaxkeyword">=&nbsp;</span><span class="syntaxdefault">self</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">full_angle_between</span><span class="syntaxkeyword">(&nbsp;</span><span class="syntaxdefault">v1</span><span class="syntaxkeyword">,&nbsp;</span><span class="syntaxdefault">v2</span><span class="syntaxkeyword">,&nbsp;</span><span class="syntaxdefault">face</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">normal&nbsp;</span><span class="syntaxkeyword">)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="syntaxdefault">face_normal&nbsp;</span><span class="syntaxkeyword">=&nbsp;</span><span class="syntaxdefault">face</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">normal<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;face_normal</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">length&nbsp;</span><span class="syntaxkeyword">=&nbsp;</span><span class="syntaxdefault">angle<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;normal&nbsp;</span><span class="syntaxkeyword">+=&nbsp;</span><span class="syntaxdefault">face_normal<br />&nbsp;&nbsp;&nbsp;&nbsp;end<br />&nbsp;&nbsp;&nbsp;&nbsp;normal</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">normalize</span><span class="syntaxkeyword">!<br />&nbsp;&nbsp;</span><span class="syntaxdefault">end<br />&nbsp;&nbsp;<br />&nbsp;&nbsp;def&nbsp;self</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">full_angle_between</span><span class="syntaxkeyword">(&nbsp;</span><span class="syntaxdefault">vector1</span><span class="syntaxkeyword">,&nbsp;</span><span class="syntaxdefault">vector2</span><span class="syntaxkeyword">,&nbsp;</span><span class="syntaxdefault">normal&nbsp;</span><span class="syntaxkeyword">)<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="syntaxdefault">cross&nbsp;</span><span class="syntaxkeyword">=&nbsp;</span><span class="syntaxdefault">vector1&nbsp;</span><span class="syntaxkeyword">*&nbsp;</span><span class="syntaxdefault">vector2<br />&nbsp;&nbsp;&nbsp;&nbsp;direction&nbsp;</span><span class="syntaxkeyword">=&nbsp;</span><span class="syntaxdefault">cross&nbsp;</span><span class="syntaxkeyword">%&nbsp;</span><span class="syntaxdefault">normal<br />&nbsp;&nbsp;&nbsp;&nbsp;angle&nbsp;</span><span class="syntaxkeyword">=&nbsp;</span><span class="syntaxdefault">vector1</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">angle_between</span><span class="syntaxkeyword">(&nbsp;</span><span class="syntaxdefault">vector2&nbsp;</span><span class="syntaxkeyword">)<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="syntaxdefault">angle&nbsp;</span><span class="syntaxkeyword">=&nbsp;</span><span class="syntaxdefault">360.degrees&nbsp;</span><span class="syntaxkeyword">-&nbsp;</span><span class="syntaxdefault">angle&nbsp;</span><span class="syntaxkeyword">if&nbsp;</span><span class="syntaxdefault">direction&nbsp;</span><span class="syntaxkeyword">>&nbsp;</span><span class="syntaxdefault">0.0<br />&nbsp;&nbsp;&nbsp;&nbsp;angle<br />&nbsp;&nbsp;end<br /></span>
                      

                      Thomas Thomassen β€” SketchUp Monkey & Coding addict
                      List of my plugins and link to the CookieWare fund

                      1 Reply Last reply Reply Quote 0
                      • thomthomT Offline
                        thomthom
                        last edited by

                        @tig said:

                        Stupid typo is my code should be norm ****+**** fnorm not ' *********'... I've corrected the original - it should now work as expected !!!!

                        I'll revisit your code again. http://www.bytehazard.com/code/vertnorm.html mentions that using the area still makes some faces weigh too much, but that it's not that notable. But since it looks to require less computing that checking the angles then it might be preferable.

                        Thomas Thomassen β€” SketchUp Monkey & Coding addict
                        List of my plugins and link to the CookieWare fund

                        1 Reply Last reply Reply Quote 0
                        • thomthomT Offline
                          thomthom
                          last edited by

                          hm... I added face area to the equations, but that yielded deviating normals depending how I divided the large face.
                          removing the face area appear to yield the exact same result.

                          VertexNormals.png
                          Weighted by angle:

                          1. Vector3d(0.419345, 0.0772543, 0.904534)
                          2. Vector3d(0.419345, 0.0772543, 0.904534)
                          3. Vector3d(0.419345, 0.0772543, 0.904534)

                          Weighted by area * angle:

                          1. Vector3d(0.324298, 0.116468, 0.938758)
                          2. Vector3d(0.706956, 0.253896, 0.660114)
                          3. Vector3d(0.770689, 0.276785, 0.573959)

                          Thomas Thomassen β€” SketchUp Monkey & Coding addict
                          List of my plugins and link to the CookieWare fund

                          1 Reply Last reply Reply Quote 0
                          • thomthomT Offline
                            thomthom
                            last edited by

                            I wonder if the linked article uses the face area because they computer the normals for lighting...

                            Thomas Thomassen β€” SketchUp Monkey & Coding addict
                            List of my plugins and link to the CookieWare fund

                            1 Reply Last reply Reply Quote 0
                            • TIGT Offline
                              TIG Moderator
                              last edited by

                              Several coplanar faces at a vertex are the same as one face of the same area as the bits? So the both area-weight-adjusted vertex-normals will be the same.
                              I think it is more for lighting...

                              TIG

                              1 Reply Last reply Reply Quote 0
                              • thomthomT Offline
                                thomthom
                                last edited by

                                @tig said:

                                Several coplanar faces at a vertex are the same as one face of the same area as the bits? So the both area-weight-adjusted vertex-normals will be the same.

                                But if a vertex is connected to three sides, one large and two small, then using the area would make the normal lean toward the large area, would it not?

                                Thomas Thomassen β€” SketchUp Monkey & Coding addict
                                List of my plugins and link to the CookieWare fund

                                1 Reply Last reply Reply Quote 0
                                • TIGT Offline
                                  TIG Moderator
                                  last edited by

                                  Not if the two small areas were equivalent to the large one... then it'd be 'balanced'...
                                  The large area pulls it over then the 1st small are pulls it back and then the 2nd small area pulls it back again.
                                  IF there's a large and a small area the large one 'wins'.

                                  TIG

                                  1 Reply Last reply Reply Quote 0
                                  • voljankoV Offline
                                    voljanko
                                    last edited by

                                    By computer you mean compute?

                                    SuSolid.com - solid check - solid repair- solid intersection check - weight plugin

                                    1 Reply Last reply Reply Quote 0
                                    • TIGT Offline
                                      TIG Moderator
                                      last edited by

                                      @voljanko said:

                                      By computer you mean compute?
                                      A simple typo by tt in the original title - but we understood what he meant... πŸ˜‰

                                      TIG

                                      1 Reply Last reply Reply Quote 0
                                      • voljankoV Offline
                                        voljanko
                                        last edited by

                                        I'm trying to follow your conversation,but not sure to understand what are you trying to do.
                                        Do you want to align faces that are nearly aligned?

                                        SuSolid.com - solid check - solid repair- solid intersection check - weight plugin

                                        1 Reply Last reply Reply Quote 0
                                        • thomthomT Offline
                                          thomthom
                                          last edited by

                                          @tig said:

                                          Not if the two small areas were equivalent to the large one... then it'd be 'balanced'...
                                          The large area pulls it over then the 1st small are pulls it back and then the 2nd small area pulls it back again.
                                          IF there's a large and a small area the large one 'wins'.

                                          Yes, but when they are not, which would be in any non-regular mesh. So I still wonder why one would use area to weigh the normals.

                                          Thomas Thomassen β€” SketchUp Monkey & Coding addict
                                          List of my plugins and link to the CookieWare fund

                                          1 Reply Last reply Reply Quote 0
                                          • thomthomT Offline
                                            thomthom
                                            last edited by

                                            @tig said:

                                            @voljanko said:

                                            By computer you mean compute?
                                            A simple typo by tt in the original title - but we understood what he meant... πŸ˜‰

                                            Fixed! 😳

                                            Thomas Thomassen β€” SketchUp Monkey & Coding addict
                                            List of my plugins and link to the CookieWare fund

                                            1 Reply Last reply Reply Quote 0
                                            • 1
                                            • 2
                                            • 1 / 2
                                            • First post
                                              Last post
                                            Buy SketchPlus
                                            Buy SUbD
                                            Buy WrapR
                                            Buy eBook
                                            Buy Modelur
                                            Buy Vertex Tools
                                            Buy SketchCuisine
                                            Buy FormFonts

                                            Advertisement