Optimize three.js rendering and other small fixes.

1. Optimize loading of mesh data into three.js in Chrome.
2. Small refactoring of our traversal encoding code.
This commit is contained in:
Frank Galligan 2017-02-16 17:27:56 -08:00
parent ef36ca97ed
commit a282c3ed5b
13 changed files with 183 additions and 109 deletions

View File

@ -350,19 +350,20 @@ set(draco_point_cloud_sources
"${draco_root}/point_cloud/point_cloud_builder.h")
set(draco_points_common_sources
"${draco_root}/compression/point_cloud/algorithms/point_cloud_compression_method.h"
"${draco_root}/compression/point_cloud/algorithms/point_cloud_types.h"
"${draco_root}/compression/point_cloud/algorithms/quantize_points_3.h"
"${draco_root}/compression/point_cloud/algorithms/queuing_policy.h")
set(draco_points_decoder_sources
"${draco_root}/compression/point_cloud/algorithms/float_points_kd_tree_decoder.cc"
"${draco_root}/compression/point_cloud/algorithms/float_points_kd_tree_decoder.h"
"${draco_root}/compression/point_cloud/algorithms/float_points_tree_decoder.cc"
"${draco_root}/compression/point_cloud/algorithms/float_points_tree_decoder.h"
"${draco_root}/compression/point_cloud/algorithms/integer_points_kd_tree_decoder.cc"
"${draco_root}/compression/point_cloud/algorithms/integer_points_kd_tree_decoder.h")
set(draco_points_encoder_sources
"${draco_root}/compression/point_cloud/algorithms/float_points_kd_tree_encoder.cc"
"${draco_root}/compression/point_cloud/algorithms/float_points_kd_tree_encoder.h"
"${draco_root}/compression/point_cloud/algorithms/float_points_tree_encoder.cc"
"${draco_root}/compression/point_cloud/algorithms/float_points_tree_encoder.h"
"${draco_root}/compression/point_cloud/algorithms/integer_points_kd_tree_encoder.cc"
"${draco_root}/compression/point_cloud/algorithms/integer_points_kd_tree_encoder.h")

View File

