func octreeMesh(octree *gfx.Octant) *gfx.Mesh { m := new(gfx.Mesh) // Slice to zero. m.Vertices = m.Vertices[:0] m.Colors = m.Colors[:0] bci := -1 nextBC := func() gfx.Color { bci++ switch bci % 3 { case 0: return gfx.Color{1, 0, 0, 0} case 1: return gfx.Color{0, 1, 0, 0} case 2: return gfx.Color{0, 0, 1, 0} } panic("never here.") } var add func(o *gfx.Octant) add = func(o *gfx.Octant) { // Add vertices. before := len(m.Vertices) appendCube(m, float32(o.AABB.Size().X/2.0)) center := o.AABB.Center() for i, v := range m.Vertices[before:] { vert := v.Vec3() vert = vert.Add(center) m.Vertices[before+i] = gfx.ConvertVec3(vert) } fmt.Println("Octant", o.Depth, "-", len(o.Objects), "objects") for s := range o.Objects { before := len(m.Vertices) appendCube(m, float32(s.AABB().Size().X/2.0)) center := s.AABB().Center() //fmt.Println(center, s.AABB()) for i, v := range m.Vertices[before:] { vert := v.Vec3() vert = vert.Add(center) m.Vertices[before+i] = gfx.ConvertVec3(vert) } } for _, octant := range o.Octants { if octant != nil { add(octant) } } } add(octree) for _ = range m.Vertices { // Add barycentric coordinates. m.Colors = append(m.Colors, nextBC()) } return m }
func RTreeMesh(tree *rtree.Tree, level int) *gfx.Mesh { m := new(gfx.Mesh) bci := -1 nextBC := func() gfx.Color { bci++ switch bci % 3 { case 0: return gfx.Color{1, 0, 0, 0} case 1: return gfx.Color{0, 1, 0, 0} case 2: return gfx.Color{0, 0, 1, 0} } panic("never here.") } nodes := 0 var add func(n *rtree.Node) add = func(n *rtree.Node) { //if nodes > 100 { // return //} nodes++ if n == nil { return } if level == 0 || nodes == level { // Add vertices. m.Vertices = Rect3LineVerts(n.Bounds(), m.Vertices) } /*for _, s := range n.Objects { c := s.Bounds().Center() sz := 0.005 sb := math.Rect3{ Min: math.Vec3Zero.AddScalar(-sz).Add(c), Max: math.Vec3Zero.AddScalar(sz).Add(c), } m.Vertices = Rect3LineVerts(sb, m.Vertices) }*/ for _, c := range n.Children { add(c) } } add(tree.Root()) fmt.Println(tree.Count(), "objects", nodes, "nodes") for _ = range m.Vertices { // Add barycentric coordinates. m.Colors = append(m.Colors, nextBC()) } return m }
func appendCube(m *gfx.Mesh, scale float32) { addV := func(x, y, z float32) { m.Vertices = append(m.Vertices, gfx.Vec3{x, y, z}) } s := scale addV(-s, -s, -s) addV(-s, -s, s) addV(-s, s, s) addV(s, s, -s) addV(-s, -s, -s) addV(-s, s, -s) addV(s, -s, s) addV(-s, -s, -s) addV(s, -s, -s) addV(s, s, -s) addV(s, -s, -s) addV(-s, -s, -s) addV(-s, -s, -s) addV(-s, s, s) addV(-s, s, -s) addV(s, -s, s) addV(-s, -s, s) addV(-s, -s, -s) addV(-s, s, s) addV(-s, -s, s) addV(s, -s, s) addV(s, s, s) addV(s, -s, -s) addV(s, s, -s) addV(s, -s, -s) addV(s, s, s) addV(s, -s, s) addV(s, s, s) addV(s, s, -s) addV(-s, s, -s) addV(s, s, s) addV(-s, s, -s) addV(-s, s, s) addV(s, s, s) addV(-s, s, s) addV(s, -s, s) }
func NTreeMesh(tree *ntree.Tree, level int) *gfx.Mesh { m := new(gfx.Mesh) nodes := 0 var add func(n *ntree.Node) add = func(n *ntree.Node) { //if nodes > 100 { // return //} nodes++ if n == nil { return } if level == 0 || nodes == level { // Add vertices. m.Vertices = Rect3LineVerts(n.Bounds(), m.Vertices) } fmt.Println("node", nodes, len(n.Objects), "objects") for _, s := range n.Objects { c := s.Bounds().Center() sz := 0.005 sb := math.Rect3{ Min: math.Vec3Zero.AddScalar(-sz).Add(c), Max: math.Vec3Zero.AddScalar(sz).Add(c), } sb = s.Bounds() m.Vertices = Rect3LineVerts(sb, m.Vertices) } for _, c := range n.Children { add(c) } } add(tree.Root) fmt.Println(tree.Count(), "objects", nodes, "nodes\n\n\n") // Generate the barycentric coordinates. //m.GenerateBary() return m }
func (r *Renderer) LoadMesh(m *gfx.Mesh, done chan *gfx.Mesh) { // Lock the mesh until we are done loading it. m.Lock() if m.Loaded && !m.HasChanged() { // Mesh is already loaded and has not changed, signal completion and // return after unlocking. m.Unlock() select { case done <- m: default: } return } f := func() { // Find the native mesh, creating a new one if none exists. var native *nativeMesh if !m.Loaded { native = new(nativeMesh) native.r = r } else { native = m.NativeMesh.(*nativeMesh) } // Determine usage hint. usageHint := gl.STATIC_DRAW if m.Dynamic { usageHint = gl.DYNAMIC_DRAW } // Update Indices VBO. if !m.Loaded || m.IndicesChanged { if len(m.Indices) == 0 { // Delete indices VBO. r.deleteVBO(&native.indices) } else { if native.indices == 0 { // Create indices VBO. native.indices = r.createVBO() } // Update indices VBO. r.updateVBO( usageHint, unsafe.Sizeof(m.Indices[0]), len(m.Indices), unsafe.Pointer(&m.Indices[0]), native.indices, ) native.indicesCount = uint32(len(m.Indices)) } m.IndicesChanged = false } // Update Vertices VBO. if !m.Loaded || m.VerticesChanged { if len(m.Vertices) == 0 { // Delete vertices VBO. r.deleteVBO(&native.vertices) native.verticesCount = 0 } else { if native.vertices == 0 { // Create vertices VBO. native.vertices = r.createVBO() } // Update vertices VBO. r.updateVBO( usageHint, unsafe.Sizeof(m.Vertices[0]), len(m.Vertices), unsafe.Pointer(&m.Vertices[0]), native.vertices, ) native.verticesCount = uint32(len(m.Vertices)) } m.VerticesChanged = false } // Update Colors VBO. if !m.Loaded || m.ColorsChanged { if len(m.Colors) == 0 { // Delete colors VBO. r.deleteVBO(&native.colors) } else { if native.colors == 0 { // Create colors VBO. native.colors = r.createVBO() } // Update colors VBO. r.updateVBO( usageHint, unsafe.Sizeof(m.Colors[0]), len(m.Colors), unsafe.Pointer(&m.Colors[0]), native.colors, ) } m.ColorsChanged = false } // Update Bary VBO. if !m.Loaded || m.BaryChanged { if len(m.Bary) == 0 { // Delete bary VBO. r.deleteVBO(&native.bary) } else { if native.bary == 0 { // Create bary VBO. native.bary = r.createVBO() } // Update bary VBO. r.updateVBO( usageHint, unsafe.Sizeof(m.Bary[0]), len(m.Bary), unsafe.Pointer(&m.Bary[0]), native.bary, ) } m.BaryChanged = false } // Any texture coordinate sets that were removed should have their // VBO's deleted. deletedMax := len(m.TexCoords) if deletedMax > len(native.texCoords) { deletedMax = len(native.texCoords) } deleted := native.texCoords[:deletedMax] native.texCoords = native.texCoords[:deletedMax] for _, vbo := range deleted { r.deleteVBO(&vbo) } // Any texture coordinate sets that were added should have VBO's // created. added := m.TexCoords[len(native.texCoords):] toUpdate := m.TexCoords for _, set := range added { vbo := r.createVBO() native.texCoords = append(native.texCoords, vbo) // Update the VBO. r.updateVBO( usageHint, unsafe.Sizeof(set.Slice[0]), len(set.Slice), unsafe.Pointer(&set.Slice[0]), vbo, ) } // And finally, any texture coordinate sets that were changed need to // have their VBO's updated. for index, set := range toUpdate { if set.Changed { // Update the VBO. r.updateVBO( usageHint, unsafe.Sizeof(set.Slice[0]), len(set.Slice), unsafe.Pointer(&set.Slice[0]), native.texCoords[index], ) } } // Ensure no buffer is active when we leave (so that OpenGL state is untouched). r.loader.BindBuffer(gl.ARRAY_BUFFER, 0) // Flush and execute OpenGL commands. r.loader.Flush() r.loader.Execute() // If the mesh is not loaded, then we need to assign the native mesh // and create a finalizer to free the native mesh later. if !m.Loaded { // Assign the native mesh. m.NativeMesh = native // Attach a finalizer to the mesh that will later free it. runtime.SetFinalizer(native, finalizeMesh) } // Set the mesh to loaded, clear any data slices if they are not wanted. m.Loaded = true m.ClearData() // Unlock, signal completion, and return. m.Unlock() select { case done <- m: default: } return } select { case r.LoaderExec <- f: default: go func() { r.LoaderExec <- f }() } }