Add TypedArray JS API for selected data types

Example Usage (TS code):
```
function _getUint16Array(
  length: number,
  decoder: DecoderInstance,
  mesh: MeshInstance,
  attributeId: number
): Uint16Array {
  const nBytes = length * 2;
  const ptr = draco._malloc(nBytes);
  const attribute = decoder.GetAttribute(mesh, attributeId);

  if (!decoder.GetAttributeUInt16ArrayForAllPoints(mesh, attribute, ptr, length)) {
    throw "GetAttributeUInt16ArrayForAllPoints failed";
  }
  const array = new Uint16Array(draco.HEAPU8.buffer, ptr, length).slice();

  draco._free(ptr);
  return array;
}
```
This commit is contained in:
Stefan Eilemann 2019-06-03 16:53:02 +02:00
parent 5db6df1985
commit 48621b5a74
3 changed files with 179 additions and 6 deletions

View File

@ -60,8 +60,7 @@ double MetadataQuerier::GetDoubleEntry(const Metadata &metadata,
const char *MetadataQuerier::GetStringEntry(const Metadata &metadata, const char *MetadataQuerier::GetStringEntry(const Metadata &metadata,
const char *entry_name) { const char *entry_name) {
const std::string name(entry_name); const std::string name(entry_name);
if (!metadata.GetEntryString(name, &last_string_returned_)) if (!metadata.GetEntryString(name, &last_string_returned_)) return nullptr;
return nullptr;
const char *value = last_string_returned_.c_str(); const char *value = last_string_returned_.c_str();
return value; return value;
@ -81,8 +80,7 @@ const char *MetadataQuerier::GetEntryName(const Metadata &metadata,
entry_names_.push_back(entry.first); entry_names_.push_back(entry.first);
} }
} }
if (entry_id < 0 || entry_id >= entry_names_.size()) if (entry_id < 0 || entry_id >= entry_names_.size()) return nullptr;
return nullptr;
return entry_names_[entry_id].c_str(); return entry_names_[entry_id].c_str();
} }
@ -154,6 +152,41 @@ long Decoder::GetTriangleStripsFromMesh(const Mesh &m,
return stripifier.num_strips(); return stripifier.num_strips();
} }
template <typename T>
bool GetTrianglesArray(const draco::Mesh &m, T *out_values,
const int out_size) {
const uint32_t num_faces = m.num_faces();
if (num_faces * 3 != out_size) {
return false;
}
for (uint32_t face_id = 0; face_id < num_faces; ++face_id) {
const Mesh::Face &face = m.face(draco::FaceIndex(face_id));
if (face.size() != 3 || face[0].value() > std::numeric_limits<T>::max() ||
face[1].value() > std::numeric_limits<T>::max() ||
face[2].value() > std::numeric_limits<T>::max()) {
return false;
}
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;
}
bool Decoder::GetTrianglesUInt16Array(const draco::Mesh &m, void *out_values,
const int out_size) {
return GetTrianglesArray<uint16_t>(
m, reinterpret_cast<uint16_t *>(out_values), out_size);
}
bool Decoder::GetTrianglesUInt32Array(const draco::Mesh &m, void *out_values,
const int out_size) {
return GetTrianglesArray<uint32_t>(
m, reinterpret_cast<uint32_t *>(out_values), out_size);
}
bool Decoder::GetAttributeFloat(const PointAttribute &pa, bool Decoder::GetAttributeFloat(const PointAttribute &pa,
draco::AttributeValueIndex::ValueType val_index, draco::AttributeValueIndex::ValueType val_index,
DracoFloat32Array *out_values) { DracoFloat32Array *out_values) {
@ -179,8 +212,7 @@ bool Decoder::GetAttributeFloatForAllPoints(const PointCloud &pc,
out_values->Resize(num_entries); out_values->Resize(num_entries);
for (draco::PointIndex i(0); i < num_points; ++i) { for (draco::PointIndex i(0); i < num_points; ++i) {
const draco::AttributeValueIndex val_index = pa.mapped_index(i); const draco::AttributeValueIndex val_index = pa.mapped_index(i);
if (!pa.ConvertValue<float>(val_index, values)) if (!pa.ConvertValue<float>(val_index, values)) return false;
return false;
for (int j = 0; j < components; ++j) { for (int j = 0; j < components; ++j) {
out_values->SetValue(entry_id++, values[j]); out_values->SetValue(entry_id++, values[j]);
} }
@ -188,6 +220,32 @@ bool Decoder::GetAttributeFloatForAllPoints(const PointCloud &pc,
return true; return true;
} }
bool Decoder::GetAttributeFloatArrayForAllPoints(const PointCloud &pc,
const PointAttribute &pa,
void *out_values,
const int out_size) {
const int components = pa.num_components();
const int num_points = pc.num_points();
const int num_entries = num_points * components;
if (num_entries != out_size) {
return false;
}
const int kMaxAttributeFloatValues = 4;
float values[kMaxAttributeFloatValues] = {-2.0, -2.0, -2.0, -2.0};
int entry_id = 0;
float *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 (!pa.ConvertValue<float>(val_index, values)) return false;
for (int j = 0; j < components; ++j) {
floats[entry_id++] = values[j];
}
}
return true;
}
bool Decoder::GetAttributeInt8ForAllPoints(const PointCloud &pc, bool Decoder::GetAttributeInt8ForAllPoints(const PointCloud &pc,
const PointAttribute &pa, const PointAttribute &pa,
DracoInt8Array *out_values) { DracoInt8Array *out_values) {
@ -202,6 +260,14 @@ bool Decoder::GetAttributeUInt8ForAllPoints(const PointCloud &pc,
pc, pa, draco::DT_INT8, draco::DT_UINT8, out_values); pc, pa, draco::DT_INT8, draco::DT_UINT8, out_values);
} }
bool Decoder::GetAttributeUInt8ArrayForAllPoints(const PointCloud &pc,
const PointAttribute &pa,
void *out_values,
const int out_size) {
return GetAttributeDataArrayForAllPoints<uint8_t>(pc, pa, draco::DT_UINT8,
out_values, out_size);
}
bool Decoder::GetAttributeInt16ForAllPoints(const PointCloud &pc, bool Decoder::GetAttributeInt16ForAllPoints(const PointCloud &pc,
const PointAttribute &pa, const PointAttribute &pa,
DracoInt16Array *out_values) { DracoInt16Array *out_values) {
@ -216,6 +282,14 @@ bool Decoder::GetAttributeUInt16ForAllPoints(const PointCloud &pc,
pc, pa, draco::DT_INT16, draco::DT_UINT16, out_values); pc, pa, draco::DT_INT16, draco::DT_UINT16, out_values);
} }
bool Decoder::GetAttributeUInt16ArrayForAllPoints(const PointCloud &pc,
const PointAttribute &pa,
void *out_values,
const int out_size) {
return GetAttributeDataArrayForAllPoints<uint16_t>(pc, pa, draco::DT_UINT16,
out_values, out_size);
}
bool Decoder::GetAttributeInt32ForAllPoints(const PointCloud &pc, bool Decoder::GetAttributeInt32ForAllPoints(const PointCloud &pc,
const PointAttribute &pa, const PointAttribute &pa,
DracoInt32Array *out_values) { DracoInt32Array *out_values) {
@ -236,6 +310,14 @@ bool Decoder::GetAttributeUInt32ForAllPoints(const PointCloud &pc,
pc, pa, draco::DT_INT32, draco::DT_UINT32, out_values); pc, pa, draco::DT_INT32, draco::DT_UINT32, out_values);
} }
bool Decoder::GetAttributeUInt32ArrayForAllPoints(const PointCloud &pc,
const PointAttribute &pa,
void *out_values,
const int out_size) {
return GetAttributeDataArrayForAllPoints<uint32_t>(pc, pa, draco::DT_UINT32,
out_values, out_size);
}
void Decoder::SkipAttributeTransform(draco_GeometryAttribute_Type att_type) { void Decoder::SkipAttributeTransform(draco_GeometryAttribute_Type att_type) {
decoder_.SetSkipAttributeTransform(att_type); decoder_.SetSkipAttributeTransform(att_type);
} }

View File

@ -146,6 +146,14 @@ class Decoder {
static long GetTriangleStripsFromMesh(const draco::Mesh &m, static long GetTriangleStripsFromMesh(const draco::Mesh &m,
DracoInt32Array *strip_values); DracoInt32Array *strip_values);
// Returns all faces as triangles. Fails if there are non-triangle faces,
// indices exceed the data range (in particular for uint16), or the
// output array size does not match
static bool GetTrianglesUInt16Array(const draco::Mesh &m, void *out_values,
int out_size);
static bool GetTrianglesUInt32Array(const draco::Mesh &m, void *out_values,
int out_size);
// Returns float attribute values in |out_values| from |entry_index| index. // Returns float attribute values in |out_values| from |entry_index| index.
static bool GetAttributeFloat( static bool GetAttributeFloat(
const draco::PointAttribute &pa, const draco::PointAttribute &pa,
@ -158,6 +166,12 @@ class Decoder {
const draco::PointAttribute &pa, const draco::PointAttribute &pa,
DracoFloat32Array *out_values); DracoFloat32Array *out_values);
// Returns float attribute values for all point ids of the point cloud.
// I.e., the |out_values| is going to contain m.num_points() entries.
static bool GetAttributeFloatArrayForAllPoints(
const draco::PointCloud &pc, const draco::PointAttribute &pa,
void *out_values, int out_size);
// Returns int8_t attribute values for all point ids of the point cloud. // Returns int8_t attribute values for all point ids of the point cloud.
// I.e., the |out_values| is going to contain m.num_points() entries. // I.e., the |out_values| is going to contain m.num_points() entries.
static bool GetAttributeInt8ForAllPoints(const draco::PointCloud &pc, static bool GetAttributeInt8ForAllPoints(const draco::PointCloud &pc,
@ -170,6 +184,12 @@ class Decoder {
const draco::PointAttribute &pa, const draco::PointAttribute &pa,
DracoUInt8Array *out_values); DracoUInt8Array *out_values);
// Returns uint8_t attribute values for all point ids of the point cloud.
// I.e., the |out_values| is going to contain m.num_points() entries.
static bool GetAttributeUInt8ArrayForAllPoints(
const draco::PointCloud &pc, const draco::PointAttribute &pa,
void *out_values, int out_size);
// Returns int16_t attribute values for all point ids of the point cloud. // Returns int16_t attribute values for all point ids of the point cloud.
// I.e., the |out_values| is going to contain m.num_points() entries. // I.e., the |out_values| is going to contain m.num_points() entries.
static bool GetAttributeInt16ForAllPoints(const draco::PointCloud &pc, static bool GetAttributeInt16ForAllPoints(const draco::PointCloud &pc,
@ -182,6 +202,12 @@ class Decoder {
const draco::PointAttribute &pa, const draco::PointAttribute &pa,
DracoUInt16Array *out_values); DracoUInt16Array *out_values);
// Returns uint16_t attribute values for all point ids of the point cloud.
// I.e., the |out_values| is going to contain m.num_points() entries.
static bool GetAttributeUInt16ArrayForAllPoints(
const draco::PointCloud &pc, const draco::PointAttribute &pa,
void *out_values, int out_size);
// Returns int32_t attribute values for all point ids of the point cloud. // Returns int32_t attribute values for all point ids of the point cloud.
// I.e., the |out_values| is going to contain m.num_points() entries. // I.e., the |out_values| is going to contain m.num_points() entries.
static bool GetAttributeInt32ForAllPoints(const draco::PointCloud &pc, static bool GetAttributeInt32ForAllPoints(const draco::PointCloud &pc,
@ -199,6 +225,12 @@ class Decoder {
const draco::PointAttribute &pa, const draco::PointAttribute &pa,
DracoUInt32Array *out_values); DracoUInt32Array *out_values);
// Returns uint32_t attribute values for all point ids of the point cloud.
// I.e., the |out_values| is going to contain m.num_points() entries.
static bool GetAttributeUInt32ArrayForAllPoints(
const draco::PointCloud &pc, const draco::PointAttribute &pa,
void *out_values, int out_size);
// Tells the decoder to skip an attribute transform (e.g. dequantization) for // Tells the decoder to skip an attribute transform (e.g. dequantization) for
// an attribute of a given type. // an attribute of a given type.
void SkipAttributeTransform(draco_GeometryAttribute_Type att_type); void SkipAttributeTransform(draco_GeometryAttribute_Type att_type);
@ -243,6 +275,41 @@ class Decoder {
return true; return true;
} }
template <class T>
static bool GetAttributeDataArrayForAllPoints(const draco::PointCloud &pc,
const draco::PointAttribute &pa,
const draco::DataType type,
void *out_values,
const int out_size) {
const int components = pa.num_components();
const int num_points = pc.num_points();
const int num_entries = num_points * components;
if (num_entries != out_size)
return false;
if (pa.data_type() == type && pa.is_mapping_identity()) {
// Copy values directly to the output vector.
const auto ptr = pa.GetAddress(draco::AttributeValueIndex(0));
::memcpy(out_values, ptr, num_entries * sizeof(T));
return true;
}
// Copy values one by one.
std::vector<T> values(components);
int entry_id = 0;
T *typed_output = reinterpret_cast<T *>(out_values);
for (draco::PointIndex i(0); i < num_points; ++i) {
const draco::AttributeValueIndex val_index = pa.mapped_index(i);
if (!pa.ConvertValue<T>(val_index, values.data()))
return false;
for (int j = 0; j < components; ++j) {
typed_output[entry_id++] = values[j];
}
}
return true;
}
draco::Decoder decoder_; draco::Decoder decoder_;
draco::Status last_status_; draco::Status last_status_;
}; };

View File

@ -117,42 +117,49 @@ interface DracoFloat32Array {
void DracoFloat32Array(); void DracoFloat32Array();
float GetValue(long index); float GetValue(long index);
long size(); long size();
boolean GetArray(VoidPtr out_values, long out_size);
}; };
interface DracoInt8Array { interface DracoInt8Array {
void DracoInt8Array(); void DracoInt8Array();
byte GetValue(long index); byte GetValue(long index);
long size(); long size();
boolean GetArray(VoidPtr out_values, long out_size);
}; };
interface DracoUInt8Array { interface DracoUInt8Array {
void DracoUInt8Array(); void DracoUInt8Array();
octet GetValue(long index); octet GetValue(long index);
long size(); long size();
boolean GetArray(VoidPtr out_values, long out_size);
}; };
interface DracoInt16Array { interface DracoInt16Array {
void DracoInt16Array(); void DracoInt16Array();
short GetValue(long index); short GetValue(long index);
long size(); long size();
boolean GetArray(VoidPtr out_values, long out_size);
}; };
interface DracoUInt16Array { interface DracoUInt16Array {
void DracoUInt16Array(); void DracoUInt16Array();
unsigned short GetValue(long index); unsigned short GetValue(long index);
long size(); long size();
boolean GetArray(VoidPtr out_values, long out_size);
}; };
interface DracoInt32Array { interface DracoInt32Array {
void DracoInt32Array(); void DracoInt32Array();
long GetValue(long index); long GetValue(long index);
long size(); long size();
boolean GetArray(VoidPtr out_values, long out_size);
}; };
interface DracoUInt32Array { interface DracoUInt32Array {
void DracoUInt32Array(); void DracoUInt32Array();
unsigned long GetValue(long index); unsigned long GetValue(long index);
long size(); long size();
boolean GetArray(VoidPtr out_values, long out_size);
}; };
interface MetadataQuerier { interface MetadataQuerier {
@ -202,6 +209,11 @@ interface Decoder {
long GetTriangleStripsFromMesh([Ref, Const] Mesh m, long GetTriangleStripsFromMesh([Ref, Const] Mesh m,
DracoInt32Array strip_values); DracoInt32Array strip_values);
boolean GetTrianglesUInt16Array([Ref, Const] Mesh m,
VoidPtr out_values, long out_size);
boolean GetTrianglesUInt32Array([Ref, Const] Mesh m,
VoidPtr out_values, long out_size);
boolean GetAttributeFloat([Ref, Const] PointAttribute pa, boolean GetAttributeFloat([Ref, Const] PointAttribute pa,
long att_index, long att_index,
DracoFloat32Array out_values); DracoFloat32Array out_values);
@ -209,6 +221,9 @@ interface Decoder {
boolean GetAttributeFloatForAllPoints([Ref, Const] PointCloud pc, boolean GetAttributeFloatForAllPoints([Ref, Const] PointCloud pc,
[Ref, Const] PointAttribute pa, [Ref, Const] PointAttribute pa,
DracoFloat32Array out_values); DracoFloat32Array out_values);
boolean GetAttributeFloatArrayForAllPoints([Ref, Const] PointCloud pc,
[Ref, Const] PointAttribute pa,
VoidPtr out_values, long out_size);
// Deprecated, use GetAttributeInt32ForAllPoints instead. // Deprecated, use GetAttributeInt32ForAllPoints instead.
boolean GetAttributeIntForAllPoints([Ref, Const] PointCloud pc, boolean GetAttributeIntForAllPoints([Ref, Const] PointCloud pc,
@ -221,18 +236,27 @@ interface Decoder {
boolean GetAttributeUInt8ForAllPoints([Ref, Const] PointCloud pc, boolean GetAttributeUInt8ForAllPoints([Ref, Const] PointCloud pc,
[Ref, Const] PointAttribute pa, [Ref, Const] PointAttribute pa,
DracoUInt8Array out_values); DracoUInt8Array out_values);
boolean GetAttributeUInt8ArrayForAllPoints([Ref, Const] PointCloud pc,
[Ref, Const] PointAttribute pa,
VoidPtr out_values, long out_size);
boolean GetAttributeInt16ForAllPoints([Ref, Const] PointCloud pc, boolean GetAttributeInt16ForAllPoints([Ref, Const] PointCloud pc,
[Ref, Const] PointAttribute pa, [Ref, Const] PointAttribute pa,
DracoInt16Array out_values); DracoInt16Array out_values);
boolean GetAttributeUInt16ForAllPoints([Ref, Const] PointCloud pc, boolean GetAttributeUInt16ForAllPoints([Ref, Const] PointCloud pc,
[Ref, Const] PointAttribute pa, [Ref, Const] PointAttribute pa,
DracoUInt16Array out_values); DracoUInt16Array out_values);
boolean GetAttributeUInt16ArrayForAllPoints([Ref, Const] PointCloud pc,
[Ref, Const] PointAttribute pa,
VoidPtr out_values, long out_size);
boolean GetAttributeInt32ForAllPoints([Ref, Const] PointCloud pc, boolean GetAttributeInt32ForAllPoints([Ref, Const] PointCloud pc,
[Ref, Const] PointAttribute pa, [Ref, Const] PointAttribute pa,
DracoInt32Array out_values); DracoInt32Array out_values);
boolean GetAttributeUInt32ForAllPoints([Ref, Const] PointCloud pc, boolean GetAttributeUInt32ForAllPoints([Ref, Const] PointCloud pc,
[Ref, Const] PointAttribute pa, [Ref, Const] PointAttribute pa,
DracoUInt32Array out_values); DracoUInt32Array out_values);
boolean GetAttributeUInt32ArrayForAllPoints([Ref, Const] PointCloud pc,
[Ref, Const] PointAttribute pa,
VoidPtr out_values, long out_size);
void SkipAttributeTransform(draco_GeometryAttribute_Type att_type); void SkipAttributeTransform(draco_GeometryAttribute_Type att_type);
}; };