@ -218,15 +218,15 @@ MESH_ATTRIBUTE_CORNER_TABLE_OBJS := mesh/mesh_attribute_corner_table.o
MESH_MISC_A := libmesh_misc.a
MESH_MISC_OBJS := mesh/mesh_misc_functions.o
FLOAT_POINTS_KD_TREE_DECODER_A := \
libfloat_points_kd_tree_decoder.a
FLOAT_POINTS_KD_TREE_DECODER_OBJS := \
compression/point_cloud/algorithms/float_points_kd_tree_decoder.o
FLOAT_POINTS_TREE_DECODER_A := \
libfloat_points_tree_decoder.a
FLOAT_POINTS_TREE_DECODER_OBJS := \
compression/point_cloud/algorithms/float_points_tree_decoder.o
FLOAT_POINTS_KD_TREE_ENCODER_A := \
libfloat_points_kd_tree_encoder.a
FLOAT_POINTS_KD_TREE_ENCODER_OBJS := \
compression/point_cloud/algorithms/float_points_kd_tree_encoder.o
FLOAT_POINTS_TREE_ENCODER_A := \
libfloat_points_tree_encoder.a
FLOAT_POINTS_TREE_ENCODER_OBJS := \
compression/point_cloud/algorithms/float_points_tree_encoder.o
INTEGER_POINTS_KD_TREE_DECODER_A := \
libinteger_points_kd_tree_decoder.a
@ -330,10 +330,10 @@ MESH_IO_OBJSA := $(addprefix $(OBJDIR)/,$(MESH_IO_OBJS:.o=_a.o))
PLY_ENCODER_OBJSA := $(addprefix $(OBJDIR)/,$(PLY_ENCODER_OBJS:.o=_a.o))
PLY_DECODER_OBJSA := $(addprefix $(OBJDIR)/,$(PLY_DECODER_OBJS:.o=_a.o))
FLOAT_POINTS_KD_TREE_DECODER_OBJSA := \
$(addprefix $(OBJDIR)/,$(FLOAT_POINTS_KD_TREE_DECODER_OBJS:.o=_a.o))
FLOAT_POINTS_KD_TREE_ENCODER_OBJSA := \
$(addprefix $(OBJDIR)/,$(FLOAT_POINTS_KD_TREE_ENCODER_OBJS:.o=_a.o))
FLOAT_POINTS_TREE_DECODER_OBJSA := \
$(addprefix $(OBJDIR)/,$(FLOAT_POINTS_TREE_DECODER_OBJS:.o=_a.o))
FLOAT_POINTS_TREE_ENCODER_OBJSA := \
$(addprefix $(OBJDIR)/,$(FLOAT_POINTS_TREE_ENCODER_OBJS:.o=_a.o))
INTEGER_POINTS_KD_TREE_DECODER_OBJSA := \
$(addprefix $(OBJDIR)/,$(INTEGER_POINTS_KD_TREE_DECODER_OBJS:.o=_a.o))
INTEGER_POINTS_KD_TREE_ENCODER_OBJSA := \
@ -370,7 +370,7 @@ DRACO_ENCODER_OBJSA += $(SEQUENTIAL_ATTRIBUTE_ENCODERS_CONTROLLER_OBJSA)
DRACO_ENCODER_OBJSA += $(POINT_CLOUD_SEQUENTIAL_ENCODER_OBJSA)
DRACO_ENCODER_OBJSA += $(POINT_CLOUD_KD_TREE_ENCODER_OBJSA)
DRACO_ENCODER_OBJSA += $(KD_TREE_ATTRIBUTES_ENCODER_OBJSA)
DRACO_ENCODER_OBJSA += $(FLOAT_POINTS_KD_TREE_ENCODER_OBJSA)
DRACO_ENCODER_OBJSA += $(FLOAT_POINTS_TREE_ENCODER_OBJSA)
DRACO_ENCODER_OBJSA += $(INTEGER_POINTS_KD_TREE_ENCODER_OBJSA)
DRACO_ENCODER_OBJSA += $(MESH_SEQUENTIAL_ENCODER_OBJSA)
DRACO_ENCODER_OBJSA += $(MESH_EDGEBREAKER_ENCODER_OBJSA)
@ -389,7 +389,7 @@ DRACO_DECODER_OBJSA += $(SEQUENTIAL_ATTRIBUTE_DECODERS_CONTROLLER_OBJSA)
DRACO_DECODER_OBJSA += $(POINT_CLOUD_SEQUENTIAL_DECODER_OBJSA)
DRACO_DECODER_OBJSA += $(POINT_CLOUD_KD_TREE_DECODER_OBJSA)
DRACO_DECODER_OBJSA += $(KD_TREE_ATTRIBUTES_DECODER_OBJSA)
DRACO_DECODER_OBJSA += $(FLOAT_POINTS_KD_TREE_DECODER_OBJSA)
DRACO_DECODER_OBJSA += $(FLOAT_POINTS_TREE_DECODER_OBJSA)
DRACO_DECODER_OBJSA += $(INTEGER_POINTS_KD_TREE_DECODER_OBJSA)
DRACO_DECODER_OBJSA += $(MESH_SEQUENTIAL_DECODER_OBJSA)
DRACO_DECODER_OBJSA += $(MESH_EDGEBREAKER_DECODER_OBJSA)
@ -455,8 +455,8 @@ LIBS += $(LIBDIR)/libdecoder_buffer.a
LIBS += $(LIBDIR)/libencoder_buffer.a
LIBS += $(LIBDIR)/libcycle_timer.a
POINTS_LIBS := $(LIBDIR)/libfloat_points_kd_tree_decoder.a
POINTS_LIBS += $(LIBDIR)/libfloat_points_kd_tree_encoder.a
POINTS_LIBS := $(LIBDIR)/libfloat_points_tree_decoder.a
POINTS_LIBS += $(LIBDIR)/libfloat_points_tree_encoder.a
POINTS_LIBS += $(LIBDIR)/libinteger_points_kd_tree_decoder.a
POINTS_LIBS += $(LIBDIR)/libinteger_points_kd_tree_encoder.a
POINTS_LIBS += $(LIBDIR)/libdirect_bit_coding.a
@ -609,10 +609,10 @@ $(LIBDIR)/libply_encoder.a: $(PLY_ENCODER_OBJSA)
$(LIBDIR)/libply_decoder.a: $(PLY_DECODER_OBJSA)
$(AR) rcs $@ $^
$(LIBDIR)/libfloat_points_kd_tree_decoder.a: $(FLOAT_POINTS_KD_TREE_DECODER_OBJSA)
$(LIBDIR)/libfloat_points_tree_decoder.a: $(FLOAT_POINTS_TREE_DECODER_OBJSA)
$(AR) rcs $@ $^
$(LIBDIR)/libfloat_points_kd_tree_encoder.a: $(FLOAT_POINTS_KD_TREE_ENCODER_OBJSA)
$(LIBDIR)/libfloat_points_tree_encoder.a: $(FLOAT_POINTS_TREE_ENCODER_OBJSA)
$(AR) rcs $@ $^
$(LIBDIR)/libinteger_points_kd_tree_decoder.a: \

