Skip to content

Commit

Permalink
feat: implement draco decoder (#1)
Browse files Browse the repository at this point in the history
* wip draco decoder

* base example setup

* add better example

* feat: add missing methods

* ci: make the build work

* ci: cache draco

* fix: refactor code

* fix: apply review comments
  • Loading branch information
okwasniewski authored Nov 6, 2024
1 parent 65dbf09 commit d87cd6e
Show file tree
Hide file tree
Showing 17 changed files with 1,420 additions and 23 deletions.
15 changes: 15 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ jobs:
run: yarn prepare

build-android:
if: false
runs-on: ubuntu-latest
env:
TURBO_CACHE_DIR: .turbo/android
Expand Down Expand Up @@ -113,6 +114,8 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v3
with:
submodules: recursive

- name: Setup
uses: ./.github/actions/setup
Expand All @@ -125,6 +128,18 @@ jobs:
restore-keys: |
${{ runner.os }}-turborepo-ios-
- name: Build draco
run: |
yarn run build-draco
- name: Cache draco
uses: actions/cache@v3
with:
path: libs/**
key: ${{ runner.os }}-draco-build-${{ hashFiles('example/ios/Podfile.lock') }}
restore-keys: |
${{ runner.os }}-draco-
- name: Check turborepo cache for iOS
run: |
TURBO_CACHE_STATUS=$(node -p "($(yarn turbo run build:ios --cache-dir="${{ env.TURBO_CACHE_DIR }}" --dry=json)).tasks.find(t => t.task === 'build:ios').cache.status")
Expand Down
99 changes: 99 additions & 0 deletions cpp/draco-helpers.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
#include "draco/core/decoder_buffer.h"
#pragma once

#include <jsi/jsi.h>

#include "draco/attributes/attribute_transform_type.h"
#include "draco/attributes/point_attribute.h"
#include "draco/compression/config/compression_shared.h"
#include "draco/compression/decode.h"
#include "draco/core/decoder_buffer.h"
#include "draco/mesh/mesh.h"

#define HOSTFN(name, size, capture) \
jsi::Function::createFromHostFunction(rt, jsi::PropNameID::forAscii(rt, name), size, \
capture(jsi::Runtime &rt, const jsi::Value &thisValue, \
const jsi::Value *arguments, size_t count) \
->jsi::Value

namespace facebook::react {
template <typename T>
std::shared_ptr<T> tryGetDracoObject(jsi::Runtime& rt, jsi::Object& obj) {
if (!obj.hasNativeState(rt)) {
return nullptr;
}

return std::dynamic_pointer_cast<T>(obj.getNativeState(rt));
}

template <typename T>
bool GetTrianglesArray(const draco::Mesh &m, const int out_size,
T *out_values) {
const uint32_t num_faces = m.num_faces();
if (num_faces * 3 * sizeof(T) != out_size) {
return false;
}

for (uint32_t face_id = 0; face_id < num_faces; ++face_id) {
const draco::Mesh::Face &face = m.face(draco::FaceIndex(face_id));
out_values[face_id * 3 + 0] = static_cast<T>(face[0].value());
out_values[face_id * 3 + 1] = static_cast<T>(face[1].value());
out_values[face_id * 3 + 2] = static_cast<T>(face[2].value());
}
return true;
}

template <class T>
static bool GetAttributeDataArrayForAllPointsHelper(const draco::PointCloud &pc,
const draco::PointAttribute &pa,
const draco::DataType type,
int out_size,
void *out_values) {
const int components = pa.num_components();
const int num_points = pc.num_points();
const size_t data_size = num_points * components * sizeof(T);
if (data_size != out_size) {
return false;
}
const bool requested_type_matches = pa.data_type() == type;
if (requested_type_matches && pa.is_mapping_identity()) {
// Copy values directly to the output vector.
const uint8_t *ptr = pa.GetAddress(draco::AttributeValueIndex(0));
::memcpy(out_values, ptr, data_size);
return true;
}

return false;
};

bool GetAttributeFloatArrayForAllPoints(const draco::PointCloud &pc,
const draco::PointAttribute &pa,
int out_size,
void *out_values) {
const int components = pa.num_components();
const int num_points = pc.num_points();
const int data_size = num_points * components * sizeof(float);
if (data_size != out_size) {
return false;
}
const bool requested_type_is_float = pa.data_type() == draco::DT_FLOAT32;
std::vector<float> values(components, -2.f);
int entry_id = 0;
float *const floats = reinterpret_cast<float *>(out_values);

for (draco::PointIndex i(0); i < num_points; ++i) {
const draco::AttributeValueIndex val_index = pa.mapped_index(i);
if (requested_type_is_float) {
pa.GetValue(val_index, &values[0]);
} else {
if (!pa.ConvertValue<float>(val_index, &values[0])) {
return false;
}
}
for (int j = 0; j < components; ++j) {
floats[entry_id++] = values[j];
}
}
return true;
}
}
57 changes: 57 additions & 0 deletions cpp/draco-state.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#pragma once

#include "draco/core/decoder_buffer.h"
#include <jsi/jsi.h>

#include "draco/attributes/point_attribute.h"
#include "draco/core/decoder_buffer.h"
#include "draco/mesh/mesh.h"

namespace facebook::react {
class DracoDecoder: public jsi::NativeState {
public:
DracoDecoder(): decoder_(draco::Decoder()), last_status_(draco::Status()) {}
virtual ~DracoDecoder() {}

draco::Decoder decoder_;
draco::Status last_status_;
};

class DracoDecoderBuffer : public jsi::NativeState {
public:
DracoDecoderBuffer() : buffer_(draco::DecoderBuffer()) {}
virtual ~DracoDecoderBuffer() {}

draco::DecoderBuffer buffer_;
};

class DracoPointCloud: public jsi::NativeState {
public:
DracoPointCloud(): pointCloud_(draco::PointCloud()) {}
virtual ~DracoPointCloud() {}

draco::PointCloud pointCloud_;
};

class DracoPointAttribute: public jsi::NativeState {
public:
DracoPointAttribute(): pointAttribute_(draco::PointAttribute()) {}
virtual ~DracoPointAttribute() {}

explicit DracoPointAttribute(const draco::PointAttribute &attribute): pointAttribute_(draco::PointAttribute()) {
pointAttribute_.CopyFrom(attribute);
}

explicit DracoPointAttribute(draco::PointAttribute &&attribute): pointAttribute_(std::move(attribute)) {}

draco::PointAttribute pointAttribute_;
};

class DracoMesh: public jsi::NativeState {
public:
DracoMesh(): mesh_(draco::Mesh()) {}
virtual ~DracoMesh() {}

draco::Mesh mesh_;
};
}
Loading

0 comments on commit d87cd6e

Please sign in to comment.