Skip to content

Commit

Permalink
Updated snapshot to 1.3.3
Browse files Browse the repository at this point in the history
* Added ExpertEncoder to the Javascript API
  * Allows developers to set quantization options per attribute id
* Bug fixes
  • Loading branch information
ondys committed Jun 15, 2018
1 parent 83cbf6c commit c75a03b
Show file tree
Hide file tree
Showing 32 changed files with 890 additions and 623 deletions.
23 changes: 11 additions & 12 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -606,9 +606,6 @@ include_directories("${draco_root}/src" "${draco_build_dir}")
if (EMSCRIPTEN AND ENABLE_JS_GLUE)
# Draco js decoder.
require_compiler_flag("-s ALLOW_MEMORY_GROWTH=1" YES)
if (IE_COMPATIBLE)
require_compiler_flag("-s LEGACY_VM_SUPPORT=1" YES)
endif ()
require_compiler_flag("-Wno-almost-asm" YES)
require_compiler_flag("--memory-init-file 0" YES)
require_compiler_flag("-fno-omit-frame-pointer" YES)
Expand All @@ -627,11 +624,7 @@ if (EMSCRIPTEN AND ENABLE_JS_GLUE)

if (CMAKE_BUILD_TYPE STREQUAL "")
# Force -O3 when no build type is specified.
if (IE_COMPATIBLE)
add_compiler_flag_if_supported("-g")
else ()
add_compiler_flag_if_supported("-O3")
endif ()
add_compiler_flag_if_supported("-O3")
endif ()

