diff --git a/draco/decoder.go b/draco/decoder.go index 0425f74..f525465 100644 --- a/draco/decoder.go +++ b/draco/decoder.go @@ -24,6 +24,11 @@ func NewDecoder() *Decoder { } func (d *Decoder) DecodeMesh(data []byte, m *Mesh) error { - s := C.dracoDecoderArrayToMesh(d.ref, (*C.char)(unsafe.Pointer(&data[0])), C.size_t(len(data)), m.ref) + s := C.dracoDecoderDecodeMesh(d.ref, (*C.char)(unsafe.Pointer(&data[0])), C.size_t(len(data)), m.ref) + return newError(s) +} + +func (d *Decoder) DecodePointCloud(data []byte, pc *PointCloud) error { + s := C.dracoDecoderDecodePointCloud(d.ref, (*C.char)(unsafe.Pointer(&data[0])), C.size_t(len(data)), pc.ref) return newError(s) } diff --git a/draco/mesh.go b/draco/mesh.go index 1b15d0e..944bcb9 100644 --- a/draco/mesh.go +++ b/draco/mesh.go @@ -3,14 +3,12 @@ package draco // #include "packaged/include/c_api.h" import "C" import ( - "fmt" - "reflect" "runtime" "unsafe" ) type Mesh struct { - ref *C.draco_mesh + PointCloud } func (m *Mesh) free() { @@ -20,7 +18,7 @@ func (m *Mesh) free() { } func NewMesh() *Mesh { - m := &Mesh{C.dracoNewMesh()} + m := &Mesh{PointCloud{C.dracoNewMesh()}} runtime.SetFinalizer(m, (*Mesh).free) return m } @@ -29,14 +27,6 @@ func (m *Mesh) NumFaces() uint32 { return uint32(C.dracoMeshNumFaces(m.ref)) } -func (m *Mesh) NumPoints() uint32 { - return uint32(C.dracoMeshNumPoints(m.ref)) -} - -func (m *Mesh) NumAttrs() int32 { - return int32(C.dracoMeshNumAttrs(m.ref)) -} - func (m *Mesh) Faces(buffer []Face) []Face { n := m.NumFaces() if len(buffer) < int(n) { @@ -45,73 +35,3 @@ func (m *Mesh) Faces(buffer []Face) []Face { C.dracoMeshGetTrianglesUint32(m.ref, C.size_t(n*3*4), (*C.uint32_t)(unsafe.Pointer(&buffer[0]))) return buffer[:n] } - -func (m *Mesh) Attr(i int32) *PointAttr { - attr := C.dracoMeshGetAttribute(m.ref, C.int32_t(i)) - if attr == nil { - return nil - } - return &PointAttr{ref: attr} -} - -func (m *Mesh) AttrByUniqueID(id uint32) *PointAttr { - attr := C.dracoMeshGetAttributeByUniqueId(m.ref, C.uint32_t(id)) - if attr == nil { - return nil - } - return &PointAttr{ref: attr} -} - -func (m *Mesh) NamedAttributeID(gt GeometryType) int32 { - return int32(C.dracoMeshGetNamedAttributeId(m.ref, C.draco_geometry_type(gt))) -} - -func (m *Mesh) AttrData(pa *PointAttr, buffer interface{}) (interface{}, bool) { - var dt DataType - n := m.NumPoints() * uint32(pa.NumComponents()) - if buffer == nil { - dt = pa.DataType() - buffer = reflect.MakeSlice(reflect.SliceOf(dt.goType()), int(n), int(n)).Interface() - } else { - v := reflect.ValueOf(buffer) - if v.IsNil() { - buffer = reflect.MakeSlice(reflect.SliceOf(dt.goType()), int(n), int(n)).Interface() - } - if v.Kind() != reflect.Slice { - panic(fmt.Sprintf("draco-go: expecting a slice but got %s", v.Kind())) - } - l := v.Len() - switch buffer.(type) { - case []int8: - dt = DT_INT8 - case []uint8: - dt = DT_UINT8 - case []int16: - dt = DT_INT16 - case []uint16: - dt = DT_UINT16 - case []int32: - dt = DT_INT32 - case []uint32: - dt = DT_UINT32 - case []int64: - dt = DT_INT64 - case []uint64: - dt = DT_UINT64 - case []float32: - dt = DT_FLOAT32 - case []float64: - dt = DT_FLOAT64 - default: - panic("draco-go: unsupported data type") - } - if l < int(n) { - tmp := reflect.MakeSlice(reflect.SliceOf(dt.goType()), int(n)-l, int(n)-l).Interface() - buffer = reflect.AppendSlice(reflect.ValueOf(buffer), reflect.ValueOf(tmp)).Interface() - } - } - v := reflect.ValueOf(buffer).Index(0) - size := n * dt.Size() - ok := C.dracoMeshGetAttributeData(m.ref, pa.ref, C.draco_data_type(dt), C.size_t(size), unsafe.Pointer(v.UnsafeAddr())) - return buffer, bool(ok) -} diff --git a/draco/packaged/include/c_api.h b/draco/packaged/include/c_api.h index ba58ca2..67b9778 100644 --- a/draco/packaged/include/c_api.h +++ b/draco/packaged/include/c_api.h @@ -101,9 +101,33 @@ EXPORT_API int64_t dracoPointAttrByteOffset(const draco_point_attr* pa); EXPORT_API uint32_t dracoPointAttrUniqueId(const draco_point_attr* pa); +// draco::PointCloud + +typedef struct draco_point_cloud draco_point_cloud; + +EXPORT_API draco_point_cloud* dracoNewPointCloud(); + +EXPORT_API void dracoPointCloudRelease(draco_point_cloud *pc); + +EXPORT_API uint32_t dracoPointCloudNumPoints(const draco_point_cloud *pc); + +EXPORT_API int32_t dracoPointCloudNumAttrs(const draco_point_cloud *pc); + +EXPORT_API const draco_point_attr* dracoPointCloudGetAttribute(const draco_point_cloud *pc, int32_t att_id); + +EXPORT_API int32_t dracoPointCloudGetNamedAttributeId(const draco_point_cloud *pc, draco_geometry_type geo_type); + +EXPORT_API const draco_point_attr* dracoPointCloudGetAttributeByUniqueId(const draco_point_cloud *pc, uint32_t unique_id); + +EXPORT_API bool dracoPointCloudGetAttributeData(const draco_point_cloud *pc, + const draco_point_attr *pa, + draco_data_type data_type, + const size_t out_size, + void *out_values); + // draco::Mesh -typedef struct draco_mesh draco_mesh; +typedef struct draco_point_cloud draco_mesh; EXPORT_API draco_mesh* dracoNewMesh(); @@ -111,14 +135,10 @@ EXPORT_API void dracoMeshRelease(draco_mesh *mesh); EXPORT_API uint32_t dracoMeshNumFaces(const draco_mesh *mesh); -EXPORT_API uint32_t dracoMeshNumPoints(const draco_mesh *mesh); - -EXPORT_API int32_t dracoMeshNumAttrs(const draco_mesh *mesh); - // Queries an array of 3*face_count elements containing the triangle indices. // out_values must be allocated to contain at least 3*face_count uint16_t elements. // out_size must be exactly 3*face_count*sizeof(uint16_t), else out_values -// won´t be filled and returns false. +// won't be filled and returns false. EXPORT_API bool dracoMeshGetTrianglesUint16(const draco_mesh *mesh, const size_t out_size, uint16_t *out_values); @@ -126,23 +146,11 @@ EXPORT_API bool dracoMeshGetTrianglesUint16(const draco_mesh *mesh, // Queries an array of 3*face_count elements containing the triangle indices. // out_values must be allocated to contain at least 3*face_count uint32_t elements. // out_size must be exactly 3*face_count*sizeof(uint32_t), else out_values -// won´t be filled and returns false. +// won't be filled and returns false. EXPORT_API bool dracoMeshGetTrianglesUint32(const draco_mesh *mesh, const size_t out_size, uint32_t *out_values); -EXPORT_API const draco_point_attr* dracoMeshGetAttribute(const draco_mesh *mesh, int32_t att_id); - -EXPORT_API int32_t dracoMeshGetNamedAttributeId(const draco_mesh *mesh, draco_geometry_type geo_type); - -EXPORT_API const draco_point_attr* dracoMeshGetAttributeByUniqueId(const draco_mesh *mesh, uint32_t unique_id); - -EXPORT_API bool dracoMeshGetAttributeData(const draco_mesh *mesh, - const draco_point_attr *pa, - draco_data_type data_type, - const size_t out_size, - void *out_values); - // draco::Decoder typedef struct draco_decoder draco_decoder; @@ -151,10 +159,16 @@ EXPORT_API draco_decoder* dracoNewDecoder(); EXPORT_API void dracoDecoderRelease(draco_decoder *decoder); -EXPORT_API draco_status* dracoDecoderArrayToMesh(draco_decoder *decoder, - const char *data, - size_t data_size, - draco_mesh *out_mesh); +EXPORT_API draco_status* dracoDecoderDecodeMesh(draco_decoder *decoder, + const char *data, + size_t data_size, + draco_mesh *out_mesh); + + +EXPORT_API draco_status* dracoDecoderDecodePointCloud(draco_decoder *decoder, + const char *data, + size_t data_size, + draco_point_cloud *out_pc); #ifdef __cplusplus } diff --git a/draco/packaged/lib/darwin_amd64/libdraco_c.a b/draco/packaged/lib/darwin_amd64/libdraco_c.a index 50b2304..b28e964 100644 Binary files a/draco/packaged/lib/darwin_amd64/libdraco_c.a and b/draco/packaged/lib/darwin_amd64/libdraco_c.a differ diff --git a/draco/packaged/lib/linux_amd64/libdraco_c.a b/draco/packaged/lib/linux_amd64/libdraco_c.a index 0dbb95b..b28e964 100644 Binary files a/draco/packaged/lib/linux_amd64/libdraco_c.a and b/draco/packaged/lib/linux_amd64/libdraco_c.a differ diff --git a/draco/packaged/lib/windows_amd64/libdraco_c.a b/draco/packaged/lib/windows_amd64/libdraco_c.a index 4d91147..e37937f 100644 Binary files a/draco/packaged/lib/windows_amd64/libdraco_c.a and b/draco/packaged/lib/windows_amd64/libdraco_c.a differ diff --git a/draco/pointcloud.go b/draco/pointcloud.go new file mode 100644 index 0000000..3d0a9fd --- /dev/null +++ b/draco/pointcloud.go @@ -0,0 +1,104 @@ +package draco + +// #include "packaged/include/c_api.h" +import "C" +import ( + "fmt" + "reflect" + "runtime" + "unsafe" +) + +type PointCloud struct { + ref *C.draco_point_cloud +} + +func (pc *PointCloud) free() { + if pc.ref != nil { + C.dracoPointCloudRelease(pc.ref) + } +} + +func NewPointCloud() *PointCloud { + pc := &PointCloud{C.dracoNewPointCloud()} + runtime.SetFinalizer(pc, (*PointCloud).free) + return pc +} + +func (pc *PointCloud) NumPoints() uint32 { + return uint32(C.dracoPointCloudNumPoints(pc.ref)) +} + +func (pc *PointCloud) NumAttrs() int32 { + return int32(C.dracoPointCloudNumAttrs(pc.ref)) +} + +func (pc *PointCloud) Attr(i int32) *PointAttr { + attr := C.dracoPointCloudGetAttribute(pc.ref, C.int32_t(i)) + if attr == nil { + return nil + } + return &PointAttr{ref: attr} +} + +func (pc *PointCloud) AttrByUniqueID(id uint32) *PointAttr { + attr := C.dracoPointCloudGetAttributeByUniqueId(pc.ref, C.uint32_t(id)) + if attr == nil { + return nil + } + return &PointAttr{ref: attr} +} + +func (pc *PointCloud) NamedAttributeID(gt GeometryType) int32 { + return int32(C.dracoPointCloudGetNamedAttributeId(pc.ref, C.draco_geometry_type(gt))) +} + +func (pc *PointCloud) AttrData(pa *PointAttr, buffer interface{}) (interface{}, bool) { + var dt DataType + n := pc.NumPoints() * uint32(pa.NumComponents()) + if buffer == nil { + dt = pa.DataType() + buffer = reflect.MakeSlice(reflect.SliceOf(dt.goType()), int(n), int(n)).Interface() + } else { + v := reflect.ValueOf(buffer) + if v.IsNil() { + buffer = reflect.MakeSlice(reflect.SliceOf(dt.goType()), int(n), int(n)).Interface() + } + if v.Kind() != reflect.Slice { + panic(fmt.Sprintf("draco-go: expecting a slice but got %s", v.Kind())) + } + l := v.Len() + switch buffer.(type) { + case []int8: + dt = DT_INT8 + case []uint8: + dt = DT_UINT8 + case []int16: + dt = DT_INT16 + case []uint16: + dt = DT_UINT16 + case []int32: + dt = DT_INT32 + case []uint32: + dt = DT_UINT32 + case []int64: + dt = DT_INT64 + case []uint64: + dt = DT_UINT64 + case []float32: + dt = DT_FLOAT32 + case []float64: + dt = DT_FLOAT64 + default: + panic("draco-go: unsupported data type") + } + if l < int(n) { + tmp := reflect.MakeSlice(reflect.SliceOf(dt.goType()), int(n)-l, int(n)-l).Interface() + buffer = reflect.AppendSlice(reflect.ValueOf(buffer), reflect.ValueOf(tmp)).Interface() + } + } + v := reflect.ValueOf(buffer).Index(0) + size := n * dt.Size() + ok := C.dracoPointCloudGetAttributeData(pc.ref, pa.ref, C.draco_data_type(dt), C.size_t(size), unsafe.Pointer(v.UnsafeAddr())) + return buffer, bool(ok) +} diff --git a/examples/decode/main.go b/examples/decode/main.go index 6c39f1b..1feba80 100644 --- a/examples/decode/main.go +++ b/examples/decode/main.go @@ -1,32 +1,32 @@ -package main - -import ( - "io/ioutil" - "log" - - "github.com/qmuntal/draco-go/draco" -) - -func main() { - data, err := ioutil.ReadFile("../../testdata/test_nm.obj.edgebreaker.cl4.2.2.drc") - if err != nil { - log.Fatalf("failed to read test file: %v", err) - } - m := draco.NewMesh() - d := draco.NewDecoder() - if err := d.DecodeMesh(data, m); err != nil { - log.Fatalf("failed to decode mesh: %v", err) - } - log.Println(m.NumFaces()) - if n := m.NumFaces(); n != 170 { - log.Fatalf("Mesh.NumFaces got 170, got %d", n) - } - if n := m.NumPoints(); n != 99 { - log.Fatalf("Mesh.NumFaces got 99, got %d", n) - } - faces := m.Faces(nil) - want := [3]uint32{0, 1, 2} - if got := faces[0]; got != want { - log.Fatalf("Mesh.Faces[0] got %v, got %v", want, got) - } -} +package main + +import ( + "io/ioutil" + "log" + + "github.com/qmuntal/draco-go/draco" +) + +func main() { + data, err := ioutil.ReadFile("../../testdata/test_nm.obj.edgebreaker.cl4.2.2.drc") + if err != nil { + log.Fatalf("failed to read test file: %v", err) + } + m := draco.NewMesh() + d := draco.NewDecoder() + if err := d.DecodeMesh(data, m); err != nil { + log.Fatalf("failed to decode mesh: %v", err) + } + log.Println(m.NumFaces()) + if n := m.NumFaces(); n != 170 { + log.Fatalf("Mesh.NumFaces got 170, got %d", n) + } + if n := m.NumPoints(); n != 99 { + log.Fatalf("Mesh.NumFaces got 99, got %d", n) + } + faces := m.Faces(nil) + want := [3]uint32{0, 1, 2} + if got := faces[0]; got != want { + log.Fatalf("Mesh.Faces[0] got %v, got %v", want, got) + } +}