Example #1
0
func WrapMesh(m *gomesh.Mesh) *Mesh {
	m.ReindexVerticesAndFaces()
	// also wrap vertices; i.e. replaces mesh.Vertex with shapeset.vertex
	for i := 0; i < m.Vertices.Len(); i++ {
		if v, ok := m.Vertices.Get(i)[0].(*gomesh.Vertex); ok {
			m.Vertices.Update(i, &Vertex{Vertex: *v})
		}
	}

	// also wrap faces and update them to reference outer vertex object
	for i := 0; i < m.Faces.Len(); i++ {
		if fx, ok := m.Faces.Get(i)[0].(*gomesh.Face); ok {
			f := &Face{Face: *fx}
			f.SetA(m.Vertices.Get(f.GetA().GetLocationInMesh(m))[0])
			f.SetB(m.Vertices.Get(f.GetB().GetLocationInMesh(m))[0])
			f.SetC(m.Vertices.Get(f.GetC().GetLocationInMesh(m))[0])
			m.Faces.Update(i, f)
			f.GetA().AddFace(f)
			f.GetB().AddFace(f)
			f.GetC().AddFace(f)
		}
	}

	// iterate faces, build set of edges
	vert_pairs := make(map[gomesh.VertexPair]*Edge)
	m.Faces.EachWithIndex(func(i int, f gomesh.FaceI) {
		pairs := [3]gomesh.VertexPair{
			gomesh.MakeVertexPair(f.GetA(), f.GetB()),
			gomesh.MakeVertexPair(f.GetB(), f.GetC()),
			gomesh.MakeVertexPair(f.GetC(), f.GetA()),
		}
		for i, pair := range pairs {
			var e *Edge
			if e1, exists := vert_pairs[pair]; !exists {
				e = &Edge{VertexPair: pair}
				e.V1.(*Vertex).AddEdge(e)
				e.V2.(*Vertex).AddEdge(e)
				vert_pairs[pair] = e
			} else {
				e = e1
			}
			e.AddFace(f.(*Face))
			f.(*Face).Edges[i] = e
		}
	})

	return &Mesh{
		Mesh:        *m,
		Borders:     make(map[BorderId]*Border),
		BoundingBox: m.BoundingBox(),
	}
}
Example #2
0
File: io.go Project: nat-n/shapeset
/* Create a new shapeset from a json labels file and a directory of meshes.
 */
