@blockv/threejs-to-v3d
Version:
Converts any format supported by ThreeJS to V3D.
137 lines (103 loc) • 2.79 kB
JavaScript
//
// V3DBuilder - Compiles blocks into a fully compatible .v3d file
const BlobBuilder = require('./BlobBuilder');
module.exports = class V3DBuilder {
constructor() {
// Properties
this.lastBlockID = 1;
this.blocks = [];
this.fileProperties = {
version: 1,
title: "Untitled Scene",
"source.exporter": "Vatomic 3D Exporter"
};
}
/** Create a block */
newBlock() {
// Create block
var blk = new Block();
blk.builder = this;
blk.id = this.lastBlockID++;
// Store block
this.blocks.push(blk);
// Done
return blk;
}
/** Compile file into a blob */
build() {
// Create blob builder
var builder = new BlobBuilder();
// Calculate header block size
var fileMetaStr = JSON.stringify(this.fileProperties);
var headerBlockSize = 4 + builder.stringLengthInBytes(fileMetaStr);
// Write file header block
builder.addByte(0x3D);
builder.addByte(0x0B);
builder.addByte(0x1E);
builder.addByte(0xC7);
builder.addString(fileMetaStr);
// Calculate final size of the directory block
var directoryBlockSize = 4 + 4 + 4;
for (var block of this.blocks) {
block.metadataStr = JSON.stringify(block.properties);
block.metadataStrLen = builder.stringLengthInBytes(block.metadataStr);
directoryBlockSize += 4 + 1 + 2 + block.metadataStrLen + 8 + 8;
}
// Write file directory block
builder.addByte(0x44);
builder.addByte(0x49);
builder.addByte(0x52);
builder.addByte(0x42);
builder.addUInt32(directoryBlockSize);
builder.addUInt32(this.blocks.length);
for (var block of this.blocks) {
// Calculate block payload offset
var offset = headerBlockSize + directoryBlockSize;
for (var blk of this.blocks) {
offset += 4 + 4 + 1 + 8;
if (blk === block) break;
offset += blk.data.length;
}
// Add block info
builder.addUInt32(block.id);
builder.addUInt8(block.levelOfDetail);
builder.addUInt16(block.metadataStrLen);
builder.addString(block.metadataStr);
builder.addUInt64(offset);
builder.addUInt64(block.data.length);
}
// Write blocks
for (var block of this.blocks) {
// Write data block header
builder.addByte(0x44);
builder.addByte(0x41);
builder.addByte(0x54);
builder.addByte(0x41);
builder.addUInt32(block.id);
builder.addUInt8(block.levelOfDetail);
builder.addUInt64(block.data.length);
builder.addBlobBuilder(block.data);
}
// Done
return builder.buildArrayBuffer();
}
}
class Block {
constructor() {
// Properties
this.builder = null;
this.id = 0;
this.levelOfDetail = 0;
this.data = new BlobBuilder();
this.properties = {
type: "",
parent: 0
};
}
newChildBlock() {
// Create new block
var blk = this.builder.newBlock();
blk.properties.parent = this.id;
return blk;
}
}