set(draco_js_dec_idl
Expand Down Expand Up @@ -798,10 +791,16 @@ else ()
add_library(draco_points_enc OBJECT
${draco_points_common_sources}
${draco_points_enc_sources})
add_library(draco_unity_plugin OBJECT
${draco_unity_plug_sources})
add_library(draco_maya_plugin OBJECT
${draco_maya_plug_sources})

if (BUILD_UNITY_PLUGIN)
add_library(draco_unity_plugin OBJECT
${draco_unity_plug_sources})
endif ()

if (BUILD_MAYA_PLUGIN)
add_library(draco_maya_plugin OBJECT
${draco_maya_plug_sources})
endif ()

# Library targets that consume the object collections.
add_library(dracodec
Expand Down
11 changes: 5 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@

News
=======
### Version 1.3.3 release
* Added ExpertEncoder to the Javascript API
* Allows developers to set quantization options per attribute id
* Bug fixes

### Version 1.3.2 release
* Bug fixes

Expand Down Expand Up @@ -212,12 +217,6 @@ $ cmake path/to/draco -DCMAKE_TOOLCHAIN_FILE=/path/to/Emscripten.cmake
$ make
~~~~~

To build a decoder module that is compatible with IE11 (at the cost of a slightly larger resulting module), set the `IE_COMPATIBLE` variable to `true` when generating the cmake file.

~~~~~ bash
$ cmake path/to/draco -DCMAKE_TOOLCHAIN_FILE=/path/to/Emscripten.cmake -DIE_COMPATIBLE=true
~~~~~

WebAssembly Decoder
-------------------

Expand Down
27 changes: 13 additions & 14 deletions javascript/draco_decoder.js

Large diffs are not rendered by default.

Binary file modified javascript/draco_decoder.wasm
Binary file not shown.
25 changes: 12 additions & 13 deletions javascript/draco_decoder_gltf.js

Large diffs are not rendered by default.

Binary file modified javascript/draco_decoder_gltf.wasm
Binary file not shown.
29 changes: 14 additions & 15 deletions javascript/draco_encoder.js

Large diffs are not rendered by default.

248 changes: 129 additions & 119 deletions javascript/draco_wasm_wrapper.js

Large diffs are not rendered by default.

248 changes: 129 additions & 119 deletions javascript/draco_wasm_wrapper_gltf.js

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions javascript/npm/draco3d/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@

News
=======
### Version 1.3.3 release
* Added ExpertEncoder to the JavaScript API
* Allows developers to set quantization options per attribute id
* Bug fixes

### Version 1.3.2 release
* Bug fixes

Expand Down
17 changes: 9 additions & 8 deletions javascript/npm/draco3d/draco_decoder_nodejs.js

Large diffs are not rendered by default.

19 changes: 10 additions & 9 deletions javascript/npm/draco3d/draco_encoder_nodejs.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion javascript/npm/draco3d/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "draco3d",
"version": "1.3.2",
"version": "1.3.3",
"description": "Draco is a library for compressing and decompressing 3D geometric meshes and point clouds. It is intended to improve the storage and transmission of 3D graphics.",
"main": "draco3d.js",
"scripts": {
Expand Down
7 changes: 6 additions & 1 deletion javascript/npm/draco3dgltf/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,13 @@ TODO: Add glTF branch url.

News
=======
### Version 1.3.3 release
* Added ExpertEncoder to the JavaScript API
* Allows developers to set quantization options per attribute id
* Bug fixes

### Version 1.3.2 release
* Bug Fixes
* Bug fixes

### Version 1.3.1 release
* Fix issue with multiple attributes when skipping an attribute transform
Expand Down
15 changes: 8 additions & 7 deletions javascript/npm/draco3dgltf/draco_decoder_gltf_nodejs.js

Large diffs are not rendered by default.

19 changes: 10 additions & 9 deletions javascript/npm/draco3dgltf/draco_encoder_gltf_nodejs.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion javascript/npm/draco3dgltf/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "draco3dgltf",
"version": "1.3.2",
"version": "1.3.3",
"description": "This package contains a specific version of Draco 3D geometric compression library that is used for glTF Draco mesh compression extension.",
"main": "draco3dgltf.js",
"scripts": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,8 @@ class PointAttributeVectorOutputIterator {
uint32_t required_decode_bytes = 0;
for (auto index = 0; index < attributes_.size(); index++) {
const AttributeTuple &att = attributes_[index];
required_decode_bytes =
(std::max)(required_decode_bytes,
std::get<1>(att) * std::get<3>(att) * std::get<4>(att));
required_decode_bytes = (std::max)(required_decode_bytes,
std::get<3>(att) * std::get<4>(att));
}
memory_.resize(required_decode_bytes);
data_ = memory_.data();
Expand Down
2 changes: 2 additions & 0 deletions src/draco/compression/attributes/mesh_traversal_sequencer.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ class MeshTraversalSequencer : public PointsSequencer {
const PointIndex point_id = face[p];
const VertexIndex vert_id =
corner_table->Vertex(CornerIndex(3 * f.value() + p));
if (vert_id == kInvalidVertexIndex)
return false;
const AttributeValueIndex att_entry_id(
encoding_data_
->vertex_to_encoded_attribute_value_index_map[vert_id.value()]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,15 +89,17 @@ bool SequentialAttributeDecodersController::
if (GetDecoder()->options()) {
const PointAttribute *const attribute =
sequential_decoders_[i]->attribute();
if (GetDecoder()->options()->GetAttributeBool(
const PointAttribute *const portable_attribute =
sequential_decoders_[i]->GetPortableAttribute();
if (portable_attribute &&
GetDecoder()->options()->GetAttributeBool(
attribute->attribute_type(), "skip_attribute_transform", false)) {
// Attribute transform should not be performed. In this case, we replace
// the output geometry attribute with the portable attribute.
// TODO(ostava): We can potentially avoid this copy by introducing a new
// mechanism that would allow to use the final attributes as portable
// attributes for predictors that may need them.
sequential_decoders_[i]->attribute()->CopyFrom(
*sequential_decoders_[i]->GetPortableAttribute());
sequential_decoders_[i]->attribute()->CopyFrom(*portable_attribute);
continue;
}
}
Expand Down
43 changes: 43 additions & 0 deletions src/draco/compression/decode_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -150,4 +150,47 @@ TEST_F(DecodeTest, TestSkipAttributeTransformOnPointCloud) {
TestSkipAttributeTransformOnPointCloudWithColor("pc_kd_color.drc");
}

TEST_F(DecodeTest, TestSkipAttributeTransformWithNoQuantization) {
// Tests that decoders can successfully skip attribute transform even though
// the input model was not quantized (it has no attribute transform).
const std::string file_name = "point_cloud_no_qp.drc";
std::ifstream input_file(draco::GetTestFileFullPath(file_name),
std::ios::binary);
ASSERT_TRUE(input_file);

// Read the file stream into a buffer.
std::streampos file_size = 0;
input_file.seekg(0, std::ios::end);
file_size = input_file.tellg() - file_size;
input_file.seekg(0, std::ios::beg);
std::vector<char> data(file_size);
input_file.read(data.data(), file_size);

ASSERT_FALSE(data.empty());

// Create a draco decoding buffer. Note that no data is copied in this step.
draco::DecoderBuffer buffer;
buffer.Init(data.data(), data.size());

draco::Decoder decoder;
// Make sure we skip dequantization for the position attribute.
decoder.SetSkipAttributeTransform(draco::GeometryAttribute::POSITION);

// Decode the input data into a geometry.
std::unique_ptr<draco::PointCloud> pc =
decoder.DecodePointCloudFromBuffer(&buffer).value();
ASSERT_NE(pc, nullptr);

const draco::PointAttribute *const pos_att =
pc->GetNamedAttribute(draco::GeometryAttribute::POSITION);
ASSERT_NE(pos_att, nullptr);

// Ensure the position attribute is of type float32 since the attribute was
// not quantized.
ASSERT_EQ(pos_att->data_type(), draco::DT_FLOAT32);

// Make sure there is no attribute transform available for the attribute.
ASSERT_EQ(pos_att->GetAttributeTransformData(), nullptr);
}

} // namespace
15 changes: 10 additions & 5 deletions src/draco/compression/encode_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ class EncodeTest : public ::testing::Test {

// Initialize the attribute values.
for (draco::PointIndex i(0); i < kNumPoints; ++i) {
const float pos_coord = float(i.value());
const float pos_coord = static_cast<float>(i.value());
pc_builder.SetAttributeValueForPoint(
pos_att_id, i,
draco::Vector3f(pos_coord, -pos_coord, pos_coord).data());
Expand Down Expand Up @@ -148,15 +148,20 @@ class EncodeTest : public ::testing::Test {
std::unique_ptr<draco::Mesh> mesh_tmp =
draco::ReadMeshFromTestFile(file_name);
mesh = mesh_tmp.get();
if (!mesh->DeduplicateAttributeValues())
return;
mesh->DeduplicatePointIds();
geometry = std::move(mesh_tmp);
} else {
geometry = draco::ReadPointCloudFromTestFile(file_name);
}
ASSERT_NE(mesh, nullptr);

draco::Encoder encoder;
encoder.SetAttributeQuantization(draco::GeometryAttribute::POSITION, 16);
encoder.SetAttributeQuantization(draco::GeometryAttribute::TEX_COORD, 15);
encoder.SetAttributeQuantization(draco::GeometryAttribute::NORMAL, 14);
encoder.SetAttributeQuantization(draco::GeometryAttribute::POSITION, 14);
encoder.SetAttributeQuantization(draco::GeometryAttribute::TEX_COORD, 12);
encoder.SetAttributeQuantization(draco::GeometryAttribute::NORMAL, 10);

encoder.SetEncodingMethod(encoding_method);

encoder.SetTrackEncodedProperties(true);
Expand Down Expand Up @@ -272,7 +277,7 @@ TEST_F(EncodeTest, TestTrackingOfNumberOfEncodedEntries) {

TEST_F(EncodeTest, TestTrackingOfNumberOfEncodedEntriesNotSet) {
// Tests that when tracing of encoded properties is disabled, the returned
// number of encoded faces and poitns is 0.
// number of encoded faces and points is 0.
std::unique_ptr<draco::Mesh> mesh(
draco::ReadMeshFromTestFile("cube_att.obj"));
ASSERT_NE(mesh, nullptr);
Expand Down
44 changes: 38 additions & 6 deletions src/draco/compression/mesh/mesh_edgebreaker_encoder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,20 @@ void MeshEdgeBreakerEncoder::ComputeNumberOfEncodedPoints() {
corner_table->num_vertices() - corner_table->NumIsolatedVertices();

if (mesh()->num_attributes() > 1) {
// Gather all corner tables for all non-position attributes.
std::vector<const MeshAttributeCornerTable *> attribute_corner_tables;
for (int i = 0; i < mesh()->num_attributes(); ++i) {
if (mesh()->attribute(i)->attribute_type() == GeometryAttribute::POSITION)
continue;
const MeshAttributeCornerTable *const att_corner_table =
GetAttributeCornerTable(i);
// Attribute corner table may not be used in some configurations. For
// these cases we can assume the attribute connectivity to be the same as
// the connectivity of the position data.
if (att_corner_table)
attribute_corner_tables.push_back(att_corner_table);
}

// Add a new point based on the configuration of interior attribute seams
// (replicating what the decoder would do).
for (VertexIndex vi(0); vi < corner_table->num_vertices(); ++vi) {
Expand All @@ -107,22 +121,40 @@ void MeshEdgeBreakerEncoder::ComputeNumberOfEncodedPoints() {
mesh()->CornerToPointId(first_corner_index);

PointIndex last_point_index = first_point_index;
CornerIndex last_corner_index = first_corner_index;
CornerIndex corner_index = corner_table->SwingRight(first_corner_index);
size_t num_attribute_seams = 0;
while (corner_index != kInvalidCornerIndex &&
corner_index != first_corner_index) {
while (corner_index != kInvalidCornerIndex) {
const PointIndex point_index = mesh()->CornerToPointId(corner_index);
bool seam_found = false;
if (point_index != last_point_index) {
// New attribute seam detected.
++num_attribute_seams;
// Point index changed - new attribute seam detected.
seam_found = true;
last_point_index = point_index;
} else {
// Even though point indices matches, there still may be a seam caused
// by non-manifold connectivity of non-position attribute data.
for (int i = 0; i < attribute_corner_tables.size(); ++i) {
if (attribute_corner_tables[i]->Vertex(corner_index) !=
attribute_corner_tables[i]->Vertex(last_corner_index)) {
seam_found = true;
break; // No need to process other attributes.
}
}
}
if (seam_found) {
++num_attribute_seams;
}

if (corner_index == first_corner_index)
break;

// Proceed to the next corner
last_corner_index = corner_index;
corner_index = corner_table->SwingRight(corner_index);
}

if (!corner_table->IsOnBoundary(vi) && num_attribute_seams > 0 &&
last_point_index == first_point_index) {
if (!corner_table->IsOnBoundary(vi) && num_attribute_seams > 0) {
// If the last visited point index is the same as the first point index
// we traveled all the way around the vertex. In this case the number of
// new points should be num_attribute_seams - 1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,34 @@ TEST_F(PointCloudKdTreeEncodingTest,
TestKdTreeEncoding(*pc);
}

// Test 16 only encoding for one attribute.
TEST_F(PointCloudKdTreeEncodingTest, TestIntKdTreeEncoding16Bit) {
constexpr int num_points = 120;
std::vector<std::array<uint16_t, 3>> points3(num_points);
for (int i = 0; i < num_points; ++i) {
std::array<uint16_t, 3> pos;
// Generate some pseudo-random points.
pos[0] = 8 * ((i * 7) % 127);
pos[1] = 13 * ((i * 3) % 321);
pos[2] = 29 * ((i * 19) % 450);
points3[i] = pos;
}

PointCloudBuilder builder;
builder.Start(num_points);
const int att_id3 =
builder.AddAttribute(GeometryAttribute::POSITION, 3, DT_UINT16);
for (PointIndex i(0); i < num_points; ++i) {
builder.SetAttributeValueForPoint(att_id3, PointIndex(i),
&(points3[i.value()])[0]);
}

std::unique_ptr<PointCloud> pc = builder.Finalize(false);
ASSERT_NE(pc, nullptr);

TestKdTreeEncoding(*pc);
}

// Test 16 and 8 bit encoding with size bigger than 32bit encoding.
TEST_F(PointCloudKdTreeEncodingTest,
TestIntKdTreeEncodingHigherDimensionVariedTypesBig16BitEncoding) {
Expand Down
2 changes: 1 addition & 1 deletion src/draco/core/draco_version.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
namespace draco {

// Draco version is comprised of <major>.<minor>.<revision>.
static const char kDracoVersion[] = "1.3.2";
static const char kDracoVersion[] = "1.3.3";

const char *Version() { return kDracoVersion; }

Expand Down
22 changes: 22 additions & 0 deletions src/draco/javascript/emscripten/draco_web_encoder.idl
Original file line number Diff line number Diff line change
Expand Up @@ -180,3 +180,25 @@ interface Encoder {
long GetNumberOfEncodedPoints();
long GetNumberOfEncodedFaces();
};

interface ExpertEncoder {
void ExpertEncoder(PointCloud pc);
void SetEncodingMethod(long method);
void SetAttributeQuantization(long att_id,
long quantization_bits);
void SetAttributeExplicitQuantization(long att_id,
long quantization_bits,
long num_components,
[Const] float[] origin,
float range);
void SetSpeedOptions(long encoding_speed, long decoding_speed);
void SetTrackEncodedProperties(boolean flag);

long EncodeToDracoBuffer(boolean deduplicate_values,
DracoInt8Array encoded_data);

// Returns the number of encoded points or faces from the last Encode
// operation. Returns 0 if SetTrackEncodedProperties was not set to true.
long GetNumberOfEncodedPoints();
long GetNumberOfEncodedFaces();
};
Loading

0 comments on commit c75a03b

Please sign in to comment.