func CreateNew(meshes_dir, labels_path string) (ss *ShapeSet, err error) {
	// Ensure meshes_dir ends with a slash
	if meshes_dir[len(meshes_dir)-1] != 47 {
		meshes_dir += "/"
	}

	// Attempt to read given paths
	var label_data []byte
	label_data, err = ioutil.ReadFile(labels_path)
	if err != nil {
		return
	}
	var files []os.FileInfo
	files, err = ioutil.ReadDir(meshes_dir)
	if err != nil {
		return
	}

	// Load labels from json file
	labels := make(map[string]string, 0)
	var labels_temp interface{}
	json.Unmarshal(label_data, &labels_temp)
	for key, val := range labels_temp.(map[string]interface{}) {
		labels[key] = val.(string)
	}

	// Load all meshes with the expected filename pattern (.obj) from the
	// directory at meshes path.
	meshes := make([]*Mesh, 0)
	for _, f := range files {
		r, _ := regexp.Compile(`^(\d+-\d+).obj$`)
		if r.MatchString(f.Name()) == true {
			mesh_file_path := meshes_dir + f.Name()
			var m *gomesh.Mesh
			m, err = gomesh.ReadOBJFile(mesh_file_path)
			if err != nil {
				return
			}
			m.Name = string(r.FindSubmatch([]byte(f.Name()))[1])
			meshes = append(meshes, WrapMesh(m))
		}
	}

	// Compose shapeset
	ss = New("New ShapeSet", labels, meshes)
	return
}
Example #3
0
// Quadric Edge Collapse Decimation
// threshold: is the maximum length edge that will be contracted
// target_face_count: is interpreted based on the assumption that every
// collapsed edge removes two faces.
// safer_mode: if true then at most one edge associated with each vertex will be
// collapsed, this seems to reduce artifacts for equivalent performance, though
// less can be achieved per invokation.
func QECD(m *mesh.Mesh, threshold float64, target_face_count int, safer_mode bool) {

	vertices := make([]*vertex, 0)
	faces := make([]*face, 0)
	edges := &edgeHeap{}

	// build up vertices
	m.Vertices.Each(func(x, y, z float64) {
		vertices = append(vertices, &vertex{
			Coords: [3]float64{x, y, z},
			Faces:  make([]*face, 0),
			Q:      &Quadric{},
			Edges:  make([]*edge, 0),
		})
	})
	// Build up faces and update verts
	// iterate through faces and collect non-border edges
	// by counting the occurances of every edge, and keeping those with a count of 2
	edge_occurances := make(map[[2]int][]*face)
	m.Faces.Each(func(a, b, c int) {
		new_face := &face{
			Vertices: [3]*vertex{vertices[a], vertices[b], vertices[c]},
		}
		faces = append(faces, new_face)
		new_face.calculateKp()

		vertices[a].Faces = append(vertices[a].Faces, new_face)
		vertices[a].Q.Add(new_face.Kp)
		vertices[b].Faces = append(vertices[b].Faces, new_face)
		vertices[b].Q.Add(new_face.Kp)
		vertices[c].Faces = append(vertices[c].Faces, new_face)
		vertices[c].Q.Add(new_face.Kp)

		var edge_description [2]int
		if a < b {
			edge_description = [2]int{a, b}
		} else {
			edge_description = [2]int{b, a}
		}
		edge_occurances[edge_description] = append(
			edge_occurances[edge_description],
			new_face,
		)
		if a < c {
			edge_description = [2]int{a, c}
		} else {
			edge_description = [2]int{c, a}
		}
		edge_occurances[edge_description] = append(
			edge_occurances[edge_description],
			new_face,
		)
		if c < b {
			edge_description = [2]int{c, b}
		} else {
			edge_description = [2]int{b, c}
		}
		edge_occurances[edge_description] = append(
			edge_occurances[edge_description],
			new_face,
		)
	})

	// First iterate through edge_occurances to identify border vertices
	boundary_vertices := make(map[int]bool)
	for e, occurances := range edge_occurances {
		if len(occurances) == 1 {
			boundary_vertices[e[0]] = true
			boundary_vertices[e[1]] = true
		}
	}

	// Iterate through edge_occurances again and build up edges
	for e, occurances := range edge_occurances {
		// Skip if edge doesn't occur in two faces (boundary or non-manifold)
		if len(occurances) == 2 {
			// Skip edge if one of the vertices is on a mesh boundary
			_, is_boundary1 := boundary_vertices[e[0]]
			_, is_boundary2 := boundary_vertices[e[1]]
			if !is_boundary1 && !is_boundary2 {
				new_edge := &edge{
					V1:      vertices[e[0]],
					V2:      vertices[e[1]],
					Faces:   occurances,
					Removed: false,
				}
				for _, occurance := range occurances {
					occurance.Edges = append(occurance.Edges, new_edge)
				}
				new_edge.calculateError()
				vertices[e[0]].Edges = append(vertices[e[0]].Edges, new_edge)
				vertices[e[1]].Edges = append(vertices[e[1]].Edges, new_edge)
				edges.Push(new_edge)
			}
		}
	}

	// Sort edges by error
	heap.Init(edges)

	// Iteratively Collapse the lowest error edges, resorting after each collapse
	// just arbitrarily half the original number of edges for starters
	edges_collapse_target := (len(faces) - target_face_count) / 2
	for len(*edges) > 0 && edges_collapse_target > 0 {
		lowest_cost_edge := heap.Pop(edges).(*edge)
		did_collapse := lowest_cost_edge.collapse(threshold)
		if did_collapse {
			edges_collapse_target--
		}
		edges.UpdateEdges(lowest_cost_edge.V1.Edges)
	}

	//
	// Update the mesh with the changes made to vertices and faces
	//
	m.Vertices = tb.NewVertexBuffer()
	m.Norms = tb.NewVectorBuffer()
	m.Faces = tb.NewTriangleBuffer()

	i := 0
	for _, v := range vertices {
		if !v.Collapsed {
			v.FinalIndex = i
			m.Vertices.Buffer = append(m.Vertices.Buffer, v.Coords[:]...)
			i++
		}
	}

	for _, f := range faces {
		if !(f.Collapsed ||
			f.Vertices[0].Collapsed ||
			f.Vertices[1].Collapsed ||
			f.Vertices[2].Collapsed) {
			a := f.Vertices[0].FinalIndex
			b := f.Vertices[1].FinalIndex
			c := f.Vertices[2].FinalIndex
			m.Faces.Buffer = append(m.Faces.Buffer, a, b, c)
		}
	}

}