View File

@ -14,7 +14,7 @@
//
#include "compression/attributes/kd_tree_attributes_decoder.h"
#include "compression/attributes/kd_tree_attributes_shared.h"
#include "compression/point_cloud/algorithms/float_points_kd_tree_decoder.h"
#include "compression/point_cloud/algorithms/float_points_tree_decoder.h"
#include "compression/point_cloud/algorithms/integer_points_kd_tree_decoder.h"
#include "compression/point_cloud/point_cloud_decoder.h"
@ -68,7 +68,7 @@ bool KdTreeAttributesDecoder::DecodeAttributes(DecoderBuffer *in_buffer) {
if (!in_buffer->Decode(&num_points))
return false;
att->Reset(num_points);
FloatPointsKdTreeDecoder decoder;
FloatPointsTreeDecoder decoder;
PointAttributeVectorOutputIterator<float, 3> out_it(att);
if (!decoder.DecodePointCloud(in_buffer, out_it))
return false;

View File

@ -14,7 +14,7 @@
//
#include "compression/attributes/kd_tree_attributes_encoder.h"
#include "compression/attributes/kd_tree_attributes_shared.h"
#include "compression/point_cloud/algorithms/float_points_kd_tree_encoder.h"
#include "compression/point_cloud/algorithms/float_points_tree_encoder.h"
#include "compression/point_cloud/algorithms/integer_points_kd_tree_encoder.h"
#include "compression/point_cloud/point_cloud_encoder.h"
@ -93,8 +93,8 @@ bool KdTreeAttributesEncoder::EncodeAttributes(EncoderBuffer *out_buffer) {
out_buffer->Encode(
static_cast<uint32_t>(encoder()->point_cloud()->num_points()));
typedef PointAttributeVectorIterator<float, 3> AttributeIterator;
FloatPointsKdTreeEncoder points_encoder(quantization_bits,
compression_level);
FloatPointsTreeEncoder points_encoder(KDTREE, quantization_bits,
compression_level);
if (!points_encoder.EncodePointCloud(
AttributeIterator(att),
AttributeIterator(att) + encoder()->point_cloud()->num_points()))

View File

@ -85,9 +85,6 @@ class MeshTraversalSequencer : public PointsSequencer {
private:
void ProcessCorner(CornerIndex corner_id) {
const FaceIndex face_id(corner_id.value() / 3);
if (traverser_.traversal_processor().IsFaceVisited(face_id))
return;
traverser_.TraverseFromCorner(corner_id);
}

View File

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//
#include "compression/point_cloud/algorithms/float_points_kd_tree_decoder.h"
#include "compression/point_cloud/algorithms/float_points_tree_decoder.h"
#include <algorithm>
@ -23,24 +23,14 @@
namespace draco {
FloatPointsKdTreeDecoder::FloatPointsKdTreeDecoder()
FloatPointsTreeDecoder::FloatPointsTreeDecoder()
: num_points_(0), compression_level_(0) {
qinfo_.quantization_bits = 0;
qinfo_.range = 0;
}
bool FloatPointsKdTreeDecoder::DecodePointCloudInternal(
bool FloatPointsTreeDecoder::DecodePointCloudKdTreeInternal(
DecoderBuffer *buffer, std::vector<Point3ui> *qpoints) {
uint32_t decoded_version;
if (!buffer->Decode(&decoded_version))
return false;
if (decoded_version != version()) {
fprintf(stderr,
"Version not supported, did you try to load an old file? \n");
return false;
}
if (!buffer->Decode(&qinfo_.quantization_bits))
return false;
if (!buffer->Decode(&qinfo_.range))
@ -125,4 +115,5 @@ bool FloatPointsKdTreeDecoder::DecodePointCloudInternal(
return true;
}
} // namespace draco

View File

@ -12,21 +12,22 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//
#ifndef DRACO_COMPRESSION_POINT_CLOUD_ALGORITHMS_FLOAT_POINTS_KD_TREE_DECODER_H_
#define DRACO_COMPRESSION_POINT_CLOUD_ALGORITHMS_FLOAT_POINTS_KD_TREE_DECODER_H_
#ifndef DRACO_COMPRESSION_POINT_CLOUD_ALGORITHMS_FLOAT_POINTS_TREE_DECODER_H_
#define DRACO_COMPRESSION_POINT_CLOUD_ALGORITHMS_FLOAT_POINTS_TREE_DECODER_H_
#include <memory>
#include "compression/point_cloud/algorithms/point_cloud_compression_method.h"
#include "compression/point_cloud/algorithms/point_cloud_types.h"
#include "compression/point_cloud/algorithms/quantize_points_3.h"
#include "core/decoder_buffer.h"
namespace draco {
// Decodes a point cloud encoded by PointCloudKdTreeEncoder.
class FloatPointsKdTreeDecoder {
// Decodes a point cloud encoded by PointCloudTreeEncoder.
class FloatPointsTreeDecoder {
public:
FloatPointsKdTreeDecoder();
FloatPointsTreeDecoder();
// Decodes a point cloud from |buffer|.
template <class OutputIteratorT>
@ -48,34 +49,54 @@ class FloatPointsKdTreeDecoder {
float range() const { return qinfo_.range; }
uint32_t num_points() const { return num_points_; }
uint32_t version() const { return version_; }
std::string identification_string() const {
return "FloatPointsKdTreeDecoder";
}
std::string identification_string() const { return "FloatPointsTreeDecoder"; }
private:
bool DecodePointCloudInternal(DecoderBuffer *buffer,
std::vector<Point3ui> *qpoints);
bool DecodePointCloudKdTreeInternal(DecoderBuffer *buffer,
std::vector<Point3ui> *qpoints);
static const uint32_t version_ = 2;
static const uint32_t version_ = 3;
QuantizationInfo qinfo_;
uint32_t num_points_;
uint32_t compression_level_;
};
template <class OutputIteratorT>
bool FloatPointsKdTreeDecoder::DecodePointCloud(DecoderBuffer *buffer,
OutputIteratorT out)
{
bool FloatPointsTreeDecoder::DecodePointCloud(DecoderBuffer *buffer,
OutputIteratorT out) {
std::vector<Point3ui> qpoints;
if (!DecodePointCloudInternal(buffer, &qpoints))
uint32_t decoded_version;
if (!buffer->Decode(&decoded_version))
return false;
DequantizePoints3(qpoints.begin(), qpoints.end(), qinfo_, out);
if (decoded_version == 3) {
int8_t method_number;
if (!buffer->Decode(&method_number))
return false;
const PointCloudCompressionMethod method =
static_cast<PointCloudCompressionMethod>(method_number);
if (method == KDTREE) {
if (!DecodePointCloudKdTreeInternal(buffer, &qpoints))
return false;
} else { // Unsupported method.
fprintf(stderr, "Method not supported. \n");
return false;
}
} else if (decoded_version == 2) { // Version 2 only uses KDTREE method.
if (!DecodePointCloudKdTreeInternal(buffer, &qpoints))
return false;
} else { // Unsupported version.
fprintf(stderr, "Version not supported. \n");
return false;
}
DequantizePoints3(qpoints.begin(), qpoints.end(), qinfo_, out);
return true;
}
} // namespace draco
#endif // DRACO_COMPRESSION_POINT_CLOUD_ALGORITHMS_FLOAT_POINTS_KD_TREE_DECODER_H_
#endif // DRACO_COMPRESSION_POINT_CLOUD_ALGORITHMS_FLOAT_POINTS_TREE_DECODER_H_

View File

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//
#include "compression/point_cloud/algorithms/float_points_kd_tree_encoder.h"
#include "compression/point_cloud/algorithms/float_points_tree_encoder.h"
#include <algorithm>
#include <cmath>
@ -22,23 +22,25 @@
namespace draco {
const uint32_t FloatPointsKdTreeEncoder::version_ = 2;
const uint32_t FloatPointsTreeEncoder::version_ = 3;
FloatPointsKdTreeEncoder::FloatPointsKdTreeEncoder()
: num_points_(0), compression_level_(8) {
FloatPointsTreeEncoder::FloatPointsTreeEncoder(
PointCloudCompressionMethod method)
: method_(method), num_points_(0), compression_level_(8) {
qinfo_.quantization_bits = 16;
qinfo_.range = 0;
}
FloatPointsKdTreeEncoder::FloatPointsKdTreeEncoder(uint32_t quantization_bits,
uint32_t compression_level)
: num_points_(0), compression_level_(compression_level) {
FloatPointsTreeEncoder::FloatPointsTreeEncoder(
PointCloudCompressionMethod method, uint32_t quantization_bits,
uint32_t compression_level)
: method_(method), num_points_(0), compression_level_(compression_level) {
DCHECK_LE(compression_level_, 10);
qinfo_.quantization_bits = quantization_bits;
qinfo_.range = 0;
}
bool FloatPointsKdTreeEncoder::EncodePointCloudInternal(
bool FloatPointsTreeEncoder::EncodePointCloudKdTreeInternal(
std::vector<Point3ui> *qpoints) {
DCHECK_LE(compression_level_, 10);
switch (compression_level_) {
@ -113,4 +115,5 @@ bool FloatPointsKdTreeEncoder::EncodePointCloudInternal(
return true;
}
} // namespace draco

View File

@ -12,12 +12,13 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//
#ifndef DRACO_COMPRESSION_POINT_CLOUD_ALGORITHMS_FLOAT_POINTS_KD_TREE_ENCODER_H_
#define DRACO_COMPRESSION_POINT_CLOUD_ALGORITHMS_FLOAT_POINTS_KD_TREE_ENCODER_H_
#ifndef DRACO_COMPRESSION_POINT_CLOUD_ALGORITHMS_FLOAT_POINTS_TREE_ENCODER_H_
#define DRACO_COMPRESSION_POINT_CLOUD_ALGORITHMS_FLOAT_POINTS_TREE_ENCODER_H_
#include <memory>
#include <vector>
#include "compression/point_cloud/algorithms/point_cloud_compression_method.h"
#include "compression/point_cloud/algorithms/point_cloud_types.h"
#include "compression/point_cloud/algorithms/quantize_points_3.h"
#include "core/encoder_buffer.h"
@ -44,11 +45,12 @@ namespace draco {
// arithmetic encoding.
// TODO(hemmer): Remove class because it duplicates quantization code.
class FloatPointsKdTreeEncoder {
class FloatPointsTreeEncoder {
public:
FloatPointsKdTreeEncoder();
explicit FloatPointsKdTreeEncoder(uint32_t quantization_bits,
uint32_t compression_level);
FloatPointsTreeEncoder(PointCloudCompressionMethod method);
explicit FloatPointsTreeEncoder(PointCloudCompressionMethod method,
uint32_t quantization_bits,
uint32_t compression_level);
template <class InputIteratorT>
bool EncodePointCloud(InputIteratorT points_begin, InputIteratorT points_end);
@ -61,24 +63,23 @@ class FloatPointsKdTreeEncoder {
uint32_t &compression_level() { return compression_level_; }
float range() const { return qinfo_.range; }
uint32_t num_points() const { return num_points_; }
std::string identification_string() const {
return "FloatPointsKdTreeEncoder";
}
std::string identification_string() const { return "FloatPointsTreeEncoder"; }
private:
void Clear() { buffer_.Clear(); }
bool EncodePointCloudInternal(std::vector<Point3ui> *qpoints);
bool EncodePointCloudKdTreeInternal(std::vector<Point3ui> *qpoints);
static const uint32_t version_;
QuantizationInfo qinfo_;
PointCloudCompressionMethod method_;
uint32_t num_points_;
EncoderBuffer buffer_;
uint32_t compression_level_;
};
template <class InputIteratorT>
bool FloatPointsKdTreeEncoder::EncodePointCloud(InputIteratorT points_begin,
InputIteratorT points_end) {
bool FloatPointsTreeEncoder::EncodePointCloud(InputIteratorT points_begin,
InputIteratorT points_end) {
Clear();
// Collect necessary data for encoding.
@ -93,15 +94,25 @@ bool FloatPointsKdTreeEncoder::EncodePointCloud(InputIteratorT points_begin,
// Encode header.
buffer()->Encode(version_);
buffer()->Encode(static_cast<int8_t>(method_));
buffer()->Encode(qinfo_.quantization_bits);
buffer()->Encode(qinfo_.range);
buffer()->Encode(num_points_);
buffer()->Encode(compression_level_);
if (method_ == KDTREE)
buffer()->Encode(compression_level_);
if (num_points_ == 0)
return true;
return EncodePointCloudInternal(&qpoints);
if (method_ == KDTREE) {
return EncodePointCloudKdTreeInternal(&qpoints);
} else { // Unsupported method.
fprintf(stderr, "Method not supported. \n");
return false;
}
}
} // namespace draco
#endif // DRACO_COMPRESSION_POINT_CLOUD_ALGORITHMS_FLOAT_POINTS_KD_TREE_ENCODER_H_
#endif // DRACO_COMPRESSION_POINT_CLOUD_ALGORITHMS_FLOAT_POINTS_TREE_ENCODER_H_

View File

@ -0,0 +1,33 @@
// Copyright 2016 The Draco Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#ifndef DRACO_COMPRESSION_POINT_CLOUD_ALGORITHMS_POINT_CLOUD_COMPRESSION_METHOD_H_
#define DRACO_COMPRESSION_POINT_CLOUD_ALGORITHMS_POINT_CLOUD_COMPRESSION_METHOD_H_
namespace draco {
// Enum indicating the used compression method, used by Encoder and Decoder.
enum PointCloudCompressionMethod {
RESERVED_POINT_CLOUD_METHOD_0 = 0, // Reserved for internal use.
// Generalized version of Encoding using the Octree method by Olivier
// Devillers to d dimensions.
// "Progressive lossless compression of arbitrary simplicial complexes"
// http://dx.doi.org/10.1145/566570.566591
KDTREE,
RESERVED_POINT_CLOUD_METHOD_1, // Reserved for internal use.
};
} // namespace draco
#endif // DRACO_COMPRESSION_POINT_CLOUD_ALGORITHMS_POINT_CLOUD_COMPRESSION_METHOD_H_

View File

@ -66,11 +66,13 @@ THREE.DRACOLoader.prototype = {
convertDracoGeometryTo3JS: function(wrapper, geometryType, buffer) {
let dracoGeometry;
const start_time = performance.now();
if (geometryType == DracoModule.TRIANGULAR_MESH) {
dracoGeometry = wrapper.DecodeMeshFromBuffer(buffer);
} else {
dracoGeometry = wrapper.DecodePointCloudFromBuffer(buffer);
}
const decode_end = performance.now();
DracoModule.destroy(buffer);
/*
* Example on how to retrieve mesh and attributes.
@ -147,43 +149,43 @@ THREE.DRACOLoader.prototype = {
}
// Structure for converting to THREEJS geometry later.
const numIndices = numFaces * 3;
const geometryBuffer = {
indices: [],
vertices: [],
normals: [],
uvs: [],
colors: []
indices: new Uint32Array(numIndices),
vertices: new Float32Array(numVertexCoordinates),
normals: new Float32Array(numVertexCoordinates),
uvs: new Float32Array(numTextureCoordinates),
colors: new Float32Array(numVertexCoordinates)
};
for (let i = 0; i < numVertexCoordinates; i += 3) {
geometryBuffer.vertices.push(
posAttributeData.GetValue(i),
posAttributeData.GetValue(i + 1),
posAttributeData.GetValue(i + 2));
geometryBuffer.vertices[i] = posAttributeData.GetValue(i);
geometryBuffer.vertices[i + 1] = posAttributeData.GetValue(i + 1);
geometryBuffer.vertices[i + 2] = posAttributeData.GetValue(i + 2);
// Add color.
if (colorAttId != -1) {
geometryBuffer.colors.push(
colAttributeData.GetValue(i),
colAttributeData.GetValue(i + 1),
colAttributeData.GetValue(i + 2));
geometryBuffer.colors[i] = colAttributeData.GetValue(i);
geometryBuffer.colors[i + 1] = colAttributeData.GetValue(i + 1);
geometryBuffer.colors[i + 2] = colAttributeData.GetValue(i + 2);
} else {
// Default is white.
geometryBuffer.colors.push(1.0, 1.0, 1.0);
// Default is white. This is faster than TypedArray.fill().
geometryBuffer.colors[i] = 1.0;
geometryBuffer.colors[i + 1] = 1.0;
geometryBuffer.colors[i + 2] = 1.0;
}
// Add normal.
if (normalAttId != -1) {
geometryBuffer.normals.push(
norAttributeData.GetValue(i),
norAttributeData.GetValue(i + 1),
norAttributeData.GetValue(i + 2));
geometryBuffer.normals[i] = norAttributeData.GetValue(i);
geometryBuffer.normals[i + 1] = norAttributeData.GetValue(i + 1);
geometryBuffer.normals[i + 2] = norAttributeData.GetValue(i + 2);
}
}
// Add texture coordinates.
if (texCoordAttId != -1) {
for (let i = 0; i < numTextureCoordinates; i += 2) {
geometryBuffer.uvs.push(
textCoordAttributeData.GetValue(i),
textCoordAttributeData.GetValue(i + 1));
geometryBuffer.uvs[i] = textCoordAttributeData.GetValue(i);
geometryBuffer.uvs[i + 1] = textCoordAttributeData.GetValue(i + 1);
}
}
@ -197,12 +199,13 @@ THREE.DRACOLoader.prototype = {
// For mesh, we need to generate the faces.
if (geometryType == DracoModule.TRIANGULAR_MESH) {
const numIndices = numFaces * 3;
const ia = new DracoInt32Array();
for (let i = 0; i < numFaces; ++i) {
wrapper.GetFaceFromMesh(dracoGeometry, i, ia);
geometryBuffer.indices.push(
ia.GetValue(0), ia.GetValue(1), ia.GetValue(2));
const index = i * 3;
geometryBuffer.indices[index] = ia.GetValue(0);
geometryBuffer.indices[index + 1] = ia.GetValue(1);
geometryBuffer.indices[index + 2] = ia.GetValue(2);
}
DracoModule.destroy(ia);
}
@ -230,6 +233,9 @@ THREE.DRACOLoader.prototype = {
geometry.addAttribute('uv',
new THREE.Float32BufferAttribute(geometryBuffer.uvs, 2));
}
fileDisplayArea.innerText += ' decode:' + (decode_end - start_time);
fileDisplayArea.innerText +=
' import:' + (performance.now() - decode_end);
return geometry;
}
};

View File

@ -44,6 +44,14 @@ class CornerTableTraversalProcessor {
return true; // Invalid faces are always considered as visited.
return is_face_visited_[face_id.value()];
}
// Returns true if the face containing the given corner was visited.
inline bool IsFaceVisited(CornerIndex corner_id) const {
if (corner_id < 0)
return true; // Invalid faces are always considered as visited.
return is_face_visited_[corner_id.value() / 3];
}
inline void MarkFaceVisited(FaceIndex face_id) {
is_face_visited_[face_id.value()] = true;
}

View File

@ -99,6 +99,9 @@ class EdgeBreakerTraverser {
edgebreaker_observer_ = edgebreaker_observer;
}
void TraverseFromCorner(CornerIndex corner_id) {
if (processor_.IsFaceVisited(corner_id))
return; // Already traversed.
corner_traversal_stack_.clear();
corner_traversal_stack_.push_back(corner_id);
// For the first face, check the remaining corners as they may not be