-
Notifications
You must be signed in to change notification settings - Fork 976
Commit
- Loading branch information
There are no files selected for viewing
Large diffs are not rendered by default.
This file was deleted.
This file was deleted.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
/** | ||
* @fileoverview Main file for draco-animation package. | ||
*/ | ||
|
||
var createEncoderModule = require('./draco_animation_encoder_nodejs'); | ||
var createDecoderModule = require('./draco_animation_decoder_nodejs'); | ||
|
||
module.exports = { | ||
createEncoderModule, | ||
createDecoderModule | ||
} |
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
// Copyright 2017 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. | ||
// | ||
'use_strict'; | ||
|
||
const assert = require('assert'); | ||
const draco = require('./draco-animation'); | ||
const decoderModule = draco.createDecoderModule({}); | ||
const encoderModule = draco.createEncoderModule({}); | ||
|
||
function generateAnimationData(numKeyframes, numAnimations, numComponents) { | ||
const timestamps = new Float32Array(numKeyframes); | ||
|
||
const keyframes = new Array(numAnimations); | ||
for (let i = 0; i < numAnimations; ++i) { | ||
keyframes[i] = new Float32Array(numKeyframes * numComponents[i]); | ||
} | ||
|
||
for (let frameId = 0; frameId < numKeyframes; ++frameId) { | ||
timestamps[frameId] = frameId; | ||
for (let keyframeId = 0; keyframeId < numAnimations; ++keyframeId) { | ||
for (let j = 0; j < numComponents[keyframeId]; ++j) { | ||
// Set an arbitrary deterministic value. | ||
keyframes[keyframeId][frameId * numComponents[keyframeId] + j] = | ||
(frameId * numComponents[keyframeId] + j) * (keyframeId + 1); | ||
} | ||
} | ||
} | ||
|
||
const animation = { | ||
timestamps : timestamps, | ||
keyframes : keyframes | ||
}; | ||
|
||
return animation; | ||
} | ||
|
||
function encodeAnimation(animation) { | ||
const encoder = new encoderModule.AnimationEncoder(); | ||
const animationBuilder = new encoderModule.AnimationBuilder(); | ||
const dracoAnimation = new encoderModule.KeyframeAnimation(); | ||
|
||
// Add timestamps to animation. | ||
const numKeyframes = animation.timestamps.length; | ||
assert(animationBuilder.SetTimestamps(dracoAnimation, numKeyframes, | ||
animation.timestamps)); | ||
|
||
// Add keyframes. | ||
for (let keyframeId = 0; keyframeId < animation.keyframes.length; | ||
++keyframeId) { | ||
const numComponents = | ||
animation.keyframes[keyframeId].length / animation.timestamps.length; | ||
assert(animationBuilder.AddKeyframes(dracoAnimation, numKeyframes, | ||
numComponents, animation.keyframes[keyframeId]) == keyframeId + 1); | ||
} | ||
|
||
const encodedData = new encoderModule.DracoInt8Array(); | ||
encoder.SetTimestampsQuantization(16); | ||
encoder.SetKeyframesQuantization(16); | ||
console.log("Quantized timestamps to 16 bits."); | ||
console.log("Quantized keyframes to 16 bits."); | ||
const encodedLen = encoder.EncodeAnimationToDracoBuffer(dracoAnimation, | ||
encodedData); | ||
|
||
encoderModule.destroy(dracoAnimation); | ||
encoderModule.destroy(animationBuilder); | ||
encoderModule.destroy(encoder); | ||
|
||
assert(encodedLen > 0, "Failed encoding."); | ||
console.log("Encoded size: " + encodedLen); | ||
|
||
const outputBuffer = new ArrayBuffer(encodedLen); | ||
const outputData = new Int8Array(outputBuffer); | ||
for (let i = 0; i < encodedLen; ++i) { | ||
const data0 = encodedData.GetValue(i); | ||
outputData[i] = encodedData.GetValue(i); | ||
} | ||
encoderModule.destroy(encodedData); | ||
|
||
return outputBuffer; | ||
} | ||
|
||
function decodeAnimation(encodedData) { | ||
const buffer = new decoderModule.DecoderBuffer(); | ||
buffer.Init(new Int8Array(encodedData), encodedData.byteLength); | ||
const decoder = new decoderModule.AnimationDecoder(); | ||
|
||
const dracoAnimation = new decoderModule.KeyframeAnimation(); | ||
decoder.DecodeBufferToKeyframeAnimation(buffer, dracoAnimation); | ||
assert(dracoAnimation.ptr != 0, "Invalid animation."); | ||
|
||
|
||
const numKeyframes = dracoAnimation.num_frames(); | ||
|
||
const timestampAttData = new decoderModule.DracoFloat32Array(); | ||
assert(decoder.GetTimestamps(dracoAnimation, timestampAttData)); | ||
const timestamps = new Float32Array(numKeyframes); | ||
for (let i = 0; i < numKeyframes; ++i) { | ||
timestamps[i] = timestampAttData.GetValue(i); | ||
} | ||
|
||
const numAnimations = dracoAnimation.num_animations(); | ||
const keyframes = new Array(numAnimations); | ||
for (let keyframeId = 0; keyframeId < numAnimations; ++keyframeId) { | ||
const animationAttData = new decoderModule.DracoFloat32Array(); | ||
// The id of keyframe attribute starts at 1. | ||
assert(decoder.GetKeyframes(dracoAnimation, keyframeId + 1, | ||
animationAttData)); | ||
keyframes[keyframeId] = new Float32Array(animationAttData.size()); | ||
for (let i = 0; i < animationAttData.size(); ++i) { | ||
keyframes[keyframeId][i] = animationAttData.GetValue(i); | ||
} | ||
} | ||
|
||
const animation = { | ||
timestamps : timestamps, | ||
keyframes : keyframes | ||
} | ||
|
||
console.log("Decoding successful."); | ||
|
||
return animation; | ||
} | ||
|
||
function compareAnimation(animation, decodedAnimation) { | ||
console.log("Comparing decoded animation data..."); | ||
assert(animation.timestamps.length == decodedAnimation.timestamps.length); | ||
assert(animation.keyframes.length == decodedAnimation.keyframes.length); | ||
|
||
console.log("Done."); | ||
} | ||
|
||
// Create animation with 50 frames and two animations. | ||
// The first animation has 3 components and the second has 4 components. | ||
const animation = generateAnimationData(100, 2, [3, 4]); | ||
const encodedData = encodeAnimation(animation); | ||
|
||
const decodedAnimation = decodeAnimation(encodedData); | ||
compareAnimation(animation, decodedAnimation); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
{ | ||
"name": "draco-animation", | ||
"version": "1.0.4", | ||
"description": "Draco animation is a library for compressing and decompressing 3D animations of geometric meshes.", | ||
"main": "draco-animation.js", | ||
"scripts": { | ||
"test": "nodejs draco_animation_encoding_test.js" | ||
}, | ||
"keywords": [ | ||
"compression", | ||
"animation" | ||
], | ||
"author": "Google Draco Team", | ||
"license": "Apache-2.0", | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/google/draco.git" | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
// Copyright 2017 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. | ||
// | ||
#include "draco/animation/keyframe_animation.h" | ||
|
||
namespace draco { | ||
|
||
KeyframeAnimation::KeyframeAnimation() {} | ||
|
||
bool KeyframeAnimation::SetTimestamps( | ||
const std::vector<TimestampType> ×tamp) { | ||
// Already added attributes. | ||
const int32_t num_frames = timestamp.size(); | ||
if (num_attributes() > 0) { | ||
// Timestamp attribute could be added only once. | ||
if (timestamps()->size()) { | ||
return false; | ||
} else { | ||
// Check if the number of frames is consistent with | ||
// the existing keyframes. | ||
if (num_frames != num_points()) | ||
return false; | ||
} | ||
} else { | ||
// This is the first attribute. | ||
set_num_frames(num_frames); | ||
} | ||
|
||
// Add attribute for time stamp data. | ||
std::unique_ptr<PointAttribute> timestamp_att = | ||
std::unique_ptr<PointAttribute>(new PointAttribute()); | ||
timestamp_att->Init(GeometryAttribute::GENERIC, nullptr, 1, DT_FLOAT32, false, | ||
sizeof(float), 0); | ||
timestamp_att->SetIdentityMapping(); | ||
timestamp_att->Reset(num_frames); | ||
for (PointIndex i(0); i < num_frames; ++i) { | ||
timestamp_att->SetAttributeValue(timestamp_att->mapped_index(i), | ||
×tamp[i.value()]); | ||
} | ||
this->SetAttribute(kTimestampId, std::move(timestamp_att)); | ||
return true; | ||
} | ||
|
||
} // namespace draco |