sketchucation logo sketchucation
    • 登入
    Oops, your profile's looking a bit empty! To help us tailor your experience, please fill in key details like your SketchUp version, skill level, operating system, and more. Update and save your info on your profile page today!
    🔌 Smart Spline | Fluid way to handle splines for furniture design and complex structures. Download

    Vertex Normals... ?

    已排程 已置頂 已鎖定 已移動 Developers' Forum
    26 貼文 6 Posters 3.4k 瀏覽 6 Watching
    正在載入更多貼文
    • 從舊到新
    • 從新到舊
    • 最多點贊
    回覆
    • 在新貼文中回覆
    登入後回覆
    此主題已被刪除。只有擁有主題管理權限的使用者可以查看。
    • O 離線
      oajfh
      最後由 編輯

      Well, after more experimenting, taking into account what's been said :

      
      # Original credit ; Anton_S
      # Get group/component entities.
      # @param [Sketchup;;Group, Sketchup;;ComponentInstance] entity
      # @return [Sketchup;;Entities]
      def get_entities(entity)
      	if entity.is_a?(Sketchup;;ComponentInstance)
      		return entity.definition.entities
      	else 
      		return entity.entities
      	end
      end
      
      # Original credit ; Anton_S
      # Get triangular mesh of the group.
      # @param [Sketchup;;Group, Sketchup;;ComponentInstance] entity
      # @param [Boolean] recursive Whether to include all the child groups and
      #   components.
      # @param [Boolean] transform Whether to give points in global coordinates.
      # @param [Integer] Keep face counter so as not to mess up normal exporting
      # @yield A procedure to determine whether particular child group/component
      #   should be considered a part of the collection.
      # @yieldparam [Sketchup;;Group, Sketchup;;ComponentInstance] entity
      # @yieldreturn [Boolean] Pass true to consider an entity as part of the
      #   collection. Pass false to not consider an entity as part of the
      #   collection.
      # @return [Geom;;PolygonMesh]
      def get_triangular_mesh(entity, recursive = true, transform = false,normal_array, &entity_validation)
      
        mesh = Geom;;PolygonMesh.new
        if( entity.is_a?(;;Sketchup;;Face)||entity.is_a?(;;Sketchup;;ComponentInstance)||entity.is_a?(;;Sketchup;;Group))
      	get_entities(entity).each { |e|
      		if e.is_a?(;;Sketchup;;Face)
      
      			e.mesh.polygons.each_index{ |i|
      			pts = e.mesh.polygon_points_at(i+1)
      			
      			mesh_b = e.mesh 4 #Temp face with normals
      
      			index = mesh.add_polygon(pts)
      			
      			#puts "e"
      			for k in 1..mesh_b.count_points
      				#puts "k"
      				#puts mesh_b.point_at(k) #Not global coordinates
      				#puts mesh_b.normal_at(k)
      				index = mesh.point_index(mesh_b.point_at(k)) # Get index of current point being examined
      				#puts index
      				#puts mesh.point_at(index)
      				#puts "k"
      				normal_array[index] = mesh_b.normal_at(k) # Set that point's normal to the current point's normal's value
      			end
      			#puts "j"
            }
      		elsif recursive && (e.is_a?(;;Sketchup;;Group) || e.is_a?(;;Sketchup;;ComponentInstance)) && entity_validation.call(e)
      			new_array = []
      			mesh2 = get_triangular_mesh(e, true, true, new_array, &entity_validation)
      			mesh2.polygons.each_index { |i|
      			index = mesh.add_polygon(mesh2.polygon_points_at(i+1))
      
      			mesh2.points.each_with_index{|point, index|
      				ind = mesh.point_index(point)
      				normal_array[ind]= new_array[index]
      			}
      		}
          end
        }
        mesh.transform!(entity.transformation) if transform
      	for l in 1..normal_array.length-1 #index 0 not used so length is 1 more than expected
      		#puts l
      		normal_array[l].transform!(entity.transformation) if transform
      	end
        end
        return mesh
      end
      
      
      normal_array = [] # Contains the VERTEX normals.
      mesh = get_triangular_mesh(group, true, true,normal_array){ |e| true }
      
      
      

      (This code is bad and unoptimised, I'm aware of that. I'm a terrible programmer)

      I'm not sure what to think of this.

      If I look at what vertex normals are returned during recursion, I occasionally get different normals for what appears to be the same vertex, and I don't know why. For a cube, I only get global axis-aligned vectors, which isn't really what I was expecting.

      1 條回覆 最後回覆 回覆 引用 0
      • J 離線
        Jim
        最後由 編輯

        I just wanted to correct my post. A PolygoMesh can calculate normals if the mesh is generated from a face. Read further for more details.

        So, what were you expecting?

        A PolygonMesh is just a container for points and triangles. It does not calculate normals.

        You can retrieve the vertex normals of a mesh when the mesh is made from an existing Face, but those normals will be the normal of the Face and not any calculated value. This is why you get multiple normals from a vertex in your code and why they are all aligned with each Face normal. The normals being aligned to the global axis is because your cube faces are aligned to the global axes, am I right?

        
        model = Sketchup.active_model
        sel = model.selection
        ents = model.active_entities
        faces = ents.grep(Sketchup;;Face)
        
        faces.each do |face|
            mesh = face.mesh(4)
            for idx in (1..mesh.count_points)
                norm = mesh.normal_at idx
                pt = mesh.point_at idx
                pt2 = pt.offset norm
                ents.add_cline(pt, pt2)
            end
        end
        
        

        2015-06_266.png

        Hi

        1 條回覆 最後回覆 回覆 引用 0
        • O 離線
          oajfh
          最後由 編輯

          😳

          Yes, you are absolutely right. I hadn't quite understood what Thomthom meant. Sorry for dragging this topic on for so long.

          1 條回覆 最後回覆 回覆 引用 0
          • tt_suT 離線
            tt_su
            最後由 編輯

            Sorry - I should have clarified - the vertex normals depend on whether the edge between the faces are Smooth. Soft doesn't matter - because only Smooth affect shading. The normal is a representation of the surface shading.

            2015-06-09_12h34_47.png

            @jim said:

            [...] but those normals will be the normal of the Face and not any calculated value. This is why you get multiple normals from a vertex in your code and why they are all aligned with each Face normal.

            They are calculated if and only if the mesh came from face.mesh. When building your own there will be no calculation. This is because PolygonMesh itself doesn't do the calculation, but SketchUp will set the vertex normals as it builds the mesh returned to face.mesh.

            Under the hood there is a set_normal function similar to set_uv. But this has never been exposed - probably because entities.add_faces_from_mesh and entitites.fill_from_mesh would never use it.

            1 條回覆 最後回覆 回覆 引用 0
            • J 離線
              Jim
              最後由 編輯

              Well that's interesting. Thanks.

              Hi

              1 條回覆 最後回覆 回覆 引用 0
              • Dan RathbunD 離線
                Dan Rathbun
                最後由 編輯

                @oajfh said:

                Sorry for dragging this topic on for so long.

                Don't worry about it.

                This is the kind of nitty-gritty dirty details us consummate geeks really love to ponder.

                😛

                I'm not here much anymore.

                1 條回覆 最後回覆 回覆 引用 0
                • 1
                • 2
                • 2 / 2
                • 第一個貼文
                  最後的貼文
                Buy SketchPlus
                Buy SUbD
                Buy WrapR
                Buy eBook
                Buy Modelur
                Buy Vertex Tools
                Buy SketchCuisine
                Buy FormFonts

                Advertisement