From 74ae5944b5ce1c6ea303b1ab4edd0b713beddc0d Mon Sep 17 00:00:00 2001 From: simon Date: Mon, 28 Aug 2023 14:13:21 -0400 Subject: [PATCH 001/111] imported code from vim-ts dev branch --- src/ts/src/abstractG3d.ts | 43 ++++ src/ts/src/bfast.ts | 8 +- src/ts/src/g3d.ts | 457 +++++++++++------------------------ src/ts/src/g3dAttributes.ts | 144 +++++++++++ src/ts/src/g3dMaterials.ts | 100 ++++++++ src/ts/src/g3dMesh.ts | 299 +++++++++++++++++++++++ src/ts/src/g3dMeshIndex.ts | 201 +++++++++++++++ src/ts/src/g3dMeshOffsets.ts | 88 +++++++ src/ts/src/g3dSubset.ts | 133 ++++++++++ src/ts/src/index.ts | 8 + src/ts/src/remoteBuffer.ts | 2 +- src/ts/src/remoteG3d.ts | 3 +- src/ts/src/remoteGeometry.ts | 36 +++ src/ts/src/remoteValue.ts | 2 +- src/ts/src/requestTracker.ts | 2 +- src/ts/src/requester.ts | 84 +++++++ 16 files changed, 1290 insertions(+), 320 deletions(-) create mode 100644 src/ts/src/abstractG3d.ts create mode 100644 src/ts/src/g3dAttributes.ts create mode 100644 src/ts/src/g3dMaterials.ts create mode 100644 src/ts/src/g3dMesh.ts create mode 100644 src/ts/src/g3dMeshIndex.ts create mode 100644 src/ts/src/g3dMeshOffsets.ts create mode 100644 src/ts/src/g3dSubset.ts create mode 100644 src/ts/src/remoteGeometry.ts create mode 100644 src/ts/src/requester.ts diff --git a/src/ts/src/abstractG3d.ts b/src/ts/src/abstractG3d.ts new file mode 100644 index 00000000..ec3dd895 --- /dev/null +++ b/src/ts/src/abstractG3d.ts @@ -0,0 +1,43 @@ + +import { G3dAttribute, G3dAttributeDescriptor } from './g3dAttributes' +import { BFast } from './bfast' + +/** + * G3D is a simple, efficient, generic binary format for storing and transmitting geometry. + * The G3D format is designed to be used either as a serialization format or as an in-memory data structure. + * See https://github.com/vimaec/g3d + */ +export class AbstractG3d { + meta: string + attributes: G3dAttribute[] + + constructor (meta: string, attributes: G3dAttribute[]) { + this.meta = meta + this.attributes = attributes + } + + findAttribute (descriptor: string): G3dAttribute | undefined { + const filter = G3dAttributeDescriptor.fromString(descriptor) + for (let i = 0; i < this.attributes.length; ++i) { + const attribute = this.attributes[i] + if (attribute.descriptor.matches(filter)) return attribute + } + } + + /** + * Create g3d from bfast by requesting all necessary buffers individually. + */ + static async createFromBfast (bfast: BFast, names: string[]) { + + const attributes = await Promise.all(names.map(async (a) => { + const bytes = await bfast.getBytes(a) + if(!bytes) return + const decriptor = G3dAttributeDescriptor.fromString(a) + return new G3dAttribute(decriptor, bytes) + })) + + const validAttributes = attributes.filter((a): a is G3dAttribute => a !== undefined) + const g3d = new AbstractG3d('meta', validAttributes) + return g3d + } +} diff --git a/src/ts/src/bfast.ts b/src/ts/src/bfast.ts index e67d96c8..cc10fd4e 100644 --- a/src/ts/src/bfast.ts +++ b/src/ts/src/bfast.ts @@ -4,6 +4,7 @@ import { RemoteValue } from './remoteValue' import { RemoteBuffer } from './remoteBuffer' + import * as pako from 'pako' type NumericArrayConstructor = | Int8ArrayConstructor @@ -246,9 +247,12 @@ export function parseName(name: string): [number, NumericArrayConstructor]{ return request.get() } - async getLocalBfast (name: string): Promise { - const buffer = await this.getBuffer(name) + async getLocalBfast (name: string, unzip: boolean = false): Promise { + let buffer = await this.getBuffer(name) if (!buffer) return undefined + if(unzip){ + buffer = pako.inflate(buffer).buffer + } return new BFast(buffer, 0, name) } diff --git a/src/ts/src/g3d.ts b/src/ts/src/g3d.ts index 483d350d..fb7743fa 100644 --- a/src/ts/src/g3d.ts +++ b/src/ts/src/g3d.ts @@ -2,184 +2,14 @@ * @module vim-ts */ +import { AbstractG3d } from './abstractG3d' import { BFast } from './bfast' +import { FilterMode } from './g3dMeshIndex' +import { G3dSubset } from './g3dSubset' -export class G3dAttributeDescriptor { - // original descriptor string - description: string - // Indicates the part of the geometry that this attribute is associated with - association: string - // the role of the attribute - semantic: string - // each attribute type should have it's own index ( you can have uv0, uv1, etc. ) - attributeTypeIndex: string - // the type of individual values (e.g. int32, float64) - dataType: string - // how many values associated with each element (e.g. UVs might be 2, geometry might be 3, quaternions 4, matrices 9 or 16) - dataArity: number - - constructor ( - description: string, - association: string, - semantic: string, - attributeTypeIndex: string, - dataType: string, - dataArity: string - ) { - if (!description.startsWith('g3d:')) { - throw new Error(`${description} must start with 'g3d'`) - } - - this.description = description - this.association = association - this.semantic = semantic - this.attributeTypeIndex = attributeTypeIndex - this.dataType = dataType - this.dataArity = parseInt(dataArity) - } - - static fromString (descriptor: string): G3dAttributeDescriptor { - const desc = descriptor.split(':') - - if (desc.length !== 6) { - throw new Error(`${descriptor}, must have 6 components delimited by ':'`) - } - - return new this(descriptor, desc[1], desc[2], desc[3], desc[4], desc[5]) - } - - matches (other: G3dAttributeDescriptor) { - const match = (a: string, b: string) => a === '*' || b === '*' || a === b - - return ( - match(this.association, other.association) && - match(this.semantic, other.semantic) && - match(this.attributeTypeIndex, other.attributeTypeIndex) && - match(this.dataType, other.dataType) - ) - } -} export type MeshSection = 'opaque' | 'transparent' | 'all' -export type TypedArray = - | Uint8Array - | Int16Array - | Uint16Array - | Int32Array - | Uint32Array - | Float32Array - | Uint32Array - | Float64Array - -export class G3dAttribute { - descriptor: G3dAttributeDescriptor - bytes: Uint8Array - data: TypedArray | undefined - - constructor (descriptor: G3dAttributeDescriptor, bytes: Uint8Array) { - this.descriptor = descriptor - this.bytes = bytes - this.data = G3dAttribute.castData(bytes, descriptor.dataType) - } - - static fromString (descriptor: string, buffer: Uint8Array): G3dAttribute { - return new this(G3dAttributeDescriptor.fromString(descriptor), buffer) - } - - // Converts a VIM attribute into a typed array from its raw data - static castData (bytes: Uint8Array, dataType: string): TypedArray | undefined { - switch (dataType) { - case 'float32': - return new Float32Array( - bytes.buffer, - bytes.byteOffset, - bytes.byteLength / 4 - ) - case 'float64': - throw new Float64Array( - bytes.buffer, - bytes.byteOffset, - bytes.byteLength / 8 - ) - case 'uint8': - case 'int8': - return bytes - case 'int16': - return new Int16Array( - bytes.buffer, - bytes.byteOffset, - bytes.byteLength / 2 - ) - case 'uint16': - return new Uint16Array( - bytes.buffer, - bytes.byteOffset, - bytes.byteLength / 2 - ) - case 'int32': - return new Int32Array( - bytes.buffer, - bytes.byteOffset, - bytes.byteLength / 4 - ) - case 'uint32': - return new Uint32Array( - bytes.buffer, - bytes.byteOffset, - bytes.byteLength / 4 - ) - - case 'int64': - case 'uint64': - console.error('G3d: 64-bit buffers unsuported') - return - default: - console.error('Unrecognized attribute data type ' + dataType) - } - } -} - -/** - * G3D is a simple, efficient, generic binary format for storing and transmitting geometry. - * The G3D format is designed to be used either as a serialization format or as an in-memory data structure. - * See https://github.com/vimaec/g3d - */ -export class AbstractG3d { - meta: string - attributes: G3dAttribute[] - - constructor (meta: string, attributes: G3dAttribute[]) { - this.meta = meta - this.attributes = attributes - } - - findAttribute (descriptor: string): G3dAttribute | undefined { - const filter = G3dAttributeDescriptor.fromString(descriptor) - for (let i = 0; i < this.attributes.length; ++i) { - const attribute = this.attributes[i] - if (attribute.descriptor.matches(filter)) return attribute - } - } - - /** - * Create g3d from bfast by requesting all necessary buffers individually. - */ - static async createFromBfast (bfast: BFast) { - - const attributes = await Promise.all(VimAttributes.all.map(async (a) => { - const bytes = await bfast.getBytes(a) - if(!bytes) return - const decriptor = G3dAttributeDescriptor.fromString(a) - return new G3dAttribute(decriptor, bytes) - })) - - const validAttributes = attributes.filter((a): a is G3dAttribute => a !== undefined) - const g3d = new AbstractG3d('meta', validAttributes) - return g3d - } -} - /** * See https://github.com/vimaec/vim#vim-geometry-attributes */ @@ -231,7 +61,11 @@ export class G3d { instanceNodes : Int32Array meshVertexOffsets: Int32Array meshInstances: Array> - meshOpaqueCount: Array + meshOpaqueCount: Int32Array + + submeshVertexStart: Int32Array + submeshVertexEnd: Int32Array + rawG3d: AbstractG3d @@ -282,6 +116,29 @@ export class G3d { this.meshInstances = this.computeMeshInstances() this.meshOpaqueCount = this.computeMeshOpaqueCount() this.sortSubmeshes() + const range = this.computeSubmeshVertexRange() + this.submeshVertexStart = range.start + this.submeshVertexEnd = range.end + } + + private computeSubmeshVertexRange(){ + const submeshCount = this.getSubmeshCount() + const start = new Int32Array(submeshCount) + const end = new Int32Array(submeshCount) + for(let sub = 0; sub < submeshCount; sub++){ + let min = Number.MAX_SAFE_INTEGER + let max = Number.MIN_SAFE_INTEGER + const subStart = this.getSubmeshIndexStart(sub) + const subEnd = this.getSubmeshIndexEnd(sub) + for(let i =subStart; i < subEnd; i ++){ + const index = this.indices[i] + min = Math.min(min, index) + max = Math.max(min, index) + } + start[sub] = min + end[sub] = max + } + return {start, end} } static createFromAbstract(g3d: AbstractG3d) { @@ -336,8 +193,15 @@ export class G3d { return result } + static async createFromPath (path: string) { + const f = await fetch(path) + const buffer = await f.arrayBuffer() + const bfast = new BFast(buffer) + return this.createFromBfast(bfast) + } + static async createFromBfast (bfast: BFast) { - const g3d = await AbstractG3d.createFromBfast(bfast) + const g3d = await AbstractG3d.createFromBfast(bfast, VimAttributes.all) return G3d.createFromAbstract(g3d) } @@ -541,11 +405,23 @@ export class G3d { } } + private unbaseIndices() { + const count = this.getMeshCount(); + for (let m = 0; m < count; m++) { + const offset = this.meshVertexOffsets[m]; + const start = this.getMeshIndexStart(m, 'all'); + const end = this.getMeshIndexEnd(m, 'all'); + for (let i = start; i < end; i++) { + this.indices[i] += offset; + } + } + } + /** * Computes an array where true if any of the materials used by a mesh has transparency. */ private computeMeshOpaqueCount () { - const result = new Array(this.getMeshCount()).fill(0) + const result = new Int32Array(this.getMeshCount()) for (let m = 0; m < result.length; m++) { const subStart = this.getMeshSubmeshStart(m, 'all') const subEnd = this.getMeshSubmeshEnd(m, 'all') @@ -557,14 +433,28 @@ export class G3d { return result } + // ------------- All ----------------- + /**Given VIM instance indices returns the corresponding G3d indices */ + remapInstances(instances : number[]){ + const map = new Map() + for(let i =0; i < instances.length; i++){ + map.set(this.instanceNodes[i], i) + } + + return instances.map((i) => map.get(i)) + } - // ------------- All ----------------- getVertexCount = () => this.positions.length / G3d.POSITION_SIZE + getIndexCount = () => this.indices.length // ------------- Meshes ----------------- getMeshCount = () => this.meshSubmeshes.length + getMeshInstanceCount(mesh: number){ + return this.meshInstances[mesh]?.length ?? 0 + } + getMeshIndexStart (mesh: number, section: MeshSection = 'all'): number { const sub = this.getMeshSubmeshStart(mesh, section) return this.getSubmeshIndexStart(sub) @@ -642,6 +532,18 @@ export class G3d { return this.getSubmeshIndexEnd(submesh) - this.getSubmeshIndexStart(submesh) } + getSubmeshVertexStart(submesh: number) : number { + return this.submeshVertexStart[submesh] + } + + getSubmeshVertexEnd(submesh: number) : number { + return this.submeshVertexEnd[submesh] + } + + getSubmeshVertexCount(submesh: number) : number { + return this.getSubmeshVertexEnd(submesh) - this.getSubmeshVertexStart(submesh) + } + /** * Returns color of given submesh as a 4-number array (RGBA) * @param submesh g3d submesh index @@ -676,6 +578,11 @@ export class G3d { // ------------- Instances ----------------- getInstanceCount = () => this.instanceMeshes.length + /** + * Returns true if instance has given flag enabled. + * @param instance instance to check. + * @param flag to check against. + */ getInstanceHasFlag(instance: number, flag: number){ return (this.instanceFlags[instance] & flag) > 0 } @@ -715,6 +622,10 @@ export class G3d { ) } + /** + * Returns the alpha component of given material + * @param material + */ getMaterialAlpha (material: number): number { if (material < 0) return 1 const index = material * G3d.COLOR_SIZE + G3d.COLOR_SIZE - 1 @@ -722,6 +633,10 @@ export class G3d { return result } + /** + * Concatenates two g3ds into a new g3d. + * @deprecated + */ append(other: G3d){ const _instanceFlags = new Uint16Array(this.instanceFlags.length + other.instanceFlags.length) _instanceFlags.set(this.instanceFlags) @@ -739,9 +654,13 @@ export class G3d { _positions.set(this.positions) _positions.set(other.positions, this.positions.length) + this.unbaseIndices() + other.unbaseIndices() const _indices = new Uint32Array(this.indices.length + other.indices.length) _indices.set(this.indices) _indices.set(other.indices.map(i => i + this.positions.length / 3), this.indices.length) + this.rebaseIndices() + other.rebaseIndices() const _meshSubmeshes = new Int32Array(this.meshSubmeshes.length + other.meshSubmeshes.length) _meshSubmeshes.set(this.meshSubmeshes) @@ -774,142 +693,6 @@ export class G3d { return g3d } - - - slice(instance: number){ - return this.filter([instance]) - } - - filter(instances: number[]){ - const instanceSet = new Set(instances) - - // Instances - const _instanceMeshes = new Int32Array(instances.length) - const _instanceFlags = new Uint16Array(instances.length) - const _instanceTransforms = new Float32Array(instances.length * 16) - let instance_i = 0 - for(let i=0; i < this.getInstanceCount(); i ++){ - if(!instanceSet.has(i)) continue - _instanceFlags[instance_i] = this.instanceFlags[i] - _instanceMeshes[instance_i] = this.instanceMeshes[i] - for(let j = 0; j < 16; j++){ - _instanceTransforms[instance_i *16 + j] = this.instanceTransforms[i * 16 +j] - } - instance_i++ - } - - // Meshes - const meshMap = new Map() - const meshSet = new Set(_instanceMeshes) - meshSet.delete(-1) - const _meshSubmeshes = new Int32Array(meshSet.size) - - let last = -1 - let mesh_i = 0 - for(let i=0; i < this.getMeshCount(); i++){ - if(!meshSet.has(i)) continue - - const offset = mesh_i > 0 ? _meshSubmeshes[mesh_i -1] : 0 - const lastCount = last < 0 ? 0 : this.getMeshSubmeshCount(last) - _meshSubmeshes[mesh_i] = lastCount + offset - meshMap.set(i, mesh_i) - last = i - mesh_i++ - } - - // Remap Instance Meshes - for(let i = 0; i < _instanceMeshes.length; i++){ - _instanceMeshes[i] = meshMap.get(_instanceMeshes[i]) ?? -1 - } - - // Mesh Attributes Count - let submeshCount = 0 - let positionCount = 0 - let indiceCount = 0 - for(let m=0; m < this.getMeshCount(); m ++){ - if(!meshSet.has(m)) continue - positionCount += this.getMeshVertexCount(m) - indiceCount += this.getMeshIndexCount(m) - submeshCount += this.getMeshSubmeshCount(m) - } - - // Meshes - let indices_i = 0 - let positions_i = 0 - let submesh_i =0 - let submeshOffset = 0 - let meshOffset = 0 - const _submeshIndexOffsets = new Int32Array(submeshCount) - const _submeshMaterials = new Int32Array(submeshCount) - const _positions = new Float32Array(positionCount*3) - const _indices = new Uint32Array(indiceCount) - - for(let mesh=0; mesh < this.getMeshCount(); mesh ++){ - if(!meshSet.has(mesh)) continue - - // submeshes - const subStart = this.getMeshSubmeshStart(mesh) - const subEnd = this.getMeshSubmeshEnd(mesh) - - for(let j = subStart; j < subEnd ; j++){ - const start = this.submeshIndexOffset[subStart] - _submeshIndexOffsets[submesh_i] = this.submeshIndexOffset[j] - start + submeshOffset - _submeshMaterials[submesh_i] = this.submeshMaterial[j] - submesh_i++ - } - submeshOffset += this.getMeshIndexCount(mesh) - - // indices - const indexStart = this.getMeshIndexStart(mesh) - const indexEnd = this.getMeshIndexEnd(mesh) - for(let j =indexStart; j < indexEnd ; j++){ - _indices[indices_i++] = this.indices[j] + meshOffset - } - meshOffset += this.getMeshVertexCount(mesh) - - // vertices - const vertexStart = this.getMeshVertexStart(mesh) - const vertexEnd = this.getMeshVertexEnd(mesh) - for(let j = vertexStart * 3; j < vertexEnd *3 ; j++){ - _positions[positions_i++] = this.positions[j] - } - } - - // Material Colors - let color_i =0 - const materialSet = new Set(_submeshMaterials) - const materialMap = new Map() - const _materialColors = new Float32Array(materialSet.size * 4) - for(let i =0; i < this.materialColors.length; i ++){ - if(materialSet.has(i)){ - materialMap.set(i, color_i) - for(let j=0; j < 4; j++){ - _materialColors[color_i *4 +j] = this.materialColors[i * 4 +j] - } - color_i++ - } - } - - // Remap Submesh Materials - for(let i=0; i < _submeshMaterials.length; i++){ - _submeshMaterials[i] = _submeshMaterials[i] < 0 ? -1 : materialMap.get(_submeshMaterials[i]) - } - - const g3d = new G3d( - _instanceMeshes, - _instanceFlags, - _instanceTransforms, - new Int32Array(instances), - _meshSubmeshes, - _submeshIndexOffsets, - _submeshMaterials, - _indices, - _positions, - _materialColors - ) - - return g3d - } validate () { const isPresent = (attribute: any, label: string) => { @@ -1018,6 +801,8 @@ export class G3d { 'Invalid material color buffer, must be divisible by ' + G3d.COLOR_SIZE ) } + + console.assert(this.meshInstances.length === this.getMeshCount()) console.assert(this.meshOpaqueCount.length === this.getMeshCount()) console.assert(this.meshSubmeshes.length === this.getMeshCount()) @@ -1037,5 +822,49 @@ export class G3d { ) } } -} + filter(mode: FilterMode, filter: number[]){ + if(filter === undefined || mode === undefined){ + return new G3dSubset(this, undefined) + } + if(mode === 'instance'){ + return this.getMeshesFromInstances(filter) + } + + if(mode === 'mesh'){ + return new G3dSubset(this, filter) + } + if(mode === 'tag' || mode === 'group'){ + throw new Error("Filter Mode Not implemented") + } + } + + private getMeshesFromInstances(instances: number[]){ + // Compute the list of unique meshes to include + const meshSet = new Set() + const meshes = new Array() + instances.forEach((instance, i) => { + const mesh = this.instanceMeshes[instance] + if(!meshSet.has(mesh) && mesh >=0){ + meshes.push(mesh) + meshSet.add(mesh) + } + }) + + + // Compute the mesh-based instances indices for each mesh + const instanceSet = new Set(instances) + const meshInstances = new Array>(meshes.length) + meshes.forEach((mesh, i) => { + const indices = new Array() + this.meshInstances[mesh].forEach((instance, j) => { + if(instanceSet.has(instance)){ + indices.push(j) + } + meshInstances[i] = indices + }) + }) + + return new G3dSubset(this, meshes, meshInstances) + } +} diff --git a/src/ts/src/g3dAttributes.ts b/src/ts/src/g3dAttributes.ts new file mode 100644 index 00000000..1cb57653 --- /dev/null +++ b/src/ts/src/g3dAttributes.ts @@ -0,0 +1,144 @@ + +export class G3dAttributeDescriptor { + // original descriptor string + description: string + // Indicates the part of the geometry that this attribute is associated with + association: string + // the role of the attribute + semantic: string + // each attribute type should have it's own index ( you can have uv0, uv1, etc. ) + attributeTypeIndex: string + // the type of individual values (e.g. int32, float64) + dataType: string + // how many values associated with each element (e.g. UVs might be 2, geometry might be 3, quaternions 4, matrices 9 or 16) + dataArity: number + + constructor ( + description: string, + association: string, + semantic: string, + attributeTypeIndex: string, + dataType: string, + dataArity: string + ) { + if (!description.startsWith('g3d:')) { + throw new Error(`${description} must start with 'g3d'`) + } + + this.description = description + this.association = association + this.semantic = semantic + this.attributeTypeIndex = attributeTypeIndex + this.dataType = dataType + this.dataArity = parseInt(dataArity) + } + + static fromString (descriptor: string): G3dAttributeDescriptor { + const desc = descriptor.split(':') + + if (desc.length !== 6) { + throw new Error(`${descriptor}, must have 6 components delimited by ':'`) + } + + return new this(descriptor, desc[1], desc[2], desc[3], desc[4], desc[5]) + } + + matches (other: G3dAttributeDescriptor) { + const match = (a: string, b: string) => a === '*' || b === '*' || a === b + + return ( + match(this.association, other.association) && + match(this.semantic, other.semantic) && + match(this.attributeTypeIndex, other.attributeTypeIndex) && + match(this.dataType, other.dataType) + ) + } +} + + +export type TypedArray = + | Uint8Array + | Int16Array + | Uint16Array + | Int32Array + | Uint32Array + | Float32Array + | Uint32Array + | BigUint64Array + | BigInt64Array + | Float64Array + +export class G3dAttribute { + descriptor: G3dAttributeDescriptor + bytes: Uint8Array + data: TypedArray | undefined + + constructor (descriptor: G3dAttributeDescriptor, bytes: Uint8Array) { + this.descriptor = descriptor + this.bytes = bytes + this.data = G3dAttribute.castData(bytes, descriptor.dataType) + } + + static fromString (descriptor: string, buffer: Uint8Array): G3dAttribute { + return new this(G3dAttributeDescriptor.fromString(descriptor), buffer) + } + + // Converts a VIM attribute into a typed array from its raw data + static castData (bytes: Uint8Array, dataType: string): TypedArray | undefined { + switch (dataType) { + case 'float32': + return new Float32Array( + bytes.buffer, + bytes.byteOffset, + bytes.byteLength / 4 + ) + case 'float64': + throw new Float64Array( + bytes.buffer, + bytes.byteOffset, + bytes.byteLength / 8 + ) + case 'uint8': + case 'int8': + return bytes + case 'int16': + return new Int16Array( + bytes.buffer, + bytes.byteOffset, + bytes.byteLength / 2 + ) + case 'uint16': + return new Uint16Array( + bytes.buffer, + bytes.byteOffset, + bytes.byteLength / 2 + ) + case 'int32': + return new Int32Array( + bytes.buffer, + bytes.byteOffset, + bytes.byteLength / 4 + ) + case 'uint32': + return new Uint32Array( + bytes.buffer, + bytes.byteOffset, + bytes.byteLength / 4 + ) + case 'int64': + return new BigInt64Array( + bytes.buffer, + bytes.byteOffset, + bytes.byteLength / 8 + ) + case 'uint64': + return new BigUint64Array( + bytes.buffer, + bytes.byteOffset, + bytes.byteLength / 8 + ) + default: + console.error('Unrecognized attribute data type ' + dataType) + } + } +} diff --git a/src/ts/src/g3dMaterials.ts b/src/ts/src/g3dMaterials.ts new file mode 100644 index 00000000..3d77ebee --- /dev/null +++ b/src/ts/src/g3dMaterials.ts @@ -0,0 +1,100 @@ +/** + * @module vim-ts + */ + +import { AbstractG3d } from './abstractG3d' +import { BFast } from './bfast' + +/** + * See https://github.com/vimaec/vim#vim-geometry-attributes + */ +export class MaterialAttributes { + static materialColors = 'g3d:material:color:0:float32:4' + + static all = [ + MaterialAttributes.materialColors + ] +} + +/** + * G3D is a simple, efficient, generic binary format for storing and transmitting geometry. + * The G3D format is designed to be used either as a serialization format or as an in-memory data structure. + * A G3d with specific attributes according to the VIM format specification. + * See https://github.com/vimaec/vim#vim-geometry-attributes for the vim specification. + * See https://github.com/vimaec/g3d for the g3d specification. + */ +export class G3dMaterial { + + static COLOR_SIZE = 4 + + rawG3d: AbstractG3d + + materialColors: Float32Array + DEFAULT_COLOR = new Float32Array([1, 1, 1, 1]) + + constructor( + + materialColors: Float32Array){ + this.materialColors = materialColors + } + + static createFromAbstract(g3d: AbstractG3d) { + + const materialColors = g3d.findAttribute(MaterialAttributes.materialColors) + ?.data as Float32Array + + const result = new G3dMaterial( + + materialColors + ) + result.rawG3d = g3d + + return result + } + + static async createFromPath (path: string) { + const f = await fetch(path) + const buffer = await f.arrayBuffer() + var g3d = this.createFromBuffer(buffer) + + return g3d + } + + static async createFromBuffer (buffer: ArrayBuffer) { + const bfast = new BFast(buffer) + return this.createFromBfast(bfast) + } + + static async createFromBfast (bfast: BFast) { + const g3d = await AbstractG3d.createFromBfast(bfast, MaterialAttributes.all) + return G3dMaterial.createFromAbstract(g3d) + } + + toG3d(){ + return new G3dMaterial( + this.materialColors + ) + } + + getMaterialCount = () => this.materialColors.length / G3dMaterial.COLOR_SIZE + + /** + * Returns color of given material as a 4-number array (RGBA) + * @param material g3d material index + */ + getMaterialColor (material: number): Float32Array { + if (material < 0) return this.DEFAULT_COLOR + return this.materialColors.subarray( + material * G3dMaterial.COLOR_SIZE, + (material + 1) * G3dMaterial.COLOR_SIZE + ) + } + + getMaterialAlpha (material: number): number { + if (material < 0) return 1 + const index = material * G3dMaterial.COLOR_SIZE + G3dMaterial.COLOR_SIZE - 1 + const result = this.materialColors[index] + return result + } +} + diff --git a/src/ts/src/g3dMesh.ts b/src/ts/src/g3dMesh.ts new file mode 100644 index 00000000..96b46f3a --- /dev/null +++ b/src/ts/src/g3dMesh.ts @@ -0,0 +1,299 @@ +/** + * @module vim-ts + */ + +import { AbstractG3d } from './abstractG3d' +import { BFast } from './bfast' +import { G3d, MeshSection } from './g3d' +import { G3dMaterial } from './g3dMaterials' + +/** + * See https://github.com/vimaec/vim#vim-geometry-attributes + */ +export class MeshAttributes { + + static instanceNodes = 'g3d:instance:node:0:int32:1' + static instanceTransforms = 'g3d:instance:transform:0:float32:16' + static instanceFlags = 'g3d:instance:flags:0:uint16:1' + static meshOpaqueSubmeshCount = 'g3d:mesh:opaquesubmeshcount:0:int32:1' + static submeshIndexOffsets = 'g3d:submesh:indexoffset:0:int32:1' + static submeshVertexOffsets = 'g3d:submesh:vertexoffset:0:int32:1' + static submeshMaterials = 'g3d:submesh:material:0:int32:1' + static positions = 'g3d:vertex:position:0:float32:3' + static indices = 'g3d:corner:index:0:int32:1' + + static all = [ + MeshAttributes.instanceNodes, + MeshAttributes.instanceTransforms, + MeshAttributes.instanceFlags, + MeshAttributes.meshOpaqueSubmeshCount, + MeshAttributes.submeshIndexOffsets, + MeshAttributes.submeshVertexOffsets, + MeshAttributes.submeshMaterials, + MeshAttributes.positions, + MeshAttributes.indices, + ] +} + +/** + * G3D is a simple, efficient, generic binary format for storing and transmitting geometry. + * The G3D format is designed to be used either as a serialization format or as an in-memory data structure. + * A G3d with specific attributes according to the VIM format specification. + * See https://github.com/vimaec/vim#vim-geometry-attributes for the vim specification. + * See https://github.com/vimaec/g3d for the g3d specification. + */ +export class G3dMesh { + rawG3d: AbstractG3d + + instanceNodes: Int32Array + instanceTransforms: Float32Array + instanceFlags: Uint16Array + + meshOpaqueSubmeshCount : number + + submeshIndexOffset: Int32Array + submeshVertexOffset: Int32Array + submeshMaterial: Int32Array + + positions: Float32Array + indices: Uint32Array + + static MATRIX_SIZE = 16 + static COLOR_SIZE = 4 + static POSITION_SIZE = 3 + /** + * Opaque white + */ + DEFAULT_COLOR = new Float32Array([1, 1, 1, 1]) + + constructor( + instanceNodes: Int32Array | undefined, + instanceTransforms: Float32Array, + instanceFlags: Uint16Array | undefined, + meshOpaqueSubmeshCount : number, + submeshIndexOffsets : Int32Array, + submeshVertexOffsets : Int32Array, + submeshMaterials : Int32Array, + indices: Int32Array | Uint32Array, + positions: Float32Array, + ){ + + this.instanceNodes = instanceNodes + this.instanceTransforms = instanceTransforms + this.instanceFlags = instanceFlags + this.meshOpaqueSubmeshCount = meshOpaqueSubmeshCount + this.submeshIndexOffset = submeshIndexOffsets + this.submeshVertexOffset = submeshVertexOffsets + this.submeshMaterial = submeshMaterials + this.indices = indices instanceof Uint32Array ? indices : new Uint32Array(indices.buffer) + this.positions = positions + + if(this.instanceFlags === undefined){ + this.instanceFlags = new Uint16Array(this.instanceNodes.length) + } + } + + static createFromAbstract(g3d: AbstractG3d) { + + const instanceNodes = g3d.findAttribute( + MeshAttributes.instanceNodes + )?.data as Int32Array + + const instanceTransforms = g3d.findAttribute( + MeshAttributes.instanceTransforms + )?.data as Float32Array + + const instanceFlags = + (g3d.findAttribute(MeshAttributes.instanceFlags)?.data as Uint16Array) ?? + new Uint16Array(instanceNodes.length) + + const meshOpaqueSubmeshCountArray = g3d.findAttribute( + MeshAttributes.meshOpaqueSubmeshCount + )?.data as Int32Array + const meshOpaqueSubmeshCount = meshOpaqueSubmeshCountArray[0] + + const submeshIndexOffsets = g3d.findAttribute( + MeshAttributes.submeshIndexOffsets + )?.data as Int32Array + + const submeshVertexOffsets = g3d.findAttribute( + MeshAttributes.submeshVertexOffsets + )?.data as Int32Array + + const submeshMaterial = g3d.findAttribute(MeshAttributes.submeshMaterials) + ?.data as Int32Array + + const indices = g3d.findAttribute(MeshAttributes.indices)?.data as Int32Array + + const positions = g3d.findAttribute(MeshAttributes.positions) + ?.data as Float32Array + + const result = new G3dMesh( + instanceNodes, + instanceTransforms, + instanceFlags, + meshOpaqueSubmeshCount, + submeshIndexOffsets, + submeshVertexOffsets, + submeshMaterial, + indices, + positions, + ) + result.rawG3d = g3d + + return result + } + + static async createFromPath (path: string) { + const f = await fetch(path) + const buffer = await f.arrayBuffer() + var g3d = this.createFromBuffer(buffer) + + return g3d + } + + static async createFromBuffer (buffer: ArrayBuffer) { + const bfast = new BFast(buffer) + return this.createFromBfast(bfast) + } + + static async createFromBfast (bfast: BFast) { + const g3d = await AbstractG3d.createFromBfast(bfast, MeshAttributes.all) + return G3dMesh.createFromAbstract(g3d) + } + + toG3d(materials : G3dMaterial){ + return new G3d( + new Int32Array(this.getInstanceCount()), + this.instanceFlags, + this.instanceTransforms, + this.instanceNodes, + new Int32Array(1).fill(0), + this.submeshIndexOffset, + this.submeshMaterial, + this.indices, + this.positions, + materials.materialColors + ) + } + + insert(g3d: G3dMesh, + instanceStart: number, + submesStart: number, + indexStart: number, + vertexStart: number, + materialStart: number + ){ + this.instanceNodes.set(g3d.instanceNodes, instanceStart) + this.instanceTransforms.set(g3d.instanceTransforms, instanceStart * G3dMesh.MATRIX_SIZE) + this.instanceFlags.set(g3d.instanceFlags, instanceStart) + + this.submeshIndexOffset.set(g3d.submeshIndexOffset, submesStart) + this.submeshMaterial.set(g3d.submeshMaterial, submesStart) + + this.indices.set(g3d.indices, indexStart) + this.positions.set(g3d.positions, vertexStart) + } + + // ------------- Mesh ----------------- + + getVertexStart(section: MeshSection = 'all'){ + const sub = this.getSubmeshStart(section) + return this.getSubmeshVertexStart(sub) + } + + getVertexEnd(section: MeshSection = 'all'){ + const sub = this.getSubmeshEnd(section) + return this.getSubmeshVertexStart(sub) + } + + getVertexCount(section: MeshSection = 'all'){ + return this.getVertexEnd(section) - this.getVertexStart(section) + } + + getIndexStart(section: MeshSection = 'all'){ + const sub = this.getSubmeshStart(section) + return this.getSubmeshIndexStart(sub) + } + + getIndexEnd(section: MeshSection = 'all'){ + const sub = this.getSubmeshEnd(section) + return this.getSubmeshIndexStart(sub) + } + + getIndexCount (section: MeshSection = 'all'): number { + return this.getIndexEnd(section) - this.getIndexStart(section) + } + + getHasTransparency () { + return this.meshOpaqueSubmeshCount < this.submeshIndexOffset.length} + + // ------------- Submeshes ----------------- + + getSubmeshStart(section: MeshSection){ + if(section === 'all') return 0 + if(section === 'opaque') return 0 + return this.meshOpaqueSubmeshCount + } + + getSubmeshEnd(section: MeshSection){ + if(section === 'all') return this.submeshIndexOffset.length + if(section === 'transparent') return this.submeshIndexOffset.length + return this.meshOpaqueSubmeshCount + } + + getSubmeshCount(section: MeshSection){ + return this.getSubmeshEnd(section) - this.getSubmeshStart(section) + } + + getSubmeshIndexStart (submesh: number): number { + return submesh < this.submeshIndexOffset.length + ? this.submeshIndexOffset[submesh] + : this.indices.length + } + + getSubmeshIndexEnd (submesh: number): number { + return submesh < this.submeshIndexOffset.length - 1 + ? this.submeshIndexOffset[submesh + 1] + : this.indices.length + } + + getSubmeshIndexCount (submesh: number): number { + return this.getSubmeshIndexEnd(submesh) - this.getSubmeshIndexStart(submesh) + } + + getSubmeshVertexStart(submesh: number){ + return submesh < this.submeshIndexOffset.length + ? this.submeshVertexOffset[submesh] + : this.positions.length / G3d.POSITION_SIZE + } + + getSubmeshVertexEnd (submesh: number): number { + return submesh < this.submeshVertexOffset.length - 1 + ? this.submeshVertexOffset[submesh + 1] + : this.positions.length / G3d.POSITION_SIZE + } + + getSubmeshVertexCount (submesh: number): number { + return this.getSubmeshVertexEnd(submesh) - this.getSubmeshVertexStart(submesh) + } + + // ------------- Instances ----------------- + getInstanceCount = () => this.instanceNodes.length + + getInstanceHasFlag(instance: number, flag: number){ + return (this.instanceFlags[instance] & flag) > 0 + } + + /** + * Returns an 16 number array representation of the matrix for given instance + * @param instance g3d instance index + */ + getInstanceMatrix (instance: number): Float32Array { + return this.instanceTransforms.subarray( + instance * G3dMesh.MATRIX_SIZE, + (instance + 1) * G3dMesh.MATRIX_SIZE + ) + } +} + diff --git a/src/ts/src/g3dMeshIndex.ts b/src/ts/src/g3dMeshIndex.ts new file mode 100644 index 00000000..bf0c70f9 --- /dev/null +++ b/src/ts/src/g3dMeshIndex.ts @@ -0,0 +1,201 @@ +/** + * @module vim-ts + */ + +import { AbstractG3d } from './abstractG3d' +import { BFast } from './bfast' +import { MeshSection } from './g3d' +import { G3dSubset } from './g3dSubset' + + +export type FilterMode = undefined | 'mesh' | 'instance' | 'group' | 'tag' + +/** + * See https://github.com/vimaec/vim#vim-geometry-attributes + */ +export class MeshIndexAttributes { + + static instanceFiles = 'g3d:instance:file:0:int32:1' + static instanceIndices = 'g3d:instance:index:0:int32:1' + static instanceNodes = 'g3d:instance:node:0:int32:1' + static instanceGroups = 'g3d:instance:group:0:int32:1' + static instanceTags = 'g3d:instance:tag:0:int64:1' + + static meshInstanceCounts = 'g3d:mesh:instancecount:0:int32:1' + static meshIndexCounts = 'g3d:mesh:indexcount:0:int32:1' + static meshVertexCounts = 'g3d:mesh:vertexcount:0:int32:1' + + static meshOpaqueIndexCount = "g3d:mesh:opaqueindexcount:0:int32:1" + static meshOpaqueVertexCount = "g3d:mesh:opaquevertexcount:0:int32:1" + + static all = [ + MeshIndexAttributes.instanceFiles, + MeshIndexAttributes.instanceIndices, + MeshIndexAttributes.instanceNodes, + MeshIndexAttributes.instanceGroups, + MeshIndexAttributes.instanceTags, + + MeshIndexAttributes.meshInstanceCounts, + MeshIndexAttributes.meshIndexCounts, + MeshIndexAttributes.meshVertexCounts, + + MeshIndexAttributes.meshOpaqueIndexCount, + MeshIndexAttributes.meshOpaqueVertexCount, + ] +} + +/** + * Represents the index, as in book index, of a collection of G3dMesh. + * Allows to find and download G3dMesh as needed. + * Allows to preallocate geometry to render G3dMeshes. + */ +export class G3dMeshIndex { + rawG3d: AbstractG3d + + instanceFiles: Int32Array + instanceIndices: Int32Array + instanceNodes: Int32Array + instanceGroups: Int32Array + instanceTags : BigInt64Array + + meshInstanceCounts: Int32Array + meshIndexCounts: Int32Array + meshVertexCounts: Int32Array + + meshOpaqueIndexCounts: Int32Array + meshOpaqueVertexCounts: Int32Array + + constructor( + rawG3d: AbstractG3d, + + instanceFiles: Int32Array, + instanceIndices: Int32Array, + instanceNodes: Int32Array, + instanceGroups: Int32Array, + instanceTags: BigInt64Array, + + meshInstanceCounts: Int32Array, + meshIndexCounts : Int32Array, + meshVertexCounts: Int32Array, + + meshOpaqueIndexCounts: Int32Array, + meshOpaqueVertexCounts: Int32Array, + ){ + + this.rawG3d = rawG3d + + this.instanceFiles = instanceFiles + this.instanceIndices = instanceIndices + this.instanceNodes = instanceNodes + this.instanceGroups = instanceGroups + this.instanceTags = instanceTags + + this.meshInstanceCounts = meshInstanceCounts + + this.meshIndexCounts = meshIndexCounts + this.meshVertexCounts = meshVertexCounts + + this.meshOpaqueIndexCounts = meshOpaqueIndexCounts + this.meshOpaqueVertexCounts = meshOpaqueVertexCounts + } + + static createFromAbstract(g3d: AbstractG3d) { + + function getArray(attribute: string){ + return g3d.findAttribute( + attribute + )?.data as T + } + + return new G3dMeshIndex( + g3d, + getArray(MeshIndexAttributes.instanceFiles), + getArray(MeshIndexAttributes.instanceIndices), + getArray(MeshIndexAttributes.instanceNodes), + getArray(MeshIndexAttributes.instanceGroups), + getArray(MeshIndexAttributes.instanceTags), + + getArray(MeshIndexAttributes.meshInstanceCounts), + + getArray(MeshIndexAttributes.meshIndexCounts), + getArray(MeshIndexAttributes.meshVertexCounts), + + getArray(MeshIndexAttributes.meshOpaqueIndexCount), + getArray(MeshIndexAttributes.meshOpaqueVertexCount), + ) + } + + static async createFromPath (path: string) { + const f = await fetch(path) + const buffer = await f.arrayBuffer() + const bfast = new BFast(buffer) + return this.createFromBfast(bfast) + } + + static async createFromBfast (bfast: BFast) { + const g3d = await AbstractG3d.createFromBfast(bfast, MeshIndexAttributes.all) + return G3dMeshIndex.createFromAbstract(g3d) + } + + getMeshCount() { + return this.meshInstanceCounts.length + } + + getMeshIndexCount(mesh: number, section: MeshSection){ + const all = this.meshIndexCounts[mesh] + if(section === 'all') return all; + const opaque = this.meshOpaqueIndexCounts[mesh] + return section === 'opaque' ? opaque : all - opaque + } + + getMeshVertexCount(mesh:number, section: MeshSection){ + const all = this.meshVertexCounts[mesh] + if(section === 'all') return all; + const opaque = this.meshOpaqueVertexCounts[mesh] + return section === 'opaque' ? opaque : all - opaque + } + + getMeshInstanceCount(mesh:number){ + return this.meshInstanceCounts[mesh] + } + + filter(mode: FilterMode, filter: number[]){ + if(filter === undefined || mode === undefined){ + return new G3dSubset(this, undefined) + } + if(mode === 'instance'){ + return this.getMeshesFromInstances(filter) + } + + if(mode === 'mesh'){ + return new G3dSubset(this, filter) + } + if(mode === 'tag' || mode === 'group'){ + throw new Error("Filter Mode Not implemented") + } + } + + private getMeshesFromInstances(instances: number[]){ + const set = new Set(instances) + const meshes = new Array() + const map = new Map() + for(let i=0; i < this.instanceNodes.length; i ++){ + const node = this.instanceNodes[i] + if(set.has(node)){ + const mesh = this.instanceFiles[i] + const index = this.instanceIndices[i] + + if(!map.has(mesh)){ + meshes.push(mesh) + map.set(mesh, [index]) + } + else{ + map.get(mesh).push(index) + } + } + } + const meshInstances = new Array>(meshes.length) + meshes.forEach((m, i) => meshInstances[i] = map.get(m)) + return new G3dSubset(this, meshes, meshInstances) + } +} diff --git a/src/ts/src/g3dMeshOffsets.ts b/src/ts/src/g3dMeshOffsets.ts new file mode 100644 index 00000000..1236b70d --- /dev/null +++ b/src/ts/src/g3dMeshOffsets.ts @@ -0,0 +1,88 @@ +import { G3d, MeshSection } from "./g3d" +import { G3dSubset } from "./g3dSubset" + +export class G3dMeshCounts{ + instances : number = 0 + meshes: number = 0 + indices : number = 0 + vertices : number = 0 +} + +/** + * Holds the offsets needed to preallocate geometry for a given meshIndexSubset + */ +export class G3dMeshOffsets { + // inputs + subset: G3dSubset + section: MeshSection + + // computed + counts : G3dMeshCounts + indexOffsets: Int32Array + vertexOffsets: Int32Array + + /** + * Computes geometry offsets for given subset and section + * @param subset subset for which to compute offsets + * @param section on of 'opaque' | 'transparent' | 'all' + */ + static fromSubset ( + subset: G3dSubset, + section: MeshSection){ + var result = new G3dMeshOffsets() + result.subset = subset + result.section = section + + function computeOffsets(getter: (mesh: number) => number){ + const meshCount = subset.getMeshCount() + const offsets = new Int32Array(meshCount) + + for(let i=1; i < meshCount; i ++){ + offsets[i] = offsets[i-1] + getter(i-1) + } + return offsets + } + + result.counts = subset.getAttributeCounts(section) + result.indexOffsets = computeOffsets((m) => subset.getMeshIndexCount(m, section)) + result.vertexOffsets = computeOffsets((m) => subset.getMeshVertexCount(m, section)) + + return result + } + + getIndexOffset(mesh: number){ + return mesh < this.counts.meshes + ? this.indexOffsets[mesh] + : this.counts.indices + } + + getVertexOffset(mesh: number){ + return mesh < this.counts.meshes + ? this.vertexOffsets[mesh] + : this.counts.vertices + } + + /** + * Returns how many instances of given meshes are the filtered view. + */ + getMeshInstanceCount(mesh: number){ + return this.subset.getMeshInstanceCount(mesh) + } + + /** + * Returns instance for given mesh. + * @mesh view-relative mesh index + * @at view-relative instance index for given mesh + * @returns mesh-relative instance index + */ + getMeshInstance(mesh: number, index: number){ + return this.subset.getMeshInstance(mesh, index) + } + + /** + * Returns the vim-relative mesh index at given index + */ + getMesh(index: number){ + return this.subset.getMesh(index) + } +} \ No newline at end of file diff --git a/src/ts/src/g3dSubset.ts b/src/ts/src/g3dSubset.ts new file mode 100644 index 00000000..ab0371fd --- /dev/null +++ b/src/ts/src/g3dSubset.ts @@ -0,0 +1,133 @@ +import { G3d, MeshSection } from './g3d' +import { G3dMeshIndex } from './g3dMeshIndex' +import { G3dMeshCounts, G3dMeshOffsets } from './g3dMeshOffsets' + +/** + * Represents a filter applied to a G3dMeshIndex. + */ +export class G3dSubset +{ + private _source: G3dMeshIndex | G3d + private _meshes: number[] | undefined + private _meshInstances : (number[] | undefined)[] | undefined + +/** + * @param index G3d source geometry. + * @param meshes indices of meshes to include or undefined if all meshes. + * @param meshToInstances indices of instances to include for each mesh or undefined if all meshes. + */ + constructor(index: G3dMeshIndex | G3d, meshes?: number[], meshToInstances? : number[][]){ + this._source = index + this._meshes = meshes + this._meshInstances = meshToInstances + } + + getMesh(index: number){ + return this._meshes?.[index] ?? index + } + + getMeshCount(){ + return this._meshes?.length ?? this._source.getMeshCount() + } + + /** + * Returns index count for given mesh and section. + */ + getMeshIndexCount(mesh: number, section: MeshSection){ + const instances = this.getMeshInstanceCount(mesh) + const indices = this._source.getMeshIndexCount(this.getMesh(mesh), section) + return indices * instances + } + + /** + * Returns vertext count for given mesh and section. + */ + getMeshVertexCount(mesh: number, section: MeshSection){ + const instances = this.getMeshInstanceCount(mesh) + const vertices = this._source.getMeshVertexCount(this.getMesh(mesh), section) + return vertices * instances + } + + /** + * Returns instance count for given mesh. + * @param mesh The index of the mesh from the g3dIndex. + */ + getMeshInstanceCount(mesh: number){ + return this._meshInstances + ? this._meshInstances[mesh].length + : this._source.getMeshInstanceCount(this.getMesh(mesh)) + } + + /** + * Returns index-th mesh-based instance index for given mesh. + * @param mesh The index of the mesh from the g3dIndex. + */ + getMeshInstance(mesh: number, index:number){ + const instance = this._meshInstances + ? this._meshInstances[mesh][index] + : index + + if(this._source instanceof G3d){ + // Dereference one more time. + return this._source.meshInstances[mesh][instance] + } + + return instance + } + + /** + * Returns the list of mesh-based instance indices for given mesh or undefined if all instances are included. + * @param mesh The index of the mesh from the g3dIndex. + */ + getMeshInstances(mesh: number){ + return this._meshInstances?.[mesh] + } + + /** + * Returns a new subset that only contains unique meshes. + */ + filterUniqueMeshes(){ + return this.filterByCount(count => count === 1) + } + + /** + * Returns a new subset that only contains non-unique meshes. + */ + filterNonUniqueMeshes(){ + return this.filterByCount(count =>count > 1) + } + + private filterByCount(predicate : (i: number) => boolean){ + const filteredMeshes = new Array() + const filteredInstances = this._meshInstances ? new Array>() : undefined + const count = this.getMeshCount() + for(let m =0; m < count; m++){ + if(predicate(this.getMeshInstanceCount(m))){ + filteredMeshes.push(this.getMesh(m)) + filteredInstances?.push(this.getMeshInstances(m)) + } + } + return new G3dSubset(this._source, filteredMeshes, filteredInstances) + } + + /** + * Returns offsets needed to build geometry. + */ + getOffsets(section: MeshSection){ + return G3dMeshOffsets.fromSubset(this, section) + } + + getAttributeCounts(section: MeshSection = 'all'){ + + const result = new G3dMeshCounts() + const count = this.getMeshCount() + for(let i = 0; i < count; i ++){ + result.instances += this.getMeshInstanceCount(i) + result.indices += this.getMeshIndexCount(i, section) + result.vertices += this.getMeshVertexCount(i, section) + } + result.meshes = count + + return result + } +} diff --git a/src/ts/src/index.ts b/src/ts/src/index.ts index 512011ba..82600355 100644 --- a/src/ts/src/index.ts +++ b/src/ts/src/index.ts @@ -1,9 +1,17 @@ // Links files to generate package type exports export * from './bfast' export * from './g3d' +export * from './remoteGeometry' +export * from './g3dMaterials' +export * from './g3dMesh' +export * from './g3dMeshIndex' +export * from './g3dSubset' +export * from './g3dMeshOffsets' export * from './remoteG3d' export * from './remoteBuffer' export * from './requestTracker' +export * from './requester' +export * from './remoteValue' export * from './vimHeader' export * from './objectModel' diff --git a/src/ts/src/remoteBuffer.ts b/src/ts/src/remoteBuffer.ts index 8fdb5e6c..c350a235 100644 --- a/src/ts/src/remoteBuffer.ts +++ b/src/ts/src/remoteBuffer.ts @@ -13,7 +13,7 @@ export function setRemoteBufferMaxConcurency(value: number){ } -class RetryRequest { +export class RetryRequest { url: string range: string | undefined // eslint-disable-next-line no-undef diff --git a/src/ts/src/remoteG3d.ts b/src/ts/src/remoteG3d.ts index a20065a1..8478d9d0 100644 --- a/src/ts/src/remoteG3d.ts +++ b/src/ts/src/remoteG3d.ts @@ -1,5 +1,6 @@ import { BFast, typeSize } from "./bfast" -import { G3d, G3dAttribute, G3dAttributeDescriptor, MeshSection, TypedArray, VimAttributes } from "./g3d" +import { G3d, VimAttributes } from "./g3d" +import { G3dAttribute, G3dAttributeDescriptor, TypedArray } from "./g3dAttributes" class G3dRemoteAttribute { descriptor: G3dAttributeDescriptor diff --git a/src/ts/src/remoteGeometry.ts b/src/ts/src/remoteGeometry.ts new file mode 100644 index 00000000..f5b5d6dd --- /dev/null +++ b/src/ts/src/remoteGeometry.ts @@ -0,0 +1,36 @@ +import { BFast } from "./bfast"; +import { G3dMaterial as G3dMaterials } from "./g3dMaterials"; +import { G3dMesh } from "./g3dMesh"; +import { G3dMeshIndex } from "./g3dMeshIndex"; +import { RemoteBuffer } from "./remoteBuffer"; + + +export class RemoteGeometry{ + bfast : BFast + + constructor(bfast : BFast){ + this.bfast = bfast + } + + static async fromPath(path: string){ + const buffer = new RemoteBuffer(path) + const bfast = new BFast(buffer) + return new RemoteGeometry(bfast) + } + + async getIndex(){ + const index = await this.bfast.getLocalBfast('index', true) + return G3dMeshIndex.createFromBfast(index) + } + + async getMaterials(){ + const mat = await this.bfast.getLocalBfast('materials', true) + return G3dMaterials.createFromBfast(mat) + } + + async getMesh(mesh: number){ + const m = await this.bfast.getLocalBfast(`mesh_${mesh}`, true) + return G3dMesh.createFromBfast(m) + } + +} \ No newline at end of file diff --git a/src/ts/src/remoteValue.ts b/src/ts/src/remoteValue.ts index 28cd9c37..71548c32 100644 --- a/src/ts/src/remoteValue.ts +++ b/src/ts/src/remoteValue.ts @@ -11,7 +11,7 @@ export class RemoteValue { private _value: T | undefined private _request: Promise | undefined - constructor (getter: () => Promise, label?: string) { + constructor (getter: () => Promise, label?: string) { this._getter = getter this.label = label ?? '' } diff --git a/src/ts/src/requestTracker.ts b/src/ts/src/requestTracker.ts index 4359bbd1..c4a3a537 100644 --- a/src/ts/src/requestTracker.ts +++ b/src/ts/src/requestTracker.ts @@ -40,7 +40,7 @@ export class RequestTracker { */ onUpdate: ((self: RequestTracker) => void) | undefined = undefined - constructor (source: string, logger : Logger = new NoLog()) { + constructor (source?: string, logger : Logger = new NoLog()) { this.source = source this.logs = logger } diff --git a/src/ts/src/requester.ts b/src/ts/src/requester.ts new file mode 100644 index 00000000..194930d0 --- /dev/null +++ b/src/ts/src/requester.ts @@ -0,0 +1,84 @@ +import { DefaultLog, Logger, NoLog } from "./logging" +import { RetryRequest } from "./remoteBuffer" +import { IProgressLogs, RequestTracker } from "./requestTracker" + +/** + * Wrapper to provide tracking for all webrequests via request logger. + */ +export class Requester { + maxConcurency: number = 10 + onProgress: (progress : IProgressLogs) => void + private _tracker: RequestTracker + private _logs : Logger + private _queue: RetryRequest[] = [] + private _active: Set = new Set() + + constructor (verbose: boolean = false) { + this._logs = verbose ? new DefaultLog() : new NoLog() + this._tracker = new RequestTracker(undefined, this._logs) + this._tracker.onUpdate = (p) => this.onProgress?.(p) + } + + abort(){ + this._active.forEach(request => { + request.abort() + }) + this._active.clear() + this._queue.length = 0 + } + + async http (url : string, label?: string) { + const request = new RetryRequest(url, undefined, 'arraybuffer') + request.msg = url + + this.enqueue(request) + return new Promise((resolve, reject) => { + this._tracker.start(label) + + request.onProgress = (e) => { + this._tracker.update(label, e) + } + request.onLoad = (result) => { + this._tracker.end(label) + resolve(result) + this.end(request) + } + request.onError = () => { + this._tracker.fail(label) + this.retry(request) + } + }) + } + + private enqueue (xhr: RetryRequest) { + this._queue.push(xhr) + this.next() + } + + private retry (xhr: RetryRequest) { + this._active.delete(xhr) + this.maxConcurency = Math.max(1, this.maxConcurency - 1) + setTimeout(() => this.enqueue(xhr), 2000) + } + + private end (xhr: RetryRequest) { + this._active.delete(xhr) + this.next() + } + + private next () { + if (this._queue.length === 0) { + return + } + + if (this._active.size >= this.maxConcurency) { + return + } + + const next = this._queue[0] + this._queue.shift() + this._active.add(next) + next.send() + this._logs.log('Starting ' + next.msg) + } +} From 982122ad38312adf7ec693f3326e8ba9646c87d2 Mon Sep 17 00:00:00 2001 From: simon Date: Mon, 28 Aug 2023 14:17:04 -0400 Subject: [PATCH 002/111] package update --- src/ts/package.json | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/ts/package.json b/src/ts/package.json index 735383c3..a59a5e47 100644 --- a/src/ts/package.json +++ b/src/ts/package.json @@ -1,6 +1,6 @@ { "name": "vim-format", - "version": "1.0.4", + "version": "1.0.6-dev.100", "description": "The VIM format is a modern and efficient open 3D data interchange format designed for BIM and manufacturing data optimized for efficient loading and rendering on low-power devices.", "directories": { "test": "tests" @@ -26,8 +26,12 @@ "devDependencies": { "@types/jest": "^29.5.2", "@types/node": "^18.16.16", + "@types/pako": "^2.0.0", "jest": "^29.2.2", "ts-jest": "^29.0.3", "typescript": "^4.8.4" + }, + "dependencies": { + "pako": "^2.1.0" } } From 6ac812b9a69587bb456110677d8d7b07e60fb851 Mon Sep 17 00:00:00 2001 From: simon Date: Wed, 30 Aug 2023 11:15:07 -0400 Subject: [PATCH 003/111] added abort to remote geometry and bfast --- src/ts/src/bfast.ts | 9 +++++++++ src/ts/src/remoteGeometry.ts | 25 +++++++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/src/ts/src/bfast.ts b/src/ts/src/bfast.ts index cc10fd4e..738d91aa 100644 --- a/src/ts/src/bfast.ts +++ b/src/ts/src/bfast.ts @@ -218,6 +218,15 @@ export function parseName(name: string): [number, NumericArrayConstructor]{ this._children = new Map>() this._ranges = new RemoteValue(() => this.requestRanges(), name + '.ranges') } + + /** + * Aborts all downloads from the underlying RemoteBuffer + */ + abort(){ + if(this.source instanceof RemoteBuffer){ + this.source.abort() + } + } /** * @returns Bfast Header diff --git a/src/ts/src/remoteGeometry.ts b/src/ts/src/remoteGeometry.ts index f5b5d6dd..ae9a0828 100644 --- a/src/ts/src/remoteGeometry.ts +++ b/src/ts/src/remoteGeometry.ts @@ -12,22 +12,47 @@ export class RemoteGeometry{ this.bfast = bfast } + + static async fromPath(path: string){ const buffer = new RemoteBuffer(path) const bfast = new BFast(buffer) return new RemoteGeometry(bfast) } + /** + * Aborts all downloads from the underlying BFAST. + */ + abort(){ + this.bfast.abort() + } + + /** + * Downloads underlying bfast making all subsequent request local. + */ + async download(){ + this.bfast.forceDownload() + } + + /** + * Fetches and returns the vimx G3dMeshIndex + */ async getIndex(){ const index = await this.bfast.getLocalBfast('index', true) return G3dMeshIndex.createFromBfast(index) } + /** + * Fetches and returns the vimx G3dMaterials + */ async getMaterials(){ const mat = await this.bfast.getLocalBfast('materials', true) return G3dMaterials.createFromBfast(mat) } + /** + * Fetches and returns the vimx G3dMesh with given index + */ async getMesh(mesh: number){ const m = await this.bfast.getLocalBfast(`mesh_${mesh}`, true) return G3dMesh.createFromBfast(m) From 4f31190e52f52b6e1622d349cfb5604f021419db Mon Sep 17 00:00:00 2001 From: simon Date: Tue, 26 Sep 2023 13:44:54 -0400 Subject: [PATCH 004/111] progress on VimX --- src/cs/Vim.BFast.Next/BFastNext.cs | 129 + src/cs/Vim.BFast.Next/BFastNextExtensions.cs | 64 + src/cs/Vim.BFast.Next/BFastNextNode.cs | 77 + src/cs/Vim.BFast.Next/IBFastNextNode.cs | 19 + src/cs/Vim.BFast.Next/Vim.BFastNext.csproj | 12 + src/cs/Vim.BFastNext.Tests/BFastNextTests.cs | 390 ++ .../Vim.BFastNext.Tests.csproj | 25 + src/cs/bfast/Vim.BFast/BFast.cs | 48 +- src/cs/bfast/Vim.BFast/BFastBufferReader.cs | 44 +- src/cs/bfast/Vim.BFast/BFastBuilder.cs | 6 +- src/cs/bfast/Vim.BFast/UnsafeHelpers.cs | 38 + src/cs/bfast/Vim.BFast/Vim.BFast.csproj | 2 +- src/cs/g3d/Vim.G3d/G3D.cs | 1 - src/cs/g3d/Vim.G3d/Vim.G3dNext.csproj | 14 + .../Vim.G3dNext.Attributes/Attributes.g.cs | 2911 ++++++++ .../MaterialAttributes.cs | 23 + .../Vim.G3dNext.Attributes/MeshAttributes.cs | 39 + .../Vim.G3dNext.Attributes/SceneAttributes.cs | 61 + .../Vim.G3dNext.Attributes.csproj | 15 + .../Vim.G3dNext.Attributes/VimAttributes.cs | 70 + src/cs/g3d/Vim.G3dNext.CodeGen/CodeBuilder.cs | 64 + .../G3dAttributeCollectionGenerator.cs | 296 + src/cs/g3d/Vim.G3dNext.CodeGen/Program.cs | 11 + .../Vim.G3dNext.CodeGen.csproj | 29 + .../Vim.G3dNext.Tests.csproj | 38 + src/cs/g3d/Vim.G3dNext/AttributeDescriptor.cs | 182 + .../Vim.G3dNext/AttributeDescriptorErrors.cs | 17 + src/cs/g3d/Vim.G3dNext/AttributeType.cs | 13 + src/cs/g3d/Vim.G3dNext/CodeGenAttributes.cs | 38 + src/cs/g3d/Vim.G3dNext/Constants.cs | 16 + src/cs/g3d/Vim.G3dNext/DataType.cs | 87 + src/cs/g3d/Vim.G3dNext/G3DNext.cs | 111 + src/cs/g3d/Vim.G3dNext/IAttribute.cs | 73 + .../g3d/Vim.G3dNext/IAttributeCollection.cs | 140 + .../g3d/Vim.G3dNext/IAttributeDescriptor.cs | 88 + src/cs/g3d/Vim.G3dNext/MetaHeader.cs | 89 + src/cs/g3d/Vim.G3dNext/Vim.G3dNext.csproj | 16 + .../temp/Vim.G3dNext.Attributes/Attributes.cs | 178 + .../Vim.G3dNext.Attributes/Attributes.g.cs | 2042 ++++++ .../Vim.G3dNext.Attributes.csproj | 34 + .../VimAttributeCollectionExtensions.cs | 86 + .../g3d/temp/Vim.G3dNext.Tests/AssimpTests.cs | 237 + .../g3d/temp/Vim.G3dNext.Tests/FileUtils.cs | 183 + .../g3d/temp/Vim.G3dNext.Tests/TestUtils.cs | 113 + .../Vim.G3dNext.Tests.csproj | 46 + .../g3d/temp/Vim.G3dNext.Tests/VimG3dTests.cs | 270 + .../Properties/Resources.Designer.cs | 2 +- src/cs/vim-format.sln | 51 +- .../vim/Vim.Format.Core/SerializableHeader.cs | 12 +- src/cs/vim/Vim.Format.Core/Serializer.cs | 2 +- src/cs/vim/Vim.Format.Vimx/FileUtils.cs | 38 + src/cs/vim/Vim.Format.Vimx/G3dMaterials.cs | 48 + src/cs/vim/Vim.Format.Vimx/G3dMesh.cs | 255 + .../vim/Vim.Format.Vimx/G3dMeshExtensions.cs | 85 + src/cs/vim/Vim.Format.Vimx/G3dScene.cs | 70 + src/cs/vim/Vim.Format.Vimx/G3dVim.cs | 288 + src/cs/vim/Vim.Format.Vimx/G3dVimFilter.cs | 152 + src/cs/vim/Vim.Format.Vimx/G3dVimMeshes.cs | 162 + src/cs/vim/Vim.Format.Vimx/G3dVimScene.cs | 99 + .../Vim.Format.Vimx/Vim.Format.Vimx.csproj | 20 + src/cs/vim/Vim.Format.Vimx/Vimx.cs | 85 + src/cs/vim/Vim.Format.Vimx/VimxHeader.cs | 37 + .../vim/Vim.Format/SceneBuilder/VimScene.cs | 20 + src/cs/vim/Vim.Vimx.Test/TestUtils.cs | 124 + .../Vim.Vimx.Test/Vim.Format.Vimx.Test.csproj | 26 + src/cs/vim/Vim.Vimx.Test/VimG3dTests.cs | 197 + src/cs/vim/Vim.Vimx.Test/VimxActions.cs | 20 + src/cs/vim/Vim.Vimx.Test/VimxTests.cs | 34 + src/ts/dist/abstractG3d.d.ts | 17 + src/ts/dist/abstractG3d.js | 39 + src/ts/dist/bfast.d.ts | 141 + src/ts/dist/bfast.js | 456 ++ src/ts/dist/converters.d.ts | 46 + src/ts/dist/converters.js | 145 + src/ts/dist/entityTable.d.ts | 22 + src/ts/dist/entityTable.js | 128 + src/ts/dist/g3d.d.ts | 178 + src/ts/dist/g3d.js | 609 ++ src/ts/dist/g3dAttributes.d.ts | 20 + src/ts/dist/g3dAttributes.js | 68 + src/ts/dist/g3dMaterials.d.ts | 38 + src/ts/dist/g3dMaterials.js | 74 + src/ts/dist/g3dMesh.d.ts | 79 + src/ts/dist/g3dMesh.js | 189 + src/ts/dist/g3dMeshIndex.d.ts | 61 + src/ts/dist/g3dMeshIndex.js | 142 + src/ts/dist/g3dMeshOffsets.d.ts | 41 + src/ts/dist/g3dMeshOffsets.js | 71 + src/ts/dist/g3dScene.d.ts | 63 + src/ts/dist/g3dScene.js | 145 + src/ts/dist/g3dSubset.d.ts | 108 + src/ts/dist/g3dSubset.js | 323 + src/ts/dist/index.d.ts | 15 + src/ts/dist/index.js | 45 + src/ts/dist/logging.d.ts | 18 + src/ts/dist/logging.js | 25 + src/ts/dist/objectModel.d.ts | 3356 +++++++++ src/ts/dist/objectModel.js | 5996 +++++++++++++++++ src/ts/dist/remoteBuffer.d.ts | 40 + src/ts/dist/remoteBuffer.js | 149 + src/ts/dist/remoteG3d.d.ts | 67 + src/ts/dist/remoteG3d.js | 384 ++ src/ts/dist/remoteGeometry.d.ts | 43 + src/ts/dist/remoteGeometry.js | 87 + src/ts/dist/remoteValue.d.ts | 17 + src/ts/dist/remoteValue.js | 36 + src/ts/dist/remoteVimx.d.ts | 43 + src/ts/dist/remoteVimx.js | 87 + src/ts/dist/requestTracker.d.ts | 61 + src/ts/dist/requestTracker.js | 107 + src/ts/dist/requester.d.ts | 19 + src/ts/dist/requester.js | 73 + src/ts/dist/structures.d.ts | 48 + src/ts/dist/structures.js | 5 + src/ts/dist/types/abstractG3d.d.ts | 17 + src/ts/dist/types/bfast.d.ts | 141 + src/ts/dist/types/converters.d.ts | 46 + src/ts/dist/types/entityTable.d.ts | 22 + src/ts/dist/types/g3d.d.ts | 178 + src/ts/dist/types/g3dAttributes.d.ts | 20 + src/ts/dist/types/g3dMaterials.d.ts | 38 + src/ts/dist/types/g3dMesh.d.ts | 79 + src/ts/dist/types/g3dMeshIndex.d.ts | 61 + src/ts/dist/types/g3dMeshOffsets.d.ts | 41 + src/ts/dist/types/g3dScene.d.ts | 63 + src/ts/dist/types/g3dSubset.d.ts | 108 + src/ts/dist/types/index.d.ts | 15 + src/ts/dist/types/logging.d.ts | 18 + src/ts/dist/types/objectModel.d.ts | 3356 +++++++++ src/ts/dist/types/remoteBuffer.d.ts | 40 + src/ts/dist/types/remoteG3d.d.ts | 67 + src/ts/dist/types/remoteGeometry.d.ts | 43 + src/ts/dist/types/remoteValue.d.ts | 17 + src/ts/dist/types/remoteVimx.d.ts | 43 + src/ts/dist/types/requestTracker.d.ts | 61 + src/ts/dist/types/requester.d.ts | 19 + src/ts/dist/types/structures.d.ts | 48 + src/ts/dist/types/vimHeader.d.ts | 14 + src/ts/dist/types/vimHelpers.d.ts | 19 + src/ts/dist/types/vimLoader.d.ts | 9 + src/ts/dist/vimHeader.d.ts | 14 + src/ts/dist/vimHeader.js | 17 + src/ts/dist/vimHelpers.d.ts | 19 + src/ts/dist/vimHelpers.js | 78 + src/ts/dist/vimLoader.d.ts | 9 + src/ts/dist/vimLoader.js | 32 + src/ts/package-lock.json | 30 +- src/ts/package.json | 2 +- src/ts/src/bfast.ts | 9 + src/ts/src/g3d.ts | 54 +- src/ts/src/g3dMesh.ts | 114 +- src/ts/src/g3dMeshIndex.ts | 201 - src/ts/src/g3dMeshOffsets.ts | 88 - src/ts/src/g3dScene.ts | 230 + src/ts/src/g3dSubset.ts | 133 - src/ts/src/index.ts | 6 +- src/ts/src/remoteGeometry.ts | 61 - src/ts/src/remoteVimx.ts | 102 + 158 files changed, 29389 insertions(+), 629 deletions(-) create mode 100644 src/cs/Vim.BFast.Next/BFastNext.cs create mode 100644 src/cs/Vim.BFast.Next/BFastNextExtensions.cs create mode 100644 src/cs/Vim.BFast.Next/BFastNextNode.cs create mode 100644 src/cs/Vim.BFast.Next/IBFastNextNode.cs create mode 100644 src/cs/Vim.BFast.Next/Vim.BFastNext.csproj create mode 100644 src/cs/Vim.BFastNext.Tests/BFastNextTests.cs create mode 100644 src/cs/Vim.BFastNext.Tests/Vim.BFastNext.Tests.csproj create mode 100644 src/cs/g3d/Vim.G3d/Vim.G3dNext.csproj create mode 100644 src/cs/g3d/Vim.G3dNext.Attributes/Attributes.g.cs create mode 100644 src/cs/g3d/Vim.G3dNext.Attributes/MaterialAttributes.cs create mode 100644 src/cs/g3d/Vim.G3dNext.Attributes/MeshAttributes.cs create mode 100644 src/cs/g3d/Vim.G3dNext.Attributes/SceneAttributes.cs create mode 100644 src/cs/g3d/Vim.G3dNext.Attributes/Vim.G3dNext.Attributes.csproj create mode 100644 src/cs/g3d/Vim.G3dNext.Attributes/VimAttributes.cs create mode 100644 src/cs/g3d/Vim.G3dNext.CodeGen/CodeBuilder.cs create mode 100644 src/cs/g3d/Vim.G3dNext.CodeGen/G3dAttributeCollectionGenerator.cs create mode 100644 src/cs/g3d/Vim.G3dNext.CodeGen/Program.cs create mode 100644 src/cs/g3d/Vim.G3dNext.CodeGen/Vim.G3dNext.CodeGen.csproj create mode 100644 src/cs/g3d/Vim.G3dNext.Tests/Vim.G3dNext.Tests.csproj create mode 100644 src/cs/g3d/Vim.G3dNext/AttributeDescriptor.cs create mode 100644 src/cs/g3d/Vim.G3dNext/AttributeDescriptorErrors.cs create mode 100644 src/cs/g3d/Vim.G3dNext/AttributeType.cs create mode 100644 src/cs/g3d/Vim.G3dNext/CodeGenAttributes.cs create mode 100644 src/cs/g3d/Vim.G3dNext/Constants.cs create mode 100644 src/cs/g3d/Vim.G3dNext/DataType.cs create mode 100644 src/cs/g3d/Vim.G3dNext/G3DNext.cs create mode 100644 src/cs/g3d/Vim.G3dNext/IAttribute.cs create mode 100644 src/cs/g3d/Vim.G3dNext/IAttributeCollection.cs create mode 100644 src/cs/g3d/Vim.G3dNext/IAttributeDescriptor.cs create mode 100644 src/cs/g3d/Vim.G3dNext/MetaHeader.cs create mode 100644 src/cs/g3d/Vim.G3dNext/Vim.G3dNext.csproj create mode 100644 src/cs/g3d/temp/Vim.G3dNext.Attributes/Attributes.cs create mode 100644 src/cs/g3d/temp/Vim.G3dNext.Attributes/Attributes.g.cs create mode 100644 src/cs/g3d/temp/Vim.G3dNext.Attributes/Vim.G3dNext.Attributes.csproj create mode 100644 src/cs/g3d/temp/Vim.G3dNext.Attributes/VimAttributeCollectionExtensions.cs create mode 100644 src/cs/g3d/temp/Vim.G3dNext.Tests/AssimpTests.cs create mode 100644 src/cs/g3d/temp/Vim.G3dNext.Tests/FileUtils.cs create mode 100644 src/cs/g3d/temp/Vim.G3dNext.Tests/TestUtils.cs create mode 100644 src/cs/g3d/temp/Vim.G3dNext.Tests/Vim.G3dNext.Tests.csproj create mode 100644 src/cs/g3d/temp/Vim.G3dNext.Tests/VimG3dTests.cs create mode 100644 src/cs/vim/Vim.Format.Vimx/FileUtils.cs create mode 100644 src/cs/vim/Vim.Format.Vimx/G3dMaterials.cs create mode 100644 src/cs/vim/Vim.Format.Vimx/G3dMesh.cs create mode 100644 src/cs/vim/Vim.Format.Vimx/G3dMeshExtensions.cs create mode 100644 src/cs/vim/Vim.Format.Vimx/G3dScene.cs create mode 100644 src/cs/vim/Vim.Format.Vimx/G3dVim.cs create mode 100644 src/cs/vim/Vim.Format.Vimx/G3dVimFilter.cs create mode 100644 src/cs/vim/Vim.Format.Vimx/G3dVimMeshes.cs create mode 100644 src/cs/vim/Vim.Format.Vimx/G3dVimScene.cs create mode 100644 src/cs/vim/Vim.Format.Vimx/Vim.Format.Vimx.csproj create mode 100644 src/cs/vim/Vim.Format.Vimx/Vimx.cs create mode 100644 src/cs/vim/Vim.Format.Vimx/VimxHeader.cs create mode 100644 src/cs/vim/Vim.Vimx.Test/TestUtils.cs create mode 100644 src/cs/vim/Vim.Vimx.Test/Vim.Format.Vimx.Test.csproj create mode 100644 src/cs/vim/Vim.Vimx.Test/VimG3dTests.cs create mode 100644 src/cs/vim/Vim.Vimx.Test/VimxActions.cs create mode 100644 src/cs/vim/Vim.Vimx.Test/VimxTests.cs create mode 100644 src/ts/dist/abstractG3d.d.ts create mode 100644 src/ts/dist/abstractG3d.js create mode 100644 src/ts/dist/bfast.d.ts create mode 100644 src/ts/dist/bfast.js create mode 100644 src/ts/dist/converters.d.ts create mode 100644 src/ts/dist/converters.js create mode 100644 src/ts/dist/entityTable.d.ts create mode 100644 src/ts/dist/entityTable.js create mode 100644 src/ts/dist/g3d.d.ts create mode 100644 src/ts/dist/g3d.js create mode 100644 src/ts/dist/g3dAttributes.d.ts create mode 100644 src/ts/dist/g3dAttributes.js create mode 100644 src/ts/dist/g3dMaterials.d.ts create mode 100644 src/ts/dist/g3dMaterials.js create mode 100644 src/ts/dist/g3dMesh.d.ts create mode 100644 src/ts/dist/g3dMesh.js create mode 100644 src/ts/dist/g3dMeshIndex.d.ts create mode 100644 src/ts/dist/g3dMeshIndex.js create mode 100644 src/ts/dist/g3dMeshOffsets.d.ts create mode 100644 src/ts/dist/g3dMeshOffsets.js create mode 100644 src/ts/dist/g3dScene.d.ts create mode 100644 src/ts/dist/g3dScene.js create mode 100644 src/ts/dist/g3dSubset.d.ts create mode 100644 src/ts/dist/g3dSubset.js create mode 100644 src/ts/dist/index.d.ts create mode 100644 src/ts/dist/index.js create mode 100644 src/ts/dist/logging.d.ts create mode 100644 src/ts/dist/logging.js create mode 100644 src/ts/dist/objectModel.d.ts create mode 100644 src/ts/dist/objectModel.js create mode 100644 src/ts/dist/remoteBuffer.d.ts create mode 100644 src/ts/dist/remoteBuffer.js create mode 100644 src/ts/dist/remoteG3d.d.ts create mode 100644 src/ts/dist/remoteG3d.js create mode 100644 src/ts/dist/remoteGeometry.d.ts create mode 100644 src/ts/dist/remoteGeometry.js create mode 100644 src/ts/dist/remoteValue.d.ts create mode 100644 src/ts/dist/remoteValue.js create mode 100644 src/ts/dist/remoteVimx.d.ts create mode 100644 src/ts/dist/remoteVimx.js create mode 100644 src/ts/dist/requestTracker.d.ts create mode 100644 src/ts/dist/requestTracker.js create mode 100644 src/ts/dist/requester.d.ts create mode 100644 src/ts/dist/requester.js create mode 100644 src/ts/dist/structures.d.ts create mode 100644 src/ts/dist/structures.js create mode 100644 src/ts/dist/types/abstractG3d.d.ts create mode 100644 src/ts/dist/types/bfast.d.ts create mode 100644 src/ts/dist/types/converters.d.ts create mode 100644 src/ts/dist/types/entityTable.d.ts create mode 100644 src/ts/dist/types/g3d.d.ts create mode 100644 src/ts/dist/types/g3dAttributes.d.ts create mode 100644 src/ts/dist/types/g3dMaterials.d.ts create mode 100644 src/ts/dist/types/g3dMesh.d.ts create mode 100644 src/ts/dist/types/g3dMeshIndex.d.ts create mode 100644 src/ts/dist/types/g3dMeshOffsets.d.ts create mode 100644 src/ts/dist/types/g3dScene.d.ts create mode 100644 src/ts/dist/types/g3dSubset.d.ts create mode 100644 src/ts/dist/types/index.d.ts create mode 100644 src/ts/dist/types/logging.d.ts create mode 100644 src/ts/dist/types/objectModel.d.ts create mode 100644 src/ts/dist/types/remoteBuffer.d.ts create mode 100644 src/ts/dist/types/remoteG3d.d.ts create mode 100644 src/ts/dist/types/remoteGeometry.d.ts create mode 100644 src/ts/dist/types/remoteValue.d.ts create mode 100644 src/ts/dist/types/remoteVimx.d.ts create mode 100644 src/ts/dist/types/requestTracker.d.ts create mode 100644 src/ts/dist/types/requester.d.ts create mode 100644 src/ts/dist/types/structures.d.ts create mode 100644 src/ts/dist/types/vimHeader.d.ts create mode 100644 src/ts/dist/types/vimHelpers.d.ts create mode 100644 src/ts/dist/types/vimLoader.d.ts create mode 100644 src/ts/dist/vimHeader.d.ts create mode 100644 src/ts/dist/vimHeader.js create mode 100644 src/ts/dist/vimHelpers.d.ts create mode 100644 src/ts/dist/vimHelpers.js create mode 100644 src/ts/dist/vimLoader.d.ts create mode 100644 src/ts/dist/vimLoader.js delete mode 100644 src/ts/src/g3dMeshIndex.ts delete mode 100644 src/ts/src/g3dMeshOffsets.ts create mode 100644 src/ts/src/g3dScene.ts delete mode 100644 src/ts/src/g3dSubset.ts delete mode 100644 src/ts/src/remoteGeometry.ts create mode 100644 src/ts/src/remoteVimx.ts diff --git a/src/cs/Vim.BFast.Next/BFastNext.cs b/src/cs/Vim.BFast.Next/BFastNext.cs new file mode 100644 index 00000000..566d0669 --- /dev/null +++ b/src/cs/Vim.BFast.Next/BFastNext.cs @@ -0,0 +1,129 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using Vim.BFast; + +namespace Vim.BFastNext +{ + public class BFastNext : IBFastNextNode + { + private Dictionary _children = new Dictionary(); + public IEnumerable Entries => _children.Keys; + private IEnumerable<(string, IWritable)> Writables => _children.Select(kvp => (kvp.Key, kvp.Value as IWritable)); + + public BFastNext() { } + public BFastNext(Stream stream) + { + var node = GetBFastNodes(stream); + _children = node.ToDictionary(c => c.name, c => c.value as IBFastNextNode); + } + + public void AddBFast(string name, BFastNext bfast) + => _children[name] = bfast; + + public void AddArray(string name, T[] array) where T : unmanaged + => _children[name] = BFastNextNode.FromArray(array); + + public void AddArray(Func getName, IEnumerable arrays) where T : unmanaged + { + var index = 0; + foreach (var array in arrays) + { + AddArray(getName(index++), array); + } + } + + public BFastNext GetBFast(string name) + { + if (!_children.ContainsKey(name)) return null; + var bfast = _children[name].AsBFast(); + _children[name] = bfast; + return bfast; + } + + public T[] GetArray(string name) where T : unmanaged + { + if (!_children.ContainsKey(name)) return null; + return _children[name].AsArray(); + } + + public IBFastNextNode GetNode(string name) + => _children.TryGetValue(name, out var value) ? value : null; + + public void Remove(string name) + => _children.Remove(name); + + public long GetSize() => GetBFastSize(Writables); + + public void Write(Stream stream) + { + WriteBFast(stream, Writables); + } + + public void Write(string path) + { + using (var file = new FileStream(path, FileMode.Create)) + { + Write(file); + } + } + + BFastNext IBFastNextNode.AsBFast() + { + return this; + } + + T[] IBFastNextNode.AsArray() + { + using (var stream = new MemoryStream()) + { + Write(stream); + var end = stream.Position; + stream.Seek(0, SeekOrigin.Begin); + return stream.ReadArrayBytes((int)end); + } + } + + private static IEnumerable<(string name, BFastNextNode value)> GetBFastNodes(Stream stream) + { + var offset = stream.Position; + var header = stream.ReadBFastHeader(); + for (var i = 1; i < header.Preamble.NumArrays; i++) + { + var node = new BFastNextNode( + stream, + header.Ranges[i].OffsetBy(offset) + ); + + yield return (header.Names[i - 1], node); + } + } + + private static void WriteBFast(Stream stream, IEnumerable<(string name, IWritable value)> writables) + { + var values = writables.Select(w => w.value).ToArray(); + var sizes = values.Select(v => v.GetSize()).ToArray(); + var names = writables.Select(w => w.name).ToArray(); + + long onBuffer(Stream writingStream, int bufferIdx, string bufferName, long bytesToWrite) + { + values[bufferIdx].Write(writingStream); + return bytesToWrite; + } + + stream.WriteBFast(names, sizes, onBuffer); + } + + private static long GetBFastSize(IEnumerable<(string name, IWritable value)> writables) + { + var values = writables.Select(w => w.value).ToArray(); + var sizes = values.Select(v => v.GetSize()).ToArray(); + var names = writables.Select(w => w.name).ToArray(); + + var header = BFast.BFast.CreateBFastHeader(sizes, names); + return header.Preamble.DataEnd; + } + } +} diff --git a/src/cs/Vim.BFast.Next/BFastNextExtensions.cs b/src/cs/Vim.BFast.Next/BFastNextExtensions.cs new file mode 100644 index 00000000..0b75b91a --- /dev/null +++ b/src/cs/Vim.BFast.Next/BFastNextExtensions.cs @@ -0,0 +1,64 @@ +using System; +using System.IO.Compression; +using System.IO; +using System.Collections.Generic; + +namespace Vim.BFastNext +{ + public static class BFastNextExtensions + { + public static BFastNext GetBFast(this BFastNext bfast, string name, bool inflate) + { + if (inflate == false) return bfast.GetBFast(name); + var output = new MemoryStream(); + using (var input = new MemoryStream()) + { + bfast.GetNode(name).Write(input); + input.Seek(0, SeekOrigin.Begin); + using (var compress = new DeflateStream(input, CompressionMode.Decompress, true)) + { + compress.CopyTo(output); + output.Seek(0, SeekOrigin.Begin); + return new BFastNext(output); + } + } + } + + public static void SetBFast(this BFastNext bfast, string name, BFastNext other, bool deflate) + { + if (deflate == false) bfast.AddBFast(name, other); + + using (var output = new MemoryStream()) + { + using (var decompress = new DeflateStream(output, CompressionMode.Compress, true)) + { + other.Write(decompress); + } + + var a = output.ToArray(); + bfast.AddArray(name, a); + } + } + + public static void SetBFast(this BFastNext bfast, Func getName, IEnumerable others, bool deflate) + { + var i = 0; + foreach(var b in others) + { + Console.WriteLine(i); + bfast.SetBFast(getName(i++), b, deflate); + } + } + + public static T ReadBFast(this string path, Func process) + { + using (var file = new FileStream(path, FileMode.Open)) + { + var bfast = new BFastNext(file); + return process(bfast); + } + } + + + } +} diff --git a/src/cs/Vim.BFast.Next/BFastNextNode.cs b/src/cs/Vim.BFast.Next/BFastNextNode.cs new file mode 100644 index 00000000..3120e93e --- /dev/null +++ b/src/cs/Vim.BFast.Next/BFastNextNode.cs @@ -0,0 +1,77 @@ +using System; +using System.IO; +using Vim.BFast; + +namespace Vim.BFastNext +{ + public class BFastNextNode : IBFastNextNode + { + private readonly Stream _stream; + private readonly BFastRange _range; + + public static BFastNextNode FromArray(T[] array) where T: unmanaged + { + /* + Is a memory leak created if a MemoryStream in .NET is not closed? + ------------------------------------------------------------------ + You won't leak anything - at least in the current implementation. + Calling Dispose won't clean up the memory used by MemoryStream any faster. It will stop your stream from being viable for Read/Write calls after the call, which may or may not be useful to you. + If you're absolutely sure that you never want to move from a MemoryStream to another kind of stream, it's not going to do you any harm to not call Dispose. However, it's generally good practice partly because if you ever do change to use a different Stream, you don't want to get bitten by a hard-to-find bug because you chose the easy way out early on. (On the other hand, there's the YAGNI argument...) + The other reason to do it anyway is that a new implementation may introduce resources which would be freed on Dispose. + https://stackoverflow.com/questions/234059/is-a-memory-leak-created-if-a-memorystream-in-net-is-not-closed + */ + var stream = new MemoryStream(); + stream.Write(array); + return new BFastNextNode(stream, stream.FullRange()); + } + + public BFastNextNode(Stream stream, BFastRange range) + { + this._stream = stream; + this._range = range; + } + + public BFastNext AsBFast() + { + _stream.Seek(_range.Begin, SeekOrigin.Begin); + try + { + return new BFastNext(_stream); + } + catch (Exception ex) + { + // It is expected most buffers are not valid bfasts. + return null; + } + } + + public T[] AsArray() where T : unmanaged + { + _stream.Seek(_range.Begin, SeekOrigin.Begin); + return _stream.ReadArrayBytes((int)_range.Count); + } + + public long GetSize() + { + return _range.Count; + } + + public void Write(Stream stream) + { + _stream.Seek(_range.Begin, SeekOrigin.Begin); + CopyStream(_stream, stream, (int)_range.Count); + } + + private static void CopyStream(Stream input, Stream output, int bytes) + { + byte[] buffer = new byte[32768]; + int read; + while (bytes > 0 && + (read = input.Read(buffer, 0, Math.Min(buffer.Length, bytes))) > 0) + { + output.Write(buffer, 0, read); + bytes -= read; + } + } + } +} diff --git a/src/cs/Vim.BFast.Next/IBFastNextNode.cs b/src/cs/Vim.BFast.Next/IBFastNextNode.cs new file mode 100644 index 00000000..e4cb8ab0 --- /dev/null +++ b/src/cs/Vim.BFast.Next/IBFastNextNode.cs @@ -0,0 +1,19 @@ +using System.IO; + +namespace Vim.BFastNext +{ + /// + /// Anything that can be added to a BFAST must have a size and write to a stream. + /// + public interface IWritable + { + long GetSize(); + void Write(Stream stream); + } + + public interface IBFastNextNode : IWritable + { + T[] AsArray() where T : unmanaged; + BFastNext AsBFast(); + } +} diff --git a/src/cs/Vim.BFast.Next/Vim.BFastNext.csproj b/src/cs/Vim.BFast.Next/Vim.BFastNext.csproj new file mode 100644 index 00000000..9c678ee3 --- /dev/null +++ b/src/cs/Vim.BFast.Next/Vim.BFastNext.csproj @@ -0,0 +1,12 @@ + + + + netstandard2.0 + true + + + + + + + diff --git a/src/cs/Vim.BFastNext.Tests/BFastNextTests.cs b/src/cs/Vim.BFastNext.Tests/BFastNextTests.cs new file mode 100644 index 00000000..5ef14ced --- /dev/null +++ b/src/cs/Vim.BFastNext.Tests/BFastNextTests.cs @@ -0,0 +1,390 @@ +using NUnit.Framework; +using Vim.Util.Tests; + +namespace Vim.BFastNext.Tests +{ + public class BFastNextTests + { + public static string RootFolder = System.IO.Path.Combine(VimFormatRepoPaths.ProjDir, "..", ".."); + public static string Path = System.IO.Path.Combine(RootFolder, "out/input.bfast"); + public static string OutputPath = System.IO.Path.Combine(RootFolder, "out/output.bfast"); + public static string ResidencePath = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); + + [SetUp] + public void Setup() + { + File.Delete(Path); + File.Delete(OutputPath); + } + + [Test] + public void EmptyBFast_Has_No_Entries() + { + var bfast = new BFastNext(); + Assert.That(bfast.Entries.Count(), Is.EqualTo(0)); + } + + [Test] + public void EmptyBFast_GetArray_Returns_Null() + { + var bfast = new BFastNext(); + Assert.IsNull(bfast.GetArray("missing")); + } + + [Test] + public void EmptyBFast_GetBfast_Returns_Null() + { + var bfast = new BFastNext(); + Assert.IsNull(bfast.GetBFast("missing")); + } + + [Test] + public void EmptyBFast_Remove_Does_Nothing() + { + var bfast = new BFastNext(); + bfast.Remove("missing"); + } + + [Test] + public void EmptyBFast_GetSize_Return_64() + { + var bfast = new BFastNext(); + Assert.That(bfast.GetSize(), Is.EqualTo(64)); + } + + [Test] + public void EmptyBFast_Writes_Header() + { + var bfast = new BFastNext(); + bfast.Write(Path); + using (var stream = File.OpenRead(Path)) + { + var bfast2 = new BFastNext(stream); + Assert.That(bfast2.GetSize(), Is.EqualTo(64)); + } + } + + [Test] + public void SetArray_Adds_Entry() + { + var bfast = new BFastNext(); + bfast.AddArray("A", new int[3] { 0, 1, 2 }); + + Assert.That(bfast.Entries.Count(), Is.EqualTo(1)); + } + + [Test] + public void SetArray_Then_GetArray() + { + var bfast = new BFastNext(); + bfast.AddArray("A", new int[3] { 0, 1, 2 }); + var result = bfast.GetArray("A"); + + Assert.That(result, Is.EqualTo(new int[3] { 0, 1, 2 })); + } + + [Test] + public void SetArray_Then_GetArray_Bytes() + { + var bfast = new BFastNext(); + bfast.AddArray("A", new int[3] { 0, 1, 2 }); + var result = bfast.GetArray("A"); + + var bytes = (new int[3] { 0, 1, 2 }).SelectMany(i => BitConverter.GetBytes(i)); + Assert.That(result, Is.EqualTo(bytes)); + } + + [Test] + public void SetArray_Then_GetArray_Float() + { + var bfast = new BFastNext(); + bfast.AddArray("A", new int[3] { 0, 1, 2 }); + var result = bfast.GetArray("A"); + + var floats = (new int[3] { 0, 1, 2 }).Select(i => BitConverter.Int32BitsToSingle(i)); + Assert.That(result, Is.EqualTo(floats)); + } + + [Test] + public void SetArray_Then_GetBFast_Returns_Null() + { + var bfast = new BFastNext(); + bfast.AddArray("A", new int[3] { 0, 1, 2 }); + var result = bfast.GetBFast("A"); + + Assert.IsNull(result); + } + + [Test] + public void SetArray_Then_SetArray_Replaces() + { + var bfast = new BFastNext(); + bfast.AddArray("A", new int[3] { 0, 1, 2 }); + bfast.AddArray("A", new float[3] { 0.1f, 0.2f, 0.3f }); + var result = bfast.GetArray("A"); + + Assert.That(result, Is.EqualTo(new float[3] { 0.1f, 0.2f, 0.3f })); + } + + [Test] + public void SetArray_Then_SetBFast_Replaces() + { + var bfast = new BFastNext(); + + bfast.AddArray("A", new int[3] { 0, 1, 2 }); + bfast.AddBFast("A", new BFastNext()); + var result = bfast.GetArray("A"); + Assert.That(result.Length > 3); + } + + [Test] + public void SetBFast_Adds_Entry() + { + var bfast = new BFastNext(); + bfast.AddBFast("A", new BFastNext()); + + Assert.That(bfast.Entries.Count(), Is.EqualTo(1)); + } + + [Test] + public void SetBFast_Then_GetBFast_Returns_Same() + { + var bfast = new BFastNext(); + var b = new BFastNext(); + bfast.AddBFast("A", b); + var result = bfast.GetBFast("A"); + + Assert.That(result, Is.EqualTo(b)); + } + + [Test] + public void SetBFast_Then_SetBFast_Replaces() + { + var bfast = new BFastNext(); + var a = new BFastNext(); + var b = new BFastNext(); + bfast.AddBFast("A", a); + bfast.AddBFast("A", b); + var result = bfast.GetBFast("A"); + Assert.That(a != b); + Assert.That(result == b); + } + + [Test] + public void SetBFast_Then_SetArray_Replaces() + { + var bfast = new BFastNext(); + bfast.AddBFast("A", new BFastNext()); + bfast.AddArray("A", new int[3] { 0, 1, 2 }); + var result = bfast.GetBFast("A"); + Assert.IsNull(result); + } + + [Test] + public void Remove_Missing_DoesNothing() + { + var bfast = new BFastNext(); + bfast.Remove("A"); + Assert.That(bfast.Entries.Count() == 0); + } + + [Test] + public void Remove_Array() + { + var bfast = new BFastNext(); + bfast.AddArray("A", new int[3] { 0, 1, 2 }); + bfast.Remove("A"); + Assert.IsNull(bfast.GetArray("A")); + Assert.That(bfast.Entries.Count() == 0); + } + + [Test] + public void Remove_BFast() + { + var bfast = new BFastNext(); + bfast.AddBFast("A", new BFastNext()); + bfast.Remove("A"); + Assert.IsNull(bfast.GetBFast("A")); + Assert.That(bfast.Entries.Count() == 0); + } + + [Test] + public void Removed_BFast_Not_Written() + { + var bfast = new BFastNext(); + bfast.AddBFast("A", new BFastNext()); + bfast.Remove("A"); + + bfast.Write(Path); + + using (var stream = File.OpenRead(Path)) + { + var other = new BFastNext(stream); + Assert.IsNull(other.GetBFast("A")); + Assert.That(other.Entries.Count() == 0); + } + } + + [Test] + public void Removed_Array_Not_Written() + { + var bfast = new BFastNext(); + bfast.AddArray("A", new int[3] { 0, 1, 2 }); + bfast.Remove("A"); + bfast.Write(Path); + + using (var stream = File.OpenRead(Path)) + { + var other = new BFastNext(stream); + Assert.IsNull(other.GetArray("A")); + Assert.That(other.Entries.Count() == 0); + } + } + + [Test] + public void Removed_InChild_Not_Written() + { + using (var residence = File.OpenRead(ResidencePath)) + { + var input = new BFastNext(residence); + var geometry = input.GetBFast("geometry"); + geometry.Remove("g3d:vertex:position:0:float32:3"); + input.AddBFast("geometry", geometry); + input.Write(Path); + } + + using (var stream = File.OpenRead(Path)) + { + var bfast = new BFastNext(stream); + var geometry = bfast.GetBFast("geometry"); + Assert.That(bfast.Entries.Count() == 5); + Assert.That(geometry.Entries.Count() == 16); + Assert.IsNull(geometry.GetArray("g3d:vertex:position:0:float32:3")); + } + } + + [Test] + public void Write_Then_Read_Array() + { + var bfast = new BFastNext(); + + bfast.AddArray("A", new int[3] { 0, 1, 2 }); + bfast.Write(Path); + + using (var stream = File.OpenRead(Path)) + { + var other = new BFastNext(stream); + var result = other.GetArray("A"); + Assert.That(result, Is.EqualTo(new int[3] { 0, 1, 2 })); + } + } + + [Test] + public void Write_Then_Read_SimpleBFast() + { + var bfast = new BFastNext(); + var child = new BFastNext(); + + bfast.AddBFast("child", child); + child.AddArray("A", new int[3] { 0, 1, 2 }); + bfast.Write(Path); + + using (var stream = File.OpenRead(Path)) + { + var other = new BFastNext(stream); + var child2 = other.GetBFast("child"); + var result = child2.GetArray("A"); + + Assert.That(other.Entries.Count() == 1); + Assert.That(child2.Entries.Count() == 1); + Assert.That(result, Is.EqualTo(new int[3] { 0, 1, 2 })); + } + } + + [Test] + public void Write_Then_Read_NestedBFast() + { + var bfast = new BFastNext(); + var child = new BFastNext(); + var grandChild = new BFastNext(); + + bfast.AddBFast("child", child); + child.AddBFast("grandChild", grandChild); + bfast.Write(Path); + + using (var stream = File.OpenRead(Path)) + { + var other = new BFastNext(stream); + var child2 = other.GetBFast("child"); + var grandChild2 = child2.GetBFast("grandChild"); + + Assert.That(other.Entries.Count() == 1); + Assert.That(child2.Entries.Count() == 1); + Assert.That(grandChild2.Entries.Count() == 0); + } + } + + [Test] + public void Write_Then_Read_NestedBFast_WithArray() + { + var bfast = new BFastNext(); + var child = new BFastNext(); + var grandChild = new BFastNext(); + + bfast.AddBFast("child", child); + child.AddBFast("grandChild", grandChild); + grandChild.AddArray("A", new int[3] { 0, 1, 2 }); + + + bfast.Write(Path); + using (var stream = File.OpenRead(Path)) + { + var other = new BFastNext(stream); + var child2 = other.GetBFast("child"); + var grandChild2 = child2.GetBFast("grandChild"); + var result = grandChild2.GetArray("A"); + + Assert.That(other.Entries.Count() == 1); + Assert.That(child2.Entries.Count() == 1); + Assert.That(grandChild2.Entries.Count() == 1); + Assert.That(result, Is.EqualTo(new int[3] { 0, 1, 2 })); + } + } + + [Test] + public void Write_Then_Read_Mixed_Sources() + { + var basic = new BFastNext(); + basic.AddArray("ints", new int[1] { 1 }); + basic.AddArray("floats", new float[1] { 2.0f }); + basic.Write(Path); + + using (var stream = File.OpenRead(Path)) + { + using (var residence = File.OpenRead(ResidencePath)) + { + var input = new BFastNext(stream); + var inputResidence = new BFastNext(residence); + var output = new BFastNext(); + + output.AddBFast("input", input); + output.AddBFast("residence", inputResidence); + output.Write(OutputPath); + } + } + + using (var stream = File.OpenRead(OutputPath)) + { + var bfast = new BFastNext(stream); + var input = bfast.GetBFast("input"); + var residence = bfast.GetBFast("residence"); + var geometry = residence.GetBFast("geometry"); + + Assert.That(bfast.Entries.Count() == 2); + Assert.That(input.Entries.Count() == 2); + Assert.That(residence.Entries.Count() == 5); + Assert.That(geometry.Entries.Count() == 17); + } + } + } +} \ No newline at end of file diff --git a/src/cs/Vim.BFastNext.Tests/Vim.BFastNext.Tests.csproj b/src/cs/Vim.BFastNext.Tests/Vim.BFastNext.Tests.csproj new file mode 100644 index 00000000..fc43f265 --- /dev/null +++ b/src/cs/Vim.BFastNext.Tests/Vim.BFastNext.Tests.csproj @@ -0,0 +1,25 @@ + + + + net6.0 + enable + enable + + false + true + + + + + + + + + + + + + + + + diff --git a/src/cs/bfast/Vim.BFast/BFast.cs b/src/cs/bfast/Vim.BFast/BFast.cs index 885fe582..e3a26b91 100644 --- a/src/cs/bfast/Vim.BFast/BFast.cs +++ b/src/cs/bfast/Vim.BFast/BFast.cs @@ -261,10 +261,13 @@ public static INamedBuffer[] Read(Stream stream) /// public static IEnumerable ReadBFast(this Stream stream) { + if (!stream.CanSeek) + { + throw new InvalidOperationException("Cannot read read non seekable stream. Consider using ReadBFastNoSeek."); + } foreach (var br in stream.GetBFastBufferReaders()) { - var s = br.Seek(); - yield return s.ReadArray((int)br.Size).ToNamedBuffer(br.Name); + yield return br.GetBuffer(); } } @@ -288,10 +291,32 @@ public static INamedBuffer[] ReadBFast(this byte[] bytes) } /// - /// The total size required to put a BFAST in the header. + /// Reads a BFAST buffer from a stream as a collection of named buffers. + /// This implementation does seek into the stream. + /// Supports non-seekable stream such as web stream. /// - public static long ComputeSize(long[] bufferSizes, string[] bufferNames) - => CreateBFastHeader(bufferSizes, bufferNames).Preamble.DataEnd; + public static void ReadBFastNoSeek(this Stream stream, Func onBuffer) + { + var header = stream.ReadBFastHeader(); + BFast.CheckAlignment(stream); + + // position after ReadBFastHeader + var position = header.Ranges[1].Begin; + + // Range 0 is Buffer Names is already read so skip to i=1. + for (var i = 1; i < header.Ranges.Length; i++) + { + // Skip padding. + var skip = header.Ranges[i].Begin - position; + stream.SkipBytes(skip); + + if (!onBuffer(stream, header.Names[i - 1], header.Ranges[i].Count)) + { + break; + } + position = header.Ranges[i].End; + } + } /// /// Writes the BFAST header and name buffer to stream using the provided BinaryWriter. The BinaryWriter will be properly aligned by padding zeros @@ -435,5 +460,18 @@ public static unsafe byte[] WriteBFastToBytes(this (string Name, T[] Data)[] public static BFastBuilder ToBFastBuilder(this IEnumerable buffers) => new BFastBuilder().Add(buffers); + + public static BFastRange OffsetBy(this BFastRange range, long offset) + => new BFastRange() { + Begin = range.Begin + offset, + End = range.End + offset + }; + + public static BFastRange FullRange(this Stream stream) + => new BFastRange() + { + Begin = 0, + End = stream.Length + }; } } diff --git a/src/cs/bfast/Vim.BFast/BFastBufferReader.cs b/src/cs/bfast/Vim.BFast/BFastBufferReader.cs index 31a07e85..ccdcaa7f 100644 --- a/src/cs/bfast/Vim.BFast/BFastBufferReader.cs +++ b/src/cs/bfast/Vim.BFast/BFastBufferReader.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.IO.Compression; using System.Linq; namespace Vim.BFast @@ -56,10 +57,29 @@ public Stream Seek() BFast.CheckAlignment(_stream); return _stream; } + + public NamedBuffer GetBuffer(bool inflate = false) where T : unmanaged + { + this.Seek(); + if (!inflate) + { + return _stream.ReadArray((int)Size).ToNamedBuffer(Name); + } + using(var deflated = new DeflateStream(_stream, CompressionMode.Decompress)){ + return _stream.ReadArray((int)Size).ToNamedBuffer(Name); + } + } + + public NamedBuffer GetBuffer(bool inflate = false) + { + return GetBuffer(inflate); + } + } public static class BFastBufferReaderExtensions { + /// /// Reads the preamble, the ranges, and the names of the rest of the buffers. /// @@ -84,7 +104,7 @@ public static BFastHeader ReadBFastHeader(this Stream stream) var padding = BFast.ComputePadding(r.Ranges); br.ReadBytes((int)padding); BFast.CheckAlignment(br.BaseStream); - + var nameBytes = br.ReadBytes((int)r.Ranges[0].Count); r.Names = nameBytes.UnpackStrings(); @@ -141,6 +161,22 @@ public static BFastBufferReader GetBFastBufferReader(this Stream stream, string ? null : stream.GetBFastBufferReaders(br => br.Name == bufferName).FirstOrDefault(); + + public static NamedBuffer GetBFastBuffer(this Stream stream, string bufferName, bool inflate = false) + { + + var buffer = stream.GetBFastBufferReader(bufferName).GetBuffer(); + return buffer; + + // if (!inflate) return buffer; + // var bytes = buffer.GetTypedData(); + // using(var inflate = new DeflateStream(stream, CompressionMode.Decompress)); + } + + public static void SeekToBFastBuffer(this Stream stream, string bufferName) + => stream.GetBFastBufferReader(bufferName).Seek(); + + /// /// Reads a BFAST stream and returns a list of labeled results. /// @@ -167,11 +203,7 @@ public static BFastBufferReader GetBFastBufferReader(this Stream stream, string public static NamedBuffer ReadBFastBuffer(this Stream stream, string bufferName) where T : unmanaged { var br = stream.GetBFastBufferReader(bufferName); - if (br == null) - return null; - - var s = br.Seek(); - return s.ReadArray((int)br.Size).ToNamedBuffer(br.Name); + return br?.GetBuffer(); } } } diff --git a/src/cs/bfast/Vim.BFast/BFastBuilder.cs b/src/cs/bfast/Vim.BFast/BFastBuilder.cs index 7c39221b..0cac6a5c 100644 --- a/src/cs/bfast/Vim.BFast/BFastBuilder.cs +++ b/src/cs/bfast/Vim.BFast/BFastBuilder.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; @@ -75,6 +76,9 @@ public BFastBuilder Add(string name, IBFastComponent component) public BFastBuilder Add(string name, IBuffer buffer) => _add(name, new BufferAsBFastComponent(buffer)); + public BFastBuilder Add(Func getName, IEnumerable buffers) + => Add(buffers.Select((b, i) => b.ToNamedBuffer(getName(i)))); + public BFastBuilder Add(INamedBuffer buffer) => Add(buffer.Name, buffer); diff --git a/src/cs/bfast/Vim.BFast/UnsafeHelpers.cs b/src/cs/bfast/Vim.BFast/UnsafeHelpers.cs index 7d01a1de..b5435fa1 100644 --- a/src/cs/bfast/Vim.BFast/UnsafeHelpers.cs +++ b/src/cs/bfast/Vim.BFast/UnsafeHelpers.cs @@ -1,4 +1,5 @@ using System; +using System.Drawing; using System.IO; namespace Vim.BFast @@ -72,6 +73,43 @@ public static unsafe T[] ReadArray(this Stream stream, int count) where T : u return r; } + + /// + /// Equivalent to ReadArray to use when you know the byte count instead of element count. + /// + public static unsafe T[] ReadArrayBytes(this Stream stream, int byteLength) where T : unmanaged + { + return ReadArray(stream, byteLength / sizeof(T)); + } + + public static unsafe T[] ConvertByteArrayToTypeArray(byte[] byteArray) where T : unmanaged + { + if (byteArray.Length % sizeof(T) != 0) + { + throw new ArgumentException("Byte array length is not a multiple of the size of the target type."); + } + + int elementCount = byteArray.Length / sizeof(T); + T[] resultArray = new T[elementCount]; + + fixed (byte* bytePtr = byteArray) + { + byte* currentBytePtr = bytePtr; + fixed (T* resultPtr = resultArray) + { + T* currentResultPtr = resultPtr; + for (int i = 0; i < elementCount; i++) + { + *currentResultPtr = *((T*)currentBytePtr); + currentBytePtr += sizeof(T); + currentResultPtr++; + } + } + } + + return resultArray; + } + /// /// A wrapper for stream.Seek(numBytes, SeekOrigin.Current) to avoid allocating memory for unrecognized buffers. /// diff --git a/src/cs/bfast/Vim.BFast/Vim.BFast.csproj b/src/cs/bfast/Vim.BFast/Vim.BFast.csproj index 3c6ef62c..1e855d5b 100644 --- a/src/cs/bfast/Vim.BFast/Vim.BFast.csproj +++ b/src/cs/bfast/Vim.BFast/Vim.BFast.csproj @@ -20,7 +20,7 @@ - + diff --git a/src/cs/g3d/Vim.G3d/G3D.cs b/src/cs/g3d/Vim.G3d/G3D.cs index 98aed23b..4017134e 100644 --- a/src/cs/g3d/Vim.G3d/G3D.cs +++ b/src/cs/g3d/Vim.G3d/G3D.cs @@ -7,7 +7,6 @@ Usage licensed under terms of MIT License using System; using System.Collections.Generic; -using System.Diagnostics; using System.IO; using System.Linq; using Vim.LinqArray; diff --git a/src/cs/g3d/Vim.G3d/Vim.G3dNext.csproj b/src/cs/g3d/Vim.G3d/Vim.G3dNext.csproj new file mode 100644 index 00000000..379ef62d --- /dev/null +++ b/src/cs/g3d/Vim.G3d/Vim.G3dNext.csproj @@ -0,0 +1,14 @@ + + + + + + netstandard2.0 + + + + + + + + diff --git a/src/cs/g3d/Vim.G3dNext.Attributes/Attributes.g.cs b/src/cs/g3d/Vim.G3dNext.Attributes/Attributes.g.cs new file mode 100644 index 00000000..4630ef5f --- /dev/null +++ b/src/cs/g3d/Vim.G3dNext.Attributes/Attributes.g.cs @@ -0,0 +1,2911 @@ +// AUTO-GENERATED FILE, DO NOT MODIFY. +// ReSharper disable All +using System; +using System.IO; +using System.Collections.Generic; +using System.Linq; +using Vim.BFast; + +namespace Vim.G3dNext.Attributes +{ + + public partial class CornersPerFaceAttribute : IAttribute + { + public const string AttributeName = "g3d:all:facesize:0:int32:1"; + + public string Name + => AttributeName; + + public int Count => TypedData?.Length ?? 0; + + public void AddTo(BFastNext.BFastNext bfast) + { + if(TypedData != null) + { + bfast.AddArray(Name, TypedData); + } + } + + public void ReadBFast(BFastNext.BFastNext bfast) + { + TypedData = bfast.GetArray("g3d:all:facesize:0:int32:1"); + } + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Singleton; + + public Type IndexInto { get; } + = null; + + public System.Int32[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + + public partial class VertexAttribute : IAttribute + { + public const string AttributeName = "g3d:vertex:position:0:float32:3"; + + public string Name + => AttributeName; + + public int Count => TypedData?.Length ?? 0; + + public void AddTo(BFastNext.BFastNext bfast) + { + if(TypedData != null) + { + bfast.AddArray(Name, TypedData); + } + } + + public void ReadBFast(BFastNext.BFastNext bfast) + { + TypedData = bfast.GetArray("g3d:vertex:position:0:float32:3"); + } + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Data; + + public Type IndexInto { get; } + = null; + + public Vim.Math3d.Vector3[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + + public partial class IndexAttribute : IAttribute + { + public const string AttributeName = "g3d:corner:index:0:int32:1"; + + public string Name + => AttributeName; + + public int Count => TypedData?.Length ?? 0; + + public void AddTo(BFastNext.BFastNext bfast) + { + if(TypedData != null) + { + bfast.AddArray(Name, TypedData); + } + } + + public void ReadBFast(BFastNext.BFastNext bfast) + { + TypedData = bfast.GetArray("g3d:corner:index:0:int32:1"); + } + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Index; + + public Type IndexInto { get; } + = typeof(Vim.G3dNext.Attributes.VertexAttribute); + + public System.Int32[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + + public partial class InstanceTransformAttribute : IAttribute + { + public const string AttributeName = "g3d:instance:transform:0:float32:16"; + + public string Name + => AttributeName; + + public int Count => TypedData?.Length ?? 0; + + public void AddTo(BFastNext.BFastNext bfast) + { + if(TypedData != null) + { + bfast.AddArray(Name, TypedData); + } + } + + public void ReadBFast(BFastNext.BFastNext bfast) + { + TypedData = bfast.GetArray("g3d:instance:transform:0:float32:16"); + } + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Data; + + public Type IndexInto { get; } + = null; + + public Vim.Math3d.Matrix4x4[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + + public partial class InstanceParentAttribute : IAttribute + { + public const string AttributeName = "g3d:instance:parent:0:int32:1"; + + public string Name + => AttributeName; + + public int Count => TypedData?.Length ?? 0; + + public void AddTo(BFastNext.BFastNext bfast) + { + if(TypedData != null) + { + bfast.AddArray(Name, TypedData); + } + } + + public void ReadBFast(BFastNext.BFastNext bfast) + { + TypedData = bfast.GetArray("g3d:instance:parent:0:int32:1"); + } + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Index; + + public Type IndexInto { get; } + = typeof(Vim.G3dNext.Attributes.InstanceTransformAttribute); + + public System.Int32[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + + public partial class InstanceFlagsAttribute : IAttribute + { + public const string AttributeName = "g3d:instance:flags:0:uint16:1"; + + public string Name + => AttributeName; + + public int Count => TypedData?.Length ?? 0; + + public void AddTo(BFastNext.BFastNext bfast) + { + if(TypedData != null) + { + bfast.AddArray(Name, TypedData); + } + } + + public void ReadBFast(BFastNext.BFastNext bfast) + { + TypedData = bfast.GetArray("g3d:instance:flags:0:uint16:1"); + } + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Data; + + public Type IndexInto { get; } + = null; + + public System.UInt16[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + + public partial class InstanceMeshAttribute : IAttribute + { + public const string AttributeName = "g3d:instance:mesh:0:int32:1"; + + public string Name + => AttributeName; + + public int Count => TypedData?.Length ?? 0; + + public void AddTo(BFastNext.BFastNext bfast) + { + if(TypedData != null) + { + bfast.AddArray(Name, TypedData); + } + } + + public void ReadBFast(BFastNext.BFastNext bfast) + { + TypedData = bfast.GetArray("g3d:instance:mesh:0:int32:1"); + } + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Index; + + public Type IndexInto { get; } + = typeof(Vim.G3dNext.Attributes.MeshSubmeshOffsetAttribute); + + public System.Int32[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + + public partial class MeshSubmeshOffsetAttribute : IAttribute + { + public const string AttributeName = "g3d:mesh:submeshoffset:0:int32:1"; + + public string Name + => AttributeName; + + public int Count => TypedData?.Length ?? 0; + + public void AddTo(BFastNext.BFastNext bfast) + { + if(TypedData != null) + { + bfast.AddArray(Name, TypedData); + } + } + + public void ReadBFast(BFastNext.BFastNext bfast) + { + TypedData = bfast.GetArray("g3d:mesh:submeshoffset:0:int32:1"); + } + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Index; + + public Type IndexInto { get; } + = typeof(Vim.G3dNext.Attributes.SubmeshIndexOffsetAttribute); + + public System.Int32[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + + public partial class SubmeshIndexOffsetAttribute : IAttribute + { + public const string AttributeName = "g3d:submesh:indexoffset:0:int32:1"; + + public string Name + => AttributeName; + + public int Count => TypedData?.Length ?? 0; + + public void AddTo(BFastNext.BFastNext bfast) + { + if(TypedData != null) + { + bfast.AddArray(Name, TypedData); + } + } + + public void ReadBFast(BFastNext.BFastNext bfast) + { + TypedData = bfast.GetArray("g3d:submesh:indexoffset:0:int32:1"); + } + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Index; + + public Type IndexInto { get; } + = typeof(Vim.G3dNext.Attributes.IndexAttribute); + + public System.Int32[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + + public partial class SubmeshMaterialAttribute : IAttribute + { + public const string AttributeName = "g3d:submesh:material:0:int32:1"; + + public string Name + => AttributeName; + + public int Count => TypedData?.Length ?? 0; + + public void AddTo(BFastNext.BFastNext bfast) + { + if(TypedData != null) + { + bfast.AddArray(Name, TypedData); + } + } + + public void ReadBFast(BFastNext.BFastNext bfast) + { + TypedData = bfast.GetArray("g3d:submesh:material:0:int32:1"); + } + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Index; + + public Type IndexInto { get; } + = typeof(Vim.G3dNext.Attributes.MaterialColorAttribute); + + public System.Int32[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + + public partial class ShapeVertexAttribute : IAttribute + { + public const string AttributeName = "g3d:shapevertex:position:0:float32:3"; + + public string Name + => AttributeName; + + public int Count => TypedData?.Length ?? 0; + + public void AddTo(BFastNext.BFastNext bfast) + { + if(TypedData != null) + { + bfast.AddArray(Name, TypedData); + } + } + + public void ReadBFast(BFastNext.BFastNext bfast) + { + TypedData = bfast.GetArray("g3d:shapevertex:position:0:float32:3"); + } + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Data; + + public Type IndexInto { get; } + = null; + + public Vim.Math3d.Vector3[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + + public partial class ShapeVertexOffsetAttribute : IAttribute + { + public const string AttributeName = "g3d:shape:vertexoffset:0:int32:1"; + + public string Name + => AttributeName; + + public int Count => TypedData?.Length ?? 0; + + public void AddTo(BFastNext.BFastNext bfast) + { + if(TypedData != null) + { + bfast.AddArray(Name, TypedData); + } + } + + public void ReadBFast(BFastNext.BFastNext bfast) + { + TypedData = bfast.GetArray("g3d:shape:vertexoffset:0:int32:1"); + } + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Index; + + public Type IndexInto { get; } + = typeof(Vim.G3dNext.Attributes.ShapeVertexAttribute); + + public System.Int32[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + + public partial class ShapeColorAttribute : IAttribute + { + public const string AttributeName = "g3d:shape:color:0:float32:4"; + + public string Name + => AttributeName; + + public int Count => TypedData?.Length ?? 0; + + public void AddTo(BFastNext.BFastNext bfast) + { + if(TypedData != null) + { + bfast.AddArray(Name, TypedData); + } + } + + public void ReadBFast(BFastNext.BFastNext bfast) + { + TypedData = bfast.GetArray("g3d:shape:color:0:float32:4"); + } + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Data; + + public Type IndexInto { get; } + = null; + + public Vim.Math3d.Vector4[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + + public partial class ShapeWidthAttribute : IAttribute + { + public const string AttributeName = "g3d:shape:width:0:float32:1"; + + public string Name + => AttributeName; + + public int Count => TypedData?.Length ?? 0; + + public void AddTo(BFastNext.BFastNext bfast) + { + if(TypedData != null) + { + bfast.AddArray(Name, TypedData); + } + } + + public void ReadBFast(BFastNext.BFastNext bfast) + { + TypedData = bfast.GetArray("g3d:shape:width:0:float32:1"); + } + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Data; + + public Type IndexInto { get; } + = null; + + public System.Single[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + + public partial class MaterialColorAttribute : IAttribute + { + public const string AttributeName = "g3d:material:color:0:float32:4"; + + public string Name + => AttributeName; + + public int Count => TypedData?.Length ?? 0; + + public void AddTo(BFastNext.BFastNext bfast) + { + if(TypedData != null) + { + bfast.AddArray(Name, TypedData); + } + } + + public void ReadBFast(BFastNext.BFastNext bfast) + { + TypedData = bfast.GetArray("g3d:material:color:0:float32:4"); + } + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Data; + + public Type IndexInto { get; } + = null; + + public Vim.Math3d.Vector4[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + + public partial class MaterialGlossinessAttribute : IAttribute + { + public const string AttributeName = "g3d:material:glossiness:0:float32:1"; + + public string Name + => AttributeName; + + public int Count => TypedData?.Length ?? 0; + + public void AddTo(BFastNext.BFastNext bfast) + { + if(TypedData != null) + { + bfast.AddArray(Name, TypedData); + } + } + + public void ReadBFast(BFastNext.BFastNext bfast) + { + TypedData = bfast.GetArray("g3d:material:glossiness:0:float32:1"); + } + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Data; + + public Type IndexInto { get; } + = null; + + public System.Single[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + + public partial class MaterialSmoothnessAttribute : IAttribute + { + public const string AttributeName = "g3d:material:smoothness:0:float32:1"; + + public string Name + => AttributeName; + + public int Count => TypedData?.Length ?? 0; + + public void AddTo(BFastNext.BFastNext bfast) + { + if(TypedData != null) + { + bfast.AddArray(Name, TypedData); + } + } + + public void ReadBFast(BFastNext.BFastNext bfast) + { + TypedData = bfast.GetArray("g3d:material:smoothness:0:float32:1"); + } + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Data; + + public Type IndexInto { get; } + = null; + + public System.Single[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + + public partial class InstanceFilesAttribute : IAttribute + { + public const string AttributeName = "g3d:instance:file:0:int32:1"; + + public string Name + => AttributeName; + + public int Count => TypedData?.Length ?? 0; + + public void AddTo(BFastNext.BFastNext bfast) + { + if(TypedData != null) + { + bfast.AddArray(Name, TypedData); + } + } + + public void ReadBFast(BFastNext.BFastNext bfast) + { + TypedData = bfast.GetArray("g3d:instance:file:0:int32:1"); + } + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Data; + + public Type IndexInto { get; } + = null; + + public System.Int32[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + + public partial class InstanceNodesAttribute : IAttribute + { + public const string AttributeName = "g3d:instance:node:0:int32:1"; + + public string Name + => AttributeName; + + public int Count => TypedData?.Length ?? 0; + + public void AddTo(BFastNext.BFastNext bfast) + { + if(TypedData != null) + { + bfast.AddArray(Name, TypedData); + } + } + + public void ReadBFast(BFastNext.BFastNext bfast) + { + TypedData = bfast.GetArray("g3d:instance:node:0:int32:1"); + } + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Data; + + public Type IndexInto { get; } + = null; + + public System.Int32[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + + public partial class InstanceIndicesAttribute : IAttribute + { + public const string AttributeName = "g3d:instance:index:0:int32:1"; + + public string Name + => AttributeName; + + public int Count => TypedData?.Length ?? 0; + + public void AddTo(BFastNext.BFastNext bfast) + { + if(TypedData != null) + { + bfast.AddArray(Name, TypedData); + } + } + + public void ReadBFast(BFastNext.BFastNext bfast) + { + TypedData = bfast.GetArray("g3d:instance:index:0:int32:1"); + } + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Data; + + public Type IndexInto { get; } + = null; + + public System.Int32[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + + public partial class InstanceGroupsAttribute : IAttribute + { + public const string AttributeName = "g3d:instance:group:0:int32:1"; + + public string Name + => AttributeName; + + public int Count => TypedData?.Length ?? 0; + + public void AddTo(BFastNext.BFastNext bfast) + { + if(TypedData != null) + { + bfast.AddArray(Name, TypedData); + } + } + + public void ReadBFast(BFastNext.BFastNext bfast) + { + TypedData = bfast.GetArray("g3d:instance:group:0:int32:1"); + } + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Data; + + public Type IndexInto { get; } + = null; + + public System.Int32[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + + public partial class InstanceTagsAttribute : IAttribute + { + public const string AttributeName = "g3d:instance:tag:0:int64:1"; + + public string Name + => AttributeName; + + public int Count => TypedData?.Length ?? 0; + + public void AddTo(BFastNext.BFastNext bfast) + { + if(TypedData != null) + { + bfast.AddArray(Name, TypedData); + } + } + + public void ReadBFast(BFastNext.BFastNext bfast) + { + TypedData = bfast.GetArray("g3d:instance:tag:0:int64:1"); + } + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Data; + + public Type IndexInto { get; } + = null; + + public System.Int64[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + + public partial class InstanceMinsAttribute : IAttribute + { + public const string AttributeName = "g3d:instance:min:0:float32:3"; + + public string Name + => AttributeName; + + public int Count => TypedData?.Length ?? 0; + + public void AddTo(BFastNext.BFastNext bfast) + { + if(TypedData != null) + { + bfast.AddArray(Name, TypedData); + } + } + + public void ReadBFast(BFastNext.BFastNext bfast) + { + TypedData = bfast.GetArray("g3d:instance:min:0:float32:3"); + } + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Data; + + public Type IndexInto { get; } + = null; + + public Vim.Math3d.Vector3[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + + public partial class InstanceMaxsAttribute : IAttribute + { + public const string AttributeName = "g3d:instance:max:0:float32:3"; + + public string Name + => AttributeName; + + public int Count => TypedData?.Length ?? 0; + + public void AddTo(BFastNext.BFastNext bfast) + { + if(TypedData != null) + { + bfast.AddArray(Name, TypedData); + } + } + + public void ReadBFast(BFastNext.BFastNext bfast) + { + TypedData = bfast.GetArray("g3d:instance:max:0:float32:3"); + } + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Data; + + public Type IndexInto { get; } + = null; + + public Vim.Math3d.Vector3[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + + public partial class MeshInstanceCountsAttribute : IAttribute + { + public const string AttributeName = "g3d:mesh:instancecount:0:int32:1"; + + public string Name + => AttributeName; + + public int Count => TypedData?.Length ?? 0; + + public void AddTo(BFastNext.BFastNext bfast) + { + if(TypedData != null) + { + bfast.AddArray(Name, TypedData); + } + } + + public void ReadBFast(BFastNext.BFastNext bfast) + { + TypedData = bfast.GetArray("g3d:mesh:instancecount:0:int32:1"); + } + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Data; + + public Type IndexInto { get; } + = null; + + public System.Int32[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + + public partial class MeshVertexCountsAttribute : IAttribute + { + public const string AttributeName = "g3d:mesh:vertexcount:0:int32:1"; + + public string Name + => AttributeName; + + public int Count => TypedData?.Length ?? 0; + + public void AddTo(BFastNext.BFastNext bfast) + { + if(TypedData != null) + { + bfast.AddArray(Name, TypedData); + } + } + + public void ReadBFast(BFastNext.BFastNext bfast) + { + TypedData = bfast.GetArray("g3d:mesh:vertexcount:0:int32:1"); + } + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Data; + + public Type IndexInto { get; } + = null; + + public System.Int32[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + + public partial class MeshIndexCountsAttribute : IAttribute + { + public const string AttributeName = "g3d:mesh:indexcount:0:int32:1"; + + public string Name + => AttributeName; + + public int Count => TypedData?.Length ?? 0; + + public void AddTo(BFastNext.BFastNext bfast) + { + if(TypedData != null) + { + bfast.AddArray(Name, TypedData); + } + } + + public void ReadBFast(BFastNext.BFastNext bfast) + { + TypedData = bfast.GetArray("g3d:mesh:indexcount:0:int32:1"); + } + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Data; + + public Type IndexInto { get; } + = null; + + public System.Int32[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + + public partial class MeshOpaqueVertexCountsAttribute : IAttribute + { + public const string AttributeName = "g3d:mesh:opaquevertexcount:0:int32:1"; + + public string Name + => AttributeName; + + public int Count => TypedData?.Length ?? 0; + + public void AddTo(BFastNext.BFastNext bfast) + { + if(TypedData != null) + { + bfast.AddArray(Name, TypedData); + } + } + + public void ReadBFast(BFastNext.BFastNext bfast) + { + TypedData = bfast.GetArray("g3d:mesh:opaquevertexcount:0:int32:1"); + } + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Data; + + public Type IndexInto { get; } + = null; + + public System.Int32[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + + public partial class MeshOpaqueIndexCountsAttribute : IAttribute + { + public const string AttributeName = "g3d:mesh:opaqueindexcount:0:int32:1"; + + public string Name + => AttributeName; + + public int Count => TypedData?.Length ?? 0; + + public void AddTo(BFastNext.BFastNext bfast) + { + if(TypedData != null) + { + bfast.AddArray(Name, TypedData); + } + } + + public void ReadBFast(BFastNext.BFastNext bfast) + { + TypedData = bfast.GetArray("g3d:mesh:opaqueindexcount:0:int32:1"); + } + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Data; + + public Type IndexInto { get; } + = null; + + public System.Int32[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + + public partial class MeshInstanceTransformAttribute : IAttribute + { + public const string AttributeName = "g3d:instance:transform:0:float32:16"; + + public string Name + => AttributeName; + + public int Count => TypedData?.Length ?? 0; + + public void AddTo(BFastNext.BFastNext bfast) + { + if(TypedData != null) + { + bfast.AddArray(Name, TypedData); + } + } + + public void ReadBFast(BFastNext.BFastNext bfast) + { + TypedData = bfast.GetArray("g3d:instance:transform:0:float32:16"); + } + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Data; + + public Type IndexInto { get; } + = null; + + public Vim.Math3d.Matrix4x4[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + + public partial class MeshOpaqueSubmeshCountAttribute : IAttribute + { + public const string AttributeName = "g3d:mesh:opaquesubmeshcount:0:int32:1"; + + public string Name + => AttributeName; + + public int Count => TypedData?.Length ?? 0; + + public void AddTo(BFastNext.BFastNext bfast) + { + if(TypedData != null) + { + bfast.AddArray(Name, TypedData); + } + } + + public void ReadBFast(BFastNext.BFastNext bfast) + { + TypedData = bfast.GetArray("g3d:mesh:opaquesubmeshcount:0:int32:1"); + } + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Data; + + public Type IndexInto { get; } + = null; + + public System.Int32[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + + public partial class MeshSubmeshIndexOffsetAttribute : IAttribute + { + public const string AttributeName = "g3d:submesh:indexoffset:0:int32:1"; + + public string Name + => AttributeName; + + public int Count => TypedData?.Length ?? 0; + + public void AddTo(BFastNext.BFastNext bfast) + { + if(TypedData != null) + { + bfast.AddArray(Name, TypedData); + } + } + + public void ReadBFast(BFastNext.BFastNext bfast) + { + TypedData = bfast.GetArray("g3d:submesh:indexoffset:0:int32:1"); + } + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Index; + + public Type IndexInto { get; } + = typeof(Vim.G3dNext.Attributes.IndexAttribute); + + public System.Int32[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + + public partial class MeshSubmeshVertexOffsetAttribute : IAttribute + { + public const string AttributeName = "g3d:submesh:vertexoffset:0:int32:1"; + + public string Name + => AttributeName; + + public int Count => TypedData?.Length ?? 0; + + public void AddTo(BFastNext.BFastNext bfast) + { + if(TypedData != null) + { + bfast.AddArray(Name, TypedData); + } + } + + public void ReadBFast(BFastNext.BFastNext bfast) + { + TypedData = bfast.GetArray("g3d:submesh:vertexoffset:0:int32:1"); + } + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Index; + + public Type IndexInto { get; } + = typeof(Vim.G3dNext.Attributes.IndexAttribute); + + public System.Int32[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + + public partial class MeshSubmeshMaterialAttribute : IAttribute + { + public const string AttributeName = "g3d:submesh:material:0:int32:1"; + + public string Name + => AttributeName; + + public int Count => TypedData?.Length ?? 0; + + public void AddTo(BFastNext.BFastNext bfast) + { + if(TypedData != null) + { + bfast.AddArray(Name, TypedData); + } + } + + public void ReadBFast(BFastNext.BFastNext bfast) + { + TypedData = bfast.GetArray("g3d:submesh:material:0:int32:1"); + } + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Index; + + public Type IndexInto { get; } + = typeof(Vim.G3dNext.Attributes.MaterialColorAttribute); + + public System.Int32[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + + public partial class MeshVertexAttribute : IAttribute + { + public const string AttributeName = "g3d:vertex:position:0:float32:3"; + + public string Name + => AttributeName; + + public int Count => TypedData?.Length ?? 0; + + public void AddTo(BFastNext.BFastNext bfast) + { + if(TypedData != null) + { + bfast.AddArray(Name, TypedData); + } + } + + public void ReadBFast(BFastNext.BFastNext bfast) + { + TypedData = bfast.GetArray("g3d:vertex:position:0:float32:3"); + } + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Data; + + public Type IndexInto { get; } + = null; + + public Vim.Math3d.Vector3[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + + public partial class MeshIndexAttribute : IAttribute + { + public const string AttributeName = "g3d:corner:index:0:int32:1"; + + public string Name + => AttributeName; + + public int Count => TypedData?.Length ?? 0; + + public void AddTo(BFastNext.BFastNext bfast) + { + if(TypedData != null) + { + bfast.AddArray(Name, TypedData); + } + } + + public void ReadBFast(BFastNext.BFastNext bfast) + { + TypedData = bfast.GetArray("g3d:corner:index:0:int32:1"); + } + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Index; + + public Type IndexInto { get; } + = typeof(Vim.G3dNext.Attributes.VertexAttribute); + + public System.Int32[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + + public class G3dVim2 + { + public G3DNext source; + + public G3dVim2() + { + this.source = new G3DNext (); + } + + public G3dVim2(G3DNext source) + { + this.source = source; + } + + public G3dVim2(BFastNext.BFastNext bfast) + { + this.source = new G3DNext(bfast); + } + + + public System.Int32[] CornersPerFace + { + get => source.AttributeCollection.CornersPerFaceAttribute.TypedData; + set => source.AttributeCollection.CornersPerFaceAttribute.TypedData = value; + } + + public Vim.Math3d.Vector3[] Vertex + { + get => source.AttributeCollection.VertexAttribute.TypedData; + set => source.AttributeCollection.VertexAttribute.TypedData = value; + } + + public System.Int32[] Index + { + get => source.AttributeCollection.IndexAttribute.TypedData; + set => source.AttributeCollection.IndexAttribute.TypedData = value; + } + + public Vim.Math3d.Matrix4x4[] InstanceTransform + { + get => source.AttributeCollection.InstanceTransformAttribute.TypedData; + set => source.AttributeCollection.InstanceTransformAttribute.TypedData = value; + } + + public System.Int32[] InstanceParent + { + get => source.AttributeCollection.InstanceParentAttribute.TypedData; + set => source.AttributeCollection.InstanceParentAttribute.TypedData = value; + } + + public System.UInt16[] InstanceFlags + { + get => source.AttributeCollection.InstanceFlagsAttribute.TypedData; + set => source.AttributeCollection.InstanceFlagsAttribute.TypedData = value; + } + + public System.Int32[] InstanceMesh + { + get => source.AttributeCollection.InstanceMeshAttribute.TypedData; + set => source.AttributeCollection.InstanceMeshAttribute.TypedData = value; + } + + public System.Int32[] MeshSubmeshOffset + { + get => source.AttributeCollection.MeshSubmeshOffsetAttribute.TypedData; + set => source.AttributeCollection.MeshSubmeshOffsetAttribute.TypedData = value; + } + + public System.Int32[] SubmeshIndexOffset + { + get => source.AttributeCollection.SubmeshIndexOffsetAttribute.TypedData; + set => source.AttributeCollection.SubmeshIndexOffsetAttribute.TypedData = value; + } + + public System.Int32[] SubmeshMaterial + { + get => source.AttributeCollection.SubmeshMaterialAttribute.TypedData; + set => source.AttributeCollection.SubmeshMaterialAttribute.TypedData = value; + } + + public Vim.Math3d.Vector4[] MaterialColor + { + get => source.AttributeCollection.MaterialColorAttribute.TypedData; + set => source.AttributeCollection.MaterialColorAttribute.TypedData = value; + } + + public System.Single[] MaterialGlossiness + { + get => source.AttributeCollection.MaterialGlossinessAttribute.TypedData; + set => source.AttributeCollection.MaterialGlossinessAttribute.TypedData = value; + } + + public System.Single[] MaterialSmoothness + { + get => source.AttributeCollection.MaterialSmoothnessAttribute.TypedData; + set => source.AttributeCollection.MaterialSmoothnessAttribute.TypedData = value; + } + + public Vim.Math3d.Vector3[] ShapeVertex + { + get => source.AttributeCollection.ShapeVertexAttribute.TypedData; + set => source.AttributeCollection.ShapeVertexAttribute.TypedData = value; + } + + public System.Int32[] ShapeVertexOffset + { + get => source.AttributeCollection.ShapeVertexOffsetAttribute.TypedData; + set => source.AttributeCollection.ShapeVertexOffsetAttribute.TypedData = value; + } + + public Vim.Math3d.Vector4[] ShapeColor + { + get => source.AttributeCollection.ShapeColorAttribute.TypedData; + set => source.AttributeCollection.ShapeColorAttribute.TypedData = value; + } + + public System.Single[] ShapeWidth + { + get => source.AttributeCollection.ShapeWidthAttribute.TypedData; + set => source.AttributeCollection.ShapeWidthAttribute.TypedData = value; + } + } + + + public partial class VimAttributeCollection : IAttributeCollection + { + public IEnumerable AttributeNames + => Attributes.Keys; + + public long GetSize() + => Attributes.Values.Sum(a => a.Data.LongLength * a.AttributeDescriptor.DataElementSize); + + public IDictionary Attributes { get; } + = new Dictionary + { + [Vim.G3dNext.Attributes.CornersPerFaceAttribute.AttributeName] = new Vim.G3dNext.Attributes.CornersPerFaceAttribute(), + [Vim.G3dNext.Attributes.VertexAttribute.AttributeName] = new Vim.G3dNext.Attributes.VertexAttribute(), + [Vim.G3dNext.Attributes.IndexAttribute.AttributeName] = new Vim.G3dNext.Attributes.IndexAttribute(), + [Vim.G3dNext.Attributes.InstanceTransformAttribute.AttributeName] = new Vim.G3dNext.Attributes.InstanceTransformAttribute(), + [Vim.G3dNext.Attributes.InstanceParentAttribute.AttributeName] = new Vim.G3dNext.Attributes.InstanceParentAttribute(), + [Vim.G3dNext.Attributes.InstanceFlagsAttribute.AttributeName] = new Vim.G3dNext.Attributes.InstanceFlagsAttribute(), + [Vim.G3dNext.Attributes.InstanceMeshAttribute.AttributeName] = new Vim.G3dNext.Attributes.InstanceMeshAttribute(), + [Vim.G3dNext.Attributes.MeshSubmeshOffsetAttribute.AttributeName] = new Vim.G3dNext.Attributes.MeshSubmeshOffsetAttribute(), + [Vim.G3dNext.Attributes.SubmeshIndexOffsetAttribute.AttributeName] = new Vim.G3dNext.Attributes.SubmeshIndexOffsetAttribute(), + [Vim.G3dNext.Attributes.SubmeshMaterialAttribute.AttributeName] = new Vim.G3dNext.Attributes.SubmeshMaterialAttribute(), + [Vim.G3dNext.Attributes.MaterialColorAttribute.AttributeName] = new Vim.G3dNext.Attributes.MaterialColorAttribute(), + [Vim.G3dNext.Attributes.MaterialGlossinessAttribute.AttributeName] = new Vim.G3dNext.Attributes.MaterialGlossinessAttribute(), + [Vim.G3dNext.Attributes.MaterialSmoothnessAttribute.AttributeName] = new Vim.G3dNext.Attributes.MaterialSmoothnessAttribute(), + [Vim.G3dNext.Attributes.ShapeVertexAttribute.AttributeName] = new Vim.G3dNext.Attributes.ShapeVertexAttribute(), + [Vim.G3dNext.Attributes.ShapeVertexOffsetAttribute.AttributeName] = new Vim.G3dNext.Attributes.ShapeVertexOffsetAttribute(), + [Vim.G3dNext.Attributes.ShapeColorAttribute.AttributeName] = new Vim.G3dNext.Attributes.ShapeColorAttribute(), + [Vim.G3dNext.Attributes.ShapeWidthAttribute.AttributeName] = new Vim.G3dNext.Attributes.ShapeWidthAttribute(), + }; + + // Named Attributes. + + public Vim.G3dNext.Attributes.CornersPerFaceAttribute CornersPerFaceAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.CornersPerFaceAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.CornersPerFaceAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.CornersPerFaceAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.VertexAttribute VertexAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.VertexAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.VertexAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.VertexAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.IndexAttribute IndexAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.IndexAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.IndexAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.IndexAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.InstanceTransformAttribute InstanceTransformAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.InstanceTransformAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceTransformAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.InstanceTransformAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.InstanceParentAttribute InstanceParentAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.InstanceParentAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceParentAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.InstanceParentAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.InstanceFlagsAttribute InstanceFlagsAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.InstanceFlagsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceFlagsAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.InstanceFlagsAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.InstanceMeshAttribute InstanceMeshAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.InstanceMeshAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceMeshAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.InstanceMeshAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.MeshSubmeshOffsetAttribute MeshSubmeshOffsetAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.MeshSubmeshOffsetAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshSubmeshOffsetAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.MeshSubmeshOffsetAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.SubmeshIndexOffsetAttribute SubmeshIndexOffsetAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.SubmeshIndexOffsetAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.SubmeshIndexOffsetAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.SubmeshIndexOffsetAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.SubmeshMaterialAttribute SubmeshMaterialAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.SubmeshMaterialAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.SubmeshMaterialAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.SubmeshMaterialAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.MaterialColorAttribute MaterialColorAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.MaterialColorAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MaterialColorAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.MaterialColorAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.MaterialGlossinessAttribute MaterialGlossinessAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.MaterialGlossinessAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MaterialGlossinessAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.MaterialGlossinessAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.MaterialSmoothnessAttribute MaterialSmoothnessAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.MaterialSmoothnessAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MaterialSmoothnessAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.MaterialSmoothnessAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.ShapeVertexAttribute ShapeVertexAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.ShapeVertexAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.ShapeVertexAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.ShapeVertexAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.ShapeVertexOffsetAttribute ShapeVertexOffsetAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.ShapeVertexOffsetAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.ShapeVertexOffsetAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.ShapeVertexOffsetAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.ShapeColorAttribute ShapeColorAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.ShapeColorAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.ShapeColorAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.ShapeColorAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.ShapeWidthAttribute ShapeWidthAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.ShapeWidthAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.ShapeWidthAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.ShapeWidthAttribute.AttributeName] = value as IAttribute; + } + + /// + public IAttribute GetAttribute(Type attributeType) + { + + if (attributeType == typeof(Vim.G3dNext.Attributes.CornersPerFaceAttribute)) + return CornersPerFaceAttribute; + + if (attributeType == typeof(Vim.G3dNext.Attributes.VertexAttribute)) + return VertexAttribute; + + if (attributeType == typeof(Vim.G3dNext.Attributes.IndexAttribute)) + return IndexAttribute; + + if (attributeType == typeof(Vim.G3dNext.Attributes.InstanceTransformAttribute)) + return InstanceTransformAttribute; + + if (attributeType == typeof(Vim.G3dNext.Attributes.InstanceParentAttribute)) + return InstanceParentAttribute; + + if (attributeType == typeof(Vim.G3dNext.Attributes.InstanceFlagsAttribute)) + return InstanceFlagsAttribute; + + if (attributeType == typeof(Vim.G3dNext.Attributes.InstanceMeshAttribute)) + return InstanceMeshAttribute; + + if (attributeType == typeof(Vim.G3dNext.Attributes.MeshSubmeshOffsetAttribute)) + return MeshSubmeshOffsetAttribute; + + if (attributeType == typeof(Vim.G3dNext.Attributes.SubmeshIndexOffsetAttribute)) + return SubmeshIndexOffsetAttribute; + + if (attributeType == typeof(Vim.G3dNext.Attributes.SubmeshMaterialAttribute)) + return SubmeshMaterialAttribute; + + if (attributeType == typeof(Vim.G3dNext.Attributes.MaterialColorAttribute)) + return MaterialColorAttribute; + + if (attributeType == typeof(Vim.G3dNext.Attributes.MaterialGlossinessAttribute)) + return MaterialGlossinessAttribute; + + if (attributeType == typeof(Vim.G3dNext.Attributes.MaterialSmoothnessAttribute)) + return MaterialSmoothnessAttribute; + + if (attributeType == typeof(Vim.G3dNext.Attributes.ShapeVertexAttribute)) + return ShapeVertexAttribute; + + if (attributeType == typeof(Vim.G3dNext.Attributes.ShapeVertexOffsetAttribute)) + return ShapeVertexOffsetAttribute; + + if (attributeType == typeof(Vim.G3dNext.Attributes.ShapeColorAttribute)) + return ShapeColorAttribute; + + if (attributeType == typeof(Vim.G3dNext.Attributes.ShapeWidthAttribute)) + return ShapeWidthAttribute; + + throw new ArgumentException("Type {attributeType.ToString()} is not supported."); + } + + public IAttribute MergeAttribute(string attributeName, IReadOnlyList otherCollections) + { + var collections = otherCollections.Prepend(this).ToArray(); + switch (attributeName) + { + + case Vim.G3dNext.Attributes.CornersPerFaceAttribute.AttributeName: + { + // Singleton Attribute (no merging) + return CornersPerFaceAttribute; + } + + case Vim.G3dNext.Attributes.VertexAttribute.AttributeName: + { + // Data Attribute + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + } + + case Vim.G3dNext.Attributes.IndexAttribute.AttributeName: + { + // Index Attribute + return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); + } + + case Vim.G3dNext.Attributes.InstanceTransformAttribute.AttributeName: + { + // Data Attribute + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + } + + case Vim.G3dNext.Attributes.InstanceParentAttribute.AttributeName: + { + // Index Attribute + return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); + } + + case Vim.G3dNext.Attributes.InstanceFlagsAttribute.AttributeName: + { + // Data Attribute + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + } + + case Vim.G3dNext.Attributes.InstanceMeshAttribute.AttributeName: + { + // Index Attribute + return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); + } + + case Vim.G3dNext.Attributes.MeshSubmeshOffsetAttribute.AttributeName: + { + // Index Attribute + return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); + } + + case Vim.G3dNext.Attributes.SubmeshIndexOffsetAttribute.AttributeName: + { + // Index Attribute + return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); + } + + case Vim.G3dNext.Attributes.SubmeshMaterialAttribute.AttributeName: + { + // Index Attribute + return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); + } + + case Vim.G3dNext.Attributes.MaterialColorAttribute.AttributeName: + { + // Data Attribute + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + } + + case Vim.G3dNext.Attributes.MaterialGlossinessAttribute.AttributeName: + { + // Data Attribute + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + } + + case Vim.G3dNext.Attributes.MaterialSmoothnessAttribute.AttributeName: + { + // Data Attribute + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + } + + case Vim.G3dNext.Attributes.ShapeVertexAttribute.AttributeName: + { + // Data Attribute + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + } + + case Vim.G3dNext.Attributes.ShapeVertexOffsetAttribute.AttributeName: + { + // Index Attribute + return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); + } + + case Vim.G3dNext.Attributes.ShapeColorAttribute.AttributeName: + { + // Data Attribute + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + } + + case Vim.G3dNext.Attributes.ShapeWidthAttribute.AttributeName: + { + // Data Attribute + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + } + + default: + throw new ArgumentException(nameof(attributeName)); + } + } + + public void Validate() + { + // Ensure all the indices are either -1 or within the bounds of the attributes they are indexing into. + + { + var maxIndex = GetAttribute(IndexAttribute.IndexInto).Data.Length - 1; + for (var i = 0; i < IndexAttribute.TypedData.Length; ++i) + { + var index = IndexAttribute.TypedData[i]; + + if (index == -1) + continue; // no relation. + + if (index < -1 || index > maxIndex) + throw new Exception($"Index out of range in Vim.G3dNext.Attributes.IndexAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); + } + } + + { + var maxIndex = GetAttribute(InstanceParentAttribute.IndexInto).Data.Length - 1; + for (var i = 0; i < InstanceParentAttribute.TypedData.Length; ++i) + { + var index = InstanceParentAttribute.TypedData[i]; + + if (index == -1) + continue; // no relation. + + if (index < -1 || index > maxIndex) + throw new Exception($"Index out of range in Vim.G3dNext.Attributes.InstanceParentAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); + } + } + + { + var maxIndex = GetAttribute(InstanceMeshAttribute.IndexInto).Data.Length - 1; + for (var i = 0; i < InstanceMeshAttribute.TypedData.Length; ++i) + { + var index = InstanceMeshAttribute.TypedData[i]; + + if (index == -1) + continue; // no relation. + + if (index < -1 || index > maxIndex) + throw new Exception($"Index out of range in Vim.G3dNext.Attributes.InstanceMeshAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); + } + } + + { + var maxIndex = GetAttribute(MeshSubmeshOffsetAttribute.IndexInto).Data.Length - 1; + for (var i = 0; i < MeshSubmeshOffsetAttribute.TypedData.Length; ++i) + { + var index = MeshSubmeshOffsetAttribute.TypedData[i]; + + if (index == -1) + continue; // no relation. + + if (index < -1 || index > maxIndex) + throw new Exception($"Index out of range in Vim.G3dNext.Attributes.MeshSubmeshOffsetAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); + } + } + + { + var maxIndex = GetAttribute(SubmeshIndexOffsetAttribute.IndexInto).Data.Length - 1; + for (var i = 0; i < SubmeshIndexOffsetAttribute.TypedData.Length; ++i) + { + var index = SubmeshIndexOffsetAttribute.TypedData[i]; + + if (index == -1) + continue; // no relation. + + if (index < -1 || index > maxIndex) + throw new Exception($"Index out of range in Vim.G3dNext.Attributes.SubmeshIndexOffsetAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); + } + } + + { + var maxIndex = GetAttribute(SubmeshMaterialAttribute.IndexInto).Data.Length - 1; + for (var i = 0; i < SubmeshMaterialAttribute.TypedData.Length; ++i) + { + var index = SubmeshMaterialAttribute.TypedData[i]; + + if (index == -1) + continue; // no relation. + + if (index < -1 || index > maxIndex) + throw new Exception($"Index out of range in Vim.G3dNext.Attributes.SubmeshMaterialAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); + } + } + + { + var maxIndex = GetAttribute(ShapeVertexOffsetAttribute.IndexInto).Data.Length - 1; + for (var i = 0; i < ShapeVertexOffsetAttribute.TypedData.Length; ++i) + { + var index = ShapeVertexOffsetAttribute.TypedData[i]; + + if (index == -1) + continue; // no relation. + + if (index < -1 || index > maxIndex) + throw new Exception($"Index out of range in Vim.G3dNext.Attributes.ShapeVertexOffsetAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); + } + } + } + } + + public class G3dMaterial2 + { + public G3DNext source; + + public G3dMaterial2() + { + this.source = new G3DNext (); + } + + public G3dMaterial2(G3DNext source) + { + this.source = source; + } + + public G3dMaterial2(BFastNext.BFastNext bfast) + { + this.source = new G3DNext(bfast); + } + + + public Vim.Math3d.Vector4[] MaterialColor + { + get => source.AttributeCollection.MaterialColorAttribute.TypedData; + set => source.AttributeCollection.MaterialColorAttribute.TypedData = value; + } + + public System.Single[] MaterialGlossiness + { + get => source.AttributeCollection.MaterialGlossinessAttribute.TypedData; + set => source.AttributeCollection.MaterialGlossinessAttribute.TypedData = value; + } + + public System.Single[] MaterialSmoothness + { + get => source.AttributeCollection.MaterialSmoothnessAttribute.TypedData; + set => source.AttributeCollection.MaterialSmoothnessAttribute.TypedData = value; + } + } + + + public partial class MaterialAttributeCollection : IAttributeCollection + { + public IEnumerable AttributeNames + => Attributes.Keys; + + public long GetSize() + => Attributes.Values.Sum(a => a.Data.LongLength * a.AttributeDescriptor.DataElementSize); + + public IDictionary Attributes { get; } + = new Dictionary + { + [Vim.G3dNext.Attributes.MaterialColorAttribute.AttributeName] = new Vim.G3dNext.Attributes.MaterialColorAttribute(), + [Vim.G3dNext.Attributes.MaterialGlossinessAttribute.AttributeName] = new Vim.G3dNext.Attributes.MaterialGlossinessAttribute(), + [Vim.G3dNext.Attributes.MaterialSmoothnessAttribute.AttributeName] = new Vim.G3dNext.Attributes.MaterialSmoothnessAttribute(), + }; + + // Named Attributes. + + public Vim.G3dNext.Attributes.MaterialColorAttribute MaterialColorAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.MaterialColorAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MaterialColorAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.MaterialColorAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.MaterialGlossinessAttribute MaterialGlossinessAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.MaterialGlossinessAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MaterialGlossinessAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.MaterialGlossinessAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.MaterialSmoothnessAttribute MaterialSmoothnessAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.MaterialSmoothnessAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MaterialSmoothnessAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.MaterialSmoothnessAttribute.AttributeName] = value as IAttribute; + } + + /// + public IAttribute GetAttribute(Type attributeType) + { + + if (attributeType == typeof(Vim.G3dNext.Attributes.MaterialColorAttribute)) + return MaterialColorAttribute; + + if (attributeType == typeof(Vim.G3dNext.Attributes.MaterialGlossinessAttribute)) + return MaterialGlossinessAttribute; + + if (attributeType == typeof(Vim.G3dNext.Attributes.MaterialSmoothnessAttribute)) + return MaterialSmoothnessAttribute; + + throw new ArgumentException("Type {attributeType.ToString()} is not supported."); + } + + public IAttribute MergeAttribute(string attributeName, IReadOnlyList otherCollections) + { + var collections = otherCollections.Prepend(this).ToArray(); + switch (attributeName) + { + + case Vim.G3dNext.Attributes.MaterialColorAttribute.AttributeName: + { + // Data Attribute + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + } + + case Vim.G3dNext.Attributes.MaterialGlossinessAttribute.AttributeName: + { + // Data Attribute + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + } + + case Vim.G3dNext.Attributes.MaterialSmoothnessAttribute.AttributeName: + { + // Data Attribute + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + } + + default: + throw new ArgumentException(nameof(attributeName)); + } + } + + public void Validate() + { + // Ensure all the indices are either -1 or within the bounds of the attributes they are indexing into. + + } + } + + public class G3dScene2 + { + public G3DNext source; + + public G3dScene2() + { + this.source = new G3DNext (); + } + + public G3dScene2(G3DNext source) + { + this.source = source; + } + + public G3dScene2(BFastNext.BFastNext bfast) + { + this.source = new G3DNext(bfast); + } + + + public System.Int32[] InstanceFiles + { + get => source.AttributeCollection.InstanceFilesAttribute.TypedData; + set => source.AttributeCollection.InstanceFilesAttribute.TypedData = value; + } + + public System.Int32[] InstanceIndices + { + get => source.AttributeCollection.InstanceIndicesAttribute.TypedData; + set => source.AttributeCollection.InstanceIndicesAttribute.TypedData = value; + } + + public System.Int32[] InstanceNodes + { + get => source.AttributeCollection.InstanceNodesAttribute.TypedData; + set => source.AttributeCollection.InstanceNodesAttribute.TypedData = value; + } + + public System.Int32[] InstanceGroups + { + get => source.AttributeCollection.InstanceGroupsAttribute.TypedData; + set => source.AttributeCollection.InstanceGroupsAttribute.TypedData = value; + } + + public System.Int64[] InstanceTags + { + get => source.AttributeCollection.InstanceTagsAttribute.TypedData; + set => source.AttributeCollection.InstanceTagsAttribute.TypedData = value; + } + + public System.UInt16[] InstanceFlags + { + get => source.AttributeCollection.InstanceFlagsAttribute.TypedData; + set => source.AttributeCollection.InstanceFlagsAttribute.TypedData = value; + } + + public Vim.Math3d.Vector3[] InstanceMins + { + get => source.AttributeCollection.InstanceMinsAttribute.TypedData; + set => source.AttributeCollection.InstanceMinsAttribute.TypedData = value; + } + + public Vim.Math3d.Vector3[] InstanceMaxs + { + get => source.AttributeCollection.InstanceMaxsAttribute.TypedData; + set => source.AttributeCollection.InstanceMaxsAttribute.TypedData = value; + } + + public System.Int32[] MeshInstanceCounts + { + get => source.AttributeCollection.MeshInstanceCountsAttribute.TypedData; + set => source.AttributeCollection.MeshInstanceCountsAttribute.TypedData = value; + } + + public System.Int32[] MeshIndexCounts + { + get => source.AttributeCollection.MeshIndexCountsAttribute.TypedData; + set => source.AttributeCollection.MeshIndexCountsAttribute.TypedData = value; + } + + public System.Int32[] MeshVertexCounts + { + get => source.AttributeCollection.MeshVertexCountsAttribute.TypedData; + set => source.AttributeCollection.MeshVertexCountsAttribute.TypedData = value; + } + + public System.Int32[] MeshOpaqueIndexCounts + { + get => source.AttributeCollection.MeshOpaqueIndexCountsAttribute.TypedData; + set => source.AttributeCollection.MeshOpaqueIndexCountsAttribute.TypedData = value; + } + + public System.Int32[] MeshOpaqueVertexCounts + { + get => source.AttributeCollection.MeshOpaqueVertexCountsAttribute.TypedData; + set => source.AttributeCollection.MeshOpaqueVertexCountsAttribute.TypedData = value; + } + } + + + public partial class SceneAttributeCollection : IAttributeCollection + { + public IEnumerable AttributeNames + => Attributes.Keys; + + public long GetSize() + => Attributes.Values.Sum(a => a.Data.LongLength * a.AttributeDescriptor.DataElementSize); + + public IDictionary Attributes { get; } + = new Dictionary + { + [Vim.G3dNext.Attributes.InstanceFilesAttribute.AttributeName] = new Vim.G3dNext.Attributes.InstanceFilesAttribute(), + [Vim.G3dNext.Attributes.InstanceIndicesAttribute.AttributeName] = new Vim.G3dNext.Attributes.InstanceIndicesAttribute(), + [Vim.G3dNext.Attributes.InstanceNodesAttribute.AttributeName] = new Vim.G3dNext.Attributes.InstanceNodesAttribute(), + [Vim.G3dNext.Attributes.InstanceGroupsAttribute.AttributeName] = new Vim.G3dNext.Attributes.InstanceGroupsAttribute(), + [Vim.G3dNext.Attributes.InstanceTagsAttribute.AttributeName] = new Vim.G3dNext.Attributes.InstanceTagsAttribute(), + [Vim.G3dNext.Attributes.InstanceFlagsAttribute.AttributeName] = new Vim.G3dNext.Attributes.InstanceFlagsAttribute(), + [Vim.G3dNext.Attributes.InstanceMinsAttribute.AttributeName] = new Vim.G3dNext.Attributes.InstanceMinsAttribute(), + [Vim.G3dNext.Attributes.InstanceMaxsAttribute.AttributeName] = new Vim.G3dNext.Attributes.InstanceMaxsAttribute(), + [Vim.G3dNext.Attributes.MeshInstanceCountsAttribute.AttributeName] = new Vim.G3dNext.Attributes.MeshInstanceCountsAttribute(), + [Vim.G3dNext.Attributes.MeshIndexCountsAttribute.AttributeName] = new Vim.G3dNext.Attributes.MeshIndexCountsAttribute(), + [Vim.G3dNext.Attributes.MeshVertexCountsAttribute.AttributeName] = new Vim.G3dNext.Attributes.MeshVertexCountsAttribute(), + [Vim.G3dNext.Attributes.MeshOpaqueIndexCountsAttribute.AttributeName] = new Vim.G3dNext.Attributes.MeshOpaqueIndexCountsAttribute(), + [Vim.G3dNext.Attributes.MeshOpaqueVertexCountsAttribute.AttributeName] = new Vim.G3dNext.Attributes.MeshOpaqueVertexCountsAttribute(), + }; + + // Named Attributes. + + public Vim.G3dNext.Attributes.InstanceFilesAttribute InstanceFilesAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.InstanceFilesAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceFilesAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.InstanceFilesAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.InstanceIndicesAttribute InstanceIndicesAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.InstanceIndicesAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceIndicesAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.InstanceIndicesAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.InstanceNodesAttribute InstanceNodesAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.InstanceNodesAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceNodesAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.InstanceNodesAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.InstanceGroupsAttribute InstanceGroupsAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.InstanceGroupsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceGroupsAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.InstanceGroupsAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.InstanceTagsAttribute InstanceTagsAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.InstanceTagsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceTagsAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.InstanceTagsAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.InstanceFlagsAttribute InstanceFlagsAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.InstanceFlagsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceFlagsAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.InstanceFlagsAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.InstanceMinsAttribute InstanceMinsAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.InstanceMinsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceMinsAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.InstanceMinsAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.InstanceMaxsAttribute InstanceMaxsAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.InstanceMaxsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceMaxsAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.InstanceMaxsAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.MeshInstanceCountsAttribute MeshInstanceCountsAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.MeshInstanceCountsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshInstanceCountsAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.MeshInstanceCountsAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.MeshIndexCountsAttribute MeshIndexCountsAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.MeshIndexCountsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshIndexCountsAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.MeshIndexCountsAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.MeshVertexCountsAttribute MeshVertexCountsAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.MeshVertexCountsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshVertexCountsAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.MeshVertexCountsAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.MeshOpaqueIndexCountsAttribute MeshOpaqueIndexCountsAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.MeshOpaqueIndexCountsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshOpaqueIndexCountsAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.MeshOpaqueIndexCountsAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.MeshOpaqueVertexCountsAttribute MeshOpaqueVertexCountsAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.MeshOpaqueVertexCountsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshOpaqueVertexCountsAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.MeshOpaqueVertexCountsAttribute.AttributeName] = value as IAttribute; + } + + /// + public IAttribute GetAttribute(Type attributeType) + { + + if (attributeType == typeof(Vim.G3dNext.Attributes.InstanceFilesAttribute)) + return InstanceFilesAttribute; + + if (attributeType == typeof(Vim.G3dNext.Attributes.InstanceIndicesAttribute)) + return InstanceIndicesAttribute; + + if (attributeType == typeof(Vim.G3dNext.Attributes.InstanceNodesAttribute)) + return InstanceNodesAttribute; + + if (attributeType == typeof(Vim.G3dNext.Attributes.InstanceGroupsAttribute)) + return InstanceGroupsAttribute; + + if (attributeType == typeof(Vim.G3dNext.Attributes.InstanceTagsAttribute)) + return InstanceTagsAttribute; + + if (attributeType == typeof(Vim.G3dNext.Attributes.InstanceFlagsAttribute)) + return InstanceFlagsAttribute; + + if (attributeType == typeof(Vim.G3dNext.Attributes.InstanceMinsAttribute)) + return InstanceMinsAttribute; + + if (attributeType == typeof(Vim.G3dNext.Attributes.InstanceMaxsAttribute)) + return InstanceMaxsAttribute; + + if (attributeType == typeof(Vim.G3dNext.Attributes.MeshInstanceCountsAttribute)) + return MeshInstanceCountsAttribute; + + if (attributeType == typeof(Vim.G3dNext.Attributes.MeshIndexCountsAttribute)) + return MeshIndexCountsAttribute; + + if (attributeType == typeof(Vim.G3dNext.Attributes.MeshVertexCountsAttribute)) + return MeshVertexCountsAttribute; + + if (attributeType == typeof(Vim.G3dNext.Attributes.MeshOpaqueIndexCountsAttribute)) + return MeshOpaqueIndexCountsAttribute; + + if (attributeType == typeof(Vim.G3dNext.Attributes.MeshOpaqueVertexCountsAttribute)) + return MeshOpaqueVertexCountsAttribute; + + throw new ArgumentException("Type {attributeType.ToString()} is not supported."); + } + + public IAttribute MergeAttribute(string attributeName, IReadOnlyList otherCollections) + { + var collections = otherCollections.Prepend(this).ToArray(); + switch (attributeName) + { + + case Vim.G3dNext.Attributes.InstanceFilesAttribute.AttributeName: + { + // Data Attribute + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + } + + case Vim.G3dNext.Attributes.InstanceIndicesAttribute.AttributeName: + { + // Data Attribute + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + } + + case Vim.G3dNext.Attributes.InstanceNodesAttribute.AttributeName: + { + // Data Attribute + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + } + + case Vim.G3dNext.Attributes.InstanceGroupsAttribute.AttributeName: + { + // Data Attribute + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + } + + case Vim.G3dNext.Attributes.InstanceTagsAttribute.AttributeName: + { + // Data Attribute + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + } + + case Vim.G3dNext.Attributes.InstanceFlagsAttribute.AttributeName: + { + // Data Attribute + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + } + + case Vim.G3dNext.Attributes.InstanceMinsAttribute.AttributeName: + { + // Data Attribute + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + } + + case Vim.G3dNext.Attributes.InstanceMaxsAttribute.AttributeName: + { + // Data Attribute + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + } + + case Vim.G3dNext.Attributes.MeshInstanceCountsAttribute.AttributeName: + { + // Data Attribute + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + } + + case Vim.G3dNext.Attributes.MeshIndexCountsAttribute.AttributeName: + { + // Data Attribute + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + } + + case Vim.G3dNext.Attributes.MeshVertexCountsAttribute.AttributeName: + { + // Data Attribute + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + } + + case Vim.G3dNext.Attributes.MeshOpaqueIndexCountsAttribute.AttributeName: + { + // Data Attribute + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + } + + case Vim.G3dNext.Attributes.MeshOpaqueVertexCountsAttribute.AttributeName: + { + // Data Attribute + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + } + + default: + throw new ArgumentException(nameof(attributeName)); + } + } + + public void Validate() + { + // Ensure all the indices are either -1 or within the bounds of the attributes they are indexing into. + + } + } + + public class G3dMesh2 + { + public G3DNext source; + + public G3dMesh2() + { + this.source = new G3DNext (); + } + + public G3dMesh2(G3DNext source) + { + this.source = source; + } + + public G3dMesh2(BFastNext.BFastNext bfast) + { + this.source = new G3DNext(bfast); + } + + + public Vim.Math3d.Matrix4x4[] MeshInstanceTransform + { + get => source.AttributeCollection.MeshInstanceTransformAttribute.TypedData; + set => source.AttributeCollection.MeshInstanceTransformAttribute.TypedData = value; + } + + public System.Int32[] MeshOpaqueSubmeshCount + { + get => source.AttributeCollection.MeshOpaqueSubmeshCountAttribute.TypedData; + set => source.AttributeCollection.MeshOpaqueSubmeshCountAttribute.TypedData = value; + } + + public System.Int32[] MeshSubmeshIndexOffset + { + get => source.AttributeCollection.MeshSubmeshIndexOffsetAttribute.TypedData; + set => source.AttributeCollection.MeshSubmeshIndexOffsetAttribute.TypedData = value; + } + + public System.Int32[] MeshSubmeshVertexOffset + { + get => source.AttributeCollection.MeshSubmeshVertexOffsetAttribute.TypedData; + set => source.AttributeCollection.MeshSubmeshVertexOffsetAttribute.TypedData = value; + } + + public System.Int32[] MeshSubmeshMaterial + { + get => source.AttributeCollection.MeshSubmeshMaterialAttribute.TypedData; + set => source.AttributeCollection.MeshSubmeshMaterialAttribute.TypedData = value; + } + + public Vim.Math3d.Vector3[] MeshVertex + { + get => source.AttributeCollection.MeshVertexAttribute.TypedData; + set => source.AttributeCollection.MeshVertexAttribute.TypedData = value; + } + + public System.Int32[] MeshIndex + { + get => source.AttributeCollection.MeshIndexAttribute.TypedData; + set => source.AttributeCollection.MeshIndexAttribute.TypedData = value; + } + } + + + public partial class MeshAttributeCollection : IAttributeCollection + { + public IEnumerable AttributeNames + => Attributes.Keys; + + public long GetSize() + => Attributes.Values.Sum(a => a.Data.LongLength * a.AttributeDescriptor.DataElementSize); + + public IDictionary Attributes { get; } + = new Dictionary + { + [Vim.G3dNext.Attributes.MeshInstanceTransformAttribute.AttributeName] = new Vim.G3dNext.Attributes.MeshInstanceTransformAttribute(), + [Vim.G3dNext.Attributes.MeshOpaqueSubmeshCountAttribute.AttributeName] = new Vim.G3dNext.Attributes.MeshOpaqueSubmeshCountAttribute(), + [Vim.G3dNext.Attributes.MeshSubmeshIndexOffsetAttribute.AttributeName] = new Vim.G3dNext.Attributes.MeshSubmeshIndexOffsetAttribute(), + [Vim.G3dNext.Attributes.MeshSubmeshVertexOffsetAttribute.AttributeName] = new Vim.G3dNext.Attributes.MeshSubmeshVertexOffsetAttribute(), + [Vim.G3dNext.Attributes.MeshSubmeshMaterialAttribute.AttributeName] = new Vim.G3dNext.Attributes.MeshSubmeshMaterialAttribute(), + [Vim.G3dNext.Attributes.MeshVertexAttribute.AttributeName] = new Vim.G3dNext.Attributes.MeshVertexAttribute(), + [Vim.G3dNext.Attributes.MeshIndexAttribute.AttributeName] = new Vim.G3dNext.Attributes.MeshIndexAttribute(), + }; + + // Named Attributes. + + public Vim.G3dNext.Attributes.MeshInstanceTransformAttribute MeshInstanceTransformAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.MeshInstanceTransformAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshInstanceTransformAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.MeshInstanceTransformAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.MeshOpaqueSubmeshCountAttribute MeshOpaqueSubmeshCountAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.MeshOpaqueSubmeshCountAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshOpaqueSubmeshCountAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.MeshOpaqueSubmeshCountAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.MeshSubmeshIndexOffsetAttribute MeshSubmeshIndexOffsetAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.MeshSubmeshIndexOffsetAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshSubmeshIndexOffsetAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.MeshSubmeshIndexOffsetAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.MeshSubmeshVertexOffsetAttribute MeshSubmeshVertexOffsetAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.MeshSubmeshVertexOffsetAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshSubmeshVertexOffsetAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.MeshSubmeshVertexOffsetAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.MeshSubmeshMaterialAttribute MeshSubmeshMaterialAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.MeshSubmeshMaterialAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshSubmeshMaterialAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.MeshSubmeshMaterialAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.MeshVertexAttribute MeshVertexAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.MeshVertexAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshVertexAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.MeshVertexAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.MeshIndexAttribute MeshIndexAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.MeshIndexAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshIndexAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.MeshIndexAttribute.AttributeName] = value as IAttribute; + } + + /// + public IAttribute GetAttribute(Type attributeType) + { + + if (attributeType == typeof(Vim.G3dNext.Attributes.MeshInstanceTransformAttribute)) + return MeshInstanceTransformAttribute; + + if (attributeType == typeof(Vim.G3dNext.Attributes.MeshOpaqueSubmeshCountAttribute)) + return MeshOpaqueSubmeshCountAttribute; + + if (attributeType == typeof(Vim.G3dNext.Attributes.MeshSubmeshIndexOffsetAttribute)) + return MeshSubmeshIndexOffsetAttribute; + + if (attributeType == typeof(Vim.G3dNext.Attributes.MeshSubmeshVertexOffsetAttribute)) + return MeshSubmeshVertexOffsetAttribute; + + if (attributeType == typeof(Vim.G3dNext.Attributes.MeshSubmeshMaterialAttribute)) + return MeshSubmeshMaterialAttribute; + + if (attributeType == typeof(Vim.G3dNext.Attributes.MeshVertexAttribute)) + return MeshVertexAttribute; + + if (attributeType == typeof(Vim.G3dNext.Attributes.MeshIndexAttribute)) + return MeshIndexAttribute; + + throw new ArgumentException("Type {attributeType.ToString()} is not supported."); + } + + public IAttribute MergeAttribute(string attributeName, IReadOnlyList otherCollections) + { + var collections = otherCollections.Prepend(this).ToArray(); + switch (attributeName) + { + + case Vim.G3dNext.Attributes.MeshInstanceTransformAttribute.AttributeName: + { + // Data Attribute + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + } + + case Vim.G3dNext.Attributes.MeshOpaqueSubmeshCountAttribute.AttributeName: + { + // Data Attribute + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + } + + case Vim.G3dNext.Attributes.MeshSubmeshIndexOffsetAttribute.AttributeName: + { + // Index Attribute + return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); + } + + case Vim.G3dNext.Attributes.MeshSubmeshVertexOffsetAttribute.AttributeName: + { + // Index Attribute + return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); + } + + case Vim.G3dNext.Attributes.MeshSubmeshMaterialAttribute.AttributeName: + { + // Index Attribute + return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); + } + + case Vim.G3dNext.Attributes.MeshVertexAttribute.AttributeName: + { + // Data Attribute + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + } + + case Vim.G3dNext.Attributes.MeshIndexAttribute.AttributeName: + { + // Index Attribute + return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); + } + + default: + throw new ArgumentException(nameof(attributeName)); + } + } + + public void Validate() + { + // Ensure all the indices are either -1 or within the bounds of the attributes they are indexing into. + + { + var maxIndex = GetAttribute(MeshSubmeshIndexOffsetAttribute.IndexInto).Data.Length - 1; + for (var i = 0; i < MeshSubmeshIndexOffsetAttribute.TypedData.Length; ++i) + { + var index = MeshSubmeshIndexOffsetAttribute.TypedData[i]; + + if (index == -1) + continue; // no relation. + + if (index < -1 || index > maxIndex) + throw new Exception($"Index out of range in Vim.G3dNext.Attributes.MeshSubmeshIndexOffsetAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); + } + } + + { + var maxIndex = GetAttribute(MeshSubmeshVertexOffsetAttribute.IndexInto).Data.Length - 1; + for (var i = 0; i < MeshSubmeshVertexOffsetAttribute.TypedData.Length; ++i) + { + var index = MeshSubmeshVertexOffsetAttribute.TypedData[i]; + + if (index == -1) + continue; // no relation. + + if (index < -1 || index > maxIndex) + throw new Exception($"Index out of range in Vim.G3dNext.Attributes.MeshSubmeshVertexOffsetAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); + } + } + + { + var maxIndex = GetAttribute(MeshSubmeshMaterialAttribute.IndexInto).Data.Length - 1; + for (var i = 0; i < MeshSubmeshMaterialAttribute.TypedData.Length; ++i) + { + var index = MeshSubmeshMaterialAttribute.TypedData[i]; + + if (index == -1) + continue; // no relation. + + if (index < -1 || index > maxIndex) + throw new Exception($"Index out of range in Vim.G3dNext.Attributes.MeshSubmeshMaterialAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); + } + } + + { + var maxIndex = GetAttribute(MeshIndexAttribute.IndexInto).Data.Length - 1; + for (var i = 0; i < MeshIndexAttribute.TypedData.Length; ++i) + { + var index = MeshIndexAttribute.TypedData[i]; + + if (index == -1) + continue; // no relation. + + if (index < -1 || index > maxIndex) + throw new Exception($"Index out of range in Vim.G3dNext.Attributes.MeshIndexAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); + } + } + } + } +} diff --git a/src/cs/g3d/Vim.G3dNext.Attributes/MaterialAttributes.cs b/src/cs/g3d/Vim.G3dNext.Attributes/MaterialAttributes.cs new file mode 100644 index 00000000..55060da5 --- /dev/null +++ b/src/cs/g3d/Vim.G3dNext.Attributes/MaterialAttributes.cs @@ -0,0 +1,23 @@ +using Vim.Math3d; + +namespace Vim.G3dNext.Attributes +{ + [AttributeCollection( + typeof(MaterialColorAttribute), + typeof(MaterialGlossinessAttribute), + typeof(MaterialSmoothnessAttribute) + )] + public partial class MaterialAttributeCollection // : IAttributeCollection + { + + } + + [AttributeDescriptor("g3d:material:color:0:float32:4", AttributeType.Data, ArrayType = typeof(Vector4))] + public partial class MaterialColorAttribute { } + + [AttributeDescriptor("g3d:material:glossiness:0:float32:1", AttributeType.Data)] + public partial class MaterialGlossinessAttribute { } + + [AttributeDescriptor("g3d:material:smoothness:0:float32:1", AttributeType.Data)] + public partial class MaterialSmoothnessAttribute { } +} diff --git a/src/cs/g3d/Vim.G3dNext.Attributes/MeshAttributes.cs b/src/cs/g3d/Vim.G3dNext.Attributes/MeshAttributes.cs new file mode 100644 index 00000000..a18ad02e --- /dev/null +++ b/src/cs/g3d/Vim.G3dNext.Attributes/MeshAttributes.cs @@ -0,0 +1,39 @@ +using Vim.Math3d; + +namespace Vim.G3dNext.Attributes +{ + [AttributeCollection( + typeof(MeshInstanceTransformAttribute), + typeof(MeshOpaqueSubmeshCountAttribute), + typeof(MeshSubmeshIndexOffsetAttribute), + typeof(MeshSubmeshVertexOffsetAttribute), + typeof(MeshSubmeshMaterialAttribute), + typeof(MeshVertexAttribute), + typeof(MeshIndexAttribute) + )] + public partial class MeshAttributeCollection // : IAttributeCollection + { + + } + + [AttributeDescriptor("g3d:instance:transform:0:float32:16", AttributeType.Data, ArrayType = typeof(Matrix4x4))] + public partial class MeshInstanceTransformAttribute { } + + [AttributeDescriptor("g3d:mesh:opaquesubmeshcount:0:int32:1", AttributeType.Data)] + public partial class MeshOpaqueSubmeshCountAttribute { } + + [AttributeDescriptor("g3d:submesh:indexoffset:0:int32:1", AttributeType.Index, IndexInto = typeof(IndexAttribute))] + public partial class MeshSubmeshIndexOffsetAttribute { } + + [AttributeDescriptor("g3d:submesh:vertexoffset:0:int32:1", AttributeType.Index, IndexInto = typeof(IndexAttribute))] + public partial class MeshSubmeshVertexOffsetAttribute { } + + [AttributeDescriptor("g3d:submesh:material:0:int32:1", AttributeType.Index, IndexInto = typeof(MaterialColorAttribute))] + public partial class MeshSubmeshMaterialAttribute { } + + [AttributeDescriptor("g3d:vertex:position:0:float32:3", AttributeType.Data, ArrayType = typeof(Vector3))] + public partial class MeshVertexAttribute { } + + [AttributeDescriptor("g3d:corner:index:0:int32:1", AttributeType.Index, IndexInto = typeof(VertexAttribute))] + public partial class MeshIndexAttribute { } +} diff --git a/src/cs/g3d/Vim.G3dNext.Attributes/SceneAttributes.cs b/src/cs/g3d/Vim.G3dNext.Attributes/SceneAttributes.cs new file mode 100644 index 00000000..9a2c5245 --- /dev/null +++ b/src/cs/g3d/Vim.G3dNext.Attributes/SceneAttributes.cs @@ -0,0 +1,61 @@ +using Vim.Math3d; + +namespace Vim.G3dNext.Attributes +{ + [AttributeCollection( + typeof(InstanceFilesAttribute), + typeof(InstanceIndicesAttribute), + typeof(InstanceNodesAttribute), + typeof(InstanceGroupsAttribute), + typeof(InstanceTagsAttribute), + typeof(InstanceFlagsAttribute), + typeof(InstanceMinsAttribute), + typeof(InstanceMaxsAttribute), + typeof(MeshInstanceCountsAttribute), + typeof(MeshIndexCountsAttribute), + typeof(MeshVertexCountsAttribute), + typeof(MeshOpaqueIndexCountsAttribute), + typeof(MeshOpaqueVertexCountsAttribute) + )] + public partial class SceneAttributeCollection // : IAttributeCollection + { + + } + + [AttributeDescriptor("g3d:instance:file:0:int32:1", AttributeType.Data)] + public partial class InstanceFilesAttribute { } + + [AttributeDescriptor("g3d:instance:node:0:int32:1", AttributeType.Data)] + public partial class InstanceNodesAttribute { } + + [AttributeDescriptor("g3d:instance:index:0:int32:1", AttributeType.Data)] + public partial class InstanceIndicesAttribute { } + + [AttributeDescriptor("g3d:instance:group:0:int32:1", AttributeType.Data)] + public partial class InstanceGroupsAttribute { } + + [AttributeDescriptor("g3d:instance:tag:0:int64:1", AttributeType.Data)] + public partial class InstanceTagsAttribute { } + + [AttributeDescriptor("g3d:instance:min:0:float32:3", AttributeType.Data, ArrayType = typeof(Vector3))] + public partial class InstanceMinsAttribute { } + + [AttributeDescriptor("g3d:instance:max:0:float32:3", AttributeType.Data, ArrayType = typeof(Vector3))] + public partial class InstanceMaxsAttribute { } + + [AttributeDescriptor("g3d:mesh:instancecount:0:int32:1", AttributeType.Data)] + public partial class MeshInstanceCountsAttribute { } + + [AttributeDescriptor("g3d:mesh:vertexcount:0:int32:1", AttributeType.Data)] + public partial class MeshVertexCountsAttribute { } + + [AttributeDescriptor("g3d:mesh:indexcount:0:int32:1", AttributeType.Data)] + public partial class MeshIndexCountsAttribute { } + + [AttributeDescriptor("g3d:mesh:opaquevertexcount:0:int32:1", AttributeType.Data)] + public partial class MeshOpaqueVertexCountsAttribute { } + + [AttributeDescriptor("g3d:mesh:opaqueindexcount:0:int32:1", AttributeType.Data)] + public partial class MeshOpaqueIndexCountsAttribute { } + +} diff --git a/src/cs/g3d/Vim.G3dNext.Attributes/Vim.G3dNext.Attributes.csproj b/src/cs/g3d/Vim.G3dNext.Attributes/Vim.G3dNext.Attributes.csproj new file mode 100644 index 00000000..b842cea6 --- /dev/null +++ b/src/cs/g3d/Vim.G3dNext.Attributes/Vim.G3dNext.Attributes.csproj @@ -0,0 +1,15 @@ + + + netstandard2.0 + + + + + + + + + + + + diff --git a/src/cs/g3d/Vim.G3dNext.Attributes/VimAttributes.cs b/src/cs/g3d/Vim.G3dNext.Attributes/VimAttributes.cs new file mode 100644 index 00000000..bbbd5145 --- /dev/null +++ b/src/cs/g3d/Vim.G3dNext.Attributes/VimAttributes.cs @@ -0,0 +1,70 @@ +using Vim.Math3d; + +namespace Vim.G3dNext.Attributes +{ + [AttributeCollection( + typeof(CornersPerFaceAttribute), + typeof(VertexAttribute), + typeof(IndexAttribute), + typeof(InstanceTransformAttribute), + typeof(InstanceParentAttribute), + typeof(InstanceFlagsAttribute), + typeof(InstanceMeshAttribute), + typeof(MeshSubmeshOffsetAttribute), + typeof(SubmeshIndexOffsetAttribute), + typeof(SubmeshMaterialAttribute), + typeof(MaterialColorAttribute), + typeof(MaterialGlossinessAttribute), + typeof(MaterialSmoothnessAttribute), + typeof(ShapeVertexAttribute), + typeof(ShapeVertexOffsetAttribute), + typeof(ShapeColorAttribute), + typeof(ShapeWidthAttribute) + )] + public partial class VimAttributeCollection // : IAttributeCollection + { + + } + + [AttributeDescriptor("g3d:all:facesize:0:int32:1", AttributeType.Singleton)] + public partial class CornersPerFaceAttribute { } + + [AttributeDescriptor("g3d:vertex:position:0:float32:3", AttributeType.Data, ArrayType = typeof(Vector3))] + public partial class VertexAttribute { } + + [AttributeDescriptor("g3d:corner:index:0:int32:1", AttributeType.Index, IndexInto = typeof(VertexAttribute))] + public partial class IndexAttribute { } + + [AttributeDescriptor("g3d:instance:transform:0:float32:16", AttributeType.Data, ArrayType = typeof(Matrix4x4))] + public partial class InstanceTransformAttribute { } + + [AttributeDescriptor("g3d:instance:parent:0:int32:1", AttributeType.Index, IndexInto = typeof(InstanceTransformAttribute))] + public partial class InstanceParentAttribute { } + + [AttributeDescriptor("g3d:instance:flags:0:uint16:1", AttributeType.Data)] + public partial class InstanceFlagsAttribute { } + + [AttributeDescriptor("g3d:instance:mesh:0:int32:1", AttributeType.Index, IndexInto = typeof(MeshSubmeshOffsetAttribute))] + public partial class InstanceMeshAttribute { } + + [AttributeDescriptor("g3d:mesh:submeshoffset:0:int32:1", AttributeType.Index, IndexInto = typeof(SubmeshIndexOffsetAttribute))] + public partial class MeshSubmeshOffsetAttribute { } + + [AttributeDescriptor("g3d:submesh:indexoffset:0:int32:1", AttributeType.Index, IndexInto = typeof(IndexAttribute))] + public partial class SubmeshIndexOffsetAttribute { } + + [AttributeDescriptor("g3d:submesh:material:0:int32:1", AttributeType.Index, IndexInto = typeof(MaterialColorAttribute))] + public partial class SubmeshMaterialAttribute { } + + [AttributeDescriptor("g3d:shapevertex:position:0:float32:3", AttributeType.Data, ArrayType = typeof(Vector3))] + public partial class ShapeVertexAttribute { } + + [AttributeDescriptor("g3d:shape:vertexoffset:0:int32:1", AttributeType.Index, IndexInto = typeof(ShapeVertexAttribute))] + public partial class ShapeVertexOffsetAttribute { } + + [AttributeDescriptor("g3d:shape:color:0:float32:4", AttributeType.Data, ArrayType = typeof(Vector4))] + public partial class ShapeColorAttribute { } + + [AttributeDescriptor("g3d:shape:width:0:float32:1", AttributeType.Data)] + public partial class ShapeWidthAttribute { } +} diff --git a/src/cs/g3d/Vim.G3dNext.CodeGen/CodeBuilder.cs b/src/cs/g3d/Vim.G3dNext.CodeGen/CodeBuilder.cs new file mode 100644 index 00000000..b3bf8158 --- /dev/null +++ b/src/cs/g3d/Vim.G3dNext.CodeGen/CodeBuilder.cs @@ -0,0 +1,64 @@ +using System.Linq; +using System.Text; + +namespace Vim.G3dNext.CodeGen +{ + public class CodeBuilder + { + private int _indentCount; + private StringBuilder _sb = new StringBuilder(); + + public CodeBuilder AppendRaw(string line) + { + _sb.Append(new string(' ', _indentCount * 4)); + _sb.AppendLine(line); + return this; + } + + public CodeBuilder AppendLine(string line = "") + { + var openBraces = line.Count(c => c == '{'); + var closeBraces = line.Count(c => c == '}'); + + // Sometimes we have {} on the same line + if (openBraces == closeBraces) + { + openBraces = 0; + closeBraces = 0; + } + + _indentCount -= closeBraces; + _sb.Append(new string(' ', _indentCount * 4)); + _sb.AppendLine(line); + _indentCount += openBraces; + return this; + } + + public void Indent() + { + ++_indentCount; + } + + public void Unindent() + { + _indentCount = System.Math.Max(0, --_indentCount); + } + + public void IndentOneLine(string line) + { + Indent(); + AppendLine(line); + Unindent(); + } + + public void UnindentOneLine(string line) + { + Unindent(); + AppendLine(line); + Indent(); + } + + public override string ToString() + => _sb.ToString(); + } +} diff --git a/src/cs/g3d/Vim.G3dNext.CodeGen/G3dAttributeCollectionGenerator.cs b/src/cs/g3d/Vim.G3dNext.CodeGen/G3dAttributeCollectionGenerator.cs new file mode 100644 index 00000000..b92d660f --- /dev/null +++ b/src/cs/g3d/Vim.G3dNext.CodeGen/G3dAttributeCollectionGenerator.cs @@ -0,0 +1,296 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; + +namespace Vim.G3dNext.CodeGen +{ + + public static class G3dAttributeCollectionGenerator + { + public static void WriteDocument(string filePath) + { + try + { + var cb = new CodeBuilder(); + + cb.AppendLine("// AUTO-GENERATED FILE, DO NOT MODIFY."); + cb.AppendLine("// ReSharper disable All"); + cb.AppendLine("using System;"); + cb.AppendLine("using System.IO;"); + cb.AppendLine("using System.Collections.Generic;"); + cb.AppendLine("using System.Linq;"); + cb.AppendLine("using Vim.BFast;"); + cb.AppendLine(); + cb.AppendLine("namespace Vim.G3dNext.Attributes"); + cb.AppendLine("{"); + WriteVimG3dAttributes(cb); + WriteVimG3dAttributeCollections(cb); + cb.AppendLine("}"); + var content = cb.ToString(); + File.WriteAllText(filePath, content); + } + catch (Exception e) + { + Console.WriteLine(e); + throw; + } + } + + public static IEnumerable GetAllClassesWithAttribute() where T: Attribute + { + // Load the assembly containing the classes you want to examine + var assembly = Assembly.GetExecutingAssembly(); + + // Find all the types in the assembly that have the MyAttribute attribute + return assembly.GetTypes() + .Where(type => type.GetCustomAttributes(false).Any()); + } + + public static void WriteVimG3dAttributes(CodeBuilder cb) + { + var adClasses = GetAllClassesWithAttribute(); + + foreach (var adClass in adClasses) + WriteVimG3dAttribute(cb, adClass); + } + + public static string GetTypedDataType(this AttributeDescriptorAttribute ada) + { + if (ada.ArrayType != null) + return ada.ArrayType.ToString(); + + if (!AttributeDescriptor.TryParse(ada.Name, out var ad)) + throw new Exception($"Could not parse attribute name {ada.Name}"); + + return ad.DataType.GetManagedType().ToString(); + } + + public static void WriteVimG3dAttribute(CodeBuilder cb, Type adClass) + { + var className = adClass.Name; + var ada = adClass.GetCustomAttribute(); + if (ada == null) + throw new Exception($"No attribute of type {nameof(AttributeDescriptorAttribute)} found on {className}"); + + var attributeName = ada.Name; + if (!AttributeDescriptor.TryParse(attributeName, out var ad)) + throw new Exception($"Invalid attribute descriptor: {attributeName}"); + + var typedDataType = ada.GetTypedDataType(); + var attributeType = ada.AttributeType; + var indexInto = ada.IndexInto; + + cb.AppendLine($@" + public partial class {className} : {nameof(IAttribute)}<{typedDataType}> + {{ + public const string AttributeName = ""{attributeName}""; + + public string Name + => AttributeName; + + public int Count => TypedData?.Length ?? 0; + + public void AddTo(BFastNext.BFastNext bfast) + {{ + if(TypedData != null) + {{ + bfast.AddArray(Name, TypedData); + }} + }} + + public void ReadBFast(BFastNext.BFastNext bfast) + {{ + TypedData = bfast.GetArray<{typedDataType}>(""{attributeName}""); + }} + + public {nameof(IAttributeDescriptor)} {nameof(AttributeDescriptor)} {{ get; }} + = new {nameof(AttributeDescriptor)}(AttributeName); + + public {nameof(AttributeType)} {nameof(IAttribute.AttributeType)} {{ get; }} + = {nameof(AttributeType)}.{attributeType}; + + public Type {nameof(IAttribute.IndexInto)} {{ get; }} + = {(indexInto == default ? "null" : $"typeof({indexInto})")}; + + public {typedDataType}[] TypedData {{ get; set; }} + = Array.Empty<{typedDataType}>(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + {{ + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + }} + }}"); + } + + public static void WriteVimG3dAttributeCollections(CodeBuilder cb) + { + var acClasses = GetAllClassesWithAttribute(); + + foreach (var acClass in acClasses) + WriteVimG3dAttributeCollection(cb, acClass); + } + + public static void WriteVimG3dAttributeCollection(CodeBuilder cb, Type acClass) + { + var className = acClass.Name; + + var ac = acClass.GetCustomAttribute(); + if (ac == null) + throw new Exception($"No attribute of type {(nameof(AttributeCollectionAttribute))} found on {className}"); + + var attributeClasses = ac.AttributeClasses; + var g3dName = "G3d" + className.Replace("AttributeCollection", "2"); + + cb.AppendLine($@" + public class {g3dName} + {{ + public G3DNext<{className}> source; + + public {g3dName}() + {{ + this.source = new G3DNext<{className}> (); + }} + + public {g3dName}(G3DNext<{className}> source) + {{ + this.source = source; + }} + + public {g3dName}(BFastNext.BFastNext bfast) + {{ + this.source = new G3DNext<{className}>(bfast); + }} + + { + string.Join(Environment.NewLine, attributeClasses.Select(c => + { + var ada = c.GetCustomAttribute(); + var typedDataType = ada.GetTypedDataType(); + return $@" + public {typedDataType}[] {c.Name.Replace("Attribute","")} + {{ + get => source.AttributeCollection.{c.Name}.TypedData; + set => source.AttributeCollection.{c.Name}.TypedData = value; + }}";})) + } + }} +"); + + + cb.AppendLine($@" + public partial class {className} : IAttributeCollection + {{ + public IEnumerable AttributeNames + => Attributes.Keys; + + public long GetSize() + => Attributes.Values.Sum(a => a.Data.LongLength * a.AttributeDescriptor.DataElementSize); + + public IDictionary Attributes {{ get; }} + = new Dictionary + {{ +{string.Join(Environment.NewLine, attributeClasses.Select(c => + $" [{c}.AttributeName] = new {c}(),"))} + }}; + + // Named Attributes. +{string.Join(Environment.NewLine, attributeClasses.Select(c => $@" + public {c} {c.Name} + {{ + get => Attributes.TryGetValue({c}.AttributeName, out var attr) ? attr as {c} : default; + set => Attributes[{c}.AttributeName] = value as IAttribute; + }}"))} + + /// + public IAttribute GetAttribute(Type attributeType) + {{ +{string.Join(Environment.NewLine, attributeClasses.Select(c => $@" + if (attributeType == typeof({c})) + return {c.Name};"))} + + throw new ArgumentException(""Type {{attributeType.ToString()}} is not supported.""); + }} + + public IAttribute MergeAttribute(string attributeName, IReadOnlyList otherCollections) + {{ + var collections = otherCollections.Prepend(this).ToArray(); + switch (attributeName) + {{ +{string.Join(Environment.NewLine, attributeClasses.Select(c => { + var ada = c.GetCustomAttribute(); + var typedDataType = ada.GetTypedDataType(); + string caseBody = null; + switch (ada.AttributeType) + { + case AttributeType.Singleton: + caseBody = $@"// Singleton Attribute (no merging) + return {c.Name};"; + break; + case AttributeType.Data: + caseBody = $@"// Data Attribute + return collections.{nameof(AttributeCollectionExtensions.GetAttributesOfType)}<{c}>().ToArray().{nameof(AttributeExtensions.MergeDataAttributes)}<{c}, {typedDataType}>();"; + break; + case AttributeType.Index: + caseBody = $@"// Index Attribute + return collections.{nameof(AttributeCollectionExtensions.GetIndexedAttributesOfType)}<{c}>().{nameof(AttributeExtensions.MergeIndexAttributes)}();"; + break; + default: + throw new ArgumentOutOfRangeException(nameof(ada.AttributeType)); + } + + return $@" + case {c}.AttributeName: + {{ + {caseBody} + }}"; +}))} + + default: + throw new ArgumentException(nameof(attributeName)); + }} + }} + + public void Validate() + {{ + // Ensure all the indices are either -1 or within the bounds of the attributes they are indexing into. +{string.Join(Environment.NewLine, attributeClasses.Select(c => +{ + var ada = c.GetCustomAttribute(); + var typedDataType = ada.GetTypedDataType(); + + switch (ada.AttributeType) + { + case AttributeType.Singleton: + case AttributeType.Data: + return null; + case AttributeType.Index: + return $@" + {{ + var maxIndex = GetAttribute({c.Name}.IndexInto).Data.Length - 1; + for (var i = 0; i < {c.Name}.TypedData.Length; ++i) + {{ + var index = {c.Name}.TypedData[i]; + + if (index == -1) + continue; // no relation. + + if (index < -1 || index > maxIndex) + throw new Exception($""Index out of range in {c} at position {{i}}. Expected either -1 for no relation, or a maximum of {{maxIndex}} but got {{index}}""); + }} + }}"; + default: + throw new ArgumentOutOfRangeException(nameof(ada.AttributeType)); + } +}).Where(s => !string.IsNullOrEmpty(s)))} + }} + }}"); + } + } +} diff --git a/src/cs/g3d/Vim.G3dNext.CodeGen/Program.cs b/src/cs/g3d/Vim.G3dNext.CodeGen/Program.cs new file mode 100644 index 00000000..15a810c1 --- /dev/null +++ b/src/cs/g3d/Vim.G3dNext.CodeGen/Program.cs @@ -0,0 +1,11 @@ +namespace Vim.G3dNext.CodeGen +{ + public static class Program + { + public static void Main(string[] args) + { + var file = args[0]; + G3dAttributeCollectionGenerator.WriteDocument(file); + } + } +} diff --git a/src/cs/g3d/Vim.G3dNext.CodeGen/Vim.G3dNext.CodeGen.csproj b/src/cs/g3d/Vim.G3dNext.CodeGen/Vim.G3dNext.CodeGen.csproj new file mode 100644 index 00000000..ddc17234 --- /dev/null +++ b/src/cs/g3d/Vim.G3dNext.CodeGen/Vim.G3dNext.CodeGen.csproj @@ -0,0 +1,29 @@ + + + netstandard2.0;net6.0 + OnOutputUpdated + + + + Exe + + Vim.G3dNext.CodeGen.Program + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/cs/g3d/Vim.G3dNext.Tests/Vim.G3dNext.Tests.csproj b/src/cs/g3d/Vim.G3dNext.Tests/Vim.G3dNext.Tests.csproj new file mode 100644 index 00000000..7cc5875b --- /dev/null +++ b/src/cs/g3d/Vim.G3dNext.Tests/Vim.G3dNext.Tests.csproj @@ -0,0 +1,38 @@ + + + netstandard2.0 + false + + + + + + + + + + + + + + + + + + True + True + Resources.resx + + + + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + + + + diff --git a/src/cs/g3d/Vim.G3dNext/AttributeDescriptor.cs b/src/cs/g3d/Vim.G3dNext/AttributeDescriptor.cs new file mode 100644 index 00000000..4efc1157 --- /dev/null +++ b/src/cs/g3d/Vim.G3dNext/AttributeDescriptor.cs @@ -0,0 +1,182 @@ +using System; +using static Vim.G3dNext.Constants; + +namespace Vim.G3dNext +{ + public class AttributeDescriptor : IAttributeDescriptor + { + /// + public string Name + => string.Join(Separator, G3dPrefix, Association, Semantic, IndexStr, DataType, DataArity); + + /// + public string Association { get; } + + /// + public string Semantic { get; } + + /// + public int Index { get; } + private readonly string IndexStr; + + /// + public DataType DataType { get; } + public readonly string DataTypeStr; + + /// + public int DataArity { get; } + public readonly string DataArityStr; + + /// + public AttributeDescriptorErrors Errors { get; } + + /// + public bool HasErrors + => Errors != AttributeDescriptorErrors.None; + + /// + /// Returns true if the Errors contains a data type error. + /// + public bool HasDataTypeError + => (Errors & AttributeDescriptorErrors.DataTypeError) == AttributeDescriptorErrors.DataTypeError; + + /// + /// Returns true if the Errors contains a data arity error. + /// + public bool HasDataArityError + => (Errors & AttributeDescriptorErrors.DataArityError) == AttributeDescriptorErrors.DataArityError; + + /// + public int DataTypeSize { get; } + + /// + public int DataElementSize { get; } + + public static (int dataTypeSize, int dataElementSize) GetDataSizes(DataType dataType, int dataArity) + { + var dataTypeSize = dataType.GetDataTypeSize(); + return (dataTypeSize, dataTypeSize * dataArity); + } + + /// + /// Constructor. + /// + /// association semantic dataType + /// | | | + /// ~~~~~~~~ ~~~~~~~~~ ~~~~~~~ + /// "g3d:instance:transform:0:float32:16" + /// ^ ~~ + /// | | + /// index dataArity + /// + /// + public AttributeDescriptor( + string association, + string semantic, + int index, + DataType dataType, + int dataArity) + { + if (string.IsNullOrWhiteSpace(association)) + throw new ArgumentException($"The association cannot be null or whitespace."); + + if (association.Contains(Separator)) + throw new ArgumentException($"The association cannot contain a '{Separator}' character"); + + if (dataType == DataType.unknown) + throw new ArgumentException($"The data type cannot be '{DataType.unknown}'."); + + if (string.IsNullOrWhiteSpace(semantic)) + throw new ArgumentException($"The semantic cannot be null or whitespace."); + + if (semantic.Contains(Separator)) + throw new ArgumentException($"The semantic must not contain a '{Separator}' character"); + + Association = association; + Semantic = semantic; + Index = index; + IndexStr = Index.ToString(); + DataType = dataType; + DataTypeStr = DataType.ToString("G"); + DataArity = dataArity; + DataArityStr = DataArity.ToString(); + (DataTypeSize, DataElementSize) = GetDataSizes(DataType, DataArity); + } + + /// + /// Constructor. Parses an input string of the form: "g3d:instance:transform:0:float32:16". + /// + public AttributeDescriptor(string str) + { + var tokens = str.Split(SeparatorChar); + + if (tokens.Length != 6) + { + Errors = AttributeDescriptorErrors.UnexpectedNumberOfTokens; + return; + } + + if (tokens[0] != G3dPrefix) + { + Errors = AttributeDescriptorErrors.PrefixError; + return; + } + + Association = tokens[1]; + if (string.IsNullOrWhiteSpace(Association)) + Errors |= AttributeDescriptorErrors.AssociationError; // do not return; there may be more errors. + + Semantic = tokens[2]; + if (string.IsNullOrWhiteSpace(Semantic)) + Errors |= AttributeDescriptorErrors.SemanticError; // do not return; there may be more errors. + + IndexStr = tokens[3]; + if (!int.TryParse(IndexStr, out var index)) + Errors |= AttributeDescriptorErrors.IndexError; // do not return; there may be more errors. + Index = index; + + DataTypeStr = tokens[4]; + if (!Enum.TryParse(DataTypeStr, out DataType dataType)) + dataType = DataType.unknown; + + DataType = dataType; + if (DataType == DataType.unknown) + Errors |= AttributeDescriptorErrors.DataTypeError; // do not return; there may be more errors. + + DataArityStr = tokens[5]; + if (!int.TryParse(DataArityStr, out var dataArity)) + Errors |= AttributeDescriptorErrors.DataArityError; + DataArity = dataArity; + + if (!HasDataTypeError && !HasDataArityError) + { + (DataTypeSize, DataElementSize) = GetDataSizes(DataType, DataArity); + } + } + + /// + /// Returns the string representation of the attribute descriptor, in the form "g3d:instance:transform:0:float32:16" + /// + public override string ToString() + => Name; + + /// + /// Attempts to parse the given string as an AttributeDescriptor. + /// + public static bool TryParse(string str, out AttributeDescriptor attributeDescriptor) + { + attributeDescriptor = null; + + try + { + attributeDescriptor = new AttributeDescriptor(str); + } + catch + { + return false; + } + + return !attributeDescriptor.HasErrors; + } + } +} diff --git a/src/cs/g3d/Vim.G3dNext/AttributeDescriptorErrors.cs b/src/cs/g3d/Vim.G3dNext/AttributeDescriptorErrors.cs new file mode 100644 index 00000000..db1908d4 --- /dev/null +++ b/src/cs/g3d/Vim.G3dNext/AttributeDescriptorErrors.cs @@ -0,0 +1,17 @@ +using System; + +namespace Vim.G3dNext +{ + [Flags] + public enum AttributeDescriptorErrors + { + None = 0, + UnexpectedNumberOfTokens = 1, + PrefixError = 1 << 1, + AssociationError = 1 << 2, + SemanticError = 1 << 3, + IndexError = 1 << 4, + DataTypeError = 1 << 5, + DataArityError = 1 << 6, + } +} diff --git a/src/cs/g3d/Vim.G3dNext/AttributeType.cs b/src/cs/g3d/Vim.G3dNext/AttributeType.cs new file mode 100644 index 00000000..0c484534 --- /dev/null +++ b/src/cs/g3d/Vim.G3dNext/AttributeType.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Vim.G3dNext +{ + public enum AttributeType + { + Singleton, + Data, + Index + } +} diff --git a/src/cs/g3d/Vim.G3dNext/CodeGenAttributes.cs b/src/cs/g3d/Vim.G3dNext/CodeGenAttributes.cs new file mode 100644 index 00000000..ab8f1285 --- /dev/null +++ b/src/cs/g3d/Vim.G3dNext/CodeGenAttributes.cs @@ -0,0 +1,38 @@ +using System; +using System.Linq.Expressions; + +namespace Vim.G3dNext +{ + [AttributeUsage(AttributeTargets.Class)] + public class AttributeDescriptorAttribute : Attribute + { + public string Name { get; set; } + public Type ArrayType { get; set; } = null; + public AttributeType AttributeType { get; set; } = AttributeType.Data; + public Type IndexInto { get; set; } = null; + + public AttributeDescriptorAttribute(string name, AttributeType attributeType) + { + Name = name; + AttributeType = attributeType; + } + } + + [AttributeUsage(AttributeTargets.Class)] + public class AttributeCollectionAttribute : Attribute + { + public Type[] AttributeClasses { get; } + + public AttributeCollectionAttribute(params Type[] attributeClasses) + => AttributeClasses = attributeClasses; + } + + [AttributeUsage(AttributeTargets.Class)] + public class G3dDefinitionAttribute : Attribute + { + public Type[] AttributeClasses { get; } + + public G3dDefinitionAttribute(params Type[] attributeClasses) + => AttributeClasses = attributeClasses; + } +} \ No newline at end of file diff --git a/src/cs/g3d/Vim.G3dNext/Constants.cs b/src/cs/g3d/Vim.G3dNext/Constants.cs new file mode 100644 index 00000000..77266c1f --- /dev/null +++ b/src/cs/g3d/Vim.G3dNext/Constants.cs @@ -0,0 +1,16 @@ +namespace Vim.G3dNext +{ + public static class Constants + { + public const string G3dPrefix = "g3d"; + public const string Separator = ":"; + public const char SeparatorChar = ':'; + + public const string MetaHeaderSegmentName = "meta"; + public const long MetaHeaderSegmentNumBytes = 8; // The header is 7 bytes + 1 bytes padding. + public const byte MetaHeaderMagicA = 0x63; + public const byte MetaHeaderMagicB = 0xD0; + + public static readonly string[] MetaHeaderSupportedUnits = { "mm", "cm", "m\0", "km", "in", "ft", "yd", "mi" }; + } +} diff --git a/src/cs/g3d/Vim.G3dNext/DataType.cs b/src/cs/g3d/Vim.G3dNext/DataType.cs new file mode 100644 index 00000000..1621d7f5 --- /dev/null +++ b/src/cs/g3d/Vim.G3dNext/DataType.cs @@ -0,0 +1,87 @@ +using System; + +namespace Vim.G3dNext +{ + public enum DataType + { + /// + /// Exists to support future values which are currently unknown. + /// + unknown, + + // IMPORTANT: the string values of these data types, including their capitalization, + // are used in the parsing mechanism of the AttributeDescriptor, so be careful! + uint8, + int8, + uint16, + int16, + uint32, + int32, + uint64, + int64, + float32, + float64, + }; + + public static class DataTypeExtensions + { + /// + /// Returns the size in bytes of the given data type. + /// + public static int GetDataTypeSize(this DataType dt) + { + switch (dt) + { + case DataType.uint8: + case DataType.int8: + return 1; + case DataType.uint16: + case DataType.int16: + return 2; + case DataType.uint32: + case DataType.int32: + return 4; + case DataType.uint64: + case DataType.int64: + return 8; + case DataType.float32: + return 4; + case DataType.float64: + return 8; + case DataType.unknown: + default: + throw new ArgumentOutOfRangeException(nameof(dt), dt, null); + } + } + + public static Type GetManagedType(this DataType dt) + { + switch (dt) + { + case DataType.uint8: + return typeof(byte); + case DataType.int8: + return typeof(sbyte); + case DataType.uint16: + return typeof(ushort); + case DataType.int16: + return typeof(short); + case DataType.uint32: + return typeof(uint); + case DataType.int32: + return typeof(int); + case DataType.uint64: + return typeof(ulong); + case DataType.int64: + return typeof(long); + case DataType.float32: + return typeof(float); + case DataType.float64: + return typeof(double); + case DataType.unknown: + default: + throw new ArgumentOutOfRangeException(nameof(dt), dt, null); + } + } + } +} diff --git a/src/cs/g3d/Vim.G3dNext/G3DNext.cs b/src/cs/g3d/Vim.G3dNext/G3DNext.cs new file mode 100644 index 00000000..d7f24f45 --- /dev/null +++ b/src/cs/g3d/Vim.G3dNext/G3DNext.cs @@ -0,0 +1,111 @@ +using System.IO; +using Vim.BFast; +using System.Linq; +using Vim.BFastNext; + +namespace Vim.G3dNext +{ + /// + /// A G3d is composed of a header and a collection of attributes containing descriptors and their data. + /// + public class G3DNext where TAttributeCollection : IAttributeCollection, new() + { + /// + /// The meta header of the G3d. Corresponds to the "meta" segment. + /// + public readonly MetaHeader MetaHeader; + + /// + /// The attributes of the G3d. + /// + public readonly TAttributeCollection AttributeCollection; + + /// + /// Constructor. + /// + public G3DNext(MetaHeader metaHeader, TAttributeCollection attributeCollection) + { + MetaHeader = metaHeader; + AttributeCollection = attributeCollection; + } + + public G3DNext(BFastNext.BFastNext bfast) + { + AttributeCollection = new TAttributeCollection(); + AttributeCollection.ReadAttributes(bfast); + MetaHeader = MetaHeader.FromBytes(bfast.GetArray("meta")); + } + + /// + /// Constructor. Uses the default header. + /// + public G3DNext(TAttributeCollection attributeCollection) + : this(MetaHeader.Default, attributeCollection) + { } + + /// + /// Constructor. Uses the default header and instantiates an attribute collection. + /// + public G3DNext() + : this(MetaHeader.Default, new TAttributeCollection()) + { } + + public static G3DNext Empty() where T : IAttributeCollection, new() + => new G3DNext(); + + /// + /// Reads the stream using the attribute collection's readers and outputs a G3d upon success. + /// + + public static G3DNext ReadBFast(BFastNext.BFastNext bfast) + { + var attributeCollection = new TAttributeCollection(); + attributeCollection.ReadAttributes(bfast); + var header = MetaHeader.FromBytes(bfast.GetArray("meta")); + + // Instantiate the object and return. + return new G3DNext(header, attributeCollection); + } + + public static G3DNext ReadBFast(string path) + { + return path.ReadBFast(ReadBFast); + } + + public long GetSize() { + return AttributeCollection.GetSize() + Constants.MetaHeaderSegmentNumBytes; + } + + public BFastNext.BFastNext ToBFast() + { + var attributes = AttributeCollection.Attributes.Values.OrderBy(n => n.Name).ToArray(); // Order the attributes by name for consistency + var bfast = new BFastNext.BFastNext(); + bfast.AddArray(Constants.MetaHeaderSegmentName, MetaHeader.ToBytes()); + foreach (var a in attributes) + { + a.AddTo(bfast); + } + return bfast; + } + + /// + /// Returns a byte array representing the G3d. + /// + public byte[] ToBytes() + { + using (var memoryStream = new MemoryStream()) + { + var b = ToBFast(); + b.Write(memoryStream); + return memoryStream.ToArray(); + } + } + + /// + /// Validates the G3d. + /// + public void Validate() + => AttributeCollection.Validate(); + + } +} diff --git a/src/cs/g3d/Vim.G3dNext/IAttribute.cs b/src/cs/g3d/Vim.G3dNext/IAttribute.cs new file mode 100644 index 00000000..891f88af --- /dev/null +++ b/src/cs/g3d/Vim.G3dNext/IAttribute.cs @@ -0,0 +1,73 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; + +namespace Vim.G3dNext +{ + public interface IAttribute + { + string Name { get; } + IAttributeDescriptor AttributeDescriptor { get; } + AttributeType AttributeType { get; } + Type IndexInto { get; } + Array Data { get; } + void Write(Stream stream); + void AddTo(BFastNext.BFastNext bfast); + void ReadBFast(BFastNext.BFastNext bfast); + } + + public interface IAttribute : IAttribute + { + T[] TypedData { get; set; } + } + + public static class AttributeExtensions + { + public static long GetSizeInBytes(this IAttribute attribute) + => attribute.AttributeDescriptor.DataElementSize * (attribute.Data?.LongLength ?? 0); + + public static TAttr MergeDataAttributes(this IReadOnlyList attributes) where TAttr : IAttribute, new() + { + if (attributes.Count == 0) + return new TAttr(); + + // Check that all attributes have the same descriptor + var first = attributes.First(); + if (!attributes.All(attr => attr.Name.Equals(first.Name))) + throw new Exception($"All attributes must have the same descriptor ({first.Name}) to be merged."); + + var data = attributes.SelectMany(attr => attr.TypedData).ToArray(); + return new TAttr { TypedData = data }; + } + + public static TAttr MergeIndexAttributes( + this IEnumerable<(TAttr Attribute, int IndexedCount)> toMerge) + where TAttr : IAttribute, new() + { + var mergeList = toMerge.ToArray(); + var mergedIndices = new int[mergeList.Sum(t => t.Attribute.TypedData.Length)]; + + var valueOffset = 0; + var mergedCount = 0; + + foreach (var (attr, indexedCount) in toMerge) + { + var typedData = attr.TypedData; + var typedDataCount = typedData.Length; + + for (var i = 0; i < typedDataCount; ++i) + { + mergedIndices[mergedCount + i] = typedData[i] < 0 + ? typedData[i] // if the index is less than 0, then do not increment it (this preserves -1 value assignments) + : typedData[i] + valueOffset; // otherwise, apply the increment. + } + + mergedCount += typedDataCount; + valueOffset += indexedCount; + } + + return new TAttr { TypedData = mergedIndices }; + } + } +} diff --git a/src/cs/g3d/Vim.G3dNext/IAttributeCollection.cs b/src/cs/g3d/Vim.G3dNext/IAttributeCollection.cs new file mode 100644 index 00000000..9e5ac03e --- /dev/null +++ b/src/cs/g3d/Vim.G3dNext/IAttributeCollection.cs @@ -0,0 +1,140 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using Vim.BFast; + +namespace Vim.G3dNext +{ + /// + /// A function which reads an attribute from the given stream and size. + /// + public delegate IAttribute AttributeReader(Stream stream, long sizeInBytes); + public delegate IAttribute AttributeReader2(BFastNext.BFastNext bfast); + + /// + /// A collection of attributes and readers which can be used to deserialize attributes from a stream.
+ ///
+ /// A class may implement this interface to define the specialized set of attributes and attribute readers for + /// a given context.
+ ///
+ /// For example, the geometry and instance information in a VIM file is defined in a class named VimAttributeCollection. + ///
+ public interface IAttributeCollection + { + long GetSize(); + + /// + /// Returns the set of attribute names supported by the AttributeCollection. + /// + IEnumerable AttributeNames { get; } + + /// + /// A mapping from attribute name to its corresponding attribute.
+ /// This is populated when reading attributes from a stream. + ///
+ IDictionary Attributes { get; } + + /// + /// Validates the attribute collection. May throw an exception if the collection is invalid. + /// + void Validate(); + + /// + /// Returns the attribute corresponding to the given type. + /// + IAttribute GetAttribute(Type attributeType); + + /// + /// Merges the attribute with the given name with any other matching attributes in the other collections. + /// + IAttribute MergeAttribute(string attributeName, IReadOnlyList otherCollections); + } + + /// + /// Extension functions and helpers for attribute collections + /// + public static class AttributeCollectionExtensions + { + public static void ReadAttributes(this IAttributeCollection attributeCollection, BFastNext.BFastNext bfast) + { + foreach (var attribute in attributeCollection.Attributes.Values) + { + attribute.ReadBFast(bfast); + } + } + + public static IEnumerable GetAttributesOfType( + this IReadOnlyList collections) + where TAttr : IAttribute + => collections + .Select(c => c.Attributes.Values.OfType().FirstOrDefault()) + .Where(a => a != null); + + public static IEnumerable<(TAttr Attribute, int IndexedCount)> GetIndexedAttributesOfType( + this IReadOnlyList collections) + where TAttr : IAttribute + => collections + .Select(c => + { + var attr = c.Attributes.Values.OfType().FirstOrDefault(); + if (attr == null || attr.IndexInto == null) + return (attr, 0); + + var indexedAttr = c.GetAttribute(attr.IndexInto); + return (attr, indexedAttr.Data.Length); + }) + .Where(t => t.attr != null); + + public static T Merge(this IReadOnlyList collections) + where T: IAttributeCollection, new() + { + if (collections == null) + return new T(); + + if (collections.Count == 1) + return collections[0]; + + // More than one collection; the first collection dictates the attributes to merge. + var @base = collections.First(); + + var others = new List(); + for (var i = 1; i < collections.Count; ++i) + { + others.Add(collections[i]); + } + + var result = new T(); + + foreach (var item in @base.Attributes) + { + var name = item.Key; + + var merged = @base.MergeAttribute(name, others); + + result.Attributes[name] = merged; + } + + return result; + } + + /// + /// Merges the given list of G3ds.
+ /// - If there is no g3d, returns a new empty g3d.
+ /// - If there is only one g3d, returns that g3d. + ///
+ public static G3DNext Merge(this IReadOnlyList> g3ds) + where T : IAttributeCollection, new() + { + switch (g3ds.Count) + { + case 0: + return new G3DNext(); + case 1: + return g3ds.First(); + default: + return new G3DNext(g3ds.Select(g => g.AttributeCollection).ToArray().Merge()); + } + } + } +} diff --git a/src/cs/g3d/Vim.G3dNext/IAttributeDescriptor.cs b/src/cs/g3d/Vim.G3dNext/IAttributeDescriptor.cs new file mode 100644 index 00000000..cd72c3fb --- /dev/null +++ b/src/cs/g3d/Vim.G3dNext/IAttributeDescriptor.cs @@ -0,0 +1,88 @@ +namespace Vim.G3dNext +{ + public interface IAttributeDescriptor + { + /// + /// The string representation of the IAttributeDescriptor. + /// + /// ex: "g3d:instance:transform:0:float32:16" + /// ~~~ + /// | + /// "g3d" is the standard prefix. + /// + /// + string Name { get; } + + /// + /// The second token in the AttributeDescriptor; designates the object to + /// which the attribute is conceptually associated + /// + /// ex: "g3d:instance:transform:0:float32:16" + /// ~~~~~~~~ + /// + /// + string Association { get; } + + /// + /// The third token in the AttributeDescriptor; designates the semantic meaning of the data. + /// + /// ex: "g3d:instance:transform:0:float32:16" + /// ~~~~~~~~~ + /// + /// + string Semantic { get; } + + /// + /// The fourth token in the AttributeDescriptor; designates the index in case + /// the same Association:Semantic combination occurs more than once among the collection of attribute descriptors. + /// + /// ex: "g3d:instance:transform:0:float32:16" + /// ^ + /// + /// + int Index { get; } + + /// + /// The fifth token in the AttributeDescriptor; designates the data type which composes the buffer. + /// + /// ex: "g3d:instance:transform:0:float32:16" + /// ~~~~~~~ + /// | + /// a transformation matrix is composed of float32 values + /// + /// + DataType DataType { get; } + + /// + /// The sixth token in the AttributeDescriptor; designates arity, or the number of values which compose + /// one semantic element. + /// + /// ex: "g3d:instance:transform:0:float32:16" + /// ~~ + /// | + /// one transformation matrix is composed of 16 values + /// + /// + int DataArity { get; } + + /// + /// The current collection of errors defined as bitwise flags + /// + AttributeDescriptorErrors Errors { get; } + + /// + /// Returns true if the Errors is not AttributeDescriptorErrors.None. + /// + bool HasErrors { get; } + + /// + /// The size in bytes of the DataType. + /// + int DataTypeSize { get; } + + /// + /// The size in bytes of one semantic element (DataTypeSize * DataArity) + /// + int DataElementSize { get; } + } +} diff --git a/src/cs/g3d/Vim.G3dNext/MetaHeader.cs b/src/cs/g3d/Vim.G3dNext/MetaHeader.cs new file mode 100644 index 00000000..2a40dd24 --- /dev/null +++ b/src/cs/g3d/Vim.G3dNext/MetaHeader.cs @@ -0,0 +1,89 @@ +using System; +using System.IO; +using System.Text; +using Vim.BFast; + +namespace Vim.G3dNext +{ + // http://docs.autodesk.com/FBX/2014/ENU/FBX-SDK-Documentation/index.html?url=files/GUID-CC93340E-C4A1-49EE-B048-E898F856CFBF.htm,topicNumber=d30e8478 + // https://twitter.com/FreyaHolmer/status/644881436982575104 + // https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#coordinate-system-and-units + + public struct MetaHeader + { + public byte MagicA; // 0x63 + public byte MagicB; // 0xD0 + public byte UnitA; // with unitB could be: 'ft', 'yd', 'mi', 'km', 'mm', 'in', 'cm', 'm', + public byte UnitB; + public byte UpAxis; // e.g. 1=y or 2=z (could be 0=x, if you hate people) + public byte ForwardVector; // e.g. 0=x, 1=y, 2=z, 3=-x, 4=-y, 5=-z + public byte Handedness; // 0=left-handed, 1=right-handed + public byte Padding; // 0 + + + + public string Unit => Encoding.ASCII.GetString(new byte[] { UnitA, UnitB }); + + public byte[] ToBytes() + => new[] { MagicA, MagicB, UnitA, UnitB, UpAxis, ForwardVector, Handedness, Padding }; + + public NamedBuffer ToNamedBuffer() + => ToBytes().ToNamedBuffer(Constants.MetaHeaderSegmentName); + + public static MetaHeader FromBytes(byte[] bytes) + => new MetaHeader + { + MagicA = bytes[0], + MagicB = bytes[1], + UnitA = bytes[2], + UnitB = bytes[3], + UpAxis = bytes[4], + ForwardVector = bytes[5], + Handedness = bytes[6], + } + .Validate(); + + public static MetaHeader Default + = new MetaHeader + { + MagicA = Constants.MetaHeaderMagicA, + MagicB = Constants.MetaHeaderMagicB, + UnitA = (byte)'m', + UnitB = 0, + UpAxis = 2, + ForwardVector = 0, + Handedness = 0, + Padding = 0 + }; + + public MetaHeader Validate() + { + if (MagicA != Constants.MetaHeaderMagicA) throw new Exception($"First magic number must be 0x{Constants.MetaHeaderMagicA:X2} not 0x{MagicA:X2}"); + if (MagicB != Constants.MetaHeaderMagicB) throw new Exception($"Second magic number must be 0x{Constants.MetaHeaderMagicB:X2} not 0x{MagicB:X2}"); + if (Array.IndexOf(Constants.MetaHeaderSupportedUnits, Unit) < 0) throw new Exception($"Unit {Unit} is not a supported unit: {string.Join(", ", Constants.MetaHeaderSupportedUnits)}"); + if (UpAxis < 0 || UpAxis > 2) throw new Exception("Up axis must be 0(x), 1(y), or 2(z)"); + if (ForwardVector < 0 || ForwardVector > 5) throw new Exception("Front vector must be 0 (x), 1(y), 2(z), 3(-x), 4(-y), or 5(-z)"); + if (Handedness < 0 || Handedness > 1) throw new Exception("Handedness must be 0 (left) or 1 (right"); + return this; + } + + public static bool IsSegmentMetaHeader(string name, long size) + => name == Constants.MetaHeaderSegmentName && size == Constants.MetaHeaderSegmentNumBytes; + + public static bool TryRead(Stream stream, long size, out MetaHeader outMetaHeader) + { + var buffer = stream.ReadArray((int)size); + + if (buffer[0] == Constants.MetaHeaderMagicA && buffer[1] == Constants.MetaHeaderMagicB) + { + outMetaHeader = FromBytes(buffer); + return true; + } + else + { + outMetaHeader = default; + return false; + } + } + } +} diff --git a/src/cs/g3d/Vim.G3dNext/Vim.G3dNext.csproj b/src/cs/g3d/Vim.G3dNext/Vim.G3dNext.csproj new file mode 100644 index 00000000..36394089 --- /dev/null +++ b/src/cs/g3d/Vim.G3dNext/Vim.G3dNext.csproj @@ -0,0 +1,16 @@ + + + netstandard2.0 + + + + + + + + + + + + + diff --git a/src/cs/g3d/temp/Vim.G3dNext.Attributes/Attributes.cs b/src/cs/g3d/temp/Vim.G3dNext.Attributes/Attributes.cs new file mode 100644 index 00000000..df17687e --- /dev/null +++ b/src/cs/g3d/temp/Vim.G3dNext.Attributes/Attributes.cs @@ -0,0 +1,178 @@ +using Vim.Math3d; + +namespace Vim.G3dNext.Attributes +{ + #region vim + [AttributeDescriptor("g3d:all:facesize:0:int32:1", AttributeType.Singleton)] + public partial class CornersPerFaceAttribute { } + + [AttributeDescriptor("g3d:vertex:position:0:float32:3", AttributeType.Data, ArrayType = typeof(Vector3))] + public partial class VertexAttribute { } + + [AttributeDescriptor("g3d:corner:index:0:int32:1", AttributeType.Index, IndexInto = typeof(VertexAttribute))] + public partial class IndexAttribute { } + + [AttributeDescriptor("g3d:instance:transform:0:float32:16", AttributeType.Data, ArrayType = typeof(Matrix4x4))] + public partial class InstanceTransformAttribute { } + + [AttributeDescriptor("g3d:instance:parent:0:int32:1", AttributeType.Index, IndexInto = typeof(InstanceTransformAttribute))] + public partial class InstanceParentAttribute { } + + [AttributeDescriptor("g3d:instance:flags:0:uint16:1", AttributeType.Data)] + public partial class InstanceFlagsAttribute { } + + [AttributeDescriptor("g3d:instance:mesh:0:int32:1", AttributeType.Index, IndexInto = typeof(MeshSubmeshOffsetAttribute))] + public partial class InstanceMeshAttribute { } + + [AttributeDescriptor("g3d:mesh:submeshoffset:0:int32:1", AttributeType.Index, IndexInto = typeof(SubmeshIndexOffsetAttribute))] + public partial class MeshSubmeshOffsetAttribute { } + + [AttributeDescriptor("g3d:submesh:indexoffset:0:int32:1", AttributeType.Index, IndexInto = typeof(IndexAttribute))] + public partial class SubmeshIndexOffsetAttribute { } + + [AttributeDescriptor("g3d:submesh:material:0:int32:1", AttributeType.Index, IndexInto = typeof(MaterialColorAttribute))] + public partial class SubmeshMaterialAttribute { } + + + + [AttributeDescriptor("g3d:shapevertex:position:0:float32:3", AttributeType.Data, ArrayType = typeof(Vector3))] + public partial class ShapeVertexAttribute { } + + [AttributeDescriptor("g3d:shape:vertexoffset:0:int32:1", AttributeType.Index, IndexInto = typeof(ShapeVertexAttribute))] + public partial class ShapeVertexOffsetAttribute { } + + [AttributeDescriptor("g3d:shape:color:0:float32:4", AttributeType.Data, ArrayType = typeof(Vector4))] + public partial class ShapeColorAttribute { } + + [AttributeDescriptor("g3d:shape:width:0:float32:1", AttributeType.Data)] + public partial class ShapeWidthAttribute { } + + [AttributeCollection( + typeof(CornersPerFaceAttribute), + typeof(VertexAttribute), + typeof(IndexAttribute), + typeof(InstanceTransformAttribute), + typeof(InstanceParentAttribute), + typeof(InstanceFlagsAttribute), + typeof(InstanceMeshAttribute), + typeof(MeshSubmeshOffsetAttribute), + typeof(SubmeshIndexOffsetAttribute), + typeof(SubmeshMaterialAttribute), + typeof(MaterialColorAttribute), + typeof(MaterialGlossinessAttribute), + typeof(MaterialSmoothnessAttribute), + typeof(ShapeVertexAttribute), + typeof(ShapeVertexOffsetAttribute), + typeof(ShapeColorAttribute), + typeof(ShapeWidthAttribute))] + public partial class VimAttributeCollection // : IAttributeCollection + { + + } + + #endregion + + #region mesh + + [AttributeDescriptor("g3d:submesh:vertexoffset:0:int32:1", AttributeType.Index, IndexInto = typeof(IndexAttribute))] + public partial class SubmeshVertexOffsetAttribute { } + + [AttributeDescriptor("g3d:mesh:opaquesubmeshcount:0:int32:1", AttributeType.Data)] + public partial class MeshOpaqueSubmeshCountAttribute { } + + [AttributeCollection( + typeof(InstanceTransformAttribute), + typeof(MeshOpaqueSubmeshCountAttribute), + typeof(SubmeshIndexOffsetAttribute), + typeof(SubmeshVertexOffsetAttribute), + typeof(SubmeshMaterialAttribute), + typeof(VertexAttribute), + typeof(IndexAttribute) + )] + public partial class MeshAttributeCollection // : IAttributeCollection + { + + } + #endregion + + #region scene + [AttributeDescriptor("g3d:instance:file:0:int32:1", AttributeType.Data)] + public partial class InstanceFileAttribute { } + + [AttributeDescriptor("g3d:instance:node:0:int32:1", AttributeType.Data)] + public partial class InstanceNodeAttribute { } + + + [AttributeDescriptor("g3d:instance:index:0:int32:1", AttributeType.Data)] + public partial class InstanceIndexAttribute { } + + [AttributeDescriptor("g3d:instance:group:0:int32:1", AttributeType.Data)] + public partial class InstanceGroupAttribute { } + + [AttributeDescriptor("g3d:instance:tag:0:int64:1", AttributeType.Data)] + public partial class InstanceTagAttribute { } + + [AttributeDescriptor("g3d:instance:min:0:float32:3", AttributeType.Data, ArrayType = typeof(Vector3))] + public partial class InstanceMinAttribute { } + + [AttributeDescriptor("g3d:instance:max:0:float32:3", AttributeType.Data, ArrayType = typeof(Vector3))] + public partial class InstanceMaxAttribute { } + + [AttributeDescriptor("g3d:mesh:instancecount:0:int32:1", AttributeType.Data)] + public partial class MeshInstanceCountAttribute { } + + [AttributeDescriptor("g3d:mesh:vertexcount:0:int32:1", AttributeType.Data)] + public partial class MeshVertexCountAttribute { } + + [AttributeDescriptor("g3d:mesh:indexcount:0:int32:1", AttributeType.Data)] + public partial class MeshIndexCountAttribute { } + + [AttributeDescriptor("g3d:mesh:opaquevertexcount:0:int32:1", AttributeType.Data)] + public partial class MeshOpaqueVertexCountAttribute { } + + [AttributeDescriptor("g3d:mesh:opaqueindexcount:0:int32:1", AttributeType.Data)] + public partial class MeshOpaqueIndexCountAttribute { } + + [AttributeCollection( + typeof(InstanceFileAttribute), + typeof(InstanceIndexAttribute), + typeof(InstanceNodeAttribute), + typeof(InstanceGroupAttribute), + typeof(InstanceTagAttribute), + typeof(InstanceFlagsAttribute), + typeof(InstanceMinAttribute), + typeof(InstanceMaxAttribute), + typeof(MeshInstanceCountAttribute), + typeof(MeshIndexCountAttribute), + typeof(MeshVertexCountAttribute), + typeof(MeshOpaqueIndexCountAttribute), + typeof(MeshOpaqueVertexCountAttribute) + )] + public partial class SceneAttributeCollection // : IAttributeCollection + { + + } + #endregion + + #region materials + // Material + [AttributeDescriptor("g3d:material:color:0:float32:4", AttributeType.Data, ArrayType = typeof(Vector4))] + public partial class MaterialColorAttribute { } + + [AttributeDescriptor("g3d:material:glossiness:0:float32:1", AttributeType.Data)] + public partial class MaterialGlossinessAttribute { } + + [AttributeDescriptor("g3d:material:smoothness:0:float32:1", AttributeType.Data)] + public partial class MaterialSmoothnessAttribute { } + + [AttributeCollection( + typeof(MaterialColorAttribute), + typeof(MaterialGlossinessAttribute), + typeof(MaterialSmoothnessAttribute) + )] + public partial class MaterialAttributeCollection // : IAttributeCollection + { + + } + #endregion +} diff --git a/src/cs/g3d/temp/Vim.G3dNext.Attributes/Attributes.g.cs b/src/cs/g3d/temp/Vim.G3dNext.Attributes/Attributes.g.cs new file mode 100644 index 00000000..c6fdca00 --- /dev/null +++ b/src/cs/g3d/temp/Vim.G3dNext.Attributes/Attributes.g.cs @@ -0,0 +1,2042 @@ +// AUTO-GENERATED FILE, DO NOT MODIFY. +// ReSharper disable All +using System; +using System.IO; +using System.Collections.Generic; +using System.Linq; +using Vim.BFast; + +namespace Vim.G3dNext.Attributes +{ + + public partial class CornersPerFaceAttribute : IAttribute + { + public const string AttributeName = "g3d:all:facesize:0:int32:1"; + + public string Name + => AttributeName; + + public static AttributeReader CreateAttributeReader() + => AttributeCollectionExtensions.CreateAttributeReader(); + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Singleton; + + public Type IndexInto { get; } + = null; + + public System.Int32[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + + public partial class VertexAttribute : IAttribute + { + public const string AttributeName = "g3d:vertex:position:0:float32:3"; + + public string Name + => AttributeName; + + public static AttributeReader CreateAttributeReader() + => AttributeCollectionExtensions.CreateAttributeReader(); + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Data; + + public Type IndexInto { get; } + = null; + + public Vim.Math3d.Vector3[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + + public partial class IndexAttribute : IAttribute + { + public const string AttributeName = "g3d:corner:index:0:int32:1"; + + public string Name + => AttributeName; + + public static AttributeReader CreateAttributeReader() + => AttributeCollectionExtensions.CreateAttributeReader(); + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Index; + + public Type IndexInto { get; } + = typeof(Vim.G3dNext.Attributes.VertexAttribute); + + public System.Int32[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + + public partial class InstanceTransformAttribute : IAttribute + { + public const string AttributeName = "g3d:instance:transform:0:float32:16"; + + public string Name + => AttributeName; + + public static AttributeReader CreateAttributeReader() + => AttributeCollectionExtensions.CreateAttributeReader(); + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Data; + + public Type IndexInto { get; } + = null; + + public Vim.Math3d.Matrix4x4[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + + public partial class InstanceParentAttribute : IAttribute + { + public const string AttributeName = "g3d:instance:parent:0:int32:1"; + + public string Name + => AttributeName; + + public static AttributeReader CreateAttributeReader() + => AttributeCollectionExtensions.CreateAttributeReader(); + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Index; + + public Type IndexInto { get; } + = typeof(Vim.G3dNext.Attributes.InstanceTransformAttribute); + + public System.Int32[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + + public partial class InstanceFlagsAttribute : IAttribute + { + public const string AttributeName = "g3d:instance:flags:0:uint16:1"; + + public string Name + => AttributeName; + + public static AttributeReader CreateAttributeReader() + => AttributeCollectionExtensions.CreateAttributeReader(); + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Data; + + public Type IndexInto { get; } + = null; + + public System.UInt16[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + + public partial class InstanceMeshAttribute : IAttribute + { + public const string AttributeName = "g3d:instance:mesh:0:int32:1"; + + public string Name + => AttributeName; + + public static AttributeReader CreateAttributeReader() + => AttributeCollectionExtensions.CreateAttributeReader(); + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Index; + + public Type IndexInto { get; } + = typeof(Vim.G3dNext.Attributes.MeshSubmeshOffsetAttribute); + + public System.Int32[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + + public partial class MeshSubmeshOffsetAttribute : IAttribute + { + public const string AttributeName = "g3d:mesh:submeshoffset:0:int32:1"; + + public string Name + => AttributeName; + + public static AttributeReader CreateAttributeReader() + => AttributeCollectionExtensions.CreateAttributeReader(); + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Index; + + public Type IndexInto { get; } + = typeof(Vim.G3dNext.Attributes.SubmeshIndexOffsetAttribute); + + public System.Int32[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + + public partial class SubmeshIndexOffsetAttribute : IAttribute + { + public const string AttributeName = "g3d:submesh:indexoffset:0:int32:1"; + + public string Name + => AttributeName; + + public static AttributeReader CreateAttributeReader() + => AttributeCollectionExtensions.CreateAttributeReader(); + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Index; + + public Type IndexInto { get; } + = typeof(Vim.G3dNext.Attributes.IndexAttribute); + + public System.Int32[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + + public partial class SubmeshMaterialAttribute : IAttribute + { + public const string AttributeName = "g3d:submesh:material:0:int32:1"; + + public string Name + => AttributeName; + + public static AttributeReader CreateAttributeReader() + => AttributeCollectionExtensions.CreateAttributeReader(); + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Index; + + public Type IndexInto { get; } + = typeof(Vim.G3dNext.Attributes.MaterialColorAttribute); + + public System.Int32[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + + public partial class ShapeVertexAttribute : IAttribute + { + public const string AttributeName = "g3d:shapevertex:position:0:float32:3"; + + public string Name + => AttributeName; + + public static AttributeReader CreateAttributeReader() + => AttributeCollectionExtensions.CreateAttributeReader(); + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Data; + + public Type IndexInto { get; } + = null; + + public Vim.Math3d.Vector3[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + + public partial class ShapeVertexOffsetAttribute : IAttribute + { + public const string AttributeName = "g3d:shape:vertexoffset:0:int32:1"; + + public string Name + => AttributeName; + + public static AttributeReader CreateAttributeReader() + => AttributeCollectionExtensions.CreateAttributeReader(); + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Index; + + public Type IndexInto { get; } + = typeof(Vim.G3dNext.Attributes.ShapeVertexAttribute); + + public System.Int32[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + + public partial class ShapeColorAttribute : IAttribute + { + public const string AttributeName = "g3d:shape:color:0:float32:4"; + + public string Name + => AttributeName; + + public static AttributeReader CreateAttributeReader() + => AttributeCollectionExtensions.CreateAttributeReader(); + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Data; + + public Type IndexInto { get; } + = null; + + public Vim.Math3d.Vector4[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + + public partial class ShapeWidthAttribute : IAttribute + { + public const string AttributeName = "g3d:shape:width:0:float32:1"; + + public string Name + => AttributeName; + + public static AttributeReader CreateAttributeReader() + => AttributeCollectionExtensions.CreateAttributeReader(); + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Data; + + public Type IndexInto { get; } + = null; + + public System.Single[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + + public partial class SubmeshVertexOffsetAttribute : IAttribute + { + public const string AttributeName = "g3d:submesh:vertexoffset:0:int32:1"; + + public string Name + => AttributeName; + + public static AttributeReader CreateAttributeReader() + => AttributeCollectionExtensions.CreateAttributeReader(); + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Index; + + public Type IndexInto { get; } + = typeof(Vim.G3dNext.Attributes.IndexAttribute); + + public System.Int32[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + + public partial class MeshOpaqueSubmeshCountAttribute : IAttribute + { + public const string AttributeName = "g3d:mesh:opaquesubmeshcount:0:int32:1"; + + public string Name + => AttributeName; + + public static AttributeReader CreateAttributeReader() + => AttributeCollectionExtensions.CreateAttributeReader(); + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Data; + + public Type IndexInto { get; } + = null; + + public System.Int32[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + + public partial class InstanceFileAttribute : IAttribute + { + public const string AttributeName = "g3d:instance:file:0:int32:1"; + + public string Name + => AttributeName; + + public static AttributeReader CreateAttributeReader() + => AttributeCollectionExtensions.CreateAttributeReader(); + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Data; + + public Type IndexInto { get; } + = null; + + public System.Int32[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + + public partial class InstanceNodeAttribute : IAttribute + { + public const string AttributeName = "g3d:instance:node:0:int32:1"; + + public string Name + => AttributeName; + + public static AttributeReader CreateAttributeReader() + => AttributeCollectionExtensions.CreateAttributeReader(); + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Data; + + public Type IndexInto { get; } + = null; + + public System.Int32[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + + public partial class InstanceIndexAttribute : IAttribute + { + public const string AttributeName = "g3d:instance:index:0:int32:1"; + + public string Name + => AttributeName; + + public static AttributeReader CreateAttributeReader() + => AttributeCollectionExtensions.CreateAttributeReader(); + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Data; + + public Type IndexInto { get; } + = null; + + public System.Int32[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + + public partial class InstanceGroupAttribute : IAttribute + { + public const string AttributeName = "g3d:instance:group:0:int32:1"; + + public string Name + => AttributeName; + + public static AttributeReader CreateAttributeReader() + => AttributeCollectionExtensions.CreateAttributeReader(); + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Data; + + public Type IndexInto { get; } + = null; + + public System.Int32[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + + public partial class InstanceTagAttribute : IAttribute + { + public const string AttributeName = "g3d:instance:tag:0:int64:1"; + + public string Name + => AttributeName; + + public static AttributeReader CreateAttributeReader() + => AttributeCollectionExtensions.CreateAttributeReader(); + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Data; + + public Type IndexInto { get; } + = null; + + public System.Int64[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + + public partial class InstanceMinAttribute : IAttribute + { + public const string AttributeName = "g3d:instance:min:0:float32:3"; + + public string Name + => AttributeName; + + public static AttributeReader CreateAttributeReader() + => AttributeCollectionExtensions.CreateAttributeReader(); + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Data; + + public Type IndexInto { get; } + = null; + + public Vim.Math3d.Vector3[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + + public partial class InstanceMaxAttribute : IAttribute + { + public const string AttributeName = "g3d:instance:max:0:float32:3"; + + public string Name + => AttributeName; + + public static AttributeReader CreateAttributeReader() + => AttributeCollectionExtensions.CreateAttributeReader(); + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Data; + + public Type IndexInto { get; } + = null; + + public Vim.Math3d.Vector3[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + + public partial class MeshInstanceCountAttribute : IAttribute + { + public const string AttributeName = "g3d:mesh:instancecount:0:int32:1"; + + public string Name + => AttributeName; + + public static AttributeReader CreateAttributeReader() + => AttributeCollectionExtensions.CreateAttributeReader(); + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Data; + + public Type IndexInto { get; } + = null; + + public System.Int32[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + + public partial class MeshVertexCountAttribute : IAttribute + { + public const string AttributeName = "g3d:mesh:vertexcount:0:int32:1"; + + public string Name + => AttributeName; + + public static AttributeReader CreateAttributeReader() + => AttributeCollectionExtensions.CreateAttributeReader(); + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Data; + + public Type IndexInto { get; } + = null; + + public System.Int32[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + + public partial class MeshIndexCountAttribute : IAttribute + { + public const string AttributeName = "g3d:mesh:indexcount:0:int32:1"; + + public string Name + => AttributeName; + + public static AttributeReader CreateAttributeReader() + => AttributeCollectionExtensions.CreateAttributeReader(); + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Data; + + public Type IndexInto { get; } + = null; + + public System.Int32[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + + public partial class MeshOpaqueVertexCountAttribute : IAttribute + { + public const string AttributeName = "g3d:mesh:opaquevertexcount:0:int32:1"; + + public string Name + => AttributeName; + + public static AttributeReader CreateAttributeReader() + => AttributeCollectionExtensions.CreateAttributeReader(); + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Data; + + public Type IndexInto { get; } + = null; + + public System.Int32[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + + public partial class MeshOpaqueIndexCountAttribute : IAttribute + { + public const string AttributeName = "g3d:mesh:opaqueindexcount:0:int32:1"; + + public string Name + => AttributeName; + + public static AttributeReader CreateAttributeReader() + => AttributeCollectionExtensions.CreateAttributeReader(); + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Data; + + public Type IndexInto { get; } + = null; + + public System.Int32[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + + public partial class MaterialColorAttribute : IAttribute + { + public const string AttributeName = "g3d:material:color:0:float32:4"; + + public string Name + => AttributeName; + + public static AttributeReader CreateAttributeReader() + => AttributeCollectionExtensions.CreateAttributeReader(); + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Data; + + public Type IndexInto { get; } + = null; + + public Vim.Math3d.Vector4[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + + public partial class MaterialGlossinessAttribute : IAttribute + { + public const string AttributeName = "g3d:material:glossiness:0:float32:1"; + + public string Name + => AttributeName; + + public static AttributeReader CreateAttributeReader() + => AttributeCollectionExtensions.CreateAttributeReader(); + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Data; + + public Type IndexInto { get; } + = null; + + public System.Single[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + + public partial class MaterialSmoothnessAttribute : IAttribute + { + public const string AttributeName = "g3d:material:smoothness:0:float32:1"; + + public string Name + => AttributeName; + + public static AttributeReader CreateAttributeReader() + => AttributeCollectionExtensions.CreateAttributeReader(); + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Data; + + public Type IndexInto { get; } + = null; + + public System.Single[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + public partial class VimAttributeCollection : IAttributeCollection + { + public IEnumerable AttributeNames + => Attributes.Keys; + + public long GetSize() + => Attributes.Values.Sum(a => a.Data.LongLength * a.AttributeDescriptor.DataElementSize); + + public IDictionary Attributes { get; } + = new Dictionary + { + [Vim.G3dNext.Attributes.CornersPerFaceAttribute.AttributeName] = new Vim.G3dNext.Attributes.CornersPerFaceAttribute(), + [Vim.G3dNext.Attributes.VertexAttribute.AttributeName] = new Vim.G3dNext.Attributes.VertexAttribute(), + [Vim.G3dNext.Attributes.IndexAttribute.AttributeName] = new Vim.G3dNext.Attributes.IndexAttribute(), + [Vim.G3dNext.Attributes.InstanceTransformAttribute.AttributeName] = new Vim.G3dNext.Attributes.InstanceTransformAttribute(), + [Vim.G3dNext.Attributes.InstanceParentAttribute.AttributeName] = new Vim.G3dNext.Attributes.InstanceParentAttribute(), + [Vim.G3dNext.Attributes.InstanceFlagsAttribute.AttributeName] = new Vim.G3dNext.Attributes.InstanceFlagsAttribute(), + [Vim.G3dNext.Attributes.InstanceMeshAttribute.AttributeName] = new Vim.G3dNext.Attributes.InstanceMeshAttribute(), + [Vim.G3dNext.Attributes.MeshSubmeshOffsetAttribute.AttributeName] = new Vim.G3dNext.Attributes.MeshSubmeshOffsetAttribute(), + [Vim.G3dNext.Attributes.SubmeshIndexOffsetAttribute.AttributeName] = new Vim.G3dNext.Attributes.SubmeshIndexOffsetAttribute(), + [Vim.G3dNext.Attributes.SubmeshMaterialAttribute.AttributeName] = new Vim.G3dNext.Attributes.SubmeshMaterialAttribute(), + [Vim.G3dNext.Attributes.MaterialColorAttribute.AttributeName] = new Vim.G3dNext.Attributes.MaterialColorAttribute(), + [Vim.G3dNext.Attributes.MaterialGlossinessAttribute.AttributeName] = new Vim.G3dNext.Attributes.MaterialGlossinessAttribute(), + [Vim.G3dNext.Attributes.MaterialSmoothnessAttribute.AttributeName] = new Vim.G3dNext.Attributes.MaterialSmoothnessAttribute(), + [Vim.G3dNext.Attributes.ShapeVertexAttribute.AttributeName] = new Vim.G3dNext.Attributes.ShapeVertexAttribute(), + [Vim.G3dNext.Attributes.ShapeVertexOffsetAttribute.AttributeName] = new Vim.G3dNext.Attributes.ShapeVertexOffsetAttribute(), + [Vim.G3dNext.Attributes.ShapeColorAttribute.AttributeName] = new Vim.G3dNext.Attributes.ShapeColorAttribute(), + [Vim.G3dNext.Attributes.ShapeWidthAttribute.AttributeName] = new Vim.G3dNext.Attributes.ShapeWidthAttribute(), + }; + + public IDictionary AttributeReaders { get; } + = new Dictionary + { + [Vim.G3dNext.Attributes.CornersPerFaceAttribute.AttributeName] = Vim.G3dNext.Attributes.CornersPerFaceAttribute.CreateAttributeReader(), + [Vim.G3dNext.Attributes.VertexAttribute.AttributeName] = Vim.G3dNext.Attributes.VertexAttribute.CreateAttributeReader(), + [Vim.G3dNext.Attributes.IndexAttribute.AttributeName] = Vim.G3dNext.Attributes.IndexAttribute.CreateAttributeReader(), + [Vim.G3dNext.Attributes.InstanceTransformAttribute.AttributeName] = Vim.G3dNext.Attributes.InstanceTransformAttribute.CreateAttributeReader(), + [Vim.G3dNext.Attributes.InstanceParentAttribute.AttributeName] = Vim.G3dNext.Attributes.InstanceParentAttribute.CreateAttributeReader(), + [Vim.G3dNext.Attributes.InstanceFlagsAttribute.AttributeName] = Vim.G3dNext.Attributes.InstanceFlagsAttribute.CreateAttributeReader(), + [Vim.G3dNext.Attributes.InstanceMeshAttribute.AttributeName] = Vim.G3dNext.Attributes.InstanceMeshAttribute.CreateAttributeReader(), + [Vim.G3dNext.Attributes.MeshSubmeshOffsetAttribute.AttributeName] = Vim.G3dNext.Attributes.MeshSubmeshOffsetAttribute.CreateAttributeReader(), + [Vim.G3dNext.Attributes.SubmeshIndexOffsetAttribute.AttributeName] = Vim.G3dNext.Attributes.SubmeshIndexOffsetAttribute.CreateAttributeReader(), + [Vim.G3dNext.Attributes.SubmeshMaterialAttribute.AttributeName] = Vim.G3dNext.Attributes.SubmeshMaterialAttribute.CreateAttributeReader(), + [Vim.G3dNext.Attributes.MaterialColorAttribute.AttributeName] = Vim.G3dNext.Attributes.MaterialColorAttribute.CreateAttributeReader(), + [Vim.G3dNext.Attributes.MaterialGlossinessAttribute.AttributeName] = Vim.G3dNext.Attributes.MaterialGlossinessAttribute.CreateAttributeReader(), + [Vim.G3dNext.Attributes.MaterialSmoothnessAttribute.AttributeName] = Vim.G3dNext.Attributes.MaterialSmoothnessAttribute.CreateAttributeReader(), + [Vim.G3dNext.Attributes.ShapeVertexAttribute.AttributeName] = Vim.G3dNext.Attributes.ShapeVertexAttribute.CreateAttributeReader(), + [Vim.G3dNext.Attributes.ShapeVertexOffsetAttribute.AttributeName] = Vim.G3dNext.Attributes.ShapeVertexOffsetAttribute.CreateAttributeReader(), + [Vim.G3dNext.Attributes.ShapeColorAttribute.AttributeName] = Vim.G3dNext.Attributes.ShapeColorAttribute.CreateAttributeReader(), + [Vim.G3dNext.Attributes.ShapeWidthAttribute.AttributeName] = Vim.G3dNext.Attributes.ShapeWidthAttribute.CreateAttributeReader(), + }; + + // Named Attributes. + + public Vim.G3dNext.Attributes.CornersPerFaceAttribute CornersPerFaceAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.CornersPerFaceAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.CornersPerFaceAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.CornersPerFaceAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.VertexAttribute VertexAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.VertexAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.VertexAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.VertexAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.IndexAttribute IndexAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.IndexAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.IndexAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.IndexAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.InstanceTransformAttribute InstanceTransformAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.InstanceTransformAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceTransformAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.InstanceTransformAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.InstanceParentAttribute InstanceParentAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.InstanceParentAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceParentAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.InstanceParentAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.InstanceFlagsAttribute InstanceFlagsAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.InstanceFlagsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceFlagsAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.InstanceFlagsAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.InstanceMeshAttribute InstanceMeshAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.InstanceMeshAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceMeshAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.InstanceMeshAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.MeshSubmeshOffsetAttribute MeshSubmeshOffsetAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.MeshSubmeshOffsetAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshSubmeshOffsetAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.MeshSubmeshOffsetAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.SubmeshIndexOffsetAttribute SubmeshIndexOffsetAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.SubmeshIndexOffsetAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.SubmeshIndexOffsetAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.SubmeshIndexOffsetAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.SubmeshMaterialAttribute SubmeshMaterialAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.SubmeshMaterialAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.SubmeshMaterialAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.SubmeshMaterialAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.MaterialColorAttribute MaterialColorAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.MaterialColorAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MaterialColorAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.MaterialColorAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.MaterialGlossinessAttribute MaterialGlossinessAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.MaterialGlossinessAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MaterialGlossinessAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.MaterialGlossinessAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.MaterialSmoothnessAttribute MaterialSmoothnessAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.MaterialSmoothnessAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MaterialSmoothnessAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.MaterialSmoothnessAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.ShapeVertexAttribute ShapeVertexAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.ShapeVertexAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.ShapeVertexAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.ShapeVertexAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.ShapeVertexOffsetAttribute ShapeVertexOffsetAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.ShapeVertexOffsetAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.ShapeVertexOffsetAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.ShapeVertexOffsetAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.ShapeColorAttribute ShapeColorAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.ShapeColorAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.ShapeColorAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.ShapeColorAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.ShapeWidthAttribute ShapeWidthAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.ShapeWidthAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.ShapeWidthAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.ShapeWidthAttribute.AttributeName] = value as IAttribute; + } + + /// + public IAttribute GetAttribute(Type attributeType) + { + + if (attributeType == typeof(Vim.G3dNext.Attributes.CornersPerFaceAttribute)) + return CornersPerFaceAttribute; + + if (attributeType == typeof(Vim.G3dNext.Attributes.VertexAttribute)) + return VertexAttribute; + + if (attributeType == typeof(Vim.G3dNext.Attributes.IndexAttribute)) + return IndexAttribute; + + if (attributeType == typeof(Vim.G3dNext.Attributes.InstanceTransformAttribute)) + return InstanceTransformAttribute; + + if (attributeType == typeof(Vim.G3dNext.Attributes.InstanceParentAttribute)) + return InstanceParentAttribute; + + if (attributeType == typeof(Vim.G3dNext.Attributes.InstanceFlagsAttribute)) + return InstanceFlagsAttribute; + + if (attributeType == typeof(Vim.G3dNext.Attributes.InstanceMeshAttribute)) + return InstanceMeshAttribute; + + if (attributeType == typeof(Vim.G3dNext.Attributes.MeshSubmeshOffsetAttribute)) + return MeshSubmeshOffsetAttribute; + + if (attributeType == typeof(Vim.G3dNext.Attributes.SubmeshIndexOffsetAttribute)) + return SubmeshIndexOffsetAttribute; + + if (attributeType == typeof(Vim.G3dNext.Attributes.SubmeshMaterialAttribute)) + return SubmeshMaterialAttribute; + + if (attributeType == typeof(Vim.G3dNext.Attributes.MaterialColorAttribute)) + return MaterialColorAttribute; + + if (attributeType == typeof(Vim.G3dNext.Attributes.MaterialGlossinessAttribute)) + return MaterialGlossinessAttribute; + + if (attributeType == typeof(Vim.G3dNext.Attributes.MaterialSmoothnessAttribute)) + return MaterialSmoothnessAttribute; + + if (attributeType == typeof(Vim.G3dNext.Attributes.ShapeVertexAttribute)) + return ShapeVertexAttribute; + + if (attributeType == typeof(Vim.G3dNext.Attributes.ShapeVertexOffsetAttribute)) + return ShapeVertexOffsetAttribute; + + if (attributeType == typeof(Vim.G3dNext.Attributes.ShapeColorAttribute)) + return ShapeColorAttribute; + + if (attributeType == typeof(Vim.G3dNext.Attributes.ShapeWidthAttribute)) + return ShapeWidthAttribute; + + throw new ArgumentException("Type {attributeType.ToString()} is not supported."); + } + + public IAttribute MergeAttribute(string attributeName, IReadOnlyList otherCollections) + { + var collections = otherCollections.Prepend(this).ToArray(); + switch (attributeName) + { + + case Vim.G3dNext.Attributes.CornersPerFaceAttribute.AttributeName: + { + // Singleton Attribute (no merging) + return CornersPerFaceAttribute; + } + + case Vim.G3dNext.Attributes.VertexAttribute.AttributeName: + { + // Data Attribute + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + } + + case Vim.G3dNext.Attributes.IndexAttribute.AttributeName: + { + // Index Attribute + return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); + } + + case Vim.G3dNext.Attributes.InstanceTransformAttribute.AttributeName: + { + // Data Attribute + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + } + + case Vim.G3dNext.Attributes.InstanceParentAttribute.AttributeName: + { + // Index Attribute + return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); + } + + case Vim.G3dNext.Attributes.InstanceFlagsAttribute.AttributeName: + { + // Data Attribute + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + } + + case Vim.G3dNext.Attributes.InstanceMeshAttribute.AttributeName: + { + // Index Attribute + return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); + } + + case Vim.G3dNext.Attributes.MeshSubmeshOffsetAttribute.AttributeName: + { + // Index Attribute + return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); + } + + case Vim.G3dNext.Attributes.SubmeshIndexOffsetAttribute.AttributeName: + { + // Index Attribute + return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); + } + + case Vim.G3dNext.Attributes.SubmeshMaterialAttribute.AttributeName: + { + // Index Attribute + return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); + } + + case Vim.G3dNext.Attributes.MaterialColorAttribute.AttributeName: + { + // Data Attribute + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + } + + case Vim.G3dNext.Attributes.MaterialGlossinessAttribute.AttributeName: + { + // Data Attribute + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + } + + case Vim.G3dNext.Attributes.MaterialSmoothnessAttribute.AttributeName: + { + // Data Attribute + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + } + + case Vim.G3dNext.Attributes.ShapeVertexAttribute.AttributeName: + { + // Data Attribute + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + } + + case Vim.G3dNext.Attributes.ShapeVertexOffsetAttribute.AttributeName: + { + // Index Attribute + return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); + } + + case Vim.G3dNext.Attributes.ShapeColorAttribute.AttributeName: + { + // Data Attribute + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + } + + case Vim.G3dNext.Attributes.ShapeWidthAttribute.AttributeName: + { + // Data Attribute + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + } + + default: + throw new ArgumentException(nameof(attributeName)); + } + } + + public void Validate() + { + // Ensure all the indices are either -1 or within the bounds of the attributes they are indexing into. + + { + var maxIndex = GetAttribute(IndexAttribute.IndexInto).Data.Length - 1; + for (var i = 0; i < IndexAttribute.TypedData.Length; ++i) + { + var index = IndexAttribute.TypedData[i]; + + if (index == -1) + continue; // no relation. + + if (index < -1 || index > maxIndex) + throw new Exception($"Index out of range in Vim.G3dNext.Attributes.IndexAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); + } + } + + { + var maxIndex = GetAttribute(InstanceParentAttribute.IndexInto).Data.Length - 1; + for (var i = 0; i < InstanceParentAttribute.TypedData.Length; ++i) + { + var index = InstanceParentAttribute.TypedData[i]; + + if (index == -1) + continue; // no relation. + + if (index < -1 || index > maxIndex) + throw new Exception($"Index out of range in Vim.G3dNext.Attributes.InstanceParentAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); + } + } + + { + var maxIndex = GetAttribute(InstanceMeshAttribute.IndexInto).Data.Length - 1; + for (var i = 0; i < InstanceMeshAttribute.TypedData.Length; ++i) + { + var index = InstanceMeshAttribute.TypedData[i]; + + if (index == -1) + continue; // no relation. + + if (index < -1 || index > maxIndex) + throw new Exception($"Index out of range in Vim.G3dNext.Attributes.InstanceMeshAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); + } + } + + { + var maxIndex = GetAttribute(MeshSubmeshOffsetAttribute.IndexInto).Data.Length - 1; + for (var i = 0; i < MeshSubmeshOffsetAttribute.TypedData.Length; ++i) + { + var index = MeshSubmeshOffsetAttribute.TypedData[i]; + + if (index == -1) + continue; // no relation. + + if (index < -1 || index > maxIndex) + throw new Exception($"Index out of range in Vim.G3dNext.Attributes.MeshSubmeshOffsetAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); + } + } + + { + var maxIndex = GetAttribute(SubmeshIndexOffsetAttribute.IndexInto).Data.Length - 1; + for (var i = 0; i < SubmeshIndexOffsetAttribute.TypedData.Length; ++i) + { + var index = SubmeshIndexOffsetAttribute.TypedData[i]; + + if (index == -1) + continue; // no relation. + + if (index < -1 || index > maxIndex) + throw new Exception($"Index out of range in Vim.G3dNext.Attributes.SubmeshIndexOffsetAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); + } + } + + { + var maxIndex = GetAttribute(SubmeshMaterialAttribute.IndexInto).Data.Length - 1; + for (var i = 0; i < SubmeshMaterialAttribute.TypedData.Length; ++i) + { + var index = SubmeshMaterialAttribute.TypedData[i]; + + if (index == -1) + continue; // no relation. + + if (index < -1 || index > maxIndex) + throw new Exception($"Index out of range in Vim.G3dNext.Attributes.SubmeshMaterialAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); + } + } + + { + var maxIndex = GetAttribute(ShapeVertexOffsetAttribute.IndexInto).Data.Length - 1; + for (var i = 0; i < ShapeVertexOffsetAttribute.TypedData.Length; ++i) + { + var index = ShapeVertexOffsetAttribute.TypedData[i]; + + if (index == -1) + continue; // no relation. + + if (index < -1 || index > maxIndex) + throw new Exception($"Index out of range in Vim.G3dNext.Attributes.ShapeVertexOffsetAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); + } + } + } + } + public partial class MeshAttributeCollection : IAttributeCollection + { + public IEnumerable AttributeNames + => Attributes.Keys; + + public long GetSize() + => Attributes.Values.Sum(a => a.Data.LongLength * a.AttributeDescriptor.DataElementSize); + + public IDictionary Attributes { get; } + = new Dictionary + { + [Vim.G3dNext.Attributes.InstanceTransformAttribute.AttributeName] = new Vim.G3dNext.Attributes.InstanceTransformAttribute(), + [Vim.G3dNext.Attributes.MeshOpaqueSubmeshCountAttribute.AttributeName] = new Vim.G3dNext.Attributes.MeshOpaqueSubmeshCountAttribute(), + [Vim.G3dNext.Attributes.SubmeshIndexOffsetAttribute.AttributeName] = new Vim.G3dNext.Attributes.SubmeshIndexOffsetAttribute(), + [Vim.G3dNext.Attributes.SubmeshVertexOffsetAttribute.AttributeName] = new Vim.G3dNext.Attributes.SubmeshVertexOffsetAttribute(), + [Vim.G3dNext.Attributes.SubmeshMaterialAttribute.AttributeName] = new Vim.G3dNext.Attributes.SubmeshMaterialAttribute(), + [Vim.G3dNext.Attributes.VertexAttribute.AttributeName] = new Vim.G3dNext.Attributes.VertexAttribute(), + [Vim.G3dNext.Attributes.IndexAttribute.AttributeName] = new Vim.G3dNext.Attributes.IndexAttribute(), + }; + + public IDictionary AttributeReaders { get; } + = new Dictionary + { + [Vim.G3dNext.Attributes.InstanceTransformAttribute.AttributeName] = Vim.G3dNext.Attributes.InstanceTransformAttribute.CreateAttributeReader(), + [Vim.G3dNext.Attributes.MeshOpaqueSubmeshCountAttribute.AttributeName] = Vim.G3dNext.Attributes.MeshOpaqueSubmeshCountAttribute.CreateAttributeReader(), + [Vim.G3dNext.Attributes.SubmeshIndexOffsetAttribute.AttributeName] = Vim.G3dNext.Attributes.SubmeshIndexOffsetAttribute.CreateAttributeReader(), + [Vim.G3dNext.Attributes.SubmeshVertexOffsetAttribute.AttributeName] = Vim.G3dNext.Attributes.SubmeshVertexOffsetAttribute.CreateAttributeReader(), + [Vim.G3dNext.Attributes.SubmeshMaterialAttribute.AttributeName] = Vim.G3dNext.Attributes.SubmeshMaterialAttribute.CreateAttributeReader(), + [Vim.G3dNext.Attributes.VertexAttribute.AttributeName] = Vim.G3dNext.Attributes.VertexAttribute.CreateAttributeReader(), + [Vim.G3dNext.Attributes.IndexAttribute.AttributeName] = Vim.G3dNext.Attributes.IndexAttribute.CreateAttributeReader(), + }; + + // Named Attributes. + + public Vim.G3dNext.Attributes.InstanceTransformAttribute InstanceTransformAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.InstanceTransformAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceTransformAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.InstanceTransformAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.MeshOpaqueSubmeshCountAttribute MeshOpaqueSubmeshCountAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.MeshOpaqueSubmeshCountAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshOpaqueSubmeshCountAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.MeshOpaqueSubmeshCountAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.SubmeshIndexOffsetAttribute SubmeshIndexOffsetAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.SubmeshIndexOffsetAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.SubmeshIndexOffsetAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.SubmeshIndexOffsetAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.SubmeshVertexOffsetAttribute SubmeshVertexOffsetAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.SubmeshVertexOffsetAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.SubmeshVertexOffsetAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.SubmeshVertexOffsetAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.SubmeshMaterialAttribute SubmeshMaterialAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.SubmeshMaterialAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.SubmeshMaterialAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.SubmeshMaterialAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.VertexAttribute VertexAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.VertexAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.VertexAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.VertexAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.IndexAttribute IndexAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.IndexAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.IndexAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.IndexAttribute.AttributeName] = value as IAttribute; + } + + /// + public IAttribute GetAttribute(Type attributeType) + { + + if (attributeType == typeof(Vim.G3dNext.Attributes.InstanceTransformAttribute)) + return InstanceTransformAttribute; + + if (attributeType == typeof(Vim.G3dNext.Attributes.MeshOpaqueSubmeshCountAttribute)) + return MeshOpaqueSubmeshCountAttribute; + + if (attributeType == typeof(Vim.G3dNext.Attributes.SubmeshIndexOffsetAttribute)) + return SubmeshIndexOffsetAttribute; + + if (attributeType == typeof(Vim.G3dNext.Attributes.SubmeshVertexOffsetAttribute)) + return SubmeshVertexOffsetAttribute; + + if (attributeType == typeof(Vim.G3dNext.Attributes.SubmeshMaterialAttribute)) + return SubmeshMaterialAttribute; + + if (attributeType == typeof(Vim.G3dNext.Attributes.VertexAttribute)) + return VertexAttribute; + + if (attributeType == typeof(Vim.G3dNext.Attributes.IndexAttribute)) + return IndexAttribute; + + throw new ArgumentException("Type {attributeType.ToString()} is not supported."); + } + + public IAttribute MergeAttribute(string attributeName, IReadOnlyList otherCollections) + { + var collections = otherCollections.Prepend(this).ToArray(); + switch (attributeName) + { + + case Vim.G3dNext.Attributes.InstanceTransformAttribute.AttributeName: + { + // Data Attribute + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + } + + case Vim.G3dNext.Attributes.MeshOpaqueSubmeshCountAttribute.AttributeName: + { + // Data Attribute + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + } + + case Vim.G3dNext.Attributes.SubmeshIndexOffsetAttribute.AttributeName: + { + // Index Attribute + return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); + } + + case Vim.G3dNext.Attributes.SubmeshVertexOffsetAttribute.AttributeName: + { + // Index Attribute + return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); + } + + case Vim.G3dNext.Attributes.SubmeshMaterialAttribute.AttributeName: + { + // Index Attribute + return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); + } + + case Vim.G3dNext.Attributes.VertexAttribute.AttributeName: + { + // Data Attribute + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + } + + case Vim.G3dNext.Attributes.IndexAttribute.AttributeName: + { + // Index Attribute + return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); + } + + default: + throw new ArgumentException(nameof(attributeName)); + } + } + + public void Validate() + { + // Ensure all the indices are either -1 or within the bounds of the attributes they are indexing into. + + { + var maxIndex = GetAttribute(SubmeshIndexOffsetAttribute.IndexInto).Data.Length - 1; + for (var i = 0; i < SubmeshIndexOffsetAttribute.TypedData.Length; ++i) + { + var index = SubmeshIndexOffsetAttribute.TypedData[i]; + + if (index == -1) + continue; // no relation. + + if (index < -1 || index > maxIndex) + throw new Exception($"Index out of range in Vim.G3dNext.Attributes.SubmeshIndexOffsetAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); + } + } + + { + var maxIndex = GetAttribute(SubmeshVertexOffsetAttribute.IndexInto).Data.Length - 1; + for (var i = 0; i < SubmeshVertexOffsetAttribute.TypedData.Length; ++i) + { + var index = SubmeshVertexOffsetAttribute.TypedData[i]; + + if (index == -1) + continue; // no relation. + + if (index < -1 || index > maxIndex) + throw new Exception($"Index out of range in Vim.G3dNext.Attributes.SubmeshVertexOffsetAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); + } + } + + { + var maxIndex = GetAttribute(SubmeshMaterialAttribute.IndexInto).Data.Length - 1; + for (var i = 0; i < SubmeshMaterialAttribute.TypedData.Length; ++i) + { + var index = SubmeshMaterialAttribute.TypedData[i]; + + if (index == -1) + continue; // no relation. + + if (index < -1 || index > maxIndex) + throw new Exception($"Index out of range in Vim.G3dNext.Attributes.SubmeshMaterialAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); + } + } + + { + var maxIndex = GetAttribute(IndexAttribute.IndexInto).Data.Length - 1; + for (var i = 0; i < IndexAttribute.TypedData.Length; ++i) + { + var index = IndexAttribute.TypedData[i]; + + if (index == -1) + continue; // no relation. + + if (index < -1 || index > maxIndex) + throw new Exception($"Index out of range in Vim.G3dNext.Attributes.IndexAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); + } + } + } + } + public partial class SceneAttributeCollection : IAttributeCollection + { + public IEnumerable AttributeNames + => Attributes.Keys; + + public long GetSize() + => Attributes.Values.Sum(a => a.Data.LongLength * a.AttributeDescriptor.DataElementSize); + + public IDictionary Attributes { get; } + = new Dictionary + { + [Vim.G3dNext.Attributes.InstanceFileAttribute.AttributeName] = new Vim.G3dNext.Attributes.InstanceFileAttribute(), + [Vim.G3dNext.Attributes.InstanceIndexAttribute.AttributeName] = new Vim.G3dNext.Attributes.InstanceIndexAttribute(), + [Vim.G3dNext.Attributes.InstanceNodeAttribute.AttributeName] = new Vim.G3dNext.Attributes.InstanceNodeAttribute(), + [Vim.G3dNext.Attributes.InstanceGroupAttribute.AttributeName] = new Vim.G3dNext.Attributes.InstanceGroupAttribute(), + [Vim.G3dNext.Attributes.InstanceTagAttribute.AttributeName] = new Vim.G3dNext.Attributes.InstanceTagAttribute(), + [Vim.G3dNext.Attributes.InstanceFlagsAttribute.AttributeName] = new Vim.G3dNext.Attributes.InstanceFlagsAttribute(), + [Vim.G3dNext.Attributes.InstanceMinAttribute.AttributeName] = new Vim.G3dNext.Attributes.InstanceMinAttribute(), + [Vim.G3dNext.Attributes.InstanceMaxAttribute.AttributeName] = new Vim.G3dNext.Attributes.InstanceMaxAttribute(), + [Vim.G3dNext.Attributes.MeshInstanceCountAttribute.AttributeName] = new Vim.G3dNext.Attributes.MeshInstanceCountAttribute(), + [Vim.G3dNext.Attributes.MeshIndexCountAttribute.AttributeName] = new Vim.G3dNext.Attributes.MeshIndexCountAttribute(), + [Vim.G3dNext.Attributes.MeshVertexCountAttribute.AttributeName] = new Vim.G3dNext.Attributes.MeshVertexCountAttribute(), + [Vim.G3dNext.Attributes.MeshOpaqueIndexCountAttribute.AttributeName] = new Vim.G3dNext.Attributes.MeshOpaqueIndexCountAttribute(), + [Vim.G3dNext.Attributes.MeshOpaqueVertexCountAttribute.AttributeName] = new Vim.G3dNext.Attributes.MeshOpaqueVertexCountAttribute(), + }; + + public IDictionary AttributeReaders { get; } + = new Dictionary + { + [Vim.G3dNext.Attributes.InstanceFileAttribute.AttributeName] = Vim.G3dNext.Attributes.InstanceFileAttribute.CreateAttributeReader(), + [Vim.G3dNext.Attributes.InstanceIndexAttribute.AttributeName] = Vim.G3dNext.Attributes.InstanceIndexAttribute.CreateAttributeReader(), + [Vim.G3dNext.Attributes.InstanceNodeAttribute.AttributeName] = Vim.G3dNext.Attributes.InstanceNodeAttribute.CreateAttributeReader(), + [Vim.G3dNext.Attributes.InstanceGroupAttribute.AttributeName] = Vim.G3dNext.Attributes.InstanceGroupAttribute.CreateAttributeReader(), + [Vim.G3dNext.Attributes.InstanceTagAttribute.AttributeName] = Vim.G3dNext.Attributes.InstanceTagAttribute.CreateAttributeReader(), + [Vim.G3dNext.Attributes.InstanceFlagsAttribute.AttributeName] = Vim.G3dNext.Attributes.InstanceFlagsAttribute.CreateAttributeReader(), + [Vim.G3dNext.Attributes.InstanceMinAttribute.AttributeName] = Vim.G3dNext.Attributes.InstanceMinAttribute.CreateAttributeReader(), + [Vim.G3dNext.Attributes.InstanceMaxAttribute.AttributeName] = Vim.G3dNext.Attributes.InstanceMaxAttribute.CreateAttributeReader(), + [Vim.G3dNext.Attributes.MeshInstanceCountAttribute.AttributeName] = Vim.G3dNext.Attributes.MeshInstanceCountAttribute.CreateAttributeReader(), + [Vim.G3dNext.Attributes.MeshIndexCountAttribute.AttributeName] = Vim.G3dNext.Attributes.MeshIndexCountAttribute.CreateAttributeReader(), + [Vim.G3dNext.Attributes.MeshVertexCountAttribute.AttributeName] = Vim.G3dNext.Attributes.MeshVertexCountAttribute.CreateAttributeReader(), + [Vim.G3dNext.Attributes.MeshOpaqueIndexCountAttribute.AttributeName] = Vim.G3dNext.Attributes.MeshOpaqueIndexCountAttribute.CreateAttributeReader(), + [Vim.G3dNext.Attributes.MeshOpaqueVertexCountAttribute.AttributeName] = Vim.G3dNext.Attributes.MeshOpaqueVertexCountAttribute.CreateAttributeReader(), + }; + + // Named Attributes. + + public Vim.G3dNext.Attributes.InstanceFileAttribute InstanceFileAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.InstanceFileAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceFileAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.InstanceFileAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.InstanceIndexAttribute InstanceIndexAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.InstanceIndexAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceIndexAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.InstanceIndexAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.InstanceNodeAttribute InstanceNodeAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.InstanceNodeAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceNodeAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.InstanceNodeAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.InstanceGroupAttribute InstanceGroupAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.InstanceGroupAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceGroupAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.InstanceGroupAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.InstanceTagAttribute InstanceTagAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.InstanceTagAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceTagAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.InstanceTagAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.InstanceFlagsAttribute InstanceFlagsAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.InstanceFlagsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceFlagsAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.InstanceFlagsAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.InstanceMinAttribute InstanceMinAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.InstanceMinAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceMinAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.InstanceMinAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.InstanceMaxAttribute InstanceMaxAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.InstanceMaxAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceMaxAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.InstanceMaxAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.MeshInstanceCountAttribute MeshInstanceCountAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.MeshInstanceCountAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshInstanceCountAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.MeshInstanceCountAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.MeshIndexCountAttribute MeshIndexCountAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.MeshIndexCountAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshIndexCountAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.MeshIndexCountAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.MeshVertexCountAttribute MeshVertexCountAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.MeshVertexCountAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshVertexCountAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.MeshVertexCountAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.MeshOpaqueIndexCountAttribute MeshOpaqueIndexCountAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.MeshOpaqueIndexCountAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshOpaqueIndexCountAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.MeshOpaqueIndexCountAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.MeshOpaqueVertexCountAttribute MeshOpaqueVertexCountAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.MeshOpaqueVertexCountAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshOpaqueVertexCountAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.MeshOpaqueVertexCountAttribute.AttributeName] = value as IAttribute; + } + + /// + public IAttribute GetAttribute(Type attributeType) + { + + if (attributeType == typeof(Vim.G3dNext.Attributes.InstanceFileAttribute)) + return InstanceFileAttribute; + + if (attributeType == typeof(Vim.G3dNext.Attributes.InstanceIndexAttribute)) + return InstanceIndexAttribute; + + if (attributeType == typeof(Vim.G3dNext.Attributes.InstanceNodeAttribute)) + return InstanceNodeAttribute; + + if (attributeType == typeof(Vim.G3dNext.Attributes.InstanceGroupAttribute)) + return InstanceGroupAttribute; + + if (attributeType == typeof(Vim.G3dNext.Attributes.InstanceTagAttribute)) + return InstanceTagAttribute; + + if (attributeType == typeof(Vim.G3dNext.Attributes.InstanceFlagsAttribute)) + return InstanceFlagsAttribute; + + if (attributeType == typeof(Vim.G3dNext.Attributes.InstanceMinAttribute)) + return InstanceMinAttribute; + + if (attributeType == typeof(Vim.G3dNext.Attributes.InstanceMaxAttribute)) + return InstanceMaxAttribute; + + if (attributeType == typeof(Vim.G3dNext.Attributes.MeshInstanceCountAttribute)) + return MeshInstanceCountAttribute; + + if (attributeType == typeof(Vim.G3dNext.Attributes.MeshIndexCountAttribute)) + return MeshIndexCountAttribute; + + if (attributeType == typeof(Vim.G3dNext.Attributes.MeshVertexCountAttribute)) + return MeshVertexCountAttribute; + + if (attributeType == typeof(Vim.G3dNext.Attributes.MeshOpaqueIndexCountAttribute)) + return MeshOpaqueIndexCountAttribute; + + if (attributeType == typeof(Vim.G3dNext.Attributes.MeshOpaqueVertexCountAttribute)) + return MeshOpaqueVertexCountAttribute; + + throw new ArgumentException("Type {attributeType.ToString()} is not supported."); + } + + public IAttribute MergeAttribute(string attributeName, IReadOnlyList otherCollections) + { + var collections = otherCollections.Prepend(this).ToArray(); + switch (attributeName) + { + + case Vim.G3dNext.Attributes.InstanceFileAttribute.AttributeName: + { + // Data Attribute + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + } + + case Vim.G3dNext.Attributes.InstanceIndexAttribute.AttributeName: + { + // Data Attribute + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + } + + case Vim.G3dNext.Attributes.InstanceNodeAttribute.AttributeName: + { + // Data Attribute + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + } + + case Vim.G3dNext.Attributes.InstanceGroupAttribute.AttributeName: + { + // Data Attribute + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + } + + case Vim.G3dNext.Attributes.InstanceTagAttribute.AttributeName: + { + // Data Attribute + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + } + + case Vim.G3dNext.Attributes.InstanceFlagsAttribute.AttributeName: + { + // Data Attribute + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + } + + case Vim.G3dNext.Attributes.InstanceMinAttribute.AttributeName: + { + // Data Attribute + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + } + + case Vim.G3dNext.Attributes.InstanceMaxAttribute.AttributeName: + { + // Data Attribute + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + } + + case Vim.G3dNext.Attributes.MeshInstanceCountAttribute.AttributeName: + { + // Data Attribute + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + } + + case Vim.G3dNext.Attributes.MeshIndexCountAttribute.AttributeName: + { + // Data Attribute + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + } + + case Vim.G3dNext.Attributes.MeshVertexCountAttribute.AttributeName: + { + // Data Attribute + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + } + + case Vim.G3dNext.Attributes.MeshOpaqueIndexCountAttribute.AttributeName: + { + // Data Attribute + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + } + + case Vim.G3dNext.Attributes.MeshOpaqueVertexCountAttribute.AttributeName: + { + // Data Attribute + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + } + + default: + throw new ArgumentException(nameof(attributeName)); + } + } + + public void Validate() + { + // Ensure all the indices are either -1 or within the bounds of the attributes they are indexing into. + + } + } + public partial class MaterialAttributeCollection : IAttributeCollection + { + public IEnumerable AttributeNames + => Attributes.Keys; + + public long GetSize() + => Attributes.Values.Sum(a => a.Data.LongLength * a.AttributeDescriptor.DataElementSize); + + public IDictionary Attributes { get; } + = new Dictionary + { + [Vim.G3dNext.Attributes.MaterialColorAttribute.AttributeName] = new Vim.G3dNext.Attributes.MaterialColorAttribute(), + [Vim.G3dNext.Attributes.MaterialGlossinessAttribute.AttributeName] = new Vim.G3dNext.Attributes.MaterialGlossinessAttribute(), + [Vim.G3dNext.Attributes.MaterialSmoothnessAttribute.AttributeName] = new Vim.G3dNext.Attributes.MaterialSmoothnessAttribute(), + }; + + public IDictionary AttributeReaders { get; } + = new Dictionary + { + [Vim.G3dNext.Attributes.MaterialColorAttribute.AttributeName] = Vim.G3dNext.Attributes.MaterialColorAttribute.CreateAttributeReader(), + [Vim.G3dNext.Attributes.MaterialGlossinessAttribute.AttributeName] = Vim.G3dNext.Attributes.MaterialGlossinessAttribute.CreateAttributeReader(), + [Vim.G3dNext.Attributes.MaterialSmoothnessAttribute.AttributeName] = Vim.G3dNext.Attributes.MaterialSmoothnessAttribute.CreateAttributeReader(), + }; + + // Named Attributes. + + public Vim.G3dNext.Attributes.MaterialColorAttribute MaterialColorAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.MaterialColorAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MaterialColorAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.MaterialColorAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.MaterialGlossinessAttribute MaterialGlossinessAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.MaterialGlossinessAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MaterialGlossinessAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.MaterialGlossinessAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.MaterialSmoothnessAttribute MaterialSmoothnessAttribute + { + get => Attributes.TryGetValue(Vim.G3dNext.Attributes.MaterialSmoothnessAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MaterialSmoothnessAttribute : default; + set => Attributes[Vim.G3dNext.Attributes.MaterialSmoothnessAttribute.AttributeName] = value as IAttribute; + } + + /// + public IAttribute GetAttribute(Type attributeType) + { + + if (attributeType == typeof(Vim.G3dNext.Attributes.MaterialColorAttribute)) + return MaterialColorAttribute; + + if (attributeType == typeof(Vim.G3dNext.Attributes.MaterialGlossinessAttribute)) + return MaterialGlossinessAttribute; + + if (attributeType == typeof(Vim.G3dNext.Attributes.MaterialSmoothnessAttribute)) + return MaterialSmoothnessAttribute; + + throw new ArgumentException("Type {attributeType.ToString()} is not supported."); + } + + public IAttribute MergeAttribute(string attributeName, IReadOnlyList otherCollections) + { + var collections = otherCollections.Prepend(this).ToArray(); + switch (attributeName) + { + + case Vim.G3dNext.Attributes.MaterialColorAttribute.AttributeName: + { + // Data Attribute + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + } + + case Vim.G3dNext.Attributes.MaterialGlossinessAttribute.AttributeName: + { + // Data Attribute + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + } + + case Vim.G3dNext.Attributes.MaterialSmoothnessAttribute.AttributeName: + { + // Data Attribute + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + } + + default: + throw new ArgumentException(nameof(attributeName)); + } + } + + public void Validate() + { + // Ensure all the indices are either -1 or within the bounds of the attributes they are indexing into. + + } + } +} diff --git a/src/cs/g3d/temp/Vim.G3dNext.Attributes/Vim.G3dNext.Attributes.csproj b/src/cs/g3d/temp/Vim.G3dNext.Attributes/Vim.G3dNext.Attributes.csproj new file mode 100644 index 00000000..2bded7f0 --- /dev/null +++ b/src/cs/g3d/temp/Vim.G3dNext.Attributes/Vim.G3dNext.Attributes.csproj @@ -0,0 +1,34 @@ + + + + + + netstandard2.0 + true + + G3D is a simple, efficient, generic binary format for storing and transmitting geometry. The G3D format is designed to be used either as a serialization format or as an in-memory data structure. G3D can represent triangular meshes, quadrilateral meshes, polygonal meshes, point clouds, and line segments. + It can be easily and efficiently deserialized and rendered in different languages and on different platforms. + + LICENSE.txt + https://github.com/vimaec/g3d + https://github.com/vimaec/g3d + GitHub + 2.0.0 + true + true + true + snupkg + + + + + + + + + + + + + + diff --git a/src/cs/g3d/temp/Vim.G3dNext.Attributes/VimAttributeCollectionExtensions.cs b/src/cs/g3d/temp/Vim.G3dNext.Attributes/VimAttributeCollectionExtensions.cs new file mode 100644 index 00000000..75498793 --- /dev/null +++ b/src/cs/g3d/temp/Vim.G3dNext.Attributes/VimAttributeCollectionExtensions.cs @@ -0,0 +1,86 @@ +using System.Linq; + +namespace Vim.G3dNext.Attributes +{ + public static class VimAttributeCollectionExtensions + { + public static int GetMeshSubmeshStart(this VimAttributeCollection c, int mesh) + { + return c.MeshSubmeshOffsetAttribute.TypedData[mesh]; + } + + public static int GetMeshSubmeshEnd(this VimAttributeCollection c, int mesh) + { + return mesh + 1 < c.GetMeshCount() + ? c.MeshSubmeshOffsetAttribute.TypedData[mesh +1] + : c.GetSubmeshCount(); + } + + public static int GetMeshSubmeshCount(this VimAttributeCollection c, int mesh) + { + return c.GetMeshSubmeshEnd(mesh) - c.GetMeshSubmeshStart(mesh); + } + + public static int GetFaceCount(this VimAttributeCollection c) + { + var cornersPerFace = c.GetCornersPerFaceCount(); + var indexCount = c.GetIndexCount(); + + return cornersPerFace != 0 ? indexCount / cornersPerFace : -1; + } + + /// + /// The number of corners per face. A value of 3 designates that all faces are triangles (a triangle has 3 corners). + /// + public static int GetCornersPerFaceCount(this VimAttributeCollection c) + => c.CornersPerFaceAttribute?.TypedData?.FirstOrDefault() ?? 0; + + /// + /// The total number of indices. + /// + public static int GetIndexCount(this VimAttributeCollection c) + => c.IndexAttribute?.TypedData?.Length ?? 0; + + /// + /// The total number of vertices. + /// + public static int GetVertexCount(this VimAttributeCollection c) + => c.VertexAttribute?.TypedData?.Length ?? 0; + + /// + /// The total number of instances. + /// + public static int GetInstanceCount(this VimAttributeCollection c) + => c.InstanceTransformAttribute?.TypedData?.Length ?? 0; + + /// + /// The total number of meshes. + /// + public static int GetMeshCount(this VimAttributeCollection c) + => c.MeshSubmeshOffsetAttribute?.TypedData?.Length ?? 0; + + /// + /// The total number of submeshes. + /// + public static int GetSubmeshCount(this VimAttributeCollection c) + => c.SubmeshIndexOffsetAttribute?.TypedData?.Length ?? 0; + + /// + /// The total number of materials. + /// + public static int GetMaterialCount(this VimAttributeCollection c) + => c.MaterialColorAttribute?.TypedData?.Length ?? 0; + + /// + /// The total number of shape vertices. + /// + public static int GetShapeVertexCount(this VimAttributeCollection c) + => c.ShapeVertexAttribute?.TypedData?.Length ?? 0; + + /// + /// The total number of shapes. + /// + public static int GetShapeCount(this VimAttributeCollection c) + => c.ShapeVertexOffsetAttribute?.TypedData?.Length ?? 0; + } +} diff --git a/src/cs/g3d/temp/Vim.G3dNext.Tests/AssimpTests.cs b/src/cs/g3d/temp/Vim.G3dNext.Tests/AssimpTests.cs new file mode 100644 index 00000000..e64b4563 --- /dev/null +++ b/src/cs/g3d/temp/Vim.G3dNext.Tests/AssimpTests.cs @@ -0,0 +1,237 @@ +using Assimp; +using NUnit.Framework; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using Vim.G3dNext.AssimpWrapper; +using Vim.G3dNext.Attributes; +using Vim.Math3d; + +using NextG3d = Vim.G3dNext.G3DNext; + +namespace Vim.G3dNext.Tests +{ + [TestFixture] + public static class AssimpTests + { + public class FileLoadData + { + public FileLoadData(string filePath) + => SourceFile = new FileInfo(filePath); + + public string ShortName => Path.GetFileName(SourceFile.FullName); + public int NumMeshes => Scene?.MeshCount ?? 0; + public FileInfo SourceFile; + public FileInfo G3DFile; + public long MSecToOpen; + public long MSecToSaveG3d; + public long MSecToOpenG3d; + public long MSecToConvert; + public long MemoryConsumption; + public long MemoryConsumptionG3d; + public Exception Error; + public Scene Scene; + public NextG3d G3d; + } + + public static readonly string ProjectFolder = new DirectoryInfo(Properties.Resources.ProjDir.Trim()).FullName; + public static string RootFolder = Path.Combine(ProjectFolder, "..", ".."); + public static string TestInputFolder = Path.Combine(RootFolder, "data", "models"); + public static string TestOutputFolder = Path.Combine(RootFolder, "out"); + + public static IEnumerable GetInputFiles() + => Directory.GetFiles(TestInputFolder, "*.*", SearchOption.AllDirectories); + + public static void ValidateSame(Object a, Object b, string name = "") + { + if (!a.Equals(b)) + throw new Exception($"Values {a} and {b} are different {name}"); + } + + public static void ValidateSameG3D(NextG3d g1, NextG3d g2) + { + var (ac1, ac2) = (g1.AttributeCollection, g2.AttributeCollection); + + ValidateSame(ac1.GetCornersPerFaceCount(), ac2.GetCornersPerFaceCount(), "GetCornersPerFaceCount"); + ValidateSame(ac1.GetIndexCount(), ac2.GetIndexCount(), "GetIndexCount"); + ValidateSame(ac1.GetVertexCount(), ac2.GetVertexCount(), "GetVertexCount"); + ValidateSame(ac1.GetInstanceCount(), ac2.GetInstanceCount(), "GetInstanceCount"); + ValidateSame(ac1.GetMeshCount(), ac2.GetMeshCount(), "GetMeshCount"); + ValidateSame(ac1.Attributes.Count, ac2.Attributes.Count, "Attribute Count"); + + foreach (var (k, attr1) in ac1.Attributes) + { + var attr2 = ac2.Attributes[k]; + ValidateSame(attr1.Name, attr2.Name, $"Attribute[{k}].Name"); + ValidateSame(attr1.Data.Length, attr2.Data.Length, $"Attribute[{k}].Data.Length"); + } + } + + [Test] + [Platform(Exclude = "Linux,Unix", Reason = "AssimpNet is failing to load its dependency on 'libdl.so'.")] + public static void OpenAndConvertAssimpFiles() + { + var testDir = "";//PrepareTestDir(); + + var files = GetInputFiles() + .Where(AssimpLoader.CanLoad) + .Select(f => new FileLoadData(f)) + .ToArray(); + + // Load all the files + foreach (var f in files) + { + try + { + (f.MemoryConsumption, f.MSecToOpen) = + TestUtils.GetMemoryConsumptionAndMSecElapsed(() => + f.Scene = AssimpLoader.Load(f.SourceFile.FullName)); + } + catch (Exception e) + { + f.Error = e; + } + } + + // Convert all the Assimp scenes to G3D + foreach (var f in files) + { + if (f.Scene == null) continue; + + try + { + f.MSecToConvert = TestUtils.GetMSecElapsed(() => + f.G3d = f.Scene.ToG3d()); + } + catch (Exception e) + { + f.Error = e; + } + } + + // Save all the G3D scenes + foreach (var f in files) + { + if (f.G3d == null) continue; + + try + { + var outputFilePath = Path.Combine(testDir, f.ShortName + ".g3d"); + f.G3DFile = new FileInfo(outputFilePath); + + f.MSecToSaveG3d = TestUtils.GetMSecElapsed(() => + f.G3d.Write(outputFilePath)); + } + catch (Exception e) + { + f.Error = e; + } + } + + // Try reading back in all of the G3D scenes, measure load times and the memory consumption + foreach (var f in files) + { + if (f.G3DFile == null) continue; + + try + { + NextG3d localG3d = null; + + (f.MemoryConsumptionG3d, f.MSecToOpenG3d) = + TestUtils.GetMemoryConsumptionAndMSecElapsed(() => + NextG3d.TryRead(f.G3DFile.FullName, out localG3d)); + + ValidateSameG3D(f.G3d, localG3d); + } + catch (Exception e) + { + f.Error = e; + } + } + + // Output the header for data + Console.WriteLine( + "Importer," + + "Extension," + + "File Name," + + "File Size(KB)," + + "Load Time(s)," + + "Memory(KB)," + + "# Meshes," + + "Time to Convert," + + "Time to Write G3D," + + "G3D File Size(KB)," + + "G3D Memory(KB)", + "G3D Load Time(s)", + "Error"); + + // Output the data rows + foreach (var f in files) + { + Console.WriteLine( + "Assimp," + + $"{Path.GetExtension(f.ShortName)}," + + $"{f.ShortName}," + + $"{f.SourceFile?.Length / 1000}," + + $"{f.MSecToOpen / 100f}," + + $"{f.MemoryConsumption / 1000}," + + $"{f.NumMeshes}," + + $"{f.MSecToConvert / 100f}," + + $"{f.MSecToSaveG3d / 100f}," + + $"{f.G3DFile?.Length / 1000}," + + $"{f.MemoryConsumptionG3d / 1000}," + + $"{f.MSecToOpenG3d / 100f}," + + $"{f.Error}"); + } + + Assert.AreEqual(0, files.Count(f => f.Error != null), "Errors occurred"); + } + + public static NextG3d LoadAssimpFile(string filePath) + { + using (var context = new AssimpContext()) + { + var scene = context.ImportFile(filePath); + Assert.AreEqual(1, scene.Meshes.Count); + return scene.Meshes[0].ToVimG3d(); + } + } + + [Test] + [Platform(Exclude = "Linux,Unix", Reason = "AssimpNet is failing to load its dependency on 'libdl.so'.")] + public static void TestWriters() + { + var testDir = "";//PrepareTestDir(); + + var fileName = Path.Combine(TestInputFolder, "PLY", "Wuson.ply"); + + var outputFileName = @"test"; + outputFileName = Path.Combine(testDir, outputFileName); + + var g3d = LoadAssimpFile(fileName); + + g3d.WritePly(outputFileName + ".ply"); + g3d.WriteObj(outputFileName + ".obj"); + + // TODO compare the PLY, the OBJ and the original file. + + var g3dFromPly = LoadAssimpFile(outputFileName + ".ply"); + var g3dFromObj = LoadAssimpFile(outputFileName + ".obj"); + + { + var ac1 = g3d.AttributeCollection; + var ac2 = g3dFromPly.AttributeCollection; + Assert.AreEqual(ac1.GetCornersPerFaceCount(), ac2.GetCornersPerFaceCount()); + Assert.AreEqual(ac1.GetFaceCount(), ac2.GetFaceCount()); + Assert.AreEqual(ac1.GetIndexCount(), ac2.GetIndexCount()); + Assert.AreEqual(ac1.GetVertexCount(), ac2.GetVertexCount()); + Assert.AreEqual(ac1.GetInstanceCount(), ac2.GetInstanceCount()); + Assert.AreEqual(ac1.GetMeshCount(), ac2.GetMeshCount()); + } + + // BUG: Assimp ignores the OBJ index buffer. God knows why. + //CompareG3D(g3d, g3dFromObj); + } + } +} diff --git a/src/cs/g3d/temp/Vim.G3dNext.Tests/FileUtils.cs b/src/cs/g3d/temp/Vim.G3dNext.Tests/FileUtils.cs new file mode 100644 index 00000000..6ee3b602 --- /dev/null +++ b/src/cs/g3d/temp/Vim.G3dNext.Tests/FileUtils.cs @@ -0,0 +1,183 @@ +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using System.Diagnostics; +using System.Threading; +using Azure.Storage.Blobs; +using Azure.Storage.Blobs.Models; +using Vim.BFast; +using Vim.LinqArray; +using Vim.G3d; +using System.IO.Compression; +using Vim.Math3d; +using System; + +namespace Vim.G3dNext +{ + public static class FileUtils + { + public static void ResetFolder(string path) + { + + if (Directory.Exists(path)) + { + Directory.Delete(path, true); + } + Directory.CreateDirectory(path); + } + + public static VimG3d LoadG3d(string path) + { + var time = Stopwatch.StartNew(); + var file = new FileStream(path, FileMode.Open); + var geometry = file.GetBFastBufferReader("geometry"); + geometry.Seek(); + var g3d = VimG3d.FromStream(file); + Console.WriteLine("LoadG3d " + time.ElapsedMilliseconds / 1000f); + return g3d; + } + + public static void SplitVim(string path, string name) + { + var time = Stopwatch.StartNew(); + var vim = VimScene.LoadVim(path, new DataFormat.LoadOptions() { + SkipAssets = true, + SkipGeometry = true, + SkipHeader = true} + ); + Console.WriteLine("LoadVim " + time.ElapsedMilliseconds / 1000f); + + time.Restart(); + var g3d = LoadG3d(path); + Console.WriteLine("VimG3d " + time.ElapsedMilliseconds / 1000f); + + time.Restart(); + var meshes = g3d.GetMeshes().ToArray(); + PolyStopwatch.instance.Print(); + Console.WriteLine("GetMeshes " + time.ElapsedMilliseconds / 1000f); + + time.Restart(); + var nodeElements = vim.DocumentModel.NodeElementIndex.ToArray(); + var categoryName = vim.DocumentModel.CategoryName; + var elementCategory = vim.DocumentModel.ElementCategoryIndex; + + // Remove select => long once using latest data model. + var nodeElementIds = nodeElements.Select(n => n < 0 || n > vim.DocumentModel.ElementId.Count + ? (long)-1 + : (long)vim.DocumentModel.ElementId[n] + ).ToArray(); + Console.WriteLine("nodes " + time.ElapsedMilliseconds / 1000f); + + time.Restart(); + var getMeshName = (MeshG3d mesh) => + { + var node = mesh.instanceNodes[0]; + + if (node < 0 || node >= nodeElements.Length) return ""; + var element = nodeElements [node]; + + if (element < 0 || element >= elementCategory.Count) return ""; + var category = elementCategory[element]; + + if (category < 0 || category >= categoryName.Count) return ""; + var name = categoryName[category]; + + return name; + }; + + meshes = meshes.OrderByDescending((m) => ( + GetPriority(getMeshName(m)), + m.GetAABB().MaxSide) + ).ToArray(); + Console.WriteLine("OrderByDescending " + time.ElapsedMilliseconds / 1000f); + + time.Restart(); + var meshBuffers = meshes.Select((m, i) => + { + return m.g3d.ToBytes() + .GzipBytes() + .ToNamedBuffer($"mesh_{i}"); + }); + Console.WriteLine("meshBuffers " + time.ElapsedMilliseconds / 1000f); + + time.Restart(); + var index = meshes.ToMeshIndex(g3d, nodeElements, nodeElementIds); + var indexBuffer = index.g3d.ToBytes() + .GzipBytes() + .ToNamedBuffer("index"); + Console.WriteLine("indexBuffer " + time.ElapsedMilliseconds / 1000f); + + time.Restart(); + var mat = g3d.getMaterials(); + var matBuffer = mat.g3d.ToBytes() + .GzipBytes() + .ToNamedBuffer("materials"); + Console.WriteLine("matBuffer " + time.ElapsedMilliseconds / 1000f); + + time.Restart(); + var bfastBuilder = new BFastBuilder(); + bfastBuilder.Add(indexBuffer); + bfastBuilder.Add(matBuffer); + + foreach (var mesh in meshBuffers) + { + bfastBuilder.Add(mesh); + } + + bfastBuilder.Write($"./{name}.vimx"); + Console.WriteLine("Write " + time.ElapsedMilliseconds / 1000f); + + } + + + static int GetPriority(string value) + { + if (string.IsNullOrWhiteSpace(value)) return 0; + + if (value.Contains("Topography")) return 110; + if (value.Contains("Floor")) return 100; + if (value.Contains("Slab")) return 100; + if (value.Contains("Ceiling")) return 90; + if (value.Contains("Roof")) return 90; + + if (value.Contains("Curtain")) return 80; + if (value.Contains("Wall")) return 80; + if (value.Contains("Window")) return 70; + + if (value.Contains("Column")) return 60; + if (value.Contains("Structural")) return 60; + + if (value.Contains("Stair")) return 40; + if (value.Contains("Doors")) return 30; + + return 1; + } + + static AABox[] ComputeBoxes(SceneG3d index, MeshG3d[] meshes) + { + var boxes = new List(); + for (var i = 0; i < index.instanceFiles.Length; i++) + { + var m = index.instanceFiles[i]; + var instance = index.instanceIndices[i]; + var mesh = meshes[m]; + boxes.Add(mesh.GetInstanceAABB(instance)); + } + return boxes.ToArray(); + } + + public static byte[] GzipBytes(this byte[] inputBytes) + { + using (var memoryStream = new MemoryStream()) + { + using (var gzipStream = new DeflateStream(memoryStream, CompressionMode.Compress, true)) + { + gzipStream.Write(inputBytes, 0, inputBytes.Length); + } + return memoryStream.ToArray(); + } + } + } + +} diff --git a/src/cs/g3d/temp/Vim.G3dNext.Tests/TestUtils.cs b/src/cs/g3d/temp/Vim.G3dNext.Tests/TestUtils.cs new file mode 100644 index 00000000..7f7322fd --- /dev/null +++ b/src/cs/g3d/temp/Vim.G3dNext.Tests/TestUtils.cs @@ -0,0 +1,113 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Net.Http; +using System.Runtime.CompilerServices; +using System.Threading.Tasks; + +namespace Vim.G3dNext.Tests; + +public static class TestUtils +{ + public static readonly string ProjectFolder = new DirectoryInfo(Properties.Resources.ProjDir.Trim()).FullName; + public static string RootFolder = Path.Combine(ProjectFolder, "..", ".."); + public static string TestInputFolder = Path.Combine(RootFolder, "data", "models"); + public static string TestOutputFolder = Path.Combine(RootFolder, "out"); + + public static async Task DownloadFileAsync(string url) + { + using (var httpClient = new HttpClient()) + { + using (var response = await httpClient.GetAsync(url, HttpCompletionOption.ResponseHeadersRead)) + { + response.EnsureSuccessStatusCode(); + var memoryStream = new MemoryStream(); + await response.Content.CopyToAsync(memoryStream); + memoryStream.Seek(0, SeekOrigin.Begin); + return memoryStream; + } + } + } + + public static string PrepareTestDir([CallerMemberName] string? testName = null) + { + if (testName == null) + throw new ArgumentException(nameof(testName)); + + var testDir = Path.Combine(TestOutputFolder, testName); + + // Prepare the test directory + if (Directory.Exists(testDir)) + Directory.Delete(testDir, true); + Directory.CreateDirectory(testDir); + + return testDir; + } + + public static (long, long) GetMemoryConsumptionAndMSecElapsed(Action action) + { + var time = 0L; + var mem = GetMemoryConsumption( + () => time = GetMSecElapsed(action)); + return (mem, time); + } + + public static long GetMSecElapsed(Action action) + { + var sw = Stopwatch.StartNew(); + action(); + return sw.ElapsedMilliseconds; + } + + /// + /// Creates a directory if needed, or clears all of its contents otherwise + /// + public static string CreateAndClearDirectory(string dirPath) + { + if (!Directory.Exists(dirPath)) + Directory.CreateDirectory(dirPath); + else + DeleteFolderContents(dirPath); + return dirPath; + } + + /// + /// Deletes all contents in a folder + /// + /// + /// https://stackoverflow.com/questions/1288718/how-to-delete-all-files-and-folders-in-a-directory + /// + private static void DeleteFolderContents(string folderPath) + { + var di = new DirectoryInfo(folderPath); + foreach (var dir in di.EnumerateDirectories().AsParallel()) + DeleteFolderAndAllContents(dir.FullName); + foreach (var file in di.EnumerateFiles().AsParallel()) + file.Delete(); + } + + /// + /// Deletes everything in a folder and then the folder. + /// + private static void DeleteFolderAndAllContents(string folderPath) + { + if (!Directory.Exists(folderPath)) + return; + + DeleteFolderContents(folderPath); + Directory.Delete(folderPath); + } + + // NOTE: Calling a function generates additional memory + private static long GetMemoryConsumption(Action action) + { + GC.Collect(); + GC.WaitForPendingFinalizers(); + var memBefore = GC.GetTotalMemory(true); + action(); + GC.Collect(); + GC.WaitForPendingFinalizers(); + return GC.GetTotalMemory(true) - memBefore; + } +} diff --git a/src/cs/g3d/temp/Vim.G3dNext.Tests/Vim.G3dNext.Tests.csproj b/src/cs/g3d/temp/Vim.G3dNext.Tests/Vim.G3dNext.Tests.csproj new file mode 100644 index 00000000..e9e647cf --- /dev/null +++ b/src/cs/g3d/temp/Vim.G3dNext.Tests/Vim.G3dNext.Tests.csproj @@ -0,0 +1,46 @@ + + + + + + net6.0 + enable + + false + + + + + + + + + + + + + + + + + + + + + True + True + Resources.resx + + + + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + + + + diff --git a/src/cs/g3d/temp/Vim.G3dNext.Tests/VimG3dTests.cs b/src/cs/g3d/temp/Vim.G3dNext.Tests/VimG3dTests.cs new file mode 100644 index 00000000..19777128 --- /dev/null +++ b/src/cs/g3d/temp/Vim.G3dNext.Tests/VimG3dTests.cs @@ -0,0 +1,270 @@ +using NUnit.Framework; +using NUnit.Framework.Internal; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using Vim.BFast; +using Vim.LinqArray; +using Vim.G3d; +using Vim.G3dNext.Attributes; +using Vim.Math3d; + +using static Vim.G3dNext.Tests.TestUtils; + +namespace Vim.G3dNext.Tests; + +[TestFixture] +public static class VimG3dTests +{ + [Test] + public static void FileRepackage() + { + //var name = "_MAIN-AEI_HSIB-R20.v1.2.73"; + var name = "residence"; + //var name = "tower"; + var path = $"./{name}.vim"; + + FileUtils.SplitVim(path, name); + } + + [Test] + public static async Task Filter() + { + var file = await DownloadFileAsync("https://vimdevelopment01storage.blob.core.windows.net/samples/residence_nozip.vim"); + var options = new DataFormat.LoadOptions() + { + SkipAssets = true, + SkipEntities = true, + SkipHeader = true, + SkipStrings = true + }; + + var vim = VimScene.LoadVim(file, options); + var bytes = vim.Document.Geometry.WriteToBytes(); + G3DNext.TryRead(bytes, out var g3d); + var next = new VimG3d(g3d); + var instances = Enumerable.Range(1, 1000).ToArray(); + var filtered = next.Filter(instances); + } + + [Test] + public static void AttributeDescriptorTest() + { + var attributeNames = new VimAttributeCollection().AttributeNames; + foreach (var name in attributeNames) + { + // Test that the attribute descriptor parsing works as intended. + var parsed = AttributeDescriptor.TryParse(name, out var desc); + Assert.IsTrue(parsed); + Assert.AreEqual(name, desc.Name); + } + } + + [Test] + public static void TriangleTest() + { + // Serialize a triangle g3d as bytes and read it back. + var vertices = new[] + { + new Vector3(0, 0, 0), + new Vector3(0, 1, 0), + new Vector3(0, 1, 1) + }; + + var indices = new[] { 0, 1, 2 }; + + //var g3d = new G3DBuilder() + // .AddVertices(vertices.ToIArray()) + // .AddIndices(indices.ToIArray()) + // .Add(materialIndices.ToIArray().ToFaceMaterialAttribute()) + // .ToVimG3d(); + var g3d1 = new G3DNext(); + var ac1 = g3d1.AttributeCollection; + ac1.CornersPerFaceAttribute.TypedData = new[] { 3 }; + ac1.VertexAttribute.TypedData = vertices; + ac1.IndexAttribute.TypedData = indices; + + var bytes = g3d1.ToBytes(); + + if (!G3DNext.TryRead(bytes, out var g)) + Assert.Fail("Could not read g3d bytes."); + + Assert.IsNotNull(g); + + var ac2 = g.AttributeCollection; + + Assert.AreEqual(3, ac2.GetVertexCount()); + Assert.AreEqual(3, ac2.GetIndexCount()); + Assert.AreEqual(3, ac2.GetCornersPerFaceCount()); + Assert.AreEqual(0, ac2.GetMeshCount()); + Assert.AreEqual(0, ac2.GetInstanceCount()); + + Assert.AreEqual(vertices, ac2.VertexAttribute.TypedData); + Assert.AreEqual(indices, ac2.IndexAttribute.TypedData); + } + + [Test] + public static void UnexpectedG3dTest() + { + var testDir = PrepareTestDir(); + var input = new FileInfo(Path.Combine(TestInputFolder, "G3D", "unexpected.g3d")); + + using var stream = input.OpenRead(); + + var result = G3DNext.TryRead(stream, out var g3d); + Assert.IsTrue(result); + + var cornerAttribute = g3d.AttributeCollection.Attributes[IndexAttribute.AttributeName]; + Assert.IsNotNull(cornerAttribute); + } + + [Test] + public static void ReadG3dInVimTest() + { + var testDir = PrepareTestDir(); + var inputVim = new FileInfo(Path.Combine(TestInputFolder, "VIM", "Mechanical_Room.r2017.vim")); + + using var stream = inputVim.OpenRead(); + + G3DNext? g3d = null; + stream.ReadBFast((s, name, size) => + { + if (name == "geometry") + G3DNext.TryRead(s, out g3d); + else + stream.Seek(size, SeekOrigin.Current); + + return null; + }); + + Assert.IsNotNull(g3d); + } + + public static G3DNext CreateTestG3d() + { + var g3d = new G3DNext(); + var attrs = g3d.AttributeCollection; + + attrs.CornersPerFaceAttribute.TypedData = new int[] { 3 }; + attrs.VertexAttribute.TypedData = new Vector3[] { Vector3.Zero, Vector3.UnitX, Vector3.UnitY, Vector3.UnitZ }; + attrs.IndexAttribute.TypedData = new int[] { 0, 1, 2, 0, 3, 2, 1, 3, 2 }; + attrs.SubmeshIndexOffsetAttribute.TypedData = new int[] { 0, 3, 6 }; + attrs.SubmeshMaterialAttribute.TypedData = new int[] { 0 }; + attrs.MeshSubmeshOffsetAttribute.TypedData = new int[] { 0 }; + attrs.InstanceTransformAttribute.TypedData = new Matrix4x4[] { Matrix4x4.Identity }; + attrs.InstanceMeshAttribute.TypedData = new int[] { 0 }; + attrs.InstanceParentAttribute.TypedData = new int[] { -1 }; + attrs.MaterialColorAttribute.TypedData = new Vector4[] { new Vector4(0.25f, 0.5f, 0.75f, 1) }; + attrs.MaterialGlossinessAttribute.TypedData = new float[] { .95f }; + attrs.MaterialSmoothnessAttribute.TypedData = new float[] { .5f }; + + g3d.Validate(); + + return g3d; + } + + [Test] + public static void WriteG3dTest() + { + var testDir = PrepareTestDir(); + + var g3d = CreateTestG3d(); + + var g3dFilePath = Path.Combine(testDir!, "test.g3d"); + g3d.Write(g3dFilePath); + + var readResult = G3DNext.TryRead(g3dFilePath, out var readG3d); + Assert.IsTrue(readResult); + + // Compare the buffers. + foreach (var attributeName in readG3d.AttributeCollection.AttributeNames) + { + var attr0 = g3d.AttributeCollection.Attributes[attributeName]; + var attr1 = readG3d.AttributeCollection.Attributes[attributeName]; + Assert.AreEqual(attr0.Data, attr1.Data); + } + } + + [Test] + public static void MergeG3dTest() + { + var testDir = PrepareTestDir(); + + var g3d = CreateTestG3d(); + + var mergedG3d = new[] { g3d, g3d }.Merge(); + + var g3dFilePath = Path.Combine(testDir!, "merged.g3d"); + mergedG3d.Write(g3dFilePath); + + var readResult = G3DNext.TryRead(g3dFilePath, out var readG3d); + Assert.IsTrue(readResult); + + var mac = readG3d.AttributeCollection; + + { + var merged = g3d.AttributeCollection.CornersPerFaceAttribute.TypedData; + Assert.AreEqual(merged, mac.CornersPerFaceAttribute.TypedData); + } + + { + var merged = Enumerable.Repeat(g3d.AttributeCollection.VertexAttribute.TypedData, 2).SelectMany(v => v).ToArray(); + Assert.AreEqual(merged, mac.VertexAttribute.TypedData); + } + + { + var tmp = g3d.AttributeCollection.IndexAttribute.TypedData; + var merged = new[] { tmp, tmp.Select(i => i + g3d.AttributeCollection.GetVertexCount()).ToArray() }.SelectMany(v => v).ToArray(); + Assert.AreEqual(merged, mac.IndexAttribute.TypedData); + } + + { + var tmp = g3d.AttributeCollection.SubmeshIndexOffsetAttribute.TypedData; + var merged = new[] { tmp, tmp.Select(i => i + g3d.AttributeCollection.GetIndexCount()).ToArray() }.SelectMany(v => v).ToArray(); + Assert.AreEqual(merged, mac.SubmeshIndexOffsetAttribute.TypedData); + } + + { + var tmp = g3d.AttributeCollection.SubmeshMaterialAttribute.TypedData; + var merged = new[] { tmp, tmp.Select(i => i + g3d.AttributeCollection.GetMaterialCount()).ToArray() }.SelectMany(v => v).ToArray(); + Assert.AreEqual(merged, mac.SubmeshMaterialAttribute.TypedData); + } + + { + var tmp = g3d.AttributeCollection.MeshSubmeshOffsetAttribute.TypedData; + var merged = new[] { tmp, tmp.Select(i => i + g3d.AttributeCollection.GetSubmeshCount()).ToArray() }.SelectMany(v => v).ToArray(); + Assert.AreEqual(merged, mac.MeshSubmeshOffsetAttribute.TypedData); + } + + { + var merged = Enumerable.Repeat(g3d.AttributeCollection.InstanceTransformAttribute.TypedData, 2).SelectMany(v => v).ToArray(); + Assert.AreEqual(merged, mac.InstanceTransformAttribute.TypedData); + } + + { + var tmp = g3d.AttributeCollection.InstanceMeshAttribute.TypedData; + var merged = new[] { tmp, tmp.Select(i => i + g3d.AttributeCollection.GetMeshCount()).ToArray() }.SelectMany(v => v).ToArray(); + Assert.AreEqual(merged, mac.InstanceMeshAttribute.TypedData); + } + + { + var merged = Enumerable.Repeat(g3d.AttributeCollection.InstanceParentAttribute.TypedData, 2).SelectMany(v => v).ToArray(); + Assert.AreEqual(merged, mac.InstanceParentAttribute.TypedData); + } + + { + var merged = Enumerable.Repeat(g3d.AttributeCollection.MaterialColorAttribute.TypedData, 2).SelectMany(v => v).ToArray(); + Assert.AreEqual(merged, mac.MaterialColorAttribute.TypedData); + } + + { + var merged = Enumerable.Repeat(g3d.AttributeCollection.MaterialGlossinessAttribute.TypedData, 2).SelectMany(v => v).ToArray(); + Assert.AreEqual(merged, mac.MaterialGlossinessAttribute.TypedData); + } + + { + var merged = Enumerable.Repeat(g3d.AttributeCollection.MaterialSmoothnessAttribute.TypedData, 2).SelectMany(v => v).ToArray(); + Assert.AreEqual(merged, mac.MaterialSmoothnessAttribute.TypedData); + } + } +} diff --git a/src/cs/util/Vim.Util.Tests/Properties/Resources.Designer.cs b/src/cs/util/Vim.Util.Tests/Properties/Resources.Designer.cs index 2d371c8f..d31f3de6 100644 --- a/src/cs/util/Vim.Util.Tests/Properties/Resources.Designer.cs +++ b/src/cs/util/Vim.Util.Tests/Properties/Resources.Designer.cs @@ -61,7 +61,7 @@ internal Resources() { } /// - /// Looks up a localized string similar to C:\DEV\vimaec\src\Vim\vim-format\src\cs\util\Vim.Util.Tests\ + /// Looks up a localized string similar to C:\Users\Rober\Desktop\Vim\vim-format\src\cs\util\Vim.Util.Tests\ ///. /// internal static string ProjDir { diff --git a/src/cs/vim-format.sln b/src/cs/vim-format.sln index ba3ae0fe..855d075a 100644 --- a/src/cs/vim-format.sln +++ b/src/cs/vim-format.sln @@ -45,7 +45,21 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vim.Util.Tests", "util\Vim. EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "util", "util", "{A279C2F9-3418-484B-A36E-D1D1C67A0B2D}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Vim.Util.Logging.Serilog", "util\Vim.Util.Logging.Serilog\Vim.Util.Logging.Serilog.csproj", "{6B9E6432-A7BB-4487-905A-0C3117398140}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vim.Util.Logging.Serilog", "util\Vim.Util.Logging.Serilog\Vim.Util.Logging.Serilog.csproj", "{6B9E6432-A7BB-4487-905A-0C3117398140}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vim.G3dNext", "g3d\Vim.G3dNext\Vim.G3dNext.csproj", "{7A3255D6-444D-46B7-8BBD-ABED88C99009}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vim.G3dNext.Attributes", "g3d\Vim.G3dNext.Attributes\Vim.G3dNext.Attributes.csproj", "{43DD1349-03E9-407F-A52C-8CACC7801F3B}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vim.G3dNext.CodeGen", "g3d\Vim.G3dNext.CodeGen\Vim.G3dNext.CodeGen.csproj", "{F0FFC990-6358-4B17-B878-C6CA087CDF3F}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vim.Format.Vimx", "vim\Vim.Format.Vimx\Vim.Format.Vimx.csproj", "{B5C8E733-8D3F-45BD-BBBE-09A9F1965545}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vim.Format.Vimx.Test", "vim\Vim.Vimx.Test\Vim.Format.Vimx.Test.csproj", "{BBF94CBD-CD39-49F5-979A-5C9E52C29330}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Vim.BFastNext", "Vim.BFast.Next\Vim.BFastNext.csproj", "{4854AD71-8023-43DE-AB2F-D5F6DCFE4974}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Vim.BFastNext.Tests", "Vim.BFastNext.Tests\Vim.BFastNext.Tests.csproj", "{3DBA3070-FCB7-405B-9272-F7C112BD92A8}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -117,6 +131,34 @@ Global {6B9E6432-A7BB-4487-905A-0C3117398140}.Debug|Any CPU.Build.0 = Debug|Any CPU {6B9E6432-A7BB-4487-905A-0C3117398140}.Release|Any CPU.ActiveCfg = Release|Any CPU {6B9E6432-A7BB-4487-905A-0C3117398140}.Release|Any CPU.Build.0 = Release|Any CPU + {7A3255D6-444D-46B7-8BBD-ABED88C99009}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7A3255D6-444D-46B7-8BBD-ABED88C99009}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7A3255D6-444D-46B7-8BBD-ABED88C99009}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7A3255D6-444D-46B7-8BBD-ABED88C99009}.Release|Any CPU.Build.0 = Release|Any CPU + {43DD1349-03E9-407F-A52C-8CACC7801F3B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {43DD1349-03E9-407F-A52C-8CACC7801F3B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {43DD1349-03E9-407F-A52C-8CACC7801F3B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {43DD1349-03E9-407F-A52C-8CACC7801F3B}.Release|Any CPU.Build.0 = Release|Any CPU + {F0FFC990-6358-4B17-B878-C6CA087CDF3F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F0FFC990-6358-4B17-B878-C6CA087CDF3F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F0FFC990-6358-4B17-B878-C6CA087CDF3F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F0FFC990-6358-4B17-B878-C6CA087CDF3F}.Release|Any CPU.Build.0 = Release|Any CPU + {B5C8E733-8D3F-45BD-BBBE-09A9F1965545}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B5C8E733-8D3F-45BD-BBBE-09A9F1965545}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B5C8E733-8D3F-45BD-BBBE-09A9F1965545}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B5C8E733-8D3F-45BD-BBBE-09A9F1965545}.Release|Any CPU.Build.0 = Release|Any CPU + {BBF94CBD-CD39-49F5-979A-5C9E52C29330}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BBF94CBD-CD39-49F5-979A-5C9E52C29330}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BBF94CBD-CD39-49F5-979A-5C9E52C29330}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BBF94CBD-CD39-49F5-979A-5C9E52C29330}.Release|Any CPU.Build.0 = Release|Any CPU + {4854AD71-8023-43DE-AB2F-D5F6DCFE4974}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4854AD71-8023-43DE-AB2F-D5F6DCFE4974}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4854AD71-8023-43DE-AB2F-D5F6DCFE4974}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4854AD71-8023-43DE-AB2F-D5F6DCFE4974}.Release|Any CPU.Build.0 = Release|Any CPU + {3DBA3070-FCB7-405B-9272-F7C112BD92A8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3DBA3070-FCB7-405B-9272-F7C112BD92A8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3DBA3070-FCB7-405B-9272-F7C112BD92A8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3DBA3070-FCB7-405B-9272-F7C112BD92A8}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -138,6 +180,13 @@ Global {EC00B2EC-3CF0-43C3-A071-320AD3C355CF} = {A279C2F9-3418-484B-A36E-D1D1C67A0B2D} {F7091670-1059-4F4F-AC3A-0B1DE4A724B5} = {A279C2F9-3418-484B-A36E-D1D1C67A0B2D} {6B9E6432-A7BB-4487-905A-0C3117398140} = {A279C2F9-3418-484B-A36E-D1D1C67A0B2D} + {7A3255D6-444D-46B7-8BBD-ABED88C99009} = {705B8FB2-D707-4527-91FC-0AADEDBA4D80} + {43DD1349-03E9-407F-A52C-8CACC7801F3B} = {705B8FB2-D707-4527-91FC-0AADEDBA4D80} + {F0FFC990-6358-4B17-B878-C6CA087CDF3F} = {705B8FB2-D707-4527-91FC-0AADEDBA4D80} + {B5C8E733-8D3F-45BD-BBBE-09A9F1965545} = {D639C635-01D1-48C4-89B5-1FD70F1AFEE9} + {BBF94CBD-CD39-49F5-979A-5C9E52C29330} = {D639C635-01D1-48C4-89B5-1FD70F1AFEE9} + {4854AD71-8023-43DE-AB2F-D5F6DCFE4974} = {F3260C54-834F-4C74-A3B7-EAB622AFA492} + {3DBA3070-FCB7-405B-9272-F7C112BD92A8} = {F3260C54-834F-4C74-A3B7-EAB622AFA492} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {7D1BF641-26E8-4809-B638-029241C51BE2} diff --git a/src/cs/vim/Vim.Format.Core/SerializableHeader.cs b/src/cs/vim/Vim.Format.Core/SerializableHeader.cs index c1c3a97c..531f46c2 100644 --- a/src/cs/vim/Vim.Format.Core/SerializableHeader.cs +++ b/src/cs/vim/Vim.Format.Core/SerializableHeader.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Globalization; using System.Linq; +using Vim.BFast; using Vim.Util; namespace Vim.Format @@ -9,8 +10,8 @@ namespace Vim.Format public class SerializableHeader { public static readonly SerializableVersion CurrentVimFormatVersion = VimFormatVersion.Current; - - public const string FormatVersionField = "vim"; + + protected const string FormatVersionField = "vim"; public const string IdField = "id"; public const string RevisionField = "revision"; public const string GeneratorField = "generator"; @@ -119,7 +120,7 @@ public static SerializableHeader Parse(string input) { var tokens = line.Split(Separator); var numTokens = tokens.Length; - + // skip empty lines. if (numTokens == 0) continue; @@ -273,5 +274,10 @@ public static string CreateDummyPersistingId() ///
public string PersistingId => CreatePersistingId(Id, Revision); + + public byte[] ToBytes() + { + return ToString().ToBytesUtf8(); + } } } diff --git a/src/cs/vim/Vim.Format.Core/Serializer.cs b/src/cs/vim/Vim.Format.Core/Serializer.cs index 63c9bdaf..08d50e88 100644 --- a/src/cs/vim/Vim.Format.Core/Serializer.cs +++ b/src/cs/vim/Vim.Format.Core/Serializer.cs @@ -172,7 +172,7 @@ public static BFastBuilder CreateBFastBuilder( IBFastComponent geometry) { var bfastBuilder = new BFastBuilder(); - bfastBuilder.Add(BufferNames.Header, header.ToString().ToBytesUtf8().ToBuffer()); + //bfastBuilder.Add(BufferNames.Header, header.ToBytes()); bfastBuilder.Add(BufferNames.Assets, assets ?? Array.Empty()); bfastBuilder.Add(BufferNames.Entities, entityTables.ToBFastBuilder()); bfastBuilder.Add(BufferNames.Strings, stringTable.PackStrings().ToBuffer()); diff --git a/src/cs/vim/Vim.Format.Vimx/FileUtils.cs b/src/cs/vim/Vim.Format.Vimx/FileUtils.cs new file mode 100644 index 00000000..79a9cd95 --- /dev/null +++ b/src/cs/vim/Vim.Format.Vimx/FileUtils.cs @@ -0,0 +1,38 @@ +using System; +using System.IO; +using System.IO.Compression; + +namespace Vim.Format.Vimx +{ + public static class FileUtils + { + public static byte[] Deflate(this byte[] inputBytes) + { + using (var memoryStream = new MemoryStream()) + { + using (var gzipStream = new DeflateStream(memoryStream, CompressionMode.Compress, true)) + { + gzipStream.Write(inputBytes, 0, inputBytes.Length); + } + return memoryStream.ToArray(); + } + } + + public static byte[] Inflate(this byte[] inputBytes) + { + using (var input = new MemoryStream(inputBytes)) + { + using (var output = new MemoryStream()) + { + using (var deflate = new DeflateStream(input, CompressionMode.Decompress, true)) + { + deflate.CopyTo(output); + return output.ToArray(); + } + } + } + + } + + } +} diff --git a/src/cs/vim/Vim.Format.Vimx/G3dMaterials.cs b/src/cs/vim/Vim.Format.Vimx/G3dMaterials.cs new file mode 100644 index 00000000..aafdd775 --- /dev/null +++ b/src/cs/vim/Vim.Format.Vimx/G3dMaterials.cs @@ -0,0 +1,48 @@ +using System.IO; +using Vim.Math3d; +using Vim.G3dNext.Attributes; +using Vim.G3dNext; + +namespace Vim.Format.Vimx +{ + public class G3dMaterials + { + public G3DNext source; + + // materials + public Vector4[] materialColors; + public float[] materialGlossiness; + public float[] materialSmoothness; + + public static G3dMaterials FromArrays( + Vector4[] materialColors, + float[] materialGlossiness, + float[] materialSmoothness) + { + var collection = new MaterialAttributeCollection(); + + collection.MaterialColorAttribute.TypedData = materialColors ?? new Vector4[0]; + collection.MaterialGlossinessAttribute.TypedData = materialGlossiness ?? new float[0]; + collection.MaterialSmoothnessAttribute.TypedData = materialSmoothness ?? new float[0]; + + var g3d = new G3DNext(collection); + return new G3dMaterials(g3d); + } + + public static G3dMaterials FromBFast(BFastNext.BFastNext bfast) + { + var g3d = G3DNext.ReadBFast(bfast); + return new G3dMaterials(g3d); + } + + public G3dMaterials(G3DNext g3d) + { + this.source = g3d; + + // materials + materialColors = g3d.AttributeCollection.MaterialColorAttribute.TypedData; + materialGlossiness = g3d.AttributeCollection.MaterialGlossinessAttribute.TypedData; + materialSmoothness = g3d.AttributeCollection.MaterialSmoothnessAttribute.TypedData; + } + } +} diff --git a/src/cs/vim/Vim.Format.Vimx/G3dMesh.cs b/src/cs/vim/Vim.Format.Vimx/G3dMesh.cs new file mode 100644 index 00000000..af468b7e --- /dev/null +++ b/src/cs/vim/Vim.Format.Vimx/G3dMesh.cs @@ -0,0 +1,255 @@ +using System.Collections.Generic; +using System.IO; +using Vim.Math3d; +using Vim.G3dNext.Attributes; +using Vim.G3dNext; + +namespace Vim.Format.Vimx +{ + public enum MeshSection + { + Opaque, + Transparent + } + + public class G3dMesh + { + public const int POSITION_SIZE = 3; + + public G3DNext source; + + // instances + public int[] instanceNodes; // This field does not get written on purpose. + public Matrix4x4[] instanceTransforms; + + //mesh + public int[] opaqueSubmeshCount; + + //submesh + public int[] submeshIndexOffsets; + public int[] submeshVertexOffsets; + public int[] submeshMaterials; + + public int[] indices; + public Vector3[] positions; + + // materials + public Vector4[] materialColors; + public float[] materialGlossiness; + public float[] materialSmoothness; + + public static G3dMesh FromArrays( + int[] instanceNode, + Matrix4x4[] instanceTransforms, + int meshOpaqueCount, + int[] submeshIndexOffsets, + int[] submeshVertexOffsets, + int[] submeshMaterials, + int[] indices, + Vector3[] vertices) + { + var collection = new MeshAttributeCollection(); + + // instances + collection.MeshInstanceTransformAttribute.TypedData = instanceTransforms ?? new Matrix4x4[0]; + + //mesh + collection.MeshOpaqueSubmeshCountAttribute.TypedData = new int[] { meshOpaqueCount }; + + // submeshes + collection.MeshSubmeshIndexOffsetAttribute.TypedData = submeshIndexOffsets ?? new int[0]; + collection.MeshSubmeshVertexOffsetAttribute.TypedData = submeshVertexOffsets ?? new int[0]; + collection.MeshSubmeshMaterialAttribute.TypedData = submeshMaterials ?? new int[0]; + + // vertices + collection.MeshIndexAttribute.TypedData = indices ?? new int[0]; + collection.MeshVertexAttribute.TypedData = vertices ?? new Vector3[0]; + + var g3d = new G3DNext(collection); + var mesh = new G3dMesh(g3d); + mesh.instanceNodes = instanceNode; + return mesh; + } + + public bool Equals(G3dVim other) + { + // instances + return + MemberwiseEquals(instanceNodes, other.instanceMeshes) && + MemberwiseEquals(instanceTransforms, other.instanceTransforms) && + + //submesh + MemberwiseEquals(submeshIndexOffsets, other.submeshIndexOffsets) && + MemberwiseEquals(submeshMaterials, other.submeshMaterials) && + + MemberwiseEquals(indices, other.indices) && + MemberwiseEquals(positions, other.vertices) && + + // materials + MemberwiseEquals(materialColors, other.materialColors) && + MemberwiseEquals(materialGlossiness, other.materialGlossiness) && + MemberwiseEquals(materialSmoothness, other.materialSmoothness); + + } + + public static bool MemberwiseEquals(T[] array1, T[] array2) + { + if (array1 == null || array2 == null) return array1 == array2; + + if (array1.Length != array2.Length) return false; + + for (var i = 0; i < array1.Length; i++) + { + if (!EqualityComparer.Default.Equals(array1[i], array2[i])) + { + return false; + } + } + + return true; + } + + public G3dMesh(G3DNext g3d) + { + this.source = g3d; + + // instances + instanceTransforms = g3d.AttributeCollection.MeshInstanceTransformAttribute.TypedData; + + // submeshes + opaqueSubmeshCount = g3d.AttributeCollection.MeshOpaqueSubmeshCountAttribute.TypedData; + submeshIndexOffsets = g3d.AttributeCollection.MeshSubmeshIndexOffsetAttribute.TypedData; + submeshVertexOffsets = g3d.AttributeCollection.MeshSubmeshVertexOffsetAttribute.TypedData; + submeshMaterials = g3d.AttributeCollection.MeshSubmeshMaterialAttribute.TypedData; + + // vertices + indices = g3d.AttributeCollection.MeshIndexAttribute.TypedData; + positions = g3d.AttributeCollection.MeshVertexAttribute.TypedData; + } + + public static G3dMesh FromBFast(BFastNext.BFastNext bfast) + { + var g3d = G3DNext.ReadBFast(bfast); + return new G3dMesh(g3d); + } + + public int GetTriangleCount() + { + return GetIndexCount() / 3; + } + + /// + /// The total number of instances. + /// + public int GetInstanceCount() => instanceTransforms?.Length ?? 0; + + /// + /// The total number of submeshes. + /// + public int GetSubmeshCount() => submeshIndexOffsets?.Length ?? 0; + + /// + /// The total number of submeshes. + /// + public int GetSubmeshCount(MeshSection section) + { + var count = GetSubmeshCount(); + if (opaqueSubmeshCount == null) return count; + var opaque = opaqueSubmeshCount[0]; + + return section == MeshSection.Opaque + ? opaque + : count - opaque; + } + + public int GetIndexStart(MeshSection section) + { + if (opaqueSubmeshCount == null) return 0; + if (section == MeshSection.Opaque) return 0; + var opaque = opaqueSubmeshCount[0]; + return GetSubmeshIndexStart(opaque); + } + + public int GetIndexEnd(MeshSection section) + { + if (opaqueSubmeshCount == null) return indices.Length; + if (section == MeshSection.Transparent) return indices.Length; + var opaque = opaqueSubmeshCount[0]; + return GetSubmeshIndexEnd(opaque - 1); + } + + public int GetIndexCount(MeshSection section) + { + return GetIndexEnd(section) - GetIndexStart(section); + } + + /// + /// The total number of indices. + /// + public int GetIndexCount() => indices?.Length ?? 0; + + public int GetVertexStart(MeshSection section) + { + if (opaqueSubmeshCount == null) return 0; + if (submeshVertexOffsets == null) return 0; + if (section == MeshSection.Opaque) return 0; + var opaque = opaqueSubmeshCount[0]; + return GetSubmeshVertexStart(opaque); + } + + public int GetVertexEnd(MeshSection section) + { + if (opaqueSubmeshCount == null) return positions.Length; + if (submeshVertexOffsets == null) return positions.Length; + if (section == MeshSection.Transparent) return positions.Length; + var opaque = opaqueSubmeshCount[0]; + return GetSubmeshVertexEnd(opaque - 1); + } + + public int GetVertexCount(MeshSection section) + { + return GetVertexEnd(section) - GetVertexStart(section); + } + + /// + /// The total number of vertices. + /// + public int GetVertexCount() => (positions?.Length ?? 0); + + + /// + /// The total number of materials. + /// + public int GetMaterialCount() => materialColors?.Length ?? 0; + + public int GetSubmeshIndexStart(int submesh) + { + return submeshIndexOffsets[submesh]; + } + + public int GetSubmeshIndexEnd(int submesh) + { + return submesh + 1 < GetSubmeshCount() ? submeshIndexOffsets[submesh + 1] : GetIndexCount(); + } + + public int GetSubmeshIndexCount(int submesh) + { + return GetSubmeshIndexEnd(submesh) - GetSubmeshIndexStart(submesh); + } + + public int GetSubmeshVertexStart(int submesh) + { + return submeshVertexOffsets[submesh]; + } + + public int GetSubmeshVertexEnd(int submesh) + { + return submesh + 1 < GetSubmeshCount() ? submeshVertexOffsets[submesh + 1] : GetVertexCount(); + } + + public int GetSubmeshVertexCount(int submesh) + { + return GetSubmeshVertexEnd(submesh) - GetSubmeshVertexStart(submesh); + } + } +} diff --git a/src/cs/vim/Vim.Format.Vimx/G3dMeshExtensions.cs b/src/cs/vim/Vim.Format.Vimx/G3dMeshExtensions.cs new file mode 100644 index 00000000..0defaa41 --- /dev/null +++ b/src/cs/vim/Vim.Format.Vimx/G3dMeshExtensions.cs @@ -0,0 +1,85 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Vim.Format.ObjectModel; +using Vim.Math3d; + +namespace Vim.Format.Vimx +{ + public static class G3dMeshExtensions + { + public static AABox GetAABB(this G3dMesh mesh) + { + var box = new AABox(mesh.positions[0], mesh.positions[0]); + for (var p = 1; p < mesh.positions.Length; p++) + { + var pos = mesh.positions[p]; + box = box.Expand(pos); + } + return box; + } + + private static AABox Expand(this AABox box, Vector3 pos) + { + return new AABox( + new Vector3( + Math.Min(box.Min.X, pos.X), + Math.Min(box.Min.Y, pos.Y), + Math.Min(box.Min.Z, pos.Z) + ), + new Vector3( + Math.Max(box.Max.X, pos.X), + Math.Max(box.Max.Y, pos.Y), + Math.Max(box.Max.Z, pos.Z) + ) + ); + } + + public static IEnumerable OrderByBim(this IEnumerable meshes, DocumentModel bim) + { + return meshes.OrderByDescending((m) => ( + GetPriority(GetMeshName(m, bim)), + m.GetAABB().MaxSide) + ); + } + + public static string GetMeshName(this G3dMesh mesh, DocumentModel bim) + { + var node = mesh.instanceNodes[0]; + + if (node < 0 || node >= bim.NodeElementIndex.Count) return ""; + var element = bim.NodeElementIndex[node]; + + if (element < 0 || element >= bim.ElementCategoryIndex.Count) return ""; + var category = bim.ElementCategoryIndex[element]; + + if (category < 0 || category >= bim.CategoryName.Count) return ""; + var name = bim.CategoryName[category]; + + return name; + } + + static int GetPriority(string value) + { + if (string.IsNullOrWhiteSpace(value)) return 0; + + if (value.Contains("Topography")) return 110; + if (value.Contains("Floor")) return 100; + if (value.Contains("Slab")) return 100; + if (value.Contains("Ceiling")) return 90; + if (value.Contains("Roof")) return 90; + + if (value.Contains("Curtain")) return 80; + if (value.Contains("Wall")) return 80; + if (value.Contains("Window")) return 70; + + if (value.Contains("Column")) return 60; + if (value.Contains("Structural")) return 60; + + if (value.Contains("Stair")) return 40; + if (value.Contains("Doors")) return 30; + + return 1; + } + } +} diff --git a/src/cs/vim/Vim.Format.Vimx/G3dScene.cs b/src/cs/vim/Vim.Format.Vimx/G3dScene.cs new file mode 100644 index 00000000..ad4522ea --- /dev/null +++ b/src/cs/vim/Vim.Format.Vimx/G3dScene.cs @@ -0,0 +1,70 @@ +using System.IO; +using Vim.G3dNext.Attributes; +using Vim.Math3d; +using Vim.G3dNext; +using Vim.BFast; +/* +namespace Vim.Format.Vimx +{ + public class G3dScene + { + public G3DNext source; + + // instances + public int[] instanceFiles; + public int[] instanceIndices; + public int[] instanceNodes; + public int[] instanceGroups; + public long[] instanceTags; + public ushort[] instanceFlags; + public Vector3[] instanceMins; + public Vector3[] instanceMaxs; + + //mesh + public int[] meshInstanceCounts; + public int[] meshVertexCounts; + public int[] meshIndexCounts; + + // mesh opaque + public int[] meshOpaqueVertexCounts; + public int[] meshOpaqueIndexCounts; + + public G3dScene() + { + this.source = new G3DNext(); + } + + public G3dScene(G3DNext g3d) + { + this.source = g3d; + + // instances + instanceFiles = g3d.AttributeCollection.InstanceFilesAttribute.TypedData; + instanceIndices = g3d.AttributeCollection.InstanceIndicesAttribute.TypedData; + instanceNodes = g3d.AttributeCollection.InstanceNodesAttribute.TypedData; + instanceGroups = g3d.AttributeCollection.InstanceGroupsAttribute.TypedData; + instanceTags = g3d.AttributeCollection.InstanceTagsAttribute.TypedData; + instanceFlags = g3d.AttributeCollection.InstanceFlagsAttribute.TypedData; + instanceMins = g3d.AttributeCollection.InstanceMinsAttribute.TypedData; + instanceMaxs = g3d.AttributeCollection.InstanceMaxsAttribute.TypedData; + + // meshes + meshInstanceCounts = g3d.AttributeCollection.MeshInstanceCountsAttribute.TypedData; + meshIndexCounts = g3d.AttributeCollection.MeshIndexCountsAttribute.TypedData; + meshVertexCounts = g3d.AttributeCollection.MeshVertexCountsAttribute.TypedData; + + // meshes opaque + meshOpaqueIndexCounts = g3d.AttributeCollection.MeshOpaqueIndexCountsAttribute.TypedData; + meshOpaqueVertexCounts = g3d.AttributeCollection.MeshOpaqueVertexCountsAttribute.TypedData; + } + + public void Write(string path, string name) + { + var p = Path.Combine(path, $"{name}_index.g3d"); + source.ToBFast().Write(p); + } + + public int MeshCount => this.meshInstanceCounts.Length; + } +} +*/ \ No newline at end of file diff --git a/src/cs/vim/Vim.Format.Vimx/G3dVim.cs b/src/cs/vim/Vim.Format.Vimx/G3dVim.cs new file mode 100644 index 00000000..351f5a1a --- /dev/null +++ b/src/cs/vim/Vim.Format.Vimx/G3dVim.cs @@ -0,0 +1,288 @@ +using System; +using System.IO; +using System.Linq; +using Vim.Math3d; +using Vim.G3dNext.Attributes; +using Vim.G3dNext; + +namespace Vim.Format.Vimx +{ + public class G3dVim + { + public G3DNext source; + + // instances + public int[] instanceMeshes; + public Matrix4x4[] instanceTransforms; + public int[] instanceParents; + public ushort[] instanceFlags; + + //mesh + public int[] meshSubmeshOffsets; + + //submesh + public int[] submeshIndexOffsets; + public int[] submeshMaterials; + + public int[] indices; + public Vector3[] vertices; + + // materials + public Vector4[] materialColors; + public float[] materialGlossiness; + public float[] materialSmoothness; + + // shapes + public Vector3[] shapeVertices; + public int[] shapeVertexOffsets; + public Vector4[] shapeColors; + public float[] shapeWidth; + + // Computed fields + public int[] meshVertexOffsets; + + + public G3dVim() + { + this.source = new G3DNext(); + } + public G3dVim(G3DNext g3d) + { + this.source = g3d; + + // instances + instanceMeshes = g3d.AttributeCollection.InstanceMeshAttribute.TypedData; + instanceTransforms = g3d.AttributeCollection.InstanceTransformAttribute.TypedData; + instanceParents = g3d.AttributeCollection.InstanceParentAttribute.TypedData; + instanceFlags = g3d.AttributeCollection.InstanceFlagsAttribute.TypedData; + if (instanceFlags.Length < instanceMeshes.Length) + { + instanceFlags = new ushort[instanceMeshes.Length]; + } + + // meshes + meshSubmeshOffsets = g3d.AttributeCollection.MeshSubmeshOffsetAttribute.TypedData; + + // submeshes + submeshIndexOffsets = g3d.AttributeCollection.SubmeshIndexOffsetAttribute.TypedData; + submeshMaterials = g3d.AttributeCollection.SubmeshMaterialAttribute.TypedData; + + // vertices + indices = g3d.AttributeCollection.IndexAttribute.TypedData; + vertices = g3d.AttributeCollection.VertexAttribute.TypedData; + + // materials + materialColors = g3d.AttributeCollection.MaterialColorAttribute.TypedData; + materialGlossiness = g3d.AttributeCollection.MaterialGlossinessAttribute.TypedData; + materialSmoothness = g3d.AttributeCollection.MaterialSmoothnessAttribute.TypedData; + + // shapes + shapeVertexOffsets = g3d.AttributeCollection.ShapeVertexOffsetAttribute.TypedData; + shapeVertices = g3d.AttributeCollection.ShapeVertexAttribute.TypedData; + shapeColors = g3d.AttributeCollection.ShapeColorAttribute.TypedData; + shapeWidth = g3d.AttributeCollection.ShapeWidthAttribute.TypedData; + + // computed fields + meshVertexOffsets = ComputeMeshVertexOffsets(); + } + + public bool Equals(G3dVim other) + { + // instances + return + instanceMeshes.SequenceEqual(other.instanceMeshes) && + instanceTransforms.SequenceEqual(other.instanceTransforms) && + instanceParents.SequenceEqual(other.instanceParents) && + instanceFlags.SequenceEqual(other.instanceFlags) && + + //mesh + meshSubmeshOffsets.SequenceEqual(other.meshSubmeshOffsets) && + + //submesh + submeshIndexOffsets.SequenceEqual(other.submeshIndexOffsets) && + submeshMaterials.SequenceEqual(other.submeshMaterials) && + + indices.SequenceEqual(other.indices) && + vertices.SequenceEqual(other.vertices) && + + // materials + materialColors.SequenceEqual(other.materialColors) && + materialGlossiness.SequenceEqual(other.materialGlossiness) && + materialSmoothness.SequenceEqual(other.materialSmoothness) && + + // shapes + shapeVertices.SequenceEqual(other.shapeVertices) && + shapeVertexOffsets.SequenceEqual(other.shapeVertexOffsets) && + shapeColors.SequenceEqual(shapeColors) && + shapeWidth.SequenceEqual(other.shapeWidth); + } + + public G3dMaterials ToG3dMaterials() + { + return G3dMaterials.FromArrays( + materialColors, + materialGlossiness, + materialSmoothness + ); + } + + public static G3dVim FromBFast2(BFastNext.BFastNext bfast) + { + var next = G3DNext.ReadBFast(bfast); + return new G3dVim(next); + } + + public static G3dVim FromPath2(string path) + { + var next = G3DNext.ReadBFast(path); + return new G3dVim(next); + } + + public static G3dVim ReadFromVim(string vimPath) + { + var file = new FileStream(vimPath, FileMode.Open); + var bfast = new BFastNext.BFastNext(file); + var geometry = bfast.GetBFast("geometry"); + return FromBFast(geometry); + } + + public static G3dVim FromBFast(BFastNext.BFastNext bfast) + { + var g3d = G3DNext.ReadBFast(bfast); + return new G3dVim(g3d); + } + + private int[] ComputeMeshVertexOffsets() + { + var result = new int[GetMeshCount()]; + for (var m = 0; m < result.Length; m++) + { + var min = int.MaxValue; + var start = GetMeshIndexStart(m); + var end = GetMeshIndexEnd(m); + for (var i = start; i < end; i++) + { + min = Math.Min(min, indices[i]); + } + result[m] = min; + } + return result; + } + + public int GetTriangleCount() + { + return GetIndexCount() / 3; + } + + /// + /// The total number of instances. + /// + public int GetInstanceCount() => instanceTransforms?.Length ?? 0; + + #region meshes + /// + /// The total number of meshes. + /// + public int GetMeshCount() => meshSubmeshOffsets?.Length ?? 0; + + public int GetMeshIndexStart(int mesh) + { + var submesh = GetMeshSubmeshStart(mesh); + return GetSubmeshIndexStart(submesh); + } + + public int GetMeshIndexEnd(int mesh) + { + var submesh = GetMeshSubmeshEnd(mesh) - 1; + return GetSubmeshIndexEnd(submesh); + } + + public int GetMeshIndexCount(int mesh) + { + return GetMeshIndexEnd(mesh) - GetMeshIndexStart(mesh); + } + + public int GetMeshVertexStart(int mesh) + { + return meshVertexOffsets[mesh]; + } + + public int GetMeshVertexEnd(int mesh) + { + return mesh + 1 < GetMeshCount() ? meshVertexOffsets[mesh + 1] : vertices.Length; + } + + public int GetMeshVertexCount(int mesh) + { + return GetMeshVertexEnd(mesh) - GetMeshVertexStart(mesh); + } + + public int GetMeshSubmeshStart(int mesh) + { + return meshSubmeshOffsets[mesh]; + } + + public int GetMeshSubmeshEnd(int mesh) + { + return mesh + 1 < GetMeshCount() + ? meshSubmeshOffsets[mesh + 1] + : GetSubmeshCount(); + } + + public int GetMeshSubmeshCount(int mesh) + { + return GetMeshSubmeshEnd(mesh) - GetMeshSubmeshStart(mesh); + } + + #endregion + + #region submesh + + /// + /// The total number of submeshes. + /// + public int GetSubmeshCount() => submeshIndexOffsets?.Length ?? 0; + + public int GetSubmeshIndexStart(int submesh) + { + return submeshIndexOffsets[submesh]; + } + + public int GetSubmeshIndexEnd(int submesh) + { + return submesh + 1 < GetSubmeshCount() ? submeshIndexOffsets[submesh + 1] : GetIndexCount(); + } + + public int GetSubmeshIndexCount(int submesh) + { + return GetSubmeshIndexEnd(submesh) - GetSubmeshIndexStart(submesh); + } + + #endregion + + /// + /// The total number of indices. + /// + public int GetIndexCount() => indices?.Length ?? 0; + + /// + /// The total number of vertices. + /// + public int GetVertexCount() => vertices?.Length ?? 0; + + /// + /// The total number of materials. + /// + public int GetMaterialCount() => materialColors?.Length ?? 0; + + /// + /// The total number of shapes. + /// + public int GetShapeCount() => shapeVertexOffsets?.Length ?? 0; + + /// + /// The total number of shape vertices. + /// + public int GetShapeVertexCount() => shapeVertices?.Length ?? 0; + } +} diff --git a/src/cs/vim/Vim.Format.Vimx/G3dVimFilter.cs b/src/cs/vim/Vim.Format.Vimx/G3dVimFilter.cs new file mode 100644 index 00000000..9a6f55b1 --- /dev/null +++ b/src/cs/vim/Vim.Format.Vimx/G3dVimFilter.cs @@ -0,0 +1,152 @@ +using System.Collections.Generic; +using Vim.Math3d; + +namespace Vim.Format.Vimx +{ + internal static class G3dVimFilter + { + /// + /// Returns a new G3d which only contains the instances provided as filter. + /// Delete this eventually if it finds no usage. + /// Was developped for server side file splitting spike. + /// + public static G3dVim Filter(this G3dVim g3d, int[] instances) + { + var vim = new G3dVim(); + var instanceSet = new HashSet(instances); + + // Instances + var instanceMeshes = new int[instances.Length]; + var instanceFlags = new ushort[instances.Length]; + var instanceTransforms = new Matrix4x4[instances.Length]; + var instance_i = 0; + for (var i = 0; i < g3d.GetInstanceCount(); i++) + { + if (!instanceSet.Contains(i)) continue; + instanceFlags[instance_i] = g3d.instanceFlags[i]; + instanceMeshes[instance_i] = g3d.instanceMeshes[i]; + instanceTransforms[instance_i] = g3d.instanceTransforms[i]; + instance_i++; + } + + // Meshes + var meshMap = new Dictionary(); + var meshSet = new HashSet(instanceMeshes); + meshSet.Remove(-1); + var meshSubmeshes = new int[meshSet.Count]; + + var last = -1; + var mesh_i = 0; + for (var i = 0; i < g3d.GetMeshCount(); i++) + { + if (!meshSet.Contains(i)) continue; + + var offset = mesh_i > 0 ? meshSubmeshes[mesh_i - 1] : 0; + var lastCount = last < 0 ? 0 : g3d.GetMeshSubmeshCount(last); + meshSubmeshes[mesh_i] = lastCount + offset; + meshMap[i] = mesh_i; + last = i; + mesh_i++; + } + + // Remap Instance Meshes + for (var i = 0; i < instanceMeshes.Length; i++) + { + instanceMeshes[i] = meshMap.TryGetValue(instanceMeshes[i], out var value) ? value : -1; + } + + // Mesh Attributes Count + var submeshCount = 0; + var positionCount = 0; + var indiceCount = 0; + for (var m = 0; m < g3d.GetMeshCount(); m++) + { + if (!meshSet.Contains(m)) continue; + positionCount += g3d.GetMeshVertexCount(m); + indiceCount += g3d.GetMeshIndexCount(m); + submeshCount += g3d.GetMeshSubmeshCount(m); + } + + // Meshes + var indices_i = 0; + var positions_i = 0; + var submesh_i = 0; + var submeshOffset = 0; + var meshOffset = 0; + var submeshIndexOffsets = new int[submeshCount]; + var submeshMaterials = new int[submeshCount]; + var positions = new Vector3[positionCount]; + var indices = new int[indiceCount]; + + for (var mesh = 0; mesh < g3d.GetMeshCount(); mesh++) + { + if (!meshSet.Contains(mesh)) continue; + + // submeshes + var subStart = g3d.GetMeshSubmeshStart(mesh); + var subEnd = g3d.GetMeshSubmeshEnd(mesh); + + for (var j = subStart; j < subEnd; j++) + { + var start = g3d.submeshIndexOffsets[subStart]; + submeshIndexOffsets[submesh_i] = g3d.submeshIndexOffsets[j] - start + submeshOffset; + submeshMaterials[submesh_i] = g3d.submeshMaterials[j]; + submesh_i++; + } + submeshOffset += g3d.GetMeshIndexCount(mesh); + + // indices + var indexStart = g3d.GetMeshIndexStart(mesh); + var indexEnd = g3d.GetMeshIndexEnd(mesh); + for (var j = indexStart; j < indexEnd; j++) + { + indices[indices_i++] = g3d.indices[j] - g3d.GetMeshVertexStart(mesh) + meshOffset; + } + meshOffset += g3d.GetMeshVertexCount(mesh); + + // vertices + var vertexStart = g3d.GetMeshVertexStart(mesh); + var vertexEnd = g3d.GetMeshVertexEnd(mesh); + for (var j = vertexStart; j < vertexEnd; j++) + { + positions[positions_i++] = g3d.vertices[j]; + } + } + + // Material Colors + var color_i = 0; + var materialSet = new HashSet(submeshMaterials); + var materialMap = new Dictionary(); + var materialColors = new Vector4[materialSet.Count]; + + for (var i = 0; i < g3d.GetMaterialCount(); i++) + { + if (materialSet.Contains(i)) + { + materialMap[i] = color_i; + materialColors[color_i] = g3d.materialColors[i]; + color_i++; + } + } + + // Remap Submesh Materials + for (var i = 0; i < submeshMaterials.Length; i++) + { + submeshMaterials[i] = submeshMaterials[i] < 0 ? -1 : materialMap[submeshMaterials[i]]; + } + + return new G3dVim() + { + instanceFlags= instanceFlags, + instanceMeshes= instanceMeshes, + instanceTransforms= instanceTransforms, + meshSubmeshOffsets= meshSubmeshes, + submeshIndexOffsets= submeshIndexOffsets, + submeshMaterials= submeshMaterials, + indices= indices, + vertices= positions, + materialColors= materialColors + }; + } + } +} \ No newline at end of file diff --git a/src/cs/vim/Vim.Format.Vimx/G3dVimMeshes.cs b/src/cs/vim/Vim.Format.Vimx/G3dVimMeshes.cs new file mode 100644 index 00000000..6cdb773e --- /dev/null +++ b/src/cs/vim/Vim.Format.Vimx/G3dVimMeshes.cs @@ -0,0 +1,162 @@ +using System.Collections.Generic; +using System.Linq; +using Vim.LinqArray; +using Vim.Util; +using Vim.BFast; +using Vim.Math3d; + +namespace Vim.Format.Vimx +{ + internal static class G3dVimMeshes + { + /// + /// Splits a g3dVim into a sequence of vimx getMesh. + /// + public static IEnumerable ToG3dMeshes(this G3dVim g3d) + { + var meshInstances = g3d.GetMeshInstances(); + + return Enumerable.Range(0, g3d.GetMeshCount()) + .Select(m => g3d.GetMesh(m, meshInstances[m])) + .WhereNotNull(); + } + + private static List[] GetMeshInstances(this G3dVim g3d) + { + var result = new List[g3d.GetMeshCount()]; + for (var i = 0; i < result.Length; i++) + { + result[i] = new List(); + } + + for (var i = 0; i < g3d.instanceMeshes.Length; i++) + { + var mesh = g3d.instanceMeshes[i]; + if (mesh >= 0) + { + result[mesh].Add(i); + } + } + + return result; + } + + private static G3dMesh GetMesh(this G3dVim g3d, int mesh, List instances) + { + if (instances.Count == 0) + { + return null; + } + var instanceNodes = new int[instances.Count]; + var instanceTransforms = new Matrix4x4[instances.Count]; + var instanceFlags = new ushort[instances.Count]; + + var submeshIndexOffsets = new List(); + var submeshVertexOffsets = new List(); + var submeshMaterials = new List(); + var indices = new List(); + var vertices = new List(); + + // instances + for (var i = 0; i < instances.Count; i++) + { + var instance = instances[i]; + instanceNodes[i] = instances[i]; + instanceTransforms[i] = g3d.instanceTransforms[instance]; + instanceFlags[i] = g3d.instanceFlags[instance]; + } + + var opaqueCount = AppendSubmeshes( + g3d, + mesh, + false, + submeshIndexOffsets, + submeshVertexOffsets, + submeshMaterials, + indices, + vertices + ); + + AppendSubmeshes( + g3d, + mesh, + true, + submeshIndexOffsets, + submeshVertexOffsets, + submeshMaterials, + indices, + vertices + ); + + var result = G3dMesh.FromArrays( + instanceNodes.ToArray(), + instanceTransforms.ToArray(), + opaqueCount, + submeshIndexOffsets.ToArray(), + submeshVertexOffsets.ToArray(), + submeshMaterials.ToArray(), + indices.ToArray(), + vertices.ToArray() + ); + return result; + } + + private static int AppendSubmeshes( + G3dVim g3d, + int mesh, + bool transparent, + List submeshIndexOffsets, + List submeshVertexOffsets, + List submeshMaterials, + List indices, + List vertices + ) + { + var subStart = g3d.GetMeshSubmeshStart(mesh); + var subEnd = g3d.GetMeshSubmeshEnd(mesh); + var count = 0; + for (var sub = subStart; sub < subEnd; sub++) + { + var currentMat = g3d.submeshMaterials[sub]; + var color = currentMat > 0 ? g3d.materialColors[currentMat] : Vector4.One; + var accept = color.W < 1 == transparent; + + if (!accept) continue; + count++; + submeshMaterials.Add(currentMat); + submeshIndexOffsets.Add(indices.Count); + submeshVertexOffsets.Add(vertices.Count); + var (subIndices, subVertices) = g3d.GetSubmesh(sub); + indices.AddRange(subIndices.Select(i => i + vertices.Count)); + vertices.AddRange(subVertices); + } + return count; + } + + private static (List, List) GetSubmesh(this G3dVim g3d, int submesh) + { + var indices = new List(); + var vertices = new List(); + var dict = new Dictionary(); + + var start = g3d.GetSubmeshIndexStart(submesh); + var end = g3d.GetSubmeshIndexEnd(submesh); + + for (var i = start; i < end; i++) + { + var v = g3d.indices[i]; + if (dict.ContainsKey(v)) + { + indices.Add(dict[v]); + } + else + { + indices.Add(vertices.Count); + dict.Add(v, vertices.Count); + vertices.Add(g3d.vertices[v]); + } + } + return (indices, vertices); + } + } +} \ No newline at end of file diff --git a/src/cs/vim/Vim.Format.Vimx/G3dVimScene.cs b/src/cs/vim/Vim.Format.Vimx/G3dVimScene.cs new file mode 100644 index 00000000..ecf8c361 --- /dev/null +++ b/src/cs/vim/Vim.Format.Vimx/G3dVimScene.cs @@ -0,0 +1,99 @@ +using System.Collections.Generic; +using System.Linq; +using Vim.BFast; +using Vim.Format.ObjectModel; +using Vim.G3dNext.Attributes; +using Vim.LinqArray; +using Vim.Math3d; + +namespace Vim.Format.Vimx +{ + public static class G3dVimScene + { + /// + /// + /// + public static G3dScene2 ToG3dScene(this G3dVim g3d, DocumentModel bim, G3dMesh[] meshes) + { + var scene = new G3dScene2(); + var nodeElements = bim.NodeElementIndex.ToArray(); + var nodeElementIds = nodeElements + .Select(n => n < 0 || n > bim.ElementId.Count + ? -1 + : bim.ElementId[n] + ).ToArray(); + + (scene.InstanceFiles, scene.InstanceIndices, scene.InstanceNodes) = meshes.GetInstanceFiles(); + scene.InstanceGroups = scene.InstanceNodes.Select(n => nodeElements[n]).ToArray(); + scene.InstanceTags = scene.InstanceNodes.Select(n => nodeElementIds[n]).ToArray(); + (scene.InstanceMins, scene.InstanceMaxs) = ComputeBoundingBoxes(meshes, scene.InstanceFiles, scene.InstanceIndices); + scene.InstanceFlags = scene.InstanceNodes.Select(i => g3d.instanceFlags[i]).ToArray(); + + // meshes + scene.MeshInstanceCounts = new int[meshes.Length]; + scene.MeshIndexCounts = new int[meshes.Length]; + scene.MeshVertexCounts = new int[meshes.Length]; + scene.MeshOpaqueIndexCounts = new int[meshes.Length]; + scene.MeshOpaqueVertexCounts = new int[meshes.Length]; + var opaqueVertices = new int[meshes.Length]; + + for (var i = 0; i < meshes.Length; i++) + { + var mesh = meshes[i]; + scene.MeshInstanceCounts[i] = mesh.GetInstanceCount(); + scene.MeshIndexCounts[i] = mesh.GetIndexCount(); + scene.MeshVertexCounts[i] = mesh.GetVertexCount(); + scene.MeshOpaqueIndexCounts[i] = mesh.GetIndexCount(MeshSection.Opaque); + opaqueVertices[i] = mesh.GetVertexCount(MeshSection.Opaque); + } + return scene; + } + + private static (Vector3[] min, Vector3[] max) ComputeBoundingBoxes(G3dMesh[] meshes, int[] instanceFiles, int[] instanceIndices) + { + var instanceMins = new Vector3[instanceFiles.Length]; + var instanceMaxs = new Vector3[instanceFiles.Length]; + for (var i = 0; i < instanceFiles.Length; i++) + { + var file = instanceFiles[i]; + var index = instanceIndices[i]; + + var min = Vector3.MaxValue; + var max = Vector3.MinValue; + var mesh = meshes[file]; + var vertexCount = mesh.GetVertexCount(); + for (var j = 0; j < vertexCount; j++) + { + var pos = mesh.positions[j]; + var matrix = mesh.instanceTransforms[index]; + var pos2 = pos.Transform(matrix); + min = min.Min(pos2); + max = max.Max(pos2); + } + instanceMins[i] = min; + instanceMaxs[i] = max; + } + return (instanceMins, instanceMaxs); + } + + private static (int[], int[], int[]) GetInstanceFiles(this G3dMesh[] meshes) + { + var instanceFiles = new List(); + var instanceIndices = new List(); + var instanceNodes = new List(); + + // Associate intances to meshes + for (var i = 0; i < meshes.Length; i++) + { + var mesh = meshes[i]; + for (var j = 0; j < mesh.instanceNodes.Length; j++) + { + instanceFiles.Add(i); + instanceIndices.Add(j); + instanceNodes.Add(mesh.instanceNodes[j]); + } + } + return (instanceFiles.ToArray(), instanceIndices.ToArray(), instanceNodes.ToArray()); + } + } +} diff --git a/src/cs/vim/Vim.Format.Vimx/Vim.Format.Vimx.csproj b/src/cs/vim/Vim.Format.Vimx/Vim.Format.Vimx.csproj new file mode 100644 index 00000000..9831295a --- /dev/null +++ b/src/cs/vim/Vim.Format.Vimx/Vim.Format.Vimx.csproj @@ -0,0 +1,20 @@ + + + + netstandard2.0 + + + + + + + + + + + + + + + + diff --git a/src/cs/vim/Vim.Format.Vimx/Vimx.cs b/src/cs/vim/Vim.Format.Vimx/Vimx.cs new file mode 100644 index 00000000..5c78a200 --- /dev/null +++ b/src/cs/vim/Vim.Format.Vimx/Vimx.cs @@ -0,0 +1,85 @@ +using System.Collections.Generic; +using System.Linq; +using Vim.BFastNext; +using Vim.Format.ObjectModel; +using Vim.G3dNext.Attributes; + +namespace Vim.Format.Vimx +{ + public static class BufferNames + { + public const string Header = Format.BufferNames.Header; + public const string Scene = "scene"; + public const string Materials = "materials"; + public static string Mesh(int mesh) => $"mesh_{mesh}"; + } + + public class Vimx + { + public VimxHeader header; + public G3dScene2 scene; + public G3dMaterials materials; + public G3dMesh[] meshes; + + Vimx(VimxHeader header, G3dScene2 scene, G3dMaterials materials, G3dMesh[] meshes) + { + this.header = header; + this.scene = scene; + this.materials = materials; + this.meshes = meshes; + } + + public static Vimx FromVim(string vimPath) + { + var vim = VimScene.LoadVim(vimPath, new Format.LoadOptions() + { + SkipAssets = true, + SkipGeometry = true, + }); + var g3d = G3dVim.ReadFromVim(vimPath); + return FromVim(g3d, vim.DocumentModel); + } + + public static Vimx FromVim(G3dVim g3d, DocumentModel bim) + { + var meshes = g3d.ToG3dMeshes().OrderByBim(bim).ToArray(); + var scene = g3d.ToG3dScene(bim, meshes); + var materials = g3d.ToG3dMaterials(); + var header = VimxHeader.CreateDefault(); + return new Vimx(header, scene, materials, meshes); + } + + public static Vimx FromBFast(BFastNext.BFastNext bfast) + { + var headerBytes = bfast.GetArray("header"); + var header = VimxHeader.FromBytes(headerBytes); + + var bfastScene = bfast.GetBFast("scene", inflate: true); + var scene = new G3dScene2(bfastScene); + + var bfastMaterials = bfast.GetBFast("materials", inflate: true); + var materials = G3dMaterials.FromBFast(bfastMaterials); + + var meshes = Enumerable.Range(0, scene.MeshIndexCounts.Length).Select(i => + { + var bfastMesh = bfast.GetBFast(BufferNames.Mesh(i), inflate: true); + return G3dMesh.FromBFast(bfastMesh); + }).ToArray(); + + return new Vimx(header, scene, materials, meshes); + } + + public static Vimx FromPath(string path) + => path.ReadBFast(FromBFast); + + public void Write(string path) + { + var bfast = new BFastNext.BFastNext(); + bfast.AddArray(BufferNames.Header, header.ToBytes()); + bfast.SetBFast(BufferNames.Scene, scene.source.ToBFast(), deflate: true); + bfast.SetBFast(BufferNames.Materials, materials.source.ToBFast(), deflate: true); + bfast.SetBFast(BufferNames.Mesh, meshes.Select(m => m.source.ToBFast()), deflate: true); + bfast.Write(path); + } + } +} diff --git a/src/cs/vim/Vim.Format.Vimx/VimxHeader.cs b/src/cs/vim/Vim.Format.Vimx/VimxHeader.cs new file mode 100644 index 00000000..fe8fdd20 --- /dev/null +++ b/src/cs/vim/Vim.Format.Vimx/VimxHeader.cs @@ -0,0 +1,37 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using Vim.BFast; +using Vim.Util; + +namespace Vim.Format.Vimx +{ + public class VimxHeader : SerializableHeader + { + new protected const string FormatVersionField = "vimx"; + public VimxHeader(string generator, SerializableVersion schema, string versionString, IReadOnlyDictionary values = null) : base(generator, schema, versionString, values) + { + } + + public VimxHeader(SerializableHeader header) : this(header.Generator, header.Schema, header.FileFormatVersion.ToString()) + { + + } + + public static VimxHeader CreateDefault() + { + return new VimxHeader( + "Vim.Vimx.Converter", + CurrentVimFormatVersion, + CurrentVimFormatVersion.ToString() + ); + } + + public static VimxHeader FromBytes(byte[] bytes) + { + var str = Encoding.UTF8.GetString(bytes); + return new VimxHeader(Parse(str)); + } + } +} diff --git a/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs b/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs index 0d744a39..48fb2f24 100644 --- a/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs +++ b/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs @@ -165,6 +165,11 @@ private IStep[] GetInitSteps(bool inParallel) private void CreateMeshes(bool inParallel) { + if (_SerializableDocument.Geometry == null) + { + return; + } + var srcGeo = _SerializableDocument.Geometry; var tmp = srcGeo?.Meshes.Select(ToIMesh); Meshes = (tmp == null) @@ -176,18 +181,33 @@ private void CreateMeshes(bool inParallel) private void CreateShapes(bool inParallel) { + if (_SerializableDocument.Geometry == null) + { + return; + } + var r = _SerializableDocument.Geometry.Shapes.Select((s, i) => new VimShape(this, i)); VimShapes = inParallel ? r.EvaluateInParallel() : r.Evaluate(); } private void CreateScene(bool inParallel) { + if (_SerializableDocument.Geometry == null) + { + return; + } + VimNodes = CreateVimSceneNodes(this, _SerializableDocument.Geometry, inParallel); Nodes = VimNodes.Select(n => n as ISceneNode); } private void CreateMaterials(bool inParallel) { + if (_SerializableDocument.Geometry == null) + { + return; + } + var query = _SerializableDocument.Geometry.Materials.Select(m => new VimMaterial(m) as IMaterial); Materials = inParallel ? query.EvaluateInParallel() : query.Evaluate(); } diff --git a/src/cs/vim/Vim.Vimx.Test/TestUtils.cs b/src/cs/vim/Vim.Vimx.Test/TestUtils.cs new file mode 100644 index 00000000..f995dc4e --- /dev/null +++ b/src/cs/vim/Vim.Vimx.Test/TestUtils.cs @@ -0,0 +1,124 @@ +using System.Diagnostics; +using System.Runtime.CompilerServices; +using Vim.G3dNext.Attributes; +using Vim.Math3d; +using Vim.Util.Tests; + +namespace Vim.G3dNext.Tests +{ + public static class TestUtils + { + public static readonly string ProjectFolder = VimFormatRepoPaths.ProjDir; + public static string RootFolder = Path.Combine(ProjectFolder, "..", ".."); + public static string TestInputFolder = Path.Combine(RootFolder, "data"); + public static string TestOutputFolder = Path.Combine(RootFolder, "out"); + public static string ResidencePath = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); + + /// + /// Deletes and/or creates a folder for given test case name. + /// + public static string PrepareTestDir([CallerMemberName] string testName = null) + { + if (testName == null) + throw new ArgumentException(nameof(testName)); + + var testDir = Path.Combine(TestOutputFolder, testName); + + // Prepare the test directory + if (Directory.Exists(testDir)) + Directory.Delete(testDir, true); + Directory.CreateDirectory(testDir); + + return testDir; + } + + public static (long, long) GetMemoryConsumptionAndMSecElapsed(Action action) + { + var time = 0L; + var mem = GetMemoryConsumption( + () => time = GetMSecElapsed(action)); + return (mem, time); + } + + public static long GetMSecElapsed(Action action) + { + var sw = Stopwatch.StartNew(); + action(); + return sw.ElapsedMilliseconds; + } + + /// + /// Creates a directory if needed, or clears all of its contents otherwise + /// + public static string CreateAndClearDirectory(string dirPath) + { + if (!Directory.Exists(dirPath)) + Directory.CreateDirectory(dirPath); + else + DeleteFolderContents(dirPath); + return dirPath; + } + + /// + /// Deletes all contents in a folder + /// + /// + /// https://stackoverflow.com/questions/1288718/how-to-delete-all-files-and-folders-in-a-directory + /// + private static void DeleteFolderContents(string folderPath) + { + var di = new DirectoryInfo(folderPath); + foreach (var dir in di.EnumerateDirectories().AsParallel()) + DeleteFolderAndAllContents(dir.FullName); + foreach (var file in di.EnumerateFiles().AsParallel()) + file.Delete(); + } + + /// + /// Deletes everything in a folder and then the folder. + /// + private static void DeleteFolderAndAllContents(string folderPath) + { + if (!Directory.Exists(folderPath)) + return; + + DeleteFolderContents(folderPath); + Directory.Delete(folderPath); + } + + // NOTE: Calling a function generates additional memory + private static long GetMemoryConsumption(Action action) + { + GC.Collect(); + GC.WaitForPendingFinalizers(); + var memBefore = GC.GetTotalMemory(true); + action(); + GC.Collect(); + GC.WaitForPendingFinalizers(); + return GC.GetTotalMemory(true) - memBefore; + } + + public static G3DNext CreateTestG3d() + { + var g3d = new G3DNext(); + var attrs = g3d.AttributeCollection; + + attrs.CornersPerFaceAttribute.TypedData = new int[] { 3 }; + attrs.VertexAttribute.TypedData = new Vector3[] { Vector3.Zero, Vector3.UnitX, Vector3.UnitY, Vector3.UnitZ }; + attrs.IndexAttribute.TypedData = new int[] { 0, 1, 2, 0, 3, 2, 1, 3, 2 }; + attrs.SubmeshIndexOffsetAttribute.TypedData = new int[] { 0, 3, 6 }; + attrs.SubmeshMaterialAttribute.TypedData = new int[] { 0 }; + attrs.MeshSubmeshOffsetAttribute.TypedData = new int[] { 0 }; + attrs.InstanceTransformAttribute.TypedData = new Matrix4x4[] { Matrix4x4.Identity }; + attrs.InstanceMeshAttribute.TypedData = new int[] { 0 }; + attrs.InstanceParentAttribute.TypedData = new int[] { -1 }; + attrs.MaterialColorAttribute.TypedData = new Vector4[] { new Vector4(0.25f, 0.5f, 0.75f, 1) }; + attrs.MaterialGlossinessAttribute.TypedData = new float[] { .95f }; + attrs.MaterialSmoothnessAttribute.TypedData = new float[] { .5f }; + + g3d.Validate(); + + return g3d; + } + } +} diff --git a/src/cs/vim/Vim.Vimx.Test/Vim.Format.Vimx.Test.csproj b/src/cs/vim/Vim.Vimx.Test/Vim.Format.Vimx.Test.csproj new file mode 100644 index 00000000..d918e4f3 --- /dev/null +++ b/src/cs/vim/Vim.Vimx.Test/Vim.Format.Vimx.Test.csproj @@ -0,0 +1,26 @@ + + + + net6.0 + enable + enable + + false + true + + + + + + + + + + + + + + + + + diff --git a/src/cs/vim/Vim.Vimx.Test/VimG3dTests.cs b/src/cs/vim/Vim.Vimx.Test/VimG3dTests.cs new file mode 100644 index 00000000..12380f2b --- /dev/null +++ b/src/cs/vim/Vim.Vimx.Test/VimG3dTests.cs @@ -0,0 +1,197 @@ +using NUnit.Framework; +using NUnit.Framework.Internal; +using Vim.BFast; +using Vim.Format.Vimx; +using Vim.G3dNext.Attributes; +using Vim.Math3d; + +namespace Vim.G3dNext.Tests +{ + [TestFixture] + public static class VimG3dTests + { + [Test] + public static void Can_Parse_Attributes() + { + var attributeNames = new VimAttributeCollection().AttributeNames; + foreach (var name in attributeNames) + { + // Test that the attribute descriptor parsing works as intended. + var parsed = AttributeDescriptor.TryParse(name, out var desc); + Assert.IsTrue(parsed); + Assert.AreEqual(name, desc.Name); + } + } + + [Test] + public static void Can_Read_Write_Triangle() + { + // Serialize a triangle g3d as bytes and read it back. + var vertices = new[] + { + new Vector3(0, 0, 0), + new Vector3(0, 1, 0), + new Vector3(0, 1, 1) + }; + + var indices = new[] { 0, 1, 2 }; + + var g3d1 = new G3DNext(); + var ac1 = g3d1.AttributeCollection; + ac1.CornersPerFaceAttribute.TypedData = new[] { 3 }; + ac1.VertexAttribute.TypedData = vertices; + ac1.IndexAttribute.TypedData = indices; + + var memoryStream = new MemoryStream(); + g3d1.ToBFast().Write(memoryStream); + memoryStream.Seek(0, SeekOrigin.Begin); + var bfast = new BFastNext.BFastNext(memoryStream); + + var g3d2 = G3DNext.ReadBFast(bfast); + Assert.IsNotNull(g3d2); + + var ac2 = g3d2.AttributeCollection; + Assert.AreEqual(3, ac2.VertexAttribute.Count); + Assert.AreEqual(3, ac2.IndexAttribute.Count); + Assert.AreEqual(0, ac2.MeshSubmeshOffsetAttribute.Count); + Assert.AreEqual(0, ac2.InstanceTransformAttribute.Count); + + Assert.AreEqual(vertices, ac2.VertexAttribute.TypedData); + Assert.AreEqual(indices, ac2.IndexAttribute.TypedData); + } + + [Test] + public static void Can_Read_G3d_From_Vim() + { + var g3d = G3dVim.ReadFromVim(TestUtils.ResidencePath); + Assert.IsNotNull(g3d); + } + + [Test] + public static void Can_Ignore_Extra_Attributes() + { + // Both G3dVim and G3dMaterial share 3 attributes + // G3dVim contains many more attributes + // We create a g3dMaterial from the bytes of a g3dVim + // Shows that extra attributes are ignored as they should. + + var memoryStream = new MemoryStream(); + var g3d = G3dVim.ReadFromVim(TestUtils.ResidencePath); + g3d.source.ToBFast().Write(memoryStream); + memoryStream.Seek(0, SeekOrigin.Begin); + var bfast = new BFastNext.BFastNext(memoryStream); + var g3dMats = G3dMaterials.FromBFast(bfast); + + Assert.IsNotNull(g3dMats); + Assert.AreEqual(g3d.materialColors, g3dMats.materialColors); + Assert.AreEqual(g3d.materialGlossiness, g3dMats.materialGlossiness); + Assert.AreEqual(g3d.materialSmoothness, g3dMats.materialSmoothness); + } + + [Test] + public static void Can_Write_And_Read() + { + var testDir = TestUtils.PrepareTestDir(); + var g3d = TestUtils.CreateTestG3d(); + + var g3dFilePath = Path.Combine(testDir, "test.g3d"); + g3d.ToBFast().Write(g3dFilePath); + var result = G3DNext.ReadBFast(g3dFilePath); + + foreach (var attributeName in result.AttributeCollection.AttributeNames) + { + var attr0 = g3d.AttributeCollection.Attributes[attributeName]; + var attr1 = result.AttributeCollection.Attributes[attributeName]; + Assert.AreEqual(attr0.Data, attr1.Data); + } + } + + [Test] + public static void Can_Merge_two_g3d() + { + var testDir = TestUtils.PrepareTestDir(); + var g3d = TestUtils.CreateTestG3d(); + + var mergedG3d = new[] { g3d, g3d }.Merge(); + + var memoryStream = new MemoryStream(); + var g3dFilePath = Path.Combine(testDir!, "merged.g3d"); + mergedG3d.ToBFast().Write(memoryStream); + memoryStream.Seek(0, SeekOrigin.Begin); + var bfast = new BFastNext.BFastNext(memoryStream); + + + var g3dResult = G3DNext.ReadBFast(bfast); + Assert.NotNull(g3d); + + var mac = g3dResult.AttributeCollection; + + { + var merged = g3d.AttributeCollection.CornersPerFaceAttribute.TypedData; + Assert.AreEqual(merged, mac.CornersPerFaceAttribute.TypedData); + } + + { + var merged = Enumerable.Repeat(g3d.AttributeCollection.VertexAttribute.TypedData, 2).SelectMany(v => v).ToArray(); + Assert.AreEqual(merged, mac.VertexAttribute.TypedData); + } + + { + var tmp = g3d.AttributeCollection.IndexAttribute.TypedData; + var merged = new[] { tmp, tmp.Select(i => i + g3d.AttributeCollection.VertexAttribute.Count).ToArray() }.SelectMany(v => v).ToArray(); + Assert.AreEqual(merged, mac.IndexAttribute.TypedData); + } + + { + var tmp = g3d.AttributeCollection.SubmeshIndexOffsetAttribute.TypedData; + var merged = new[] { tmp, tmp.Select(i => i + g3d.AttributeCollection.IndexAttribute.Count).ToArray() }.SelectMany(v => v).ToArray(); + Assert.AreEqual(merged, mac.SubmeshIndexOffsetAttribute.TypedData); + } + + { + var tmp = g3d.AttributeCollection.SubmeshMaterialAttribute.TypedData; + var merged = new[] { tmp, tmp.Select(i => i + g3d.AttributeCollection.MaterialColorAttribute.Count).ToArray() }.SelectMany(v => v).ToArray(); + Assert.AreEqual(merged, mac.SubmeshMaterialAttribute.TypedData); + } + + { + var tmp = g3d.AttributeCollection.MeshSubmeshOffsetAttribute.TypedData; + var merged = new[] { tmp, tmp.Select(i => i + g3d.AttributeCollection.SubmeshIndexOffsetAttribute.Count).ToArray() }.SelectMany(v => v).ToArray(); + Assert.AreEqual(merged, mac.MeshSubmeshOffsetAttribute.TypedData); + } + + { + var merged = Enumerable.Repeat(g3d.AttributeCollection.InstanceTransformAttribute.TypedData, 2).SelectMany(v => v).ToArray(); + Assert.AreEqual(merged, mac.InstanceTransformAttribute.TypedData); + } + + { + var tmp = g3d.AttributeCollection.InstanceMeshAttribute.TypedData; + var merged = new[] { tmp, tmp.Select(i => i + g3d.AttributeCollection.MeshSubmeshOffsetAttribute.Count).ToArray() }.SelectMany(v => v).ToArray(); + Assert.AreEqual(merged, mac.InstanceMeshAttribute.TypedData); + } + + { + var merged = Enumerable.Repeat(g3d.AttributeCollection.InstanceParentAttribute.TypedData, 2).SelectMany(v => v).ToArray(); + Assert.AreEqual(merged, mac.InstanceParentAttribute.TypedData); + } + + { + var merged = Enumerable.Repeat(g3d.AttributeCollection.MaterialColorAttribute.TypedData, 2).SelectMany(v => v).ToArray(); + Assert.AreEqual(merged, mac.MaterialColorAttribute.TypedData); + } + + { + var merged = Enumerable.Repeat(g3d.AttributeCollection.MaterialGlossinessAttribute.TypedData, 2).SelectMany(v => v).ToArray(); + Assert.AreEqual(merged, mac.MaterialGlossinessAttribute.TypedData); + } + + { + var merged = Enumerable.Repeat(g3d.AttributeCollection.MaterialSmoothnessAttribute.TypedData, 2).SelectMany(v => v).ToArray(); + Assert.AreEqual(merged, mac.MaterialSmoothnessAttribute.TypedData); + } + } + } + +} + diff --git a/src/cs/vim/Vim.Vimx.Test/VimxActions.cs b/src/cs/vim/Vim.Vimx.Test/VimxActions.cs new file mode 100644 index 00000000..5d13cd74 --- /dev/null +++ b/src/cs/vim/Vim.Vimx.Test/VimxActions.cs @@ -0,0 +1,20 @@ +using NUnit.Framework; +using Vim.G3dNext.Tests; + +namespace Vim.Format.Vimx.Test +{ + [TestFixture] + public static class VimxActions + { + [Test] + public static void ConvertVimToVimx() + { + var input = TestUtils.ResidencePath; + var name = Path.GetFileNameWithoutExtension(TestUtils.ResidencePath); + var output = Path.Combine(TestUtils.TestOutputFolder, name + ".vimx"); + + var vimx = Vimx.FromVim(input); + vimx.Write(output); + } + } +} diff --git a/src/cs/vim/Vim.Vimx.Test/VimxTests.cs b/src/cs/vim/Vim.Vimx.Test/VimxTests.cs new file mode 100644 index 00000000..b18ab0db --- /dev/null +++ b/src/cs/vim/Vim.Vimx.Test/VimxTests.cs @@ -0,0 +1,34 @@ +using NUnit.Framework; +using NUnit.Framework.Internal; +using Vim.BFast; +using Vim.Format.Vimx; +using Vim.G3dNext.Attributes; +using Vim.G3dNext.Tests; +using Vim.Math3d; + +namespace Vim.Format.Vimx.Tests +{ + [TestFixture] + public static class VimxTests + { + [Test] + public static void Can_Convert_And_Read_Vimx() + { + var input = TestUtils.ResidencePath; + var name = Path.GetFileNameWithoutExtension(TestUtils.ResidencePath); + var output = Path.Combine(TestUtils.TestOutputFolder, name + ".vimx"); + + var vimx = Vimx.FromVim(input); + vimx.Write(output); + + var result = Vimx.FromPath(output); + Assert.AreEqual(vimx.scene.InstanceFiles, result.scene.InstanceFiles); + Assert.AreEqual(vimx.materials.materialColors, result.materials.materialColors); + Assert.AreEqual(vimx.meshes.Length, result.meshes.Length); + + } + + } + +} + diff --git a/src/ts/dist/abstractG3d.d.ts b/src/ts/dist/abstractG3d.d.ts new file mode 100644 index 00000000..20af3b6e --- /dev/null +++ b/src/ts/dist/abstractG3d.d.ts @@ -0,0 +1,17 @@ +import { G3dAttribute } from './g3dAttributes'; +import { BFast } from './bfast'; +/** + * G3D is a simple, efficient, generic binary format for storing and transmitting geometry. + * The G3D format is designed to be used either as a serialization format or as an in-memory data structure. + * See https://github.com/vimaec/g3d + */ +export declare class AbstractG3d { + meta: string; + attributes: G3dAttribute[]; + constructor(meta: string, attributes: G3dAttribute[]); + findAttribute(descriptor: string): G3dAttribute | undefined; + /** + * Create g3d from bfast by requesting all necessary buffers individually. + */ + static createFromBfast(bfast: BFast, names: string[]): Promise; +} diff --git a/src/ts/dist/abstractG3d.js b/src/ts/dist/abstractG3d.js new file mode 100644 index 00000000..e2d1d39e --- /dev/null +++ b/src/ts/dist/abstractG3d.js @@ -0,0 +1,39 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.AbstractG3d = void 0; +const g3dAttributes_1 = require("./g3dAttributes"); +/** + * G3D is a simple, efficient, generic binary format for storing and transmitting geometry. + * The G3D format is designed to be used either as a serialization format or as an in-memory data structure. + * See https://github.com/vimaec/g3d + */ +class AbstractG3d { + constructor(meta, attributes) { + this.meta = meta; + this.attributes = attributes; + } + findAttribute(descriptor) { + const filter = g3dAttributes_1.G3dAttributeDescriptor.fromString(descriptor); + for (let i = 0; i < this.attributes.length; ++i) { + const attribute = this.attributes[i]; + if (attribute.descriptor.matches(filter)) + return attribute; + } + } + /** + * Create g3d from bfast by requesting all necessary buffers individually. + */ + static async createFromBfast(bfast, names) { + const attributes = await Promise.all(names.map(async (a) => { + const bytes = await bfast.getBytes(a); + if (!bytes) + return; + const decriptor = g3dAttributes_1.G3dAttributeDescriptor.fromString(a); + return new g3dAttributes_1.G3dAttribute(decriptor, bytes); + })); + const validAttributes = attributes.filter((a) => a !== undefined); + const g3d = new AbstractG3d('meta', validAttributes); + return g3d; + } +} +exports.AbstractG3d = AbstractG3d; diff --git a/src/ts/dist/bfast.d.ts b/src/ts/dist/bfast.d.ts new file mode 100644 index 00000000..a75624bf --- /dev/null +++ b/src/ts/dist/bfast.d.ts @@ -0,0 +1,141 @@ +/** + * @module vim-ts + */ +import { RemoteBuffer } from './remoteBuffer'; +declare type NumericArrayConstructor = Int8ArrayConstructor | Uint8ArrayConstructor | Int16ArrayConstructor | Uint16ArrayConstructor | Int32ArrayConstructor | Uint32ArrayConstructor | BigInt64ArrayConstructor | BigUint64ArrayConstructor | Float32ArrayConstructor | Float64ArrayConstructor; +export declare type NumericArray = Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array | BigInt64Array | BigUint64Array; +export declare class Range { + start: number; + end: number; + get length(): number; + constructor(start: number, end: number); + offset(offset: number): Range; +} +/** + * Returns -1 size for undefined attributes. + */ +export declare function parseName(name: string): [number, NumericArrayConstructor]; +export declare function typeSize(type: string): 1 | 2 | 4 | 8; +/** + * Bfast header, mainly for validation. + * See https://github.com/vimaec/bfast + */ +export declare class BFastHeader { + magic: number; + dataStart: number; + dataEnd: number; + numArrays: number; + constructor(magic: number, dataStart: number, dataEnd: number, numArrays: number); + static createFromArray(array: Uint32Array): BFastHeader; + static createFromBuffer(array: ArrayBuffer): BFastHeader; +} +/** + * See https://github.com/vimaec/bfast for bfast format spec + * This implementation can either lazily request content as needed from http + * Or it can serve the data directly from an ArrayBuffer + * Remote mode can transition to buffer mode if server doesnt support partial http request + */ +export declare class BFast { + source: RemoteBuffer | ArrayBuffer; + offset: number; + name: string; + private _header; + private _ranges; + private _children; + constructor(source: RemoteBuffer | ArrayBuffer, offset?: number, name?: string); + /** + * Aborts all downloads from the underlying RemoteBuffer + */ + abort(): void; + /** + * @returns Bfast Header + */ + getHeader(): Promise; + /** + * @returns a map of all buffers by names + */ + getRanges(): Promise>; + /** + * Returns the buffer associated with name as a new bfast. + * This value is cached for future requests. + * @param name buffer name + */ + getBfast(name: string): Promise; + getLocalBfast(name: string, unzip?: boolean): Promise; + getLocalBfastRaw(name: string, unzip?: boolean): Promise; + /** + * Returns the raw buffer associated with a name + * This value is not cached. + * @param name buffer name + */ + getBuffer(name: string): Promise; + /** + * Returns a number array from the buffer associated with name + * @param name buffer name + */ + getArray(name: string): Promise; + /** + * Returns a single value from given buffer name + * @param name buffer name + * @param index row index + */ + getValue(name: string, index: number): Promise; + getRange(name: string): Promise; + /** + * Returns count subsequent values from given buffer name. + * @param name buffer name + * @param index row index + * @param count count of values to return + */ + getValues(name: string, index: number, count: number): Promise; + /** + + * Returns the buffer with given name as a byte array + * @param name buffer name + */ + getBytes(name: string): Promise; + /** + * Returns a map of name-values with the same index from all buffers. + * @param name buffer name + */ + getRow(index: number): Promise | undefined>; + /** + * Forces download of the full underlying buffer, from now on all calls will be local. + */ + forceDownload(): Promise; + /** + * Downloads the appropriate range and cast it as a new sub bfast. + */ + private requestBfast; + /** + * Downloads and parses ranges as a map of name->range + */ + private requestRanges; + /** + * Downloads and parse names from remote. + */ + private requestNames; + /** + * Downloads and parse header from remote. + */ + private requestHeader; + /** + * Gets array buffer from from cache, or partial http, fallback to full http + * @param range range to get, or get full resource if undefined + * @param label label for logs + */ + private request; + /** + * returns requested range from cache. + */ + private local; + /** + * returns requested range from remote. + */ + private remote; + /** + * Returns a new local bfast equivalent to this bfast. + */ + getSelf(): Promise; +} +export {}; diff --git a/src/ts/dist/bfast.js b/src/ts/dist/bfast.js new file mode 100644 index 00000000..e6457db5 --- /dev/null +++ b/src/ts/dist/bfast.js @@ -0,0 +1,456 @@ +"use strict"; +/** + * @module vim-ts + */ +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.BFast = exports.BFastHeader = exports.typeSize = exports.parseName = exports.Range = void 0; +const remoteValue_1 = require("./remoteValue"); +const remoteBuffer_1 = require("./remoteBuffer"); +const pako = __importStar(require("pako")); +class Range { + constructor(start, end) { + this.start = start; + this.end = end; + } + get length() { + return this.end - this.start; + } + offset(offset) { + return new Range(this.start + offset, this.end + offset); + } +} +exports.Range = Range; +/** + * Returns -1 size for undefined attributes. + */ +function parseName(name) { + if (name.startsWith('g3d')) { + const result = name.includes(':int8:') ? [1, Int8Array] + : name.includes(':uint8:') ? [1, Uint8Array] + : name.includes(':int16:') ? [2, Int16Array] + : name.includes(':uint16:') ? [2, Uint16Array] + : name.includes(':int32:') ? [4, Int32Array] + : name.includes(':uint32:') ? [4, Uint32Array] + : name.includes(':int64:') ? [8, BigInt64Array] + : name.includes(':uint64:') ? [8, BigUint64Array] + : name.includes(':float32:') ? [4, Float32Array] + : name.includes(':float64:') ? [8, Float64Array] + : [-1, undefined]; + return result; + } + else { + const result = name.startsWith('byte:') ? [1, Int8Array] + : name.startsWith('ubyte:') ? [1, Uint8Array] + : name.startsWith('short:') ? [2, Int16Array] + : name.startsWith('ushort:') ? [2, Uint16Array] + : name.startsWith('int:') ? [4, Int32Array] + : name.startsWith('uint:') ? [4, Uint32Array] + : name.startsWith('long:') ? [8, BigInt64Array] + : name.startsWith('ulong:') ? [8, BigUint64Array] + : name.startsWith('float:') ? [4, Float32Array] + : name.startsWith('double:') ? [8, Float64Array] + : [-1, undefined]; + return result; + } +} +exports.parseName = parseName; +function typeSize(type) { + switch (type) { + case 'byte': + case 'ubyte': + return 1; + case 'short': + case 'ushort': + return 2; + case 'int': + case 'uint': + case 'float': + return 4; + case 'long': + case 'ulong': + case 'double': + return 8; + default: + return 4; + } +} +exports.typeSize = typeSize; +function typeConstructor(type) { + switch (type) { + case 'byte': + return Int8Array; + case 'ubyte': + return Uint8Array; + case 'short': + return Int16Array; + case 'ushort': + return Uint16Array; + case 'int': + return Int32Array; + case 'uint': + return Uint32Array; + case 'long': + return BigInt64Array; + case 'ulong': + return BigUint64Array; + case 'float': + return Float32Array; + case 'double': + return Float64Array; + default: + return Int32Array; + } +} +/** + * Bfast header, mainly for validation. + * See https://github.com/vimaec/bfast + */ +class BFastHeader { + constructor(magic, dataStart, dataEnd, numArrays) { + if (magic !== 0xbfa5) { + throw new Error('Invalid Bfast. Invalid Magic number'); + } + if (dataStart <= 32 || dataStart > Number.MAX_SAFE_INTEGER) { + throw new Error('Invalid Bfast. Data start is out of valid range'); + } + if (dataEnd < dataStart || dataEnd > Number.MAX_SAFE_INTEGER) { + throw new Error('Invalid Bfast. Data end is out of valid range'); + } + if (numArrays < 0 || numArrays > dataEnd) { + throw new Error('Invalid Bfast. Number of arrays is invalid'); + } + this.magic = magic; + this.dataStart = dataStart; + this.dataEnd = dataEnd; + this.numArrays = numArrays; + } + static createFromArray(array) { + // Check validity of data + // TODO: check endianness + if (array[1] !== 0) { + throw new Error('Invalid Bfast. Expected 0 in byte position 0'); + } + if (array[3] !== 0) { + throw new Error('Invalid Bfast. Expected 0 in byte position 8'); + } + if (array[5] !== 0) { + throw new Error('Invalid Bfast. Expected 0 in position 16'); + } + if (array[7] !== 0) { + throw new Error('Invalid Bfast. Expected 0 in position 24'); + } + return new this(array[0], array[2], array[4], array[6]); + } + static createFromBuffer(array) { + return BFastHeader.createFromArray(new Uint32Array(array)); + } +} +exports.BFastHeader = BFastHeader; +/** + * See https://github.com/vimaec/bfast for bfast format spec + * This implementation can either lazily request content as needed from http + * Or it can serve the data directly from an ArrayBuffer + * Remote mode can transition to buffer mode if server doesnt support partial http request + */ +class BFast { + constructor(source, offset = 0, name = '') { + this.source = source; + this.offset = offset; + this.name = name; + this._header = new remoteValue_1.RemoteValue(() => this.requestHeader(), name + '.header'); + this._children = new Map(); + this._ranges = new remoteValue_1.RemoteValue(() => this.requestRanges(), name + '.ranges'); + } + /** + * Aborts all downloads from the underlying RemoteBuffer + */ + abort() { + if (this.source instanceof remoteBuffer_1.RemoteBuffer) { + this.source.abort(); + } + } + /** + * @returns Bfast Header + */ + async getHeader() { + return this._header.get(); + } + /** + * @returns a map of all buffers by names + */ + async getRanges() { + return this._ranges.get(); + } + /** + * Returns the buffer associated with name as a new bfast. + * This value is cached for future requests. + * @param name buffer name + */ + async getBfast(name) { + let request = this._children.get(name); + if (!request) { + request = new remoteValue_1.RemoteValue(() => this.requestBfast(name)); + this._children.set(name, request); + } + return request.get(); + } + async getLocalBfast(name, unzip = false) { + let buffer = await this.getBuffer(name); + if (!buffer) + return undefined; + if (unzip) { + buffer = pako.inflate(buffer).buffer; + } + return new BFast(buffer, 0, name); + } + async getLocalBfastRaw(name, unzip = false) { + let buffer = await this.getBuffer(name); + if (!buffer) + return undefined; + if (unzip) { + buffer = pako.inflateRaw(buffer).buffer; + } + return new BFast(buffer, 0, name); + } + /** + * Returns the raw buffer associated with a name + * This value is not cached. + * @param name buffer name + */ + async getBuffer(name) { + const ranges = await this.getRanges(); + const range = ranges.get(name); + if (!range) + return undefined; + const buffer = await this.request(range, name); + return buffer; + } + /** + * Returns a number array from the buffer associated with name + * @param name buffer name + */ + async getArray(name) { + const buffer = await this.getBuffer(name); + if (!buffer) + return undefined; + const type = name.split(':')[0]; + const Ctor = typeConstructor(type); + const array = new Ctor(buffer); + return array; + } + /** + * Returns a single value from given buffer name + * @param name buffer name + * @param index row index + */ + async getValue(name, index) { + const array = await this.getValues(name, index, 1); + return array?.[0]; + } + async getRange(name) { + const ranges = await this.getRanges(); + return ranges.get(name); + } + /** + * Returns count subsequent values from given buffer name. + * @param name buffer name + * @param index row index + * @param count count of values to return + */ + async getValues(name, index, count) { + if (index < 0 || count < 1) + return undefined; + const range = await this.getRange(name); + if (!range) + return undefined; + const [size, ctor] = parseName(name); + if (size < 0) + return undefined; + const start = Math.min(range.start + index * size, range.end); + const end = Math.min(start + size * count, range.end); + const dataRange = new Range(start, end); + if (dataRange.length <= 0) + return undefined; + const buffer = await this.request(dataRange, `${name}[${index.toString()}]`); + if (!buffer) + return undefined; + const array = new ctor(buffer); + return array; + } + /** + + * Returns the buffer with given name as a byte array + * @param name buffer name + */ + async getBytes(name) { + const buffer = await this.getBuffer(name); + if (!buffer) + return undefined; + const array = new Uint8Array(buffer); + return array; + } + /** + * Returns a map of name-values with the same index from all buffers. + * @param name buffer name + */ + async getRow(index) { + const ranges = await this.getRanges(); + if (!ranges) + return undefined; + const result = new Map(); + const promises = []; + for (const name of ranges.keys()) { + const p = this.getValue(name, index).then((v) => result.set(name, v)); + promises.push(p); + } + await Promise.all(promises); + return result; + } + /** + * Forces download of the full underlying buffer, from now on all calls will be local. + */ + async forceDownload() { + if (this.source instanceof ArrayBuffer) { + console.log('Ignoring forceDownload on local buffer.'); + return; + } + const buffer = await this.remote(undefined, this.name); + if (!buffer) + throw new Error('Failed to download BFAST.'); + this.source = buffer; + } + /** + * Downloads the appropriate range and cast it as a new sub bfast. + */ + async requestBfast(name) { + const ranges = await this.getRanges(); + const range = ranges.get(name); + if (!range) + return undefined; + const result = new BFast(this.source, this.offset + range.start, this.name + '.' + name); + return result; + } + /** + * Downloads and parses ranges as a map of name->range + */ + async requestRanges() { + const header = await this.getHeader(); + const buffer = await this.request(new Range(32, 32 + header.numArrays * 16), 'Ranges'); + if (!buffer) + throw new Error('Could not get BFAST Ranges.'); + // Parse range + const array = new Uint32Array(buffer); + const ranges = []; + for (let i = 0; i < array.length; i += 4) { + if (array[i + 1] !== 0 || array[i + 3] !== 0) { + throw new Error('Invalid Bfast. 64 bit ranges not supported'); + } + ranges.push(new Range(array[i], array[i + 2])); + } + const names = await this.requestNames(ranges[0]); + if (ranges.length !== names.length + 1) { + throw new Error('Mismatched ranges and names count'); + } + // Map ranges and names + const map = new Map(); + for (let i = 0; i < names.length; i++) { + map.set(names[i], ranges[i + 1]); + } + return map; + } + /** + * Downloads and parse names from remote. + */ + async requestNames(range) { + const buffer = await this.request(range, 'Names'); + const names = new TextDecoder('utf-8').decode(buffer); + const result = names.slice(0, -1).split('\0'); + return result; + } + /** + * Downloads and parse header from remote. + */ + async requestHeader() { + const buffer = await this.request(new Range(0, 32), 'Header'); + if (!buffer) + throw new Error('Could not get BFAST Header'); + const result = BFastHeader.createFromBuffer(buffer); + return result; + } + /** + * Gets array buffer from from cache, or partial http, fallback to full http + * @param range range to get, or get full resource if undefined + * @param label label for logs + */ + async request(range, label) { + const buffer = this.local(range, label) ?? + (await this.remote(range, label)) ?? + (await this.remote(undefined, label)); + if (!buffer) { + throw new Error(`Could not load vim at ${this.source}`); + } + if (buffer.byteLength > range.length) { + this.source = buffer; + return this.local(range, label); + } + return buffer; + } + /** + * returns requested range from cache. + */ + local(range, label) { + if (!(this.source instanceof ArrayBuffer)) + return undefined; + //console.log(`Returning local ${this.name}.${label}`) + const r = range.offset(this.offset); + return this.source.slice(r.start, r.end); + } + /** + * returns requested range from remote. + */ + async remote(range, label) { + if (!(this.source instanceof remoteBuffer_1.RemoteBuffer)) + return undefined; + const r = range?.offset(this.offset); + const buffer = await this.source.http(r, `${this.name}.${label}`); + if (range && (buffer?.byteLength ?? 0) < range.length) { + console.log('Range request request failed.'); + return undefined; + } + return buffer; + } + /** + * Returns a new local bfast equivalent to this bfast. + */ + async getSelf() { + const header = await this._header.get(); + const range = new Range(0, header.dataEnd); + const buffer = await this.request(range, this.name); + const result = new BFast(buffer, 0, this.name); + return result; + } +} +exports.BFast = BFast; diff --git a/src/ts/dist/converters.d.ts b/src/ts/dist/converters.d.ts new file mode 100644 index 00000000..4ce85f94 --- /dev/null +++ b/src/ts/dist/converters.d.ts @@ -0,0 +1,46 @@ +/** + * @module vim-ts + */ +import { Vector2, Vector3, Vector4, AABox, AABox2D, AABox4D, Matrix4x4 } from "./structures"; +export interface IConverter { + get columns(): string[]; + convertFromArray(array: number[]): T; + convertToArray(value: T): number[]; +} +export declare class Vector2Converter implements IConverter { + get columns(): string[]; + convertFromArray(array: number[]): Vector2; + convertToArray(value: Vector2): number[]; +} +export declare class Vector3Converter implements IConverter { + get columns(): string[]; + convertFromArray(array: number[]): Vector3; + convertToArray(value: Vector3): number[]; +} +export declare class Vector4Converter implements IConverter { + get columns(): string[]; + convertFromArray(array: number[]): Vector4; + convertToArray(value: Vector4): number[]; +} +export declare class AABox2DConverter implements IConverter { + get columns(): string[]; + convertFromArray(array: number[]): AABox2D; + convertToArray(value: AABox2D): number[]; +} +export declare class AABoxConverter implements IConverter { + get columns(): string[]; + convertFromArray(array: number[]): AABox; + convertToArray(value: AABox): number[]; +} +export declare class AABox4DConverter implements IConverter { + get columns(): string[]; + convertFromArray(array: number[]): AABox4D; + convertToArray(value: AABox4D): number[]; +} +export declare class Matrix4x4Converter implements IConverter { + get columns(): string[]; + convertFromArray(array: number[]): Matrix4x4; + convertToArray(value: Matrix4x4): number[]; +} +export declare function convert(converter: IConverter, array: (number | undefined)[]): T; +export declare function convertArray(converter: IConverter, arrays: (number[] | undefined)[]): T[]; diff --git a/src/ts/dist/converters.js b/src/ts/dist/converters.js new file mode 100644 index 00000000..4c645c05 --- /dev/null +++ b/src/ts/dist/converters.js @@ -0,0 +1,145 @@ +"use strict"; +/** + * @module vim-ts + */ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.convertArray = exports.convert = exports.Matrix4x4Converter = exports.AABox4DConverter = exports.AABoxConverter = exports.AABox2DConverter = exports.Vector4Converter = exports.Vector3Converter = exports.Vector2Converter = void 0; +class Vector2Converter { + get columns() { + return [".X", ".Y"]; + } + convertFromArray(array) { + return { x: array[0], y: array[1] }; + } + convertToArray(value) { + return [value.x, value.y]; + } +} +exports.Vector2Converter = Vector2Converter; +class Vector3Converter { + get columns() { + return [".X", ".Y", ".Z"]; + } + convertFromArray(array) { + return { x: array[0], y: array[1], z: array[2] }; + } + convertToArray(value) { + return [value.x, value.y, value.z]; + } +} +exports.Vector3Converter = Vector3Converter; +class Vector4Converter { + get columns() { + return [".X", ".Y", ".Z", ".W"]; + } + convertFromArray(array) { + return { x: array[0], y: array[1], z: array[2], w: array[3] }; + } + convertToArray(value) { + return [value.x, value.y, value.z, value.w]; + } +} +exports.Vector4Converter = Vector4Converter; +class AABox2DConverter { + get columns() { + return [".Min.X", ".Min.Y", ".Max.X", ".Max.Y"]; + } + convertFromArray(array) { + return { + min: { x: array[0], y: array[1] }, + max: { x: array[2], y: array[3] } + }; + } + convertToArray(value) { + return [ + value.min.x, value.min.y, + value.max.x, value.max.y + ]; + } +} +exports.AABox2DConverter = AABox2DConverter; +class AABoxConverter { + get columns() { + return [".Min.X", ".Min.Y", ".Min.Z", ".Max.X", ".Max.Y", ".Max.Z"]; + } + convertFromArray(array) { + return { + min: { x: array[0], y: array[1], z: array[2] }, + max: { x: array[3], y: array[4], z: array[5] } + }; + } + convertToArray(value) { + return [ + value.min.x, value.min.y, value.min.z, + value.max.x, value.max.y, value.max.z + ]; + } +} +exports.AABoxConverter = AABoxConverter; +class AABox4DConverter { + get columns() { + return [".Min.X", ".Min.Y", ".Min.Z", ".Min.W", ".Max.X", ".Max.Y", ".Max.Z", ".Max.W"]; + } + convertFromArray(array) { + return { + min: { x: array[0], y: array[1], z: array[2], w: array[3] }, + max: { x: array[4], y: array[5], z: array[6], w: array[7] } + }; + } + convertToArray(value) { + return [ + value.min.x, value.min.y, value.min.z, value.min.w, + value.max.x, value.max.y, value.max.z, value.max.w + ]; + } +} +exports.AABox4DConverter = AABox4DConverter; +class Matrix4x4Converter { + get columns() { + return [ + ".M11", ".M12", ".M13", ".M14", + ".M21", ".M22", ".M23", ".M24", + ".M31", ".M32", ".M33", ".M34", + ".M41", ".M42", ".M43", ".M44" + ]; + } + convertFromArray(array) { + return { + m11: array[0], m12: array[1], m13: array[2], m14: array[3], + m21: array[4], m22: array[5], m23: array[6], m24: array[7], + m31: array[8], m32: array[9], m33: array[10], m34: array[11], + m41: array[12], m42: array[13], m43: array[14], m44: array[15] + }; + } + convertToArray(value) { + return [ + value.m11, value.m12, value.m13, value.m14, + value.m21, value.m22, value.m23, value.m24, + value.m31, value.m32, value.m33, value.m34, + value.m41, value.m42, value.m43, value.m44 + ]; + } +} +exports.Matrix4x4Converter = Matrix4x4Converter; +function convert(converter, array) { + if (array.some(n => n === undefined)) { + return undefined; + } + return converter.convertFromArray(array.map(n => n)); +} +exports.convert = convert; +function convertArray(converter, arrays) { + if (arrays.some(n => n === undefined)) { + return undefined; + } + let result = []; + for (let i = 0; i < arrays[0].length; i++) { + let array = []; + for (let j = 0; j < arrays.length; j++) { + array.push(arrays[j][i]); + } + result.push(converter.convertFromArray(array)); + } + return result; +} +exports.convertArray = convertArray; diff --git a/src/ts/dist/entityTable.d.ts b/src/ts/dist/entityTable.d.ts new file mode 100644 index 00000000..da20ed57 --- /dev/null +++ b/src/ts/dist/entityTable.d.ts @@ -0,0 +1,22 @@ +/** + * @module vim-ts + */ +import { BFast, NumericArray } from './bfast'; +export declare class EntityTable { + private readonly bfast; + private readonly strings; + constructor(bfast: BFast, strings: string[] | undefined); + getLocal(): Promise; + static getTypeSize(colName: string): number; + getCount(): Promise; + getArray(columnName: string): Promise; + getNumberArray(columnName: string): Promise; + getNumber(elementIndex: number, columnName: string): Promise; + getBigIntArray(columnName: string): Promise; + getBigInt(elementIndex: number, columnName: string): Promise; + getBoolean(elementIndex: number, columnName: string): Promise; + getBooleanArray(columnName: string): Promise; + toIndex(value: number | bigint): number; + getString(elementIndex: number, columnName: string): Promise; + getStringArray(columnName: string): Promise; +} diff --git a/src/ts/dist/entityTable.js b/src/ts/dist/entityTable.js new file mode 100644 index 00000000..593872bb --- /dev/null +++ b/src/ts/dist/entityTable.js @@ -0,0 +1,128 @@ +"use strict"; +/** + * @module vim-ts + */ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.EntityTable = void 0; +class EntityTable { + constructor(bfast, strings) { + this.bfast = bfast; + this.strings = strings; + } + async getLocal() { + return new EntityTable(await this.bfast.getSelf(), this.strings); + } + static getTypeSize(colName) { + if (colName.startsWith('index:') || + colName.startsWith('string:') || + colName.startsWith('int:') || + colName.startsWith('uint:') || + colName.startsWith('float:')) { + return 4; // 4 bytes + } + if (colName.startsWith('double:') || + colName.startsWith('long:') || + colName.startsWith('ulong')) { + return 8; // 8 bytes + } + if (colName.startsWith('byte:') || + colName.startsWith('ubyte:')) { + return 1; // 1 byte + } + if (colName.startsWith('short:') || + colName.startsWith('ushort:')) { + return 2; // 2 bytes + } + return 1; // default to 1 byte + } + async getCount() { + const ranges = await this.bfast.getRanges(); + if (!ranges || ranges.size === 0) + return 0; + const [colName, range] = ranges.entries().next().value; + const rangeSize = range.length; + const typeSize = EntityTable.getTypeSize(colName); + return rangeSize / typeSize; + } + getArray(columnName) { + return this.bfast.getArray(columnName); + } + async getNumberArray(columnName) { + const array = await this.bfast.getArray(columnName); + if (!array || (array instanceof BigInt64Array) || (array instanceof BigUint64Array)) + return undefined; + return Array.from(array); + } + async getNumber(elementIndex, columnName) { + const array = await this.bfast.getArray(columnName); + if ((array?.length ?? -1) <= elementIndex) + return undefined; + return Number(array[elementIndex]); + } + async getBigIntArray(columnName) { + const array = await this.bfast.getArray(columnName); + if (!array) + return undefined; + if (array instanceof BigInt64Array) + return array; + const result = new BigInt64Array(array.length); + for (var i = 0; i < array.length; ++i) { + result[i] = BigInt(array[i]); + } + return result; + } + async getBigInt(elementIndex, columnName) { + const array = await this.bfast.getArray(columnName); + if ((array?.length ?? -1) <= elementIndex) + return undefined; + const element = array[elementIndex]; + if (element === undefined) + return undefined; + return BigInt(element); + } + async getBoolean(elementIndex, columnName) { + const array = await this.bfast.getArray(columnName); + if ((array?.length ?? -1) <= elementIndex) + return undefined; + const element = array[elementIndex]; + if (element === undefined) + return undefined; + return Boolean(element); + } + async getBooleanArray(columnName) { + const array = await this.bfast.getArray(columnName); + if (!array) + return undefined; + const result = new Array(array.length); + for (let i = 0; i < array.length; ++i) { + result[i] = Boolean(array[i]); + } + return result; + } + toIndex(value) { + return typeof value === 'bigint' + ? Number(BigInt.asIntN(32, value)) // clamp to signed integer value + : value; + } + async getString(elementIndex, columnName) { + if (this.strings === undefined) + return undefined; + const array = await this.bfast.getArray(columnName); + if ((array?.length ?? -1) <= elementIndex) + return undefined; + return this.strings[this.toIndex(array[elementIndex])]; + } + async getStringArray(columnName) { + if (this.strings === undefined) + return undefined; + const array = await this.bfast.getArray(columnName); + if (!array) + return undefined; + const result = new Array(array.length); + for (let i = 0; i < array.length; ++i) { + result[i] = this.strings[this.toIndex(array[i])]; + } + return result; + } +} +exports.EntityTable = EntityTable; diff --git a/src/ts/dist/g3d.d.ts b/src/ts/dist/g3d.d.ts new file mode 100644 index 00000000..bba0b4a2 --- /dev/null +++ b/src/ts/dist/g3d.d.ts @@ -0,0 +1,178 @@ +/** + * @module vim-ts + */ +import { AbstractG3d } from './abstractG3d'; +import { BFast } from './bfast'; +export declare type MeshSection = 'opaque' | 'transparent' | 'all'; +/** + * See https://github.com/vimaec/vim#vim-geometry-attributes + */ +export declare class VimAttributes { + static positions: string; + static indices: string; + static instanceMeshes: string; + static instanceTransforms: string; + static instanceNodes: string; + static instanceFlags: string; + static meshSubmeshes: string; + static submeshIndexOffsets: string; + static submeshMaterials: string; + static materialColors: string; + static all: string[]; +} +/** + * G3D is a simple, efficient, generic binary format for storing and transmitting geometry. + * The G3D format is designed to be used either as a serialization format or as an in-memory data structure. + * A G3d with specific attributes according to the VIM format specification. + * See https://github.com/vimaec/vim#vim-geometry-attributes for the vim specification. + * See https://github.com/vimaec/g3d for the g3d specification. + */ +export declare class G3d { + positions: Float32Array; + indices: Uint32Array; + instanceMeshes: Int32Array; + instanceTransforms: Float32Array; + instanceFlags: Uint16Array; + meshSubmeshes: Int32Array; + submeshIndexOffset: Int32Array; + submeshMaterial: Int32Array; + materialColors: Float32Array; + instanceNodes: Int32Array; + meshVertexOffsets: Int32Array; + meshInstances: Array>; + meshOpaqueCount: Int32Array; + submeshVertexStart: Int32Array; + submeshVertexEnd: Int32Array; + rawG3d: AbstractG3d; + static MATRIX_SIZE: number; + static COLOR_SIZE: number; + static POSITION_SIZE: number; + /** + * Opaque white + */ + DEFAULT_COLOR: Float32Array; + constructor(instanceMeshes: Int32Array, instanceFlags: Uint16Array | undefined, instanceTransforms: Float32Array, instanceNodes: Int32Array | undefined, meshSubmeshes: Int32Array, submeshIndexOffsets: Int32Array, submeshMaterials: Int32Array, indices: Int32Array | Uint32Array, positions: Float32Array, materialColors: Float32Array); + private computeSubmeshVertexRange; + static createFromAbstract(g3d: AbstractG3d): G3d; + static createFromPath(path: string): Promise; + static createFromBfast(bfast: BFast): Promise; + /** + * Computes the index of the first vertex of each mesh + */ + private computeMeshVertexOffsets; + /** + * Computes all instances pointing to each mesh. + */ + private computeMeshInstances; + /** + * Reorders submeshIndexOffset, submeshMaterials and indices + * such that for each mesh, submeshes are sorted according to material alpha. + * This enables efficient splitting of arrays into opaque and transparent continuous ranges. + */ + private sortSubmeshes; + /** + * Stores result of getSubmeshIndexEnd for each submesh in an array + */ + private computeSubmeshEnd; + /** + * Stores result of getMeshIndexStart for each mesh in an array + */ + private computeMeshIndexOffsets; + /** + * Reorder submesh arrays and returns size of largest reordered mesh + */ + private reorderSubmeshes; + /** + * Sorts the range from start to end in every array provided in arrays in increasing criterion order. + * Using a simple bubble sort, there is a limited number of submeshes per mesh. + */ + private Sort; + /** + * Reorders the index buffer to match the new order of the submesh arrays. + */ + private reorderIndices; + /** + * Rebase indices to be relative to its own mesh instead of to the whole g3d + */ + private rebaseIndices; + private unbaseIndices; + /** + * Computes an array where true if any of the materials used by a mesh has transparency. + */ + private computeMeshOpaqueCount; + /**Given VIM instance indices returns the corresponding G3d indices */ + remapInstances(instances: number[]): number[]; + getVertexCount: () => number; + getIndexCount: () => number; + getMeshCount: () => number; + getMeshInstanceCount(mesh: number): number; + getMeshIndexStart(mesh: number, section?: MeshSection): number; + getMeshIndexEnd(mesh: number, section?: MeshSection): number; + getMeshIndexCount(mesh: number, section?: MeshSection): number; + getMeshVertexStart(mesh: number): number; + getMeshVertexEnd(mesh: number): number; + getMeshVertexCount(mesh: number): number; + getMeshSubmeshStart(mesh: number, section?: MeshSection): number; + getMeshSubmeshEnd(mesh: number, section?: MeshSection): number; + getMeshSubmeshCount(mesh: number, section?: MeshSection): number; + getMeshHasTransparency(mesh: number): boolean; + getSubmeshIndexStart(submesh: number): number; + getSubmeshIndexEnd(submesh: number): number; + getSubmeshIndexCount(submesh: number): number; + getSubmeshVertexStart(submesh: number): number; + getSubmeshVertexEnd(submesh: number): number; + getSubmeshVertexCount(submesh: number): number; + /** + * Returns color of given submesh as a 4-number array (RGBA) + * @param submesh g3d submesh index + */ + getSubmeshColor(submesh: number): Float32Array; + /** + * Returns color of given submesh as a 4-number array (RGBA) + * @param submesh g3d submesh index + */ + getSubmeshAlpha(submesh: number): number; + /** + * Returns true if submesh is transparent. + * @param submesh g3d submesh index + */ + getSubmeshIsTransparent(submesh: number): boolean; + /** + * Returns the total number of mesh in the g3d + */ + getSubmeshCount(): number; + getInstanceCount: () => number; + /** + * Returns true if instance has given flag enabled. + * @param instance instance to check. + * @param flag to check against. + */ + getInstanceHasFlag(instance: number, flag: number): boolean; + /** + * Returns mesh index of given instance + * @param instance g3d instance index + */ + getInstanceMesh(instance: number): number; + /** + * Returns an 16 number array representation of the matrix for given instance + * @param instance g3d instance index + */ + getInstanceMatrix(instance: number): Float32Array; + getMaterialCount: () => number; + /** + * Returns color of given material as a 4-number array (RGBA) + * @param material g3d material index + */ + getMaterialColor(material: number): Float32Array; + /** + * Returns the alpha component of given material + * @param material + */ + getMaterialAlpha(material: number): number; + /** + * Concatenates two g3ds into a new g3d. + * @deprecated + */ + append(other: G3d): G3d; + validate(): void; +} diff --git a/src/ts/dist/g3d.js b/src/ts/dist/g3d.js new file mode 100644 index 00000000..1cf5cd24 --- /dev/null +++ b/src/ts/dist/g3d.js @@ -0,0 +1,609 @@ +"use strict"; +/** + * @module vim-ts + */ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.G3d = exports.VimAttributes = void 0; +const abstractG3d_1 = require("./abstractG3d"); +const bfast_1 = require("./bfast"); +/** + * See https://github.com/vimaec/vim#vim-geometry-attributes + */ +class VimAttributes { +} +exports.VimAttributes = VimAttributes; +VimAttributes.positions = 'g3d:vertex:position:0:float32:3'; +VimAttributes.indices = 'g3d:corner:index:0:int32:1'; +VimAttributes.instanceMeshes = 'g3d:instance:mesh:0:int32:1'; +VimAttributes.instanceTransforms = 'g3d:instance:transform:0:float32:16'; +VimAttributes.instanceNodes = 'g3d:instance:element:0:int32:1'; +VimAttributes.instanceFlags = 'g3d:instance:flags:0:uint16:1'; +VimAttributes.meshSubmeshes = 'g3d:mesh:submeshoffset:0:int32:1'; +VimAttributes.submeshIndexOffsets = 'g3d:submesh:indexoffset:0:int32:1'; +VimAttributes.submeshMaterials = 'g3d:submesh:material:0:int32:1'; +VimAttributes.materialColors = 'g3d:material:color:0:float32:4'; +VimAttributes.all = [ + VimAttributes.positions, + VimAttributes.indices, + VimAttributes.instanceMeshes, + VimAttributes.instanceTransforms, + VimAttributes.instanceFlags, + VimAttributes.meshSubmeshes, + VimAttributes.submeshIndexOffsets, + VimAttributes.submeshMaterials, + VimAttributes.materialColors +]; +/** + * G3D is a simple, efficient, generic binary format for storing and transmitting geometry. + * The G3D format is designed to be used either as a serialization format or as an in-memory data structure. + * A G3d with specific attributes according to the VIM format specification. + * See https://github.com/vimaec/vim#vim-geometry-attributes for the vim specification. + * See https://github.com/vimaec/g3d for the g3d specification. + */ +class G3d { + constructor(instanceMeshes, instanceFlags, instanceTransforms, instanceNodes, meshSubmeshes, submeshIndexOffsets, submeshMaterials, indices, positions, materialColors) { + /** + * Opaque white + */ + this.DEFAULT_COLOR = new Float32Array([1, 1, 1, 1]); + this.getVertexCount = () => this.positions.length / G3d.POSITION_SIZE; + this.getIndexCount = () => this.indices.length; + // ------------- Meshes ----------------- + this.getMeshCount = () => this.meshSubmeshes.length; + // ------------- Instances ----------------- + this.getInstanceCount = () => this.instanceMeshes.length; + // ------------- Material ----------------- + this.getMaterialCount = () => this.materialColors.length / G3d.COLOR_SIZE; + this.instanceMeshes = instanceMeshes; + this.instanceFlags = instanceFlags; + this.instanceTransforms = instanceTransforms; + this.instanceNodes = instanceNodes; + this.meshSubmeshes = meshSubmeshes; + this.submeshIndexOffset = submeshIndexOffsets; + this.submeshMaterial = submeshMaterials; + this.indices = indices instanceof Uint32Array ? indices : new Uint32Array(indices.buffer); + this.positions = positions; + this.materialColors = materialColors; + if (this.instanceFlags === undefined) { + this.instanceFlags = new Uint16Array(this.instanceMeshes.length); + } + if (this.instanceNodes === undefined) { + this.instanceNodes = new Int32Array(instanceMeshes.length); + for (let i = 0; i < this.instanceNodes.length; i++) { + this.instanceNodes[i] = i; + } + } + this.meshVertexOffsets = this.computeMeshVertexOffsets(); + this.rebaseIndices(); + this.meshInstances = this.computeMeshInstances(); + this.meshOpaqueCount = this.computeMeshOpaqueCount(); + this.sortSubmeshes(); + const range = this.computeSubmeshVertexRange(); + this.submeshVertexStart = range.start; + this.submeshVertexEnd = range.end; + } + computeSubmeshVertexRange() { + const submeshCount = this.getSubmeshCount(); + const start = new Int32Array(submeshCount); + const end = new Int32Array(submeshCount); + for (let sub = 0; sub < submeshCount; sub++) { + let min = Number.MAX_SAFE_INTEGER; + let max = Number.MIN_SAFE_INTEGER; + const subStart = this.getSubmeshIndexStart(sub); + const subEnd = this.getSubmeshIndexEnd(sub); + for (let i = subStart; i < subEnd; i++) { + const index = this.indices[i]; + min = Math.min(min, index); + max = Math.max(min, index); + } + start[sub] = min; + end[sub] = max; + } + return { start, end }; + } + static createFromAbstract(g3d) { + const instanceMeshes = g3d.findAttribute(VimAttributes.instanceMeshes) + ?.data; + const instanceTransforms = g3d.findAttribute(VimAttributes.instanceTransforms)?.data; + const instanceFlags = g3d.findAttribute(VimAttributes.instanceFlags)?.data ?? + new Uint16Array(instanceMeshes.length); + const instanceNodes = g3d.findAttribute(VimAttributes.instanceNodes)?.data; + const meshSubmeshes = g3d.findAttribute(VimAttributes.meshSubmeshes) + ?.data; + const submeshIndexOffset = g3d.findAttribute(VimAttributes.submeshIndexOffsets)?.data; + const submeshMaterial = g3d.findAttribute(VimAttributes.submeshMaterials) + ?.data; + const indices = g3d.findAttribute(VimAttributes.indices)?.data; + const positions = g3d.findAttribute(VimAttributes.positions) + ?.data; + const materialColors = g3d.findAttribute(VimAttributes.materialColors) + ?.data; + const result = new G3d(instanceMeshes, instanceFlags, instanceTransforms, instanceNodes, meshSubmeshes, submeshIndexOffset, submeshMaterial, indices, positions, materialColors); + result.rawG3d = g3d; + return result; + } + static async createFromPath(path) { + const f = await fetch(path); + const buffer = await f.arrayBuffer(); + const bfast = new bfast_1.BFast(buffer); + return this.createFromBfast(bfast); + } + static async createFromBfast(bfast) { + const g3d = await abstractG3d_1.AbstractG3d.createFromBfast(bfast, VimAttributes.all); + return G3d.createFromAbstract(g3d); + } + /** + * Computes the index of the first vertex of each mesh + */ + computeMeshVertexOffsets() { + const result = new Int32Array(this.getMeshCount()); + for (let m = 0; m < result.length; m++) { + let min = Number.MAX_SAFE_INTEGER; + const start = this.getMeshIndexStart(m, 'all'); + const end = this.getMeshIndexEnd(m, 'all'); + for (let i = start; i < end; i++) { + min = Math.min(min, this.indices[i]); + } + result[m] = min; + } + return result; + } + /** + * Computes all instances pointing to each mesh. + */ + computeMeshInstances() { + const result = new Array(this.getMeshCount()); + for (let i = 0; i < this.instanceMeshes.length; i++) { + const mesh = this.instanceMeshes[i]; + if (mesh < 0) + continue; + const instanceIndices = result[mesh]; + if (instanceIndices) + instanceIndices.push(i); + else + result[mesh] = [i]; + } + return result; + } + /** + * Reorders submeshIndexOffset, submeshMaterials and indices + * such that for each mesh, submeshes are sorted according to material alpha. + * This enables efficient splitting of arrays into opaque and transparent continuous ranges. + */ + sortSubmeshes() { + // We need to compute where submeshes end before we can reorder them. + const submeshEnd = this.computeSubmeshEnd(); + // We need to compute mesh index offsets from before we swap thins around to recompute new submesh offsets. + const meshIndexOffsets = this.computeMeshIndexOffsets(); + const meshCount = this.getMeshCount(); + const meshReordered = new Array(meshCount); + const submeshArrays = [ + this.submeshIndexOffset, + this.submeshMaterial, + submeshEnd + ]; + // Largest mesh size thus minimum buffer size to use to reorder indices. + const largestMesh = this.reorderSubmeshes(submeshArrays, meshReordered); + this.reorderIndices(meshIndexOffsets, submeshEnd, meshReordered, largestMesh); + } + /** + * Stores result of getSubmeshIndexEnd for each submesh in an array + */ + computeSubmeshEnd() { + const submeshCount = this.getSubmeshCount(); + const result = new Int32Array(submeshCount); + for (let s = 0; s < submeshCount; s++) { + result[s] = this.getSubmeshIndexEnd(s); + } + return result; + } + /** + * Stores result of getMeshIndexStart for each mesh in an array + */ + computeMeshIndexOffsets() { + const meshCount = this.getMeshCount(); + const result = new Int32Array(meshCount); + for (let m = 0; m < meshCount; m++) { + result[m] = this.getMeshIndexStart(m, 'all'); + } + return result; + } + /** + * Reorder submesh arrays and returns size of largest reordered mesh + */ + reorderSubmeshes(submeshArrays, reordered) { + const meshCount = this.getMeshCount(); + let largestMesh = 0; + for (let m = 0; m < meshCount; m++) { + const subStart = this.getMeshSubmeshStart(m, 'all'); + const subEnd = this.getMeshSubmeshEnd(m, 'all'); + if (subEnd - subStart <= 1) { + continue; + } + largestMesh = Math.max(largestMesh, this.getMeshIndexCount(m, 'all')); + reordered[m] = this.Sort(subStart, subEnd, (i) => this.getSubmeshAlpha(i), submeshArrays); + } + return largestMesh; + } + /** + * Sorts the range from start to end in every array provided in arrays in increasing criterion order. + * Using a simple bubble sort, there is a limited number of submeshes per mesh. + */ + Sort(start, end, criterion, arrays) { + let swapped = false; + while (true) { + let loop = false; + for (let i = start; i < end - 1; i++) { + if (criterion(i) < criterion(i + 1)) { + loop = true; + swapped = true; + for (let j = 0; j < arrays.length; j++) { + const array = arrays[j]; + const t = array[i]; + array[i] = array[i + 1]; + array[i + 1] = t; + } + } + } + if (!loop) { + break; + } + } + return swapped; + } + /** + * Reorders the index buffer to match the new order of the submesh arrays. + */ + reorderIndices(meshIndexOffsets, submeshEnd, meshReordered, bufferSize) { + const meshCount = this.getMeshCount(); + const buffer = new Float32Array(bufferSize); + for (let m = 0; m < meshCount; m++) { + if (!meshReordered[m]) + continue; + const meshOffset = meshIndexOffsets[m]; + const subStart = this.getMeshSubmeshStart(m, 'all'); + const subEnd = this.getMeshSubmeshEnd(m, 'all'); + let index = 0; + // Copy indices -> buffer, in sorted order. + for (let s = subStart; s < subEnd; s++) { + const start = this.submeshIndexOffset[s]; + const end = submeshEnd[s]; + // Change submesh offset to match new ordering + this.submeshIndexOffset[s] = meshOffset + index; + for (let i = start; i < end; i++) { + buffer[index++] = this.indices[i]; + } + } + // Copy buffer -> indices + for (let i = 0; i < index; i++) { + this.indices[meshOffset + i] = buffer[i]; + } + } + } + /** + * Rebase indices to be relative to its own mesh instead of to the whole g3d + */ + rebaseIndices() { + const count = this.getMeshCount(); + for (let m = 0; m < count; m++) { + const offset = this.meshVertexOffsets[m]; + const start = this.getMeshIndexStart(m, 'all'); + const end = this.getMeshIndexEnd(m, 'all'); + for (let i = start; i < end; i++) { + this.indices[i] -= offset; + } + } + } + unbaseIndices() { + const count = this.getMeshCount(); + for (let m = 0; m < count; m++) { + const offset = this.meshVertexOffsets[m]; + const start = this.getMeshIndexStart(m, 'all'); + const end = this.getMeshIndexEnd(m, 'all'); + for (let i = start; i < end; i++) { + this.indices[i] += offset; + } + } + } + /** + * Computes an array where true if any of the materials used by a mesh has transparency. + */ + computeMeshOpaqueCount() { + const result = new Int32Array(this.getMeshCount()); + for (let m = 0; m < result.length; m++) { + const subStart = this.getMeshSubmeshStart(m, 'all'); + const subEnd = this.getMeshSubmeshEnd(m, 'all'); + for (let s = subStart; s < subEnd; s++) { + const alpha = this.getSubmeshAlpha(s); + result[m] += alpha === 1 ? 1 : 0; + } + } + return result; + } + // ------------- All ----------------- + /**Given VIM instance indices returns the corresponding G3d indices */ + remapInstances(instances) { + const map = new Map(); + for (let i = 0; i < instances.length; i++) { + map.set(this.instanceNodes[i], i); + } + return instances.map((i) => map.get(i)); + } + getMeshInstanceCount(mesh) { + return this.meshInstances[mesh]?.length ?? 0; + } + getMeshIndexStart(mesh, section = 'all') { + const sub = this.getMeshSubmeshStart(mesh, section); + return this.getSubmeshIndexStart(sub); + } + getMeshIndexEnd(mesh, section = 'all') { + const sub = this.getMeshSubmeshEnd(mesh, section); + return this.getSubmeshIndexEnd(sub - 1); + } + getMeshIndexCount(mesh, section = 'all') { + return (this.getMeshIndexEnd(mesh, section) - + this.getMeshIndexStart(mesh, section)); + } + getMeshVertexStart(mesh) { + return this.meshVertexOffsets[mesh]; + } + getMeshVertexEnd(mesh) { + return mesh < this.meshVertexOffsets.length - 1 + ? this.meshVertexOffsets[mesh + 1] + : this.getVertexCount(); + } + getMeshVertexCount(mesh) { + return this.getMeshVertexEnd(mesh) - this.getMeshVertexStart(mesh); + } + getMeshSubmeshStart(mesh, section = 'all') { + if (section === 'transparent') { + return this.getMeshSubmeshEnd(mesh, 'opaque'); + } + return this.meshSubmeshes[mesh]; + } + getMeshSubmeshEnd(mesh, section = 'all') { + if (section === 'opaque') { + return this.meshSubmeshes[mesh] + this.meshOpaqueCount[mesh]; + } + return mesh < this.meshSubmeshes.length - 1 + ? this.meshSubmeshes[mesh + 1] + : this.getSubmeshCount(); + } + getMeshSubmeshCount(mesh, section = 'all') { + const end = this.getMeshSubmeshEnd(mesh, section); + const start = this.getMeshSubmeshStart(mesh, section); + return end - start; + } + getMeshHasTransparency(mesh) { + return this.getMeshSubmeshCount(mesh, 'transparent') > 0; + } + // ------------- Submeshes ----------------- + getSubmeshIndexStart(submesh) { + return submesh < this.submeshIndexOffset.length + ? this.submeshIndexOffset[submesh] + : this.indices.length; + } + getSubmeshIndexEnd(submesh) { + return submesh < this.submeshIndexOffset.length - 1 + ? this.submeshIndexOffset[submesh + 1] + : this.indices.length; + } + getSubmeshIndexCount(submesh) { + return this.getSubmeshIndexEnd(submesh) - this.getSubmeshIndexStart(submesh); + } + getSubmeshVertexStart(submesh) { + return this.submeshVertexStart[submesh]; + } + getSubmeshVertexEnd(submesh) { + return this.submeshVertexEnd[submesh]; + } + getSubmeshVertexCount(submesh) { + return this.getSubmeshVertexEnd(submesh) - this.getSubmeshVertexStart(submesh); + } + /** + * Returns color of given submesh as a 4-number array (RGBA) + * @param submesh g3d submesh index + */ + getSubmeshColor(submesh) { + return this.getMaterialColor(this.submeshMaterial[submesh]); + } + /** + * Returns color of given submesh as a 4-number array (RGBA) + * @param submesh g3d submesh index + */ + getSubmeshAlpha(submesh) { + return this.getMaterialAlpha(this.submeshMaterial[submesh]); + } + /** + * Returns true if submesh is transparent. + * @param submesh g3d submesh index + */ + getSubmeshIsTransparent(submesh) { + return this.getSubmeshAlpha(submesh) < 1; + } + /** + * Returns the total number of mesh in the g3d + */ + getSubmeshCount() { + return this.submeshIndexOffset.length; + } + /** + * Returns true if instance has given flag enabled. + * @param instance instance to check. + * @param flag to check against. + */ + getInstanceHasFlag(instance, flag) { + return (this.instanceFlags[instance] & flag) > 0; + } + /** + * Returns mesh index of given instance + * @param instance g3d instance index + */ + getInstanceMesh(instance) { + return this.instanceMeshes[instance]; + } + /** + * Returns an 16 number array representation of the matrix for given instance + * @param instance g3d instance index + */ + getInstanceMatrix(instance) { + return this.instanceTransforms.subarray(instance * G3d.MATRIX_SIZE, (instance + 1) * G3d.MATRIX_SIZE); + } + /** + * Returns color of given material as a 4-number array (RGBA) + * @param material g3d material index + */ + getMaterialColor(material) { + if (material < 0) + return this.DEFAULT_COLOR; + return this.materialColors.subarray(material * G3d.COLOR_SIZE, (material + 1) * G3d.COLOR_SIZE); + } + /** + * Returns the alpha component of given material + * @param material + */ + getMaterialAlpha(material) { + if (material < 0) + return 1; + const index = material * G3d.COLOR_SIZE + G3d.COLOR_SIZE - 1; + const result = this.materialColors[index]; + return result; + } + /** + * Concatenates two g3ds into a new g3d. + * @deprecated + */ + append(other) { + const _instanceFlags = new Uint16Array(this.instanceFlags.length + other.instanceFlags.length); + _instanceFlags.set(this.instanceFlags); + _instanceFlags.set(other.instanceFlags, this.instanceFlags.length); + const _instanceMeshes = new Int32Array(this.instanceMeshes.length + other.instanceMeshes.length); + _instanceMeshes.set(this.instanceMeshes); + _instanceMeshes.set(other.instanceMeshes.map(m => m >= 0 ? (m + this.meshSubmeshes.length) : -1), this.instanceMeshes.length); + const _instanceTransforms = new Float32Array(this.instanceTransforms.length + other.instanceTransforms.length); + _instanceTransforms.set(this.instanceTransforms); + _instanceTransforms.set(other.instanceTransforms, this.instanceTransforms.length); + const _positions = new Float32Array(this.positions.length + other.positions.length); + _positions.set(this.positions); + _positions.set(other.positions, this.positions.length); + this.unbaseIndices(); + other.unbaseIndices(); + const _indices = new Uint32Array(this.indices.length + other.indices.length); + _indices.set(this.indices); + _indices.set(other.indices.map(i => i + this.positions.length / 3), this.indices.length); + this.rebaseIndices(); + other.rebaseIndices(); + const _meshSubmeshes = new Int32Array(this.meshSubmeshes.length + other.meshSubmeshes.length); + _meshSubmeshes.set(this.meshSubmeshes); + _meshSubmeshes.set(other.meshSubmeshes.map(s => s + this.submeshIndexOffset.length), this.meshSubmeshes.length); + const _submeshIndexOffsets = new Int32Array(this.submeshIndexOffset.length + other.submeshIndexOffset.length); + _submeshIndexOffsets.set(this.submeshIndexOffset); + _submeshIndexOffsets.set(other.submeshIndexOffset.map(s => s + this.indices.length), this.submeshIndexOffset.length); + const _submeshMaterials = new Int32Array(this.submeshMaterial.length + other.submeshMaterial.length); + _submeshMaterials.set(this.submeshMaterial); + _submeshMaterials.set(other.submeshMaterial.map(s => s >= 0 ? (s + this.materialColors.length / 4) : -1), this.submeshMaterial.length); + const _materialColors = new Float32Array(this.materialColors.length + other.materialColors.length); + _materialColors.set(this.materialColors); + _materialColors.set(other.materialColors, this.materialColors.length); + const g3d = new G3d(_instanceMeshes, _instanceFlags, _instanceTransforms, undefined, _meshSubmeshes, _submeshIndexOffsets, _submeshMaterials, _indices, _positions, _materialColors); + return g3d; + } + validate() { + const isPresent = (attribute, label) => { + if (!attribute) { + throw new Error(`Missing Attribute Buffer: ${label}`); + } + }; + isPresent(this.positions, 'position'); + isPresent(this.indices, 'indices'); + isPresent(this.instanceMeshes, 'instanceMeshes'); + isPresent(this.instanceTransforms, 'instanceTransforms'); + isPresent(this.meshSubmeshes, 'meshSubmeshes'); + isPresent(this.submeshIndexOffset, 'submeshIndexOffset'); + isPresent(this.submeshMaterial, 'submeshMaterial'); + isPresent(this.materialColors, 'materialColors'); + // Basic + if (this.positions.length % G3d.POSITION_SIZE !== 0) { + throw new Error('Invalid position buffer, must be divisible by ' + G3d.POSITION_SIZE); + } + if (this.indices.length % 3 !== 0) { + throw new Error('Invalid Index Count, must be divisible by 3'); + } + for (let i = 0; i < this.indices.length; i++) { + if (this.indices[i] < 0 || this.indices[i] >= this.positions.length) { + throw new Error('Vertex index out of bound'); + } + } + // Instances + if (this.instanceMeshes.length !== + this.instanceTransforms.length / G3d.MATRIX_SIZE) { + throw new Error('Instance buffers mismatched'); + } + if (this.instanceTransforms.length % G3d.MATRIX_SIZE !== 0) { + throw new Error('Invalid InstanceTransform buffer, must respect arity ' + + G3d.MATRIX_SIZE); + } + for (let i = 0; i < this.instanceMeshes.length; i++) { + if (this.instanceMeshes[i] >= this.meshSubmeshes.length) { + throw new Error('Instance Mesh Out of range.'); + } + } + // Meshes + for (let i = 0; i < this.meshSubmeshes.length; i++) { + if (this.meshSubmeshes[i] < 0 || + this.meshSubmeshes[i] >= this.submeshIndexOffset.length) { + throw new Error('MeshSubmeshOffset out of bound at'); + } + } + for (let i = 0; i < this.meshSubmeshes.length - 1; i++) { + if (this.meshSubmeshes[i] >= this.meshSubmeshes[i + 1]) { + throw new Error('MeshSubmesh out of sequence.'); + } + } + // Submeshes + if (this.submeshIndexOffset.length !== this.submeshMaterial.length) { + throw new Error('Mismatched submesh buffers'); + } + for (let i = 0; i < this.submeshIndexOffset.length; i++) { + if (this.submeshIndexOffset[i] < 0 || + this.submeshIndexOffset[i] >= this.indices.length) { + throw new Error('SubmeshIndexOffset out of bound'); + } + } + for (let i = 0; i < this.submeshIndexOffset.length; i++) { + if (this.submeshIndexOffset[i] % 3 !== 0) { + throw new Error('Invalid SubmeshIndexOffset, must be divisible by 3'); + } + } + for (let i = 0; i < this.submeshIndexOffset.length - 1; i++) { + if (this.submeshIndexOffset[i] >= this.submeshIndexOffset[i + 1]) { + throw new Error('SubmeshIndexOffset out of sequence.'); + } + } + for (let i = 0; i < this.submeshMaterial.length; i++) { + if (this.submeshMaterial[i] >= this.materialColors.length) { + throw new Error('submeshMaterial out of bound'); + } + } + // Materials + if (this.materialColors.length % G3d.COLOR_SIZE !== 0) { + throw new Error('Invalid material color buffer, must be divisible by ' + G3d.COLOR_SIZE); + } + console.assert(this.meshInstances.length === this.getMeshCount()); + console.assert(this.meshOpaqueCount.length === this.getMeshCount()); + console.assert(this.meshSubmeshes.length === this.getMeshCount()); + console.assert(this.meshVertexOffsets.length === this.getMeshCount()); + for (let m = 0; m < this.getMeshCount(); m++) { + console.assert(this.getMeshSubmeshCount(m, 'opaque') + + this.getMeshSubmeshCount(m, 'transparent') === + this.getMeshSubmeshCount(m, 'all')); + console.assert(this.getMeshIndexCount(m, 'opaque') + + this.getMeshIndexCount(m, 'transparent') === + this.getMeshIndexCount(m, 'all')); + } + } +} +exports.G3d = G3d; +G3d.MATRIX_SIZE = 16; +G3d.COLOR_SIZE = 4; +G3d.POSITION_SIZE = 3; diff --git a/src/ts/dist/g3dAttributes.d.ts b/src/ts/dist/g3dAttributes.d.ts new file mode 100644 index 00000000..2258933d --- /dev/null +++ b/src/ts/dist/g3dAttributes.d.ts @@ -0,0 +1,20 @@ +export declare class G3dAttributeDescriptor { + description: string; + association: string; + semantic: string; + attributeTypeIndex: string; + dataType: string; + dataArity: number; + constructor(description: string, association: string, semantic: string, attributeTypeIndex: string, dataType: string, dataArity: string); + static fromString(descriptor: string): G3dAttributeDescriptor; + matches(other: G3dAttributeDescriptor): boolean; +} +export declare type TypedArray = Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Uint32Array | BigUint64Array | BigInt64Array | Float64Array; +export declare class G3dAttribute { + descriptor: G3dAttributeDescriptor; + bytes: Uint8Array; + data: TypedArray | undefined; + constructor(descriptor: G3dAttributeDescriptor, bytes: Uint8Array); + static fromString(descriptor: string, buffer: Uint8Array): G3dAttribute; + static castData(bytes: Uint8Array, dataType: string): TypedArray | undefined; +} diff --git a/src/ts/dist/g3dAttributes.js b/src/ts/dist/g3dAttributes.js new file mode 100644 index 00000000..eb39cf5d --- /dev/null +++ b/src/ts/dist/g3dAttributes.js @@ -0,0 +1,68 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.G3dAttribute = exports.G3dAttributeDescriptor = void 0; +class G3dAttributeDescriptor { + constructor(description, association, semantic, attributeTypeIndex, dataType, dataArity) { + if (!description.startsWith('g3d:')) { + throw new Error(`${description} must start with 'g3d'`); + } + this.description = description; + this.association = association; + this.semantic = semantic; + this.attributeTypeIndex = attributeTypeIndex; + this.dataType = dataType; + this.dataArity = parseInt(dataArity); + } + static fromString(descriptor) { + const desc = descriptor.split(':'); + if (desc.length !== 6) { + throw new Error(`${descriptor}, must have 6 components delimited by ':'`); + } + return new this(descriptor, desc[1], desc[2], desc[3], desc[4], desc[5]); + } + matches(other) { + const match = (a, b) => a === '*' || b === '*' || a === b; + return (match(this.association, other.association) && + match(this.semantic, other.semantic) && + match(this.attributeTypeIndex, other.attributeTypeIndex) && + match(this.dataType, other.dataType)); + } +} +exports.G3dAttributeDescriptor = G3dAttributeDescriptor; +class G3dAttribute { + constructor(descriptor, bytes) { + this.descriptor = descriptor; + this.bytes = bytes; + this.data = G3dAttribute.castData(bytes, descriptor.dataType); + } + static fromString(descriptor, buffer) { + return new this(G3dAttributeDescriptor.fromString(descriptor), buffer); + } + // Converts a VIM attribute into a typed array from its raw data + static castData(bytes, dataType) { + switch (dataType) { + case 'float32': + return new Float32Array(bytes.buffer, bytes.byteOffset, bytes.byteLength / 4); + case 'float64': + throw new Float64Array(bytes.buffer, bytes.byteOffset, bytes.byteLength / 8); + case 'uint8': + case 'int8': + return bytes; + case 'int16': + return new Int16Array(bytes.buffer, bytes.byteOffset, bytes.byteLength / 2); + case 'uint16': + return new Uint16Array(bytes.buffer, bytes.byteOffset, bytes.byteLength / 2); + case 'int32': + return new Int32Array(bytes.buffer, bytes.byteOffset, bytes.byteLength / 4); + case 'uint32': + return new Uint32Array(bytes.buffer, bytes.byteOffset, bytes.byteLength / 4); + case 'int64': + return new BigInt64Array(bytes.buffer, bytes.byteOffset, bytes.byteLength / 8); + case 'uint64': + return new BigUint64Array(bytes.buffer, bytes.byteOffset, bytes.byteLength / 8); + default: + console.error('Unrecognized attribute data type ' + dataType); + } + } +} +exports.G3dAttribute = G3dAttribute; diff --git a/src/ts/dist/g3dMaterials.d.ts b/src/ts/dist/g3dMaterials.d.ts new file mode 100644 index 00000000..8737e18d --- /dev/null +++ b/src/ts/dist/g3dMaterials.d.ts @@ -0,0 +1,38 @@ +/** + * @module vim-ts + */ +import { AbstractG3d } from './abstractG3d'; +import { BFast } from './bfast'; +/** + * See https://github.com/vimaec/vim#vim-geometry-attributes + */ +export declare class MaterialAttributes { + static materialColors: string; + static all: string[]; +} +/** + * G3D is a simple, efficient, generic binary format for storing and transmitting geometry. + * The G3D format is designed to be used either as a serialization format or as an in-memory data structure. + * A G3d with specific attributes according to the VIM format specification. + * See https://github.com/vimaec/vim#vim-geometry-attributes for the vim specification. + * See https://github.com/vimaec/g3d for the g3d specification. + */ +export declare class G3dMaterial { + static COLOR_SIZE: number; + rawG3d: AbstractG3d; + materialColors: Float32Array; + DEFAULT_COLOR: Float32Array; + constructor(materialColors: Float32Array); + static createFromAbstract(g3d: AbstractG3d): G3dMaterial; + static createFromPath(path: string): Promise; + static createFromBuffer(buffer: ArrayBuffer): Promise; + static createFromBfast(bfast: BFast): Promise; + toG3d(): G3dMaterial; + getMaterialCount: () => number; + /** + * Returns color of given material as a 4-number array (RGBA) + * @param material g3d material index + */ + getMaterialColor(material: number): Float32Array; + getMaterialAlpha(material: number): number; +} diff --git a/src/ts/dist/g3dMaterials.js b/src/ts/dist/g3dMaterials.js new file mode 100644 index 00000000..a8c71df3 --- /dev/null +++ b/src/ts/dist/g3dMaterials.js @@ -0,0 +1,74 @@ +"use strict"; +/** + * @module vim-ts + */ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.G3dMaterial = exports.MaterialAttributes = void 0; +const abstractG3d_1 = require("./abstractG3d"); +const bfast_1 = require("./bfast"); +/** + * See https://github.com/vimaec/vim#vim-geometry-attributes + */ +class MaterialAttributes { +} +exports.MaterialAttributes = MaterialAttributes; +MaterialAttributes.materialColors = 'g3d:material:color:0:float32:4'; +MaterialAttributes.all = [ + MaterialAttributes.materialColors +]; +/** + * G3D is a simple, efficient, generic binary format for storing and transmitting geometry. + * The G3D format is designed to be used either as a serialization format or as an in-memory data structure. + * A G3d with specific attributes according to the VIM format specification. + * See https://github.com/vimaec/vim#vim-geometry-attributes for the vim specification. + * See https://github.com/vimaec/g3d for the g3d specification. + */ +class G3dMaterial { + constructor(materialColors) { + this.DEFAULT_COLOR = new Float32Array([1, 1, 1, 1]); + this.getMaterialCount = () => this.materialColors.length / G3dMaterial.COLOR_SIZE; + this.materialColors = materialColors; + } + static createFromAbstract(g3d) { + const materialColors = g3d.findAttribute(MaterialAttributes.materialColors) + ?.data; + const result = new G3dMaterial(materialColors); + result.rawG3d = g3d; + return result; + } + static async createFromPath(path) { + const f = await fetch(path); + const buffer = await f.arrayBuffer(); + var g3d = this.createFromBuffer(buffer); + return g3d; + } + static async createFromBuffer(buffer) { + const bfast = new bfast_1.BFast(buffer); + return this.createFromBfast(bfast); + } + static async createFromBfast(bfast) { + const g3d = await abstractG3d_1.AbstractG3d.createFromBfast(bfast, MaterialAttributes.all); + return G3dMaterial.createFromAbstract(g3d); + } + toG3d() { + return new G3dMaterial(this.materialColors); + } + /** + * Returns color of given material as a 4-number array (RGBA) + * @param material g3d material index + */ + getMaterialColor(material) { + if (material < 0) + return this.DEFAULT_COLOR; + return this.materialColors.subarray(material * G3dMaterial.COLOR_SIZE, (material + 1) * G3dMaterial.COLOR_SIZE); + } + getMaterialAlpha(material) { + if (material < 0) + return 1; + const index = material * G3dMaterial.COLOR_SIZE + G3dMaterial.COLOR_SIZE - 1; + const result = this.materialColors[index]; + return result; + } +} +exports.G3dMaterial = G3dMaterial; +G3dMaterial.COLOR_SIZE = 4; diff --git a/src/ts/dist/g3dMesh.d.ts b/src/ts/dist/g3dMesh.d.ts new file mode 100644 index 00000000..3f755f41 --- /dev/null +++ b/src/ts/dist/g3dMesh.d.ts @@ -0,0 +1,79 @@ +/** + * @module vim-ts + */ +import { AbstractG3d } from './abstractG3d'; +import { BFast } from './bfast'; +import { MeshSection } from './g3d'; +import { G3dScene } from './g3dScene'; +/** + * See https://github.com/vimaec/vim#vim-geometry-attributes + */ +export declare class MeshAttributes { + static instanceTransforms: string; + static meshOpaqueSubmeshCount: string; + static submeshIndexOffsets: string; + static submeshVertexOffsets: string; + static submeshMaterials: string; + static positions: string; + static indices: string; + static all: string[]; +} +/** + * G3D is a simple, efficient, generic binary format for storing and transmitting geometry. + * The G3D format is designed to be used either as a serialization format or as an in-memory data structure. + * A G3d with specific attributes according to the VIM format specification. + * See https://github.com/vimaec/vim#vim-geometry-attributes for the vim specification. + * See https://github.com/vimaec/g3d for the g3d specification. + */ +export declare class G3dMesh { + scene: G3dScene; + meshIndex: number; + rawG3d: AbstractG3d; + instanceTransforms: Float32Array; + meshOpaqueSubmeshCount: number; + submeshIndexOffset: Int32Array; + submeshVertexOffset: Int32Array; + submeshMaterial: Int32Array; + positions: Float32Array; + indices: Uint32Array; + static MATRIX_SIZE: number; + static COLOR_SIZE: number; + static POSITION_SIZE: number; + /** + * Opaque white + */ + DEFAULT_COLOR: Float32Array; + constructor(instanceTransforms: Float32Array, meshOpaqueSubmeshCount: number, submeshIndexOffsets: Int32Array, submeshVertexOffsets: Int32Array, submeshMaterials: Int32Array, indices: Int32Array | Uint32Array, positions: Float32Array); + static createFromAbstract(g3d: AbstractG3d): G3dMesh; + static createFromPath(path: string): Promise; + static createFromBuffer(buffer: ArrayBuffer): Promise; + static createFromBfast(bfast: BFast): Promise; + getBimInstance(meshInstance: number): number; + getInstanceMax(meshInstance: number): Float32Array; + getInstanceMin(meshInstance: number): Float32Array; + getInstanceGroup(meshInstance: number): number; + getInstanceTag(meshInstance: number): bigint; + getInstanceHasFlag(meshInstance: number, flag: number): boolean; + getInstanceCount: () => number; + /** + * Returns an 16 number array representation of the matrix for given instance + * @param instance g3d instance index + */ + getInstanceMatrix(instance: number): Float32Array; + getVertexStart(section?: MeshSection): number; + getVertexEnd(section?: MeshSection): number; + getVertexCount(section?: MeshSection): number; + getIndexStart(section?: MeshSection): number; + getIndexEnd(section?: MeshSection): number; + getIndexCount(section?: MeshSection): number; + getHasTransparency(): boolean; + getSubmeshStart(section: MeshSection): number; + getSubmeshEnd(section: MeshSection): number; + getSubmeshCount(section: MeshSection): number; + getSubmeshIndexStart(submesh: number): number; + getSubmeshIndexEnd(submesh: number): number; + getSubmeshIndexCount(submesh: number): number; + getSubmeshVertexStart(submesh: number): number; + getSubmeshVertexEnd(submesh: number): number; + getSubmeshVertexCount(submesh: number): number; +} diff --git a/src/ts/dist/g3dMesh.js b/src/ts/dist/g3dMesh.js new file mode 100644 index 00000000..b5be09e7 --- /dev/null +++ b/src/ts/dist/g3dMesh.js @@ -0,0 +1,189 @@ +"use strict"; +/** + * @module vim-ts + */ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.G3dMesh = exports.MeshAttributes = void 0; +const abstractG3d_1 = require("./abstractG3d"); +const bfast_1 = require("./bfast"); +const g3d_1 = require("./g3d"); +/** + * See https://github.com/vimaec/vim#vim-geometry-attributes + */ +class MeshAttributes { +} +exports.MeshAttributes = MeshAttributes; +MeshAttributes.instanceTransforms = 'g3d:instance:transform:0:float32:16'; +MeshAttributes.meshOpaqueSubmeshCount = 'g3d:mesh:opaquesubmeshcount:0:int32:1'; +MeshAttributes.submeshIndexOffsets = 'g3d:submesh:indexoffset:0:int32:1'; +MeshAttributes.submeshVertexOffsets = 'g3d:submesh:vertexoffset:0:int32:1'; +MeshAttributes.submeshMaterials = 'g3d:submesh:material:0:int32:1'; +MeshAttributes.positions = 'g3d:vertex:position:0:float32:3'; +MeshAttributes.indices = 'g3d:corner:index:0:int32:1'; +MeshAttributes.all = [ + MeshAttributes.instanceTransforms, + MeshAttributes.meshOpaqueSubmeshCount, + MeshAttributes.submeshIndexOffsets, + MeshAttributes.submeshVertexOffsets, + MeshAttributes.submeshMaterials, + MeshAttributes.positions, + MeshAttributes.indices, +]; +/** + * G3D is a simple, efficient, generic binary format for storing and transmitting geometry. + * The G3D format is designed to be used either as a serialization format or as an in-memory data structure. + * A G3d with specific attributes according to the VIM format specification. + * See https://github.com/vimaec/vim#vim-geometry-attributes for the vim specification. + * See https://github.com/vimaec/g3d for the g3d specification. + */ +class G3dMesh { + constructor(instanceTransforms, meshOpaqueSubmeshCount, submeshIndexOffsets, submeshVertexOffsets, submeshMaterials, indices, positions) { + /** + * Opaque white + */ + this.DEFAULT_COLOR = new Float32Array([1, 1, 1, 1]); + this.getInstanceCount = () => this.instanceTransforms.length; + this.instanceTransforms = instanceTransforms; + this.meshOpaqueSubmeshCount = meshOpaqueSubmeshCount; + this.submeshIndexOffset = submeshIndexOffsets; + this.submeshVertexOffset = submeshVertexOffsets; + this.submeshMaterial = submeshMaterials; + this.indices = indices instanceof Uint32Array ? indices : new Uint32Array(indices.buffer); + this.positions = positions; + } + static createFromAbstract(g3d) { + const instanceTransforms = g3d.findAttribute(MeshAttributes.instanceTransforms)?.data; + const meshOpaqueSubmeshCountArray = g3d.findAttribute(MeshAttributes.meshOpaqueSubmeshCount)?.data; + const meshOpaqueSubmeshCount = meshOpaqueSubmeshCountArray[0]; + const submeshIndexOffsets = g3d.findAttribute(MeshAttributes.submeshIndexOffsets)?.data; + const submeshVertexOffsets = g3d.findAttribute(MeshAttributes.submeshVertexOffsets)?.data; + const submeshMaterial = g3d.findAttribute(MeshAttributes.submeshMaterials) + ?.data; + const indices = g3d.findAttribute(MeshAttributes.indices)?.data; + const positions = g3d.findAttribute(MeshAttributes.positions) + ?.data; + const result = new G3dMesh(instanceTransforms, meshOpaqueSubmeshCount, submeshIndexOffsets, submeshVertexOffsets, submeshMaterial, indices, positions); + result.rawG3d = g3d; + return result; + } + static async createFromPath(path) { + const f = await fetch(path); + const buffer = await f.arrayBuffer(); + var g3d = this.createFromBuffer(buffer); + return g3d; + } + static async createFromBuffer(buffer) { + const bfast = new bfast_1.BFast(buffer); + return this.createFromBfast(bfast); + } + static async createFromBfast(bfast) { + const g3d = await abstractG3d_1.AbstractG3d.createFromBfast(bfast, MeshAttributes.all); + return G3dMesh.createFromAbstract(g3d); + } + // -----------Instances--------------- + getBimInstance(meshInstance) { + const sceneInstance = this.scene.getMeshSceneInstance(this.meshIndex, meshInstance); + return this.scene.instanceNodes[sceneInstance]; + } + getInstanceMax(meshInstance) { + const sceneInstance = this.scene.getMeshSceneInstance(this.meshIndex, meshInstance); + return this.scene.instanceMaxs.subarray(sceneInstance * 3, (sceneInstance + 1) * 3); + } + getInstanceMin(meshInstance) { + const sceneInstance = this.scene.getMeshSceneInstance(this.meshIndex, meshInstance); + return this.scene.instanceMins.subarray(sceneInstance * 3, (sceneInstance + 1) * 3); + } + getInstanceGroup(meshInstance) { + const sceneInstance = this.scene.getMeshSceneInstance(this.meshIndex, meshInstance); + return this.scene.instanceGroups[sceneInstance]; + } + getInstanceTag(meshInstance) { + const sceneInstance = this.scene.getMeshSceneInstance(this.meshIndex, meshInstance); + return this.scene.instanceTags[sceneInstance]; + } + getInstanceHasFlag(meshInstance, flag) { + const sceneInstance = this.scene.getMeshSceneInstance(this.meshIndex, meshInstance); + return (this.scene.instanceFlags[sceneInstance] & flag) > 0; + } + /** + * Returns an 16 number array representation of the matrix for given instance + * @param instance g3d instance index + */ + getInstanceMatrix(instance) { + return this.instanceTransforms.subarray(instance * G3dMesh.MATRIX_SIZE, (instance + 1) * G3dMesh.MATRIX_SIZE); + } + // ------------- Mesh ----------------- + getVertexStart(section = 'all') { + const sub = this.getSubmeshStart(section); + return this.getSubmeshVertexStart(sub); + } + getVertexEnd(section = 'all') { + const sub = this.getSubmeshEnd(section); + return this.getSubmeshVertexStart(sub); + } + getVertexCount(section = 'all') { + return this.getVertexEnd(section) - this.getVertexStart(section); + } + getIndexStart(section = 'all') { + const sub = this.getSubmeshStart(section); + return this.getSubmeshIndexStart(sub); + } + getIndexEnd(section = 'all') { + const sub = this.getSubmeshEnd(section); + return this.getSubmeshIndexStart(sub); + } + getIndexCount(section = 'all') { + return this.getIndexEnd(section) - this.getIndexStart(section); + } + getHasTransparency() { + return this.meshOpaqueSubmeshCount < this.submeshIndexOffset.length; + } + // ------------- Submeshes ----------------- + getSubmeshStart(section) { + if (section === 'all') + return 0; + if (section === 'opaque') + return 0; + return this.meshOpaqueSubmeshCount; + } + getSubmeshEnd(section) { + if (section === 'all') + return this.submeshIndexOffset.length; + if (section === 'transparent') + return this.submeshIndexOffset.length; + return this.meshOpaqueSubmeshCount; + } + getSubmeshCount(section) { + return this.getSubmeshEnd(section) - this.getSubmeshStart(section); + } + getSubmeshIndexStart(submesh) { + return submesh < this.submeshIndexOffset.length + ? this.submeshIndexOffset[submesh] + : this.indices.length; + } + getSubmeshIndexEnd(submesh) { + return submesh < this.submeshIndexOffset.length - 1 + ? this.submeshIndexOffset[submesh + 1] + : this.indices.length; + } + getSubmeshIndexCount(submesh) { + return this.getSubmeshIndexEnd(submesh) - this.getSubmeshIndexStart(submesh); + } + getSubmeshVertexStart(submesh) { + return submesh < this.submeshIndexOffset.length + ? this.submeshVertexOffset[submesh] + : this.positions.length / g3d_1.G3d.POSITION_SIZE; + } + getSubmeshVertexEnd(submesh) { + return submesh < this.submeshVertexOffset.length - 1 + ? this.submeshVertexOffset[submesh + 1] + : this.positions.length / g3d_1.G3d.POSITION_SIZE; + } + getSubmeshVertexCount(submesh) { + return this.getSubmeshVertexEnd(submesh) - this.getSubmeshVertexStart(submesh); + } +} +exports.G3dMesh = G3dMesh; +G3dMesh.MATRIX_SIZE = 16; +G3dMesh.COLOR_SIZE = 4; +G3dMesh.POSITION_SIZE = 3; diff --git a/src/ts/dist/g3dMeshIndex.d.ts b/src/ts/dist/g3dMeshIndex.d.ts new file mode 100644 index 00000000..af2886a7 --- /dev/null +++ b/src/ts/dist/g3dMeshIndex.d.ts @@ -0,0 +1,61 @@ +/** + * @module vim-ts + */ +import { AbstractG3d } from './abstractG3d'; +import { BFast } from './bfast'; +import { MeshSection } from './g3d'; +export declare type FilterMode = undefined | 'mesh' | 'instance' | 'group' | 'tag'; +/** + * See https://github.com/vimaec/vim#vim-geometry-attributes + */ +export declare class SceneAttributes { + static instanceFiles: string; + static instanceIndices: string; + static instanceNodes: string; + static instanceGroups: string; + static instanceTags: string; + static instanceMins: string; + static instanceMaxs: string; + static meshInstanceCounts: string; + static meshIndexCounts: string; + static meshVertexCounts: string; + static meshOpaqueIndexCount: string; + static meshOpaqueVertexCount: string; + static all: string[]; +} +/** + * Represents the index, as in book index, of a collection of G3dMesh. + * Allows to find and download G3dMesh as needed. + * Allows to preallocate geometry to render G3dMeshes. + */ +export declare class G3dScene { + rawG3d: AbstractG3d; + instanceMeshes: Int32Array; + instanceIndices: Int32Array; + instanceNodes: Int32Array; + instanceGroups: Int32Array; + instanceTags: BigInt64Array; + instanceMins: Float32Array; + instanceMaxs: Float32Array; + meshInstanceCounts: Int32Array; + meshIndexCounts: Int32Array; + meshVertexCounts: Int32Array; + meshOpaqueIndexCounts: Int32Array; + meshOpaqueVertexCounts: Int32Array; + private nodeToInstance; + private meshSceneInstances; + constructor(rawG3d: AbstractG3d, instanceFiles: Int32Array, instanceIndices: Int32Array, instanceNodes: Int32Array, instanceGroups: Int32Array, instanceTags: BigInt64Array, instanceMins: Float32Array, instanceMaxs: Float32Array, meshInstanceCounts: Int32Array, meshIndexCounts: Int32Array, meshVertexCounts: Int32Array, meshOpaqueIndexCounts: Int32Array, meshOpaqueVertexCounts: Int32Array); + private createMap; + static createFromAbstract(g3d: AbstractG3d): G3dScene; + static createFromPath(path: string): Promise; + static createFromBfast(bfast: BFast): Promise; + getMeshSceneInstance(mesh: number, meshIndex: number): number; + getMeshCount(): number; + getMeshIndexCount(mesh: number, section: MeshSection): number; + getMeshVertexCount(mesh: number, section: MeshSection): number; + getMeshInstanceCount(mesh: number): number; + getNodeMin(node: number): Float32Array; + getNodeMax(node: number): Float32Array; + getInstanceMin(instance: number): Float32Array; + getInstanceMax(instance: number): Float32Array; +} diff --git a/src/ts/dist/g3dMeshIndex.js b/src/ts/dist/g3dMeshIndex.js new file mode 100644 index 00000000..8e5a8e63 --- /dev/null +++ b/src/ts/dist/g3dMeshIndex.js @@ -0,0 +1,142 @@ +"use strict"; +/** + * @module vim-ts + */ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.G3dScene = exports.SceneAttributes = void 0; +const abstractG3d_1 = require("./abstractG3d"); +const bfast_1 = require("./bfast"); +const g3d_1 = require("./g3d"); +/** + * See https://github.com/vimaec/vim#vim-geometry-attributes + */ +class SceneAttributes { +} +exports.SceneAttributes = SceneAttributes; +SceneAttributes.instanceFiles = 'g3d:instance:file:0:int32:1'; +SceneAttributes.instanceIndices = 'g3d:instance:index:0:int32:1'; +SceneAttributes.instanceNodes = 'g3d:instance:node:0:int32:1'; +SceneAttributes.instanceGroups = 'g3d:instance:group:0:int32:1'; +SceneAttributes.instanceTags = 'g3d:instance:tag:0:int64:1'; +SceneAttributes.instanceMins = 'g3d:instance:min:0:float32:3'; +SceneAttributes.instanceMaxs = 'g3d:instance:max:0:float32:3'; +SceneAttributes.meshInstanceCounts = 'g3d:mesh:instancecount:0:int32:1'; +SceneAttributes.meshIndexCounts = 'g3d:mesh:indexcount:0:int32:1'; +SceneAttributes.meshVertexCounts = 'g3d:mesh:vertexcount:0:int32:1'; +SceneAttributes.meshOpaqueIndexCount = "g3d:mesh:opaqueindexcount:0:int32:1"; +SceneAttributes.meshOpaqueVertexCount = "g3d:mesh:opaquevertexcount:0:int32:1"; +SceneAttributes.all = [ + SceneAttributes.instanceFiles, + SceneAttributes.instanceIndices, + SceneAttributes.instanceNodes, + SceneAttributes.instanceGroups, + SceneAttributes.instanceTags, + SceneAttributes.instanceMins, + SceneAttributes.instanceMaxs, + SceneAttributes.meshInstanceCounts, + SceneAttributes.meshIndexCounts, + SceneAttributes.meshVertexCounts, + SceneAttributes.meshOpaqueIndexCount, + SceneAttributes.meshOpaqueVertexCount, +]; +/** + * Represents the index, as in book index, of a collection of G3dMesh. + * Allows to find and download G3dMesh as needed. + * Allows to preallocate geometry to render G3dMeshes. + */ +class G3dScene { + constructor(rawG3d, instanceFiles, instanceIndices, instanceNodes, instanceGroups, instanceTags, instanceMins, instanceMaxs, meshInstanceCounts, meshIndexCounts, meshVertexCounts, meshOpaqueIndexCounts, meshOpaqueVertexCounts) { + this.rawG3d = rawG3d; + this.instanceMeshes = instanceFiles; + this.instanceIndices = instanceIndices; + this.instanceNodes = instanceNodes; + this.instanceGroups = instanceGroups; + this.instanceTags = instanceTags; + this.instanceMins = instanceMins; + this.instanceMaxs = instanceMaxs; + this.meshInstanceCounts = meshInstanceCounts; + this.meshIndexCounts = meshIndexCounts; + this.meshVertexCounts = meshVertexCounts; + this.meshOpaqueIndexCounts = meshOpaqueIndexCounts; + this.meshOpaqueVertexCounts = meshOpaqueVertexCounts; + // Reverse instanceNodes + this.nodeToInstance = new Map(); + for (let i = 0; i < this.instanceNodes.length; i++) { + this.nodeToInstance.set(this.instanceNodes[i], i); + } + this.meshSceneInstances = this.createMap(); + } + createMap() { + // From : (mesh, scene-index) -> mesh-index + // To: (mesh, mesh-index) -> scene-index + const map = new Map(); + for (let i = 0; i < this.instanceMeshes.length; i++) { + const mesh = this.instanceMeshes[i]; + const index = this.instanceIndices[i]; + const indices = map.get(mesh) ?? new Map(); + indices.set(index, i); + map.set(mesh, indices); + } + return map; + } + static createFromAbstract(g3d) { + function getArray(attribute) { + return g3d.findAttribute(attribute)?.data; + } + return new G3dScene(g3d, getArray(SceneAttributes.instanceFiles), getArray(SceneAttributes.instanceIndices), getArray(SceneAttributes.instanceNodes), getArray(SceneAttributes.instanceGroups), getArray(SceneAttributes.instanceTags), getArray(SceneAttributes.instanceMins), getArray(SceneAttributes.instanceMaxs), getArray(SceneAttributes.meshInstanceCounts), getArray(SceneAttributes.meshIndexCounts), getArray(SceneAttributes.meshVertexCounts), getArray(SceneAttributes.meshOpaqueIndexCount), getArray(SceneAttributes.meshOpaqueVertexCount)); + } + static async createFromPath(path) { + const f = await fetch(path); + const buffer = await f.arrayBuffer(); + const bfast = new bfast_1.BFast(buffer); + return this.createFromBfast(bfast); + } + static async createFromBfast(bfast) { + const g3d = await abstractG3d_1.AbstractG3d.createFromBfast(bfast, SceneAttributes.all); + return G3dScene.createFromAbstract(g3d); + } + getMeshSceneInstance(mesh, meshIndex) { + return this.meshSceneInstances.get(mesh)?.get(meshIndex); + } + getMeshCount() { + return this.meshInstanceCounts.length; + } + getMeshIndexCount(mesh, section) { + const all = this.meshIndexCounts[mesh]; + if (section === 'all') + return all; + const opaque = this.meshOpaqueIndexCounts[mesh]; + return section === 'opaque' ? opaque : all - opaque; + } + getMeshVertexCount(mesh, section) { + const all = this.meshVertexCounts[mesh]; + if (section === 'all') + return all; + const opaque = this.meshOpaqueVertexCounts[mesh]; + return section === 'opaque' ? opaque : all - opaque; + } + getMeshInstanceCount(mesh) { + return this.meshInstanceCounts[mesh]; + } + getNodeMin(node) { + const instance = this.nodeToInstance.get(node); + if (!node) { + return undefined; + } + return this.getInstanceMin(instance); + } + getNodeMax(node) { + const instance = this.nodeToInstance.get(node); + if (!node) { + return undefined; + } + return this.getInstanceMax(instance); + } + getInstanceMin(instance) { + return this.instanceMins.subarray(instance * g3d_1.G3d.POSITION_SIZE); + } + getInstanceMax(instance) { + return this.instanceMaxs.subarray(instance * g3d_1.G3d.POSITION_SIZE); + } +} +exports.G3dScene = G3dScene; diff --git a/src/ts/dist/g3dMeshOffsets.d.ts b/src/ts/dist/g3dMeshOffsets.d.ts new file mode 100644 index 00000000..b9295313 --- /dev/null +++ b/src/ts/dist/g3dMeshOffsets.d.ts @@ -0,0 +1,41 @@ +import { MeshSection } from "./g3d"; +import { G3dSubset } from "./g3dSubset"; +export declare class G3dMeshCounts { + instances: number; + meshes: number; + indices: number; + vertices: number; +} +/** + * Holds the offsets needed to preallocate geometry for a given meshIndexSubset + */ +export declare class G3dMeshOffsets { + subset: G3dSubset; + section: MeshSection; + counts: G3dMeshCounts; + indexOffsets: Int32Array; + vertexOffsets: Int32Array; + /** + * Computes geometry offsets for given subset and section + * @param subset subset for which to compute offsets + * @param section on of 'opaque' | 'transparent' | 'all' + */ + static fromSubset(subset: G3dSubset, section: MeshSection): G3dMeshOffsets; + getIndexOffset(mesh: number): number; + getVertexOffset(mesh: number): number; + /** + * Returns how many instances of given meshes are the filtered view. + */ + getMeshInstanceCount(mesh: number): number; + /** + * Returns instance for given mesh. + * @mesh view-relative mesh index + * @at view-relative instance index for given mesh + * @returns mesh-relative instance index + */ + getMeshInstance(mesh: number, index: number): number; + /** + * Returns the vim-relative mesh index at given index + */ + getMesh(index: number): number; +} diff --git a/src/ts/dist/g3dMeshOffsets.js b/src/ts/dist/g3dMeshOffsets.js new file mode 100644 index 00000000..f9d4eba7 --- /dev/null +++ b/src/ts/dist/g3dMeshOffsets.js @@ -0,0 +1,71 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.G3dMeshOffsets = exports.G3dMeshCounts = void 0; +class G3dMeshCounts { + constructor() { + this.instances = 0; + this.meshes = 0; + this.indices = 0; + this.vertices = 0; + } +} +exports.G3dMeshCounts = G3dMeshCounts; +/** + * Holds the offsets needed to preallocate geometry for a given meshIndexSubset + */ +class G3dMeshOffsets { + /** + * Computes geometry offsets for given subset and section + * @param subset subset for which to compute offsets + * @param section on of 'opaque' | 'transparent' | 'all' + */ + static fromSubset(subset, section) { + var result = new G3dMeshOffsets(); + result.subset = subset; + result.section = section; + function computeOffsets(getter) { + const meshCount = subset.getMeshCount(); + const offsets = new Int32Array(meshCount); + for (let i = 1; i < meshCount; i++) { + offsets[i] = offsets[i - 1] + getter(i - 1); + } + return offsets; + } + result.counts = subset.getAttributeCounts(section); + result.indexOffsets = computeOffsets((m) => subset.getMeshIndexCount(m, section)); + result.vertexOffsets = computeOffsets((m) => subset.getMeshVertexCount(m, section)); + return result; + } + getIndexOffset(mesh) { + return mesh < this.counts.meshes + ? this.indexOffsets[mesh] + : this.counts.indices; + } + getVertexOffset(mesh) { + return mesh < this.counts.meshes + ? this.vertexOffsets[mesh] + : this.counts.vertices; + } + /** + * Returns how many instances of given meshes are the filtered view. + */ + getMeshInstanceCount(mesh) { + return this.subset.getMeshInstanceCount(mesh); + } + /** + * Returns instance for given mesh. + * @mesh view-relative mesh index + * @at view-relative instance index for given mesh + * @returns mesh-relative instance index + */ + getMeshInstance(mesh, index) { + return this.subset.getMeshInstance(mesh, index); + } + /** + * Returns the vim-relative mesh index at given index + */ + getMesh(index) { + return this.subset.getMesh(index); + } +} +exports.G3dMeshOffsets = G3dMeshOffsets; diff --git a/src/ts/dist/g3dScene.d.ts b/src/ts/dist/g3dScene.d.ts new file mode 100644 index 00000000..b501fb8a --- /dev/null +++ b/src/ts/dist/g3dScene.d.ts @@ -0,0 +1,63 @@ +/** + * @module vim-ts + */ +import { AbstractG3d } from './abstractG3d'; +import { BFast } from './bfast'; +import { MeshSection } from './g3d'; +export declare type FilterMode = undefined | 'mesh' | 'instance' | 'group' | 'tag'; +/** + * See https://github.com/vimaec/vim#vim-geometry-attributes + */ +export declare class SceneAttributes { + static instanceFiles: string; + static instanceIndices: string; + static instanceNodes: string; + static instanceGroups: string; + static instanceTags: string; + static instanceFlags: string; + static instanceMins: string; + static instanceMaxs: string; + static meshInstanceCounts: string; + static meshIndexCounts: string; + static meshVertexCounts: string; + static meshOpaqueIndexCount: string; + static meshOpaqueVertexCount: string; + static all: string[]; +} +/** + * Represents the index, as in book index, of a collection of G3dMesh. + * Allows to find and download G3dMesh as needed. + * Allows to preallocate geometry to render G3dMeshes. + */ +export declare class G3dScene { + rawG3d: AbstractG3d; + instanceMeshes: Int32Array; + instanceIndices: Int32Array; + instanceNodes: Int32Array; + instanceGroups: Int32Array; + instanceTags: BigInt64Array; + instanceFlags: Uint16Array; + instanceMins: Float32Array; + instanceMaxs: Float32Array; + meshInstanceCounts: Int32Array; + meshIndexCounts: Int32Array; + meshVertexCounts: Int32Array; + meshOpaqueIndexCounts: Int32Array; + meshOpaqueVertexCounts: Int32Array; + private nodeToInstance; + private meshSceneInstances; + constructor(rawG3d: AbstractG3d, instanceFiles: Int32Array, instanceIndices: Int32Array, instanceNodes: Int32Array, instanceGroups: Int32Array, instanceTags: BigInt64Array, instanceFlags: Uint16Array, instanceMins: Float32Array, instanceMaxs: Float32Array, meshInstanceCounts: Int32Array, meshIndexCounts: Int32Array, meshVertexCounts: Int32Array, meshOpaqueIndexCounts: Int32Array, meshOpaqueVertexCounts: Int32Array); + private createMap; + static createFromAbstract(g3d: AbstractG3d): G3dScene; + static createFromPath(path: string): Promise; + static createFromBfast(bfast: BFast): Promise; + getMeshSceneInstance(mesh: number, meshIndex: number): number; + getMeshCount(): number; + getMeshIndexCount(mesh: number, section: MeshSection): number; + getMeshVertexCount(mesh: number, section: MeshSection): number; + getMeshInstanceCount(mesh: number): number; + getNodeMin(node: number): Float32Array; + getNodeMax(node: number): Float32Array; + getInstanceMin(instance: number): Float32Array; + getInstanceMax(instance: number): Float32Array; +} diff --git a/src/ts/dist/g3dScene.js b/src/ts/dist/g3dScene.js new file mode 100644 index 00000000..0a9a55b1 --- /dev/null +++ b/src/ts/dist/g3dScene.js @@ -0,0 +1,145 @@ +"use strict"; +/** + * @module vim-ts + */ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.G3dScene = exports.SceneAttributes = void 0; +const abstractG3d_1 = require("./abstractG3d"); +const bfast_1 = require("./bfast"); +const g3d_1 = require("./g3d"); +/** + * See https://github.com/vimaec/vim#vim-geometry-attributes + */ +class SceneAttributes { +} +exports.SceneAttributes = SceneAttributes; +SceneAttributes.instanceFiles = 'g3d:instance:file:0:int32:1'; +SceneAttributes.instanceIndices = 'g3d:instance:index:0:int32:1'; +SceneAttributes.instanceNodes = 'g3d:instance:node:0:int32:1'; +SceneAttributes.instanceGroups = 'g3d:instance:group:0:int32:1'; +SceneAttributes.instanceTags = 'g3d:instance:tag:0:int64:1'; +SceneAttributes.instanceFlags = 'g3d:instance:tag:0:uint16:1'; +SceneAttributes.instanceMins = 'g3d:instance:min:0:float32:3'; +SceneAttributes.instanceMaxs = 'g3d:instance:max:0:float32:3'; +SceneAttributes.meshInstanceCounts = 'g3d:mesh:instancecount:0:int32:1'; +SceneAttributes.meshIndexCounts = 'g3d:mesh:indexcount:0:int32:1'; +SceneAttributes.meshVertexCounts = 'g3d:mesh:vertexcount:0:int32:1'; +SceneAttributes.meshOpaqueIndexCount = "g3d:mesh:opaqueindexcount:0:int32:1"; +SceneAttributes.meshOpaqueVertexCount = "g3d:mesh:opaquevertexcount:0:int32:1"; +SceneAttributes.all = [ + SceneAttributes.instanceFiles, + SceneAttributes.instanceIndices, + SceneAttributes.instanceNodes, + SceneAttributes.instanceGroups, + SceneAttributes.instanceTags, + SceneAttributes.instanceFlags, + SceneAttributes.instanceMins, + SceneAttributes.instanceMaxs, + SceneAttributes.meshInstanceCounts, + SceneAttributes.meshIndexCounts, + SceneAttributes.meshVertexCounts, + SceneAttributes.meshOpaqueIndexCount, + SceneAttributes.meshOpaqueVertexCount, +]; +/** + * Represents the index, as in book index, of a collection of G3dMesh. + * Allows to find and download G3dMesh as needed. + * Allows to preallocate geometry to render G3dMeshes. + */ +class G3dScene { + constructor(rawG3d, instanceFiles, instanceIndices, instanceNodes, instanceGroups, instanceTags, instanceFlags, instanceMins, instanceMaxs, meshInstanceCounts, meshIndexCounts, meshVertexCounts, meshOpaqueIndexCounts, meshOpaqueVertexCounts) { + this.rawG3d = rawG3d; + this.instanceMeshes = instanceFiles; + this.instanceIndices = instanceIndices; + this.instanceNodes = instanceNodes; + this.instanceGroups = instanceGroups; + this.instanceTags = instanceTags; + this.instanceFlags = instanceFlags; + this.instanceMins = instanceMins; + this.instanceMaxs = instanceMaxs; + this.meshInstanceCounts = meshInstanceCounts; + this.meshIndexCounts = meshIndexCounts; + this.meshVertexCounts = meshVertexCounts; + this.meshOpaqueIndexCounts = meshOpaqueIndexCounts; + this.meshOpaqueVertexCounts = meshOpaqueVertexCounts; + // Reverse instanceNodes + this.nodeToInstance = new Map(); + for (let i = 0; i < this.instanceNodes.length; i++) { + this.nodeToInstance.set(this.instanceNodes[i], i); + } + this.meshSceneInstances = this.createMap(); + } + createMap() { + // From : (mesh, scene-index) -> mesh-index + // To: (mesh, mesh-index) -> scene-index + const map = new Map(); + for (let i = 0; i < this.instanceMeshes.length; i++) { + const mesh = this.instanceMeshes[i]; + const index = this.instanceIndices[i]; + const indices = map.get(mesh) ?? new Map(); + indices.set(index, i); + map.set(mesh, indices); + } + return map; + } + static createFromAbstract(g3d) { + function getArray(attribute) { + return g3d.findAttribute(attribute)?.data; + } + return new G3dScene(g3d, getArray(SceneAttributes.instanceFiles), getArray(SceneAttributes.instanceIndices), getArray(SceneAttributes.instanceNodes), getArray(SceneAttributes.instanceGroups), getArray(SceneAttributes.instanceTags), getArray(SceneAttributes.instanceFlags), getArray(SceneAttributes.instanceMins), getArray(SceneAttributes.instanceMaxs), getArray(SceneAttributes.meshInstanceCounts), getArray(SceneAttributes.meshIndexCounts), getArray(SceneAttributes.meshVertexCounts), getArray(SceneAttributes.meshOpaqueIndexCount), getArray(SceneAttributes.meshOpaqueVertexCount)); + } + static async createFromPath(path) { + const f = await fetch(path); + const buffer = await f.arrayBuffer(); + const bfast = new bfast_1.BFast(buffer); + return this.createFromBfast(bfast); + } + static async createFromBfast(bfast) { + const g3d = await abstractG3d_1.AbstractG3d.createFromBfast(bfast, SceneAttributes.all); + return G3dScene.createFromAbstract(g3d); + } + getMeshSceneInstance(mesh, meshIndex) { + return this.meshSceneInstances.get(mesh)?.get(meshIndex); + } + getMeshCount() { + return this.meshInstanceCounts.length; + } + getMeshIndexCount(mesh, section) { + const all = this.meshIndexCounts[mesh]; + if (section === 'all') + return all; + const opaque = this.meshOpaqueIndexCounts[mesh]; + return section === 'opaque' ? opaque : all - opaque; + } + getMeshVertexCount(mesh, section) { + const all = this.meshVertexCounts[mesh]; + if (section === 'all') + return all; + const opaque = this.meshOpaqueVertexCounts[mesh]; + return section === 'opaque' ? opaque : all - opaque; + } + getMeshInstanceCount(mesh) { + return this.meshInstanceCounts[mesh]; + } + getNodeMin(node) { + const instance = this.nodeToInstance.get(node); + if (!node) { + return undefined; + } + return this.getInstanceMin(instance); + } + getNodeMax(node) { + const instance = this.nodeToInstance.get(node); + if (!node) { + return undefined; + } + return this.getInstanceMax(instance); + } + getInstanceMin(instance) { + return this.instanceMins.subarray(instance * g3d_1.G3d.POSITION_SIZE); + } + getInstanceMax(instance) { + return this.instanceMaxs.subarray(instance * g3d_1.G3d.POSITION_SIZE); + } +} +exports.G3dScene = G3dScene; diff --git a/src/ts/dist/g3dSubset.d.ts b/src/ts/dist/g3dSubset.d.ts new file mode 100644 index 00000000..c49c3cb7 --- /dev/null +++ b/src/ts/dist/g3dSubset.d.ts @@ -0,0 +1,108 @@ +import { G3d, MeshSection } from './g3d'; +import { FilterMode, G3dMeshIndex } from './g3dMeshIndex'; +import { G3dMeshCounts, G3dMeshOffsets } from './g3dMeshOffsets'; +export declare type G3dSubset = G3dSubsetOG | G3dSubset2; +export declare class G3dSubset2 { + private _source; + private _instances; + private _meshes; + private _meshInstances; + constructor(source: G3dMeshIndex | G3d, instances: number[]); + getMesh(index: number): number; + getMeshCount(): number; + /** + * Returns index count for given mesh and section. + */ + getMeshIndexCount(mesh: number, section: MeshSection): number; + /** + * Returns vertext count for given mesh and section. + */ + getMeshVertexCount(mesh: number, section: MeshSection): number; + /** + * Returns instance count for given mesh. + * @param mesh The index of the mesh from the g3dIndex. + */ + getMeshInstanceCount(mesh: number): number; + /** + * Returns the list of mesh-based instance indices for given mesh or undefined if all instances are included. + * @param mesh The index of the mesh from the g3dIndex. + */ + getMeshInstances(mesh: number): number[]; + /** + * Returns index-th mesh-based instance index for given mesh. + * @param mesh The index of the mesh from the g3dIndex. + */ + getMeshInstance(mesh: number, index: number): number; + /** + * Returns a new subset that only contains unique meshes. + */ + filterUniqueMeshes(): G3dSubset2; + /** + * Returns a new subset that only contains non-unique meshes. + */ + filterNonUniqueMeshes(): G3dSubset2; + private filterByCount; + /** + * Returns offsets needed to build geometry. + */ + getOffsets(section: MeshSection): G3dMeshOffsets; + getAttributeCounts(section?: MeshSection): G3dMeshCounts; + getBoudingBox(): Float32Array; + filter(mode: FilterMode, filter: number[]): G3dSubset2; + private filterOnArray; +} +/** + * Represents a filter applied to a G3dMeshIndex. + */ +export declare class G3dSubsetOG { + private _source; + private _instances; + private _meshes; + private _meshInstances; + /** + * @param index G3d source geometry. + * @param meshes indices of meshes to include or undefined if all meshes. + * @param meshToInstances indices of instances to include for each mesh or undefined if all meshes. + */ + constructor(index: G3dMeshIndex | G3d, instances: number[], meshes: number[], meshToInstances: number[][]); + getBoudingBox(): Float32Array; + getMesh(index: number): number; + getMeshCount(): number; + /** + * Returns index count for given mesh and section. + */ + getMeshIndexCount(mesh: number, section: MeshSection): number; + /** + * Returns vertext count for given mesh and section. + */ + getMeshVertexCount(mesh: number, section: MeshSection): number; + /** + * Returns instance count for given mesh. + * @param mesh The index of the mesh from the g3dIndex. + */ + getMeshInstanceCount(mesh: number): number; + /** + * Returns index-th mesh-based instance index for given mesh. Returns -1 otherwise. + * @param mesh The index of the mesh from the g3dIndex. + */ + getMeshInstance(mesh: number, index: number): number; + /** + * Returns the list of mesh-based instance indices for given mesh or undefined if all instances are included. + * @param mesh The index of the mesh from the g3dIndex. + */ + getMeshInstances(mesh: number): number[]; + /** + * Returns a new subset that only contains unique meshes. + */ + filterUniqueMeshes(): G3dSubsetOG; + /** + * Returns a new subset that only contains non-unique meshes. + */ + filterNonUniqueMeshes(): G3dSubsetOG; + private filterByCount; + /** + * Returns offsets needed to build geometry. + */ + getOffsets(section: MeshSection): G3dMeshOffsets; + getAttributeCounts(section?: MeshSection): G3dMeshCounts; +} diff --git a/src/ts/dist/g3dSubset.js b/src/ts/dist/g3dSubset.js new file mode 100644 index 00000000..acac37d7 --- /dev/null +++ b/src/ts/dist/g3dSubset.js @@ -0,0 +1,323 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.G3dSubsetOG = exports.G3dSubset2 = void 0; +const g3d_1 = require("./g3d"); +const g3dMeshIndex_1 = require("./g3dMeshIndex"); +const g3dMeshOffsets_1 = require("./g3dMeshOffsets"); +class G3dSubset2 { + constructor(source, + //source-based indices of included instanced + instances) { + this._source = source; + // TODO: Remove this + if (!instances) { + instances = new Array(); + for (let i = 0; i < source.instanceMeshes.length; i++) { + if (source.instanceMeshes[i] >= 0) { + instances.push(i); + } + } + } + this._instances = instances; + this._meshes = new Array(); + const map = new Map(); + instances.forEach(instance => { + const mesh = source.instanceMeshes[instance]; + const index = source instanceof g3dMeshIndex_1.G3dMeshIndex ? source.instanceIndices[instance] : instance; + if (!map.has(mesh)) { + this._meshes.push(mesh); + map.set(mesh, [index]); + } + else { + map.get(mesh).push(index); + } + }); + this._meshInstances = new Array(this._meshes.length); + this._meshes.forEach((m, i) => this._meshInstances[i] = map.get(m)); + } + getMesh(index) { + return this._meshes?.[index] ?? index; + } + getMeshCount() { + return this._meshes?.length ?? this._source.getMeshCount(); + } + /** + * Returns index count for given mesh and section. + */ + getMeshIndexCount(mesh, section) { + const instances = this.getMeshInstanceCount(mesh); + const indices = this._source.getMeshIndexCount(this.getMesh(mesh), section); + return indices * instances; + } + /** + * Returns vertext count for given mesh and section. + */ + getMeshVertexCount(mesh, section) { + const instances = this.getMeshInstanceCount(mesh); + const vertices = this._source.getMeshVertexCount(this.getMesh(mesh), section); + return vertices * instances; + } + /** + * Returns instance count for given mesh. + * @param mesh The index of the mesh from the g3dIndex. + */ + getMeshInstanceCount(mesh) { + return this._meshInstances + ? this._meshInstances[mesh].length + : this._source.getMeshInstanceCount(this.getMesh(mesh)); + } + /** + * Returns the list of mesh-based instance indices for given mesh or undefined if all instances are included. + * @param mesh The index of the mesh from the g3dIndex. + */ + getMeshInstances(mesh) { + return this._meshInstances?.[mesh]; + } + /** + * Returns index-th mesh-based instance index for given mesh. + * @param mesh The index of the mesh from the g3dIndex. + */ + getMeshInstance(mesh, index) { + const instance = this._meshInstances + ? this._meshInstances[mesh][index] + : index; + return instance; + } + /** + * Returns a new subset that only contains unique meshes. + */ + filterUniqueMeshes() { + return this.filterByCount(count => count === 1); + } + /** + * Returns a new subset that only contains non-unique meshes. + */ + filterNonUniqueMeshes() { + return this.filterByCount(count => count > 1); + } + filterByCount(predicate) { + const set = new Set(); + this._meshInstances.forEach((instances, i) => { + if (predicate(instances.length)) { + set.add(this._meshes[i]); + } + }); + const instances = this._instances.filter(instance => set.has(this._source.instanceMeshes[instance])); + return new G3dSubset2(this._source, instances); + } + /** + * Returns offsets needed to build geometry. + */ + getOffsets(section) { + return g3dMeshOffsets_1.G3dMeshOffsets.fromSubset(this, section); + } + getAttributeCounts(section = 'all') { + const result = new g3dMeshOffsets_1.G3dMeshCounts(); + const count = this.getMeshCount(); + for (let i = 0; i < count; i++) { + result.instances += this.getMeshInstanceCount(i); + result.indices += this.getMeshIndexCount(i, section); + result.vertices += this.getMeshVertexCount(i, section); + } + result.meshes = count; + return result; + } + getBoudingBox() { + if (this._instances.length === 0) + return; + if (this._source instanceof g3dMeshIndex_1.G3dMeshIndex) { + // To avoid including (0,0,0) + let box = new Float32Array(6); + const min = this._source.getInstanceMin(this._instances[0]); + const max = this._source.getInstanceMax(this._instances[0]); + box[0] = min[0]; + box[1] = min[1]; + box[2] = min[2]; + box[3] = max[0]; + box[4] = max[1]; + box[5] = max[2]; + for (let i = 1; i < this._instances.length; i++) { + const instance = this._instances[i]; + const min = this._source.getInstanceMin(instance); + const max = this._source.getInstanceMax(instance); + minBox(box, min); + maxBox(box, max); + } + return box; + } + } + filter(mode, filter) { + if (filter === undefined || mode === undefined) { + return new G3dSubset2(this._source, undefined); + } + if (mode === 'instance') { + const instances = this.filterOnArray(filter, this._source.instanceNodes); + return new G3dSubset2(this._source, instances); + } + if (mode === 'mesh') { + const instances = this.filterOnArray(filter, this._source.instanceMeshes); + return new G3dSubset2(this._source, instances); + } + if (mode === 'tag' || mode === 'group') { + throw new Error("Filter Mode Not implemented"); + } + } + filterOnArray(filter, array) { + const set = new Set(filter); + const result = new Array(); + array.forEach((mesh, i) => { + if (set.has(mesh) && this._source.instanceMeshes[i] >= 0) { + result.push(i); + } + }); + return result; + } +} +exports.G3dSubset2 = G3dSubset2; +/** + * Represents a filter applied to a G3dMeshIndex. + */ +class G3dSubsetOG { + /** + * @param index G3d source geometry. + * @param meshes indices of meshes to include or undefined if all meshes. + * @param meshToInstances indices of instances to include for each mesh or undefined if all meshes. + */ + constructor(index, instances, meshes, meshToInstances) { + this._source = index; + this._instances = instances; + this._meshes = meshes; + this._meshInstances = meshToInstances; + } + getBoudingBox() { + if (this._instances.length === 0) + return; + if (this._source instanceof g3dMeshIndex_1.G3dMeshIndex) { + // To avoid including (0,0,0) + let box = new Float32Array(6); + const min = this._source.getInstanceMin(this._instances[0]); + const max = this._source.getInstanceMax(this._instances[0]); + box[0] = min[0]; + box[1] = min[1]; + box[2] = min[2]; + box[3] = max[0]; + box[4] = max[1]; + box[5] = max[2]; + for (let i = 1; i < this._instances.length; i++) { + const instance = this._instances[i]; + const min = this._source.getInstanceMin(instance); + const max = this._source.getInstanceMax(instance); + minBox(box, min); + maxBox(box, max); + } + return box; + } + } + getMesh(index) { + return this._meshes?.[index] ?? index; + } + getMeshCount() { + return this._meshes?.length ?? this._source.getMeshCount(); + } + /** + * Returns index count for given mesh and section. + */ + getMeshIndexCount(mesh, section) { + const instances = this.getMeshInstanceCount(mesh); + const indices = this._source.getMeshIndexCount(this.getMesh(mesh), section); + return indices * instances; + } + /** + * Returns vertext count for given mesh and section. + */ + getMeshVertexCount(mesh, section) { + const instances = this.getMeshInstanceCount(mesh); + const vertices = this._source.getMeshVertexCount(this.getMesh(mesh), section); + return vertices * instances; + } + /** + * Returns instance count for given mesh. + * @param mesh The index of the mesh from the g3dIndex. + */ + getMeshInstanceCount(mesh) { + return this._meshInstances + ? this._meshInstances[mesh].length + : this._source.getMeshInstanceCount(this.getMesh(mesh)); + } + /** + * Returns index-th mesh-based instance index for given mesh. Returns -1 otherwise. + * @param mesh The index of the mesh from the g3dIndex. + */ + getMeshInstance(mesh, index) { + const instance = this._meshInstances + ? this._meshInstances[mesh][index] + : index; + if (this._source instanceof g3d_1.G3d) { + // Dereference one more time. Meshes can sometime be unreferenced + const m = this.getMesh(mesh); + return this._source.meshInstances[m]?.[instance] ?? -1; + } + return instance; + } + /** + * Returns the list of mesh-based instance indices for given mesh or undefined if all instances are included. + * @param mesh The index of the mesh from the g3dIndex. + */ + getMeshInstances(mesh) { + return this._meshInstances?.[mesh]; + } + /** + * Returns a new subset that only contains unique meshes. + */ + filterUniqueMeshes() { + return this.filterByCount(count => count === 1); + } + /** + * Returns a new subset that only contains non-unique meshes. + */ + filterNonUniqueMeshes() { + return this.filterByCount(count => count > 1); + } + filterByCount(predicate) { + const filteredMeshes = new Array(); + const filteredInstances = this._meshInstances ? new Array() : undefined; + const count = this.getMeshCount(); + for (let m = 0; m < count; m++) { + if (predicate(this.getMeshInstanceCount(m))) { + filteredMeshes.push(this.getMesh(m)); + filteredInstances?.push(this.getMeshInstances(m)); + } + } + const meshes = new Set(filteredMeshes); + const instances = this._instances?.filter(i => meshes.has(this._source.instanceMeshes[i])); + return new G3dSubsetOG(this._source, instances, filteredMeshes, filteredInstances); + } + /** + * Returns offsets needed to build geometry. + */ + getOffsets(section) { + return g3dMeshOffsets_1.G3dMeshOffsets.fromSubset(this, section); + } + getAttributeCounts(section = 'all') { + const result = new g3dMeshOffsets_1.G3dMeshCounts(); + const count = this.getMeshCount(); + for (let i = 0; i < count; i++) { + result.instances += this.getMeshInstanceCount(i); + result.indices += this.getMeshIndexCount(i, section); + result.vertices += this.getMeshVertexCount(i, section); + } + result.meshes = count; + return result; + } +} +exports.G3dSubsetOG = G3dSubsetOG; +function minBox(box, other) { + box[0] = Math.min(box[0], other[0]); + box[1] = Math.min(box[1], other[1]); + box[2] = Math.min(box[2], other[2]); +} +function maxBox(box, other) { + box[3] = Math.max(box[3], other[0]); + box[4] = Math.max(box[4], other[1]); + box[5] = Math.max(box[5], other[2]); +} diff --git a/src/ts/dist/index.d.ts b/src/ts/dist/index.d.ts new file mode 100644 index 00000000..8b034a7e --- /dev/null +++ b/src/ts/dist/index.d.ts @@ -0,0 +1,15 @@ +export * from './bfast'; +export * from './g3d'; +export * from './remoteVimx'; +export * from './g3dMaterials'; +export * from './g3dMesh'; +export * from './g3dScene'; +export * from './remoteG3d'; +export * from './remoteBuffer'; +export * from './requestTracker'; +export * from './requester'; +export * from './remoteValue'; +export * from './vimHeader'; +export * from './objectModel'; +export * from './structures'; +export * as VimHelpers from './vimHelpers'; diff --git a/src/ts/dist/index.js b/src/ts/dist/index.js new file mode 100644 index 00000000..35a61b6b --- /dev/null +++ b/src/ts/dist/index.js @@ -0,0 +1,45 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.VimHelpers = void 0; +// Links files to generate package type exports +__exportStar(require("./bfast"), exports); +__exportStar(require("./g3d"), exports); +__exportStar(require("./remoteVimx"), exports); +__exportStar(require("./g3dMaterials"), exports); +__exportStar(require("./g3dMesh"), exports); +__exportStar(require("./g3dScene"), exports); +__exportStar(require("./remoteG3d"), exports); +__exportStar(require("./remoteBuffer"), exports); +__exportStar(require("./requestTracker"), exports); +__exportStar(require("./requester"), exports); +__exportStar(require("./remoteValue"), exports); +__exportStar(require("./vimHeader"), exports); +__exportStar(require("./objectModel"), exports); +__exportStar(require("./structures"), exports); +exports.VimHelpers = __importStar(require("./vimHelpers")); diff --git a/src/ts/dist/logging.d.ts b/src/ts/dist/logging.d.ts new file mode 100644 index 00000000..1316f5b9 --- /dev/null +++ b/src/ts/dist/logging.d.ts @@ -0,0 +1,18 @@ +/** + * @module vim-ts + */ +export declare class Logger { + log: (s: any) => void; + warn: (s: any) => void; + error: (s: any) => void; +} +export declare class DefaultLog implements Logger { + log: (s: any) => void; + warn: (s: any) => void; + error: (s: any) => void; +} +export declare class NoLog implements Logger { + log: (s: any) => void; + warn: (s: any) => void; + error: (s: any) => void; +} diff --git a/src/ts/dist/logging.js b/src/ts/dist/logging.js new file mode 100644 index 00000000..5fd14219 --- /dev/null +++ b/src/ts/dist/logging.js @@ -0,0 +1,25 @@ +"use strict"; +/** + * @module vim-ts + */ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.NoLog = exports.DefaultLog = exports.Logger = void 0; +class Logger { +} +exports.Logger = Logger; +class DefaultLog { + constructor() { + this.log = (s) => console.log(s); + this.warn = (s) => console.warn(s); + this.error = (s) => console.error(s); + } +} +exports.DefaultLog = DefaultLog; +class NoLog { + constructor() { + this.log = (s) => { }; + this.warn = (s) => { }; + this.error = (s) => { }; + } +} +exports.NoLog = NoLog; diff --git a/src/ts/dist/objectModel.d.ts b/src/ts/dist/objectModel.d.ts new file mode 100644 index 00000000..73c72add --- /dev/null +++ b/src/ts/dist/objectModel.d.ts @@ -0,0 +1,3356 @@ +/** + * @module vim-ts + */ +import { BFast } from "./bfast"; +export interface IAsset { + index: number; + bufferName?: string; +} +export interface IAssetTable { + getCount(): Promise; + get(assetIndex: number): Promise; + getAll(): Promise; + getBufferName(assetIndex: number): Promise; + getAllBufferName(): Promise; +} +export declare class Asset implements IAsset { + index: number; + bufferName?: string; + static createFromTable(table: IAssetTable, index: number): Promise; +} +export declare class AssetTable implements IAssetTable { + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(assetIndex: number): Promise; + getAll(): Promise; + getBufferName(assetIndex: number): Promise; + getAllBufferName(): Promise; +} +export interface IDisplayUnit { + index: number; + spec?: string; + type?: string; + label?: string; +} +export interface IDisplayUnitTable { + getCount(): Promise; + get(displayUnitIndex: number): Promise; + getAll(): Promise; + getSpec(displayUnitIndex: number): Promise; + getAllSpec(): Promise; + getType(displayUnitIndex: number): Promise; + getAllType(): Promise; + getLabel(displayUnitIndex: number): Promise; + getAllLabel(): Promise; +} +export declare class DisplayUnit implements IDisplayUnit { + index: number; + spec?: string; + type?: string; + label?: string; + static createFromTable(table: IDisplayUnitTable, index: number): Promise; +} +export declare class DisplayUnitTable implements IDisplayUnitTable { + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(displayUnitIndex: number): Promise; + getAll(): Promise; + getSpec(displayUnitIndex: number): Promise; + getAllSpec(): Promise; + getType(displayUnitIndex: number): Promise; + getAllType(): Promise; + getLabel(displayUnitIndex: number): Promise; + getAllLabel(): Promise; +} +export interface IParameterDescriptor { + index: number; + name?: string; + group?: string; + parameterType?: string; + isInstance?: boolean; + isShared?: boolean; + isReadOnly?: boolean; + flags?: number; + guid?: string; + displayUnitIndex?: number; + displayUnit?: IDisplayUnit; +} +export interface IParameterDescriptorTable { + getCount(): Promise; + get(parameterDescriptorIndex: number): Promise; + getAll(): Promise; + getName(parameterDescriptorIndex: number): Promise; + getAllName(): Promise; + getGroup(parameterDescriptorIndex: number): Promise; + getAllGroup(): Promise; + getParameterType(parameterDescriptorIndex: number): Promise; + getAllParameterType(): Promise; + getIsInstance(parameterDescriptorIndex: number): Promise; + getAllIsInstance(): Promise; + getIsShared(parameterDescriptorIndex: number): Promise; + getAllIsShared(): Promise; + getIsReadOnly(parameterDescriptorIndex: number): Promise; + getAllIsReadOnly(): Promise; + getFlags(parameterDescriptorIndex: number): Promise; + getAllFlags(): Promise; + getGuid(parameterDescriptorIndex: number): Promise; + getAllGuid(): Promise; + getDisplayUnitIndex(parameterDescriptorIndex: number): Promise; + getAllDisplayUnitIndex(): Promise; + getDisplayUnit(parameterDescriptorIndex: number): Promise; +} +export declare class ParameterDescriptor implements IParameterDescriptor { + index: number; + name?: string; + group?: string; + parameterType?: string; + isInstance?: boolean; + isShared?: boolean; + isReadOnly?: boolean; + flags?: number; + guid?: string; + displayUnitIndex?: number; + displayUnit?: IDisplayUnit; + static createFromTable(table: IParameterDescriptorTable, index: number): Promise; +} +export declare class ParameterDescriptorTable implements IParameterDescriptorTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(parameterDescriptorIndex: number): Promise; + getAll(): Promise; + getName(parameterDescriptorIndex: number): Promise; + getAllName(): Promise; + getGroup(parameterDescriptorIndex: number): Promise; + getAllGroup(): Promise; + getParameterType(parameterDescriptorIndex: number): Promise; + getAllParameterType(): Promise; + getIsInstance(parameterDescriptorIndex: number): Promise; + getAllIsInstance(): Promise; + getIsShared(parameterDescriptorIndex: number): Promise; + getAllIsShared(): Promise; + getIsReadOnly(parameterDescriptorIndex: number): Promise; + getAllIsReadOnly(): Promise; + getFlags(parameterDescriptorIndex: number): Promise; + getAllFlags(): Promise; + getGuid(parameterDescriptorIndex: number): Promise; + getAllGuid(): Promise; + getDisplayUnitIndex(parameterDescriptorIndex: number): Promise; + getAllDisplayUnitIndex(): Promise; + getDisplayUnit(parameterDescriptorIndex: number): Promise; +} +export interface IParameter { + index: number; + value?: string; + parameterDescriptorIndex?: number; + parameterDescriptor?: IParameterDescriptor; + elementIndex?: number; + element?: IElement; +} +export interface IParameterTable { + getCount(): Promise; + get(parameterIndex: number): Promise; + getAll(): Promise; + getValue(parameterIndex: number): Promise; + getAllValue(): Promise; + getParameterDescriptorIndex(parameterIndex: number): Promise; + getAllParameterDescriptorIndex(): Promise; + getParameterDescriptor(parameterIndex: number): Promise; + getElementIndex(parameterIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(parameterIndex: number): Promise; +} +export declare class Parameter implements IParameter { + index: number; + value?: string; + parameterDescriptorIndex?: number; + parameterDescriptor?: IParameterDescriptor; + elementIndex?: number; + element?: IElement; + static createFromTable(table: IParameterTable, index: number): Promise; +} +export declare class ParameterTable implements IParameterTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(parameterIndex: number): Promise; + getAll(): Promise; + getValue(parameterIndex: number): Promise; + getAllValue(): Promise; + getParameterDescriptorIndex(parameterIndex: number): Promise; + getAllParameterDescriptorIndex(): Promise; + getParameterDescriptor(parameterIndex: number): Promise; + getElementIndex(parameterIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(parameterIndex: number): Promise; +} +export interface IElement { + index: number; + id?: bigint; + type?: string; + name?: string; + uniqueId?: string; + location_X?: number; + location_Y?: number; + location_Z?: number; + familyName?: string; + isPinned?: boolean; + levelIndex?: number; + level?: ILevel; + phaseCreatedIndex?: number; + phaseCreated?: IPhase; + phaseDemolishedIndex?: number; + phaseDemolished?: IPhase; + categoryIndex?: number; + category?: ICategory; + worksetIndex?: number; + workset?: IWorkset; + designOptionIndex?: number; + designOption?: IDesignOption; + ownerViewIndex?: number; + ownerView?: IView; + groupIndex?: number; + group?: IGroup; + assemblyInstanceIndex?: number; + assemblyInstance?: IAssemblyInstance; + bimDocumentIndex?: number; + bimDocument?: IBimDocument; + roomIndex?: number; + room?: IRoom; +} +export interface IElementTable { + getCount(): Promise; + get(elementIndex: number): Promise; + getAll(): Promise; + getId(elementIndex: number): Promise; + getAllId(): Promise; + getType(elementIndex: number): Promise; + getAllType(): Promise; + getName(elementIndex: number): Promise; + getAllName(): Promise; + getUniqueId(elementIndex: number): Promise; + getAllUniqueId(): Promise; + getLocation_X(elementIndex: number): Promise; + getAllLocation_X(): Promise; + getLocation_Y(elementIndex: number): Promise; + getAllLocation_Y(): Promise; + getLocation_Z(elementIndex: number): Promise; + getAllLocation_Z(): Promise; + getFamilyName(elementIndex: number): Promise; + getAllFamilyName(): Promise; + getIsPinned(elementIndex: number): Promise; + getAllIsPinned(): Promise; + getLevelIndex(elementIndex: number): Promise; + getAllLevelIndex(): Promise; + getLevel(elementIndex: number): Promise; + getPhaseCreatedIndex(elementIndex: number): Promise; + getAllPhaseCreatedIndex(): Promise; + getPhaseCreated(elementIndex: number): Promise; + getPhaseDemolishedIndex(elementIndex: number): Promise; + getAllPhaseDemolishedIndex(): Promise; + getPhaseDemolished(elementIndex: number): Promise; + getCategoryIndex(elementIndex: number): Promise; + getAllCategoryIndex(): Promise; + getCategory(elementIndex: number): Promise; + getWorksetIndex(elementIndex: number): Promise; + getAllWorksetIndex(): Promise; + getWorkset(elementIndex: number): Promise; + getDesignOptionIndex(elementIndex: number): Promise; + getAllDesignOptionIndex(): Promise; + getDesignOption(elementIndex: number): Promise; + getOwnerViewIndex(elementIndex: number): Promise; + getAllOwnerViewIndex(): Promise; + getOwnerView(elementIndex: number): Promise; + getGroupIndex(elementIndex: number): Promise; + getAllGroupIndex(): Promise; + getGroup(elementIndex: number): Promise; + getAssemblyInstanceIndex(elementIndex: number): Promise; + getAllAssemblyInstanceIndex(): Promise; + getAssemblyInstance(elementIndex: number): Promise; + getBimDocumentIndex(elementIndex: number): Promise; + getAllBimDocumentIndex(): Promise; + getBimDocument(elementIndex: number): Promise; + getRoomIndex(elementIndex: number): Promise; + getAllRoomIndex(): Promise; + getRoom(elementIndex: number): Promise; +} +export declare class Element implements IElement { + index: number; + id?: bigint; + type?: string; + name?: string; + uniqueId?: string; + location_X?: number; + location_Y?: number; + location_Z?: number; + familyName?: string; + isPinned?: boolean; + levelIndex?: number; + level?: ILevel; + phaseCreatedIndex?: number; + phaseCreated?: IPhase; + phaseDemolishedIndex?: number; + phaseDemolished?: IPhase; + categoryIndex?: number; + category?: ICategory; + worksetIndex?: number; + workset?: IWorkset; + designOptionIndex?: number; + designOption?: IDesignOption; + ownerViewIndex?: number; + ownerView?: IView; + groupIndex?: number; + group?: IGroup; + assemblyInstanceIndex?: number; + assemblyInstance?: IAssemblyInstance; + bimDocumentIndex?: number; + bimDocument?: IBimDocument; + roomIndex?: number; + room?: IRoom; + static createFromTable(table: IElementTable, index: number): Promise; +} +export declare class ElementTable implements IElementTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(elementIndex: number): Promise; + getAll(): Promise; + getId(elementIndex: number): Promise; + getAllId(): Promise; + getType(elementIndex: number): Promise; + getAllType(): Promise; + getName(elementIndex: number): Promise; + getAllName(): Promise; + getUniqueId(elementIndex: number): Promise; + getAllUniqueId(): Promise; + getLocation_X(elementIndex: number): Promise; + getAllLocation_X(): Promise; + getLocation_Y(elementIndex: number): Promise; + getAllLocation_Y(): Promise; + getLocation_Z(elementIndex: number): Promise; + getAllLocation_Z(): Promise; + getFamilyName(elementIndex: number): Promise; + getAllFamilyName(): Promise; + getIsPinned(elementIndex: number): Promise; + getAllIsPinned(): Promise; + getLevelIndex(elementIndex: number): Promise; + getAllLevelIndex(): Promise; + getLevel(elementIndex: number): Promise; + getPhaseCreatedIndex(elementIndex: number): Promise; + getAllPhaseCreatedIndex(): Promise; + getPhaseCreated(elementIndex: number): Promise; + getPhaseDemolishedIndex(elementIndex: number): Promise; + getAllPhaseDemolishedIndex(): Promise; + getPhaseDemolished(elementIndex: number): Promise; + getCategoryIndex(elementIndex: number): Promise; + getAllCategoryIndex(): Promise; + getCategory(elementIndex: number): Promise; + getWorksetIndex(elementIndex: number): Promise; + getAllWorksetIndex(): Promise; + getWorkset(elementIndex: number): Promise; + getDesignOptionIndex(elementIndex: number): Promise; + getAllDesignOptionIndex(): Promise; + getDesignOption(elementIndex: number): Promise; + getOwnerViewIndex(elementIndex: number): Promise; + getAllOwnerViewIndex(): Promise; + getOwnerView(elementIndex: number): Promise; + getGroupIndex(elementIndex: number): Promise; + getAllGroupIndex(): Promise; + getGroup(elementIndex: number): Promise; + getAssemblyInstanceIndex(elementIndex: number): Promise; + getAllAssemblyInstanceIndex(): Promise; + getAssemblyInstance(elementIndex: number): Promise; + getBimDocumentIndex(elementIndex: number): Promise; + getAllBimDocumentIndex(): Promise; + getBimDocument(elementIndex: number): Promise; + getRoomIndex(elementIndex: number): Promise; + getAllRoomIndex(): Promise; + getRoom(elementIndex: number): Promise; +} +export interface IWorkset { + index: number; + id?: number; + name?: string; + kind?: string; + isOpen?: boolean; + isEditable?: boolean; + owner?: string; + uniqueId?: string; + bimDocumentIndex?: number; + bimDocument?: IBimDocument; +} +export interface IWorksetTable { + getCount(): Promise; + get(worksetIndex: number): Promise; + getAll(): Promise; + getId(worksetIndex: number): Promise; + getAllId(): Promise; + getName(worksetIndex: number): Promise; + getAllName(): Promise; + getKind(worksetIndex: number): Promise; + getAllKind(): Promise; + getIsOpen(worksetIndex: number): Promise; + getAllIsOpen(): Promise; + getIsEditable(worksetIndex: number): Promise; + getAllIsEditable(): Promise; + getOwner(worksetIndex: number): Promise; + getAllOwner(): Promise; + getUniqueId(worksetIndex: number): Promise; + getAllUniqueId(): Promise; + getBimDocumentIndex(worksetIndex: number): Promise; + getAllBimDocumentIndex(): Promise; + getBimDocument(worksetIndex: number): Promise; +} +export declare class Workset implements IWorkset { + index: number; + id?: number; + name?: string; + kind?: string; + isOpen?: boolean; + isEditable?: boolean; + owner?: string; + uniqueId?: string; + bimDocumentIndex?: number; + bimDocument?: IBimDocument; + static createFromTable(table: IWorksetTable, index: number): Promise; +} +export declare class WorksetTable implements IWorksetTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(worksetIndex: number): Promise; + getAll(): Promise; + getId(worksetIndex: number): Promise; + getAllId(): Promise; + getName(worksetIndex: number): Promise; + getAllName(): Promise; + getKind(worksetIndex: number): Promise; + getAllKind(): Promise; + getIsOpen(worksetIndex: number): Promise; + getAllIsOpen(): Promise; + getIsEditable(worksetIndex: number): Promise; + getAllIsEditable(): Promise; + getOwner(worksetIndex: number): Promise; + getAllOwner(): Promise; + getUniqueId(worksetIndex: number): Promise; + getAllUniqueId(): Promise; + getBimDocumentIndex(worksetIndex: number): Promise; + getAllBimDocumentIndex(): Promise; + getBimDocument(worksetIndex: number): Promise; +} +export interface IAssemblyInstance { + index: number; + assemblyTypeName?: string; + position_X?: number; + position_Y?: number; + position_Z?: number; + elementIndex?: number; + element?: IElement; +} +export interface IAssemblyInstanceTable { + getCount(): Promise; + get(assemblyInstanceIndex: number): Promise; + getAll(): Promise; + getAssemblyTypeName(assemblyInstanceIndex: number): Promise; + getAllAssemblyTypeName(): Promise; + getPosition_X(assemblyInstanceIndex: number): Promise; + getAllPosition_X(): Promise; + getPosition_Y(assemblyInstanceIndex: number): Promise; + getAllPosition_Y(): Promise; + getPosition_Z(assemblyInstanceIndex: number): Promise; + getAllPosition_Z(): Promise; + getElementIndex(assemblyInstanceIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(assemblyInstanceIndex: number): Promise; +} +export declare class AssemblyInstance implements IAssemblyInstance { + index: number; + assemblyTypeName?: string; + position_X?: number; + position_Y?: number; + position_Z?: number; + elementIndex?: number; + element?: IElement; + static createFromTable(table: IAssemblyInstanceTable, index: number): Promise; +} +export declare class AssemblyInstanceTable implements IAssemblyInstanceTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(assemblyInstanceIndex: number): Promise; + getAll(): Promise; + getAssemblyTypeName(assemblyInstanceIndex: number): Promise; + getAllAssemblyTypeName(): Promise; + getPosition_X(assemblyInstanceIndex: number): Promise; + getAllPosition_X(): Promise; + getPosition_Y(assemblyInstanceIndex: number): Promise; + getAllPosition_Y(): Promise; + getPosition_Z(assemblyInstanceIndex: number): Promise; + getAllPosition_Z(): Promise; + getElementIndex(assemblyInstanceIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(assemblyInstanceIndex: number): Promise; +} +export interface IGroup { + index: number; + groupType?: string; + position_X?: number; + position_Y?: number; + position_Z?: number; + elementIndex?: number; + element?: IElement; +} +export interface IGroupTable { + getCount(): Promise; + get(groupIndex: number): Promise; + getAll(): Promise; + getGroupType(groupIndex: number): Promise; + getAllGroupType(): Promise; + getPosition_X(groupIndex: number): Promise; + getAllPosition_X(): Promise; + getPosition_Y(groupIndex: number): Promise; + getAllPosition_Y(): Promise; + getPosition_Z(groupIndex: number): Promise; + getAllPosition_Z(): Promise; + getElementIndex(groupIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(groupIndex: number): Promise; +} +export declare class Group implements IGroup { + index: number; + groupType?: string; + position_X?: number; + position_Y?: number; + position_Z?: number; + elementIndex?: number; + element?: IElement; + static createFromTable(table: IGroupTable, index: number): Promise; +} +export declare class GroupTable implements IGroupTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(groupIndex: number): Promise; + getAll(): Promise; + getGroupType(groupIndex: number): Promise; + getAllGroupType(): Promise; + getPosition_X(groupIndex: number): Promise; + getAllPosition_X(): Promise; + getPosition_Y(groupIndex: number): Promise; + getAllPosition_Y(): Promise; + getPosition_Z(groupIndex: number): Promise; + getAllPosition_Z(): Promise; + getElementIndex(groupIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(groupIndex: number): Promise; +} +export interface IDesignOption { + index: number; + isPrimary?: boolean; + elementIndex?: number; + element?: IElement; +} +export interface IDesignOptionTable { + getCount(): Promise; + get(designOptionIndex: number): Promise; + getAll(): Promise; + getIsPrimary(designOptionIndex: number): Promise; + getAllIsPrimary(): Promise; + getElementIndex(designOptionIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(designOptionIndex: number): Promise; +} +export declare class DesignOption implements IDesignOption { + index: number; + isPrimary?: boolean; + elementIndex?: number; + element?: IElement; + static createFromTable(table: IDesignOptionTable, index: number): Promise; +} +export declare class DesignOptionTable implements IDesignOptionTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(designOptionIndex: number): Promise; + getAll(): Promise; + getIsPrimary(designOptionIndex: number): Promise; + getAllIsPrimary(): Promise; + getElementIndex(designOptionIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(designOptionIndex: number): Promise; +} +export interface ILevel { + index: number; + elevation?: number; + familyTypeIndex?: number; + familyType?: IFamilyType; + elementIndex?: number; + element?: IElement; +} +export interface ILevelTable { + getCount(): Promise; + get(levelIndex: number): Promise; + getAll(): Promise; + getElevation(levelIndex: number): Promise; + getAllElevation(): Promise; + getFamilyTypeIndex(levelIndex: number): Promise; + getAllFamilyTypeIndex(): Promise; + getFamilyType(levelIndex: number): Promise; + getElementIndex(levelIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(levelIndex: number): Promise; +} +export declare class Level implements ILevel { + index: number; + elevation?: number; + familyTypeIndex?: number; + familyType?: IFamilyType; + elementIndex?: number; + element?: IElement; + static createFromTable(table: ILevelTable, index: number): Promise; +} +export declare class LevelTable implements ILevelTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(levelIndex: number): Promise; + getAll(): Promise; + getElevation(levelIndex: number): Promise; + getAllElevation(): Promise; + getFamilyTypeIndex(levelIndex: number): Promise; + getAllFamilyTypeIndex(): Promise; + getFamilyType(levelIndex: number): Promise; + getElementIndex(levelIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(levelIndex: number): Promise; +} +export interface IPhase { + index: number; + elementIndex?: number; + element?: IElement; +} +export interface IPhaseTable { + getCount(): Promise; + get(phaseIndex: number): Promise; + getAll(): Promise; + getElementIndex(phaseIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(phaseIndex: number): Promise; +} +export declare class Phase implements IPhase { + index: number; + elementIndex?: number; + element?: IElement; + static createFromTable(table: IPhaseTable, index: number): Promise; +} +export declare class PhaseTable implements IPhaseTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(phaseIndex: number): Promise; + getAll(): Promise; + getElementIndex(phaseIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(phaseIndex: number): Promise; +} +export interface IRoom { + index: number; + baseOffset?: number; + limitOffset?: number; + unboundedHeight?: number; + volume?: number; + perimeter?: number; + area?: number; + number?: string; + upperLimitIndex?: number; + upperLimit?: ILevel; + elementIndex?: number; + element?: IElement; +} +export interface IRoomTable { + getCount(): Promise; + get(roomIndex: number): Promise; + getAll(): Promise; + getBaseOffset(roomIndex: number): Promise; + getAllBaseOffset(): Promise; + getLimitOffset(roomIndex: number): Promise; + getAllLimitOffset(): Promise; + getUnboundedHeight(roomIndex: number): Promise; + getAllUnboundedHeight(): Promise; + getVolume(roomIndex: number): Promise; + getAllVolume(): Promise; + getPerimeter(roomIndex: number): Promise; + getAllPerimeter(): Promise; + getArea(roomIndex: number): Promise; + getAllArea(): Promise; + getNumber(roomIndex: number): Promise; + getAllNumber(): Promise; + getUpperLimitIndex(roomIndex: number): Promise; + getAllUpperLimitIndex(): Promise; + getUpperLimit(roomIndex: number): Promise; + getElementIndex(roomIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(roomIndex: number): Promise; +} +export declare class Room implements IRoom { + index: number; + baseOffset?: number; + limitOffset?: number; + unboundedHeight?: number; + volume?: number; + perimeter?: number; + area?: number; + number?: string; + upperLimitIndex?: number; + upperLimit?: ILevel; + elementIndex?: number; + element?: IElement; + static createFromTable(table: IRoomTable, index: number): Promise; +} +export declare class RoomTable implements IRoomTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(roomIndex: number): Promise; + getAll(): Promise; + getBaseOffset(roomIndex: number): Promise; + getAllBaseOffset(): Promise; + getLimitOffset(roomIndex: number): Promise; + getAllLimitOffset(): Promise; + getUnboundedHeight(roomIndex: number): Promise; + getAllUnboundedHeight(): Promise; + getVolume(roomIndex: number): Promise; + getAllVolume(): Promise; + getPerimeter(roomIndex: number): Promise; + getAllPerimeter(): Promise; + getArea(roomIndex: number): Promise; + getAllArea(): Promise; + getNumber(roomIndex: number): Promise; + getAllNumber(): Promise; + getUpperLimitIndex(roomIndex: number): Promise; + getAllUpperLimitIndex(): Promise; + getUpperLimit(roomIndex: number): Promise; + getElementIndex(roomIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(roomIndex: number): Promise; +} +export interface IBimDocument { + index: number; + title?: string; + isMetric?: boolean; + guid?: string; + numSaves?: number; + isLinked?: boolean; + isDetached?: boolean; + isWorkshared?: boolean; + pathName?: string; + latitude?: number; + longitude?: number; + timeZone?: number; + placeName?: string; + weatherStationName?: string; + elevation?: number; + projectLocation?: string; + issueDate?: string; + status?: string; + clientName?: string; + address?: string; + name?: string; + number?: string; + author?: string; + buildingName?: string; + organizationName?: string; + organizationDescription?: string; + product?: string; + version?: string; + user?: string; + activeViewIndex?: number; + activeView?: IView; + ownerFamilyIndex?: number; + ownerFamily?: IFamily; + parentIndex?: number; + parent?: IBimDocument; + elementIndex?: number; + element?: IElement; +} +export interface IBimDocumentTable { + getCount(): Promise; + get(bimDocumentIndex: number): Promise; + getAll(): Promise; + getTitle(bimDocumentIndex: number): Promise; + getAllTitle(): Promise; + getIsMetric(bimDocumentIndex: number): Promise; + getAllIsMetric(): Promise; + getGuid(bimDocumentIndex: number): Promise; + getAllGuid(): Promise; + getNumSaves(bimDocumentIndex: number): Promise; + getAllNumSaves(): Promise; + getIsLinked(bimDocumentIndex: number): Promise; + getAllIsLinked(): Promise; + getIsDetached(bimDocumentIndex: number): Promise; + getAllIsDetached(): Promise; + getIsWorkshared(bimDocumentIndex: number): Promise; + getAllIsWorkshared(): Promise; + getPathName(bimDocumentIndex: number): Promise; + getAllPathName(): Promise; + getLatitude(bimDocumentIndex: number): Promise; + getAllLatitude(): Promise; + getLongitude(bimDocumentIndex: number): Promise; + getAllLongitude(): Promise; + getTimeZone(bimDocumentIndex: number): Promise; + getAllTimeZone(): Promise; + getPlaceName(bimDocumentIndex: number): Promise; + getAllPlaceName(): Promise; + getWeatherStationName(bimDocumentIndex: number): Promise; + getAllWeatherStationName(): Promise; + getElevation(bimDocumentIndex: number): Promise; + getAllElevation(): Promise; + getProjectLocation(bimDocumentIndex: number): Promise; + getAllProjectLocation(): Promise; + getIssueDate(bimDocumentIndex: number): Promise; + getAllIssueDate(): Promise; + getStatus(bimDocumentIndex: number): Promise; + getAllStatus(): Promise; + getClientName(bimDocumentIndex: number): Promise; + getAllClientName(): Promise; + getAddress(bimDocumentIndex: number): Promise; + getAllAddress(): Promise; + getName(bimDocumentIndex: number): Promise; + getAllName(): Promise; + getNumber(bimDocumentIndex: number): Promise; + getAllNumber(): Promise; + getAuthor(bimDocumentIndex: number): Promise; + getAllAuthor(): Promise; + getBuildingName(bimDocumentIndex: number): Promise; + getAllBuildingName(): Promise; + getOrganizationName(bimDocumentIndex: number): Promise; + getAllOrganizationName(): Promise; + getOrganizationDescription(bimDocumentIndex: number): Promise; + getAllOrganizationDescription(): Promise; + getProduct(bimDocumentIndex: number): Promise; + getAllProduct(): Promise; + getVersion(bimDocumentIndex: number): Promise; + getAllVersion(): Promise; + getUser(bimDocumentIndex: number): Promise; + getAllUser(): Promise; + getActiveViewIndex(bimDocumentIndex: number): Promise; + getAllActiveViewIndex(): Promise; + getActiveView(bimDocumentIndex: number): Promise; + getOwnerFamilyIndex(bimDocumentIndex: number): Promise; + getAllOwnerFamilyIndex(): Promise; + getOwnerFamily(bimDocumentIndex: number): Promise; + getParentIndex(bimDocumentIndex: number): Promise; + getAllParentIndex(): Promise; + getParent(bimDocumentIndex: number): Promise; + getElementIndex(bimDocumentIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(bimDocumentIndex: number): Promise; +} +export declare class BimDocument implements IBimDocument { + index: number; + title?: string; + isMetric?: boolean; + guid?: string; + numSaves?: number; + isLinked?: boolean; + isDetached?: boolean; + isWorkshared?: boolean; + pathName?: string; + latitude?: number; + longitude?: number; + timeZone?: number; + placeName?: string; + weatherStationName?: string; + elevation?: number; + projectLocation?: string; + issueDate?: string; + status?: string; + clientName?: string; + address?: string; + name?: string; + number?: string; + author?: string; + buildingName?: string; + organizationName?: string; + organizationDescription?: string; + product?: string; + version?: string; + user?: string; + activeViewIndex?: number; + activeView?: IView; + ownerFamilyIndex?: number; + ownerFamily?: IFamily; + parentIndex?: number; + parent?: IBimDocument; + elementIndex?: number; + element?: IElement; + static createFromTable(table: IBimDocumentTable, index: number): Promise; +} +export declare class BimDocumentTable implements IBimDocumentTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(bimDocumentIndex: number): Promise; + getAll(): Promise; + getTitle(bimDocumentIndex: number): Promise; + getAllTitle(): Promise; + getIsMetric(bimDocumentIndex: number): Promise; + getAllIsMetric(): Promise; + getGuid(bimDocumentIndex: number): Promise; + getAllGuid(): Promise; + getNumSaves(bimDocumentIndex: number): Promise; + getAllNumSaves(): Promise; + getIsLinked(bimDocumentIndex: number): Promise; + getAllIsLinked(): Promise; + getIsDetached(bimDocumentIndex: number): Promise; + getAllIsDetached(): Promise; + getIsWorkshared(bimDocumentIndex: number): Promise; + getAllIsWorkshared(): Promise; + getPathName(bimDocumentIndex: number): Promise; + getAllPathName(): Promise; + getLatitude(bimDocumentIndex: number): Promise; + getAllLatitude(): Promise; + getLongitude(bimDocumentIndex: number): Promise; + getAllLongitude(): Promise; + getTimeZone(bimDocumentIndex: number): Promise; + getAllTimeZone(): Promise; + getPlaceName(bimDocumentIndex: number): Promise; + getAllPlaceName(): Promise; + getWeatherStationName(bimDocumentIndex: number): Promise; + getAllWeatherStationName(): Promise; + getElevation(bimDocumentIndex: number): Promise; + getAllElevation(): Promise; + getProjectLocation(bimDocumentIndex: number): Promise; + getAllProjectLocation(): Promise; + getIssueDate(bimDocumentIndex: number): Promise; + getAllIssueDate(): Promise; + getStatus(bimDocumentIndex: number): Promise; + getAllStatus(): Promise; + getClientName(bimDocumentIndex: number): Promise; + getAllClientName(): Promise; + getAddress(bimDocumentIndex: number): Promise; + getAllAddress(): Promise; + getName(bimDocumentIndex: number): Promise; + getAllName(): Promise; + getNumber(bimDocumentIndex: number): Promise; + getAllNumber(): Promise; + getAuthor(bimDocumentIndex: number): Promise; + getAllAuthor(): Promise; + getBuildingName(bimDocumentIndex: number): Promise; + getAllBuildingName(): Promise; + getOrganizationName(bimDocumentIndex: number): Promise; + getAllOrganizationName(): Promise; + getOrganizationDescription(bimDocumentIndex: number): Promise; + getAllOrganizationDescription(): Promise; + getProduct(bimDocumentIndex: number): Promise; + getAllProduct(): Promise; + getVersion(bimDocumentIndex: number): Promise; + getAllVersion(): Promise; + getUser(bimDocumentIndex: number): Promise; + getAllUser(): Promise; + getActiveViewIndex(bimDocumentIndex: number): Promise; + getAllActiveViewIndex(): Promise; + getActiveView(bimDocumentIndex: number): Promise; + getOwnerFamilyIndex(bimDocumentIndex: number): Promise; + getAllOwnerFamilyIndex(): Promise; + getOwnerFamily(bimDocumentIndex: number): Promise; + getParentIndex(bimDocumentIndex: number): Promise; + getAllParentIndex(): Promise; + getParent(bimDocumentIndex: number): Promise; + getElementIndex(bimDocumentIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(bimDocumentIndex: number): Promise; +} +export interface IDisplayUnitInBimDocument { + index: number; + displayUnitIndex?: number; + displayUnit?: IDisplayUnit; + bimDocumentIndex?: number; + bimDocument?: IBimDocument; +} +export interface IDisplayUnitInBimDocumentTable { + getCount(): Promise; + get(displayUnitInBimDocumentIndex: number): Promise; + getAll(): Promise; + getDisplayUnitIndex(displayUnitInBimDocumentIndex: number): Promise; + getAllDisplayUnitIndex(): Promise; + getDisplayUnit(displayUnitInBimDocumentIndex: number): Promise; + getBimDocumentIndex(displayUnitInBimDocumentIndex: number): Promise; + getAllBimDocumentIndex(): Promise; + getBimDocument(displayUnitInBimDocumentIndex: number): Promise; +} +export declare class DisplayUnitInBimDocument implements IDisplayUnitInBimDocument { + index: number; + displayUnitIndex?: number; + displayUnit?: IDisplayUnit; + bimDocumentIndex?: number; + bimDocument?: IBimDocument; + static createFromTable(table: IDisplayUnitInBimDocumentTable, index: number): Promise; +} +export declare class DisplayUnitInBimDocumentTable implements IDisplayUnitInBimDocumentTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(displayUnitInBimDocumentIndex: number): Promise; + getAll(): Promise; + getDisplayUnitIndex(displayUnitInBimDocumentIndex: number): Promise; + getAllDisplayUnitIndex(): Promise; + getDisplayUnit(displayUnitInBimDocumentIndex: number): Promise; + getBimDocumentIndex(displayUnitInBimDocumentIndex: number): Promise; + getAllBimDocumentIndex(): Promise; + getBimDocument(displayUnitInBimDocumentIndex: number): Promise; +} +export interface IPhaseOrderInBimDocument { + index: number; + orderIndex?: number; + phaseIndex?: number; + phase?: IPhase; + bimDocumentIndex?: number; + bimDocument?: IBimDocument; +} +export interface IPhaseOrderInBimDocumentTable { + getCount(): Promise; + get(phaseOrderInBimDocumentIndex: number): Promise; + getAll(): Promise; + getOrderIndex(phaseOrderInBimDocumentIndex: number): Promise; + getAllOrderIndex(): Promise; + getPhaseIndex(phaseOrderInBimDocumentIndex: number): Promise; + getAllPhaseIndex(): Promise; + getPhase(phaseOrderInBimDocumentIndex: number): Promise; + getBimDocumentIndex(phaseOrderInBimDocumentIndex: number): Promise; + getAllBimDocumentIndex(): Promise; + getBimDocument(phaseOrderInBimDocumentIndex: number): Promise; +} +export declare class PhaseOrderInBimDocument implements IPhaseOrderInBimDocument { + index: number; + orderIndex?: number; + phaseIndex?: number; + phase?: IPhase; + bimDocumentIndex?: number; + bimDocument?: IBimDocument; + static createFromTable(table: IPhaseOrderInBimDocumentTable, index: number): Promise; +} +export declare class PhaseOrderInBimDocumentTable implements IPhaseOrderInBimDocumentTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(phaseOrderInBimDocumentIndex: number): Promise; + getAll(): Promise; + getOrderIndex(phaseOrderInBimDocumentIndex: number): Promise; + getAllOrderIndex(): Promise; + getPhaseIndex(phaseOrderInBimDocumentIndex: number): Promise; + getAllPhaseIndex(): Promise; + getPhase(phaseOrderInBimDocumentIndex: number): Promise; + getBimDocumentIndex(phaseOrderInBimDocumentIndex: number): Promise; + getAllBimDocumentIndex(): Promise; + getBimDocument(phaseOrderInBimDocumentIndex: number): Promise; +} +export interface ICategory { + index: number; + name?: string; + id?: bigint; + categoryType?: string; + lineColor_X?: number; + lineColor_Y?: number; + lineColor_Z?: number; + builtInCategory?: string; + parentIndex?: number; + parent?: ICategory; + materialIndex?: number; + material?: IMaterial; +} +export interface ICategoryTable { + getCount(): Promise; + get(categoryIndex: number): Promise; + getAll(): Promise; + getName(categoryIndex: number): Promise; + getAllName(): Promise; + getId(categoryIndex: number): Promise; + getAllId(): Promise; + getCategoryType(categoryIndex: number): Promise; + getAllCategoryType(): Promise; + getLineColor_X(categoryIndex: number): Promise; + getAllLineColor_X(): Promise; + getLineColor_Y(categoryIndex: number): Promise; + getAllLineColor_Y(): Promise; + getLineColor_Z(categoryIndex: number): Promise; + getAllLineColor_Z(): Promise; + getBuiltInCategory(categoryIndex: number): Promise; + getAllBuiltInCategory(): Promise; + getParentIndex(categoryIndex: number): Promise; + getAllParentIndex(): Promise; + getParent(categoryIndex: number): Promise; + getMaterialIndex(categoryIndex: number): Promise; + getAllMaterialIndex(): Promise; + getMaterial(categoryIndex: number): Promise; +} +export declare class Category implements ICategory { + index: number; + name?: string; + id?: bigint; + categoryType?: string; + lineColor_X?: number; + lineColor_Y?: number; + lineColor_Z?: number; + builtInCategory?: string; + parentIndex?: number; + parent?: ICategory; + materialIndex?: number; + material?: IMaterial; + static createFromTable(table: ICategoryTable, index: number): Promise; +} +export declare class CategoryTable implements ICategoryTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(categoryIndex: number): Promise; + getAll(): Promise; + getName(categoryIndex: number): Promise; + getAllName(): Promise; + getId(categoryIndex: number): Promise; + getAllId(): Promise; + getCategoryType(categoryIndex: number): Promise; + getAllCategoryType(): Promise; + getLineColor_X(categoryIndex: number): Promise; + getAllLineColor_X(): Promise; + getLineColor_Y(categoryIndex: number): Promise; + getAllLineColor_Y(): Promise; + getLineColor_Z(categoryIndex: number): Promise; + getAllLineColor_Z(): Promise; + getBuiltInCategory(categoryIndex: number): Promise; + getAllBuiltInCategory(): Promise; + getParentIndex(categoryIndex: number): Promise; + getAllParentIndex(): Promise; + getParent(categoryIndex: number): Promise; + getMaterialIndex(categoryIndex: number): Promise; + getAllMaterialIndex(): Promise; + getMaterial(categoryIndex: number): Promise; +} +export interface IFamily { + index: number; + structuralMaterialType?: string; + structuralSectionShape?: string; + isSystemFamily?: boolean; + isInPlace?: boolean; + familyCategoryIndex?: number; + familyCategory?: ICategory; + elementIndex?: number; + element?: IElement; +} +export interface IFamilyTable { + getCount(): Promise; + get(familyIndex: number): Promise; + getAll(): Promise; + getStructuralMaterialType(familyIndex: number): Promise; + getAllStructuralMaterialType(): Promise; + getStructuralSectionShape(familyIndex: number): Promise; + getAllStructuralSectionShape(): Promise; + getIsSystemFamily(familyIndex: number): Promise; + getAllIsSystemFamily(): Promise; + getIsInPlace(familyIndex: number): Promise; + getAllIsInPlace(): Promise; + getFamilyCategoryIndex(familyIndex: number): Promise; + getAllFamilyCategoryIndex(): Promise; + getFamilyCategory(familyIndex: number): Promise; + getElementIndex(familyIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(familyIndex: number): Promise; +} +export declare class Family implements IFamily { + index: number; + structuralMaterialType?: string; + structuralSectionShape?: string; + isSystemFamily?: boolean; + isInPlace?: boolean; + familyCategoryIndex?: number; + familyCategory?: ICategory; + elementIndex?: number; + element?: IElement; + static createFromTable(table: IFamilyTable, index: number): Promise; +} +export declare class FamilyTable implements IFamilyTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(familyIndex: number): Promise; + getAll(): Promise; + getStructuralMaterialType(familyIndex: number): Promise; + getAllStructuralMaterialType(): Promise; + getStructuralSectionShape(familyIndex: number): Promise; + getAllStructuralSectionShape(): Promise; + getIsSystemFamily(familyIndex: number): Promise; + getAllIsSystemFamily(): Promise; + getIsInPlace(familyIndex: number): Promise; + getAllIsInPlace(): Promise; + getFamilyCategoryIndex(familyIndex: number): Promise; + getAllFamilyCategoryIndex(): Promise; + getFamilyCategory(familyIndex: number): Promise; + getElementIndex(familyIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(familyIndex: number): Promise; +} +export interface IFamilyType { + index: number; + isSystemFamilyType?: boolean; + familyIndex?: number; + family?: IFamily; + compoundStructureIndex?: number; + compoundStructure?: ICompoundStructure; + elementIndex?: number; + element?: IElement; +} +export interface IFamilyTypeTable { + getCount(): Promise; + get(familyTypeIndex: number): Promise; + getAll(): Promise; + getIsSystemFamilyType(familyTypeIndex: number): Promise; + getAllIsSystemFamilyType(): Promise; + getFamilyIndex(familyTypeIndex: number): Promise; + getAllFamilyIndex(): Promise; + getFamily(familyTypeIndex: number): Promise; + getCompoundStructureIndex(familyTypeIndex: number): Promise; + getAllCompoundStructureIndex(): Promise; + getCompoundStructure(familyTypeIndex: number): Promise; + getElementIndex(familyTypeIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(familyTypeIndex: number): Promise; +} +export declare class FamilyType implements IFamilyType { + index: number; + isSystemFamilyType?: boolean; + familyIndex?: number; + family?: IFamily; + compoundStructureIndex?: number; + compoundStructure?: ICompoundStructure; + elementIndex?: number; + element?: IElement; + static createFromTable(table: IFamilyTypeTable, index: number): Promise; +} +export declare class FamilyTypeTable implements IFamilyTypeTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(familyTypeIndex: number): Promise; + getAll(): Promise; + getIsSystemFamilyType(familyTypeIndex: number): Promise; + getAllIsSystemFamilyType(): Promise; + getFamilyIndex(familyTypeIndex: number): Promise; + getAllFamilyIndex(): Promise; + getFamily(familyTypeIndex: number): Promise; + getCompoundStructureIndex(familyTypeIndex: number): Promise; + getAllCompoundStructureIndex(): Promise; + getCompoundStructure(familyTypeIndex: number): Promise; + getElementIndex(familyTypeIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(familyTypeIndex: number): Promise; +} +export interface IFamilyInstance { + index: number; + facingFlipped?: boolean; + facingOrientation_X?: number; + facingOrientation_Y?: number; + facingOrientation_Z?: number; + handFlipped?: boolean; + mirrored?: boolean; + hasModifiedGeometry?: boolean; + scale?: number; + basisX_X?: number; + basisX_Y?: number; + basisX_Z?: number; + basisY_X?: number; + basisY_Y?: number; + basisY_Z?: number; + basisZ_X?: number; + basisZ_Y?: number; + basisZ_Z?: number; + translation_X?: number; + translation_Y?: number; + translation_Z?: number; + handOrientation_X?: number; + handOrientation_Y?: number; + handOrientation_Z?: number; + familyTypeIndex?: number; + familyType?: IFamilyType; + hostIndex?: number; + host?: IElement; + fromRoomIndex?: number; + fromRoom?: IRoom; + toRoomIndex?: number; + toRoom?: IRoom; + elementIndex?: number; + element?: IElement; +} +export interface IFamilyInstanceTable { + getCount(): Promise; + get(familyInstanceIndex: number): Promise; + getAll(): Promise; + getFacingFlipped(familyInstanceIndex: number): Promise; + getAllFacingFlipped(): Promise; + getFacingOrientation_X(familyInstanceIndex: number): Promise; + getAllFacingOrientation_X(): Promise; + getFacingOrientation_Y(familyInstanceIndex: number): Promise; + getAllFacingOrientation_Y(): Promise; + getFacingOrientation_Z(familyInstanceIndex: number): Promise; + getAllFacingOrientation_Z(): Promise; + getHandFlipped(familyInstanceIndex: number): Promise; + getAllHandFlipped(): Promise; + getMirrored(familyInstanceIndex: number): Promise; + getAllMirrored(): Promise; + getHasModifiedGeometry(familyInstanceIndex: number): Promise; + getAllHasModifiedGeometry(): Promise; + getScale(familyInstanceIndex: number): Promise; + getAllScale(): Promise; + getBasisX_X(familyInstanceIndex: number): Promise; + getAllBasisX_X(): Promise; + getBasisX_Y(familyInstanceIndex: number): Promise; + getAllBasisX_Y(): Promise; + getBasisX_Z(familyInstanceIndex: number): Promise; + getAllBasisX_Z(): Promise; + getBasisY_X(familyInstanceIndex: number): Promise; + getAllBasisY_X(): Promise; + getBasisY_Y(familyInstanceIndex: number): Promise; + getAllBasisY_Y(): Promise; + getBasisY_Z(familyInstanceIndex: number): Promise; + getAllBasisY_Z(): Promise; + getBasisZ_X(familyInstanceIndex: number): Promise; + getAllBasisZ_X(): Promise; + getBasisZ_Y(familyInstanceIndex: number): Promise; + getAllBasisZ_Y(): Promise; + getBasisZ_Z(familyInstanceIndex: number): Promise; + getAllBasisZ_Z(): Promise; + getTranslation_X(familyInstanceIndex: number): Promise; + getAllTranslation_X(): Promise; + getTranslation_Y(familyInstanceIndex: number): Promise; + getAllTranslation_Y(): Promise; + getTranslation_Z(familyInstanceIndex: number): Promise; + getAllTranslation_Z(): Promise; + getHandOrientation_X(familyInstanceIndex: number): Promise; + getAllHandOrientation_X(): Promise; + getHandOrientation_Y(familyInstanceIndex: number): Promise; + getAllHandOrientation_Y(): Promise; + getHandOrientation_Z(familyInstanceIndex: number): Promise; + getAllHandOrientation_Z(): Promise; + getFamilyTypeIndex(familyInstanceIndex: number): Promise; + getAllFamilyTypeIndex(): Promise; + getFamilyType(familyInstanceIndex: number): Promise; + getHostIndex(familyInstanceIndex: number): Promise; + getAllHostIndex(): Promise; + getHost(familyInstanceIndex: number): Promise; + getFromRoomIndex(familyInstanceIndex: number): Promise; + getAllFromRoomIndex(): Promise; + getFromRoom(familyInstanceIndex: number): Promise; + getToRoomIndex(familyInstanceIndex: number): Promise; + getAllToRoomIndex(): Promise; + getToRoom(familyInstanceIndex: number): Promise; + getElementIndex(familyInstanceIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(familyInstanceIndex: number): Promise; +} +export declare class FamilyInstance implements IFamilyInstance { + index: number; + facingFlipped?: boolean; + facingOrientation_X?: number; + facingOrientation_Y?: number; + facingOrientation_Z?: number; + handFlipped?: boolean; + mirrored?: boolean; + hasModifiedGeometry?: boolean; + scale?: number; + basisX_X?: number; + basisX_Y?: number; + basisX_Z?: number; + basisY_X?: number; + basisY_Y?: number; + basisY_Z?: number; + basisZ_X?: number; + basisZ_Y?: number; + basisZ_Z?: number; + translation_X?: number; + translation_Y?: number; + translation_Z?: number; + handOrientation_X?: number; + handOrientation_Y?: number; + handOrientation_Z?: number; + familyTypeIndex?: number; + familyType?: IFamilyType; + hostIndex?: number; + host?: IElement; + fromRoomIndex?: number; + fromRoom?: IRoom; + toRoomIndex?: number; + toRoom?: IRoom; + elementIndex?: number; + element?: IElement; + static createFromTable(table: IFamilyInstanceTable, index: number): Promise; +} +export declare class FamilyInstanceTable implements IFamilyInstanceTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(familyInstanceIndex: number): Promise; + getAll(): Promise; + getFacingFlipped(familyInstanceIndex: number): Promise; + getAllFacingFlipped(): Promise; + getFacingOrientation_X(familyInstanceIndex: number): Promise; + getAllFacingOrientation_X(): Promise; + getFacingOrientation_Y(familyInstanceIndex: number): Promise; + getAllFacingOrientation_Y(): Promise; + getFacingOrientation_Z(familyInstanceIndex: number): Promise; + getAllFacingOrientation_Z(): Promise; + getHandFlipped(familyInstanceIndex: number): Promise; + getAllHandFlipped(): Promise; + getMirrored(familyInstanceIndex: number): Promise; + getAllMirrored(): Promise; + getHasModifiedGeometry(familyInstanceIndex: number): Promise; + getAllHasModifiedGeometry(): Promise; + getScale(familyInstanceIndex: number): Promise; + getAllScale(): Promise; + getBasisX_X(familyInstanceIndex: number): Promise; + getAllBasisX_X(): Promise; + getBasisX_Y(familyInstanceIndex: number): Promise; + getAllBasisX_Y(): Promise; + getBasisX_Z(familyInstanceIndex: number): Promise; + getAllBasisX_Z(): Promise; + getBasisY_X(familyInstanceIndex: number): Promise; + getAllBasisY_X(): Promise; + getBasisY_Y(familyInstanceIndex: number): Promise; + getAllBasisY_Y(): Promise; + getBasisY_Z(familyInstanceIndex: number): Promise; + getAllBasisY_Z(): Promise; + getBasisZ_X(familyInstanceIndex: number): Promise; + getAllBasisZ_X(): Promise; + getBasisZ_Y(familyInstanceIndex: number): Promise; + getAllBasisZ_Y(): Promise; + getBasisZ_Z(familyInstanceIndex: number): Promise; + getAllBasisZ_Z(): Promise; + getTranslation_X(familyInstanceIndex: number): Promise; + getAllTranslation_X(): Promise; + getTranslation_Y(familyInstanceIndex: number): Promise; + getAllTranslation_Y(): Promise; + getTranslation_Z(familyInstanceIndex: number): Promise; + getAllTranslation_Z(): Promise; + getHandOrientation_X(familyInstanceIndex: number): Promise; + getAllHandOrientation_X(): Promise; + getHandOrientation_Y(familyInstanceIndex: number): Promise; + getAllHandOrientation_Y(): Promise; + getHandOrientation_Z(familyInstanceIndex: number): Promise; + getAllHandOrientation_Z(): Promise; + getFamilyTypeIndex(familyInstanceIndex: number): Promise; + getAllFamilyTypeIndex(): Promise; + getFamilyType(familyInstanceIndex: number): Promise; + getHostIndex(familyInstanceIndex: number): Promise; + getAllHostIndex(): Promise; + getHost(familyInstanceIndex: number): Promise; + getFromRoomIndex(familyInstanceIndex: number): Promise; + getAllFromRoomIndex(): Promise; + getFromRoom(familyInstanceIndex: number): Promise; + getToRoomIndex(familyInstanceIndex: number): Promise; + getAllToRoomIndex(): Promise; + getToRoom(familyInstanceIndex: number): Promise; + getElementIndex(familyInstanceIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(familyInstanceIndex: number): Promise; +} +export interface IView { + index: number; + title?: string; + viewType?: string; + up_X?: number; + up_Y?: number; + up_Z?: number; + right_X?: number; + right_Y?: number; + right_Z?: number; + origin_X?: number; + origin_Y?: number; + origin_Z?: number; + viewDirection_X?: number; + viewDirection_Y?: number; + viewDirection_Z?: number; + viewPosition_X?: number; + viewPosition_Y?: number; + viewPosition_Z?: number; + scale?: number; + outline_Min_X?: number; + outline_Min_Y?: number; + outline_Max_X?: number; + outline_Max_Y?: number; + detailLevel?: number; + cameraIndex?: number; + camera?: ICamera; + familyTypeIndex?: number; + familyType?: IFamilyType; + elementIndex?: number; + element?: IElement; +} +export interface IViewTable { + getCount(): Promise; + get(viewIndex: number): Promise; + getAll(): Promise; + getTitle(viewIndex: number): Promise; + getAllTitle(): Promise; + getViewType(viewIndex: number): Promise; + getAllViewType(): Promise; + getUp_X(viewIndex: number): Promise; + getAllUp_X(): Promise; + getUp_Y(viewIndex: number): Promise; + getAllUp_Y(): Promise; + getUp_Z(viewIndex: number): Promise; + getAllUp_Z(): Promise; + getRight_X(viewIndex: number): Promise; + getAllRight_X(): Promise; + getRight_Y(viewIndex: number): Promise; + getAllRight_Y(): Promise; + getRight_Z(viewIndex: number): Promise; + getAllRight_Z(): Promise; + getOrigin_X(viewIndex: number): Promise; + getAllOrigin_X(): Promise; + getOrigin_Y(viewIndex: number): Promise; + getAllOrigin_Y(): Promise; + getOrigin_Z(viewIndex: number): Promise; + getAllOrigin_Z(): Promise; + getViewDirection_X(viewIndex: number): Promise; + getAllViewDirection_X(): Promise; + getViewDirection_Y(viewIndex: number): Promise; + getAllViewDirection_Y(): Promise; + getViewDirection_Z(viewIndex: number): Promise; + getAllViewDirection_Z(): Promise; + getViewPosition_X(viewIndex: number): Promise; + getAllViewPosition_X(): Promise; + getViewPosition_Y(viewIndex: number): Promise; + getAllViewPosition_Y(): Promise; + getViewPosition_Z(viewIndex: number): Promise; + getAllViewPosition_Z(): Promise; + getScale(viewIndex: number): Promise; + getAllScale(): Promise; + getOutline_Min_X(viewIndex: number): Promise; + getAllOutline_Min_X(): Promise; + getOutline_Min_Y(viewIndex: number): Promise; + getAllOutline_Min_Y(): Promise; + getOutline_Max_X(viewIndex: number): Promise; + getAllOutline_Max_X(): Promise; + getOutline_Max_Y(viewIndex: number): Promise; + getAllOutline_Max_Y(): Promise; + getDetailLevel(viewIndex: number): Promise; + getAllDetailLevel(): Promise; + getCameraIndex(viewIndex: number): Promise; + getAllCameraIndex(): Promise; + getCamera(viewIndex: number): Promise; + getFamilyTypeIndex(viewIndex: number): Promise; + getAllFamilyTypeIndex(): Promise; + getFamilyType(viewIndex: number): Promise; + getElementIndex(viewIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(viewIndex: number): Promise; +} +export declare class View implements IView { + index: number; + title?: string; + viewType?: string; + up_X?: number; + up_Y?: number; + up_Z?: number; + right_X?: number; + right_Y?: number; + right_Z?: number; + origin_X?: number; + origin_Y?: number; + origin_Z?: number; + viewDirection_X?: number; + viewDirection_Y?: number; + viewDirection_Z?: number; + viewPosition_X?: number; + viewPosition_Y?: number; + viewPosition_Z?: number; + scale?: number; + outline_Min_X?: number; + outline_Min_Y?: number; + outline_Max_X?: number; + outline_Max_Y?: number; + detailLevel?: number; + cameraIndex?: number; + camera?: ICamera; + familyTypeIndex?: number; + familyType?: IFamilyType; + elementIndex?: number; + element?: IElement; + static createFromTable(table: IViewTable, index: number): Promise; +} +export declare class ViewTable implements IViewTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(viewIndex: number): Promise; + getAll(): Promise; + getTitle(viewIndex: number): Promise; + getAllTitle(): Promise; + getViewType(viewIndex: number): Promise; + getAllViewType(): Promise; + getUp_X(viewIndex: number): Promise; + getAllUp_X(): Promise; + getUp_Y(viewIndex: number): Promise; + getAllUp_Y(): Promise; + getUp_Z(viewIndex: number): Promise; + getAllUp_Z(): Promise; + getRight_X(viewIndex: number): Promise; + getAllRight_X(): Promise; + getRight_Y(viewIndex: number): Promise; + getAllRight_Y(): Promise; + getRight_Z(viewIndex: number): Promise; + getAllRight_Z(): Promise; + getOrigin_X(viewIndex: number): Promise; + getAllOrigin_X(): Promise; + getOrigin_Y(viewIndex: number): Promise; + getAllOrigin_Y(): Promise; + getOrigin_Z(viewIndex: number): Promise; + getAllOrigin_Z(): Promise; + getViewDirection_X(viewIndex: number): Promise; + getAllViewDirection_X(): Promise; + getViewDirection_Y(viewIndex: number): Promise; + getAllViewDirection_Y(): Promise; + getViewDirection_Z(viewIndex: number): Promise; + getAllViewDirection_Z(): Promise; + getViewPosition_X(viewIndex: number): Promise; + getAllViewPosition_X(): Promise; + getViewPosition_Y(viewIndex: number): Promise; + getAllViewPosition_Y(): Promise; + getViewPosition_Z(viewIndex: number): Promise; + getAllViewPosition_Z(): Promise; + getScale(viewIndex: number): Promise; + getAllScale(): Promise; + getOutline_Min_X(viewIndex: number): Promise; + getAllOutline_Min_X(): Promise; + getOutline_Min_Y(viewIndex: number): Promise; + getAllOutline_Min_Y(): Promise; + getOutline_Max_X(viewIndex: number): Promise; + getAllOutline_Max_X(): Promise; + getOutline_Max_Y(viewIndex: number): Promise; + getAllOutline_Max_Y(): Promise; + getDetailLevel(viewIndex: number): Promise; + getAllDetailLevel(): Promise; + getCameraIndex(viewIndex: number): Promise; + getAllCameraIndex(): Promise; + getCamera(viewIndex: number): Promise; + getFamilyTypeIndex(viewIndex: number): Promise; + getAllFamilyTypeIndex(): Promise; + getFamilyType(viewIndex: number): Promise; + getElementIndex(viewIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(viewIndex: number): Promise; +} +export interface IElementInView { + index: number; + viewIndex?: number; + view?: IView; + elementIndex?: number; + element?: IElement; +} +export interface IElementInViewTable { + getCount(): Promise; + get(elementInViewIndex: number): Promise; + getAll(): Promise; + getViewIndex(elementInViewIndex: number): Promise; + getAllViewIndex(): Promise; + getView(elementInViewIndex: number): Promise; + getElementIndex(elementInViewIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(elementInViewIndex: number): Promise; +} +export declare class ElementInView implements IElementInView { + index: number; + viewIndex?: number; + view?: IView; + elementIndex?: number; + element?: IElement; + static createFromTable(table: IElementInViewTable, index: number): Promise; +} +export declare class ElementInViewTable implements IElementInViewTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(elementInViewIndex: number): Promise; + getAll(): Promise; + getViewIndex(elementInViewIndex: number): Promise; + getAllViewIndex(): Promise; + getView(elementInViewIndex: number): Promise; + getElementIndex(elementInViewIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(elementInViewIndex: number): Promise; +} +export interface IShapeInView { + index: number; + shapeIndex?: number; + shape?: IShape; + viewIndex?: number; + view?: IView; +} +export interface IShapeInViewTable { + getCount(): Promise; + get(shapeInViewIndex: number): Promise; + getAll(): Promise; + getShapeIndex(shapeInViewIndex: number): Promise; + getAllShapeIndex(): Promise; + getShape(shapeInViewIndex: number): Promise; + getViewIndex(shapeInViewIndex: number): Promise; + getAllViewIndex(): Promise; + getView(shapeInViewIndex: number): Promise; +} +export declare class ShapeInView implements IShapeInView { + index: number; + shapeIndex?: number; + shape?: IShape; + viewIndex?: number; + view?: IView; + static createFromTable(table: IShapeInViewTable, index: number): Promise; +} +export declare class ShapeInViewTable implements IShapeInViewTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(shapeInViewIndex: number): Promise; + getAll(): Promise; + getShapeIndex(shapeInViewIndex: number): Promise; + getAllShapeIndex(): Promise; + getShape(shapeInViewIndex: number): Promise; + getViewIndex(shapeInViewIndex: number): Promise; + getAllViewIndex(): Promise; + getView(shapeInViewIndex: number): Promise; +} +export interface IAssetInView { + index: number; + assetIndex?: number; + asset?: IAsset; + viewIndex?: number; + view?: IView; +} +export interface IAssetInViewTable { + getCount(): Promise; + get(assetInViewIndex: number): Promise; + getAll(): Promise; + getAssetIndex(assetInViewIndex: number): Promise; + getAllAssetIndex(): Promise; + getAsset(assetInViewIndex: number): Promise; + getViewIndex(assetInViewIndex: number): Promise; + getAllViewIndex(): Promise; + getView(assetInViewIndex: number): Promise; +} +export declare class AssetInView implements IAssetInView { + index: number; + assetIndex?: number; + asset?: IAsset; + viewIndex?: number; + view?: IView; + static createFromTable(table: IAssetInViewTable, index: number): Promise; +} +export declare class AssetInViewTable implements IAssetInViewTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(assetInViewIndex: number): Promise; + getAll(): Promise; + getAssetIndex(assetInViewIndex: number): Promise; + getAllAssetIndex(): Promise; + getAsset(assetInViewIndex: number): Promise; + getViewIndex(assetInViewIndex: number): Promise; + getAllViewIndex(): Promise; + getView(assetInViewIndex: number): Promise; +} +export interface IAssetInViewSheet { + index: number; + assetIndex?: number; + asset?: IAsset; + viewSheetIndex?: number; + viewSheet?: IViewSheet; +} +export interface IAssetInViewSheetTable { + getCount(): Promise; + get(assetInViewSheetIndex: number): Promise; + getAll(): Promise; + getAssetIndex(assetInViewSheetIndex: number): Promise; + getAllAssetIndex(): Promise; + getAsset(assetInViewSheetIndex: number): Promise; + getViewSheetIndex(assetInViewSheetIndex: number): Promise; + getAllViewSheetIndex(): Promise; + getViewSheet(assetInViewSheetIndex: number): Promise; +} +export declare class AssetInViewSheet implements IAssetInViewSheet { + index: number; + assetIndex?: number; + asset?: IAsset; + viewSheetIndex?: number; + viewSheet?: IViewSheet; + static createFromTable(table: IAssetInViewSheetTable, index: number): Promise; +} +export declare class AssetInViewSheetTable implements IAssetInViewSheetTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(assetInViewSheetIndex: number): Promise; + getAll(): Promise; + getAssetIndex(assetInViewSheetIndex: number): Promise; + getAllAssetIndex(): Promise; + getAsset(assetInViewSheetIndex: number): Promise; + getViewSheetIndex(assetInViewSheetIndex: number): Promise; + getAllViewSheetIndex(): Promise; + getViewSheet(assetInViewSheetIndex: number): Promise; +} +export interface ILevelInView { + index: number; + extents_Min_X?: number; + extents_Min_Y?: number; + extents_Min_Z?: number; + extents_Max_X?: number; + extents_Max_Y?: number; + extents_Max_Z?: number; + levelIndex?: number; + level?: ILevel; + viewIndex?: number; + view?: IView; +} +export interface ILevelInViewTable { + getCount(): Promise; + get(levelInViewIndex: number): Promise; + getAll(): Promise; + getExtents_Min_X(levelInViewIndex: number): Promise; + getAllExtents_Min_X(): Promise; + getExtents_Min_Y(levelInViewIndex: number): Promise; + getAllExtents_Min_Y(): Promise; + getExtents_Min_Z(levelInViewIndex: number): Promise; + getAllExtents_Min_Z(): Promise; + getExtents_Max_X(levelInViewIndex: number): Promise; + getAllExtents_Max_X(): Promise; + getExtents_Max_Y(levelInViewIndex: number): Promise; + getAllExtents_Max_Y(): Promise; + getExtents_Max_Z(levelInViewIndex: number): Promise; + getAllExtents_Max_Z(): Promise; + getLevelIndex(levelInViewIndex: number): Promise; + getAllLevelIndex(): Promise; + getLevel(levelInViewIndex: number): Promise; + getViewIndex(levelInViewIndex: number): Promise; + getAllViewIndex(): Promise; + getView(levelInViewIndex: number): Promise; +} +export declare class LevelInView implements ILevelInView { + index: number; + extents_Min_X?: number; + extents_Min_Y?: number; + extents_Min_Z?: number; + extents_Max_X?: number; + extents_Max_Y?: number; + extents_Max_Z?: number; + levelIndex?: number; + level?: ILevel; + viewIndex?: number; + view?: IView; + static createFromTable(table: ILevelInViewTable, index: number): Promise; +} +export declare class LevelInViewTable implements ILevelInViewTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(levelInViewIndex: number): Promise; + getAll(): Promise; + getExtents_Min_X(levelInViewIndex: number): Promise; + getAllExtents_Min_X(): Promise; + getExtents_Min_Y(levelInViewIndex: number): Promise; + getAllExtents_Min_Y(): Promise; + getExtents_Min_Z(levelInViewIndex: number): Promise; + getAllExtents_Min_Z(): Promise; + getExtents_Max_X(levelInViewIndex: number): Promise; + getAllExtents_Max_X(): Promise; + getExtents_Max_Y(levelInViewIndex: number): Promise; + getAllExtents_Max_Y(): Promise; + getExtents_Max_Z(levelInViewIndex: number): Promise; + getAllExtents_Max_Z(): Promise; + getLevelIndex(levelInViewIndex: number): Promise; + getAllLevelIndex(): Promise; + getLevel(levelInViewIndex: number): Promise; + getViewIndex(levelInViewIndex: number): Promise; + getAllViewIndex(): Promise; + getView(levelInViewIndex: number): Promise; +} +export interface ICamera { + index: number; + id?: number; + isPerspective?: number; + verticalExtent?: number; + horizontalExtent?: number; + farDistance?: number; + nearDistance?: number; + targetDistance?: number; + rightOffset?: number; + upOffset?: number; +} +export interface ICameraTable { + getCount(): Promise; + get(cameraIndex: number): Promise; + getAll(): Promise; + getId(cameraIndex: number): Promise; + getAllId(): Promise; + getIsPerspective(cameraIndex: number): Promise; + getAllIsPerspective(): Promise; + getVerticalExtent(cameraIndex: number): Promise; + getAllVerticalExtent(): Promise; + getHorizontalExtent(cameraIndex: number): Promise; + getAllHorizontalExtent(): Promise; + getFarDistance(cameraIndex: number): Promise; + getAllFarDistance(): Promise; + getNearDistance(cameraIndex: number): Promise; + getAllNearDistance(): Promise; + getTargetDistance(cameraIndex: number): Promise; + getAllTargetDistance(): Promise; + getRightOffset(cameraIndex: number): Promise; + getAllRightOffset(): Promise; + getUpOffset(cameraIndex: number): Promise; + getAllUpOffset(): Promise; +} +export declare class Camera implements ICamera { + index: number; + id?: number; + isPerspective?: number; + verticalExtent?: number; + horizontalExtent?: number; + farDistance?: number; + nearDistance?: number; + targetDistance?: number; + rightOffset?: number; + upOffset?: number; + static createFromTable(table: ICameraTable, index: number): Promise; +} +export declare class CameraTable implements ICameraTable { + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(cameraIndex: number): Promise; + getAll(): Promise; + getId(cameraIndex: number): Promise; + getAllId(): Promise; + getIsPerspective(cameraIndex: number): Promise; + getAllIsPerspective(): Promise; + getVerticalExtent(cameraIndex: number): Promise; + getAllVerticalExtent(): Promise; + getHorizontalExtent(cameraIndex: number): Promise; + getAllHorizontalExtent(): Promise; + getFarDistance(cameraIndex: number): Promise; + getAllFarDistance(): Promise; + getNearDistance(cameraIndex: number): Promise; + getAllNearDistance(): Promise; + getTargetDistance(cameraIndex: number): Promise; + getAllTargetDistance(): Promise; + getRightOffset(cameraIndex: number): Promise; + getAllRightOffset(): Promise; + getUpOffset(cameraIndex: number): Promise; + getAllUpOffset(): Promise; +} +export interface IMaterial { + index: number; + name?: string; + materialCategory?: string; + color_X?: number; + color_Y?: number; + color_Z?: number; + colorUvScaling_X?: number; + colorUvScaling_Y?: number; + colorUvOffset_X?: number; + colorUvOffset_Y?: number; + normalUvScaling_X?: number; + normalUvScaling_Y?: number; + normalUvOffset_X?: number; + normalUvOffset_Y?: number; + normalAmount?: number; + glossiness?: number; + smoothness?: number; + transparency?: number; + colorTextureFileIndex?: number; + colorTextureFile?: IAsset; + normalTextureFileIndex?: number; + normalTextureFile?: IAsset; + elementIndex?: number; + element?: IElement; +} +export interface IMaterialTable { + getCount(): Promise; + get(materialIndex: number): Promise; + getAll(): Promise; + getName(materialIndex: number): Promise; + getAllName(): Promise; + getMaterialCategory(materialIndex: number): Promise; + getAllMaterialCategory(): Promise; + getColor_X(materialIndex: number): Promise; + getAllColor_X(): Promise; + getColor_Y(materialIndex: number): Promise; + getAllColor_Y(): Promise; + getColor_Z(materialIndex: number): Promise; + getAllColor_Z(): Promise; + getColorUvScaling_X(materialIndex: number): Promise; + getAllColorUvScaling_X(): Promise; + getColorUvScaling_Y(materialIndex: number): Promise; + getAllColorUvScaling_Y(): Promise; + getColorUvOffset_X(materialIndex: number): Promise; + getAllColorUvOffset_X(): Promise; + getColorUvOffset_Y(materialIndex: number): Promise; + getAllColorUvOffset_Y(): Promise; + getNormalUvScaling_X(materialIndex: number): Promise; + getAllNormalUvScaling_X(): Promise; + getNormalUvScaling_Y(materialIndex: number): Promise; + getAllNormalUvScaling_Y(): Promise; + getNormalUvOffset_X(materialIndex: number): Promise; + getAllNormalUvOffset_X(): Promise; + getNormalUvOffset_Y(materialIndex: number): Promise; + getAllNormalUvOffset_Y(): Promise; + getNormalAmount(materialIndex: number): Promise; + getAllNormalAmount(): Promise; + getGlossiness(materialIndex: number): Promise; + getAllGlossiness(): Promise; + getSmoothness(materialIndex: number): Promise; + getAllSmoothness(): Promise; + getTransparency(materialIndex: number): Promise; + getAllTransparency(): Promise; + getColorTextureFileIndex(materialIndex: number): Promise; + getAllColorTextureFileIndex(): Promise; + getColorTextureFile(materialIndex: number): Promise; + getNormalTextureFileIndex(materialIndex: number): Promise; + getAllNormalTextureFileIndex(): Promise; + getNormalTextureFile(materialIndex: number): Promise; + getElementIndex(materialIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(materialIndex: number): Promise; +} +export declare class Material implements IMaterial { + index: number; + name?: string; + materialCategory?: string; + color_X?: number; + color_Y?: number; + color_Z?: number; + colorUvScaling_X?: number; + colorUvScaling_Y?: number; + colorUvOffset_X?: number; + colorUvOffset_Y?: number; + normalUvScaling_X?: number; + normalUvScaling_Y?: number; + normalUvOffset_X?: number; + normalUvOffset_Y?: number; + normalAmount?: number; + glossiness?: number; + smoothness?: number; + transparency?: number; + colorTextureFileIndex?: number; + colorTextureFile?: IAsset; + normalTextureFileIndex?: number; + normalTextureFile?: IAsset; + elementIndex?: number; + element?: IElement; + static createFromTable(table: IMaterialTable, index: number): Promise; +} +export declare class MaterialTable implements IMaterialTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(materialIndex: number): Promise; + getAll(): Promise; + getName(materialIndex: number): Promise; + getAllName(): Promise; + getMaterialCategory(materialIndex: number): Promise; + getAllMaterialCategory(): Promise; + getColor_X(materialIndex: number): Promise; + getAllColor_X(): Promise; + getColor_Y(materialIndex: number): Promise; + getAllColor_Y(): Promise; + getColor_Z(materialIndex: number): Promise; + getAllColor_Z(): Promise; + getColorUvScaling_X(materialIndex: number): Promise; + getAllColorUvScaling_X(): Promise; + getColorUvScaling_Y(materialIndex: number): Promise; + getAllColorUvScaling_Y(): Promise; + getColorUvOffset_X(materialIndex: number): Promise; + getAllColorUvOffset_X(): Promise; + getColorUvOffset_Y(materialIndex: number): Promise; + getAllColorUvOffset_Y(): Promise; + getNormalUvScaling_X(materialIndex: number): Promise; + getAllNormalUvScaling_X(): Promise; + getNormalUvScaling_Y(materialIndex: number): Promise; + getAllNormalUvScaling_Y(): Promise; + getNormalUvOffset_X(materialIndex: number): Promise; + getAllNormalUvOffset_X(): Promise; + getNormalUvOffset_Y(materialIndex: number): Promise; + getAllNormalUvOffset_Y(): Promise; + getNormalAmount(materialIndex: number): Promise; + getAllNormalAmount(): Promise; + getGlossiness(materialIndex: number): Promise; + getAllGlossiness(): Promise; + getSmoothness(materialIndex: number): Promise; + getAllSmoothness(): Promise; + getTransparency(materialIndex: number): Promise; + getAllTransparency(): Promise; + getColorTextureFileIndex(materialIndex: number): Promise; + getAllColorTextureFileIndex(): Promise; + getColorTextureFile(materialIndex: number): Promise; + getNormalTextureFileIndex(materialIndex: number): Promise; + getAllNormalTextureFileIndex(): Promise; + getNormalTextureFile(materialIndex: number): Promise; + getElementIndex(materialIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(materialIndex: number): Promise; +} +export interface IMaterialInElement { + index: number; + area?: number; + volume?: number; + isPaint?: boolean; + materialIndex?: number; + material?: IMaterial; + elementIndex?: number; + element?: IElement; +} +export interface IMaterialInElementTable { + getCount(): Promise; + get(materialInElementIndex: number): Promise; + getAll(): Promise; + getArea(materialInElementIndex: number): Promise; + getAllArea(): Promise; + getVolume(materialInElementIndex: number): Promise; + getAllVolume(): Promise; + getIsPaint(materialInElementIndex: number): Promise; + getAllIsPaint(): Promise; + getMaterialIndex(materialInElementIndex: number): Promise; + getAllMaterialIndex(): Promise; + getMaterial(materialInElementIndex: number): Promise; + getElementIndex(materialInElementIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(materialInElementIndex: number): Promise; +} +export declare class MaterialInElement implements IMaterialInElement { + index: number; + area?: number; + volume?: number; + isPaint?: boolean; + materialIndex?: number; + material?: IMaterial; + elementIndex?: number; + element?: IElement; + static createFromTable(table: IMaterialInElementTable, index: number): Promise; +} +export declare class MaterialInElementTable implements IMaterialInElementTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(materialInElementIndex: number): Promise; + getAll(): Promise; + getArea(materialInElementIndex: number): Promise; + getAllArea(): Promise; + getVolume(materialInElementIndex: number): Promise; + getAllVolume(): Promise; + getIsPaint(materialInElementIndex: number): Promise; + getAllIsPaint(): Promise; + getMaterialIndex(materialInElementIndex: number): Promise; + getAllMaterialIndex(): Promise; + getMaterial(materialInElementIndex: number): Promise; + getElementIndex(materialInElementIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(materialInElementIndex: number): Promise; +} +export interface ICompoundStructureLayer { + index: number; + orderIndex?: number; + width?: number; + materialFunctionAssignment?: string; + materialIndex?: number; + material?: IMaterial; + compoundStructureIndex?: number; + compoundStructure?: ICompoundStructure; +} +export interface ICompoundStructureLayerTable { + getCount(): Promise; + get(compoundStructureLayerIndex: number): Promise; + getAll(): Promise; + getOrderIndex(compoundStructureLayerIndex: number): Promise; + getAllOrderIndex(): Promise; + getWidth(compoundStructureLayerIndex: number): Promise; + getAllWidth(): Promise; + getMaterialFunctionAssignment(compoundStructureLayerIndex: number): Promise; + getAllMaterialFunctionAssignment(): Promise; + getMaterialIndex(compoundStructureLayerIndex: number): Promise; + getAllMaterialIndex(): Promise; + getMaterial(compoundStructureLayerIndex: number): Promise; + getCompoundStructureIndex(compoundStructureLayerIndex: number): Promise; + getAllCompoundStructureIndex(): Promise; + getCompoundStructure(compoundStructureLayerIndex: number): Promise; +} +export declare class CompoundStructureLayer implements ICompoundStructureLayer { + index: number; + orderIndex?: number; + width?: number; + materialFunctionAssignment?: string; + materialIndex?: number; + material?: IMaterial; + compoundStructureIndex?: number; + compoundStructure?: ICompoundStructure; + static createFromTable(table: ICompoundStructureLayerTable, index: number): Promise; +} +export declare class CompoundStructureLayerTable implements ICompoundStructureLayerTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(compoundStructureLayerIndex: number): Promise; + getAll(): Promise; + getOrderIndex(compoundStructureLayerIndex: number): Promise; + getAllOrderIndex(): Promise; + getWidth(compoundStructureLayerIndex: number): Promise; + getAllWidth(): Promise; + getMaterialFunctionAssignment(compoundStructureLayerIndex: number): Promise; + getAllMaterialFunctionAssignment(): Promise; + getMaterialIndex(compoundStructureLayerIndex: number): Promise; + getAllMaterialIndex(): Promise; + getMaterial(compoundStructureLayerIndex: number): Promise; + getCompoundStructureIndex(compoundStructureLayerIndex: number): Promise; + getAllCompoundStructureIndex(): Promise; + getCompoundStructure(compoundStructureLayerIndex: number): Promise; +} +export interface ICompoundStructure { + index: number; + width?: number; + structuralLayerIndex?: number; + structuralLayer?: ICompoundStructureLayer; +} +export interface ICompoundStructureTable { + getCount(): Promise; + get(compoundStructureIndex: number): Promise; + getAll(): Promise; + getWidth(compoundStructureIndex: number): Promise; + getAllWidth(): Promise; + getStructuralLayerIndex(compoundStructureIndex: number): Promise; + getAllStructuralLayerIndex(): Promise; + getStructuralLayer(compoundStructureIndex: number): Promise; +} +export declare class CompoundStructure implements ICompoundStructure { + index: number; + width?: number; + structuralLayerIndex?: number; + structuralLayer?: ICompoundStructureLayer; + static createFromTable(table: ICompoundStructureTable, index: number): Promise; +} +export declare class CompoundStructureTable implements ICompoundStructureTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(compoundStructureIndex: number): Promise; + getAll(): Promise; + getWidth(compoundStructureIndex: number): Promise; + getAllWidth(): Promise; + getStructuralLayerIndex(compoundStructureIndex: number): Promise; + getAllStructuralLayerIndex(): Promise; + getStructuralLayer(compoundStructureIndex: number): Promise; +} +export interface INode { + index: number; + elementIndex?: number; + element?: IElement; +} +export interface INodeTable { + getCount(): Promise; + get(nodeIndex: number): Promise; + getAll(): Promise; + getElementIndex(nodeIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(nodeIndex: number): Promise; +} +export declare class Node implements INode { + index: number; + elementIndex?: number; + element?: IElement; + static createFromTable(table: INodeTable, index: number): Promise; +} +export declare class NodeTable implements INodeTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(nodeIndex: number): Promise; + getAll(): Promise; + getElementIndex(nodeIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(nodeIndex: number): Promise; +} +export interface IGeometry { + index: number; + box_Min_X?: number; + box_Min_Y?: number; + box_Min_Z?: number; + box_Max_X?: number; + box_Max_Y?: number; + box_Max_Z?: number; + vertexCount?: number; + faceCount?: number; +} +export interface IGeometryTable { + getCount(): Promise; + get(geometryIndex: number): Promise; + getAll(): Promise; + getBox_Min_X(geometryIndex: number): Promise; + getAllBox_Min_X(): Promise; + getBox_Min_Y(geometryIndex: number): Promise; + getAllBox_Min_Y(): Promise; + getBox_Min_Z(geometryIndex: number): Promise; + getAllBox_Min_Z(): Promise; + getBox_Max_X(geometryIndex: number): Promise; + getAllBox_Max_X(): Promise; + getBox_Max_Y(geometryIndex: number): Promise; + getAllBox_Max_Y(): Promise; + getBox_Max_Z(geometryIndex: number): Promise; + getAllBox_Max_Z(): Promise; + getVertexCount(geometryIndex: number): Promise; + getAllVertexCount(): Promise; + getFaceCount(geometryIndex: number): Promise; + getAllFaceCount(): Promise; +} +export declare class Geometry implements IGeometry { + index: number; + box_Min_X?: number; + box_Min_Y?: number; + box_Min_Z?: number; + box_Max_X?: number; + box_Max_Y?: number; + box_Max_Z?: number; + vertexCount?: number; + faceCount?: number; + static createFromTable(table: IGeometryTable, index: number): Promise; +} +export declare class GeometryTable implements IGeometryTable { + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(geometryIndex: number): Promise; + getAll(): Promise; + getBox_Min_X(geometryIndex: number): Promise; + getAllBox_Min_X(): Promise; + getBox_Min_Y(geometryIndex: number): Promise; + getAllBox_Min_Y(): Promise; + getBox_Min_Z(geometryIndex: number): Promise; + getAllBox_Min_Z(): Promise; + getBox_Max_X(geometryIndex: number): Promise; + getAllBox_Max_X(): Promise; + getBox_Max_Y(geometryIndex: number): Promise; + getAllBox_Max_Y(): Promise; + getBox_Max_Z(geometryIndex: number): Promise; + getAllBox_Max_Z(): Promise; + getVertexCount(geometryIndex: number): Promise; + getAllVertexCount(): Promise; + getFaceCount(geometryIndex: number): Promise; + getAllFaceCount(): Promise; +} +export interface IShape { + index: number; + elementIndex?: number; + element?: IElement; +} +export interface IShapeTable { + getCount(): Promise; + get(shapeIndex: number): Promise; + getAll(): Promise; + getElementIndex(shapeIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(shapeIndex: number): Promise; +} +export declare class Shape implements IShape { + index: number; + elementIndex?: number; + element?: IElement; + static createFromTable(table: IShapeTable, index: number): Promise; +} +export declare class ShapeTable implements IShapeTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(shapeIndex: number): Promise; + getAll(): Promise; + getElementIndex(shapeIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(shapeIndex: number): Promise; +} +export interface IShapeCollection { + index: number; + elementIndex?: number; + element?: IElement; +} +export interface IShapeCollectionTable { + getCount(): Promise; + get(shapeCollectionIndex: number): Promise; + getAll(): Promise; + getElementIndex(shapeCollectionIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(shapeCollectionIndex: number): Promise; +} +export declare class ShapeCollection implements IShapeCollection { + index: number; + elementIndex?: number; + element?: IElement; + static createFromTable(table: IShapeCollectionTable, index: number): Promise; +} +export declare class ShapeCollectionTable implements IShapeCollectionTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(shapeCollectionIndex: number): Promise; + getAll(): Promise; + getElementIndex(shapeCollectionIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(shapeCollectionIndex: number): Promise; +} +export interface IShapeInShapeCollection { + index: number; + shapeIndex?: number; + shape?: IShape; + shapeCollectionIndex?: number; + shapeCollection?: IShapeCollection; +} +export interface IShapeInShapeCollectionTable { + getCount(): Promise; + get(shapeInShapeCollectionIndex: number): Promise; + getAll(): Promise; + getShapeIndex(shapeInShapeCollectionIndex: number): Promise; + getAllShapeIndex(): Promise; + getShape(shapeInShapeCollectionIndex: number): Promise; + getShapeCollectionIndex(shapeInShapeCollectionIndex: number): Promise; + getAllShapeCollectionIndex(): Promise; + getShapeCollection(shapeInShapeCollectionIndex: number): Promise; +} +export declare class ShapeInShapeCollection implements IShapeInShapeCollection { + index: number; + shapeIndex?: number; + shape?: IShape; + shapeCollectionIndex?: number; + shapeCollection?: IShapeCollection; + static createFromTable(table: IShapeInShapeCollectionTable, index: number): Promise; +} +export declare class ShapeInShapeCollectionTable implements IShapeInShapeCollectionTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(shapeInShapeCollectionIndex: number): Promise; + getAll(): Promise; + getShapeIndex(shapeInShapeCollectionIndex: number): Promise; + getAllShapeIndex(): Promise; + getShape(shapeInShapeCollectionIndex: number): Promise; + getShapeCollectionIndex(shapeInShapeCollectionIndex: number): Promise; + getAllShapeCollectionIndex(): Promise; + getShapeCollection(shapeInShapeCollectionIndex: number): Promise; +} +export interface ISystem { + index: number; + systemType?: number; + familyTypeIndex?: number; + familyType?: IFamilyType; + elementIndex?: number; + element?: IElement; +} +export interface ISystemTable { + getCount(): Promise; + get(systemIndex: number): Promise; + getAll(): Promise; + getSystemType(systemIndex: number): Promise; + getAllSystemType(): Promise; + getFamilyTypeIndex(systemIndex: number): Promise; + getAllFamilyTypeIndex(): Promise; + getFamilyType(systemIndex: number): Promise; + getElementIndex(systemIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(systemIndex: number): Promise; +} +export declare class System implements ISystem { + index: number; + systemType?: number; + familyTypeIndex?: number; + familyType?: IFamilyType; + elementIndex?: number; + element?: IElement; + static createFromTable(table: ISystemTable, index: number): Promise; +} +export declare class SystemTable implements ISystemTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(systemIndex: number): Promise; + getAll(): Promise; + getSystemType(systemIndex: number): Promise; + getAllSystemType(): Promise; + getFamilyTypeIndex(systemIndex: number): Promise; + getAllFamilyTypeIndex(): Promise; + getFamilyType(systemIndex: number): Promise; + getElementIndex(systemIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(systemIndex: number): Promise; +} +export interface IElementInSystem { + index: number; + roles?: number; + systemIndex?: number; + system?: ISystem; + elementIndex?: number; + element?: IElement; +} +export interface IElementInSystemTable { + getCount(): Promise; + get(elementInSystemIndex: number): Promise; + getAll(): Promise; + getRoles(elementInSystemIndex: number): Promise; + getAllRoles(): Promise; + getSystemIndex(elementInSystemIndex: number): Promise; + getAllSystemIndex(): Promise; + getSystem(elementInSystemIndex: number): Promise; + getElementIndex(elementInSystemIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(elementInSystemIndex: number): Promise; +} +export declare class ElementInSystem implements IElementInSystem { + index: number; + roles?: number; + systemIndex?: number; + system?: ISystem; + elementIndex?: number; + element?: IElement; + static createFromTable(table: IElementInSystemTable, index: number): Promise; +} +export declare class ElementInSystemTable implements IElementInSystemTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(elementInSystemIndex: number): Promise; + getAll(): Promise; + getRoles(elementInSystemIndex: number): Promise; + getAllRoles(): Promise; + getSystemIndex(elementInSystemIndex: number): Promise; + getAllSystemIndex(): Promise; + getSystem(elementInSystemIndex: number): Promise; + getElementIndex(elementInSystemIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(elementInSystemIndex: number): Promise; +} +export interface IWarning { + index: number; + guid?: string; + severity?: string; + description?: string; + bimDocumentIndex?: number; + bimDocument?: IBimDocument; +} +export interface IWarningTable { + getCount(): Promise; + get(warningIndex: number): Promise; + getAll(): Promise; + getGuid(warningIndex: number): Promise; + getAllGuid(): Promise; + getSeverity(warningIndex: number): Promise; + getAllSeverity(): Promise; + getDescription(warningIndex: number): Promise; + getAllDescription(): Promise; + getBimDocumentIndex(warningIndex: number): Promise; + getAllBimDocumentIndex(): Promise; + getBimDocument(warningIndex: number): Promise; +} +export declare class Warning implements IWarning { + index: number; + guid?: string; + severity?: string; + description?: string; + bimDocumentIndex?: number; + bimDocument?: IBimDocument; + static createFromTable(table: IWarningTable, index: number): Promise; +} +export declare class WarningTable implements IWarningTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(warningIndex: number): Promise; + getAll(): Promise; + getGuid(warningIndex: number): Promise; + getAllGuid(): Promise; + getSeverity(warningIndex: number): Promise; + getAllSeverity(): Promise; + getDescription(warningIndex: number): Promise; + getAllDescription(): Promise; + getBimDocumentIndex(warningIndex: number): Promise; + getAllBimDocumentIndex(): Promise; + getBimDocument(warningIndex: number): Promise; +} +export interface IElementInWarning { + index: number; + warningIndex?: number; + warning?: IWarning; + elementIndex?: number; + element?: IElement; +} +export interface IElementInWarningTable { + getCount(): Promise; + get(elementInWarningIndex: number): Promise; + getAll(): Promise; + getWarningIndex(elementInWarningIndex: number): Promise; + getAllWarningIndex(): Promise; + getWarning(elementInWarningIndex: number): Promise; + getElementIndex(elementInWarningIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(elementInWarningIndex: number): Promise; +} +export declare class ElementInWarning implements IElementInWarning { + index: number; + warningIndex?: number; + warning?: IWarning; + elementIndex?: number; + element?: IElement; + static createFromTable(table: IElementInWarningTable, index: number): Promise; +} +export declare class ElementInWarningTable implements IElementInWarningTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(elementInWarningIndex: number): Promise; + getAll(): Promise; + getWarningIndex(elementInWarningIndex: number): Promise; + getAllWarningIndex(): Promise; + getWarning(elementInWarningIndex: number): Promise; + getElementIndex(elementInWarningIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(elementInWarningIndex: number): Promise; +} +export interface IBasePoint { + index: number; + isSurveyPoint?: boolean; + position_X?: number; + position_Y?: number; + position_Z?: number; + sharedPosition_X?: number; + sharedPosition_Y?: number; + sharedPosition_Z?: number; + elementIndex?: number; + element?: IElement; +} +export interface IBasePointTable { + getCount(): Promise; + get(basePointIndex: number): Promise; + getAll(): Promise; + getIsSurveyPoint(basePointIndex: number): Promise; + getAllIsSurveyPoint(): Promise; + getPosition_X(basePointIndex: number): Promise; + getAllPosition_X(): Promise; + getPosition_Y(basePointIndex: number): Promise; + getAllPosition_Y(): Promise; + getPosition_Z(basePointIndex: number): Promise; + getAllPosition_Z(): Promise; + getSharedPosition_X(basePointIndex: number): Promise; + getAllSharedPosition_X(): Promise; + getSharedPosition_Y(basePointIndex: number): Promise; + getAllSharedPosition_Y(): Promise; + getSharedPosition_Z(basePointIndex: number): Promise; + getAllSharedPosition_Z(): Promise; + getElementIndex(basePointIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(basePointIndex: number): Promise; +} +export declare class BasePoint implements IBasePoint { + index: number; + isSurveyPoint?: boolean; + position_X?: number; + position_Y?: number; + position_Z?: number; + sharedPosition_X?: number; + sharedPosition_Y?: number; + sharedPosition_Z?: number; + elementIndex?: number; + element?: IElement; + static createFromTable(table: IBasePointTable, index: number): Promise; +} +export declare class BasePointTable implements IBasePointTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(basePointIndex: number): Promise; + getAll(): Promise; + getIsSurveyPoint(basePointIndex: number): Promise; + getAllIsSurveyPoint(): Promise; + getPosition_X(basePointIndex: number): Promise; + getAllPosition_X(): Promise; + getPosition_Y(basePointIndex: number): Promise; + getAllPosition_Y(): Promise; + getPosition_Z(basePointIndex: number): Promise; + getAllPosition_Z(): Promise; + getSharedPosition_X(basePointIndex: number): Promise; + getAllSharedPosition_X(): Promise; + getSharedPosition_Y(basePointIndex: number): Promise; + getAllSharedPosition_Y(): Promise; + getSharedPosition_Z(basePointIndex: number): Promise; + getAllSharedPosition_Z(): Promise; + getElementIndex(basePointIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(basePointIndex: number): Promise; +} +export interface IPhaseFilter { + index: number; + _new?: number; + existing?: number; + demolished?: number; + temporary?: number; + elementIndex?: number; + element?: IElement; +} +export interface IPhaseFilterTable { + getCount(): Promise; + get(phaseFilterIndex: number): Promise; + getAll(): Promise; + getNew(phaseFilterIndex: number): Promise; + getAllNew(): Promise; + getExisting(phaseFilterIndex: number): Promise; + getAllExisting(): Promise; + getDemolished(phaseFilterIndex: number): Promise; + getAllDemolished(): Promise; + getTemporary(phaseFilterIndex: number): Promise; + getAllTemporary(): Promise; + getElementIndex(phaseFilterIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(phaseFilterIndex: number): Promise; +} +export declare class PhaseFilter implements IPhaseFilter { + index: number; + _new?: number; + existing?: number; + demolished?: number; + temporary?: number; + elementIndex?: number; + element?: IElement; + static createFromTable(table: IPhaseFilterTable, index: number): Promise; +} +export declare class PhaseFilterTable implements IPhaseFilterTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(phaseFilterIndex: number): Promise; + getAll(): Promise; + getNew(phaseFilterIndex: number): Promise; + getAllNew(): Promise; + getExisting(phaseFilterIndex: number): Promise; + getAllExisting(): Promise; + getDemolished(phaseFilterIndex: number): Promise; + getAllDemolished(): Promise; + getTemporary(phaseFilterIndex: number): Promise; + getAllTemporary(): Promise; + getElementIndex(phaseFilterIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(phaseFilterIndex: number): Promise; +} +export interface IGrid { + index: number; + startPoint_X?: number; + startPoint_Y?: number; + startPoint_Z?: number; + endPoint_X?: number; + endPoint_Y?: number; + endPoint_Z?: number; + isCurved?: boolean; + extents_Min_X?: number; + extents_Min_Y?: number; + extents_Min_Z?: number; + extents_Max_X?: number; + extents_Max_Y?: number; + extents_Max_Z?: number; + familyTypeIndex?: number; + familyType?: IFamilyType; + elementIndex?: number; + element?: IElement; +} +export interface IGridTable { + getCount(): Promise; + get(gridIndex: number): Promise; + getAll(): Promise; + getStartPoint_X(gridIndex: number): Promise; + getAllStartPoint_X(): Promise; + getStartPoint_Y(gridIndex: number): Promise; + getAllStartPoint_Y(): Promise; + getStartPoint_Z(gridIndex: number): Promise; + getAllStartPoint_Z(): Promise; + getEndPoint_X(gridIndex: number): Promise; + getAllEndPoint_X(): Promise; + getEndPoint_Y(gridIndex: number): Promise; + getAllEndPoint_Y(): Promise; + getEndPoint_Z(gridIndex: number): Promise; + getAllEndPoint_Z(): Promise; + getIsCurved(gridIndex: number): Promise; + getAllIsCurved(): Promise; + getExtents_Min_X(gridIndex: number): Promise; + getAllExtents_Min_X(): Promise; + getExtents_Min_Y(gridIndex: number): Promise; + getAllExtents_Min_Y(): Promise; + getExtents_Min_Z(gridIndex: number): Promise; + getAllExtents_Min_Z(): Promise; + getExtents_Max_X(gridIndex: number): Promise; + getAllExtents_Max_X(): Promise; + getExtents_Max_Y(gridIndex: number): Promise; + getAllExtents_Max_Y(): Promise; + getExtents_Max_Z(gridIndex: number): Promise; + getAllExtents_Max_Z(): Promise; + getFamilyTypeIndex(gridIndex: number): Promise; + getAllFamilyTypeIndex(): Promise; + getFamilyType(gridIndex: number): Promise; + getElementIndex(gridIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(gridIndex: number): Promise; +} +export declare class Grid implements IGrid { + index: number; + startPoint_X?: number; + startPoint_Y?: number; + startPoint_Z?: number; + endPoint_X?: number; + endPoint_Y?: number; + endPoint_Z?: number; + isCurved?: boolean; + extents_Min_X?: number; + extents_Min_Y?: number; + extents_Min_Z?: number; + extents_Max_X?: number; + extents_Max_Y?: number; + extents_Max_Z?: number; + familyTypeIndex?: number; + familyType?: IFamilyType; + elementIndex?: number; + element?: IElement; + static createFromTable(table: IGridTable, index: number): Promise; +} +export declare class GridTable implements IGridTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(gridIndex: number): Promise; + getAll(): Promise; + getStartPoint_X(gridIndex: number): Promise; + getAllStartPoint_X(): Promise; + getStartPoint_Y(gridIndex: number): Promise; + getAllStartPoint_Y(): Promise; + getStartPoint_Z(gridIndex: number): Promise; + getAllStartPoint_Z(): Promise; + getEndPoint_X(gridIndex: number): Promise; + getAllEndPoint_X(): Promise; + getEndPoint_Y(gridIndex: number): Promise; + getAllEndPoint_Y(): Promise; + getEndPoint_Z(gridIndex: number): Promise; + getAllEndPoint_Z(): Promise; + getIsCurved(gridIndex: number): Promise; + getAllIsCurved(): Promise; + getExtents_Min_X(gridIndex: number): Promise; + getAllExtents_Min_X(): Promise; + getExtents_Min_Y(gridIndex: number): Promise; + getAllExtents_Min_Y(): Promise; + getExtents_Min_Z(gridIndex: number): Promise; + getAllExtents_Min_Z(): Promise; + getExtents_Max_X(gridIndex: number): Promise; + getAllExtents_Max_X(): Promise; + getExtents_Max_Y(gridIndex: number): Promise; + getAllExtents_Max_Y(): Promise; + getExtents_Max_Z(gridIndex: number): Promise; + getAllExtents_Max_Z(): Promise; + getFamilyTypeIndex(gridIndex: number): Promise; + getAllFamilyTypeIndex(): Promise; + getFamilyType(gridIndex: number): Promise; + getElementIndex(gridIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(gridIndex: number): Promise; +} +export interface IArea { + index: number; + value?: number; + perimeter?: number; + number?: string; + isGrossInterior?: boolean; + areaSchemeIndex?: number; + areaScheme?: IAreaScheme; + elementIndex?: number; + element?: IElement; +} +export interface IAreaTable { + getCount(): Promise; + get(areaIndex: number): Promise; + getAll(): Promise; + getValue(areaIndex: number): Promise; + getAllValue(): Promise; + getPerimeter(areaIndex: number): Promise; + getAllPerimeter(): Promise; + getNumber(areaIndex: number): Promise; + getAllNumber(): Promise; + getIsGrossInterior(areaIndex: number): Promise; + getAllIsGrossInterior(): Promise; + getAreaSchemeIndex(areaIndex: number): Promise; + getAllAreaSchemeIndex(): Promise; + getAreaScheme(areaIndex: number): Promise; + getElementIndex(areaIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(areaIndex: number): Promise; +} +export declare class Area implements IArea { + index: number; + value?: number; + perimeter?: number; + number?: string; + isGrossInterior?: boolean; + areaSchemeIndex?: number; + areaScheme?: IAreaScheme; + elementIndex?: number; + element?: IElement; + static createFromTable(table: IAreaTable, index: number): Promise; +} +export declare class AreaTable implements IAreaTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(areaIndex: number): Promise; + getAll(): Promise; + getValue(areaIndex: number): Promise; + getAllValue(): Promise; + getPerimeter(areaIndex: number): Promise; + getAllPerimeter(): Promise; + getNumber(areaIndex: number): Promise; + getAllNumber(): Promise; + getIsGrossInterior(areaIndex: number): Promise; + getAllIsGrossInterior(): Promise; + getAreaSchemeIndex(areaIndex: number): Promise; + getAllAreaSchemeIndex(): Promise; + getAreaScheme(areaIndex: number): Promise; + getElementIndex(areaIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(areaIndex: number): Promise; +} +export interface IAreaScheme { + index: number; + isGrossBuildingArea?: boolean; + elementIndex?: number; + element?: IElement; +} +export interface IAreaSchemeTable { + getCount(): Promise; + get(areaSchemeIndex: number): Promise; + getAll(): Promise; + getIsGrossBuildingArea(areaSchemeIndex: number): Promise; + getAllIsGrossBuildingArea(): Promise; + getElementIndex(areaSchemeIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(areaSchemeIndex: number): Promise; +} +export declare class AreaScheme implements IAreaScheme { + index: number; + isGrossBuildingArea?: boolean; + elementIndex?: number; + element?: IElement; + static createFromTable(table: IAreaSchemeTable, index: number): Promise; +} +export declare class AreaSchemeTable implements IAreaSchemeTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(areaSchemeIndex: number): Promise; + getAll(): Promise; + getIsGrossBuildingArea(areaSchemeIndex: number): Promise; + getAllIsGrossBuildingArea(): Promise; + getElementIndex(areaSchemeIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(areaSchemeIndex: number): Promise; +} +export interface ISchedule { + index: number; + elementIndex?: number; + element?: IElement; +} +export interface IScheduleTable { + getCount(): Promise; + get(scheduleIndex: number): Promise; + getAll(): Promise; + getElementIndex(scheduleIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(scheduleIndex: number): Promise; +} +export declare class Schedule implements ISchedule { + index: number; + elementIndex?: number; + element?: IElement; + static createFromTable(table: IScheduleTable, index: number): Promise; +} +export declare class ScheduleTable implements IScheduleTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(scheduleIndex: number): Promise; + getAll(): Promise; + getElementIndex(scheduleIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(scheduleIndex: number): Promise; +} +export interface IScheduleColumn { + index: number; + name?: string; + columnIndex?: number; + scheduleIndex?: number; + schedule?: ISchedule; +} +export interface IScheduleColumnTable { + getCount(): Promise; + get(scheduleColumnIndex: number): Promise; + getAll(): Promise; + getName(scheduleColumnIndex: number): Promise; + getAllName(): Promise; + getColumnIndex(scheduleColumnIndex: number): Promise; + getAllColumnIndex(): Promise; + getScheduleIndex(scheduleColumnIndex: number): Promise; + getAllScheduleIndex(): Promise; + getSchedule(scheduleColumnIndex: number): Promise; +} +export declare class ScheduleColumn implements IScheduleColumn { + index: number; + name?: string; + columnIndex?: number; + scheduleIndex?: number; + schedule?: ISchedule; + static createFromTable(table: IScheduleColumnTable, index: number): Promise; +} +export declare class ScheduleColumnTable implements IScheduleColumnTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(scheduleColumnIndex: number): Promise; + getAll(): Promise; + getName(scheduleColumnIndex: number): Promise; + getAllName(): Promise; + getColumnIndex(scheduleColumnIndex: number): Promise; + getAllColumnIndex(): Promise; + getScheduleIndex(scheduleColumnIndex: number): Promise; + getAllScheduleIndex(): Promise; + getSchedule(scheduleColumnIndex: number): Promise; +} +export interface IScheduleCell { + index: number; + value?: string; + rowIndex?: number; + scheduleColumnIndex?: number; + scheduleColumn?: IScheduleColumn; +} +export interface IScheduleCellTable { + getCount(): Promise; + get(scheduleCellIndex: number): Promise; + getAll(): Promise; + getValue(scheduleCellIndex: number): Promise; + getAllValue(): Promise; + getRowIndex(scheduleCellIndex: number): Promise; + getAllRowIndex(): Promise; + getScheduleColumnIndex(scheduleCellIndex: number): Promise; + getAllScheduleColumnIndex(): Promise; + getScheduleColumn(scheduleCellIndex: number): Promise; +} +export declare class ScheduleCell implements IScheduleCell { + index: number; + value?: string; + rowIndex?: number; + scheduleColumnIndex?: number; + scheduleColumn?: IScheduleColumn; + static createFromTable(table: IScheduleCellTable, index: number): Promise; +} +export declare class ScheduleCellTable implements IScheduleCellTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(scheduleCellIndex: number): Promise; + getAll(): Promise; + getValue(scheduleCellIndex: number): Promise; + getAllValue(): Promise; + getRowIndex(scheduleCellIndex: number): Promise; + getAllRowIndex(): Promise; + getScheduleColumnIndex(scheduleCellIndex: number): Promise; + getAllScheduleColumnIndex(): Promise; + getScheduleColumn(scheduleCellIndex: number): Promise; +} +export interface IViewSheetSet { + index: number; + elementIndex?: number; + element?: IElement; +} +export interface IViewSheetSetTable { + getCount(): Promise; + get(viewSheetSetIndex: number): Promise; + getAll(): Promise; + getElementIndex(viewSheetSetIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(viewSheetSetIndex: number): Promise; +} +export declare class ViewSheetSet implements IViewSheetSet { + index: number; + elementIndex?: number; + element?: IElement; + static createFromTable(table: IViewSheetSetTable, index: number): Promise; +} +export declare class ViewSheetSetTable implements IViewSheetSetTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(viewSheetSetIndex: number): Promise; + getAll(): Promise; + getElementIndex(viewSheetSetIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(viewSheetSetIndex: number): Promise; +} +export interface IViewSheet { + index: number; + familyTypeIndex?: number; + familyType?: IFamilyType; + elementIndex?: number; + element?: IElement; +} +export interface IViewSheetTable { + getCount(): Promise; + get(viewSheetIndex: number): Promise; + getAll(): Promise; + getFamilyTypeIndex(viewSheetIndex: number): Promise; + getAllFamilyTypeIndex(): Promise; + getFamilyType(viewSheetIndex: number): Promise; + getElementIndex(viewSheetIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(viewSheetIndex: number): Promise; +} +export declare class ViewSheet implements IViewSheet { + index: number; + familyTypeIndex?: number; + familyType?: IFamilyType; + elementIndex?: number; + element?: IElement; + static createFromTable(table: IViewSheetTable, index: number): Promise; +} +export declare class ViewSheetTable implements IViewSheetTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(viewSheetIndex: number): Promise; + getAll(): Promise; + getFamilyTypeIndex(viewSheetIndex: number): Promise; + getAllFamilyTypeIndex(): Promise; + getFamilyType(viewSheetIndex: number): Promise; + getElementIndex(viewSheetIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(viewSheetIndex: number): Promise; +} +export interface IViewSheetInViewSheetSet { + index: number; + viewSheetIndex?: number; + viewSheet?: IViewSheet; + viewSheetSetIndex?: number; + viewSheetSet?: IViewSheetSet; +} +export interface IViewSheetInViewSheetSetTable { + getCount(): Promise; + get(viewSheetInViewSheetSetIndex: number): Promise; + getAll(): Promise; + getViewSheetIndex(viewSheetInViewSheetSetIndex: number): Promise; + getAllViewSheetIndex(): Promise; + getViewSheet(viewSheetInViewSheetSetIndex: number): Promise; + getViewSheetSetIndex(viewSheetInViewSheetSetIndex: number): Promise; + getAllViewSheetSetIndex(): Promise; + getViewSheetSet(viewSheetInViewSheetSetIndex: number): Promise; +} +export declare class ViewSheetInViewSheetSet implements IViewSheetInViewSheetSet { + index: number; + viewSheetIndex?: number; + viewSheet?: IViewSheet; + viewSheetSetIndex?: number; + viewSheetSet?: IViewSheetSet; + static createFromTable(table: IViewSheetInViewSheetSetTable, index: number): Promise; +} +export declare class ViewSheetInViewSheetSetTable implements IViewSheetInViewSheetSetTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(viewSheetInViewSheetSetIndex: number): Promise; + getAll(): Promise; + getViewSheetIndex(viewSheetInViewSheetSetIndex: number): Promise; + getAllViewSheetIndex(): Promise; + getViewSheet(viewSheetInViewSheetSetIndex: number): Promise; + getViewSheetSetIndex(viewSheetInViewSheetSetIndex: number): Promise; + getAllViewSheetSetIndex(): Promise; + getViewSheetSet(viewSheetInViewSheetSetIndex: number): Promise; +} +export interface IViewInViewSheetSet { + index: number; + viewIndex?: number; + view?: IView; + viewSheetSetIndex?: number; + viewSheetSet?: IViewSheetSet; +} +export interface IViewInViewSheetSetTable { + getCount(): Promise; + get(viewInViewSheetSetIndex: number): Promise; + getAll(): Promise; + getViewIndex(viewInViewSheetSetIndex: number): Promise; + getAllViewIndex(): Promise; + getView(viewInViewSheetSetIndex: number): Promise; + getViewSheetSetIndex(viewInViewSheetSetIndex: number): Promise; + getAllViewSheetSetIndex(): Promise; + getViewSheetSet(viewInViewSheetSetIndex: number): Promise; +} +export declare class ViewInViewSheetSet implements IViewInViewSheetSet { + index: number; + viewIndex?: number; + view?: IView; + viewSheetSetIndex?: number; + viewSheetSet?: IViewSheetSet; + static createFromTable(table: IViewInViewSheetSetTable, index: number): Promise; +} +export declare class ViewInViewSheetSetTable implements IViewInViewSheetSetTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(viewInViewSheetSetIndex: number): Promise; + getAll(): Promise; + getViewIndex(viewInViewSheetSetIndex: number): Promise; + getAllViewIndex(): Promise; + getView(viewInViewSheetSetIndex: number): Promise; + getViewSheetSetIndex(viewInViewSheetSetIndex: number): Promise; + getAllViewSheetSetIndex(): Promise; + getViewSheetSet(viewInViewSheetSetIndex: number): Promise; +} +export interface IViewInViewSheet { + index: number; + viewIndex?: number; + view?: IView; + viewSheetIndex?: number; + viewSheet?: IViewSheet; +} +export interface IViewInViewSheetTable { + getCount(): Promise; + get(viewInViewSheetIndex: number): Promise; + getAll(): Promise; + getViewIndex(viewInViewSheetIndex: number): Promise; + getAllViewIndex(): Promise; + getView(viewInViewSheetIndex: number): Promise; + getViewSheetIndex(viewInViewSheetIndex: number): Promise; + getAllViewSheetIndex(): Promise; + getViewSheet(viewInViewSheetIndex: number): Promise; +} +export declare class ViewInViewSheet implements IViewInViewSheet { + index: number; + viewIndex?: number; + view?: IView; + viewSheetIndex?: number; + viewSheet?: IViewSheet; + static createFromTable(table: IViewInViewSheetTable, index: number): Promise; +} +export declare class ViewInViewSheetTable implements IViewInViewSheetTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(viewInViewSheetIndex: number): Promise; + getAll(): Promise; + getViewIndex(viewInViewSheetIndex: number): Promise; + getAllViewIndex(): Promise; + getView(viewInViewSheetIndex: number): Promise; + getViewSheetIndex(viewInViewSheetIndex: number): Promise; + getAllViewSheetIndex(): Promise; + getViewSheet(viewInViewSheetIndex: number): Promise; +} +export declare class VimDocument { + asset: IAssetTable | undefined; + displayUnit: IDisplayUnitTable | undefined; + parameterDescriptor: IParameterDescriptorTable | undefined; + parameter: IParameterTable | undefined; + element: IElementTable | undefined; + workset: IWorksetTable | undefined; + assemblyInstance: IAssemblyInstanceTable | undefined; + group: IGroupTable | undefined; + designOption: IDesignOptionTable | undefined; + level: ILevelTable | undefined; + phase: IPhaseTable | undefined; + room: IRoomTable | undefined; + bimDocument: IBimDocumentTable | undefined; + displayUnitInBimDocument: IDisplayUnitInBimDocumentTable | undefined; + phaseOrderInBimDocument: IPhaseOrderInBimDocumentTable | undefined; + category: ICategoryTable | undefined; + family: IFamilyTable | undefined; + familyType: IFamilyTypeTable | undefined; + familyInstance: IFamilyInstanceTable | undefined; + view: IViewTable | undefined; + elementInView: IElementInViewTable | undefined; + shapeInView: IShapeInViewTable | undefined; + assetInView: IAssetInViewTable | undefined; + assetInViewSheet: IAssetInViewSheetTable | undefined; + levelInView: ILevelInViewTable | undefined; + camera: ICameraTable | undefined; + material: IMaterialTable | undefined; + materialInElement: IMaterialInElementTable | undefined; + compoundStructureLayer: ICompoundStructureLayerTable | undefined; + compoundStructure: ICompoundStructureTable | undefined; + node: INodeTable | undefined; + geometry: IGeometryTable | undefined; + shape: IShapeTable | undefined; + shapeCollection: IShapeCollectionTable | undefined; + shapeInShapeCollection: IShapeInShapeCollectionTable | undefined; + system: ISystemTable | undefined; + elementInSystem: IElementInSystemTable | undefined; + warning: IWarningTable | undefined; + elementInWarning: IElementInWarningTable | undefined; + basePoint: IBasePointTable | undefined; + phaseFilter: IPhaseFilterTable | undefined; + grid: IGridTable | undefined; + area: IAreaTable | undefined; + areaScheme: IAreaSchemeTable | undefined; + schedule: IScheduleTable | undefined; + scheduleColumn: IScheduleColumnTable | undefined; + scheduleCell: IScheduleCellTable | undefined; + viewSheetSet: IViewSheetSetTable | undefined; + viewSheet: IViewSheetTable | undefined; + viewSheetInViewSheetSet: IViewSheetInViewSheetSetTable | undefined; + viewInViewSheetSet: IViewInViewSheetSetTable | undefined; + viewInViewSheet: IViewInViewSheetTable | undefined; + entities: BFast; + strings: string[] | undefined; + private constructor(); + static createFromBfast(bfast: BFast, ignoreStrings?: boolean): Promise; +} diff --git a/src/ts/dist/objectModel.js b/src/ts/dist/objectModel.js new file mode 100644 index 00000000..8f1cbbe4 --- /dev/null +++ b/src/ts/dist/objectModel.js @@ -0,0 +1,5996 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.LevelInViewTable = exports.LevelInView = exports.AssetInViewSheetTable = exports.AssetInViewSheet = exports.AssetInViewTable = exports.AssetInView = exports.ShapeInViewTable = exports.ShapeInView = exports.ElementInViewTable = exports.ElementInView = exports.ViewTable = exports.View = exports.FamilyInstanceTable = exports.FamilyInstance = exports.FamilyTypeTable = exports.FamilyType = exports.FamilyTable = exports.Family = exports.CategoryTable = exports.Category = exports.PhaseOrderInBimDocumentTable = exports.PhaseOrderInBimDocument = exports.DisplayUnitInBimDocumentTable = exports.DisplayUnitInBimDocument = exports.BimDocumentTable = exports.BimDocument = exports.RoomTable = exports.Room = exports.PhaseTable = exports.Phase = exports.LevelTable = exports.Level = exports.DesignOptionTable = exports.DesignOption = exports.GroupTable = exports.Group = exports.AssemblyInstanceTable = exports.AssemblyInstance = exports.WorksetTable = exports.Workset = exports.ElementTable = exports.Element = exports.ParameterTable = exports.Parameter = exports.ParameterDescriptorTable = exports.ParameterDescriptor = exports.DisplayUnitTable = exports.DisplayUnit = exports.AssetTable = exports.Asset = void 0; +exports.ViewSheetInViewSheetSetTable = exports.ViewSheetInViewSheetSet = exports.ViewSheetTable = exports.ViewSheet = exports.ViewSheetSetTable = exports.ViewSheetSet = exports.ScheduleCellTable = exports.ScheduleCell = exports.ScheduleColumnTable = exports.ScheduleColumn = exports.ScheduleTable = exports.Schedule = exports.AreaSchemeTable = exports.AreaScheme = exports.AreaTable = exports.Area = exports.GridTable = exports.Grid = exports.PhaseFilterTable = exports.PhaseFilter = exports.BasePointTable = exports.BasePoint = exports.ElementInWarningTable = exports.ElementInWarning = exports.WarningTable = exports.Warning = exports.ElementInSystemTable = exports.ElementInSystem = exports.SystemTable = exports.System = exports.ShapeInShapeCollectionTable = exports.ShapeInShapeCollection = exports.ShapeCollectionTable = exports.ShapeCollection = exports.ShapeTable = exports.Shape = exports.GeometryTable = exports.Geometry = exports.NodeTable = exports.Node = exports.CompoundStructureTable = exports.CompoundStructure = exports.CompoundStructureLayerTable = exports.CompoundStructureLayer = exports.MaterialInElementTable = exports.MaterialInElement = exports.MaterialTable = exports.Material = exports.CameraTable = exports.Camera = void 0; +exports.VimDocument = exports.ViewInViewSheetTable = exports.ViewInViewSheet = exports.ViewInViewSheetSetTable = exports.ViewInViewSheetSet = void 0; +const entityTable_1 = require("./entityTable"); +const vimLoader_1 = require("./vimLoader"); +class Asset { + static async createFromTable(table, index) { + let result = new Asset(); + result.index = index; + await Promise.all([ + table.getBufferName(index).then(v => result.bufferName = v), + ]); + return result; + } +} +exports.Asset = Asset; +class AssetTable { + static async createFromDocument(document) { + const entity = await document.entities.getBfast("Vim.Asset"); + if (!entity) { + return undefined; + } + let table = new AssetTable(); + table.entityTable = new entityTable_1.EntityTable(entity, document.strings); + return table; + } + getCount() { + return this.entityTable.getCount(); + } + async get(assetIndex) { + return await Asset.createFromTable(this, assetIndex); + } + async getAll() { + const localTable = await this.entityTable.getLocal(); + let bufferName; + await Promise.all([ + (async () => { bufferName = (await localTable.getStringArray("string:BufferName")); })(), + ]); + let asset = []; + for (let i = 0; i < bufferName.length; i++) { + asset.push({ + index: i, + bufferName: bufferName ? bufferName[i] : undefined + }); + } + return asset; + } + async getBufferName(assetIndex) { + return (await this.entityTable.getString(assetIndex, "string:BufferName")); + } + async getAllBufferName() { + return (await this.entityTable.getStringArray("string:BufferName")); + } +} +exports.AssetTable = AssetTable; +class DisplayUnit { + static async createFromTable(table, index) { + let result = new DisplayUnit(); + result.index = index; + await Promise.all([ + table.getSpec(index).then(v => result.spec = v), + table.getType(index).then(v => result.type = v), + table.getLabel(index).then(v => result.label = v), + ]); + return result; + } +} +exports.DisplayUnit = DisplayUnit; +class DisplayUnitTable { + static async createFromDocument(document) { + const entity = await document.entities.getBfast("Vim.DisplayUnit"); + if (!entity) { + return undefined; + } + let table = new DisplayUnitTable(); + table.entityTable = new entityTable_1.EntityTable(entity, document.strings); + return table; + } + getCount() { + return this.entityTable.getCount(); + } + async get(displayUnitIndex) { + return await DisplayUnit.createFromTable(this, displayUnitIndex); + } + async getAll() { + const localTable = await this.entityTable.getLocal(); + let spec; + let type; + let label; + await Promise.all([ + (async () => { spec = (await localTable.getStringArray("string:Spec")); })(), + (async () => { type = (await localTable.getStringArray("string:Type")); })(), + (async () => { label = (await localTable.getStringArray("string:Label")); })(), + ]); + let displayUnit = []; + for (let i = 0; i < spec.length; i++) { + displayUnit.push({ + index: i, + spec: spec ? spec[i] : undefined, + type: type ? type[i] : undefined, + label: label ? label[i] : undefined + }); + } + return displayUnit; + } + async getSpec(displayUnitIndex) { + return (await this.entityTable.getString(displayUnitIndex, "string:Spec")); + } + async getAllSpec() { + return (await this.entityTable.getStringArray("string:Spec")); + } + async getType(displayUnitIndex) { + return (await this.entityTable.getString(displayUnitIndex, "string:Type")); + } + async getAllType() { + return (await this.entityTable.getStringArray("string:Type")); + } + async getLabel(displayUnitIndex) { + return (await this.entityTable.getString(displayUnitIndex, "string:Label")); + } + async getAllLabel() { + return (await this.entityTable.getStringArray("string:Label")); + } +} +exports.DisplayUnitTable = DisplayUnitTable; +class ParameterDescriptor { + static async createFromTable(table, index) { + let result = new ParameterDescriptor(); + result.index = index; + await Promise.all([ + table.getName(index).then(v => result.name = v), + table.getGroup(index).then(v => result.group = v), + table.getParameterType(index).then(v => result.parameterType = v), + table.getIsInstance(index).then(v => result.isInstance = v), + table.getIsShared(index).then(v => result.isShared = v), + table.getIsReadOnly(index).then(v => result.isReadOnly = v), + table.getFlags(index).then(v => result.flags = v), + table.getGuid(index).then(v => result.guid = v), + table.getDisplayUnitIndex(index).then(v => result.displayUnitIndex = v), + ]); + return result; + } +} +exports.ParameterDescriptor = ParameterDescriptor; +class ParameterDescriptorTable { + static async createFromDocument(document) { + const entity = await document.entities.getBfast("Vim.ParameterDescriptor"); + if (!entity) { + return undefined; + } + let table = new ParameterDescriptorTable(); + table.document = document; + table.entityTable = new entityTable_1.EntityTable(entity, document.strings); + return table; + } + getCount() { + return this.entityTable.getCount(); + } + async get(parameterDescriptorIndex) { + return await ParameterDescriptor.createFromTable(this, parameterDescriptorIndex); + } + async getAll() { + const localTable = await this.entityTable.getLocal(); + let name; + let group; + let parameterType; + let isInstance; + let isShared; + let isReadOnly; + let flags; + let guid; + let displayUnitIndex; + await Promise.all([ + (async () => { name = (await localTable.getStringArray("string:Name")); })(), + (async () => { group = (await localTable.getStringArray("string:Group")); })(), + (async () => { parameterType = (await localTable.getStringArray("string:ParameterType")); })(), + (async () => { isInstance = (await localTable.getBooleanArray("byte:IsInstance")); })(), + (async () => { isShared = (await localTable.getBooleanArray("byte:IsShared")); })(), + (async () => { isReadOnly = (await localTable.getBooleanArray("byte:IsReadOnly")); })(), + (async () => { flags = (await localTable.getNumberArray("int:Flags")); })(), + (async () => { guid = (await localTable.getStringArray("string:Guid")); })(), + (async () => { displayUnitIndex = (await localTable.getNumberArray("index:Vim.DisplayUnit:DisplayUnit")); })(), + ]); + let parameterDescriptor = []; + for (let i = 0; i < name.length; i++) { + parameterDescriptor.push({ + index: i, + name: name ? name[i] : undefined, + group: group ? group[i] : undefined, + parameterType: parameterType ? parameterType[i] : undefined, + isInstance: isInstance ? isInstance[i] : undefined, + isShared: isShared ? isShared[i] : undefined, + isReadOnly: isReadOnly ? isReadOnly[i] : undefined, + flags: flags ? flags[i] : undefined, + guid: guid ? guid[i] : undefined, + displayUnitIndex: displayUnitIndex ? displayUnitIndex[i] : undefined + }); + } + return parameterDescriptor; + } + async getName(parameterDescriptorIndex) { + return (await this.entityTable.getString(parameterDescriptorIndex, "string:Name")); + } + async getAllName() { + return (await this.entityTable.getStringArray("string:Name")); + } + async getGroup(parameterDescriptorIndex) { + return (await this.entityTable.getString(parameterDescriptorIndex, "string:Group")); + } + async getAllGroup() { + return (await this.entityTable.getStringArray("string:Group")); + } + async getParameterType(parameterDescriptorIndex) { + return (await this.entityTable.getString(parameterDescriptorIndex, "string:ParameterType")); + } + async getAllParameterType() { + return (await this.entityTable.getStringArray("string:ParameterType")); + } + async getIsInstance(parameterDescriptorIndex) { + return (await this.entityTable.getBoolean(parameterDescriptorIndex, "byte:IsInstance")); + } + async getAllIsInstance() { + return (await this.entityTable.getBooleanArray("byte:IsInstance")); + } + async getIsShared(parameterDescriptorIndex) { + return (await this.entityTable.getBoolean(parameterDescriptorIndex, "byte:IsShared")); + } + async getAllIsShared() { + return (await this.entityTable.getBooleanArray("byte:IsShared")); + } + async getIsReadOnly(parameterDescriptorIndex) { + return (await this.entityTable.getBoolean(parameterDescriptorIndex, "byte:IsReadOnly")); + } + async getAllIsReadOnly() { + return (await this.entityTable.getBooleanArray("byte:IsReadOnly")); + } + async getFlags(parameterDescriptorIndex) { + return (await this.entityTable.getNumber(parameterDescriptorIndex, "int:Flags")); + } + async getAllFlags() { + return (await this.entityTable.getNumberArray("int:Flags")); + } + async getGuid(parameterDescriptorIndex) { + return (await this.entityTable.getString(parameterDescriptorIndex, "string:Guid")); + } + async getAllGuid() { + return (await this.entityTable.getStringArray("string:Guid")); + } + async getDisplayUnitIndex(parameterDescriptorIndex) { + return await this.entityTable.getNumber(parameterDescriptorIndex, "index:Vim.DisplayUnit:DisplayUnit"); + } + async getAllDisplayUnitIndex() { + return await this.entityTable.getNumberArray("index:Vim.DisplayUnit:DisplayUnit"); + } + async getDisplayUnit(parameterDescriptorIndex) { + const index = await this.getDisplayUnitIndex(parameterDescriptorIndex); + if (index === undefined) { + return undefined; + } + return await this.document.displayUnit?.get(index); + } +} +exports.ParameterDescriptorTable = ParameterDescriptorTable; +class Parameter { + static async createFromTable(table, index) { + let result = new Parameter(); + result.index = index; + await Promise.all([ + table.getValue(index).then(v => result.value = v), + table.getParameterDescriptorIndex(index).then(v => result.parameterDescriptorIndex = v), + table.getElementIndex(index).then(v => result.elementIndex = v), + ]); + return result; + } +} +exports.Parameter = Parameter; +class ParameterTable { + static async createFromDocument(document) { + const entity = await document.entities.getBfast("Vim.Parameter"); + if (!entity) { + return undefined; + } + let table = new ParameterTable(); + table.document = document; + table.entityTable = new entityTable_1.EntityTable(entity, document.strings); + return table; + } + getCount() { + return this.entityTable.getCount(); + } + async get(parameterIndex) { + return await Parameter.createFromTable(this, parameterIndex); + } + async getAll() { + const localTable = await this.entityTable.getLocal(); + let value; + let parameterDescriptorIndex; + let elementIndex; + await Promise.all([ + (async () => { value = (await localTable.getStringArray("string:Value")); })(), + (async () => { parameterDescriptorIndex = (await localTable.getNumberArray("index:Vim.ParameterDescriptor:ParameterDescriptor")); })(), + (async () => { elementIndex = (await localTable.getNumberArray("index:Vim.Element:Element")); })(), + ]); + let parameter = []; + for (let i = 0; i < value.length; i++) { + parameter.push({ + index: i, + value: value ? value[i] : undefined, + parameterDescriptorIndex: parameterDescriptorIndex ? parameterDescriptorIndex[i] : undefined, + elementIndex: elementIndex ? elementIndex[i] : undefined + }); + } + return parameter; + } + async getValue(parameterIndex) { + return (await this.entityTable.getString(parameterIndex, "string:Value")); + } + async getAllValue() { + return (await this.entityTable.getStringArray("string:Value")); + } + async getParameterDescriptorIndex(parameterIndex) { + return await this.entityTable.getNumber(parameterIndex, "index:Vim.ParameterDescriptor:ParameterDescriptor"); + } + async getAllParameterDescriptorIndex() { + return await this.entityTable.getNumberArray("index:Vim.ParameterDescriptor:ParameterDescriptor"); + } + async getParameterDescriptor(parameterIndex) { + const index = await this.getParameterDescriptorIndex(parameterIndex); + if (index === undefined) { + return undefined; + } + return await this.document.parameterDescriptor?.get(index); + } + async getElementIndex(parameterIndex) { + return await this.entityTable.getNumber(parameterIndex, "index:Vim.Element:Element"); + } + async getAllElementIndex() { + return await this.entityTable.getNumberArray("index:Vim.Element:Element"); + } + async getElement(parameterIndex) { + const index = await this.getElementIndex(parameterIndex); + if (index === undefined) { + return undefined; + } + return await this.document.element?.get(index); + } +} +exports.ParameterTable = ParameterTable; +class Element { + static async createFromTable(table, index) { + let result = new Element(); + result.index = index; + await Promise.all([ + table.getId(index).then(v => result.id = v), + table.getType(index).then(v => result.type = v), + table.getName(index).then(v => result.name = v), + table.getUniqueId(index).then(v => result.uniqueId = v), + table.getLocation_X(index).then(v => result.location_X = v), + table.getLocation_Y(index).then(v => result.location_Y = v), + table.getLocation_Z(index).then(v => result.location_Z = v), + table.getFamilyName(index).then(v => result.familyName = v), + table.getIsPinned(index).then(v => result.isPinned = v), + table.getLevelIndex(index).then(v => result.levelIndex = v), + table.getPhaseCreatedIndex(index).then(v => result.phaseCreatedIndex = v), + table.getPhaseDemolishedIndex(index).then(v => result.phaseDemolishedIndex = v), + table.getCategoryIndex(index).then(v => result.categoryIndex = v), + table.getWorksetIndex(index).then(v => result.worksetIndex = v), + table.getDesignOptionIndex(index).then(v => result.designOptionIndex = v), + table.getOwnerViewIndex(index).then(v => result.ownerViewIndex = v), + table.getGroupIndex(index).then(v => result.groupIndex = v), + table.getAssemblyInstanceIndex(index).then(v => result.assemblyInstanceIndex = v), + table.getBimDocumentIndex(index).then(v => result.bimDocumentIndex = v), + table.getRoomIndex(index).then(v => result.roomIndex = v), + ]); + return result; + } +} +exports.Element = Element; +class ElementTable { + static async createFromDocument(document) { + const entity = await document.entities.getBfast("Vim.Element"); + if (!entity) { + return undefined; + } + let table = new ElementTable(); + table.document = document; + table.entityTable = new entityTable_1.EntityTable(entity, document.strings); + return table; + } + getCount() { + return this.entityTable.getCount(); + } + async get(elementIndex) { + return await Element.createFromTable(this, elementIndex); + } + async getAll() { + const localTable = await this.entityTable.getLocal(); + let id; + let type; + let name; + let uniqueId; + let location_X; + let location_Y; + let location_Z; + let familyName; + let isPinned; + let levelIndex; + let phaseCreatedIndex; + let phaseDemolishedIndex; + let categoryIndex; + let worksetIndex; + let designOptionIndex; + let ownerViewIndex; + let groupIndex; + let assemblyInstanceIndex; + let bimDocumentIndex; + let roomIndex; + await Promise.all([ + (async () => { id = (await localTable.getBigIntArray("long:Id")) ?? (await localTable.getBigIntArray("int:Id")); })(), + (async () => { type = (await localTable.getStringArray("string:Type")); })(), + (async () => { name = (await localTable.getStringArray("string:Name")); })(), + (async () => { uniqueId = (await localTable.getStringArray("string:UniqueId")); })(), + (async () => { location_X = (await localTable.getNumberArray("float:Location.X")); })(), + (async () => { location_Y = (await localTable.getNumberArray("float:Location.Y")); })(), + (async () => { location_Z = (await localTable.getNumberArray("float:Location.Z")); })(), + (async () => { familyName = (await localTable.getStringArray("string:FamilyName")); })(), + (async () => { isPinned = (await localTable.getBooleanArray("byte:IsPinned")); })(), + (async () => { levelIndex = (await localTable.getNumberArray("index:Vim.Level:Level")); })(), + (async () => { phaseCreatedIndex = (await localTable.getNumberArray("index:Vim.Phase:PhaseCreated")); })(), + (async () => { phaseDemolishedIndex = (await localTable.getNumberArray("index:Vim.Phase:PhaseDemolished")); })(), + (async () => { categoryIndex = (await localTable.getNumberArray("index:Vim.Category:Category")); })(), + (async () => { worksetIndex = (await localTable.getNumberArray("index:Vim.Workset:Workset")); })(), + (async () => { designOptionIndex = (await localTable.getNumberArray("index:Vim.DesignOption:DesignOption")); })(), + (async () => { ownerViewIndex = (await localTable.getNumberArray("index:Vim.View:OwnerView")); })(), + (async () => { groupIndex = (await localTable.getNumberArray("index:Vim.Group:Group")); })(), + (async () => { assemblyInstanceIndex = (await localTable.getNumberArray("index:Vim.AssemblyInstance:AssemblyInstance")); })(), + (async () => { bimDocumentIndex = (await localTable.getNumberArray("index:Vim.BimDocument:BimDocument")); })(), + (async () => { roomIndex = (await localTable.getNumberArray("index:Vim.Room:Room")); })(), + ]); + let element = []; + for (let i = 0; i < id.length; i++) { + element.push({ + index: i, + id: id ? id[i] : undefined, + type: type ? type[i] : undefined, + name: name ? name[i] : undefined, + uniqueId: uniqueId ? uniqueId[i] : undefined, + location_X: location_X ? location_X[i] : undefined, + location_Y: location_Y ? location_Y[i] : undefined, + location_Z: location_Z ? location_Z[i] : undefined, + familyName: familyName ? familyName[i] : undefined, + isPinned: isPinned ? isPinned[i] : undefined, + levelIndex: levelIndex ? levelIndex[i] : undefined, + phaseCreatedIndex: phaseCreatedIndex ? phaseCreatedIndex[i] : undefined, + phaseDemolishedIndex: phaseDemolishedIndex ? phaseDemolishedIndex[i] : undefined, + categoryIndex: categoryIndex ? categoryIndex[i] : undefined, + worksetIndex: worksetIndex ? worksetIndex[i] : undefined, + designOptionIndex: designOptionIndex ? designOptionIndex[i] : undefined, + ownerViewIndex: ownerViewIndex ? ownerViewIndex[i] : undefined, + groupIndex: groupIndex ? groupIndex[i] : undefined, + assemblyInstanceIndex: assemblyInstanceIndex ? assemblyInstanceIndex[i] : undefined, + bimDocumentIndex: bimDocumentIndex ? bimDocumentIndex[i] : undefined, + roomIndex: roomIndex ? roomIndex[i] : undefined + }); + } + return element; + } + async getId(elementIndex) { + return (await this.entityTable.getBigInt(elementIndex, "long:Id")) ?? (await this.entityTable.getBigInt(elementIndex, "int:Id")); + } + async getAllId() { + return (await this.entityTable.getBigIntArray("long:Id")) ?? (await this.entityTable.getBigIntArray("int:Id")); + } + async getType(elementIndex) { + return (await this.entityTable.getString(elementIndex, "string:Type")); + } + async getAllType() { + return (await this.entityTable.getStringArray("string:Type")); + } + async getName(elementIndex) { + return (await this.entityTable.getString(elementIndex, "string:Name")); + } + async getAllName() { + return (await this.entityTable.getStringArray("string:Name")); + } + async getUniqueId(elementIndex) { + return (await this.entityTable.getString(elementIndex, "string:UniqueId")); + } + async getAllUniqueId() { + return (await this.entityTable.getStringArray("string:UniqueId")); + } + async getLocation_X(elementIndex) { + return (await this.entityTable.getNumber(elementIndex, "float:Location.X")); + } + async getAllLocation_X() { + return (await this.entityTable.getNumberArray("float:Location.X")); + } + async getLocation_Y(elementIndex) { + return (await this.entityTable.getNumber(elementIndex, "float:Location.Y")); + } + async getAllLocation_Y() { + return (await this.entityTable.getNumberArray("float:Location.Y")); + } + async getLocation_Z(elementIndex) { + return (await this.entityTable.getNumber(elementIndex, "float:Location.Z")); + } + async getAllLocation_Z() { + return (await this.entityTable.getNumberArray("float:Location.Z")); + } + async getFamilyName(elementIndex) { + return (await this.entityTable.getString(elementIndex, "string:FamilyName")); + } + async getAllFamilyName() { + return (await this.entityTable.getStringArray("string:FamilyName")); + } + async getIsPinned(elementIndex) { + return (await this.entityTable.getBoolean(elementIndex, "byte:IsPinned")); + } + async getAllIsPinned() { + return (await this.entityTable.getBooleanArray("byte:IsPinned")); + } + async getLevelIndex(elementIndex) { + return await this.entityTable.getNumber(elementIndex, "index:Vim.Level:Level"); + } + async getAllLevelIndex() { + return await this.entityTable.getNumberArray("index:Vim.Level:Level"); + } + async getLevel(elementIndex) { + const index = await this.getLevelIndex(elementIndex); + if (index === undefined) { + return undefined; + } + return await this.document.level?.get(index); + } + async getPhaseCreatedIndex(elementIndex) { + return await this.entityTable.getNumber(elementIndex, "index:Vim.Phase:PhaseCreated"); + } + async getAllPhaseCreatedIndex() { + return await this.entityTable.getNumberArray("index:Vim.Phase:PhaseCreated"); + } + async getPhaseCreated(elementIndex) { + const index = await this.getPhaseCreatedIndex(elementIndex); + if (index === undefined) { + return undefined; + } + return await this.document.phase?.get(index); + } + async getPhaseDemolishedIndex(elementIndex) { + return await this.entityTable.getNumber(elementIndex, "index:Vim.Phase:PhaseDemolished"); + } + async getAllPhaseDemolishedIndex() { + return await this.entityTable.getNumberArray("index:Vim.Phase:PhaseDemolished"); + } + async getPhaseDemolished(elementIndex) { + const index = await this.getPhaseDemolishedIndex(elementIndex); + if (index === undefined) { + return undefined; + } + return await this.document.phase?.get(index); + } + async getCategoryIndex(elementIndex) { + return await this.entityTable.getNumber(elementIndex, "index:Vim.Category:Category"); + } + async getAllCategoryIndex() { + return await this.entityTable.getNumberArray("index:Vim.Category:Category"); + } + async getCategory(elementIndex) { + const index = await this.getCategoryIndex(elementIndex); + if (index === undefined) { + return undefined; + } + return await this.document.category?.get(index); + } + async getWorksetIndex(elementIndex) { + return await this.entityTable.getNumber(elementIndex, "index:Vim.Workset:Workset"); + } + async getAllWorksetIndex() { + return await this.entityTable.getNumberArray("index:Vim.Workset:Workset"); + } + async getWorkset(elementIndex) { + const index = await this.getWorksetIndex(elementIndex); + if (index === undefined) { + return undefined; + } + return await this.document.workset?.get(index); + } + async getDesignOptionIndex(elementIndex) { + return await this.entityTable.getNumber(elementIndex, "index:Vim.DesignOption:DesignOption"); + } + async getAllDesignOptionIndex() { + return await this.entityTable.getNumberArray("index:Vim.DesignOption:DesignOption"); + } + async getDesignOption(elementIndex) { + const index = await this.getDesignOptionIndex(elementIndex); + if (index === undefined) { + return undefined; + } + return await this.document.designOption?.get(index); + } + async getOwnerViewIndex(elementIndex) { + return await this.entityTable.getNumber(elementIndex, "index:Vim.View:OwnerView"); + } + async getAllOwnerViewIndex() { + return await this.entityTable.getNumberArray("index:Vim.View:OwnerView"); + } + async getOwnerView(elementIndex) { + const index = await this.getOwnerViewIndex(elementIndex); + if (index === undefined) { + return undefined; + } + return await this.document.view?.get(index); + } + async getGroupIndex(elementIndex) { + return await this.entityTable.getNumber(elementIndex, "index:Vim.Group:Group"); + } + async getAllGroupIndex() { + return await this.entityTable.getNumberArray("index:Vim.Group:Group"); + } + async getGroup(elementIndex) { + const index = await this.getGroupIndex(elementIndex); + if (index === undefined) { + return undefined; + } + return await this.document.group?.get(index); + } + async getAssemblyInstanceIndex(elementIndex) { + return await this.entityTable.getNumber(elementIndex, "index:Vim.AssemblyInstance:AssemblyInstance"); + } + async getAllAssemblyInstanceIndex() { + return await this.entityTable.getNumberArray("index:Vim.AssemblyInstance:AssemblyInstance"); + } + async getAssemblyInstance(elementIndex) { + const index = await this.getAssemblyInstanceIndex(elementIndex); + if (index === undefined) { + return undefined; + } + return await this.document.assemblyInstance?.get(index); + } + async getBimDocumentIndex(elementIndex) { + return await this.entityTable.getNumber(elementIndex, "index:Vim.BimDocument:BimDocument"); + } + async getAllBimDocumentIndex() { + return await this.entityTable.getNumberArray("index:Vim.BimDocument:BimDocument"); + } + async getBimDocument(elementIndex) { + const index = await this.getBimDocumentIndex(elementIndex); + if (index === undefined) { + return undefined; + } + return await this.document.bimDocument?.get(index); + } + async getRoomIndex(elementIndex) { + return await this.entityTable.getNumber(elementIndex, "index:Vim.Room:Room"); + } + async getAllRoomIndex() { + return await this.entityTable.getNumberArray("index:Vim.Room:Room"); + } + async getRoom(elementIndex) { + const index = await this.getRoomIndex(elementIndex); + if (index === undefined) { + return undefined; + } + return await this.document.room?.get(index); + } +} +exports.ElementTable = ElementTable; +class Workset { + static async createFromTable(table, index) { + let result = new Workset(); + result.index = index; + await Promise.all([ + table.getId(index).then(v => result.id = v), + table.getName(index).then(v => result.name = v), + table.getKind(index).then(v => result.kind = v), + table.getIsOpen(index).then(v => result.isOpen = v), + table.getIsEditable(index).then(v => result.isEditable = v), + table.getOwner(index).then(v => result.owner = v), + table.getUniqueId(index).then(v => result.uniqueId = v), + table.getBimDocumentIndex(index).then(v => result.bimDocumentIndex = v), + ]); + return result; + } +} +exports.Workset = Workset; +class WorksetTable { + static async createFromDocument(document) { + const entity = await document.entities.getBfast("Vim.Workset"); + if (!entity) { + return undefined; + } + let table = new WorksetTable(); + table.document = document; + table.entityTable = new entityTable_1.EntityTable(entity, document.strings); + return table; + } + getCount() { + return this.entityTable.getCount(); + } + async get(worksetIndex) { + return await Workset.createFromTable(this, worksetIndex); + } + async getAll() { + const localTable = await this.entityTable.getLocal(); + let id; + let name; + let kind; + let isOpen; + let isEditable; + let owner; + let uniqueId; + let bimDocumentIndex; + await Promise.all([ + (async () => { id = (await localTable.getNumberArray("int:Id")); })(), + (async () => { name = (await localTable.getStringArray("string:Name")); })(), + (async () => { kind = (await localTable.getStringArray("string:Kind")); })(), + (async () => { isOpen = (await localTable.getBooleanArray("byte:IsOpen")); })(), + (async () => { isEditable = (await localTable.getBooleanArray("byte:IsEditable")); })(), + (async () => { owner = (await localTable.getStringArray("string:Owner")); })(), + (async () => { uniqueId = (await localTable.getStringArray("string:UniqueId")); })(), + (async () => { bimDocumentIndex = (await localTable.getNumberArray("index:Vim.BimDocument:BimDocument")); })(), + ]); + let workset = []; + for (let i = 0; i < id.length; i++) { + workset.push({ + index: i, + id: id ? id[i] : undefined, + name: name ? name[i] : undefined, + kind: kind ? kind[i] : undefined, + isOpen: isOpen ? isOpen[i] : undefined, + isEditable: isEditable ? isEditable[i] : undefined, + owner: owner ? owner[i] : undefined, + uniqueId: uniqueId ? uniqueId[i] : undefined, + bimDocumentIndex: bimDocumentIndex ? bimDocumentIndex[i] : undefined + }); + } + return workset; + } + async getId(worksetIndex) { + return (await this.entityTable.getNumber(worksetIndex, "int:Id")); + } + async getAllId() { + return (await this.entityTable.getNumberArray("int:Id")); + } + async getName(worksetIndex) { + return (await this.entityTable.getString(worksetIndex, "string:Name")); + } + async getAllName() { + return (await this.entityTable.getStringArray("string:Name")); + } + async getKind(worksetIndex) { + return (await this.entityTable.getString(worksetIndex, "string:Kind")); + } + async getAllKind() { + return (await this.entityTable.getStringArray("string:Kind")); + } + async getIsOpen(worksetIndex) { + return (await this.entityTable.getBoolean(worksetIndex, "byte:IsOpen")); + } + async getAllIsOpen() { + return (await this.entityTable.getBooleanArray("byte:IsOpen")); + } + async getIsEditable(worksetIndex) { + return (await this.entityTable.getBoolean(worksetIndex, "byte:IsEditable")); + } + async getAllIsEditable() { + return (await this.entityTable.getBooleanArray("byte:IsEditable")); + } + async getOwner(worksetIndex) { + return (await this.entityTable.getString(worksetIndex, "string:Owner")); + } + async getAllOwner() { + return (await this.entityTable.getStringArray("string:Owner")); + } + async getUniqueId(worksetIndex) { + return (await this.entityTable.getString(worksetIndex, "string:UniqueId")); + } + async getAllUniqueId() { + return (await this.entityTable.getStringArray("string:UniqueId")); + } + async getBimDocumentIndex(worksetIndex) { + return await this.entityTable.getNumber(worksetIndex, "index:Vim.BimDocument:BimDocument"); + } + async getAllBimDocumentIndex() { + return await this.entityTable.getNumberArray("index:Vim.BimDocument:BimDocument"); + } + async getBimDocument(worksetIndex) { + const index = await this.getBimDocumentIndex(worksetIndex); + if (index === undefined) { + return undefined; + } + return await this.document.bimDocument?.get(index); + } +} +exports.WorksetTable = WorksetTable; +class AssemblyInstance { + static async createFromTable(table, index) { + let result = new AssemblyInstance(); + result.index = index; + await Promise.all([ + table.getAssemblyTypeName(index).then(v => result.assemblyTypeName = v), + table.getPosition_X(index).then(v => result.position_X = v), + table.getPosition_Y(index).then(v => result.position_Y = v), + table.getPosition_Z(index).then(v => result.position_Z = v), + table.getElementIndex(index).then(v => result.elementIndex = v), + ]); + return result; + } +} +exports.AssemblyInstance = AssemblyInstance; +class AssemblyInstanceTable { + static async createFromDocument(document) { + const entity = await document.entities.getBfast("Vim.AssemblyInstance"); + if (!entity) { + return undefined; + } + let table = new AssemblyInstanceTable(); + table.document = document; + table.entityTable = new entityTable_1.EntityTable(entity, document.strings); + return table; + } + getCount() { + return this.entityTable.getCount(); + } + async get(assemblyInstanceIndex) { + return await AssemblyInstance.createFromTable(this, assemblyInstanceIndex); + } + async getAll() { + const localTable = await this.entityTable.getLocal(); + let assemblyTypeName; + let position_X; + let position_Y; + let position_Z; + let elementIndex; + await Promise.all([ + (async () => { assemblyTypeName = (await localTable.getStringArray("string:AssemblyTypeName")); })(), + (async () => { position_X = (await localTable.getNumberArray("float:Position.X")); })(), + (async () => { position_Y = (await localTable.getNumberArray("float:Position.Y")); })(), + (async () => { position_Z = (await localTable.getNumberArray("float:Position.Z")); })(), + (async () => { elementIndex = (await localTable.getNumberArray("index:Vim.Element:Element")); })(), + ]); + let assemblyInstance = []; + for (let i = 0; i < assemblyTypeName.length; i++) { + assemblyInstance.push({ + index: i, + assemblyTypeName: assemblyTypeName ? assemblyTypeName[i] : undefined, + position_X: position_X ? position_X[i] : undefined, + position_Y: position_Y ? position_Y[i] : undefined, + position_Z: position_Z ? position_Z[i] : undefined, + elementIndex: elementIndex ? elementIndex[i] : undefined + }); + } + return assemblyInstance; + } + async getAssemblyTypeName(assemblyInstanceIndex) { + return (await this.entityTable.getString(assemblyInstanceIndex, "string:AssemblyTypeName")); + } + async getAllAssemblyTypeName() { + return (await this.entityTable.getStringArray("string:AssemblyTypeName")); + } + async getPosition_X(assemblyInstanceIndex) { + return (await this.entityTable.getNumber(assemblyInstanceIndex, "float:Position.X")); + } + async getAllPosition_X() { + return (await this.entityTable.getNumberArray("float:Position.X")); + } + async getPosition_Y(assemblyInstanceIndex) { + return (await this.entityTable.getNumber(assemblyInstanceIndex, "float:Position.Y")); + } + async getAllPosition_Y() { + return (await this.entityTable.getNumberArray("float:Position.Y")); + } + async getPosition_Z(assemblyInstanceIndex) { + return (await this.entityTable.getNumber(assemblyInstanceIndex, "float:Position.Z")); + } + async getAllPosition_Z() { + return (await this.entityTable.getNumberArray("float:Position.Z")); + } + async getElementIndex(assemblyInstanceIndex) { + return await this.entityTable.getNumber(assemblyInstanceIndex, "index:Vim.Element:Element"); + } + async getAllElementIndex() { + return await this.entityTable.getNumberArray("index:Vim.Element:Element"); + } + async getElement(assemblyInstanceIndex) { + const index = await this.getElementIndex(assemblyInstanceIndex); + if (index === undefined) { + return undefined; + } + return await this.document.element?.get(index); + } +} +exports.AssemblyInstanceTable = AssemblyInstanceTable; +class Group { + static async createFromTable(table, index) { + let result = new Group(); + result.index = index; + await Promise.all([ + table.getGroupType(index).then(v => result.groupType = v), + table.getPosition_X(index).then(v => result.position_X = v), + table.getPosition_Y(index).then(v => result.position_Y = v), + table.getPosition_Z(index).then(v => result.position_Z = v), + table.getElementIndex(index).then(v => result.elementIndex = v), + ]); + return result; + } +} +exports.Group = Group; +class GroupTable { + static async createFromDocument(document) { + const entity = await document.entities.getBfast("Vim.Group"); + if (!entity) { + return undefined; + } + let table = new GroupTable(); + table.document = document; + table.entityTable = new entityTable_1.EntityTable(entity, document.strings); + return table; + } + getCount() { + return this.entityTable.getCount(); + } + async get(groupIndex) { + return await Group.createFromTable(this, groupIndex); + } + async getAll() { + const localTable = await this.entityTable.getLocal(); + let groupType; + let position_X; + let position_Y; + let position_Z; + let elementIndex; + await Promise.all([ + (async () => { groupType = (await localTable.getStringArray("string:GroupType")); })(), + (async () => { position_X = (await localTable.getNumberArray("float:Position.X")); })(), + (async () => { position_Y = (await localTable.getNumberArray("float:Position.Y")); })(), + (async () => { position_Z = (await localTable.getNumberArray("float:Position.Z")); })(), + (async () => { elementIndex = (await localTable.getNumberArray("index:Vim.Element:Element")); })(), + ]); + let group = []; + for (let i = 0; i < groupType.length; i++) { + group.push({ + index: i, + groupType: groupType ? groupType[i] : undefined, + position_X: position_X ? position_X[i] : undefined, + position_Y: position_Y ? position_Y[i] : undefined, + position_Z: position_Z ? position_Z[i] : undefined, + elementIndex: elementIndex ? elementIndex[i] : undefined + }); + } + return group; + } + async getGroupType(groupIndex) { + return (await this.entityTable.getString(groupIndex, "string:GroupType")); + } + async getAllGroupType() { + return (await this.entityTable.getStringArray("string:GroupType")); + } + async getPosition_X(groupIndex) { + return (await this.entityTable.getNumber(groupIndex, "float:Position.X")); + } + async getAllPosition_X() { + return (await this.entityTable.getNumberArray("float:Position.X")); + } + async getPosition_Y(groupIndex) { + return (await this.entityTable.getNumber(groupIndex, "float:Position.Y")); + } + async getAllPosition_Y() { + return (await this.entityTable.getNumberArray("float:Position.Y")); + } + async getPosition_Z(groupIndex) { + return (await this.entityTable.getNumber(groupIndex, "float:Position.Z")); + } + async getAllPosition_Z() { + return (await this.entityTable.getNumberArray("float:Position.Z")); + } + async getElementIndex(groupIndex) { + return await this.entityTable.getNumber(groupIndex, "index:Vim.Element:Element"); + } + async getAllElementIndex() { + return await this.entityTable.getNumberArray("index:Vim.Element:Element"); + } + async getElement(groupIndex) { + const index = await this.getElementIndex(groupIndex); + if (index === undefined) { + return undefined; + } + return await this.document.element?.get(index); + } +} +exports.GroupTable = GroupTable; +class DesignOption { + static async createFromTable(table, index) { + let result = new DesignOption(); + result.index = index; + await Promise.all([ + table.getIsPrimary(index).then(v => result.isPrimary = v), + table.getElementIndex(index).then(v => result.elementIndex = v), + ]); + return result; + } +} +exports.DesignOption = DesignOption; +class DesignOptionTable { + static async createFromDocument(document) { + const entity = await document.entities.getBfast("Vim.DesignOption"); + if (!entity) { + return undefined; + } + let table = new DesignOptionTable(); + table.document = document; + table.entityTable = new entityTable_1.EntityTable(entity, document.strings); + return table; + } + getCount() { + return this.entityTable.getCount(); + } + async get(designOptionIndex) { + return await DesignOption.createFromTable(this, designOptionIndex); + } + async getAll() { + const localTable = await this.entityTable.getLocal(); + let isPrimary; + let elementIndex; + await Promise.all([ + (async () => { isPrimary = (await localTable.getBooleanArray("byte:IsPrimary")); })(), + (async () => { elementIndex = (await localTable.getNumberArray("index:Vim.Element:Element")); })(), + ]); + let designOption = []; + for (let i = 0; i < isPrimary.length; i++) { + designOption.push({ + index: i, + isPrimary: isPrimary ? isPrimary[i] : undefined, + elementIndex: elementIndex ? elementIndex[i] : undefined + }); + } + return designOption; + } + async getIsPrimary(designOptionIndex) { + return (await this.entityTable.getBoolean(designOptionIndex, "byte:IsPrimary")); + } + async getAllIsPrimary() { + return (await this.entityTable.getBooleanArray("byte:IsPrimary")); + } + async getElementIndex(designOptionIndex) { + return await this.entityTable.getNumber(designOptionIndex, "index:Vim.Element:Element"); + } + async getAllElementIndex() { + return await this.entityTable.getNumberArray("index:Vim.Element:Element"); + } + async getElement(designOptionIndex) { + const index = await this.getElementIndex(designOptionIndex); + if (index === undefined) { + return undefined; + } + return await this.document.element?.get(index); + } +} +exports.DesignOptionTable = DesignOptionTable; +class Level { + static async createFromTable(table, index) { + let result = new Level(); + result.index = index; + await Promise.all([ + table.getElevation(index).then(v => result.elevation = v), + table.getFamilyTypeIndex(index).then(v => result.familyTypeIndex = v), + table.getElementIndex(index).then(v => result.elementIndex = v), + ]); + return result; + } +} +exports.Level = Level; +class LevelTable { + static async createFromDocument(document) { + const entity = await document.entities.getBfast("Vim.Level"); + if (!entity) { + return undefined; + } + let table = new LevelTable(); + table.document = document; + table.entityTable = new entityTable_1.EntityTable(entity, document.strings); + return table; + } + getCount() { + return this.entityTable.getCount(); + } + async get(levelIndex) { + return await Level.createFromTable(this, levelIndex); + } + async getAll() { + const localTable = await this.entityTable.getLocal(); + let elevation; + let familyTypeIndex; + let elementIndex; + await Promise.all([ + (async () => { elevation = (await localTable.getNumberArray("double:Elevation")); })(), + (async () => { familyTypeIndex = (await localTable.getNumberArray("index:Vim.FamilyType:FamilyType")); })(), + (async () => { elementIndex = (await localTable.getNumberArray("index:Vim.Element:Element")); })(), + ]); + let level = []; + for (let i = 0; i < elevation.length; i++) { + level.push({ + index: i, + elevation: elevation ? elevation[i] : undefined, + familyTypeIndex: familyTypeIndex ? familyTypeIndex[i] : undefined, + elementIndex: elementIndex ? elementIndex[i] : undefined + }); + } + return level; + } + async getElevation(levelIndex) { + return (await this.entityTable.getNumber(levelIndex, "double:Elevation")); + } + async getAllElevation() { + return (await this.entityTable.getNumberArray("double:Elevation")); + } + async getFamilyTypeIndex(levelIndex) { + return await this.entityTable.getNumber(levelIndex, "index:Vim.FamilyType:FamilyType"); + } + async getAllFamilyTypeIndex() { + return await this.entityTable.getNumberArray("index:Vim.FamilyType:FamilyType"); + } + async getFamilyType(levelIndex) { + const index = await this.getFamilyTypeIndex(levelIndex); + if (index === undefined) { + return undefined; + } + return await this.document.familyType?.get(index); + } + async getElementIndex(levelIndex) { + return await this.entityTable.getNumber(levelIndex, "index:Vim.Element:Element"); + } + async getAllElementIndex() { + return await this.entityTable.getNumberArray("index:Vim.Element:Element"); + } + async getElement(levelIndex) { + const index = await this.getElementIndex(levelIndex); + if (index === undefined) { + return undefined; + } + return await this.document.element?.get(index); + } +} +exports.LevelTable = LevelTable; +class Phase { + static async createFromTable(table, index) { + let result = new Phase(); + result.index = index; + await Promise.all([ + table.getElementIndex(index).then(v => result.elementIndex = v), + ]); + return result; + } +} +exports.Phase = Phase; +class PhaseTable { + static async createFromDocument(document) { + const entity = await document.entities.getBfast("Vim.Phase"); + if (!entity) { + return undefined; + } + let table = new PhaseTable(); + table.document = document; + table.entityTable = new entityTable_1.EntityTable(entity, document.strings); + return table; + } + getCount() { + return this.entityTable.getCount(); + } + async get(phaseIndex) { + return await Phase.createFromTable(this, phaseIndex); + } + async getAll() { + const localTable = await this.entityTable.getLocal(); + let elementIndex; + await Promise.all([ + (async () => { elementIndex = (await localTable.getNumberArray("index:Vim.Element:Element")); })(), + ]); + let phase = []; + for (let i = 0; i < elementIndex.length; i++) { + phase.push({ + index: i, + elementIndex: elementIndex ? elementIndex[i] : undefined + }); + } + return phase; + } + async getElementIndex(phaseIndex) { + return await this.entityTable.getNumber(phaseIndex, "index:Vim.Element:Element"); + } + async getAllElementIndex() { + return await this.entityTable.getNumberArray("index:Vim.Element:Element"); + } + async getElement(phaseIndex) { + const index = await this.getElementIndex(phaseIndex); + if (index === undefined) { + return undefined; + } + return await this.document.element?.get(index); + } +} +exports.PhaseTable = PhaseTable; +class Room { + static async createFromTable(table, index) { + let result = new Room(); + result.index = index; + await Promise.all([ + table.getBaseOffset(index).then(v => result.baseOffset = v), + table.getLimitOffset(index).then(v => result.limitOffset = v), + table.getUnboundedHeight(index).then(v => result.unboundedHeight = v), + table.getVolume(index).then(v => result.volume = v), + table.getPerimeter(index).then(v => result.perimeter = v), + table.getArea(index).then(v => result.area = v), + table.getNumber(index).then(v => result.number = v), + table.getUpperLimitIndex(index).then(v => result.upperLimitIndex = v), + table.getElementIndex(index).then(v => result.elementIndex = v), + ]); + return result; + } +} +exports.Room = Room; +class RoomTable { + static async createFromDocument(document) { + const entity = await document.entities.getBfast("Vim.Room"); + if (!entity) { + return undefined; + } + let table = new RoomTable(); + table.document = document; + table.entityTable = new entityTable_1.EntityTable(entity, document.strings); + return table; + } + getCount() { + return this.entityTable.getCount(); + } + async get(roomIndex) { + return await Room.createFromTable(this, roomIndex); + } + async getAll() { + const localTable = await this.entityTable.getLocal(); + let baseOffset; + let limitOffset; + let unboundedHeight; + let volume; + let perimeter; + let area; + let number; + let upperLimitIndex; + let elementIndex; + await Promise.all([ + (async () => { baseOffset = (await localTable.getNumberArray("double:BaseOffset")); })(), + (async () => { limitOffset = (await localTable.getNumberArray("double:LimitOffset")); })(), + (async () => { unboundedHeight = (await localTable.getNumberArray("double:UnboundedHeight")); })(), + (async () => { volume = (await localTable.getNumberArray("double:Volume")); })(), + (async () => { perimeter = (await localTable.getNumberArray("double:Perimeter")); })(), + (async () => { area = (await localTable.getNumberArray("double:Area")); })(), + (async () => { number = (await localTable.getStringArray("string:Number")); })(), + (async () => { upperLimitIndex = (await localTable.getNumberArray("index:Vim.Level:UpperLimit")); })(), + (async () => { elementIndex = (await localTable.getNumberArray("index:Vim.Element:Element")); })(), + ]); + let room = []; + for (let i = 0; i < baseOffset.length; i++) { + room.push({ + index: i, + baseOffset: baseOffset ? baseOffset[i] : undefined, + limitOffset: limitOffset ? limitOffset[i] : undefined, + unboundedHeight: unboundedHeight ? unboundedHeight[i] : undefined, + volume: volume ? volume[i] : undefined, + perimeter: perimeter ? perimeter[i] : undefined, + area: area ? area[i] : undefined, + number: number ? number[i] : undefined, + upperLimitIndex: upperLimitIndex ? upperLimitIndex[i] : undefined, + elementIndex: elementIndex ? elementIndex[i] : undefined + }); + } + return room; + } + async getBaseOffset(roomIndex) { + return (await this.entityTable.getNumber(roomIndex, "double:BaseOffset")); + } + async getAllBaseOffset() { + return (await this.entityTable.getNumberArray("double:BaseOffset")); + } + async getLimitOffset(roomIndex) { + return (await this.entityTable.getNumber(roomIndex, "double:LimitOffset")); + } + async getAllLimitOffset() { + return (await this.entityTable.getNumberArray("double:LimitOffset")); + } + async getUnboundedHeight(roomIndex) { + return (await this.entityTable.getNumber(roomIndex, "double:UnboundedHeight")); + } + async getAllUnboundedHeight() { + return (await this.entityTable.getNumberArray("double:UnboundedHeight")); + } + async getVolume(roomIndex) { + return (await this.entityTable.getNumber(roomIndex, "double:Volume")); + } + async getAllVolume() { + return (await this.entityTable.getNumberArray("double:Volume")); + } + async getPerimeter(roomIndex) { + return (await this.entityTable.getNumber(roomIndex, "double:Perimeter")); + } + async getAllPerimeter() { + return (await this.entityTable.getNumberArray("double:Perimeter")); + } + async getArea(roomIndex) { + return (await this.entityTable.getNumber(roomIndex, "double:Area")); + } + async getAllArea() { + return (await this.entityTable.getNumberArray("double:Area")); + } + async getNumber(roomIndex) { + return (await this.entityTable.getString(roomIndex, "string:Number")); + } + async getAllNumber() { + return (await this.entityTable.getStringArray("string:Number")); + } + async getUpperLimitIndex(roomIndex) { + return await this.entityTable.getNumber(roomIndex, "index:Vim.Level:UpperLimit"); + } + async getAllUpperLimitIndex() { + return await this.entityTable.getNumberArray("index:Vim.Level:UpperLimit"); + } + async getUpperLimit(roomIndex) { + const index = await this.getUpperLimitIndex(roomIndex); + if (index === undefined) { + return undefined; + } + return await this.document.level?.get(index); + } + async getElementIndex(roomIndex) { + return await this.entityTable.getNumber(roomIndex, "index:Vim.Element:Element"); + } + async getAllElementIndex() { + return await this.entityTable.getNumberArray("index:Vim.Element:Element"); + } + async getElement(roomIndex) { + const index = await this.getElementIndex(roomIndex); + if (index === undefined) { + return undefined; + } + return await this.document.element?.get(index); + } +} +exports.RoomTable = RoomTable; +class BimDocument { + static async createFromTable(table, index) { + let result = new BimDocument(); + result.index = index; + await Promise.all([ + table.getTitle(index).then(v => result.title = v), + table.getIsMetric(index).then(v => result.isMetric = v), + table.getGuid(index).then(v => result.guid = v), + table.getNumSaves(index).then(v => result.numSaves = v), + table.getIsLinked(index).then(v => result.isLinked = v), + table.getIsDetached(index).then(v => result.isDetached = v), + table.getIsWorkshared(index).then(v => result.isWorkshared = v), + table.getPathName(index).then(v => result.pathName = v), + table.getLatitude(index).then(v => result.latitude = v), + table.getLongitude(index).then(v => result.longitude = v), + table.getTimeZone(index).then(v => result.timeZone = v), + table.getPlaceName(index).then(v => result.placeName = v), + table.getWeatherStationName(index).then(v => result.weatherStationName = v), + table.getElevation(index).then(v => result.elevation = v), + table.getProjectLocation(index).then(v => result.projectLocation = v), + table.getIssueDate(index).then(v => result.issueDate = v), + table.getStatus(index).then(v => result.status = v), + table.getClientName(index).then(v => result.clientName = v), + table.getAddress(index).then(v => result.address = v), + table.getName(index).then(v => result.name = v), + table.getNumber(index).then(v => result.number = v), + table.getAuthor(index).then(v => result.author = v), + table.getBuildingName(index).then(v => result.buildingName = v), + table.getOrganizationName(index).then(v => result.organizationName = v), + table.getOrganizationDescription(index).then(v => result.organizationDescription = v), + table.getProduct(index).then(v => result.product = v), + table.getVersion(index).then(v => result.version = v), + table.getUser(index).then(v => result.user = v), + table.getActiveViewIndex(index).then(v => result.activeViewIndex = v), + table.getOwnerFamilyIndex(index).then(v => result.ownerFamilyIndex = v), + table.getParentIndex(index).then(v => result.parentIndex = v), + table.getElementIndex(index).then(v => result.elementIndex = v), + ]); + return result; + } +} +exports.BimDocument = BimDocument; +class BimDocumentTable { + static async createFromDocument(document) { + const entity = await document.entities.getBfast("Vim.BimDocument"); + if (!entity) { + return undefined; + } + let table = new BimDocumentTable(); + table.document = document; + table.entityTable = new entityTable_1.EntityTable(entity, document.strings); + return table; + } + getCount() { + return this.entityTable.getCount(); + } + async get(bimDocumentIndex) { + return await BimDocument.createFromTable(this, bimDocumentIndex); + } + async getAll() { + const localTable = await this.entityTable.getLocal(); + let title; + let isMetric; + let guid; + let numSaves; + let isLinked; + let isDetached; + let isWorkshared; + let pathName; + let latitude; + let longitude; + let timeZone; + let placeName; + let weatherStationName; + let elevation; + let projectLocation; + let issueDate; + let status; + let clientName; + let address; + let name; + let number; + let author; + let buildingName; + let organizationName; + let organizationDescription; + let product; + let version; + let user; + let activeViewIndex; + let ownerFamilyIndex; + let parentIndex; + let elementIndex; + await Promise.all([ + (async () => { title = (await localTable.getStringArray("string:Title")); })(), + (async () => { isMetric = (await localTable.getBooleanArray("byte:IsMetric")); })(), + (async () => { guid = (await localTable.getStringArray("string:Guid")); })(), + (async () => { numSaves = (await localTable.getNumberArray("int:NumSaves")); })(), + (async () => { isLinked = (await localTable.getBooleanArray("byte:IsLinked")); })(), + (async () => { isDetached = (await localTable.getBooleanArray("byte:IsDetached")); })(), + (async () => { isWorkshared = (await localTable.getBooleanArray("byte:IsWorkshared")); })(), + (async () => { pathName = (await localTable.getStringArray("string:PathName")); })(), + (async () => { latitude = (await localTable.getNumberArray("double:Latitude")); })(), + (async () => { longitude = (await localTable.getNumberArray("double:Longitude")); })(), + (async () => { timeZone = (await localTable.getNumberArray("double:TimeZone")); })(), + (async () => { placeName = (await localTable.getStringArray("string:PlaceName")); })(), + (async () => { weatherStationName = (await localTable.getStringArray("string:WeatherStationName")); })(), + (async () => { elevation = (await localTable.getNumberArray("double:Elevation")); })(), + (async () => { projectLocation = (await localTable.getStringArray("string:ProjectLocation")); })(), + (async () => { issueDate = (await localTable.getStringArray("string:IssueDate")); })(), + (async () => { status = (await localTable.getStringArray("string:Status")); })(), + (async () => { clientName = (await localTable.getStringArray("string:ClientName")); })(), + (async () => { address = (await localTable.getStringArray("string:Address")); })(), + (async () => { name = (await localTable.getStringArray("string:Name")); })(), + (async () => { number = (await localTable.getStringArray("string:Number")); })(), + (async () => { author = (await localTable.getStringArray("string:Author")); })(), + (async () => { buildingName = (await localTable.getStringArray("string:BuildingName")); })(), + (async () => { organizationName = (await localTable.getStringArray("string:OrganizationName")); })(), + (async () => { organizationDescription = (await localTable.getStringArray("string:OrganizationDescription")); })(), + (async () => { product = (await localTable.getStringArray("string:Product")); })(), + (async () => { version = (await localTable.getStringArray("string:Version")); })(), + (async () => { user = (await localTable.getStringArray("string:User")); })(), + (async () => { activeViewIndex = (await localTable.getNumberArray("index:Vim.View:ActiveView")); })(), + (async () => { ownerFamilyIndex = (await localTable.getNumberArray("index:Vim.Family:OwnerFamily")); })(), + (async () => { parentIndex = (await localTable.getNumberArray("index:Vim.BimDocument:Parent")); })(), + (async () => { elementIndex = (await localTable.getNumberArray("index:Vim.Element:Element")); })(), + ]); + let bimDocument = []; + for (let i = 0; i < title.length; i++) { + bimDocument.push({ + index: i, + title: title ? title[i] : undefined, + isMetric: isMetric ? isMetric[i] : undefined, + guid: guid ? guid[i] : undefined, + numSaves: numSaves ? numSaves[i] : undefined, + isLinked: isLinked ? isLinked[i] : undefined, + isDetached: isDetached ? isDetached[i] : undefined, + isWorkshared: isWorkshared ? isWorkshared[i] : undefined, + pathName: pathName ? pathName[i] : undefined, + latitude: latitude ? latitude[i] : undefined, + longitude: longitude ? longitude[i] : undefined, + timeZone: timeZone ? timeZone[i] : undefined, + placeName: placeName ? placeName[i] : undefined, + weatherStationName: weatherStationName ? weatherStationName[i] : undefined, + elevation: elevation ? elevation[i] : undefined, + projectLocation: projectLocation ? projectLocation[i] : undefined, + issueDate: issueDate ? issueDate[i] : undefined, + status: status ? status[i] : undefined, + clientName: clientName ? clientName[i] : undefined, + address: address ? address[i] : undefined, + name: name ? name[i] : undefined, + number: number ? number[i] : undefined, + author: author ? author[i] : undefined, + buildingName: buildingName ? buildingName[i] : undefined, + organizationName: organizationName ? organizationName[i] : undefined, + organizationDescription: organizationDescription ? organizationDescription[i] : undefined, + product: product ? product[i] : undefined, + version: version ? version[i] : undefined, + user: user ? user[i] : undefined, + activeViewIndex: activeViewIndex ? activeViewIndex[i] : undefined, + ownerFamilyIndex: ownerFamilyIndex ? ownerFamilyIndex[i] : undefined, + parentIndex: parentIndex ? parentIndex[i] : undefined, + elementIndex: elementIndex ? elementIndex[i] : undefined + }); + } + return bimDocument; + } + async getTitle(bimDocumentIndex) { + return (await this.entityTable.getString(bimDocumentIndex, "string:Title")); + } + async getAllTitle() { + return (await this.entityTable.getStringArray("string:Title")); + } + async getIsMetric(bimDocumentIndex) { + return (await this.entityTable.getBoolean(bimDocumentIndex, "byte:IsMetric")); + } + async getAllIsMetric() { + return (await this.entityTable.getBooleanArray("byte:IsMetric")); + } + async getGuid(bimDocumentIndex) { + return (await this.entityTable.getString(bimDocumentIndex, "string:Guid")); + } + async getAllGuid() { + return (await this.entityTable.getStringArray("string:Guid")); + } + async getNumSaves(bimDocumentIndex) { + return (await this.entityTable.getNumber(bimDocumentIndex, "int:NumSaves")); + } + async getAllNumSaves() { + return (await this.entityTable.getNumberArray("int:NumSaves")); + } + async getIsLinked(bimDocumentIndex) { + return (await this.entityTable.getBoolean(bimDocumentIndex, "byte:IsLinked")); + } + async getAllIsLinked() { + return (await this.entityTable.getBooleanArray("byte:IsLinked")); + } + async getIsDetached(bimDocumentIndex) { + return (await this.entityTable.getBoolean(bimDocumentIndex, "byte:IsDetached")); + } + async getAllIsDetached() { + return (await this.entityTable.getBooleanArray("byte:IsDetached")); + } + async getIsWorkshared(bimDocumentIndex) { + return (await this.entityTable.getBoolean(bimDocumentIndex, "byte:IsWorkshared")); + } + async getAllIsWorkshared() { + return (await this.entityTable.getBooleanArray("byte:IsWorkshared")); + } + async getPathName(bimDocumentIndex) { + return (await this.entityTable.getString(bimDocumentIndex, "string:PathName")); + } + async getAllPathName() { + return (await this.entityTable.getStringArray("string:PathName")); + } + async getLatitude(bimDocumentIndex) { + return (await this.entityTable.getNumber(bimDocumentIndex, "double:Latitude")); + } + async getAllLatitude() { + return (await this.entityTable.getNumberArray("double:Latitude")); + } + async getLongitude(bimDocumentIndex) { + return (await this.entityTable.getNumber(bimDocumentIndex, "double:Longitude")); + } + async getAllLongitude() { + return (await this.entityTable.getNumberArray("double:Longitude")); + } + async getTimeZone(bimDocumentIndex) { + return (await this.entityTable.getNumber(bimDocumentIndex, "double:TimeZone")); + } + async getAllTimeZone() { + return (await this.entityTable.getNumberArray("double:TimeZone")); + } + async getPlaceName(bimDocumentIndex) { + return (await this.entityTable.getString(bimDocumentIndex, "string:PlaceName")); + } + async getAllPlaceName() { + return (await this.entityTable.getStringArray("string:PlaceName")); + } + async getWeatherStationName(bimDocumentIndex) { + return (await this.entityTable.getString(bimDocumentIndex, "string:WeatherStationName")); + } + async getAllWeatherStationName() { + return (await this.entityTable.getStringArray("string:WeatherStationName")); + } + async getElevation(bimDocumentIndex) { + return (await this.entityTable.getNumber(bimDocumentIndex, "double:Elevation")); + } + async getAllElevation() { + return (await this.entityTable.getNumberArray("double:Elevation")); + } + async getProjectLocation(bimDocumentIndex) { + return (await this.entityTable.getString(bimDocumentIndex, "string:ProjectLocation")); + } + async getAllProjectLocation() { + return (await this.entityTable.getStringArray("string:ProjectLocation")); + } + async getIssueDate(bimDocumentIndex) { + return (await this.entityTable.getString(bimDocumentIndex, "string:IssueDate")); + } + async getAllIssueDate() { + return (await this.entityTable.getStringArray("string:IssueDate")); + } + async getStatus(bimDocumentIndex) { + return (await this.entityTable.getString(bimDocumentIndex, "string:Status")); + } + async getAllStatus() { + return (await this.entityTable.getStringArray("string:Status")); + } + async getClientName(bimDocumentIndex) { + return (await this.entityTable.getString(bimDocumentIndex, "string:ClientName")); + } + async getAllClientName() { + return (await this.entityTable.getStringArray("string:ClientName")); + } + async getAddress(bimDocumentIndex) { + return (await this.entityTable.getString(bimDocumentIndex, "string:Address")); + } + async getAllAddress() { + return (await this.entityTable.getStringArray("string:Address")); + } + async getName(bimDocumentIndex) { + return (await this.entityTable.getString(bimDocumentIndex, "string:Name")); + } + async getAllName() { + return (await this.entityTable.getStringArray("string:Name")); + } + async getNumber(bimDocumentIndex) { + return (await this.entityTable.getString(bimDocumentIndex, "string:Number")); + } + async getAllNumber() { + return (await this.entityTable.getStringArray("string:Number")); + } + async getAuthor(bimDocumentIndex) { + return (await this.entityTable.getString(bimDocumentIndex, "string:Author")); + } + async getAllAuthor() { + return (await this.entityTable.getStringArray("string:Author")); + } + async getBuildingName(bimDocumentIndex) { + return (await this.entityTable.getString(bimDocumentIndex, "string:BuildingName")); + } + async getAllBuildingName() { + return (await this.entityTable.getStringArray("string:BuildingName")); + } + async getOrganizationName(bimDocumentIndex) { + return (await this.entityTable.getString(bimDocumentIndex, "string:OrganizationName")); + } + async getAllOrganizationName() { + return (await this.entityTable.getStringArray("string:OrganizationName")); + } + async getOrganizationDescription(bimDocumentIndex) { + return (await this.entityTable.getString(bimDocumentIndex, "string:OrganizationDescription")); + } + async getAllOrganizationDescription() { + return (await this.entityTable.getStringArray("string:OrganizationDescription")); + } + async getProduct(bimDocumentIndex) { + return (await this.entityTable.getString(bimDocumentIndex, "string:Product")); + } + async getAllProduct() { + return (await this.entityTable.getStringArray("string:Product")); + } + async getVersion(bimDocumentIndex) { + return (await this.entityTable.getString(bimDocumentIndex, "string:Version")); + } + async getAllVersion() { + return (await this.entityTable.getStringArray("string:Version")); + } + async getUser(bimDocumentIndex) { + return (await this.entityTable.getString(bimDocumentIndex, "string:User")); + } + async getAllUser() { + return (await this.entityTable.getStringArray("string:User")); + } + async getActiveViewIndex(bimDocumentIndex) { + return await this.entityTable.getNumber(bimDocumentIndex, "index:Vim.View:ActiveView"); + } + async getAllActiveViewIndex() { + return await this.entityTable.getNumberArray("index:Vim.View:ActiveView"); + } + async getActiveView(bimDocumentIndex) { + const index = await this.getActiveViewIndex(bimDocumentIndex); + if (index === undefined) { + return undefined; + } + return await this.document.view?.get(index); + } + async getOwnerFamilyIndex(bimDocumentIndex) { + return await this.entityTable.getNumber(bimDocumentIndex, "index:Vim.Family:OwnerFamily"); + } + async getAllOwnerFamilyIndex() { + return await this.entityTable.getNumberArray("index:Vim.Family:OwnerFamily"); + } + async getOwnerFamily(bimDocumentIndex) { + const index = await this.getOwnerFamilyIndex(bimDocumentIndex); + if (index === undefined) { + return undefined; + } + return await this.document.family?.get(index); + } + async getParentIndex(bimDocumentIndex) { + return await this.entityTable.getNumber(bimDocumentIndex, "index:Vim.BimDocument:Parent"); + } + async getAllParentIndex() { + return await this.entityTable.getNumberArray("index:Vim.BimDocument:Parent"); + } + async getParent(bimDocumentIndex) { + const index = await this.getParentIndex(bimDocumentIndex); + if (index === undefined) { + return undefined; + } + return await this.document.bimDocument?.get(index); + } + async getElementIndex(bimDocumentIndex) { + return await this.entityTable.getNumber(bimDocumentIndex, "index:Vim.Element:Element"); + } + async getAllElementIndex() { + return await this.entityTable.getNumberArray("index:Vim.Element:Element"); + } + async getElement(bimDocumentIndex) { + const index = await this.getElementIndex(bimDocumentIndex); + if (index === undefined) { + return undefined; + } + return await this.document.element?.get(index); + } +} +exports.BimDocumentTable = BimDocumentTable; +class DisplayUnitInBimDocument { + static async createFromTable(table, index) { + let result = new DisplayUnitInBimDocument(); + result.index = index; + await Promise.all([ + table.getDisplayUnitIndex(index).then(v => result.displayUnitIndex = v), + table.getBimDocumentIndex(index).then(v => result.bimDocumentIndex = v), + ]); + return result; + } +} +exports.DisplayUnitInBimDocument = DisplayUnitInBimDocument; +class DisplayUnitInBimDocumentTable { + static async createFromDocument(document) { + const entity = await document.entities.getBfast("Vim.DisplayUnitInBimDocument"); + if (!entity) { + return undefined; + } + let table = new DisplayUnitInBimDocumentTable(); + table.document = document; + table.entityTable = new entityTable_1.EntityTable(entity, document.strings); + return table; + } + getCount() { + return this.entityTable.getCount(); + } + async get(displayUnitInBimDocumentIndex) { + return await DisplayUnitInBimDocument.createFromTable(this, displayUnitInBimDocumentIndex); + } + async getAll() { + const localTable = await this.entityTable.getLocal(); + let displayUnitIndex; + let bimDocumentIndex; + await Promise.all([ + (async () => { displayUnitIndex = (await localTable.getNumberArray("index:Vim.DisplayUnit:DisplayUnit")); })(), + (async () => { bimDocumentIndex = (await localTable.getNumberArray("index:Vim.BimDocument:BimDocument")); })(), + ]); + let displayUnitInBimDocument = []; + for (let i = 0; i < displayUnitIndex.length; i++) { + displayUnitInBimDocument.push({ + index: i, + displayUnitIndex: displayUnitIndex ? displayUnitIndex[i] : undefined, + bimDocumentIndex: bimDocumentIndex ? bimDocumentIndex[i] : undefined + }); + } + return displayUnitInBimDocument; + } + async getDisplayUnitIndex(displayUnitInBimDocumentIndex) { + return await this.entityTable.getNumber(displayUnitInBimDocumentIndex, "index:Vim.DisplayUnit:DisplayUnit"); + } + async getAllDisplayUnitIndex() { + return await this.entityTable.getNumberArray("index:Vim.DisplayUnit:DisplayUnit"); + } + async getDisplayUnit(displayUnitInBimDocumentIndex) { + const index = await this.getDisplayUnitIndex(displayUnitInBimDocumentIndex); + if (index === undefined) { + return undefined; + } + return await this.document.displayUnit?.get(index); + } + async getBimDocumentIndex(displayUnitInBimDocumentIndex) { + return await this.entityTable.getNumber(displayUnitInBimDocumentIndex, "index:Vim.BimDocument:BimDocument"); + } + async getAllBimDocumentIndex() { + return await this.entityTable.getNumberArray("index:Vim.BimDocument:BimDocument"); + } + async getBimDocument(displayUnitInBimDocumentIndex) { + const index = await this.getBimDocumentIndex(displayUnitInBimDocumentIndex); + if (index === undefined) { + return undefined; + } + return await this.document.bimDocument?.get(index); + } +} +exports.DisplayUnitInBimDocumentTable = DisplayUnitInBimDocumentTable; +class PhaseOrderInBimDocument { + static async createFromTable(table, index) { + let result = new PhaseOrderInBimDocument(); + result.index = index; + await Promise.all([ + table.getOrderIndex(index).then(v => result.orderIndex = v), + table.getPhaseIndex(index).then(v => result.phaseIndex = v), + table.getBimDocumentIndex(index).then(v => result.bimDocumentIndex = v), + ]); + return result; + } +} +exports.PhaseOrderInBimDocument = PhaseOrderInBimDocument; +class PhaseOrderInBimDocumentTable { + static async createFromDocument(document) { + const entity = await document.entities.getBfast("Vim.PhaseOrderInBimDocument"); + if (!entity) { + return undefined; + } + let table = new PhaseOrderInBimDocumentTable(); + table.document = document; + table.entityTable = new entityTable_1.EntityTable(entity, document.strings); + return table; + } + getCount() { + return this.entityTable.getCount(); + } + async get(phaseOrderInBimDocumentIndex) { + return await PhaseOrderInBimDocument.createFromTable(this, phaseOrderInBimDocumentIndex); + } + async getAll() { + const localTable = await this.entityTable.getLocal(); + let orderIndex; + let phaseIndex; + let bimDocumentIndex; + await Promise.all([ + (async () => { orderIndex = (await localTable.getNumberArray("int:OrderIndex")); })(), + (async () => { phaseIndex = (await localTable.getNumberArray("index:Vim.Phase:Phase")); })(), + (async () => { bimDocumentIndex = (await localTable.getNumberArray("index:Vim.BimDocument:BimDocument")); })(), + ]); + let phaseOrderInBimDocument = []; + for (let i = 0; i < orderIndex.length; i++) { + phaseOrderInBimDocument.push({ + index: i, + orderIndex: orderIndex ? orderIndex[i] : undefined, + phaseIndex: phaseIndex ? phaseIndex[i] : undefined, + bimDocumentIndex: bimDocumentIndex ? bimDocumentIndex[i] : undefined + }); + } + return phaseOrderInBimDocument; + } + async getOrderIndex(phaseOrderInBimDocumentIndex) { + return (await this.entityTable.getNumber(phaseOrderInBimDocumentIndex, "int:OrderIndex")); + } + async getAllOrderIndex() { + return (await this.entityTable.getNumberArray("int:OrderIndex")); + } + async getPhaseIndex(phaseOrderInBimDocumentIndex) { + return await this.entityTable.getNumber(phaseOrderInBimDocumentIndex, "index:Vim.Phase:Phase"); + } + async getAllPhaseIndex() { + return await this.entityTable.getNumberArray("index:Vim.Phase:Phase"); + } + async getPhase(phaseOrderInBimDocumentIndex) { + const index = await this.getPhaseIndex(phaseOrderInBimDocumentIndex); + if (index === undefined) { + return undefined; + } + return await this.document.phase?.get(index); + } + async getBimDocumentIndex(phaseOrderInBimDocumentIndex) { + return await this.entityTable.getNumber(phaseOrderInBimDocumentIndex, "index:Vim.BimDocument:BimDocument"); + } + async getAllBimDocumentIndex() { + return await this.entityTable.getNumberArray("index:Vim.BimDocument:BimDocument"); + } + async getBimDocument(phaseOrderInBimDocumentIndex) { + const index = await this.getBimDocumentIndex(phaseOrderInBimDocumentIndex); + if (index === undefined) { + return undefined; + } + return await this.document.bimDocument?.get(index); + } +} +exports.PhaseOrderInBimDocumentTable = PhaseOrderInBimDocumentTable; +class Category { + static async createFromTable(table, index) { + let result = new Category(); + result.index = index; + await Promise.all([ + table.getName(index).then(v => result.name = v), + table.getId(index).then(v => result.id = v), + table.getCategoryType(index).then(v => result.categoryType = v), + table.getLineColor_X(index).then(v => result.lineColor_X = v), + table.getLineColor_Y(index).then(v => result.lineColor_Y = v), + table.getLineColor_Z(index).then(v => result.lineColor_Z = v), + table.getBuiltInCategory(index).then(v => result.builtInCategory = v), + table.getParentIndex(index).then(v => result.parentIndex = v), + table.getMaterialIndex(index).then(v => result.materialIndex = v), + ]); + return result; + } +} +exports.Category = Category; +class CategoryTable { + static async createFromDocument(document) { + const entity = await document.entities.getBfast("Vim.Category"); + if (!entity) { + return undefined; + } + let table = new CategoryTable(); + table.document = document; + table.entityTable = new entityTable_1.EntityTable(entity, document.strings); + return table; + } + getCount() { + return this.entityTable.getCount(); + } + async get(categoryIndex) { + return await Category.createFromTable(this, categoryIndex); + } + async getAll() { + const localTable = await this.entityTable.getLocal(); + let name; + let id; + let categoryType; + let lineColor_X; + let lineColor_Y; + let lineColor_Z; + let builtInCategory; + let parentIndex; + let materialIndex; + await Promise.all([ + (async () => { name = (await localTable.getStringArray("string:Name")); })(), + (async () => { id = (await localTable.getBigIntArray("long:Id")) ?? (await localTable.getBigIntArray("int:Id")); })(), + (async () => { categoryType = (await localTable.getStringArray("string:CategoryType")); })(), + (async () => { lineColor_X = (await localTable.getNumberArray("double:LineColor.X")); })(), + (async () => { lineColor_Y = (await localTable.getNumberArray("double:LineColor.Y")); })(), + (async () => { lineColor_Z = (await localTable.getNumberArray("double:LineColor.Z")); })(), + (async () => { builtInCategory = (await localTable.getStringArray("string:BuiltInCategory")); })(), + (async () => { parentIndex = (await localTable.getNumberArray("index:Vim.Category:Parent")); })(), + (async () => { materialIndex = (await localTable.getNumberArray("index:Vim.Material:Material")); })(), + ]); + let category = []; + for (let i = 0; i < name.length; i++) { + category.push({ + index: i, + name: name ? name[i] : undefined, + id: id ? id[i] : undefined, + categoryType: categoryType ? categoryType[i] : undefined, + lineColor_X: lineColor_X ? lineColor_X[i] : undefined, + lineColor_Y: lineColor_Y ? lineColor_Y[i] : undefined, + lineColor_Z: lineColor_Z ? lineColor_Z[i] : undefined, + builtInCategory: builtInCategory ? builtInCategory[i] : undefined, + parentIndex: parentIndex ? parentIndex[i] : undefined, + materialIndex: materialIndex ? materialIndex[i] : undefined + }); + } + return category; + } + async getName(categoryIndex) { + return (await this.entityTable.getString(categoryIndex, "string:Name")); + } + async getAllName() { + return (await this.entityTable.getStringArray("string:Name")); + } + async getId(categoryIndex) { + return (await this.entityTable.getBigInt(categoryIndex, "long:Id")) ?? (await this.entityTable.getBigInt(categoryIndex, "int:Id")); + } + async getAllId() { + return (await this.entityTable.getBigIntArray("long:Id")) ?? (await this.entityTable.getBigIntArray("int:Id")); + } + async getCategoryType(categoryIndex) { + return (await this.entityTable.getString(categoryIndex, "string:CategoryType")); + } + async getAllCategoryType() { + return (await this.entityTable.getStringArray("string:CategoryType")); + } + async getLineColor_X(categoryIndex) { + return (await this.entityTable.getNumber(categoryIndex, "double:LineColor.X")); + } + async getAllLineColor_X() { + return (await this.entityTable.getNumberArray("double:LineColor.X")); + } + async getLineColor_Y(categoryIndex) { + return (await this.entityTable.getNumber(categoryIndex, "double:LineColor.Y")); + } + async getAllLineColor_Y() { + return (await this.entityTable.getNumberArray("double:LineColor.Y")); + } + async getLineColor_Z(categoryIndex) { + return (await this.entityTable.getNumber(categoryIndex, "double:LineColor.Z")); + } + async getAllLineColor_Z() { + return (await this.entityTable.getNumberArray("double:LineColor.Z")); + } + async getBuiltInCategory(categoryIndex) { + return (await this.entityTable.getString(categoryIndex, "string:BuiltInCategory")); + } + async getAllBuiltInCategory() { + return (await this.entityTable.getStringArray("string:BuiltInCategory")); + } + async getParentIndex(categoryIndex) { + return await this.entityTable.getNumber(categoryIndex, "index:Vim.Category:Parent"); + } + async getAllParentIndex() { + return await this.entityTable.getNumberArray("index:Vim.Category:Parent"); + } + async getParent(categoryIndex) { + const index = await this.getParentIndex(categoryIndex); + if (index === undefined) { + return undefined; + } + return await this.document.category?.get(index); + } + async getMaterialIndex(categoryIndex) { + return await this.entityTable.getNumber(categoryIndex, "index:Vim.Material:Material"); + } + async getAllMaterialIndex() { + return await this.entityTable.getNumberArray("index:Vim.Material:Material"); + } + async getMaterial(categoryIndex) { + const index = await this.getMaterialIndex(categoryIndex); + if (index === undefined) { + return undefined; + } + return await this.document.material?.get(index); + } +} +exports.CategoryTable = CategoryTable; +class Family { + static async createFromTable(table, index) { + let result = new Family(); + result.index = index; + await Promise.all([ + table.getStructuralMaterialType(index).then(v => result.structuralMaterialType = v), + table.getStructuralSectionShape(index).then(v => result.structuralSectionShape = v), + table.getIsSystemFamily(index).then(v => result.isSystemFamily = v), + table.getIsInPlace(index).then(v => result.isInPlace = v), + table.getFamilyCategoryIndex(index).then(v => result.familyCategoryIndex = v), + table.getElementIndex(index).then(v => result.elementIndex = v), + ]); + return result; + } +} +exports.Family = Family; +class FamilyTable { + static async createFromDocument(document) { + const entity = await document.entities.getBfast("Vim.Family"); + if (!entity) { + return undefined; + } + let table = new FamilyTable(); + table.document = document; + table.entityTable = new entityTable_1.EntityTable(entity, document.strings); + return table; + } + getCount() { + return this.entityTable.getCount(); + } + async get(familyIndex) { + return await Family.createFromTable(this, familyIndex); + } + async getAll() { + const localTable = await this.entityTable.getLocal(); + let structuralMaterialType; + let structuralSectionShape; + let isSystemFamily; + let isInPlace; + let familyCategoryIndex; + let elementIndex; + await Promise.all([ + (async () => { structuralMaterialType = (await localTable.getStringArray("string:StructuralMaterialType")); })(), + (async () => { structuralSectionShape = (await localTable.getStringArray("string:StructuralSectionShape")); })(), + (async () => { isSystemFamily = (await localTable.getBooleanArray("byte:IsSystemFamily")); })(), + (async () => { isInPlace = (await localTable.getBooleanArray("byte:IsInPlace")); })(), + (async () => { familyCategoryIndex = (await localTable.getNumberArray("index:Vim.Category:FamilyCategory")); })(), + (async () => { elementIndex = (await localTable.getNumberArray("index:Vim.Element:Element")); })(), + ]); + let family = []; + for (let i = 0; i < structuralMaterialType.length; i++) { + family.push({ + index: i, + structuralMaterialType: structuralMaterialType ? structuralMaterialType[i] : undefined, + structuralSectionShape: structuralSectionShape ? structuralSectionShape[i] : undefined, + isSystemFamily: isSystemFamily ? isSystemFamily[i] : undefined, + isInPlace: isInPlace ? isInPlace[i] : undefined, + familyCategoryIndex: familyCategoryIndex ? familyCategoryIndex[i] : undefined, + elementIndex: elementIndex ? elementIndex[i] : undefined + }); + } + return family; + } + async getStructuralMaterialType(familyIndex) { + return (await this.entityTable.getString(familyIndex, "string:StructuralMaterialType")); + } + async getAllStructuralMaterialType() { + return (await this.entityTable.getStringArray("string:StructuralMaterialType")); + } + async getStructuralSectionShape(familyIndex) { + return (await this.entityTable.getString(familyIndex, "string:StructuralSectionShape")); + } + async getAllStructuralSectionShape() { + return (await this.entityTable.getStringArray("string:StructuralSectionShape")); + } + async getIsSystemFamily(familyIndex) { + return (await this.entityTable.getBoolean(familyIndex, "byte:IsSystemFamily")); + } + async getAllIsSystemFamily() { + return (await this.entityTable.getBooleanArray("byte:IsSystemFamily")); + } + async getIsInPlace(familyIndex) { + return (await this.entityTable.getBoolean(familyIndex, "byte:IsInPlace")); + } + async getAllIsInPlace() { + return (await this.entityTable.getBooleanArray("byte:IsInPlace")); + } + async getFamilyCategoryIndex(familyIndex) { + return await this.entityTable.getNumber(familyIndex, "index:Vim.Category:FamilyCategory"); + } + async getAllFamilyCategoryIndex() { + return await this.entityTable.getNumberArray("index:Vim.Category:FamilyCategory"); + } + async getFamilyCategory(familyIndex) { + const index = await this.getFamilyCategoryIndex(familyIndex); + if (index === undefined) { + return undefined; + } + return await this.document.category?.get(index); + } + async getElementIndex(familyIndex) { + return await this.entityTable.getNumber(familyIndex, "index:Vim.Element:Element"); + } + async getAllElementIndex() { + return await this.entityTable.getNumberArray("index:Vim.Element:Element"); + } + async getElement(familyIndex) { + const index = await this.getElementIndex(familyIndex); + if (index === undefined) { + return undefined; + } + return await this.document.element?.get(index); + } +} +exports.FamilyTable = FamilyTable; +class FamilyType { + static async createFromTable(table, index) { + let result = new FamilyType(); + result.index = index; + await Promise.all([ + table.getIsSystemFamilyType(index).then(v => result.isSystemFamilyType = v), + table.getFamilyIndex(index).then(v => result.familyIndex = v), + table.getCompoundStructureIndex(index).then(v => result.compoundStructureIndex = v), + table.getElementIndex(index).then(v => result.elementIndex = v), + ]); + return result; + } +} +exports.FamilyType = FamilyType; +class FamilyTypeTable { + static async createFromDocument(document) { + const entity = await document.entities.getBfast("Vim.FamilyType"); + if (!entity) { + return undefined; + } + let table = new FamilyTypeTable(); + table.document = document; + table.entityTable = new entityTable_1.EntityTable(entity, document.strings); + return table; + } + getCount() { + return this.entityTable.getCount(); + } + async get(familyTypeIndex) { + return await FamilyType.createFromTable(this, familyTypeIndex); + } + async getAll() { + const localTable = await this.entityTable.getLocal(); + let isSystemFamilyType; + let familyIndex; + let compoundStructureIndex; + let elementIndex; + await Promise.all([ + (async () => { isSystemFamilyType = (await localTable.getBooleanArray("byte:IsSystemFamilyType")); })(), + (async () => { familyIndex = (await localTable.getNumberArray("index:Vim.Family:Family")); })(), + (async () => { compoundStructureIndex = (await localTable.getNumberArray("index:Vim.CompoundStructure:CompoundStructure")); })(), + (async () => { elementIndex = (await localTable.getNumberArray("index:Vim.Element:Element")); })(), + ]); + let familyType = []; + for (let i = 0; i < isSystemFamilyType.length; i++) { + familyType.push({ + index: i, + isSystemFamilyType: isSystemFamilyType ? isSystemFamilyType[i] : undefined, + familyIndex: familyIndex ? familyIndex[i] : undefined, + compoundStructureIndex: compoundStructureIndex ? compoundStructureIndex[i] : undefined, + elementIndex: elementIndex ? elementIndex[i] : undefined + }); + } + return familyType; + } + async getIsSystemFamilyType(familyTypeIndex) { + return (await this.entityTable.getBoolean(familyTypeIndex, "byte:IsSystemFamilyType")); + } + async getAllIsSystemFamilyType() { + return (await this.entityTable.getBooleanArray("byte:IsSystemFamilyType")); + } + async getFamilyIndex(familyTypeIndex) { + return await this.entityTable.getNumber(familyTypeIndex, "index:Vim.Family:Family"); + } + async getAllFamilyIndex() { + return await this.entityTable.getNumberArray("index:Vim.Family:Family"); + } + async getFamily(familyTypeIndex) { + const index = await this.getFamilyIndex(familyTypeIndex); + if (index === undefined) { + return undefined; + } + return await this.document.family?.get(index); + } + async getCompoundStructureIndex(familyTypeIndex) { + return await this.entityTable.getNumber(familyTypeIndex, "index:Vim.CompoundStructure:CompoundStructure"); + } + async getAllCompoundStructureIndex() { + return await this.entityTable.getNumberArray("index:Vim.CompoundStructure:CompoundStructure"); + } + async getCompoundStructure(familyTypeIndex) { + const index = await this.getCompoundStructureIndex(familyTypeIndex); + if (index === undefined) { + return undefined; + } + return await this.document.compoundStructure?.get(index); + } + async getElementIndex(familyTypeIndex) { + return await this.entityTable.getNumber(familyTypeIndex, "index:Vim.Element:Element"); + } + async getAllElementIndex() { + return await this.entityTable.getNumberArray("index:Vim.Element:Element"); + } + async getElement(familyTypeIndex) { + const index = await this.getElementIndex(familyTypeIndex); + if (index === undefined) { + return undefined; + } + return await this.document.element?.get(index); + } +} +exports.FamilyTypeTable = FamilyTypeTable; +class FamilyInstance { + static async createFromTable(table, index) { + let result = new FamilyInstance(); + result.index = index; + await Promise.all([ + table.getFacingFlipped(index).then(v => result.facingFlipped = v), + table.getFacingOrientation_X(index).then(v => result.facingOrientation_X = v), + table.getFacingOrientation_Y(index).then(v => result.facingOrientation_Y = v), + table.getFacingOrientation_Z(index).then(v => result.facingOrientation_Z = v), + table.getHandFlipped(index).then(v => result.handFlipped = v), + table.getMirrored(index).then(v => result.mirrored = v), + table.getHasModifiedGeometry(index).then(v => result.hasModifiedGeometry = v), + table.getScale(index).then(v => result.scale = v), + table.getBasisX_X(index).then(v => result.basisX_X = v), + table.getBasisX_Y(index).then(v => result.basisX_Y = v), + table.getBasisX_Z(index).then(v => result.basisX_Z = v), + table.getBasisY_X(index).then(v => result.basisY_X = v), + table.getBasisY_Y(index).then(v => result.basisY_Y = v), + table.getBasisY_Z(index).then(v => result.basisY_Z = v), + table.getBasisZ_X(index).then(v => result.basisZ_X = v), + table.getBasisZ_Y(index).then(v => result.basisZ_Y = v), + table.getBasisZ_Z(index).then(v => result.basisZ_Z = v), + table.getTranslation_X(index).then(v => result.translation_X = v), + table.getTranslation_Y(index).then(v => result.translation_Y = v), + table.getTranslation_Z(index).then(v => result.translation_Z = v), + table.getHandOrientation_X(index).then(v => result.handOrientation_X = v), + table.getHandOrientation_Y(index).then(v => result.handOrientation_Y = v), + table.getHandOrientation_Z(index).then(v => result.handOrientation_Z = v), + table.getFamilyTypeIndex(index).then(v => result.familyTypeIndex = v), + table.getHostIndex(index).then(v => result.hostIndex = v), + table.getFromRoomIndex(index).then(v => result.fromRoomIndex = v), + table.getToRoomIndex(index).then(v => result.toRoomIndex = v), + table.getElementIndex(index).then(v => result.elementIndex = v), + ]); + return result; + } +} +exports.FamilyInstance = FamilyInstance; +class FamilyInstanceTable { + static async createFromDocument(document) { + const entity = await document.entities.getBfast("Vim.FamilyInstance"); + if (!entity) { + return undefined; + } + let table = new FamilyInstanceTable(); + table.document = document; + table.entityTable = new entityTable_1.EntityTable(entity, document.strings); + return table; + } + getCount() { + return this.entityTable.getCount(); + } + async get(familyInstanceIndex) { + return await FamilyInstance.createFromTable(this, familyInstanceIndex); + } + async getAll() { + const localTable = await this.entityTable.getLocal(); + let facingFlipped; + let facingOrientation_X; + let facingOrientation_Y; + let facingOrientation_Z; + let handFlipped; + let mirrored; + let hasModifiedGeometry; + let scale; + let basisX_X; + let basisX_Y; + let basisX_Z; + let basisY_X; + let basisY_Y; + let basisY_Z; + let basisZ_X; + let basisZ_Y; + let basisZ_Z; + let translation_X; + let translation_Y; + let translation_Z; + let handOrientation_X; + let handOrientation_Y; + let handOrientation_Z; + let familyTypeIndex; + let hostIndex; + let fromRoomIndex; + let toRoomIndex; + let elementIndex; + await Promise.all([ + (async () => { facingFlipped = (await localTable.getBooleanArray("byte:FacingFlipped")); })(), + (async () => { facingOrientation_X = (await localTable.getNumberArray("float:FacingOrientation.X")); })(), + (async () => { facingOrientation_Y = (await localTable.getNumberArray("float:FacingOrientation.Y")); })(), + (async () => { facingOrientation_Z = (await localTable.getNumberArray("float:FacingOrientation.Z")); })(), + (async () => { handFlipped = (await localTable.getBooleanArray("byte:HandFlipped")); })(), + (async () => { mirrored = (await localTable.getBooleanArray("byte:Mirrored")); })(), + (async () => { hasModifiedGeometry = (await localTable.getBooleanArray("byte:HasModifiedGeometry")); })(), + (async () => { scale = (await localTable.getNumberArray("float:Scale")); })(), + (async () => { basisX_X = (await localTable.getNumberArray("float:BasisX.X")); })(), + (async () => { basisX_Y = (await localTable.getNumberArray("float:BasisX.Y")); })(), + (async () => { basisX_Z = (await localTable.getNumberArray("float:BasisX.Z")); })(), + (async () => { basisY_X = (await localTable.getNumberArray("float:BasisY.X")); })(), + (async () => { basisY_Y = (await localTable.getNumberArray("float:BasisY.Y")); })(), + (async () => { basisY_Z = (await localTable.getNumberArray("float:BasisY.Z")); })(), + (async () => { basisZ_X = (await localTable.getNumberArray("float:BasisZ.X")); })(), + (async () => { basisZ_Y = (await localTable.getNumberArray("float:BasisZ.Y")); })(), + (async () => { basisZ_Z = (await localTable.getNumberArray("float:BasisZ.Z")); })(), + (async () => { translation_X = (await localTable.getNumberArray("float:Translation.X")); })(), + (async () => { translation_Y = (await localTable.getNumberArray("float:Translation.Y")); })(), + (async () => { translation_Z = (await localTable.getNumberArray("float:Translation.Z")); })(), + (async () => { handOrientation_X = (await localTable.getNumberArray("float:HandOrientation.X")); })(), + (async () => { handOrientation_Y = (await localTable.getNumberArray("float:HandOrientation.Y")); })(), + (async () => { handOrientation_Z = (await localTable.getNumberArray("float:HandOrientation.Z")); })(), + (async () => { familyTypeIndex = (await localTable.getNumberArray("index:Vim.FamilyType:FamilyType")); })(), + (async () => { hostIndex = (await localTable.getNumberArray("index:Vim.Element:Host")); })(), + (async () => { fromRoomIndex = (await localTable.getNumberArray("index:Vim.Room:FromRoom")); })(), + (async () => { toRoomIndex = (await localTable.getNumberArray("index:Vim.Room:ToRoom")); })(), + (async () => { elementIndex = (await localTable.getNumberArray("index:Vim.Element:Element")); })(), + ]); + let familyInstance = []; + for (let i = 0; i < facingFlipped.length; i++) { + familyInstance.push({ + index: i, + facingFlipped: facingFlipped ? facingFlipped[i] : undefined, + facingOrientation_X: facingOrientation_X ? facingOrientation_X[i] : undefined, + facingOrientation_Y: facingOrientation_Y ? facingOrientation_Y[i] : undefined, + facingOrientation_Z: facingOrientation_Z ? facingOrientation_Z[i] : undefined, + handFlipped: handFlipped ? handFlipped[i] : undefined, + mirrored: mirrored ? mirrored[i] : undefined, + hasModifiedGeometry: hasModifiedGeometry ? hasModifiedGeometry[i] : undefined, + scale: scale ? scale[i] : undefined, + basisX_X: basisX_X ? basisX_X[i] : undefined, + basisX_Y: basisX_Y ? basisX_Y[i] : undefined, + basisX_Z: basisX_Z ? basisX_Z[i] : undefined, + basisY_X: basisY_X ? basisY_X[i] : undefined, + basisY_Y: basisY_Y ? basisY_Y[i] : undefined, + basisY_Z: basisY_Z ? basisY_Z[i] : undefined, + basisZ_X: basisZ_X ? basisZ_X[i] : undefined, + basisZ_Y: basisZ_Y ? basisZ_Y[i] : undefined, + basisZ_Z: basisZ_Z ? basisZ_Z[i] : undefined, + translation_X: translation_X ? translation_X[i] : undefined, + translation_Y: translation_Y ? translation_Y[i] : undefined, + translation_Z: translation_Z ? translation_Z[i] : undefined, + handOrientation_X: handOrientation_X ? handOrientation_X[i] : undefined, + handOrientation_Y: handOrientation_Y ? handOrientation_Y[i] : undefined, + handOrientation_Z: handOrientation_Z ? handOrientation_Z[i] : undefined, + familyTypeIndex: familyTypeIndex ? familyTypeIndex[i] : undefined, + hostIndex: hostIndex ? hostIndex[i] : undefined, + fromRoomIndex: fromRoomIndex ? fromRoomIndex[i] : undefined, + toRoomIndex: toRoomIndex ? toRoomIndex[i] : undefined, + elementIndex: elementIndex ? elementIndex[i] : undefined + }); + } + return familyInstance; + } + async getFacingFlipped(familyInstanceIndex) { + return (await this.entityTable.getBoolean(familyInstanceIndex, "byte:FacingFlipped")); + } + async getAllFacingFlipped() { + return (await this.entityTable.getBooleanArray("byte:FacingFlipped")); + } + async getFacingOrientation_X(familyInstanceIndex) { + return (await this.entityTable.getNumber(familyInstanceIndex, "float:FacingOrientation.X")); + } + async getAllFacingOrientation_X() { + return (await this.entityTable.getNumberArray("float:FacingOrientation.X")); + } + async getFacingOrientation_Y(familyInstanceIndex) { + return (await this.entityTable.getNumber(familyInstanceIndex, "float:FacingOrientation.Y")); + } + async getAllFacingOrientation_Y() { + return (await this.entityTable.getNumberArray("float:FacingOrientation.Y")); + } + async getFacingOrientation_Z(familyInstanceIndex) { + return (await this.entityTable.getNumber(familyInstanceIndex, "float:FacingOrientation.Z")); + } + async getAllFacingOrientation_Z() { + return (await this.entityTable.getNumberArray("float:FacingOrientation.Z")); + } + async getHandFlipped(familyInstanceIndex) { + return (await this.entityTable.getBoolean(familyInstanceIndex, "byte:HandFlipped")); + } + async getAllHandFlipped() { + return (await this.entityTable.getBooleanArray("byte:HandFlipped")); + } + async getMirrored(familyInstanceIndex) { + return (await this.entityTable.getBoolean(familyInstanceIndex, "byte:Mirrored")); + } + async getAllMirrored() { + return (await this.entityTable.getBooleanArray("byte:Mirrored")); + } + async getHasModifiedGeometry(familyInstanceIndex) { + return (await this.entityTable.getBoolean(familyInstanceIndex, "byte:HasModifiedGeometry")); + } + async getAllHasModifiedGeometry() { + return (await this.entityTable.getBooleanArray("byte:HasModifiedGeometry")); + } + async getScale(familyInstanceIndex) { + return (await this.entityTable.getNumber(familyInstanceIndex, "float:Scale")); + } + async getAllScale() { + return (await this.entityTable.getNumberArray("float:Scale")); + } + async getBasisX_X(familyInstanceIndex) { + return (await this.entityTable.getNumber(familyInstanceIndex, "float:BasisX.X")); + } + async getAllBasisX_X() { + return (await this.entityTable.getNumberArray("float:BasisX.X")); + } + async getBasisX_Y(familyInstanceIndex) { + return (await this.entityTable.getNumber(familyInstanceIndex, "float:BasisX.Y")); + } + async getAllBasisX_Y() { + return (await this.entityTable.getNumberArray("float:BasisX.Y")); + } + async getBasisX_Z(familyInstanceIndex) { + return (await this.entityTable.getNumber(familyInstanceIndex, "float:BasisX.Z")); + } + async getAllBasisX_Z() { + return (await this.entityTable.getNumberArray("float:BasisX.Z")); + } + async getBasisY_X(familyInstanceIndex) { + return (await this.entityTable.getNumber(familyInstanceIndex, "float:BasisY.X")); + } + async getAllBasisY_X() { + return (await this.entityTable.getNumberArray("float:BasisY.X")); + } + async getBasisY_Y(familyInstanceIndex) { + return (await this.entityTable.getNumber(familyInstanceIndex, "float:BasisY.Y")); + } + async getAllBasisY_Y() { + return (await this.entityTable.getNumberArray("float:BasisY.Y")); + } + async getBasisY_Z(familyInstanceIndex) { + return (await this.entityTable.getNumber(familyInstanceIndex, "float:BasisY.Z")); + } + async getAllBasisY_Z() { + return (await this.entityTable.getNumberArray("float:BasisY.Z")); + } + async getBasisZ_X(familyInstanceIndex) { + return (await this.entityTable.getNumber(familyInstanceIndex, "float:BasisZ.X")); + } + async getAllBasisZ_X() { + return (await this.entityTable.getNumberArray("float:BasisZ.X")); + } + async getBasisZ_Y(familyInstanceIndex) { + return (await this.entityTable.getNumber(familyInstanceIndex, "float:BasisZ.Y")); + } + async getAllBasisZ_Y() { + return (await this.entityTable.getNumberArray("float:BasisZ.Y")); + } + async getBasisZ_Z(familyInstanceIndex) { + return (await this.entityTable.getNumber(familyInstanceIndex, "float:BasisZ.Z")); + } + async getAllBasisZ_Z() { + return (await this.entityTable.getNumberArray("float:BasisZ.Z")); + } + async getTranslation_X(familyInstanceIndex) { + return (await this.entityTable.getNumber(familyInstanceIndex, "float:Translation.X")); + } + async getAllTranslation_X() { + return (await this.entityTable.getNumberArray("float:Translation.X")); + } + async getTranslation_Y(familyInstanceIndex) { + return (await this.entityTable.getNumber(familyInstanceIndex, "float:Translation.Y")); + } + async getAllTranslation_Y() { + return (await this.entityTable.getNumberArray("float:Translation.Y")); + } + async getTranslation_Z(familyInstanceIndex) { + return (await this.entityTable.getNumber(familyInstanceIndex, "float:Translation.Z")); + } + async getAllTranslation_Z() { + return (await this.entityTable.getNumberArray("float:Translation.Z")); + } + async getHandOrientation_X(familyInstanceIndex) { + return (await this.entityTable.getNumber(familyInstanceIndex, "float:HandOrientation.X")); + } + async getAllHandOrientation_X() { + return (await this.entityTable.getNumberArray("float:HandOrientation.X")); + } + async getHandOrientation_Y(familyInstanceIndex) { + return (await this.entityTable.getNumber(familyInstanceIndex, "float:HandOrientation.Y")); + } + async getAllHandOrientation_Y() { + return (await this.entityTable.getNumberArray("float:HandOrientation.Y")); + } + async getHandOrientation_Z(familyInstanceIndex) { + return (await this.entityTable.getNumber(familyInstanceIndex, "float:HandOrientation.Z")); + } + async getAllHandOrientation_Z() { + return (await this.entityTable.getNumberArray("float:HandOrientation.Z")); + } + async getFamilyTypeIndex(familyInstanceIndex) { + return await this.entityTable.getNumber(familyInstanceIndex, "index:Vim.FamilyType:FamilyType"); + } + async getAllFamilyTypeIndex() { + return await this.entityTable.getNumberArray("index:Vim.FamilyType:FamilyType"); + } + async getFamilyType(familyInstanceIndex) { + const index = await this.getFamilyTypeIndex(familyInstanceIndex); + if (index === undefined) { + return undefined; + } + return await this.document.familyType?.get(index); + } + async getHostIndex(familyInstanceIndex) { + return await this.entityTable.getNumber(familyInstanceIndex, "index:Vim.Element:Host"); + } + async getAllHostIndex() { + return await this.entityTable.getNumberArray("index:Vim.Element:Host"); + } + async getHost(familyInstanceIndex) { + const index = await this.getHostIndex(familyInstanceIndex); + if (index === undefined) { + return undefined; + } + return await this.document.element?.get(index); + } + async getFromRoomIndex(familyInstanceIndex) { + return await this.entityTable.getNumber(familyInstanceIndex, "index:Vim.Room:FromRoom"); + } + async getAllFromRoomIndex() { + return await this.entityTable.getNumberArray("index:Vim.Room:FromRoom"); + } + async getFromRoom(familyInstanceIndex) { + const index = await this.getFromRoomIndex(familyInstanceIndex); + if (index === undefined) { + return undefined; + } + return await this.document.room?.get(index); + } + async getToRoomIndex(familyInstanceIndex) { + return await this.entityTable.getNumber(familyInstanceIndex, "index:Vim.Room:ToRoom"); + } + async getAllToRoomIndex() { + return await this.entityTable.getNumberArray("index:Vim.Room:ToRoom"); + } + async getToRoom(familyInstanceIndex) { + const index = await this.getToRoomIndex(familyInstanceIndex); + if (index === undefined) { + return undefined; + } + return await this.document.room?.get(index); + } + async getElementIndex(familyInstanceIndex) { + return await this.entityTable.getNumber(familyInstanceIndex, "index:Vim.Element:Element"); + } + async getAllElementIndex() { + return await this.entityTable.getNumberArray("index:Vim.Element:Element"); + } + async getElement(familyInstanceIndex) { + const index = await this.getElementIndex(familyInstanceIndex); + if (index === undefined) { + return undefined; + } + return await this.document.element?.get(index); + } +} +exports.FamilyInstanceTable = FamilyInstanceTable; +class View { + static async createFromTable(table, index) { + let result = new View(); + result.index = index; + await Promise.all([ + table.getTitle(index).then(v => result.title = v), + table.getViewType(index).then(v => result.viewType = v), + table.getUp_X(index).then(v => result.up_X = v), + table.getUp_Y(index).then(v => result.up_Y = v), + table.getUp_Z(index).then(v => result.up_Z = v), + table.getRight_X(index).then(v => result.right_X = v), + table.getRight_Y(index).then(v => result.right_Y = v), + table.getRight_Z(index).then(v => result.right_Z = v), + table.getOrigin_X(index).then(v => result.origin_X = v), + table.getOrigin_Y(index).then(v => result.origin_Y = v), + table.getOrigin_Z(index).then(v => result.origin_Z = v), + table.getViewDirection_X(index).then(v => result.viewDirection_X = v), + table.getViewDirection_Y(index).then(v => result.viewDirection_Y = v), + table.getViewDirection_Z(index).then(v => result.viewDirection_Z = v), + table.getViewPosition_X(index).then(v => result.viewPosition_X = v), + table.getViewPosition_Y(index).then(v => result.viewPosition_Y = v), + table.getViewPosition_Z(index).then(v => result.viewPosition_Z = v), + table.getScale(index).then(v => result.scale = v), + table.getOutline_Min_X(index).then(v => result.outline_Min_X = v), + table.getOutline_Min_Y(index).then(v => result.outline_Min_Y = v), + table.getOutline_Max_X(index).then(v => result.outline_Max_X = v), + table.getOutline_Max_Y(index).then(v => result.outline_Max_Y = v), + table.getDetailLevel(index).then(v => result.detailLevel = v), + table.getCameraIndex(index).then(v => result.cameraIndex = v), + table.getFamilyTypeIndex(index).then(v => result.familyTypeIndex = v), + table.getElementIndex(index).then(v => result.elementIndex = v), + ]); + return result; + } +} +exports.View = View; +class ViewTable { + static async createFromDocument(document) { + const entity = await document.entities.getBfast("Vim.View"); + if (!entity) { + return undefined; + } + let table = new ViewTable(); + table.document = document; + table.entityTable = new entityTable_1.EntityTable(entity, document.strings); + return table; + } + getCount() { + return this.entityTable.getCount(); + } + async get(viewIndex) { + return await View.createFromTable(this, viewIndex); + } + async getAll() { + const localTable = await this.entityTable.getLocal(); + let title; + let viewType; + let up_X; + let up_Y; + let up_Z; + let right_X; + let right_Y; + let right_Z; + let origin_X; + let origin_Y; + let origin_Z; + let viewDirection_X; + let viewDirection_Y; + let viewDirection_Z; + let viewPosition_X; + let viewPosition_Y; + let viewPosition_Z; + let scale; + let outline_Min_X; + let outline_Min_Y; + let outline_Max_X; + let outline_Max_Y; + let detailLevel; + let cameraIndex; + let familyTypeIndex; + let elementIndex; + await Promise.all([ + (async () => { title = (await localTable.getStringArray("string:Title")); })(), + (async () => { viewType = (await localTable.getStringArray("string:ViewType")); })(), + (async () => { up_X = (await localTable.getNumberArray("double:Up.X")); })(), + (async () => { up_Y = (await localTable.getNumberArray("double:Up.Y")); })(), + (async () => { up_Z = (await localTable.getNumberArray("double:Up.Z")); })(), + (async () => { right_X = (await localTable.getNumberArray("double:Right.X")); })(), + (async () => { right_Y = (await localTable.getNumberArray("double:Right.Y")); })(), + (async () => { right_Z = (await localTable.getNumberArray("double:Right.Z")); })(), + (async () => { origin_X = (await localTable.getNumberArray("double:Origin.X")); })(), + (async () => { origin_Y = (await localTable.getNumberArray("double:Origin.Y")); })(), + (async () => { origin_Z = (await localTable.getNumberArray("double:Origin.Z")); })(), + (async () => { viewDirection_X = (await localTable.getNumberArray("double:ViewDirection.X")); })(), + (async () => { viewDirection_Y = (await localTable.getNumberArray("double:ViewDirection.Y")); })(), + (async () => { viewDirection_Z = (await localTable.getNumberArray("double:ViewDirection.Z")); })(), + (async () => { viewPosition_X = (await localTable.getNumberArray("double:ViewPosition.X")); })(), + (async () => { viewPosition_Y = (await localTable.getNumberArray("double:ViewPosition.Y")); })(), + (async () => { viewPosition_Z = (await localTable.getNumberArray("double:ViewPosition.Z")); })(), + (async () => { scale = (await localTable.getNumberArray("double:Scale")); })(), + (async () => { outline_Min_X = (await localTable.getNumberArray("double:Outline.Min.X")); })(), + (async () => { outline_Min_Y = (await localTable.getNumberArray("double:Outline.Min.Y")); })(), + (async () => { outline_Max_X = (await localTable.getNumberArray("double:Outline.Max.X")); })(), + (async () => { outline_Max_Y = (await localTable.getNumberArray("double:Outline.Max.Y")); })(), + (async () => { detailLevel = (await localTable.getNumberArray("int:DetailLevel")); })(), + (async () => { cameraIndex = (await localTable.getNumberArray("index:Vim.Camera:Camera")); })(), + (async () => { familyTypeIndex = (await localTable.getNumberArray("index:Vim.FamilyType:FamilyType")); })(), + (async () => { elementIndex = (await localTable.getNumberArray("index:Vim.Element:Element")); })(), + ]); + let view = []; + for (let i = 0; i < title.length; i++) { + view.push({ + index: i, + title: title ? title[i] : undefined, + viewType: viewType ? viewType[i] : undefined, + up_X: up_X ? up_X[i] : undefined, + up_Y: up_Y ? up_Y[i] : undefined, + up_Z: up_Z ? up_Z[i] : undefined, + right_X: right_X ? right_X[i] : undefined, + right_Y: right_Y ? right_Y[i] : undefined, + right_Z: right_Z ? right_Z[i] : undefined, + origin_X: origin_X ? origin_X[i] : undefined, + origin_Y: origin_Y ? origin_Y[i] : undefined, + origin_Z: origin_Z ? origin_Z[i] : undefined, + viewDirection_X: viewDirection_X ? viewDirection_X[i] : undefined, + viewDirection_Y: viewDirection_Y ? viewDirection_Y[i] : undefined, + viewDirection_Z: viewDirection_Z ? viewDirection_Z[i] : undefined, + viewPosition_X: viewPosition_X ? viewPosition_X[i] : undefined, + viewPosition_Y: viewPosition_Y ? viewPosition_Y[i] : undefined, + viewPosition_Z: viewPosition_Z ? viewPosition_Z[i] : undefined, + scale: scale ? scale[i] : undefined, + outline_Min_X: outline_Min_X ? outline_Min_X[i] : undefined, + outline_Min_Y: outline_Min_Y ? outline_Min_Y[i] : undefined, + outline_Max_X: outline_Max_X ? outline_Max_X[i] : undefined, + outline_Max_Y: outline_Max_Y ? outline_Max_Y[i] : undefined, + detailLevel: detailLevel ? detailLevel[i] : undefined, + cameraIndex: cameraIndex ? cameraIndex[i] : undefined, + familyTypeIndex: familyTypeIndex ? familyTypeIndex[i] : undefined, + elementIndex: elementIndex ? elementIndex[i] : undefined + }); + } + return view; + } + async getTitle(viewIndex) { + return (await this.entityTable.getString(viewIndex, "string:Title")); + } + async getAllTitle() { + return (await this.entityTable.getStringArray("string:Title")); + } + async getViewType(viewIndex) { + return (await this.entityTable.getString(viewIndex, "string:ViewType")); + } + async getAllViewType() { + return (await this.entityTable.getStringArray("string:ViewType")); + } + async getUp_X(viewIndex) { + return (await this.entityTable.getNumber(viewIndex, "double:Up.X")); + } + async getAllUp_X() { + return (await this.entityTable.getNumberArray("double:Up.X")); + } + async getUp_Y(viewIndex) { + return (await this.entityTable.getNumber(viewIndex, "double:Up.Y")); + } + async getAllUp_Y() { + return (await this.entityTable.getNumberArray("double:Up.Y")); + } + async getUp_Z(viewIndex) { + return (await this.entityTable.getNumber(viewIndex, "double:Up.Z")); + } + async getAllUp_Z() { + return (await this.entityTable.getNumberArray("double:Up.Z")); + } + async getRight_X(viewIndex) { + return (await this.entityTable.getNumber(viewIndex, "double:Right.X")); + } + async getAllRight_X() { + return (await this.entityTable.getNumberArray("double:Right.X")); + } + async getRight_Y(viewIndex) { + return (await this.entityTable.getNumber(viewIndex, "double:Right.Y")); + } + async getAllRight_Y() { + return (await this.entityTable.getNumberArray("double:Right.Y")); + } + async getRight_Z(viewIndex) { + return (await this.entityTable.getNumber(viewIndex, "double:Right.Z")); + } + async getAllRight_Z() { + return (await this.entityTable.getNumberArray("double:Right.Z")); + } + async getOrigin_X(viewIndex) { + return (await this.entityTable.getNumber(viewIndex, "double:Origin.X")); + } + async getAllOrigin_X() { + return (await this.entityTable.getNumberArray("double:Origin.X")); + } + async getOrigin_Y(viewIndex) { + return (await this.entityTable.getNumber(viewIndex, "double:Origin.Y")); + } + async getAllOrigin_Y() { + return (await this.entityTable.getNumberArray("double:Origin.Y")); + } + async getOrigin_Z(viewIndex) { + return (await this.entityTable.getNumber(viewIndex, "double:Origin.Z")); + } + async getAllOrigin_Z() { + return (await this.entityTable.getNumberArray("double:Origin.Z")); + } + async getViewDirection_X(viewIndex) { + return (await this.entityTable.getNumber(viewIndex, "double:ViewDirection.X")); + } + async getAllViewDirection_X() { + return (await this.entityTable.getNumberArray("double:ViewDirection.X")); + } + async getViewDirection_Y(viewIndex) { + return (await this.entityTable.getNumber(viewIndex, "double:ViewDirection.Y")); + } + async getAllViewDirection_Y() { + return (await this.entityTable.getNumberArray("double:ViewDirection.Y")); + } + async getViewDirection_Z(viewIndex) { + return (await this.entityTable.getNumber(viewIndex, "double:ViewDirection.Z")); + } + async getAllViewDirection_Z() { + return (await this.entityTable.getNumberArray("double:ViewDirection.Z")); + } + async getViewPosition_X(viewIndex) { + return (await this.entityTable.getNumber(viewIndex, "double:ViewPosition.X")); + } + async getAllViewPosition_X() { + return (await this.entityTable.getNumberArray("double:ViewPosition.X")); + } + async getViewPosition_Y(viewIndex) { + return (await this.entityTable.getNumber(viewIndex, "double:ViewPosition.Y")); + } + async getAllViewPosition_Y() { + return (await this.entityTable.getNumberArray("double:ViewPosition.Y")); + } + async getViewPosition_Z(viewIndex) { + return (await this.entityTable.getNumber(viewIndex, "double:ViewPosition.Z")); + } + async getAllViewPosition_Z() { + return (await this.entityTable.getNumberArray("double:ViewPosition.Z")); + } + async getScale(viewIndex) { + return (await this.entityTable.getNumber(viewIndex, "double:Scale")); + } + async getAllScale() { + return (await this.entityTable.getNumberArray("double:Scale")); + } + async getOutline_Min_X(viewIndex) { + return (await this.entityTable.getNumber(viewIndex, "double:Outline.Min.X")); + } + async getAllOutline_Min_X() { + return (await this.entityTable.getNumberArray("double:Outline.Min.X")); + } + async getOutline_Min_Y(viewIndex) { + return (await this.entityTable.getNumber(viewIndex, "double:Outline.Min.Y")); + } + async getAllOutline_Min_Y() { + return (await this.entityTable.getNumberArray("double:Outline.Min.Y")); + } + async getOutline_Max_X(viewIndex) { + return (await this.entityTable.getNumber(viewIndex, "double:Outline.Max.X")); + } + async getAllOutline_Max_X() { + return (await this.entityTable.getNumberArray("double:Outline.Max.X")); + } + async getOutline_Max_Y(viewIndex) { + return (await this.entityTable.getNumber(viewIndex, "double:Outline.Max.Y")); + } + async getAllOutline_Max_Y() { + return (await this.entityTable.getNumberArray("double:Outline.Max.Y")); + } + async getDetailLevel(viewIndex) { + return (await this.entityTable.getNumber(viewIndex, "int:DetailLevel")); + } + async getAllDetailLevel() { + return (await this.entityTable.getNumberArray("int:DetailLevel")); + } + async getCameraIndex(viewIndex) { + return await this.entityTable.getNumber(viewIndex, "index:Vim.Camera:Camera"); + } + async getAllCameraIndex() { + return await this.entityTable.getNumberArray("index:Vim.Camera:Camera"); + } + async getCamera(viewIndex) { + const index = await this.getCameraIndex(viewIndex); + if (index === undefined) { + return undefined; + } + return await this.document.camera?.get(index); + } + async getFamilyTypeIndex(viewIndex) { + return await this.entityTable.getNumber(viewIndex, "index:Vim.FamilyType:FamilyType"); + } + async getAllFamilyTypeIndex() { + return await this.entityTable.getNumberArray("index:Vim.FamilyType:FamilyType"); + } + async getFamilyType(viewIndex) { + const index = await this.getFamilyTypeIndex(viewIndex); + if (index === undefined) { + return undefined; + } + return await this.document.familyType?.get(index); + } + async getElementIndex(viewIndex) { + return await this.entityTable.getNumber(viewIndex, "index:Vim.Element:Element"); + } + async getAllElementIndex() { + return await this.entityTable.getNumberArray("index:Vim.Element:Element"); + } + async getElement(viewIndex) { + const index = await this.getElementIndex(viewIndex); + if (index === undefined) { + return undefined; + } + return await this.document.element?.get(index); + } +} +exports.ViewTable = ViewTable; +class ElementInView { + static async createFromTable(table, index) { + let result = new ElementInView(); + result.index = index; + await Promise.all([ + table.getViewIndex(index).then(v => result.viewIndex = v), + table.getElementIndex(index).then(v => result.elementIndex = v), + ]); + return result; + } +} +exports.ElementInView = ElementInView; +class ElementInViewTable { + static async createFromDocument(document) { + const entity = await document.entities.getBfast("Vim.ElementInView"); + if (!entity) { + return undefined; + } + let table = new ElementInViewTable(); + table.document = document; + table.entityTable = new entityTable_1.EntityTable(entity, document.strings); + return table; + } + getCount() { + return this.entityTable.getCount(); + } + async get(elementInViewIndex) { + return await ElementInView.createFromTable(this, elementInViewIndex); + } + async getAll() { + const localTable = await this.entityTable.getLocal(); + let viewIndex; + let elementIndex; + await Promise.all([ + (async () => { viewIndex = (await localTable.getNumberArray("index:Vim.View:View")); })(), + (async () => { elementIndex = (await localTable.getNumberArray("index:Vim.Element:Element")); })(), + ]); + let elementInView = []; + for (let i = 0; i < viewIndex.length; i++) { + elementInView.push({ + index: i, + viewIndex: viewIndex ? viewIndex[i] : undefined, + elementIndex: elementIndex ? elementIndex[i] : undefined + }); + } + return elementInView; + } + async getViewIndex(elementInViewIndex) { + return await this.entityTable.getNumber(elementInViewIndex, "index:Vim.View:View"); + } + async getAllViewIndex() { + return await this.entityTable.getNumberArray("index:Vim.View:View"); + } + async getView(elementInViewIndex) { + const index = await this.getViewIndex(elementInViewIndex); + if (index === undefined) { + return undefined; + } + return await this.document.view?.get(index); + } + async getElementIndex(elementInViewIndex) { + return await this.entityTable.getNumber(elementInViewIndex, "index:Vim.Element:Element"); + } + async getAllElementIndex() { + return await this.entityTable.getNumberArray("index:Vim.Element:Element"); + } + async getElement(elementInViewIndex) { + const index = await this.getElementIndex(elementInViewIndex); + if (index === undefined) { + return undefined; + } + return await this.document.element?.get(index); + } +} +exports.ElementInViewTable = ElementInViewTable; +class ShapeInView { + static async createFromTable(table, index) { + let result = new ShapeInView(); + result.index = index; + await Promise.all([ + table.getShapeIndex(index).then(v => result.shapeIndex = v), + table.getViewIndex(index).then(v => result.viewIndex = v), + ]); + return result; + } +} +exports.ShapeInView = ShapeInView; +class ShapeInViewTable { + static async createFromDocument(document) { + const entity = await document.entities.getBfast("Vim.ShapeInView"); + if (!entity) { + return undefined; + } + let table = new ShapeInViewTable(); + table.document = document; + table.entityTable = new entityTable_1.EntityTable(entity, document.strings); + return table; + } + getCount() { + return this.entityTable.getCount(); + } + async get(shapeInViewIndex) { + return await ShapeInView.createFromTable(this, shapeInViewIndex); + } + async getAll() { + const localTable = await this.entityTable.getLocal(); + let shapeIndex; + let viewIndex; + await Promise.all([ + (async () => { shapeIndex = (await localTable.getNumberArray("index:Vim.Shape:Shape")); })(), + (async () => { viewIndex = (await localTable.getNumberArray("index:Vim.View:View")); })(), + ]); + let shapeInView = []; + for (let i = 0; i < shapeIndex.length; i++) { + shapeInView.push({ + index: i, + shapeIndex: shapeIndex ? shapeIndex[i] : undefined, + viewIndex: viewIndex ? viewIndex[i] : undefined + }); + } + return shapeInView; + } + async getShapeIndex(shapeInViewIndex) { + return await this.entityTable.getNumber(shapeInViewIndex, "index:Vim.Shape:Shape"); + } + async getAllShapeIndex() { + return await this.entityTable.getNumberArray("index:Vim.Shape:Shape"); + } + async getShape(shapeInViewIndex) { + const index = await this.getShapeIndex(shapeInViewIndex); + if (index === undefined) { + return undefined; + } + return await this.document.shape?.get(index); + } + async getViewIndex(shapeInViewIndex) { + return await this.entityTable.getNumber(shapeInViewIndex, "index:Vim.View:View"); + } + async getAllViewIndex() { + return await this.entityTable.getNumberArray("index:Vim.View:View"); + } + async getView(shapeInViewIndex) { + const index = await this.getViewIndex(shapeInViewIndex); + if (index === undefined) { + return undefined; + } + return await this.document.view?.get(index); + } +} +exports.ShapeInViewTable = ShapeInViewTable; +class AssetInView { + static async createFromTable(table, index) { + let result = new AssetInView(); + result.index = index; + await Promise.all([ + table.getAssetIndex(index).then(v => result.assetIndex = v), + table.getViewIndex(index).then(v => result.viewIndex = v), + ]); + return result; + } +} +exports.AssetInView = AssetInView; +class AssetInViewTable { + static async createFromDocument(document) { + const entity = await document.entities.getBfast("Vim.AssetInView"); + if (!entity) { + return undefined; + } + let table = new AssetInViewTable(); + table.document = document; + table.entityTable = new entityTable_1.EntityTable(entity, document.strings); + return table; + } + getCount() { + return this.entityTable.getCount(); + } + async get(assetInViewIndex) { + return await AssetInView.createFromTable(this, assetInViewIndex); + } + async getAll() { + const localTable = await this.entityTable.getLocal(); + let assetIndex; + let viewIndex; + await Promise.all([ + (async () => { assetIndex = (await localTable.getNumberArray("index:Vim.Asset:Asset")); })(), + (async () => { viewIndex = (await localTable.getNumberArray("index:Vim.View:View")); })(), + ]); + let assetInView = []; + for (let i = 0; i < assetIndex.length; i++) { + assetInView.push({ + index: i, + assetIndex: assetIndex ? assetIndex[i] : undefined, + viewIndex: viewIndex ? viewIndex[i] : undefined + }); + } + return assetInView; + } + async getAssetIndex(assetInViewIndex) { + return await this.entityTable.getNumber(assetInViewIndex, "index:Vim.Asset:Asset"); + } + async getAllAssetIndex() { + return await this.entityTable.getNumberArray("index:Vim.Asset:Asset"); + } + async getAsset(assetInViewIndex) { + const index = await this.getAssetIndex(assetInViewIndex); + if (index === undefined) { + return undefined; + } + return await this.document.asset?.get(index); + } + async getViewIndex(assetInViewIndex) { + return await this.entityTable.getNumber(assetInViewIndex, "index:Vim.View:View"); + } + async getAllViewIndex() { + return await this.entityTable.getNumberArray("index:Vim.View:View"); + } + async getView(assetInViewIndex) { + const index = await this.getViewIndex(assetInViewIndex); + if (index === undefined) { + return undefined; + } + return await this.document.view?.get(index); + } +} +exports.AssetInViewTable = AssetInViewTable; +class AssetInViewSheet { + static async createFromTable(table, index) { + let result = new AssetInViewSheet(); + result.index = index; + await Promise.all([ + table.getAssetIndex(index).then(v => result.assetIndex = v), + table.getViewSheetIndex(index).then(v => result.viewSheetIndex = v), + ]); + return result; + } +} +exports.AssetInViewSheet = AssetInViewSheet; +class AssetInViewSheetTable { + static async createFromDocument(document) { + const entity = await document.entities.getBfast("Vim.AssetInViewSheet"); + if (!entity) { + return undefined; + } + let table = new AssetInViewSheetTable(); + table.document = document; + table.entityTable = new entityTable_1.EntityTable(entity, document.strings); + return table; + } + getCount() { + return this.entityTable.getCount(); + } + async get(assetInViewSheetIndex) { + return await AssetInViewSheet.createFromTable(this, assetInViewSheetIndex); + } + async getAll() { + const localTable = await this.entityTable.getLocal(); + let assetIndex; + let viewSheetIndex; + await Promise.all([ + (async () => { assetIndex = (await localTable.getNumberArray("index:Vim.Asset:Asset")); })(), + (async () => { viewSheetIndex = (await localTable.getNumberArray("index:Vim.ViewSheet:ViewSheet")); })(), + ]); + let assetInViewSheet = []; + for (let i = 0; i < assetIndex.length; i++) { + assetInViewSheet.push({ + index: i, + assetIndex: assetIndex ? assetIndex[i] : undefined, + viewSheetIndex: viewSheetIndex ? viewSheetIndex[i] : undefined + }); + } + return assetInViewSheet; + } + async getAssetIndex(assetInViewSheetIndex) { + return await this.entityTable.getNumber(assetInViewSheetIndex, "index:Vim.Asset:Asset"); + } + async getAllAssetIndex() { + return await this.entityTable.getNumberArray("index:Vim.Asset:Asset"); + } + async getAsset(assetInViewSheetIndex) { + const index = await this.getAssetIndex(assetInViewSheetIndex); + if (index === undefined) { + return undefined; + } + return await this.document.asset?.get(index); + } + async getViewSheetIndex(assetInViewSheetIndex) { + return await this.entityTable.getNumber(assetInViewSheetIndex, "index:Vim.ViewSheet:ViewSheet"); + } + async getAllViewSheetIndex() { + return await this.entityTable.getNumberArray("index:Vim.ViewSheet:ViewSheet"); + } + async getViewSheet(assetInViewSheetIndex) { + const index = await this.getViewSheetIndex(assetInViewSheetIndex); + if (index === undefined) { + return undefined; + } + return await this.document.viewSheet?.get(index); + } +} +exports.AssetInViewSheetTable = AssetInViewSheetTable; +class LevelInView { + static async createFromTable(table, index) { + let result = new LevelInView(); + result.index = index; + await Promise.all([ + table.getExtents_Min_X(index).then(v => result.extents_Min_X = v), + table.getExtents_Min_Y(index).then(v => result.extents_Min_Y = v), + table.getExtents_Min_Z(index).then(v => result.extents_Min_Z = v), + table.getExtents_Max_X(index).then(v => result.extents_Max_X = v), + table.getExtents_Max_Y(index).then(v => result.extents_Max_Y = v), + table.getExtents_Max_Z(index).then(v => result.extents_Max_Z = v), + table.getLevelIndex(index).then(v => result.levelIndex = v), + table.getViewIndex(index).then(v => result.viewIndex = v), + ]); + return result; + } +} +exports.LevelInView = LevelInView; +class LevelInViewTable { + static async createFromDocument(document) { + const entity = await document.entities.getBfast("Vim.LevelInView"); + if (!entity) { + return undefined; + } + let table = new LevelInViewTable(); + table.document = document; + table.entityTable = new entityTable_1.EntityTable(entity, document.strings); + return table; + } + getCount() { + return this.entityTable.getCount(); + } + async get(levelInViewIndex) { + return await LevelInView.createFromTable(this, levelInViewIndex); + } + async getAll() { + const localTable = await this.entityTable.getLocal(); + let extents_Min_X; + let extents_Min_Y; + let extents_Min_Z; + let extents_Max_X; + let extents_Max_Y; + let extents_Max_Z; + let levelIndex; + let viewIndex; + await Promise.all([ + (async () => { extents_Min_X = (await localTable.getNumberArray("double:Extents.Min.X")); })(), + (async () => { extents_Min_Y = (await localTable.getNumberArray("double:Extents.Min.Y")); })(), + (async () => { extents_Min_Z = (await localTable.getNumberArray("double:Extents.Min.Z")); })(), + (async () => { extents_Max_X = (await localTable.getNumberArray("double:Extents.Max.X")); })(), + (async () => { extents_Max_Y = (await localTable.getNumberArray("double:Extents.Max.Y")); })(), + (async () => { extents_Max_Z = (await localTable.getNumberArray("double:Extents.Max.Z")); })(), + (async () => { levelIndex = (await localTable.getNumberArray("index:Vim.Level:Level")); })(), + (async () => { viewIndex = (await localTable.getNumberArray("index:Vim.View:View")); })(), + ]); + let levelInView = []; + for (let i = 0; i < extents_Min_X.length; i++) { + levelInView.push({ + index: i, + extents_Min_X: extents_Min_X ? extents_Min_X[i] : undefined, + extents_Min_Y: extents_Min_Y ? extents_Min_Y[i] : undefined, + extents_Min_Z: extents_Min_Z ? extents_Min_Z[i] : undefined, + extents_Max_X: extents_Max_X ? extents_Max_X[i] : undefined, + extents_Max_Y: extents_Max_Y ? extents_Max_Y[i] : undefined, + extents_Max_Z: extents_Max_Z ? extents_Max_Z[i] : undefined, + levelIndex: levelIndex ? levelIndex[i] : undefined, + viewIndex: viewIndex ? viewIndex[i] : undefined + }); + } + return levelInView; + } + async getExtents_Min_X(levelInViewIndex) { + return (await this.entityTable.getNumber(levelInViewIndex, "double:Extents.Min.X")); + } + async getAllExtents_Min_X() { + return (await this.entityTable.getNumberArray("double:Extents.Min.X")); + } + async getExtents_Min_Y(levelInViewIndex) { + return (await this.entityTable.getNumber(levelInViewIndex, "double:Extents.Min.Y")); + } + async getAllExtents_Min_Y() { + return (await this.entityTable.getNumberArray("double:Extents.Min.Y")); + } + async getExtents_Min_Z(levelInViewIndex) { + return (await this.entityTable.getNumber(levelInViewIndex, "double:Extents.Min.Z")); + } + async getAllExtents_Min_Z() { + return (await this.entityTable.getNumberArray("double:Extents.Min.Z")); + } + async getExtents_Max_X(levelInViewIndex) { + return (await this.entityTable.getNumber(levelInViewIndex, "double:Extents.Max.X")); + } + async getAllExtents_Max_X() { + return (await this.entityTable.getNumberArray("double:Extents.Max.X")); + } + async getExtents_Max_Y(levelInViewIndex) { + return (await this.entityTable.getNumber(levelInViewIndex, "double:Extents.Max.Y")); + } + async getAllExtents_Max_Y() { + return (await this.entityTable.getNumberArray("double:Extents.Max.Y")); + } + async getExtents_Max_Z(levelInViewIndex) { + return (await this.entityTable.getNumber(levelInViewIndex, "double:Extents.Max.Z")); + } + async getAllExtents_Max_Z() { + return (await this.entityTable.getNumberArray("double:Extents.Max.Z")); + } + async getLevelIndex(levelInViewIndex) { + return await this.entityTable.getNumber(levelInViewIndex, "index:Vim.Level:Level"); + } + async getAllLevelIndex() { + return await this.entityTable.getNumberArray("index:Vim.Level:Level"); + } + async getLevel(levelInViewIndex) { + const index = await this.getLevelIndex(levelInViewIndex); + if (index === undefined) { + return undefined; + } + return await this.document.level?.get(index); + } + async getViewIndex(levelInViewIndex) { + return await this.entityTable.getNumber(levelInViewIndex, "index:Vim.View:View"); + } + async getAllViewIndex() { + return await this.entityTable.getNumberArray("index:Vim.View:View"); + } + async getView(levelInViewIndex) { + const index = await this.getViewIndex(levelInViewIndex); + if (index === undefined) { + return undefined; + } + return await this.document.view?.get(index); + } +} +exports.LevelInViewTable = LevelInViewTable; +class Camera { + static async createFromTable(table, index) { + let result = new Camera(); + result.index = index; + await Promise.all([ + table.getId(index).then(v => result.id = v), + table.getIsPerspective(index).then(v => result.isPerspective = v), + table.getVerticalExtent(index).then(v => result.verticalExtent = v), + table.getHorizontalExtent(index).then(v => result.horizontalExtent = v), + table.getFarDistance(index).then(v => result.farDistance = v), + table.getNearDistance(index).then(v => result.nearDistance = v), + table.getTargetDistance(index).then(v => result.targetDistance = v), + table.getRightOffset(index).then(v => result.rightOffset = v), + table.getUpOffset(index).then(v => result.upOffset = v), + ]); + return result; + } +} +exports.Camera = Camera; +class CameraTable { + static async createFromDocument(document) { + const entity = await document.entities.getBfast("Vim.Camera"); + if (!entity) { + return undefined; + } + let table = new CameraTable(); + table.entityTable = new entityTable_1.EntityTable(entity, document.strings); + return table; + } + getCount() { + return this.entityTable.getCount(); + } + async get(cameraIndex) { + return await Camera.createFromTable(this, cameraIndex); + } + async getAll() { + const localTable = await this.entityTable.getLocal(); + let id; + let isPerspective; + let verticalExtent; + let horizontalExtent; + let farDistance; + let nearDistance; + let targetDistance; + let rightOffset; + let upOffset; + await Promise.all([ + (async () => { id = (await localTable.getNumberArray("int:Id")); })(), + (async () => { isPerspective = (await localTable.getNumberArray("int:IsPerspective")); })(), + (async () => { verticalExtent = (await localTable.getNumberArray("double:VerticalExtent")); })(), + (async () => { horizontalExtent = (await localTable.getNumberArray("double:HorizontalExtent")); })(), + (async () => { farDistance = (await localTable.getNumberArray("double:FarDistance")); })(), + (async () => { nearDistance = (await localTable.getNumberArray("double:NearDistance")); })(), + (async () => { targetDistance = (await localTable.getNumberArray("double:TargetDistance")); })(), + (async () => { rightOffset = (await localTable.getNumberArray("double:RightOffset")); })(), + (async () => { upOffset = (await localTable.getNumberArray("double:UpOffset")); })(), + ]); + let camera = []; + for (let i = 0; i < id.length; i++) { + camera.push({ + index: i, + id: id ? id[i] : undefined, + isPerspective: isPerspective ? isPerspective[i] : undefined, + verticalExtent: verticalExtent ? verticalExtent[i] : undefined, + horizontalExtent: horizontalExtent ? horizontalExtent[i] : undefined, + farDistance: farDistance ? farDistance[i] : undefined, + nearDistance: nearDistance ? nearDistance[i] : undefined, + targetDistance: targetDistance ? targetDistance[i] : undefined, + rightOffset: rightOffset ? rightOffset[i] : undefined, + upOffset: upOffset ? upOffset[i] : undefined + }); + } + return camera; + } + async getId(cameraIndex) { + return (await this.entityTable.getNumber(cameraIndex, "int:Id")); + } + async getAllId() { + return (await this.entityTable.getNumberArray("int:Id")); + } + async getIsPerspective(cameraIndex) { + return (await this.entityTable.getNumber(cameraIndex, "int:IsPerspective")); + } + async getAllIsPerspective() { + return (await this.entityTable.getNumberArray("int:IsPerspective")); + } + async getVerticalExtent(cameraIndex) { + return (await this.entityTable.getNumber(cameraIndex, "double:VerticalExtent")); + } + async getAllVerticalExtent() { + return (await this.entityTable.getNumberArray("double:VerticalExtent")); + } + async getHorizontalExtent(cameraIndex) { + return (await this.entityTable.getNumber(cameraIndex, "double:HorizontalExtent")); + } + async getAllHorizontalExtent() { + return (await this.entityTable.getNumberArray("double:HorizontalExtent")); + } + async getFarDistance(cameraIndex) { + return (await this.entityTable.getNumber(cameraIndex, "double:FarDistance")); + } + async getAllFarDistance() { + return (await this.entityTable.getNumberArray("double:FarDistance")); + } + async getNearDistance(cameraIndex) { + return (await this.entityTable.getNumber(cameraIndex, "double:NearDistance")); + } + async getAllNearDistance() { + return (await this.entityTable.getNumberArray("double:NearDistance")); + } + async getTargetDistance(cameraIndex) { + return (await this.entityTable.getNumber(cameraIndex, "double:TargetDistance")); + } + async getAllTargetDistance() { + return (await this.entityTable.getNumberArray("double:TargetDistance")); + } + async getRightOffset(cameraIndex) { + return (await this.entityTable.getNumber(cameraIndex, "double:RightOffset")); + } + async getAllRightOffset() { + return (await this.entityTable.getNumberArray("double:RightOffset")); + } + async getUpOffset(cameraIndex) { + return (await this.entityTable.getNumber(cameraIndex, "double:UpOffset")); + } + async getAllUpOffset() { + return (await this.entityTable.getNumberArray("double:UpOffset")); + } +} +exports.CameraTable = CameraTable; +class Material { + static async createFromTable(table, index) { + let result = new Material(); + result.index = index; + await Promise.all([ + table.getName(index).then(v => result.name = v), + table.getMaterialCategory(index).then(v => result.materialCategory = v), + table.getColor_X(index).then(v => result.color_X = v), + table.getColor_Y(index).then(v => result.color_Y = v), + table.getColor_Z(index).then(v => result.color_Z = v), + table.getColorUvScaling_X(index).then(v => result.colorUvScaling_X = v), + table.getColorUvScaling_Y(index).then(v => result.colorUvScaling_Y = v), + table.getColorUvOffset_X(index).then(v => result.colorUvOffset_X = v), + table.getColorUvOffset_Y(index).then(v => result.colorUvOffset_Y = v), + table.getNormalUvScaling_X(index).then(v => result.normalUvScaling_X = v), + table.getNormalUvScaling_Y(index).then(v => result.normalUvScaling_Y = v), + table.getNormalUvOffset_X(index).then(v => result.normalUvOffset_X = v), + table.getNormalUvOffset_Y(index).then(v => result.normalUvOffset_Y = v), + table.getNormalAmount(index).then(v => result.normalAmount = v), + table.getGlossiness(index).then(v => result.glossiness = v), + table.getSmoothness(index).then(v => result.smoothness = v), + table.getTransparency(index).then(v => result.transparency = v), + table.getColorTextureFileIndex(index).then(v => result.colorTextureFileIndex = v), + table.getNormalTextureFileIndex(index).then(v => result.normalTextureFileIndex = v), + table.getElementIndex(index).then(v => result.elementIndex = v), + ]); + return result; + } +} +exports.Material = Material; +class MaterialTable { + static async createFromDocument(document) { + const entity = await document.entities.getBfast("Vim.Material"); + if (!entity) { + return undefined; + } + let table = new MaterialTable(); + table.document = document; + table.entityTable = new entityTable_1.EntityTable(entity, document.strings); + return table; + } + getCount() { + return this.entityTable.getCount(); + } + async get(materialIndex) { + return await Material.createFromTable(this, materialIndex); + } + async getAll() { + const localTable = await this.entityTable.getLocal(); + let name; + let materialCategory; + let color_X; + let color_Y; + let color_Z; + let colorUvScaling_X; + let colorUvScaling_Y; + let colorUvOffset_X; + let colorUvOffset_Y; + let normalUvScaling_X; + let normalUvScaling_Y; + let normalUvOffset_X; + let normalUvOffset_Y; + let normalAmount; + let glossiness; + let smoothness; + let transparency; + let colorTextureFileIndex; + let normalTextureFileIndex; + let elementIndex; + await Promise.all([ + (async () => { name = (await localTable.getStringArray("string:Name")); })(), + (async () => { materialCategory = (await localTable.getStringArray("string:MaterialCategory")); })(), + (async () => { color_X = (await localTable.getNumberArray("double:Color.X")); })(), + (async () => { color_Y = (await localTable.getNumberArray("double:Color.Y")); })(), + (async () => { color_Z = (await localTable.getNumberArray("double:Color.Z")); })(), + (async () => { colorUvScaling_X = (await localTable.getNumberArray("double:ColorUvScaling.X")); })(), + (async () => { colorUvScaling_Y = (await localTable.getNumberArray("double:ColorUvScaling.Y")); })(), + (async () => { colorUvOffset_X = (await localTable.getNumberArray("double:ColorUvOffset.X")); })(), + (async () => { colorUvOffset_Y = (await localTable.getNumberArray("double:ColorUvOffset.Y")); })(), + (async () => { normalUvScaling_X = (await localTable.getNumberArray("double:NormalUvScaling.X")); })(), + (async () => { normalUvScaling_Y = (await localTable.getNumberArray("double:NormalUvScaling.Y")); })(), + (async () => { normalUvOffset_X = (await localTable.getNumberArray("double:NormalUvOffset.X")); })(), + (async () => { normalUvOffset_Y = (await localTable.getNumberArray("double:NormalUvOffset.Y")); })(), + (async () => { normalAmount = (await localTable.getNumberArray("double:NormalAmount")); })(), + (async () => { glossiness = (await localTable.getNumberArray("double:Glossiness")); })(), + (async () => { smoothness = (await localTable.getNumberArray("double:Smoothness")); })(), + (async () => { transparency = (await localTable.getNumberArray("double:Transparency")); })(), + (async () => { colorTextureFileIndex = (await localTable.getNumberArray("index:Vim.Asset:ColorTextureFile")); })(), + (async () => { normalTextureFileIndex = (await localTable.getNumberArray("index:Vim.Asset:NormalTextureFile")); })(), + (async () => { elementIndex = (await localTable.getNumberArray("index:Vim.Element:Element")); })(), + ]); + let material = []; + for (let i = 0; i < name.length; i++) { + material.push({ + index: i, + name: name ? name[i] : undefined, + materialCategory: materialCategory ? materialCategory[i] : undefined, + color_X: color_X ? color_X[i] : undefined, + color_Y: color_Y ? color_Y[i] : undefined, + color_Z: color_Z ? color_Z[i] : undefined, + colorUvScaling_X: colorUvScaling_X ? colorUvScaling_X[i] : undefined, + colorUvScaling_Y: colorUvScaling_Y ? colorUvScaling_Y[i] : undefined, + colorUvOffset_X: colorUvOffset_X ? colorUvOffset_X[i] : undefined, + colorUvOffset_Y: colorUvOffset_Y ? colorUvOffset_Y[i] : undefined, + normalUvScaling_X: normalUvScaling_X ? normalUvScaling_X[i] : undefined, + normalUvScaling_Y: normalUvScaling_Y ? normalUvScaling_Y[i] : undefined, + normalUvOffset_X: normalUvOffset_X ? normalUvOffset_X[i] : undefined, + normalUvOffset_Y: normalUvOffset_Y ? normalUvOffset_Y[i] : undefined, + normalAmount: normalAmount ? normalAmount[i] : undefined, + glossiness: glossiness ? glossiness[i] : undefined, + smoothness: smoothness ? smoothness[i] : undefined, + transparency: transparency ? transparency[i] : undefined, + colorTextureFileIndex: colorTextureFileIndex ? colorTextureFileIndex[i] : undefined, + normalTextureFileIndex: normalTextureFileIndex ? normalTextureFileIndex[i] : undefined, + elementIndex: elementIndex ? elementIndex[i] : undefined + }); + } + return material; + } + async getName(materialIndex) { + return (await this.entityTable.getString(materialIndex, "string:Name")); + } + async getAllName() { + return (await this.entityTable.getStringArray("string:Name")); + } + async getMaterialCategory(materialIndex) { + return (await this.entityTable.getString(materialIndex, "string:MaterialCategory")); + } + async getAllMaterialCategory() { + return (await this.entityTable.getStringArray("string:MaterialCategory")); + } + async getColor_X(materialIndex) { + return (await this.entityTable.getNumber(materialIndex, "double:Color.X")); + } + async getAllColor_X() { + return (await this.entityTable.getNumberArray("double:Color.X")); + } + async getColor_Y(materialIndex) { + return (await this.entityTable.getNumber(materialIndex, "double:Color.Y")); + } + async getAllColor_Y() { + return (await this.entityTable.getNumberArray("double:Color.Y")); + } + async getColor_Z(materialIndex) { + return (await this.entityTable.getNumber(materialIndex, "double:Color.Z")); + } + async getAllColor_Z() { + return (await this.entityTable.getNumberArray("double:Color.Z")); + } + async getColorUvScaling_X(materialIndex) { + return (await this.entityTable.getNumber(materialIndex, "double:ColorUvScaling.X")); + } + async getAllColorUvScaling_X() { + return (await this.entityTable.getNumberArray("double:ColorUvScaling.X")); + } + async getColorUvScaling_Y(materialIndex) { + return (await this.entityTable.getNumber(materialIndex, "double:ColorUvScaling.Y")); + } + async getAllColorUvScaling_Y() { + return (await this.entityTable.getNumberArray("double:ColorUvScaling.Y")); + } + async getColorUvOffset_X(materialIndex) { + return (await this.entityTable.getNumber(materialIndex, "double:ColorUvOffset.X")); + } + async getAllColorUvOffset_X() { + return (await this.entityTable.getNumberArray("double:ColorUvOffset.X")); + } + async getColorUvOffset_Y(materialIndex) { + return (await this.entityTable.getNumber(materialIndex, "double:ColorUvOffset.Y")); + } + async getAllColorUvOffset_Y() { + return (await this.entityTable.getNumberArray("double:ColorUvOffset.Y")); + } + async getNormalUvScaling_X(materialIndex) { + return (await this.entityTable.getNumber(materialIndex, "double:NormalUvScaling.X")); + } + async getAllNormalUvScaling_X() { + return (await this.entityTable.getNumberArray("double:NormalUvScaling.X")); + } + async getNormalUvScaling_Y(materialIndex) { + return (await this.entityTable.getNumber(materialIndex, "double:NormalUvScaling.Y")); + } + async getAllNormalUvScaling_Y() { + return (await this.entityTable.getNumberArray("double:NormalUvScaling.Y")); + } + async getNormalUvOffset_X(materialIndex) { + return (await this.entityTable.getNumber(materialIndex, "double:NormalUvOffset.X")); + } + async getAllNormalUvOffset_X() { + return (await this.entityTable.getNumberArray("double:NormalUvOffset.X")); + } + async getNormalUvOffset_Y(materialIndex) { + return (await this.entityTable.getNumber(materialIndex, "double:NormalUvOffset.Y")); + } + async getAllNormalUvOffset_Y() { + return (await this.entityTable.getNumberArray("double:NormalUvOffset.Y")); + } + async getNormalAmount(materialIndex) { + return (await this.entityTable.getNumber(materialIndex, "double:NormalAmount")); + } + async getAllNormalAmount() { + return (await this.entityTable.getNumberArray("double:NormalAmount")); + } + async getGlossiness(materialIndex) { + return (await this.entityTable.getNumber(materialIndex, "double:Glossiness")); + } + async getAllGlossiness() { + return (await this.entityTable.getNumberArray("double:Glossiness")); + } + async getSmoothness(materialIndex) { + return (await this.entityTable.getNumber(materialIndex, "double:Smoothness")); + } + async getAllSmoothness() { + return (await this.entityTable.getNumberArray("double:Smoothness")); + } + async getTransparency(materialIndex) { + return (await this.entityTable.getNumber(materialIndex, "double:Transparency")); + } + async getAllTransparency() { + return (await this.entityTable.getNumberArray("double:Transparency")); + } + async getColorTextureFileIndex(materialIndex) { + return await this.entityTable.getNumber(materialIndex, "index:Vim.Asset:ColorTextureFile"); + } + async getAllColorTextureFileIndex() { + return await this.entityTable.getNumberArray("index:Vim.Asset:ColorTextureFile"); + } + async getColorTextureFile(materialIndex) { + const index = await this.getColorTextureFileIndex(materialIndex); + if (index === undefined) { + return undefined; + } + return await this.document.asset?.get(index); + } + async getNormalTextureFileIndex(materialIndex) { + return await this.entityTable.getNumber(materialIndex, "index:Vim.Asset:NormalTextureFile"); + } + async getAllNormalTextureFileIndex() { + return await this.entityTable.getNumberArray("index:Vim.Asset:NormalTextureFile"); + } + async getNormalTextureFile(materialIndex) { + const index = await this.getNormalTextureFileIndex(materialIndex); + if (index === undefined) { + return undefined; + } + return await this.document.asset?.get(index); + } + async getElementIndex(materialIndex) { + return await this.entityTable.getNumber(materialIndex, "index:Vim.Element:Element"); + } + async getAllElementIndex() { + return await this.entityTable.getNumberArray("index:Vim.Element:Element"); + } + async getElement(materialIndex) { + const index = await this.getElementIndex(materialIndex); + if (index === undefined) { + return undefined; + } + return await this.document.element?.get(index); + } +} +exports.MaterialTable = MaterialTable; +class MaterialInElement { + static async createFromTable(table, index) { + let result = new MaterialInElement(); + result.index = index; + await Promise.all([ + table.getArea(index).then(v => result.area = v), + table.getVolume(index).then(v => result.volume = v), + table.getIsPaint(index).then(v => result.isPaint = v), + table.getMaterialIndex(index).then(v => result.materialIndex = v), + table.getElementIndex(index).then(v => result.elementIndex = v), + ]); + return result; + } +} +exports.MaterialInElement = MaterialInElement; +class MaterialInElementTable { + static async createFromDocument(document) { + const entity = await document.entities.getBfast("Vim.MaterialInElement"); + if (!entity) { + return undefined; + } + let table = new MaterialInElementTable(); + table.document = document; + table.entityTable = new entityTable_1.EntityTable(entity, document.strings); + return table; + } + getCount() { + return this.entityTable.getCount(); + } + async get(materialInElementIndex) { + return await MaterialInElement.createFromTable(this, materialInElementIndex); + } + async getAll() { + const localTable = await this.entityTable.getLocal(); + let area; + let volume; + let isPaint; + let materialIndex; + let elementIndex; + await Promise.all([ + (async () => { area = (await localTable.getNumberArray("double:Area")); })(), + (async () => { volume = (await localTable.getNumberArray("double:Volume")); })(), + (async () => { isPaint = (await localTable.getBooleanArray("byte:IsPaint")); })(), + (async () => { materialIndex = (await localTable.getNumberArray("index:Vim.Material:Material")); })(), + (async () => { elementIndex = (await localTable.getNumberArray("index:Vim.Element:Element")); })(), + ]); + let materialInElement = []; + for (let i = 0; i < area.length; i++) { + materialInElement.push({ + index: i, + area: area ? area[i] : undefined, + volume: volume ? volume[i] : undefined, + isPaint: isPaint ? isPaint[i] : undefined, + materialIndex: materialIndex ? materialIndex[i] : undefined, + elementIndex: elementIndex ? elementIndex[i] : undefined + }); + } + return materialInElement; + } + async getArea(materialInElementIndex) { + return (await this.entityTable.getNumber(materialInElementIndex, "double:Area")); + } + async getAllArea() { + return (await this.entityTable.getNumberArray("double:Area")); + } + async getVolume(materialInElementIndex) { + return (await this.entityTable.getNumber(materialInElementIndex, "double:Volume")); + } + async getAllVolume() { + return (await this.entityTable.getNumberArray("double:Volume")); + } + async getIsPaint(materialInElementIndex) { + return (await this.entityTable.getBoolean(materialInElementIndex, "byte:IsPaint")); + } + async getAllIsPaint() { + return (await this.entityTable.getBooleanArray("byte:IsPaint")); + } + async getMaterialIndex(materialInElementIndex) { + return await this.entityTable.getNumber(materialInElementIndex, "index:Vim.Material:Material"); + } + async getAllMaterialIndex() { + return await this.entityTable.getNumberArray("index:Vim.Material:Material"); + } + async getMaterial(materialInElementIndex) { + const index = await this.getMaterialIndex(materialInElementIndex); + if (index === undefined) { + return undefined; + } + return await this.document.material?.get(index); + } + async getElementIndex(materialInElementIndex) { + return await this.entityTable.getNumber(materialInElementIndex, "index:Vim.Element:Element"); + } + async getAllElementIndex() { + return await this.entityTable.getNumberArray("index:Vim.Element:Element"); + } + async getElement(materialInElementIndex) { + const index = await this.getElementIndex(materialInElementIndex); + if (index === undefined) { + return undefined; + } + return await this.document.element?.get(index); + } +} +exports.MaterialInElementTable = MaterialInElementTable; +class CompoundStructureLayer { + static async createFromTable(table, index) { + let result = new CompoundStructureLayer(); + result.index = index; + await Promise.all([ + table.getOrderIndex(index).then(v => result.orderIndex = v), + table.getWidth(index).then(v => result.width = v), + table.getMaterialFunctionAssignment(index).then(v => result.materialFunctionAssignment = v), + table.getMaterialIndex(index).then(v => result.materialIndex = v), + table.getCompoundStructureIndex(index).then(v => result.compoundStructureIndex = v), + ]); + return result; + } +} +exports.CompoundStructureLayer = CompoundStructureLayer; +class CompoundStructureLayerTable { + static async createFromDocument(document) { + const entity = await document.entities.getBfast("Vim.CompoundStructureLayer"); + if (!entity) { + return undefined; + } + let table = new CompoundStructureLayerTable(); + table.document = document; + table.entityTable = new entityTable_1.EntityTable(entity, document.strings); + return table; + } + getCount() { + return this.entityTable.getCount(); + } + async get(compoundStructureLayerIndex) { + return await CompoundStructureLayer.createFromTable(this, compoundStructureLayerIndex); + } + async getAll() { + const localTable = await this.entityTable.getLocal(); + let orderIndex; + let width; + let materialFunctionAssignment; + let materialIndex; + let compoundStructureIndex; + await Promise.all([ + (async () => { orderIndex = (await localTable.getNumberArray("int:OrderIndex")); })(), + (async () => { width = (await localTable.getNumberArray("double:Width")); })(), + (async () => { materialFunctionAssignment = (await localTable.getStringArray("string:MaterialFunctionAssignment")); })(), + (async () => { materialIndex = (await localTable.getNumberArray("index:Vim.Material:Material")); })(), + (async () => { compoundStructureIndex = (await localTable.getNumberArray("index:Vim.CompoundStructure:CompoundStructure")); })(), + ]); + let compoundStructureLayer = []; + for (let i = 0; i < orderIndex.length; i++) { + compoundStructureLayer.push({ + index: i, + orderIndex: orderIndex ? orderIndex[i] : undefined, + width: width ? width[i] : undefined, + materialFunctionAssignment: materialFunctionAssignment ? materialFunctionAssignment[i] : undefined, + materialIndex: materialIndex ? materialIndex[i] : undefined, + compoundStructureIndex: compoundStructureIndex ? compoundStructureIndex[i] : undefined + }); + } + return compoundStructureLayer; + } + async getOrderIndex(compoundStructureLayerIndex) { + return (await this.entityTable.getNumber(compoundStructureLayerIndex, "int:OrderIndex")); + } + async getAllOrderIndex() { + return (await this.entityTable.getNumberArray("int:OrderIndex")); + } + async getWidth(compoundStructureLayerIndex) { + return (await this.entityTable.getNumber(compoundStructureLayerIndex, "double:Width")); + } + async getAllWidth() { + return (await this.entityTable.getNumberArray("double:Width")); + } + async getMaterialFunctionAssignment(compoundStructureLayerIndex) { + return (await this.entityTable.getString(compoundStructureLayerIndex, "string:MaterialFunctionAssignment")); + } + async getAllMaterialFunctionAssignment() { + return (await this.entityTable.getStringArray("string:MaterialFunctionAssignment")); + } + async getMaterialIndex(compoundStructureLayerIndex) { + return await this.entityTable.getNumber(compoundStructureLayerIndex, "index:Vim.Material:Material"); + } + async getAllMaterialIndex() { + return await this.entityTable.getNumberArray("index:Vim.Material:Material"); + } + async getMaterial(compoundStructureLayerIndex) { + const index = await this.getMaterialIndex(compoundStructureLayerIndex); + if (index === undefined) { + return undefined; + } + return await this.document.material?.get(index); + } + async getCompoundStructureIndex(compoundStructureLayerIndex) { + return await this.entityTable.getNumber(compoundStructureLayerIndex, "index:Vim.CompoundStructure:CompoundStructure"); + } + async getAllCompoundStructureIndex() { + return await this.entityTable.getNumberArray("index:Vim.CompoundStructure:CompoundStructure"); + } + async getCompoundStructure(compoundStructureLayerIndex) { + const index = await this.getCompoundStructureIndex(compoundStructureLayerIndex); + if (index === undefined) { + return undefined; + } + return await this.document.compoundStructure?.get(index); + } +} +exports.CompoundStructureLayerTable = CompoundStructureLayerTable; +class CompoundStructure { + static async createFromTable(table, index) { + let result = new CompoundStructure(); + result.index = index; + await Promise.all([ + table.getWidth(index).then(v => result.width = v), + table.getStructuralLayerIndex(index).then(v => result.structuralLayerIndex = v), + ]); + return result; + } +} +exports.CompoundStructure = CompoundStructure; +class CompoundStructureTable { + static async createFromDocument(document) { + const entity = await document.entities.getBfast("Vim.CompoundStructure"); + if (!entity) { + return undefined; + } + let table = new CompoundStructureTable(); + table.document = document; + table.entityTable = new entityTable_1.EntityTable(entity, document.strings); + return table; + } + getCount() { + return this.entityTable.getCount(); + } + async get(compoundStructureIndex) { + return await CompoundStructure.createFromTable(this, compoundStructureIndex); + } + async getAll() { + const localTable = await this.entityTable.getLocal(); + let width; + let structuralLayerIndex; + await Promise.all([ + (async () => { width = (await localTable.getNumberArray("double:Width")); })(), + (async () => { structuralLayerIndex = (await localTable.getNumberArray("index:Vim.CompoundStructureLayer:StructuralLayer")); })(), + ]); + let compoundStructure = []; + for (let i = 0; i < width.length; i++) { + compoundStructure.push({ + index: i, + width: width ? width[i] : undefined, + structuralLayerIndex: structuralLayerIndex ? structuralLayerIndex[i] : undefined + }); + } + return compoundStructure; + } + async getWidth(compoundStructureIndex) { + return (await this.entityTable.getNumber(compoundStructureIndex, "double:Width")); + } + async getAllWidth() { + return (await this.entityTable.getNumberArray("double:Width")); + } + async getStructuralLayerIndex(compoundStructureIndex) { + return await this.entityTable.getNumber(compoundStructureIndex, "index:Vim.CompoundStructureLayer:StructuralLayer"); + } + async getAllStructuralLayerIndex() { + return await this.entityTable.getNumberArray("index:Vim.CompoundStructureLayer:StructuralLayer"); + } + async getStructuralLayer(compoundStructureIndex) { + const index = await this.getStructuralLayerIndex(compoundStructureIndex); + if (index === undefined) { + return undefined; + } + return await this.document.compoundStructureLayer?.get(index); + } +} +exports.CompoundStructureTable = CompoundStructureTable; +class Node { + static async createFromTable(table, index) { + let result = new Node(); + result.index = index; + await Promise.all([ + table.getElementIndex(index).then(v => result.elementIndex = v), + ]); + return result; + } +} +exports.Node = Node; +class NodeTable { + static async createFromDocument(document) { + const entity = await document.entities.getBfast("Vim.Node"); + if (!entity) { + return undefined; + } + let table = new NodeTable(); + table.document = document; + table.entityTable = new entityTable_1.EntityTable(entity, document.strings); + return table; + } + getCount() { + return this.entityTable.getCount(); + } + async get(nodeIndex) { + return await Node.createFromTable(this, nodeIndex); + } + async getAll() { + const localTable = await this.entityTable.getLocal(); + let elementIndex; + await Promise.all([ + (async () => { elementIndex = (await localTable.getNumberArray("index:Vim.Element:Element")); })(), + ]); + let node = []; + for (let i = 0; i < elementIndex.length; i++) { + node.push({ + index: i, + elementIndex: elementIndex ? elementIndex[i] : undefined + }); + } + return node; + } + async getElementIndex(nodeIndex) { + return await this.entityTable.getNumber(nodeIndex, "index:Vim.Element:Element"); + } + async getAllElementIndex() { + return await this.entityTable.getNumberArray("index:Vim.Element:Element"); + } + async getElement(nodeIndex) { + const index = await this.getElementIndex(nodeIndex); + if (index === undefined) { + return undefined; + } + return await this.document.element?.get(index); + } +} +exports.NodeTable = NodeTable; +class Geometry { + static async createFromTable(table, index) { + let result = new Geometry(); + result.index = index; + await Promise.all([ + table.getBox_Min_X(index).then(v => result.box_Min_X = v), + table.getBox_Min_Y(index).then(v => result.box_Min_Y = v), + table.getBox_Min_Z(index).then(v => result.box_Min_Z = v), + table.getBox_Max_X(index).then(v => result.box_Max_X = v), + table.getBox_Max_Y(index).then(v => result.box_Max_Y = v), + table.getBox_Max_Z(index).then(v => result.box_Max_Z = v), + table.getVertexCount(index).then(v => result.vertexCount = v), + table.getFaceCount(index).then(v => result.faceCount = v), + ]); + return result; + } +} +exports.Geometry = Geometry; +class GeometryTable { + static async createFromDocument(document) { + const entity = await document.entities.getBfast("Vim.Geometry"); + if (!entity) { + return undefined; + } + let table = new GeometryTable(); + table.entityTable = new entityTable_1.EntityTable(entity, document.strings); + return table; + } + getCount() { + return this.entityTable.getCount(); + } + async get(geometryIndex) { + return await Geometry.createFromTable(this, geometryIndex); + } + async getAll() { + const localTable = await this.entityTable.getLocal(); + let box_Min_X; + let box_Min_Y; + let box_Min_Z; + let box_Max_X; + let box_Max_Y; + let box_Max_Z; + let vertexCount; + let faceCount; + await Promise.all([ + (async () => { box_Min_X = (await localTable.getNumberArray("float:Box.Min.X")); })(), + (async () => { box_Min_Y = (await localTable.getNumberArray("float:Box.Min.Y")); })(), + (async () => { box_Min_Z = (await localTable.getNumberArray("float:Box.Min.Z")); })(), + (async () => { box_Max_X = (await localTable.getNumberArray("float:Box.Max.X")); })(), + (async () => { box_Max_Y = (await localTable.getNumberArray("float:Box.Max.Y")); })(), + (async () => { box_Max_Z = (await localTable.getNumberArray("float:Box.Max.Z")); })(), + (async () => { vertexCount = (await localTable.getNumberArray("int:VertexCount")); })(), + (async () => { faceCount = (await localTable.getNumberArray("int:FaceCount")); })(), + ]); + let geometry = []; + for (let i = 0; i < box_Min_X.length; i++) { + geometry.push({ + index: i, + box_Min_X: box_Min_X ? box_Min_X[i] : undefined, + box_Min_Y: box_Min_Y ? box_Min_Y[i] : undefined, + box_Min_Z: box_Min_Z ? box_Min_Z[i] : undefined, + box_Max_X: box_Max_X ? box_Max_X[i] : undefined, + box_Max_Y: box_Max_Y ? box_Max_Y[i] : undefined, + box_Max_Z: box_Max_Z ? box_Max_Z[i] : undefined, + vertexCount: vertexCount ? vertexCount[i] : undefined, + faceCount: faceCount ? faceCount[i] : undefined + }); + } + return geometry; + } + async getBox_Min_X(geometryIndex) { + return (await this.entityTable.getNumber(geometryIndex, "float:Box.Min.X")); + } + async getAllBox_Min_X() { + return (await this.entityTable.getNumberArray("float:Box.Min.X")); + } + async getBox_Min_Y(geometryIndex) { + return (await this.entityTable.getNumber(geometryIndex, "float:Box.Min.Y")); + } + async getAllBox_Min_Y() { + return (await this.entityTable.getNumberArray("float:Box.Min.Y")); + } + async getBox_Min_Z(geometryIndex) { + return (await this.entityTable.getNumber(geometryIndex, "float:Box.Min.Z")); + } + async getAllBox_Min_Z() { + return (await this.entityTable.getNumberArray("float:Box.Min.Z")); + } + async getBox_Max_X(geometryIndex) { + return (await this.entityTable.getNumber(geometryIndex, "float:Box.Max.X")); + } + async getAllBox_Max_X() { + return (await this.entityTable.getNumberArray("float:Box.Max.X")); + } + async getBox_Max_Y(geometryIndex) { + return (await this.entityTable.getNumber(geometryIndex, "float:Box.Max.Y")); + } + async getAllBox_Max_Y() { + return (await this.entityTable.getNumberArray("float:Box.Max.Y")); + } + async getBox_Max_Z(geometryIndex) { + return (await this.entityTable.getNumber(geometryIndex, "float:Box.Max.Z")); + } + async getAllBox_Max_Z() { + return (await this.entityTable.getNumberArray("float:Box.Max.Z")); + } + async getVertexCount(geometryIndex) { + return (await this.entityTable.getNumber(geometryIndex, "int:VertexCount")); + } + async getAllVertexCount() { + return (await this.entityTable.getNumberArray("int:VertexCount")); + } + async getFaceCount(geometryIndex) { + return (await this.entityTable.getNumber(geometryIndex, "int:FaceCount")); + } + async getAllFaceCount() { + return (await this.entityTable.getNumberArray("int:FaceCount")); + } +} +exports.GeometryTable = GeometryTable; +class Shape { + static async createFromTable(table, index) { + let result = new Shape(); + result.index = index; + await Promise.all([ + table.getElementIndex(index).then(v => result.elementIndex = v), + ]); + return result; + } +} +exports.Shape = Shape; +class ShapeTable { + static async createFromDocument(document) { + const entity = await document.entities.getBfast("Vim.Shape"); + if (!entity) { + return undefined; + } + let table = new ShapeTable(); + table.document = document; + table.entityTable = new entityTable_1.EntityTable(entity, document.strings); + return table; + } + getCount() { + return this.entityTable.getCount(); + } + async get(shapeIndex) { + return await Shape.createFromTable(this, shapeIndex); + } + async getAll() { + const localTable = await this.entityTable.getLocal(); + let elementIndex; + await Promise.all([ + (async () => { elementIndex = (await localTable.getNumberArray("index:Vim.Element:Element")); })(), + ]); + let shape = []; + for (let i = 0; i < elementIndex.length; i++) { + shape.push({ + index: i, + elementIndex: elementIndex ? elementIndex[i] : undefined + }); + } + return shape; + } + async getElementIndex(shapeIndex) { + return await this.entityTable.getNumber(shapeIndex, "index:Vim.Element:Element"); + } + async getAllElementIndex() { + return await this.entityTable.getNumberArray("index:Vim.Element:Element"); + } + async getElement(shapeIndex) { + const index = await this.getElementIndex(shapeIndex); + if (index === undefined) { + return undefined; + } + return await this.document.element?.get(index); + } +} +exports.ShapeTable = ShapeTable; +class ShapeCollection { + static async createFromTable(table, index) { + let result = new ShapeCollection(); + result.index = index; + await Promise.all([ + table.getElementIndex(index).then(v => result.elementIndex = v), + ]); + return result; + } +} +exports.ShapeCollection = ShapeCollection; +class ShapeCollectionTable { + static async createFromDocument(document) { + const entity = await document.entities.getBfast("Vim.ShapeCollection"); + if (!entity) { + return undefined; + } + let table = new ShapeCollectionTable(); + table.document = document; + table.entityTable = new entityTable_1.EntityTable(entity, document.strings); + return table; + } + getCount() { + return this.entityTable.getCount(); + } + async get(shapeCollectionIndex) { + return await ShapeCollection.createFromTable(this, shapeCollectionIndex); + } + async getAll() { + const localTable = await this.entityTable.getLocal(); + let elementIndex; + await Promise.all([ + (async () => { elementIndex = (await localTable.getNumberArray("index:Vim.Element:Element")); })(), + ]); + let shapeCollection = []; + for (let i = 0; i < elementIndex.length; i++) { + shapeCollection.push({ + index: i, + elementIndex: elementIndex ? elementIndex[i] : undefined + }); + } + return shapeCollection; + } + async getElementIndex(shapeCollectionIndex) { + return await this.entityTable.getNumber(shapeCollectionIndex, "index:Vim.Element:Element"); + } + async getAllElementIndex() { + return await this.entityTable.getNumberArray("index:Vim.Element:Element"); + } + async getElement(shapeCollectionIndex) { + const index = await this.getElementIndex(shapeCollectionIndex); + if (index === undefined) { + return undefined; + } + return await this.document.element?.get(index); + } +} +exports.ShapeCollectionTable = ShapeCollectionTable; +class ShapeInShapeCollection { + static async createFromTable(table, index) { + let result = new ShapeInShapeCollection(); + result.index = index; + await Promise.all([ + table.getShapeIndex(index).then(v => result.shapeIndex = v), + table.getShapeCollectionIndex(index).then(v => result.shapeCollectionIndex = v), + ]); + return result; + } +} +exports.ShapeInShapeCollection = ShapeInShapeCollection; +class ShapeInShapeCollectionTable { + static async createFromDocument(document) { + const entity = await document.entities.getBfast("Vim.ShapeInShapeCollection"); + if (!entity) { + return undefined; + } + let table = new ShapeInShapeCollectionTable(); + table.document = document; + table.entityTable = new entityTable_1.EntityTable(entity, document.strings); + return table; + } + getCount() { + return this.entityTable.getCount(); + } + async get(shapeInShapeCollectionIndex) { + return await ShapeInShapeCollection.createFromTable(this, shapeInShapeCollectionIndex); + } + async getAll() { + const localTable = await this.entityTable.getLocal(); + let shapeIndex; + let shapeCollectionIndex; + await Promise.all([ + (async () => { shapeIndex = (await localTable.getNumberArray("index:Vim.Shape:Shape")); })(), + (async () => { shapeCollectionIndex = (await localTable.getNumberArray("index:Vim.ShapeCollection:ShapeCollection")); })(), + ]); + let shapeInShapeCollection = []; + for (let i = 0; i < shapeIndex.length; i++) { + shapeInShapeCollection.push({ + index: i, + shapeIndex: shapeIndex ? shapeIndex[i] : undefined, + shapeCollectionIndex: shapeCollectionIndex ? shapeCollectionIndex[i] : undefined + }); + } + return shapeInShapeCollection; + } + async getShapeIndex(shapeInShapeCollectionIndex) { + return await this.entityTable.getNumber(shapeInShapeCollectionIndex, "index:Vim.Shape:Shape"); + } + async getAllShapeIndex() { + return await this.entityTable.getNumberArray("index:Vim.Shape:Shape"); + } + async getShape(shapeInShapeCollectionIndex) { + const index = await this.getShapeIndex(shapeInShapeCollectionIndex); + if (index === undefined) { + return undefined; + } + return await this.document.shape?.get(index); + } + async getShapeCollectionIndex(shapeInShapeCollectionIndex) { + return await this.entityTable.getNumber(shapeInShapeCollectionIndex, "index:Vim.ShapeCollection:ShapeCollection"); + } + async getAllShapeCollectionIndex() { + return await this.entityTable.getNumberArray("index:Vim.ShapeCollection:ShapeCollection"); + } + async getShapeCollection(shapeInShapeCollectionIndex) { + const index = await this.getShapeCollectionIndex(shapeInShapeCollectionIndex); + if (index === undefined) { + return undefined; + } + return await this.document.shapeCollection?.get(index); + } +} +exports.ShapeInShapeCollectionTable = ShapeInShapeCollectionTable; +class System { + static async createFromTable(table, index) { + let result = new System(); + result.index = index; + await Promise.all([ + table.getSystemType(index).then(v => result.systemType = v), + table.getFamilyTypeIndex(index).then(v => result.familyTypeIndex = v), + table.getElementIndex(index).then(v => result.elementIndex = v), + ]); + return result; + } +} +exports.System = System; +class SystemTable { + static async createFromDocument(document) { + const entity = await document.entities.getBfast("Vim.System"); + if (!entity) { + return undefined; + } + let table = new SystemTable(); + table.document = document; + table.entityTable = new entityTable_1.EntityTable(entity, document.strings); + return table; + } + getCount() { + return this.entityTable.getCount(); + } + async get(systemIndex) { + return await System.createFromTable(this, systemIndex); + } + async getAll() { + const localTable = await this.entityTable.getLocal(); + let systemType; + let familyTypeIndex; + let elementIndex; + await Promise.all([ + (async () => { systemType = (await localTable.getNumberArray("int:SystemType")); })(), + (async () => { familyTypeIndex = (await localTable.getNumberArray("index:Vim.FamilyType:FamilyType")); })(), + (async () => { elementIndex = (await localTable.getNumberArray("index:Vim.Element:Element")); })(), + ]); + let system = []; + for (let i = 0; i < systemType.length; i++) { + system.push({ + index: i, + systemType: systemType ? systemType[i] : undefined, + familyTypeIndex: familyTypeIndex ? familyTypeIndex[i] : undefined, + elementIndex: elementIndex ? elementIndex[i] : undefined + }); + } + return system; + } + async getSystemType(systemIndex) { + return (await this.entityTable.getNumber(systemIndex, "int:SystemType")); + } + async getAllSystemType() { + return (await this.entityTable.getNumberArray("int:SystemType")); + } + async getFamilyTypeIndex(systemIndex) { + return await this.entityTable.getNumber(systemIndex, "index:Vim.FamilyType:FamilyType"); + } + async getAllFamilyTypeIndex() { + return await this.entityTable.getNumberArray("index:Vim.FamilyType:FamilyType"); + } + async getFamilyType(systemIndex) { + const index = await this.getFamilyTypeIndex(systemIndex); + if (index === undefined) { + return undefined; + } + return await this.document.familyType?.get(index); + } + async getElementIndex(systemIndex) { + return await this.entityTable.getNumber(systemIndex, "index:Vim.Element:Element"); + } + async getAllElementIndex() { + return await this.entityTable.getNumberArray("index:Vim.Element:Element"); + } + async getElement(systemIndex) { + const index = await this.getElementIndex(systemIndex); + if (index === undefined) { + return undefined; + } + return await this.document.element?.get(index); + } +} +exports.SystemTable = SystemTable; +class ElementInSystem { + static async createFromTable(table, index) { + let result = new ElementInSystem(); + result.index = index; + await Promise.all([ + table.getRoles(index).then(v => result.roles = v), + table.getSystemIndex(index).then(v => result.systemIndex = v), + table.getElementIndex(index).then(v => result.elementIndex = v), + ]); + return result; + } +} +exports.ElementInSystem = ElementInSystem; +class ElementInSystemTable { + static async createFromDocument(document) { + const entity = await document.entities.getBfast("Vim.ElementInSystem"); + if (!entity) { + return undefined; + } + let table = new ElementInSystemTable(); + table.document = document; + table.entityTable = new entityTable_1.EntityTable(entity, document.strings); + return table; + } + getCount() { + return this.entityTable.getCount(); + } + async get(elementInSystemIndex) { + return await ElementInSystem.createFromTable(this, elementInSystemIndex); + } + async getAll() { + const localTable = await this.entityTable.getLocal(); + let roles; + let systemIndex; + let elementIndex; + await Promise.all([ + (async () => { roles = (await localTable.getNumberArray("int:Roles")); })(), + (async () => { systemIndex = (await localTable.getNumberArray("index:Vim.System:System")); })(), + (async () => { elementIndex = (await localTable.getNumberArray("index:Vim.Element:Element")); })(), + ]); + let elementInSystem = []; + for (let i = 0; i < roles.length; i++) { + elementInSystem.push({ + index: i, + roles: roles ? roles[i] : undefined, + systemIndex: systemIndex ? systemIndex[i] : undefined, + elementIndex: elementIndex ? elementIndex[i] : undefined + }); + } + return elementInSystem; + } + async getRoles(elementInSystemIndex) { + return (await this.entityTable.getNumber(elementInSystemIndex, "int:Roles")); + } + async getAllRoles() { + return (await this.entityTable.getNumberArray("int:Roles")); + } + async getSystemIndex(elementInSystemIndex) { + return await this.entityTable.getNumber(elementInSystemIndex, "index:Vim.System:System"); + } + async getAllSystemIndex() { + return await this.entityTable.getNumberArray("index:Vim.System:System"); + } + async getSystem(elementInSystemIndex) { + const index = await this.getSystemIndex(elementInSystemIndex); + if (index === undefined) { + return undefined; + } + return await this.document.system?.get(index); + } + async getElementIndex(elementInSystemIndex) { + return await this.entityTable.getNumber(elementInSystemIndex, "index:Vim.Element:Element"); + } + async getAllElementIndex() { + return await this.entityTable.getNumberArray("index:Vim.Element:Element"); + } + async getElement(elementInSystemIndex) { + const index = await this.getElementIndex(elementInSystemIndex); + if (index === undefined) { + return undefined; + } + return await this.document.element?.get(index); + } +} +exports.ElementInSystemTable = ElementInSystemTable; +class Warning { + static async createFromTable(table, index) { + let result = new Warning(); + result.index = index; + await Promise.all([ + table.getGuid(index).then(v => result.guid = v), + table.getSeverity(index).then(v => result.severity = v), + table.getDescription(index).then(v => result.description = v), + table.getBimDocumentIndex(index).then(v => result.bimDocumentIndex = v), + ]); + return result; + } +} +exports.Warning = Warning; +class WarningTable { + static async createFromDocument(document) { + const entity = await document.entities.getBfast("Vim.Warning"); + if (!entity) { + return undefined; + } + let table = new WarningTable(); + table.document = document; + table.entityTable = new entityTable_1.EntityTable(entity, document.strings); + return table; + } + getCount() { + return this.entityTable.getCount(); + } + async get(warningIndex) { + return await Warning.createFromTable(this, warningIndex); + } + async getAll() { + const localTable = await this.entityTable.getLocal(); + let guid; + let severity; + let description; + let bimDocumentIndex; + await Promise.all([ + (async () => { guid = (await localTable.getStringArray("string:Guid")); })(), + (async () => { severity = (await localTable.getStringArray("string:Severity")); })(), + (async () => { description = (await localTable.getStringArray("string:Description")); })(), + (async () => { bimDocumentIndex = (await localTable.getNumberArray("index:Vim.BimDocument:BimDocument")); })(), + ]); + let warning = []; + for (let i = 0; i < guid.length; i++) { + warning.push({ + index: i, + guid: guid ? guid[i] : undefined, + severity: severity ? severity[i] : undefined, + description: description ? description[i] : undefined, + bimDocumentIndex: bimDocumentIndex ? bimDocumentIndex[i] : undefined + }); + } + return warning; + } + async getGuid(warningIndex) { + return (await this.entityTable.getString(warningIndex, "string:Guid")); + } + async getAllGuid() { + return (await this.entityTable.getStringArray("string:Guid")); + } + async getSeverity(warningIndex) { + return (await this.entityTable.getString(warningIndex, "string:Severity")); + } + async getAllSeverity() { + return (await this.entityTable.getStringArray("string:Severity")); + } + async getDescription(warningIndex) { + return (await this.entityTable.getString(warningIndex, "string:Description")); + } + async getAllDescription() { + return (await this.entityTable.getStringArray("string:Description")); + } + async getBimDocumentIndex(warningIndex) { + return await this.entityTable.getNumber(warningIndex, "index:Vim.BimDocument:BimDocument"); + } + async getAllBimDocumentIndex() { + return await this.entityTable.getNumberArray("index:Vim.BimDocument:BimDocument"); + } + async getBimDocument(warningIndex) { + const index = await this.getBimDocumentIndex(warningIndex); + if (index === undefined) { + return undefined; + } + return await this.document.bimDocument?.get(index); + } +} +exports.WarningTable = WarningTable; +class ElementInWarning { + static async createFromTable(table, index) { + let result = new ElementInWarning(); + result.index = index; + await Promise.all([ + table.getWarningIndex(index).then(v => result.warningIndex = v), + table.getElementIndex(index).then(v => result.elementIndex = v), + ]); + return result; + } +} +exports.ElementInWarning = ElementInWarning; +class ElementInWarningTable { + static async createFromDocument(document) { + const entity = await document.entities.getBfast("Vim.ElementInWarning"); + if (!entity) { + return undefined; + } + let table = new ElementInWarningTable(); + table.document = document; + table.entityTable = new entityTable_1.EntityTable(entity, document.strings); + return table; + } + getCount() { + return this.entityTable.getCount(); + } + async get(elementInWarningIndex) { + return await ElementInWarning.createFromTable(this, elementInWarningIndex); + } + async getAll() { + const localTable = await this.entityTable.getLocal(); + let warningIndex; + let elementIndex; + await Promise.all([ + (async () => { warningIndex = (await localTable.getNumberArray("index:Vim.Warning:Warning")); })(), + (async () => { elementIndex = (await localTable.getNumberArray("index:Vim.Element:Element")); })(), + ]); + let elementInWarning = []; + for (let i = 0; i < warningIndex.length; i++) { + elementInWarning.push({ + index: i, + warningIndex: warningIndex ? warningIndex[i] : undefined, + elementIndex: elementIndex ? elementIndex[i] : undefined + }); + } + return elementInWarning; + } + async getWarningIndex(elementInWarningIndex) { + return await this.entityTable.getNumber(elementInWarningIndex, "index:Vim.Warning:Warning"); + } + async getAllWarningIndex() { + return await this.entityTable.getNumberArray("index:Vim.Warning:Warning"); + } + async getWarning(elementInWarningIndex) { + const index = await this.getWarningIndex(elementInWarningIndex); + if (index === undefined) { + return undefined; + } + return await this.document.warning?.get(index); + } + async getElementIndex(elementInWarningIndex) { + return await this.entityTable.getNumber(elementInWarningIndex, "index:Vim.Element:Element"); + } + async getAllElementIndex() { + return await this.entityTable.getNumberArray("index:Vim.Element:Element"); + } + async getElement(elementInWarningIndex) { + const index = await this.getElementIndex(elementInWarningIndex); + if (index === undefined) { + return undefined; + } + return await this.document.element?.get(index); + } +} +exports.ElementInWarningTable = ElementInWarningTable; +class BasePoint { + static async createFromTable(table, index) { + let result = new BasePoint(); + result.index = index; + await Promise.all([ + table.getIsSurveyPoint(index).then(v => result.isSurveyPoint = v), + table.getPosition_X(index).then(v => result.position_X = v), + table.getPosition_Y(index).then(v => result.position_Y = v), + table.getPosition_Z(index).then(v => result.position_Z = v), + table.getSharedPosition_X(index).then(v => result.sharedPosition_X = v), + table.getSharedPosition_Y(index).then(v => result.sharedPosition_Y = v), + table.getSharedPosition_Z(index).then(v => result.sharedPosition_Z = v), + table.getElementIndex(index).then(v => result.elementIndex = v), + ]); + return result; + } +} +exports.BasePoint = BasePoint; +class BasePointTable { + static async createFromDocument(document) { + const entity = await document.entities.getBfast("Vim.BasePoint"); + if (!entity) { + return undefined; + } + let table = new BasePointTable(); + table.document = document; + table.entityTable = new entityTable_1.EntityTable(entity, document.strings); + return table; + } + getCount() { + return this.entityTable.getCount(); + } + async get(basePointIndex) { + return await BasePoint.createFromTable(this, basePointIndex); + } + async getAll() { + const localTable = await this.entityTable.getLocal(); + let isSurveyPoint; + let position_X; + let position_Y; + let position_Z; + let sharedPosition_X; + let sharedPosition_Y; + let sharedPosition_Z; + let elementIndex; + await Promise.all([ + (async () => { isSurveyPoint = (await localTable.getBooleanArray("byte:IsSurveyPoint")); })(), + (async () => { position_X = (await localTable.getNumberArray("double:Position.X")); })(), + (async () => { position_Y = (await localTable.getNumberArray("double:Position.Y")); })(), + (async () => { position_Z = (await localTable.getNumberArray("double:Position.Z")); })(), + (async () => { sharedPosition_X = (await localTable.getNumberArray("double:SharedPosition.X")); })(), + (async () => { sharedPosition_Y = (await localTable.getNumberArray("double:SharedPosition.Y")); })(), + (async () => { sharedPosition_Z = (await localTable.getNumberArray("double:SharedPosition.Z")); })(), + (async () => { elementIndex = (await localTable.getNumberArray("index:Vim.Element:Element")); })(), + ]); + let basePoint = []; + for (let i = 0; i < isSurveyPoint.length; i++) { + basePoint.push({ + index: i, + isSurveyPoint: isSurveyPoint ? isSurveyPoint[i] : undefined, + position_X: position_X ? position_X[i] : undefined, + position_Y: position_Y ? position_Y[i] : undefined, + position_Z: position_Z ? position_Z[i] : undefined, + sharedPosition_X: sharedPosition_X ? sharedPosition_X[i] : undefined, + sharedPosition_Y: sharedPosition_Y ? sharedPosition_Y[i] : undefined, + sharedPosition_Z: sharedPosition_Z ? sharedPosition_Z[i] : undefined, + elementIndex: elementIndex ? elementIndex[i] : undefined + }); + } + return basePoint; + } + async getIsSurveyPoint(basePointIndex) { + return (await this.entityTable.getBoolean(basePointIndex, "byte:IsSurveyPoint")); + } + async getAllIsSurveyPoint() { + return (await this.entityTable.getBooleanArray("byte:IsSurveyPoint")); + } + async getPosition_X(basePointIndex) { + return (await this.entityTable.getNumber(basePointIndex, "double:Position.X")); + } + async getAllPosition_X() { + return (await this.entityTable.getNumberArray("double:Position.X")); + } + async getPosition_Y(basePointIndex) { + return (await this.entityTable.getNumber(basePointIndex, "double:Position.Y")); + } + async getAllPosition_Y() { + return (await this.entityTable.getNumberArray("double:Position.Y")); + } + async getPosition_Z(basePointIndex) { + return (await this.entityTable.getNumber(basePointIndex, "double:Position.Z")); + } + async getAllPosition_Z() { + return (await this.entityTable.getNumberArray("double:Position.Z")); + } + async getSharedPosition_X(basePointIndex) { + return (await this.entityTable.getNumber(basePointIndex, "double:SharedPosition.X")); + } + async getAllSharedPosition_X() { + return (await this.entityTable.getNumberArray("double:SharedPosition.X")); + } + async getSharedPosition_Y(basePointIndex) { + return (await this.entityTable.getNumber(basePointIndex, "double:SharedPosition.Y")); + } + async getAllSharedPosition_Y() { + return (await this.entityTable.getNumberArray("double:SharedPosition.Y")); + } + async getSharedPosition_Z(basePointIndex) { + return (await this.entityTable.getNumber(basePointIndex, "double:SharedPosition.Z")); + } + async getAllSharedPosition_Z() { + return (await this.entityTable.getNumberArray("double:SharedPosition.Z")); + } + async getElementIndex(basePointIndex) { + return await this.entityTable.getNumber(basePointIndex, "index:Vim.Element:Element"); + } + async getAllElementIndex() { + return await this.entityTable.getNumberArray("index:Vim.Element:Element"); + } + async getElement(basePointIndex) { + const index = await this.getElementIndex(basePointIndex); + if (index === undefined) { + return undefined; + } + return await this.document.element?.get(index); + } +} +exports.BasePointTable = BasePointTable; +class PhaseFilter { + static async createFromTable(table, index) { + let result = new PhaseFilter(); + result.index = index; + await Promise.all([ + table.getNew(index).then(v => result._new = v), + table.getExisting(index).then(v => result.existing = v), + table.getDemolished(index).then(v => result.demolished = v), + table.getTemporary(index).then(v => result.temporary = v), + table.getElementIndex(index).then(v => result.elementIndex = v), + ]); + return result; + } +} +exports.PhaseFilter = PhaseFilter; +class PhaseFilterTable { + static async createFromDocument(document) { + const entity = await document.entities.getBfast("Vim.PhaseFilter"); + if (!entity) { + return undefined; + } + let table = new PhaseFilterTable(); + table.document = document; + table.entityTable = new entityTable_1.EntityTable(entity, document.strings); + return table; + } + getCount() { + return this.entityTable.getCount(); + } + async get(phaseFilterIndex) { + return await PhaseFilter.createFromTable(this, phaseFilterIndex); + } + async getAll() { + const localTable = await this.entityTable.getLocal(); + let _new; + let existing; + let demolished; + let temporary; + let elementIndex; + await Promise.all([ + (async () => { _new = (await localTable.getNumberArray("int:New")); })(), + (async () => { existing = (await localTable.getNumberArray("int:Existing")); })(), + (async () => { demolished = (await localTable.getNumberArray("int:Demolished")); })(), + (async () => { temporary = (await localTable.getNumberArray("int:Temporary")); })(), + (async () => { elementIndex = (await localTable.getNumberArray("index:Vim.Element:Element")); })(), + ]); + let phaseFilter = []; + for (let i = 0; i < _new.length; i++) { + phaseFilter.push({ + index: i, + _new: _new ? _new[i] : undefined, + existing: existing ? existing[i] : undefined, + demolished: demolished ? demolished[i] : undefined, + temporary: temporary ? temporary[i] : undefined, + elementIndex: elementIndex ? elementIndex[i] : undefined + }); + } + return phaseFilter; + } + async getNew(phaseFilterIndex) { + return (await this.entityTable.getNumber(phaseFilterIndex, "int:New")); + } + async getAllNew() { + return (await this.entityTable.getNumberArray("int:New")); + } + async getExisting(phaseFilterIndex) { + return (await this.entityTable.getNumber(phaseFilterIndex, "int:Existing")); + } + async getAllExisting() { + return (await this.entityTable.getNumberArray("int:Existing")); + } + async getDemolished(phaseFilterIndex) { + return (await this.entityTable.getNumber(phaseFilterIndex, "int:Demolished")); + } + async getAllDemolished() { + return (await this.entityTable.getNumberArray("int:Demolished")); + } + async getTemporary(phaseFilterIndex) { + return (await this.entityTable.getNumber(phaseFilterIndex, "int:Temporary")); + } + async getAllTemporary() { + return (await this.entityTable.getNumberArray("int:Temporary")); + } + async getElementIndex(phaseFilterIndex) { + return await this.entityTable.getNumber(phaseFilterIndex, "index:Vim.Element:Element"); + } + async getAllElementIndex() { + return await this.entityTable.getNumberArray("index:Vim.Element:Element"); + } + async getElement(phaseFilterIndex) { + const index = await this.getElementIndex(phaseFilterIndex); + if (index === undefined) { + return undefined; + } + return await this.document.element?.get(index); + } +} +exports.PhaseFilterTable = PhaseFilterTable; +class Grid { + static async createFromTable(table, index) { + let result = new Grid(); + result.index = index; + await Promise.all([ + table.getStartPoint_X(index).then(v => result.startPoint_X = v), + table.getStartPoint_Y(index).then(v => result.startPoint_Y = v), + table.getStartPoint_Z(index).then(v => result.startPoint_Z = v), + table.getEndPoint_X(index).then(v => result.endPoint_X = v), + table.getEndPoint_Y(index).then(v => result.endPoint_Y = v), + table.getEndPoint_Z(index).then(v => result.endPoint_Z = v), + table.getIsCurved(index).then(v => result.isCurved = v), + table.getExtents_Min_X(index).then(v => result.extents_Min_X = v), + table.getExtents_Min_Y(index).then(v => result.extents_Min_Y = v), + table.getExtents_Min_Z(index).then(v => result.extents_Min_Z = v), + table.getExtents_Max_X(index).then(v => result.extents_Max_X = v), + table.getExtents_Max_Y(index).then(v => result.extents_Max_Y = v), + table.getExtents_Max_Z(index).then(v => result.extents_Max_Z = v), + table.getFamilyTypeIndex(index).then(v => result.familyTypeIndex = v), + table.getElementIndex(index).then(v => result.elementIndex = v), + ]); + return result; + } +} +exports.Grid = Grid; +class GridTable { + static async createFromDocument(document) { + const entity = await document.entities.getBfast("Vim.Grid"); + if (!entity) { + return undefined; + } + let table = new GridTable(); + table.document = document; + table.entityTable = new entityTable_1.EntityTable(entity, document.strings); + return table; + } + getCount() { + return this.entityTable.getCount(); + } + async get(gridIndex) { + return await Grid.createFromTable(this, gridIndex); + } + async getAll() { + const localTable = await this.entityTable.getLocal(); + let startPoint_X; + let startPoint_Y; + let startPoint_Z; + let endPoint_X; + let endPoint_Y; + let endPoint_Z; + let isCurved; + let extents_Min_X; + let extents_Min_Y; + let extents_Min_Z; + let extents_Max_X; + let extents_Max_Y; + let extents_Max_Z; + let familyTypeIndex; + let elementIndex; + await Promise.all([ + (async () => { startPoint_X = (await localTable.getNumberArray("double:StartPoint.X")); })(), + (async () => { startPoint_Y = (await localTable.getNumberArray("double:StartPoint.Y")); })(), + (async () => { startPoint_Z = (await localTable.getNumberArray("double:StartPoint.Z")); })(), + (async () => { endPoint_X = (await localTable.getNumberArray("double:EndPoint.X")); })(), + (async () => { endPoint_Y = (await localTable.getNumberArray("double:EndPoint.Y")); })(), + (async () => { endPoint_Z = (await localTable.getNumberArray("double:EndPoint.Z")); })(), + (async () => { isCurved = (await localTable.getBooleanArray("byte:IsCurved")); })(), + (async () => { extents_Min_X = (await localTable.getNumberArray("double:Extents.Min.X")); })(), + (async () => { extents_Min_Y = (await localTable.getNumberArray("double:Extents.Min.Y")); })(), + (async () => { extents_Min_Z = (await localTable.getNumberArray("double:Extents.Min.Z")); })(), + (async () => { extents_Max_X = (await localTable.getNumberArray("double:Extents.Max.X")); })(), + (async () => { extents_Max_Y = (await localTable.getNumberArray("double:Extents.Max.Y")); })(), + (async () => { extents_Max_Z = (await localTable.getNumberArray("double:Extents.Max.Z")); })(), + (async () => { familyTypeIndex = (await localTable.getNumberArray("index:Vim.FamilyType:FamilyType")); })(), + (async () => { elementIndex = (await localTable.getNumberArray("index:Vim.Element:Element")); })(), + ]); + let grid = []; + for (let i = 0; i < startPoint_X.length; i++) { + grid.push({ + index: i, + startPoint_X: startPoint_X ? startPoint_X[i] : undefined, + startPoint_Y: startPoint_Y ? startPoint_Y[i] : undefined, + startPoint_Z: startPoint_Z ? startPoint_Z[i] : undefined, + endPoint_X: endPoint_X ? endPoint_X[i] : undefined, + endPoint_Y: endPoint_Y ? endPoint_Y[i] : undefined, + endPoint_Z: endPoint_Z ? endPoint_Z[i] : undefined, + isCurved: isCurved ? isCurved[i] : undefined, + extents_Min_X: extents_Min_X ? extents_Min_X[i] : undefined, + extents_Min_Y: extents_Min_Y ? extents_Min_Y[i] : undefined, + extents_Min_Z: extents_Min_Z ? extents_Min_Z[i] : undefined, + extents_Max_X: extents_Max_X ? extents_Max_X[i] : undefined, + extents_Max_Y: extents_Max_Y ? extents_Max_Y[i] : undefined, + extents_Max_Z: extents_Max_Z ? extents_Max_Z[i] : undefined, + familyTypeIndex: familyTypeIndex ? familyTypeIndex[i] : undefined, + elementIndex: elementIndex ? elementIndex[i] : undefined + }); + } + return grid; + } + async getStartPoint_X(gridIndex) { + return (await this.entityTable.getNumber(gridIndex, "double:StartPoint.X")); + } + async getAllStartPoint_X() { + return (await this.entityTable.getNumberArray("double:StartPoint.X")); + } + async getStartPoint_Y(gridIndex) { + return (await this.entityTable.getNumber(gridIndex, "double:StartPoint.Y")); + } + async getAllStartPoint_Y() { + return (await this.entityTable.getNumberArray("double:StartPoint.Y")); + } + async getStartPoint_Z(gridIndex) { + return (await this.entityTable.getNumber(gridIndex, "double:StartPoint.Z")); + } + async getAllStartPoint_Z() { + return (await this.entityTable.getNumberArray("double:StartPoint.Z")); + } + async getEndPoint_X(gridIndex) { + return (await this.entityTable.getNumber(gridIndex, "double:EndPoint.X")); + } + async getAllEndPoint_X() { + return (await this.entityTable.getNumberArray("double:EndPoint.X")); + } + async getEndPoint_Y(gridIndex) { + return (await this.entityTable.getNumber(gridIndex, "double:EndPoint.Y")); + } + async getAllEndPoint_Y() { + return (await this.entityTable.getNumberArray("double:EndPoint.Y")); + } + async getEndPoint_Z(gridIndex) { + return (await this.entityTable.getNumber(gridIndex, "double:EndPoint.Z")); + } + async getAllEndPoint_Z() { + return (await this.entityTable.getNumberArray("double:EndPoint.Z")); + } + async getIsCurved(gridIndex) { + return (await this.entityTable.getBoolean(gridIndex, "byte:IsCurved")); + } + async getAllIsCurved() { + return (await this.entityTable.getBooleanArray("byte:IsCurved")); + } + async getExtents_Min_X(gridIndex) { + return (await this.entityTable.getNumber(gridIndex, "double:Extents.Min.X")); + } + async getAllExtents_Min_X() { + return (await this.entityTable.getNumberArray("double:Extents.Min.X")); + } + async getExtents_Min_Y(gridIndex) { + return (await this.entityTable.getNumber(gridIndex, "double:Extents.Min.Y")); + } + async getAllExtents_Min_Y() { + return (await this.entityTable.getNumberArray("double:Extents.Min.Y")); + } + async getExtents_Min_Z(gridIndex) { + return (await this.entityTable.getNumber(gridIndex, "double:Extents.Min.Z")); + } + async getAllExtents_Min_Z() { + return (await this.entityTable.getNumberArray("double:Extents.Min.Z")); + } + async getExtents_Max_X(gridIndex) { + return (await this.entityTable.getNumber(gridIndex, "double:Extents.Max.X")); + } + async getAllExtents_Max_X() { + return (await this.entityTable.getNumberArray("double:Extents.Max.X")); + } + async getExtents_Max_Y(gridIndex) { + return (await this.entityTable.getNumber(gridIndex, "double:Extents.Max.Y")); + } + async getAllExtents_Max_Y() { + return (await this.entityTable.getNumberArray("double:Extents.Max.Y")); + } + async getExtents_Max_Z(gridIndex) { + return (await this.entityTable.getNumber(gridIndex, "double:Extents.Max.Z")); + } + async getAllExtents_Max_Z() { + return (await this.entityTable.getNumberArray("double:Extents.Max.Z")); + } + async getFamilyTypeIndex(gridIndex) { + return await this.entityTable.getNumber(gridIndex, "index:Vim.FamilyType:FamilyType"); + } + async getAllFamilyTypeIndex() { + return await this.entityTable.getNumberArray("index:Vim.FamilyType:FamilyType"); + } + async getFamilyType(gridIndex) { + const index = await this.getFamilyTypeIndex(gridIndex); + if (index === undefined) { + return undefined; + } + return await this.document.familyType?.get(index); + } + async getElementIndex(gridIndex) { + return await this.entityTable.getNumber(gridIndex, "index:Vim.Element:Element"); + } + async getAllElementIndex() { + return await this.entityTable.getNumberArray("index:Vim.Element:Element"); + } + async getElement(gridIndex) { + const index = await this.getElementIndex(gridIndex); + if (index === undefined) { + return undefined; + } + return await this.document.element?.get(index); + } +} +exports.GridTable = GridTable; +class Area { + static async createFromTable(table, index) { + let result = new Area(); + result.index = index; + await Promise.all([ + table.getValue(index).then(v => result.value = v), + table.getPerimeter(index).then(v => result.perimeter = v), + table.getNumber(index).then(v => result.number = v), + table.getIsGrossInterior(index).then(v => result.isGrossInterior = v), + table.getAreaSchemeIndex(index).then(v => result.areaSchemeIndex = v), + table.getElementIndex(index).then(v => result.elementIndex = v), + ]); + return result; + } +} +exports.Area = Area; +class AreaTable { + static async createFromDocument(document) { + const entity = await document.entities.getBfast("Vim.Area"); + if (!entity) { + return undefined; + } + let table = new AreaTable(); + table.document = document; + table.entityTable = new entityTable_1.EntityTable(entity, document.strings); + return table; + } + getCount() { + return this.entityTable.getCount(); + } + async get(areaIndex) { + return await Area.createFromTable(this, areaIndex); + } + async getAll() { + const localTable = await this.entityTable.getLocal(); + let value; + let perimeter; + let number; + let isGrossInterior; + let areaSchemeIndex; + let elementIndex; + await Promise.all([ + (async () => { value = (await localTable.getNumberArray("double:Value")); })(), + (async () => { perimeter = (await localTable.getNumberArray("double:Perimeter")); })(), + (async () => { number = (await localTable.getStringArray("string:Number")); })(), + (async () => { isGrossInterior = (await localTable.getBooleanArray("byte:IsGrossInterior")); })(), + (async () => { areaSchemeIndex = (await localTable.getNumberArray("index:Vim.AreaScheme:AreaScheme")); })(), + (async () => { elementIndex = (await localTable.getNumberArray("index:Vim.Element:Element")); })(), + ]); + let area = []; + for (let i = 0; i < value.length; i++) { + area.push({ + index: i, + value: value ? value[i] : undefined, + perimeter: perimeter ? perimeter[i] : undefined, + number: number ? number[i] : undefined, + isGrossInterior: isGrossInterior ? isGrossInterior[i] : undefined, + areaSchemeIndex: areaSchemeIndex ? areaSchemeIndex[i] : undefined, + elementIndex: elementIndex ? elementIndex[i] : undefined + }); + } + return area; + } + async getValue(areaIndex) { + return (await this.entityTable.getNumber(areaIndex, "double:Value")); + } + async getAllValue() { + return (await this.entityTable.getNumberArray("double:Value")); + } + async getPerimeter(areaIndex) { + return (await this.entityTable.getNumber(areaIndex, "double:Perimeter")); + } + async getAllPerimeter() { + return (await this.entityTable.getNumberArray("double:Perimeter")); + } + async getNumber(areaIndex) { + return (await this.entityTable.getString(areaIndex, "string:Number")); + } + async getAllNumber() { + return (await this.entityTable.getStringArray("string:Number")); + } + async getIsGrossInterior(areaIndex) { + return (await this.entityTable.getBoolean(areaIndex, "byte:IsGrossInterior")); + } + async getAllIsGrossInterior() { + return (await this.entityTable.getBooleanArray("byte:IsGrossInterior")); + } + async getAreaSchemeIndex(areaIndex) { + return await this.entityTable.getNumber(areaIndex, "index:Vim.AreaScheme:AreaScheme"); + } + async getAllAreaSchemeIndex() { + return await this.entityTable.getNumberArray("index:Vim.AreaScheme:AreaScheme"); + } + async getAreaScheme(areaIndex) { + const index = await this.getAreaSchemeIndex(areaIndex); + if (index === undefined) { + return undefined; + } + return await this.document.areaScheme?.get(index); + } + async getElementIndex(areaIndex) { + return await this.entityTable.getNumber(areaIndex, "index:Vim.Element:Element"); + } + async getAllElementIndex() { + return await this.entityTable.getNumberArray("index:Vim.Element:Element"); + } + async getElement(areaIndex) { + const index = await this.getElementIndex(areaIndex); + if (index === undefined) { + return undefined; + } + return await this.document.element?.get(index); + } +} +exports.AreaTable = AreaTable; +class AreaScheme { + static async createFromTable(table, index) { + let result = new AreaScheme(); + result.index = index; + await Promise.all([ + table.getIsGrossBuildingArea(index).then(v => result.isGrossBuildingArea = v), + table.getElementIndex(index).then(v => result.elementIndex = v), + ]); + return result; + } +} +exports.AreaScheme = AreaScheme; +class AreaSchemeTable { + static async createFromDocument(document) { + const entity = await document.entities.getBfast("Vim.AreaScheme"); + if (!entity) { + return undefined; + } + let table = new AreaSchemeTable(); + table.document = document; + table.entityTable = new entityTable_1.EntityTable(entity, document.strings); + return table; + } + getCount() { + return this.entityTable.getCount(); + } + async get(areaSchemeIndex) { + return await AreaScheme.createFromTable(this, areaSchemeIndex); + } + async getAll() { + const localTable = await this.entityTable.getLocal(); + let isGrossBuildingArea; + let elementIndex; + await Promise.all([ + (async () => { isGrossBuildingArea = (await localTable.getBooleanArray("byte:IsGrossBuildingArea")); })(), + (async () => { elementIndex = (await localTable.getNumberArray("index:Vim.Element:Element")); })(), + ]); + let areaScheme = []; + for (let i = 0; i < isGrossBuildingArea.length; i++) { + areaScheme.push({ + index: i, + isGrossBuildingArea: isGrossBuildingArea ? isGrossBuildingArea[i] : undefined, + elementIndex: elementIndex ? elementIndex[i] : undefined + }); + } + return areaScheme; + } + async getIsGrossBuildingArea(areaSchemeIndex) { + return (await this.entityTable.getBoolean(areaSchemeIndex, "byte:IsGrossBuildingArea")); + } + async getAllIsGrossBuildingArea() { + return (await this.entityTable.getBooleanArray("byte:IsGrossBuildingArea")); + } + async getElementIndex(areaSchemeIndex) { + return await this.entityTable.getNumber(areaSchemeIndex, "index:Vim.Element:Element"); + } + async getAllElementIndex() { + return await this.entityTable.getNumberArray("index:Vim.Element:Element"); + } + async getElement(areaSchemeIndex) { + const index = await this.getElementIndex(areaSchemeIndex); + if (index === undefined) { + return undefined; + } + return await this.document.element?.get(index); + } +} +exports.AreaSchemeTable = AreaSchemeTable; +class Schedule { + static async createFromTable(table, index) { + let result = new Schedule(); + result.index = index; + await Promise.all([ + table.getElementIndex(index).then(v => result.elementIndex = v), + ]); + return result; + } +} +exports.Schedule = Schedule; +class ScheduleTable { + static async createFromDocument(document) { + const entity = await document.entities.getBfast("Vim.Schedule"); + if (!entity) { + return undefined; + } + let table = new ScheduleTable(); + table.document = document; + table.entityTable = new entityTable_1.EntityTable(entity, document.strings); + return table; + } + getCount() { + return this.entityTable.getCount(); + } + async get(scheduleIndex) { + return await Schedule.createFromTable(this, scheduleIndex); + } + async getAll() { + const localTable = await this.entityTable.getLocal(); + let elementIndex; + await Promise.all([ + (async () => { elementIndex = (await localTable.getNumberArray("index:Vim.Element:Element")); })(), + ]); + let schedule = []; + for (let i = 0; i < elementIndex.length; i++) { + schedule.push({ + index: i, + elementIndex: elementIndex ? elementIndex[i] : undefined + }); + } + return schedule; + } + async getElementIndex(scheduleIndex) { + return await this.entityTable.getNumber(scheduleIndex, "index:Vim.Element:Element"); + } + async getAllElementIndex() { + return await this.entityTable.getNumberArray("index:Vim.Element:Element"); + } + async getElement(scheduleIndex) { + const index = await this.getElementIndex(scheduleIndex); + if (index === undefined) { + return undefined; + } + return await this.document.element?.get(index); + } +} +exports.ScheduleTable = ScheduleTable; +class ScheduleColumn { + static async createFromTable(table, index) { + let result = new ScheduleColumn(); + result.index = index; + await Promise.all([ + table.getName(index).then(v => result.name = v), + table.getColumnIndex(index).then(v => result.columnIndex = v), + table.getScheduleIndex(index).then(v => result.scheduleIndex = v), + ]); + return result; + } +} +exports.ScheduleColumn = ScheduleColumn; +class ScheduleColumnTable { + static async createFromDocument(document) { + const entity = await document.entities.getBfast("Vim.ScheduleColumn"); + if (!entity) { + return undefined; + } + let table = new ScheduleColumnTable(); + table.document = document; + table.entityTable = new entityTable_1.EntityTable(entity, document.strings); + return table; + } + getCount() { + return this.entityTable.getCount(); + } + async get(scheduleColumnIndex) { + return await ScheduleColumn.createFromTable(this, scheduleColumnIndex); + } + async getAll() { + const localTable = await this.entityTable.getLocal(); + let name; + let columnIndex; + let scheduleIndex; + await Promise.all([ + (async () => { name = (await localTable.getStringArray("string:Name")); })(), + (async () => { columnIndex = (await localTable.getNumberArray("int:ColumnIndex")); })(), + (async () => { scheduleIndex = (await localTable.getNumberArray("index:Vim.Schedule:Schedule")); })(), + ]); + let scheduleColumn = []; + for (let i = 0; i < name.length; i++) { + scheduleColumn.push({ + index: i, + name: name ? name[i] : undefined, + columnIndex: columnIndex ? columnIndex[i] : undefined, + scheduleIndex: scheduleIndex ? scheduleIndex[i] : undefined + }); + } + return scheduleColumn; + } + async getName(scheduleColumnIndex) { + return (await this.entityTable.getString(scheduleColumnIndex, "string:Name")); + } + async getAllName() { + return (await this.entityTable.getStringArray("string:Name")); + } + async getColumnIndex(scheduleColumnIndex) { + return (await this.entityTable.getNumber(scheduleColumnIndex, "int:ColumnIndex")); + } + async getAllColumnIndex() { + return (await this.entityTable.getNumberArray("int:ColumnIndex")); + } + async getScheduleIndex(scheduleColumnIndex) { + return await this.entityTable.getNumber(scheduleColumnIndex, "index:Vim.Schedule:Schedule"); + } + async getAllScheduleIndex() { + return await this.entityTable.getNumberArray("index:Vim.Schedule:Schedule"); + } + async getSchedule(scheduleColumnIndex) { + const index = await this.getScheduleIndex(scheduleColumnIndex); + if (index === undefined) { + return undefined; + } + return await this.document.schedule?.get(index); + } +} +exports.ScheduleColumnTable = ScheduleColumnTable; +class ScheduleCell { + static async createFromTable(table, index) { + let result = new ScheduleCell(); + result.index = index; + await Promise.all([ + table.getValue(index).then(v => result.value = v), + table.getRowIndex(index).then(v => result.rowIndex = v), + table.getScheduleColumnIndex(index).then(v => result.scheduleColumnIndex = v), + ]); + return result; + } +} +exports.ScheduleCell = ScheduleCell; +class ScheduleCellTable { + static async createFromDocument(document) { + const entity = await document.entities.getBfast("Vim.ScheduleCell"); + if (!entity) { + return undefined; + } + let table = new ScheduleCellTable(); + table.document = document; + table.entityTable = new entityTable_1.EntityTable(entity, document.strings); + return table; + } + getCount() { + return this.entityTable.getCount(); + } + async get(scheduleCellIndex) { + return await ScheduleCell.createFromTable(this, scheduleCellIndex); + } + async getAll() { + const localTable = await this.entityTable.getLocal(); + let value; + let rowIndex; + let scheduleColumnIndex; + await Promise.all([ + (async () => { value = (await localTable.getStringArray("string:Value")); })(), + (async () => { rowIndex = (await localTable.getNumberArray("int:RowIndex")); })(), + (async () => { scheduleColumnIndex = (await localTable.getNumberArray("index:Vim.ScheduleColumn:ScheduleColumn")); })(), + ]); + let scheduleCell = []; + for (let i = 0; i < value.length; i++) { + scheduleCell.push({ + index: i, + value: value ? value[i] : undefined, + rowIndex: rowIndex ? rowIndex[i] : undefined, + scheduleColumnIndex: scheduleColumnIndex ? scheduleColumnIndex[i] : undefined + }); + } + return scheduleCell; + } + async getValue(scheduleCellIndex) { + return (await this.entityTable.getString(scheduleCellIndex, "string:Value")); + } + async getAllValue() { + return (await this.entityTable.getStringArray("string:Value")); + } + async getRowIndex(scheduleCellIndex) { + return (await this.entityTable.getNumber(scheduleCellIndex, "int:RowIndex")); + } + async getAllRowIndex() { + return (await this.entityTable.getNumberArray("int:RowIndex")); + } + async getScheduleColumnIndex(scheduleCellIndex) { + return await this.entityTable.getNumber(scheduleCellIndex, "index:Vim.ScheduleColumn:ScheduleColumn"); + } + async getAllScheduleColumnIndex() { + return await this.entityTable.getNumberArray("index:Vim.ScheduleColumn:ScheduleColumn"); + } + async getScheduleColumn(scheduleCellIndex) { + const index = await this.getScheduleColumnIndex(scheduleCellIndex); + if (index === undefined) { + return undefined; + } + return await this.document.scheduleColumn?.get(index); + } +} +exports.ScheduleCellTable = ScheduleCellTable; +class ViewSheetSet { + static async createFromTable(table, index) { + let result = new ViewSheetSet(); + result.index = index; + await Promise.all([ + table.getElementIndex(index).then(v => result.elementIndex = v), + ]); + return result; + } +} +exports.ViewSheetSet = ViewSheetSet; +class ViewSheetSetTable { + static async createFromDocument(document) { + const entity = await document.entities.getBfast("Vim.ViewSheetSet"); + if (!entity) { + return undefined; + } + let table = new ViewSheetSetTable(); + table.document = document; + table.entityTable = new entityTable_1.EntityTable(entity, document.strings); + return table; + } + getCount() { + return this.entityTable.getCount(); + } + async get(viewSheetSetIndex) { + return await ViewSheetSet.createFromTable(this, viewSheetSetIndex); + } + async getAll() { + const localTable = await this.entityTable.getLocal(); + let elementIndex; + await Promise.all([ + (async () => { elementIndex = (await localTable.getNumberArray("index:Vim.Element:Element")); })(), + ]); + let viewSheetSet = []; + for (let i = 0; i < elementIndex.length; i++) { + viewSheetSet.push({ + index: i, + elementIndex: elementIndex ? elementIndex[i] : undefined + }); + } + return viewSheetSet; + } + async getElementIndex(viewSheetSetIndex) { + return await this.entityTable.getNumber(viewSheetSetIndex, "index:Vim.Element:Element"); + } + async getAllElementIndex() { + return await this.entityTable.getNumberArray("index:Vim.Element:Element"); + } + async getElement(viewSheetSetIndex) { + const index = await this.getElementIndex(viewSheetSetIndex); + if (index === undefined) { + return undefined; + } + return await this.document.element?.get(index); + } +} +exports.ViewSheetSetTable = ViewSheetSetTable; +class ViewSheet { + static async createFromTable(table, index) { + let result = new ViewSheet(); + result.index = index; + await Promise.all([ + table.getFamilyTypeIndex(index).then(v => result.familyTypeIndex = v), + table.getElementIndex(index).then(v => result.elementIndex = v), + ]); + return result; + } +} +exports.ViewSheet = ViewSheet; +class ViewSheetTable { + static async createFromDocument(document) { + const entity = await document.entities.getBfast("Vim.ViewSheet"); + if (!entity) { + return undefined; + } + let table = new ViewSheetTable(); + table.document = document; + table.entityTable = new entityTable_1.EntityTable(entity, document.strings); + return table; + } + getCount() { + return this.entityTable.getCount(); + } + async get(viewSheetIndex) { + return await ViewSheet.createFromTable(this, viewSheetIndex); + } + async getAll() { + const localTable = await this.entityTable.getLocal(); + let familyTypeIndex; + let elementIndex; + await Promise.all([ + (async () => { familyTypeIndex = (await localTable.getNumberArray("index:Vim.FamilyType:FamilyType")); })(), + (async () => { elementIndex = (await localTable.getNumberArray("index:Vim.Element:Element")); })(), + ]); + let viewSheet = []; + for (let i = 0; i < familyTypeIndex.length; i++) { + viewSheet.push({ + index: i, + familyTypeIndex: familyTypeIndex ? familyTypeIndex[i] : undefined, + elementIndex: elementIndex ? elementIndex[i] : undefined + }); + } + return viewSheet; + } + async getFamilyTypeIndex(viewSheetIndex) { + return await this.entityTable.getNumber(viewSheetIndex, "index:Vim.FamilyType:FamilyType"); + } + async getAllFamilyTypeIndex() { + return await this.entityTable.getNumberArray("index:Vim.FamilyType:FamilyType"); + } + async getFamilyType(viewSheetIndex) { + const index = await this.getFamilyTypeIndex(viewSheetIndex); + if (index === undefined) { + return undefined; + } + return await this.document.familyType?.get(index); + } + async getElementIndex(viewSheetIndex) { + return await this.entityTable.getNumber(viewSheetIndex, "index:Vim.Element:Element"); + } + async getAllElementIndex() { + return await this.entityTable.getNumberArray("index:Vim.Element:Element"); + } + async getElement(viewSheetIndex) { + const index = await this.getElementIndex(viewSheetIndex); + if (index === undefined) { + return undefined; + } + return await this.document.element?.get(index); + } +} +exports.ViewSheetTable = ViewSheetTable; +class ViewSheetInViewSheetSet { + static async createFromTable(table, index) { + let result = new ViewSheetInViewSheetSet(); + result.index = index; + await Promise.all([ + table.getViewSheetIndex(index).then(v => result.viewSheetIndex = v), + table.getViewSheetSetIndex(index).then(v => result.viewSheetSetIndex = v), + ]); + return result; + } +} +exports.ViewSheetInViewSheetSet = ViewSheetInViewSheetSet; +class ViewSheetInViewSheetSetTable { + static async createFromDocument(document) { + const entity = await document.entities.getBfast("Vim.ViewSheetInViewSheetSet"); + if (!entity) { + return undefined; + } + let table = new ViewSheetInViewSheetSetTable(); + table.document = document; + table.entityTable = new entityTable_1.EntityTable(entity, document.strings); + return table; + } + getCount() { + return this.entityTable.getCount(); + } + async get(viewSheetInViewSheetSetIndex) { + return await ViewSheetInViewSheetSet.createFromTable(this, viewSheetInViewSheetSetIndex); + } + async getAll() { + const localTable = await this.entityTable.getLocal(); + let viewSheetIndex; + let viewSheetSetIndex; + await Promise.all([ + (async () => { viewSheetIndex = (await localTable.getNumberArray("index:Vim.ViewSheet:ViewSheet")); })(), + (async () => { viewSheetSetIndex = (await localTable.getNumberArray("index:Vim.ViewSheetSet:ViewSheetSet")); })(), + ]); + let viewSheetInViewSheetSet = []; + for (let i = 0; i < viewSheetIndex.length; i++) { + viewSheetInViewSheetSet.push({ + index: i, + viewSheetIndex: viewSheetIndex ? viewSheetIndex[i] : undefined, + viewSheetSetIndex: viewSheetSetIndex ? viewSheetSetIndex[i] : undefined + }); + } + return viewSheetInViewSheetSet; + } + async getViewSheetIndex(viewSheetInViewSheetSetIndex) { + return await this.entityTable.getNumber(viewSheetInViewSheetSetIndex, "index:Vim.ViewSheet:ViewSheet"); + } + async getAllViewSheetIndex() { + return await this.entityTable.getNumberArray("index:Vim.ViewSheet:ViewSheet"); + } + async getViewSheet(viewSheetInViewSheetSetIndex) { + const index = await this.getViewSheetIndex(viewSheetInViewSheetSetIndex); + if (index === undefined) { + return undefined; + } + return await this.document.viewSheet?.get(index); + } + async getViewSheetSetIndex(viewSheetInViewSheetSetIndex) { + return await this.entityTable.getNumber(viewSheetInViewSheetSetIndex, "index:Vim.ViewSheetSet:ViewSheetSet"); + } + async getAllViewSheetSetIndex() { + return await this.entityTable.getNumberArray("index:Vim.ViewSheetSet:ViewSheetSet"); + } + async getViewSheetSet(viewSheetInViewSheetSetIndex) { + const index = await this.getViewSheetSetIndex(viewSheetInViewSheetSetIndex); + if (index === undefined) { + return undefined; + } + return await this.document.viewSheetSet?.get(index); + } +} +exports.ViewSheetInViewSheetSetTable = ViewSheetInViewSheetSetTable; +class ViewInViewSheetSet { + static async createFromTable(table, index) { + let result = new ViewInViewSheetSet(); + result.index = index; + await Promise.all([ + table.getViewIndex(index).then(v => result.viewIndex = v), + table.getViewSheetSetIndex(index).then(v => result.viewSheetSetIndex = v), + ]); + return result; + } +} +exports.ViewInViewSheetSet = ViewInViewSheetSet; +class ViewInViewSheetSetTable { + static async createFromDocument(document) { + const entity = await document.entities.getBfast("Vim.ViewInViewSheetSet"); + if (!entity) { + return undefined; + } + let table = new ViewInViewSheetSetTable(); + table.document = document; + table.entityTable = new entityTable_1.EntityTable(entity, document.strings); + return table; + } + getCount() { + return this.entityTable.getCount(); + } + async get(viewInViewSheetSetIndex) { + return await ViewInViewSheetSet.createFromTable(this, viewInViewSheetSetIndex); + } + async getAll() { + const localTable = await this.entityTable.getLocal(); + let viewIndex; + let viewSheetSetIndex; + await Promise.all([ + (async () => { viewIndex = (await localTable.getNumberArray("index:Vim.View:View")); })(), + (async () => { viewSheetSetIndex = (await localTable.getNumberArray("index:Vim.ViewSheetSet:ViewSheetSet")); })(), + ]); + let viewInViewSheetSet = []; + for (let i = 0; i < viewIndex.length; i++) { + viewInViewSheetSet.push({ + index: i, + viewIndex: viewIndex ? viewIndex[i] : undefined, + viewSheetSetIndex: viewSheetSetIndex ? viewSheetSetIndex[i] : undefined + }); + } + return viewInViewSheetSet; + } + async getViewIndex(viewInViewSheetSetIndex) { + return await this.entityTable.getNumber(viewInViewSheetSetIndex, "index:Vim.View:View"); + } + async getAllViewIndex() { + return await this.entityTable.getNumberArray("index:Vim.View:View"); + } + async getView(viewInViewSheetSetIndex) { + const index = await this.getViewIndex(viewInViewSheetSetIndex); + if (index === undefined) { + return undefined; + } + return await this.document.view?.get(index); + } + async getViewSheetSetIndex(viewInViewSheetSetIndex) { + return await this.entityTable.getNumber(viewInViewSheetSetIndex, "index:Vim.ViewSheetSet:ViewSheetSet"); + } + async getAllViewSheetSetIndex() { + return await this.entityTable.getNumberArray("index:Vim.ViewSheetSet:ViewSheetSet"); + } + async getViewSheetSet(viewInViewSheetSetIndex) { + const index = await this.getViewSheetSetIndex(viewInViewSheetSetIndex); + if (index === undefined) { + return undefined; + } + return await this.document.viewSheetSet?.get(index); + } +} +exports.ViewInViewSheetSetTable = ViewInViewSheetSetTable; +class ViewInViewSheet { + static async createFromTable(table, index) { + let result = new ViewInViewSheet(); + result.index = index; + await Promise.all([ + table.getViewIndex(index).then(v => result.viewIndex = v), + table.getViewSheetIndex(index).then(v => result.viewSheetIndex = v), + ]); + return result; + } +} +exports.ViewInViewSheet = ViewInViewSheet; +class ViewInViewSheetTable { + static async createFromDocument(document) { + const entity = await document.entities.getBfast("Vim.ViewInViewSheet"); + if (!entity) { + return undefined; + } + let table = new ViewInViewSheetTable(); + table.document = document; + table.entityTable = new entityTable_1.EntityTable(entity, document.strings); + return table; + } + getCount() { + return this.entityTable.getCount(); + } + async get(viewInViewSheetIndex) { + return await ViewInViewSheet.createFromTable(this, viewInViewSheetIndex); + } + async getAll() { + const localTable = await this.entityTable.getLocal(); + let viewIndex; + let viewSheetIndex; + await Promise.all([ + (async () => { viewIndex = (await localTable.getNumberArray("index:Vim.View:View")); })(), + (async () => { viewSheetIndex = (await localTable.getNumberArray("index:Vim.ViewSheet:ViewSheet")); })(), + ]); + let viewInViewSheet = []; + for (let i = 0; i < viewIndex.length; i++) { + viewInViewSheet.push({ + index: i, + viewIndex: viewIndex ? viewIndex[i] : undefined, + viewSheetIndex: viewSheetIndex ? viewSheetIndex[i] : undefined + }); + } + return viewInViewSheet; + } + async getViewIndex(viewInViewSheetIndex) { + return await this.entityTable.getNumber(viewInViewSheetIndex, "index:Vim.View:View"); + } + async getAllViewIndex() { + return await this.entityTable.getNumberArray("index:Vim.View:View"); + } + async getView(viewInViewSheetIndex) { + const index = await this.getViewIndex(viewInViewSheetIndex); + if (index === undefined) { + return undefined; + } + return await this.document.view?.get(index); + } + async getViewSheetIndex(viewInViewSheetIndex) { + return await this.entityTable.getNumber(viewInViewSheetIndex, "index:Vim.ViewSheet:ViewSheet"); + } + async getAllViewSheetIndex() { + return await this.entityTable.getNumberArray("index:Vim.ViewSheet:ViewSheet"); + } + async getViewSheet(viewInViewSheetIndex) { + const index = await this.getViewSheetIndex(viewInViewSheetIndex); + if (index === undefined) { + return undefined; + } + return await this.document.viewSheet?.get(index); + } +} +exports.ViewInViewSheetTable = ViewInViewSheetTable; +class VimDocument { + constructor(entities, strings) { + this.entities = entities; + this.strings = strings; + } + static async createFromBfast(bfast, ignoreStrings = false) { + const loaded = await vimLoader_1.VimLoader.loadFromBfast(bfast, ignoreStrings); + if (loaded[0] === undefined) + return undefined; + let doc = new VimDocument(loaded[0], loaded[1]); + doc.asset = await AssetTable.createFromDocument(doc); + doc.displayUnit = await DisplayUnitTable.createFromDocument(doc); + doc.parameterDescriptor = await ParameterDescriptorTable.createFromDocument(doc); + doc.parameter = await ParameterTable.createFromDocument(doc); + doc.element = await ElementTable.createFromDocument(doc); + doc.workset = await WorksetTable.createFromDocument(doc); + doc.assemblyInstance = await AssemblyInstanceTable.createFromDocument(doc); + doc.group = await GroupTable.createFromDocument(doc); + doc.designOption = await DesignOptionTable.createFromDocument(doc); + doc.level = await LevelTable.createFromDocument(doc); + doc.phase = await PhaseTable.createFromDocument(doc); + doc.room = await RoomTable.createFromDocument(doc); + doc.bimDocument = await BimDocumentTable.createFromDocument(doc); + doc.displayUnitInBimDocument = await DisplayUnitInBimDocumentTable.createFromDocument(doc); + doc.phaseOrderInBimDocument = await PhaseOrderInBimDocumentTable.createFromDocument(doc); + doc.category = await CategoryTable.createFromDocument(doc); + doc.family = await FamilyTable.createFromDocument(doc); + doc.familyType = await FamilyTypeTable.createFromDocument(doc); + doc.familyInstance = await FamilyInstanceTable.createFromDocument(doc); + doc.view = await ViewTable.createFromDocument(doc); + doc.elementInView = await ElementInViewTable.createFromDocument(doc); + doc.shapeInView = await ShapeInViewTable.createFromDocument(doc); + doc.assetInView = await AssetInViewTable.createFromDocument(doc); + doc.assetInViewSheet = await AssetInViewSheetTable.createFromDocument(doc); + doc.levelInView = await LevelInViewTable.createFromDocument(doc); + doc.camera = await CameraTable.createFromDocument(doc); + doc.material = await MaterialTable.createFromDocument(doc); + doc.materialInElement = await MaterialInElementTable.createFromDocument(doc); + doc.compoundStructureLayer = await CompoundStructureLayerTable.createFromDocument(doc); + doc.compoundStructure = await CompoundStructureTable.createFromDocument(doc); + doc.node = await NodeTable.createFromDocument(doc); + doc.geometry = await GeometryTable.createFromDocument(doc); + doc.shape = await ShapeTable.createFromDocument(doc); + doc.shapeCollection = await ShapeCollectionTable.createFromDocument(doc); + doc.shapeInShapeCollection = await ShapeInShapeCollectionTable.createFromDocument(doc); + doc.system = await SystemTable.createFromDocument(doc); + doc.elementInSystem = await ElementInSystemTable.createFromDocument(doc); + doc.warning = await WarningTable.createFromDocument(doc); + doc.elementInWarning = await ElementInWarningTable.createFromDocument(doc); + doc.basePoint = await BasePointTable.createFromDocument(doc); + doc.phaseFilter = await PhaseFilterTable.createFromDocument(doc); + doc.grid = await GridTable.createFromDocument(doc); + doc.area = await AreaTable.createFromDocument(doc); + doc.areaScheme = await AreaSchemeTable.createFromDocument(doc); + doc.schedule = await ScheduleTable.createFromDocument(doc); + doc.scheduleColumn = await ScheduleColumnTable.createFromDocument(doc); + doc.scheduleCell = await ScheduleCellTable.createFromDocument(doc); + doc.viewSheetSet = await ViewSheetSetTable.createFromDocument(doc); + doc.viewSheet = await ViewSheetTable.createFromDocument(doc); + doc.viewSheetInViewSheetSet = await ViewSheetInViewSheetSetTable.createFromDocument(doc); + doc.viewInViewSheetSet = await ViewInViewSheetSetTable.createFromDocument(doc); + doc.viewInViewSheet = await ViewInViewSheetTable.createFromDocument(doc); + return doc; + } +} +exports.VimDocument = VimDocument; diff --git a/src/ts/dist/remoteBuffer.d.ts b/src/ts/dist/remoteBuffer.d.ts new file mode 100644 index 00000000..eddb9302 --- /dev/null +++ b/src/ts/dist/remoteBuffer.d.ts @@ -0,0 +1,40 @@ +/** + * @module vim-ts + */ +import { Range } from './bfast'; +import { IProgressLogs } from './requestTracker'; +export declare function setRemoteBufferMaxConcurency(value: number): void; +export declare class RetryRequest { + url: string; + range: string | undefined; + responseType: XMLHttpRequestResponseType; + msg: string | undefined; + xhr: XMLHttpRequest | undefined; + constructor(url: string, range: string | undefined, responseType: XMLHttpRequestResponseType); + onLoad: ((result: any) => void) | undefined; + onError: (() => void) | undefined; + onProgress: ((e: ProgressEvent) => void) | undefined; + abort(): void; + send(): void; +} +/** + * Wrapper to provide tracking for all webrequests via request logger. + */ +export declare class RemoteBuffer { + url: string; + maxConcurency: number; + onProgress: (progress: IProgressLogs) => void; + private _tracker; + private _logs; + private _queue; + private _active; + private _encoded; + constructor(url: string, verbose?: boolean); + private requestEncoding; + abort(): void; + http(range: Range | undefined, label: string): Promise; + private enqueue; + private retry; + private end; + private next; +} diff --git a/src/ts/dist/remoteBuffer.js b/src/ts/dist/remoteBuffer.js new file mode 100644 index 00000000..a477049c --- /dev/null +++ b/src/ts/dist/remoteBuffer.js @@ -0,0 +1,149 @@ +"use strict"; +/** + * @module vim-ts + */ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.RemoteBuffer = exports.RetryRequest = exports.setRemoteBufferMaxConcurency = void 0; +const remoteValue_1 = require("./remoteValue"); +const requestTracker_1 = require("./requestTracker"); +const logging_1 = require("./logging"); +let RemoteBufferMaxConcurency = 10; +function setRemoteBufferMaxConcurency(value) { + RemoteBufferMaxConcurency = value; +} +exports.setRemoteBufferMaxConcurency = setRemoteBufferMaxConcurency; +class RetryRequest { + constructor(url, range, + // eslint-disable-next-line no-undef + responseType) { + this.url = url; + this.range = range; + this.responseType = responseType; + } + abort() { + this.xhr.abort(); + } + send() { + this.xhr?.abort(); + const xhr = new XMLHttpRequest(); + xhr.open('GET', this.url); + xhr.responseType = this.responseType; + if (this.range) { + xhr.setRequestHeader('Range', this.range); + } + xhr.onprogress = (e) => { + this.onProgress?.(e); + }; + xhr.onload = (e) => { + this.onProgress?.(e); + this.onLoad?.(xhr.response); + }; + xhr.onerror = (_) => { + this.onError?.(); + }; + xhr.send(); + this.xhr = xhr; + } +} +exports.RetryRequest = RetryRequest; +/** + * Wrapper to provide tracking for all webrequests via request logger. + */ +class RemoteBuffer { + constructor(url, verbose = false) { + this.maxConcurency = RemoteBufferMaxConcurency; + this._queue = []; + this._active = new Set(); + this.url = url; + this._logs = verbose ? new logging_1.DefaultLog() : new logging_1.NoLog(); + this._tracker = new requestTracker_1.RequestTracker(url, this._logs); + this._tracker.onUpdate = (p) => this.onProgress?.(p); + this._encoded = new remoteValue_1.RemoteValue(() => this.requestEncoding()); + } + async requestEncoding() { + const xhr = new XMLHttpRequest(); + xhr.open('HEAD', this.url); + xhr.send(); + this._logs.log(`Requesting header for ${this.url}`); + const promise = new Promise((resolve, reject) => { + xhr.onload = (_) => { + let encoding; + try { + encoding = xhr.getResponseHeader('content-encoding'); + } + catch (e) { + this._logs.error(e); + } + resolve(encoding ?? undefined); + }; + xhr.onerror = (_) => resolve(undefined); + }); + const encoding = await promise; + const encoded = !!encoding; + this._logs.log(`Encoding for ${this.url} = ${encoding}`); + if (encoded) { + this._logs.log(`Defaulting to download strategy for encoded content at ${this.url}`); + } + return encoded; + } + abort() { + this._active.forEach(request => { + request.abort(); + }); + this._active.clear(); + this._queue.length = 0; + } + async http(range, label) { + const useRange = range && !(await this._encoded.get()); + const rangeStr = useRange + ? `bytes=${range.start}-${range.end - 1}` + : undefined; + const request = new RetryRequest(this.url, rangeStr, 'arraybuffer'); + request.msg = useRange + ? `${label} : [${range.start}, ${range.end}] of ${this.url}` + : `${label} of ${this.url}`; + this.enqueue(request); + return new Promise((resolve, reject) => { + this._tracker.start(label); + request.onProgress = (e) => { + this._tracker.update(label, e); + }; + request.onLoad = (result) => { + this._tracker.end(label); + resolve(result); + this.end(request); + }; + request.onError = () => { + this._tracker.fail(label); + this.retry(request); + }; + }); + } + enqueue(xhr) { + this._queue.push(xhr); + this.next(); + } + retry(xhr) { + this._active.delete(xhr); + this.maxConcurency = Math.max(1, this.maxConcurency - 1); + setTimeout(() => this.enqueue(xhr), 2000); + } + end(xhr) { + this._active.delete(xhr); + this.next(); + } + next() { + if (this._queue.length === 0) { + return; + } + if (this._active.size >= this.maxConcurency) { + return; + } + const next = this._queue[0]; + this._queue.shift(); + this._active.add(next); + next.send(); + this._logs.log('Starting ' + next.msg); + } +} +exports.RemoteBuffer = RemoteBuffer; diff --git a/src/ts/dist/remoteG3d.d.ts b/src/ts/dist/remoteG3d.d.ts new file mode 100644 index 00000000..c379d894 --- /dev/null +++ b/src/ts/dist/remoteG3d.d.ts @@ -0,0 +1,67 @@ +import { BFast } from "./bfast"; +import { G3d } from "./g3d"; +import { G3dAttributeDescriptor, TypedArray } from "./g3dAttributes"; +declare class G3dRemoteAttribute { + descriptor: G3dAttributeDescriptor; + bfast: BFast; + constructor(descriptor: G3dAttributeDescriptor, bfast: BFast); + getAll(): Promise; + getByte(index: number): Promise; + getNumber(index: number): Promise; + getValue(index: number): Promise; + getValues(index: number, count: number): Promise; + getCount(): Promise; + static fromString(description: string, bfast: BFast): G3dRemoteAttribute; +} +/** + * G3D is a simple, efficient, generic binary format for storing and transmitting geometry. + * The G3D format is designed to be used either as a serialization format or as an in-memory data structure. + * See https://github.com/vimaec/g3d + */ +export declare class RemoteAbstractG3d { + meta: string; + attributes: G3dRemoteAttribute[]; + constructor(meta: string, attributes: G3dRemoteAttribute[]); + findAttribute(descriptor: string): G3dRemoteAttribute | undefined; + /** + * Create g3d from bfast by requesting all necessary buffers individually. + */ + static createFromBfast(bfast: BFast): RemoteAbstractG3d; +} +export declare class RemoteG3d { + rawG3d: RemoteAbstractG3d; + positions: G3dRemoteAttribute; + indices: G3dRemoteAttribute; + instanceMeshes: G3dRemoteAttribute; + instanceTransforms: G3dRemoteAttribute; + instanceFlags: G3dRemoteAttribute; + meshSubmeshes: G3dRemoteAttribute; + submeshIndexOffsets: G3dRemoteAttribute; + submeshMaterials: G3dRemoteAttribute; + materialColors: G3dRemoteAttribute; + constructor(g3d: RemoteAbstractG3d); + static createFromBfast(bfast: BFast): RemoteG3d; + getVertexCount: () => Promise; + getMeshCount: () => Promise; + getSubmeshCount: () => Promise; + getMeshIndexStart(mesh: number): Promise; + getMeshIndexEnd(mesh: number): Promise; + getMeshIndexCount(mesh: number): Promise; + getMeshIndices(mesh: number): Promise; + getMeshSubmeshEnd(mesh: number): Promise; + getMeshSubmeshStart(mesh: number): Promise; + getMeshSubmeshCount(mesh: number): Promise; + getSubmeshIndexStart(submesh: number): Promise; + getSubmeshIndexEnd(submesh: number): Promise; + getSubmeshIndexCount(submesh: number): Promise; + toG3d(): Promise; + slice(instance: number): Promise; + filter(instances: number[]): Promise; + private filterInstances; + private filterMesh; + private filterSubmeshes; + private filterIndices; + private filterPositions; + private filterMaterials; +} +export {}; diff --git a/src/ts/dist/remoteG3d.js b/src/ts/dist/remoteG3d.js new file mode 100644 index 00000000..6871e20b --- /dev/null +++ b/src/ts/dist/remoteG3d.js @@ -0,0 +1,384 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.RemoteG3d = exports.RemoteAbstractG3d = void 0; +const bfast_1 = require("./bfast"); +const g3d_1 = require("./g3d"); +const g3dAttributes_1 = require("./g3dAttributes"); +class G3dRemoteAttribute { + constructor(descriptor, bfast) { + this.descriptor = descriptor; + this.bfast = bfast; + } + async getAll() { + const bytes = await this.bfast.getBytes(this.descriptor.description); + if (!bytes) + return; + const data = g3dAttributes_1.G3dAttribute.castData(bytes, this.descriptor.dataType); + return data; + } + async getByte(index) { + return await this.bfast.getValue(this.descriptor.description, index); + } + async getNumber(index) { + return Number(await this.bfast.getValue(this.descriptor.description, index)); + } + async getValue(index) { + const value = await this.bfast.getValues(this.descriptor.description, index * this.descriptor.dataArity, this.descriptor.dataArity); + return value; + } + async getValues(index, count) { + const value = await this.bfast.getValues(this.descriptor.description, index * this.descriptor.dataArity, count * this.descriptor.dataArity); + return value; + } + async getCount() { + const range = await this.bfast.getRange(this.descriptor.description); + const count = range.length / (this.descriptor.dataArity * (0, bfast_1.typeSize)(this.descriptor.dataType)); + return count; + } + static fromString(description, bfast) { + return new G3dRemoteAttribute(g3dAttributes_1.G3dAttributeDescriptor.fromString(description), bfast); + } +} +/** + * G3D is a simple, efficient, generic binary format for storing and transmitting geometry. + * The G3D format is designed to be used either as a serialization format or as an in-memory data structure. + * See https://github.com/vimaec/g3d + */ +class RemoteAbstractG3d { + constructor(meta, attributes) { + this.meta = meta; + this.attributes = attributes; + } + findAttribute(descriptor) { + const filter = g3dAttributes_1.G3dAttributeDescriptor.fromString(descriptor); + for (let i = 0; i < this.attributes.length; ++i) { + const attribute = this.attributes[i]; + if (attribute.descriptor.matches(filter)) + return attribute; + } + } + /** + * Create g3d from bfast by requesting all necessary buffers individually. + */ + static createFromBfast(bfast) { + const attributes = g3d_1.VimAttributes.all.map((a) => G3dRemoteAttribute.fromString(a, bfast)); + return new RemoteAbstractG3d('meta', attributes); + } +} +exports.RemoteAbstractG3d = RemoteAbstractG3d; +class RemoteG3d { + constructor(g3d) { + // ------------- All ----------------- + this.getVertexCount = () => this.positions.getCount(); + // ------------- Meshes ----------------- + this.getMeshCount = () => this.meshSubmeshes.getCount(); + this.getSubmeshCount = () => this.submeshIndexOffsets.getCount(); + this.rawG3d = g3d; + this.positions = g3d.findAttribute(g3d_1.VimAttributes.positions); + this.indices = g3d.findAttribute(g3d_1.VimAttributes.indices); + this.meshSubmeshes = g3d.findAttribute(g3d_1.VimAttributes.meshSubmeshes); + this.submeshIndexOffsets = g3d.findAttribute(g3d_1.VimAttributes.submeshIndexOffsets); + this.submeshMaterials = g3d.findAttribute(g3d_1.VimAttributes.submeshMaterials); + this.materialColors = g3d.findAttribute(g3d_1.VimAttributes.materialColors); + this.instanceMeshes = g3d.findAttribute(g3d_1.VimAttributes.instanceMeshes); + this.instanceTransforms = g3d.findAttribute(g3d_1.VimAttributes.instanceTransforms); + this.instanceFlags = + g3d.findAttribute(g3d_1.VimAttributes.instanceFlags); + } + static createFromBfast(bfast) { + const abstract = RemoteAbstractG3d.createFromBfast(bfast); + return new RemoteG3d(abstract); + } + async getMeshIndexStart(mesh) { + const sub = await this.getMeshSubmeshStart(mesh); + return this.getSubmeshIndexStart(sub); + } + async getMeshIndexEnd(mesh) { + const sub = await this.getMeshSubmeshEnd(mesh); + return this.getSubmeshIndexEnd(sub - 1); + } + async getMeshIndexCount(mesh) { + const start = await this.getMeshIndexStart(mesh); + const end = await this.getMeshIndexEnd(mesh); + return end - start; + } + async getMeshIndices(mesh) { + const start = await this.getMeshIndexStart(mesh); + const end = await this.getMeshIndexEnd(mesh); + const indices = await this.indices.getValues(start, end - start); + return new Uint32Array(indices.buffer); + } + async getMeshSubmeshEnd(mesh) { + const meshCount = await this.getMeshCount(); + const submeshCount = await this.getSubmeshCount(); + return mesh + 1 < meshCount + ? await this.meshSubmeshes.getNumber(mesh + 1) + : submeshCount; + } + async getMeshSubmeshStart(mesh) { + return this.meshSubmeshes.getNumber(mesh); + } + async getMeshSubmeshCount(mesh) { + const end = await this.getMeshSubmeshEnd(mesh); + const start = await this.getMeshSubmeshStart(mesh); + return end - start; + } + // // ------------- Submeshes ----------------- + async getSubmeshIndexStart(submesh) { + const submeshCount = await this.submeshIndexOffsets.getCount(); + return submesh < submeshCount + ? this.submeshIndexOffsets.getNumber(submesh) + : await this.indices.getCount(); + } + async getSubmeshIndexEnd(submesh) { + const submeshCount = await this.submeshIndexOffsets.getCount(); + return submesh < submeshCount - 1 + ? this.submeshIndexOffsets.getNumber(submesh + 1) + : await this.indices.getCount(); + } + async getSubmeshIndexCount(submesh) { + const start = await this.getSubmeshIndexStart(submesh); + const end = await this.getSubmeshIndexEnd(submesh); + return end - start; + } + async toG3d() { + const attributes = await Promise.all([ + this.instanceMeshes.getAll(), + this.instanceFlags.getAll(), + this.instanceTransforms.getAll(), + Promise.resolve(undefined), + this.meshSubmeshes.getAll(), + this.submeshIndexOffsets.getAll(), + this.submeshMaterials.getAll(), + this.indices.getAll(), + this.positions.getAll(), + this.materialColors.getAll(), + ]); + return new g3d_1.G3d(...attributes); + } + async slice(instance) { + return this.filter([instance]); + } + async filter(instances) { + // Instances + const instanceData = await this.filterInstances(instances); + // Meshes + const meshes = await this.filterMesh(instanceData.meshes); + if (!meshes.hasMeshes) + return instanceData.toG3d(); + instanceData.remapMeshes(meshes.map); + const [indiceCount, submeshCount] = await meshes.getAttributeCounts(this); + let submeshes; + let materials; + const A = async () => { + submeshes = await this.filterSubmeshes(meshes, submeshCount); + materials = await this.filterMaterials(submeshes.materials); + }; + let vertices; + let positions; + const B = async () => { + vertices = await this.filterIndices(meshes, indiceCount); + positions = await this.filterPositions(vertices, meshes); + }; + await Promise.all([A(), B()]); + submeshes.remapMaterials(materials.map); + return new g3d_1.G3d(instanceData.meshes, instanceData.flags, instanceData.transforms, instanceData.nodes, meshes.submeshes, submeshes.indexOffsets, submeshes.materials, vertices.indices, positions, materials.colors); + } + async filterInstances(instances) { + const instanceSet = new Set(instances); + const attributes = new InstanceData(instanceSet.size); + let instance_i = 0; + const instanceCount = await this.instanceMeshes.getCount(); + const promises = []; + for (let i = 0; i < instanceCount; i++) { + if (!instanceSet.has(i)) + continue; + const current = instance_i; + promises.push(this.instanceFlags.getNumber(i).then(v => attributes.flags[current] = v)); + promises.push(this.instanceMeshes.getNumber(i).then(v => attributes.meshes[current] = v)); + promises.push(this.instanceTransforms.getValue(i).then(v => attributes.transforms.set(v, current * 16))); + attributes.nodes[current] = i; + instance_i++; + } + await Promise.all(promises); + return attributes; + } + async filterMesh(instanceMeshes) { + const meshes = new MeshData(instanceMeshes); + if (meshes.hasMeshes) { + meshes.originalCount = await this.meshSubmeshes.getCount(); + let last = -1; + let mesh_i = 0; + for (let i = 0; i < meshes.originalCount; i++) { + if (!meshes.set.has(i)) + continue; + const offset = mesh_i > 0 ? meshes.submeshes[mesh_i - 1] : 0; + const lastCount = last < 0 ? 0 : await this.getMeshSubmeshCount(last); + meshes.submeshes[mesh_i] = lastCount + offset; + meshes.map.set(i, mesh_i); + last = i; + mesh_i++; + } + } + return meshes; + } + async filterSubmeshes(meshes, submeshCount) { + let submesh_i = 0; + let submeshOffset = 0; + const submeshes = new SubmeshData(submeshCount); + for (let mesh = 0; mesh < meshes.originalCount; mesh++) { + if (!meshes.set.has(mesh)) + continue; + const subStart = await this.getMeshSubmeshStart(mesh); + const subEnd = await this.getMeshSubmeshEnd(mesh); + const promises = []; + for (let j = subStart; j < subEnd; j++) { + const current = submesh_i; + promises.push(this.submeshIndexOffsets.getNumber(subStart) + .then(start => this.submeshIndexOffsets.getNumber(j) + .then(v => submeshes.indexOffsets[current] = v - start + submeshOffset))); + promises.push(this.submeshMaterials.getNumber(j).then(v => submeshes.materials[current] = v)); + submesh_i++; + } + await Promise.all(promises); + submeshOffset += await this.getMeshIndexCount(mesh); + } + return submeshes; + } + async filterIndices(meshes, indicesCount) { + let indices_i = 0; + let mesh_i = 0; + const result = new VertexData(meshes, indicesCount); + for (let mesh = 0; mesh < meshes.originalCount; mesh++) { + if (!meshes.set.has(mesh)) + continue; + const [indexStart, indexEnd] = await Promise.all([ + this.getMeshIndexStart(mesh), + this.getMeshIndexEnd(mesh) + ]); + const indices = await this.indices.getValues(indexStart, indexEnd - indexStart); + result.indices.set(indices, indices_i); + let min = Number.MAX_SAFE_INTEGER; + let max = Number.MIN_SAFE_INTEGER; + for (let i = 0; i < indices.length; i++) { + min = Math.min(indices[i], min); + max = Math.max(indices[i] + 1, max); + } + for (let i = 0; i < indices.length; i++) { + result.indices[indices_i + i] = result.indices[indices_i + i] - min + result.positionCount; + } + result.meshVertexStart[mesh_i] = min; + result.meshVertexEnd[mesh_i] = max; + result.positionCount += max - min; + if (mesh_i > 0) { + const previous = result.vertexOffsets[mesh_i - 1]; + const previousLength = result.meshVertexEnd[mesh_i - 1] - result.meshVertexStart[mesh_i - 1]; + result.vertexOffsets[mesh_i] = previous + previousLength; + } + mesh_i++; + indices_i += indices.length; + } + return result; + } + async filterPositions(indices, meshes) { + const _positions = new Float32Array(indices.positionCount * g3d_1.G3d.POSITION_SIZE); + const promises = []; + let mesh_i = 0; + for (let mesh = 0; mesh < meshes.originalCount; mesh++) { + if (!meshes.set.has(mesh)) + continue; + const vertexStart = indices.meshVertexStart[mesh_i]; + const vertexEnd = indices.meshVertexEnd[mesh_i]; + const current = mesh_i; + promises.push(this.positions.getValues(vertexStart, vertexEnd - vertexStart) + .then(v => _positions.set(v, indices.vertexOffsets[current] * g3d_1.G3d.POSITION_SIZE))); + mesh_i++; + } + await Promise.all(promises); + return _positions; + } + async filterMaterials(submeshMaterials) { + // Material Colors + const materialCount = await this.materialColors.getCount(); + let color_i = 0; + const materials = new MaterialData(submeshMaterials); + const promises = []; + for (let i = 0; i < materialCount; i++) { + if (materials.set.has(i)) { + materials.map.set(i, color_i); + const current = color_i; + promises.push(this.materialColors.getValue(i) + .then(c => materials.colors.set(c, current * g3d_1.G3d.COLOR_SIZE))); + color_i++; + } + } + await Promise.all(promises); + return materials; + } +} +exports.RemoteG3d = RemoteG3d; +class InstanceData { + constructor(count) { + this.meshes = new Int32Array(count); + this.flags = new Uint16Array(count); + this.transforms = new Float32Array(count * 16); + this.nodes = new Int32Array(count); + } + remapMeshes(map) { + for (let i = 0; i < this.meshes.length; i++) { + this.meshes[i] = map.get(this.meshes[i]) ?? -1; + } + } + toG3d() { + return new g3d_1.G3d(this.meshes, this.flags, this.transforms, this.nodes, new Int32Array(), new Int32Array(), new Int32Array(), new Uint32Array(), new Float32Array(), new Float32Array()); + } +} +class MeshData { + constructor(instanceMeshes) { + this.set = new Set(instanceMeshes); + this.set.delete(-1); + this.hasMeshes = this.set.size > 0; + this.submeshes = this.hasMeshes ? new Int32Array(this.set.size) : undefined; + this.map = this.hasMeshes ? new Map() : undefined; + } + async getAttributeCounts(g3d) { + let submeshCount = 0; + let indiceCount = 0; + const promises = []; + for (let mesh = 0; mesh < this.originalCount; mesh++) { + if (!this.set.has(mesh)) + continue; + promises.push(g3d.getMeshIndexCount(mesh).then(v => indiceCount += v)); + promises.push(g3d.getMeshSubmeshCount(mesh).then(v => submeshCount += v)); + } + await Promise.all(promises); + return [indiceCount, submeshCount]; + } +} +class SubmeshData { + constructor(count) { + this.indexOffsets = new Int32Array(count); + this.materials = new Int32Array(count); + } + remapMaterials(map) { + for (let i = 0; i < this.materials.length; i++) { + this.materials[i] = this.materials[i] < 0 ? -1 : map.get(this.materials[i]); + } + } +} +class VertexData { + constructor(meshes, indicesCount) { + this.positionCount = 0; + this.indices = new Uint32Array(indicesCount); + this.meshVertexStart = new Int32Array(meshes.set.size); + this.meshVertexEnd = new Int32Array(meshes.set.size); + this.vertexOffsets = new Int32Array(meshes.set.size); + } +} +class MaterialData { + constructor(submeshMaterials) { + this.set = new Set(submeshMaterials); + this.map = new Map(); + this.colors = new Float32Array(this.set.size * g3d_1.G3d.COLOR_SIZE); + } +} diff --git a/src/ts/dist/remoteGeometry.d.ts b/src/ts/dist/remoteGeometry.d.ts new file mode 100644 index 00000000..9c250d80 --- /dev/null +++ b/src/ts/dist/remoteGeometry.d.ts @@ -0,0 +1,43 @@ +import { BFast } from "./bfast"; +import { G3dMaterial as G3dMaterials } from "./g3dMaterials"; +import { G3dMesh } from "./g3dMesh"; +import { G3dScene } from "./g3dScene"; +import { RemoteValue } from "./remoteValue"; +export declare class RemoteGeometry { + bfast: BFast; + scene: RemoteValue; + sceneRaw: RemoteValue; + constructor(bfast: BFast); + static fromPath(path: string): Promise; + /** + * Aborts all downloads from the underlying BFAST. + */ + abort(): void; + /** + * Downloads underlying bfast making all subsequent request local. + */ + download(): Promise; + /** + * Fetches and returns the vimx G3dMeshIndex + */ + private requestIndex; + private requestIndexRaw; + getIndex(): Promise; + getIndexRaw(): Promise; + /** + * Fetches and returns the vimx G3dMaterials + */ + getMaterials(): Promise; + /** + * Fetches and returns the vimx G3dMesh with given index + */ + getMesh(mesh: number): Promise; + /** + * Fetches and returns the vimx G3dMaterials + */ + getMaterialsRaw(): Promise; + /** + * Fetches and returns the vimx G3dMesh with given index + */ + getMeshRaw(mesh: number): Promise; +} diff --git a/src/ts/dist/remoteGeometry.js b/src/ts/dist/remoteGeometry.js new file mode 100644 index 00000000..68fba3c6 --- /dev/null +++ b/src/ts/dist/remoteGeometry.js @@ -0,0 +1,87 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.RemoteGeometry = void 0; +const bfast_1 = require("./bfast"); +const g3dMaterials_1 = require("./g3dMaterials"); +const g3dMesh_1 = require("./g3dMesh"); +const g3dScene_1 = require("./g3dScene"); +const remoteBuffer_1 = require("./remoteBuffer"); +const remoteValue_1 = require("./remoteValue"); +class RemoteGeometry { + constructor(bfast) { + this.bfast = bfast; + this.scene = new remoteValue_1.RemoteValue(() => this.requestIndex()); + this.sceneRaw = new remoteValue_1.RemoteValue(() => this.requestIndexRaw()); + } + static async fromPath(path) { + const buffer = new remoteBuffer_1.RemoteBuffer(path); + const bfast = new bfast_1.BFast(buffer); + return new RemoteGeometry(bfast); + } + /** + * Aborts all downloads from the underlying BFAST. + */ + abort() { + this.bfast.abort(); + } + /** + * Downloads underlying bfast making all subsequent request local. + */ + async download() { + this.bfast.forceDownload(); + } + /** + * Fetches and returns the vimx G3dMeshIndex + */ + async requestIndex() { + const index = await this.bfast.getLocalBfast('index', true); + return g3dScene_1.G3dScene.createFromBfast(index); + } + async requestIndexRaw() { + const index = await this.bfast.getLocalBfastRaw('index', true); + return g3dScene_1.G3dScene.createFromBfast(index); + } + async getIndex() { + return this.scene.get(); + } + async getIndexRaw() { + return this.sceneRaw.get(); + } + /** + * Fetches and returns the vimx G3dMaterials + */ + async getMaterials() { + const mat = await this.bfast.getLocalBfast('materials', true); + return g3dMaterials_1.G3dMaterial.createFromBfast(mat); + } + /** + * Fetches and returns the vimx G3dMesh with given index + */ + async getMesh(mesh) { + const m = await this.bfast.getLocalBfast(`mesh_${mesh}`, true); + const result = await g3dMesh_1.G3dMesh.createFromBfast(m); + const scene = await this.scene.get(); + result.scene = scene; + result.meshIndex = mesh; + return result; + } + /** + * Fetches and returns the vimx G3dMaterials + */ + async getMaterialsRaw() { + const mat = await this.bfast.getLocalBfastRaw('materials', true); + return g3dMaterials_1.G3dMaterial.createFromBfast(mat); + } + /** + * Fetches and returns the vimx G3dMesh with given index + */ + async getMeshRaw(mesh) { + const m = await this.bfast.getLocalBfastRaw(`mesh_${mesh}`, true); + const result = await g3dMesh_1.G3dMesh.createFromBfast(m); + const scene = await this.sceneRaw.get(); + result.scene = scene; + result.meshIndex = mesh; + return result; + } +} +exports.RemoteGeometry = RemoteGeometry; diff --git a/src/ts/dist/remoteValue.d.ts b/src/ts/dist/remoteValue.d.ts new file mode 100644 index 00000000..9aaed21a --- /dev/null +++ b/src/ts/dist/remoteValue.d.ts @@ -0,0 +1,17 @@ +/** + * @module vim-ts + */ +/** + * Returns a value from cache or queue up existing request or start a new requests + */ +export declare class RemoteValue { + label: string; + private _getter; + private _value; + private _request; + constructor(getter: () => Promise, label?: string); + /** + * Returns a value from cache or queue up existing request or start a new requests + */ + get(): Promise; +} diff --git a/src/ts/dist/remoteValue.js b/src/ts/dist/remoteValue.js new file mode 100644 index 00000000..51139cf4 --- /dev/null +++ b/src/ts/dist/remoteValue.js @@ -0,0 +1,36 @@ +"use strict"; +/** + * @module vim-ts + */ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.RemoteValue = void 0; +/** + * Returns a value from cache or queue up existing request or start a new requests + */ +class RemoteValue { + constructor(getter, label) { + this._getter = getter; + this.label = label ?? ''; + } + /** + * Returns a value from cache or queue up existing request or start a new requests + */ + get() { + if (this._value !== undefined) { + // console.log(this.label + ' returning cached value ') + return Promise.resolve(this._value); + } + if (this._request) { + // console.log(this.label + ' returning existing request') + return this._request; + } + // console.log(this.label + ' creating new request') + this._request = this._getter().then((value) => { + this._value = value; + this._request = undefined; + return this._value; + }); + return this._request; + } +} +exports.RemoteValue = RemoteValue; diff --git a/src/ts/dist/remoteVimx.d.ts b/src/ts/dist/remoteVimx.d.ts new file mode 100644 index 00000000..a5c02aee --- /dev/null +++ b/src/ts/dist/remoteVimx.d.ts @@ -0,0 +1,43 @@ +import { BFast } from "./bfast"; +import { G3dMaterial as G3dMaterials } from "./g3dMaterials"; +import { G3dMesh } from "./g3dMesh"; +import { G3dScene } from "./g3dScene"; +import { RemoteValue } from "./remoteValue"; +export declare class RemoteVimx { + bfast: BFast; + scene: RemoteValue; + sceneRaw: RemoteValue; + constructor(bfast: BFast); + static fromPath(path: string): Promise; + /** + * Aborts all downloads from the underlying BFAST. + */ + abort(): void; + /** + * Downloads underlying bfast making all subsequent request local. + */ + download(): Promise; + /** + * Fetches and returns the vimx G3dMeshIndex + */ + private requestIndex; + private requestIndexRaw; + getIndex(): Promise; + getIndexRaw(): Promise; + /** + * Fetches and returns the vimx G3dMaterials + */ + getMaterials(): Promise; + /** + * Fetches and returns the vimx G3dMesh with given index + */ + getMesh(mesh: number): Promise; + /** + * Fetches and returns the vimx G3dMaterials + */ + getMaterialsRaw(): Promise; + /** + * Fetches and returns the vimx G3dMesh with given index + */ + getMeshRaw(mesh: number): Promise; +} diff --git a/src/ts/dist/remoteVimx.js b/src/ts/dist/remoteVimx.js new file mode 100644 index 00000000..c97299aa --- /dev/null +++ b/src/ts/dist/remoteVimx.js @@ -0,0 +1,87 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.RemoteVimx = void 0; +const bfast_1 = require("./bfast"); +const g3dMaterials_1 = require("./g3dMaterials"); +const g3dMesh_1 = require("./g3dMesh"); +const g3dScene_1 = require("./g3dScene"); +const remoteBuffer_1 = require("./remoteBuffer"); +const remoteValue_1 = require("./remoteValue"); +class RemoteVimx { + constructor(bfast) { + this.bfast = bfast; + this.scene = new remoteValue_1.RemoteValue(() => this.requestIndex()); + this.sceneRaw = new remoteValue_1.RemoteValue(() => this.requestIndexRaw()); + } + static async fromPath(path) { + const buffer = new remoteBuffer_1.RemoteBuffer(path); + const bfast = new bfast_1.BFast(buffer); + return new RemoteVimx(bfast); + } + /** + * Aborts all downloads from the underlying BFAST. + */ + abort() { + this.bfast.abort(); + } + /** + * Downloads underlying bfast making all subsequent request local. + */ + async download() { + this.bfast.forceDownload(); + } + /** + * Fetches and returns the vimx G3dMeshIndex + */ + async requestIndex() { + const index = await this.bfast.getLocalBfast('scene', true); + return g3dScene_1.G3dScene.createFromBfast(index); + } + async requestIndexRaw() { + const index = await this.bfast.getLocalBfastRaw('scene', true); + return g3dScene_1.G3dScene.createFromBfast(index); + } + async getIndex() { + return this.scene.get(); + } + async getIndexRaw() { + return this.sceneRaw.get(); + } + /** + * Fetches and returns the vimx G3dMaterials + */ + async getMaterials() { + const mat = await this.bfast.getLocalBfast('materials', true); + return g3dMaterials_1.G3dMaterial.createFromBfast(mat); + } + /** + * Fetches and returns the vimx G3dMesh with given index + */ + async getMesh(mesh) { + const m = await this.bfast.getLocalBfast(`mesh_${mesh}`, true); + const result = await g3dMesh_1.G3dMesh.createFromBfast(m); + const scene = await this.scene.get(); + result.scene = scene; + result.meshIndex = mesh; + return result; + } + /** + * Fetches and returns the vimx G3dMaterials + */ + async getMaterialsRaw() { + const mat = await this.bfast.getLocalBfastRaw('materials', true); + return g3dMaterials_1.G3dMaterial.createFromBfast(mat); + } + /** + * Fetches and returns the vimx G3dMesh with given index + */ + async getMeshRaw(mesh) { + const m = await this.bfast.getLocalBfastRaw(`mesh_${mesh}`, true); + const result = await g3dMesh_1.G3dMesh.createFromBfast(m); + const scene = await this.sceneRaw.get(); + result.scene = scene; + result.meshIndex = mesh; + return result; + } +} +exports.RemoteVimx = RemoteVimx; diff --git a/src/ts/dist/requestTracker.d.ts b/src/ts/dist/requestTracker.d.ts new file mode 100644 index 00000000..18f38234 --- /dev/null +++ b/src/ts/dist/requestTracker.d.ts @@ -0,0 +1,61 @@ +import { Logger } from "./logging"; +/** + * Represents the state of a single web request + */ +declare class Request { + status: 'active' | 'completed' | 'failed'; + field: string; + loaded: number; + total: number; + lengthComputable: boolean; + constructor(field: string); +} +export interface IProgressLogs { + get loaded(): number; + get total(): number; + get all(): Map; +} +/** + * Represents a collection of webrequests + * Will only send update signal at most every delay + * Provides convenient aggregation of metrics. + */ +export declare class RequestTracker { + source: string; + all: Map; + lastUpdate: number; + delay: number; + sleeping: boolean; + logs: Logger; + /** + * callback on update, called at most every delay time. + */ + onUpdate: ((self: RequestTracker) => void) | undefined; + constructor(source?: string, logger?: Logger); + /** + * Returns the sum of .loaded across all requests + */ + get loaded(): number; + /** + * Returns the sum of .total across all requests + */ + get total(): number; + /** + * Starts tracking a new web request + */ + start(field: string): void; + /** + * Update an existing web request + */ + update(field: string, progress: ProgressEvent): void; + /** + * Notify a webrequest of failure + */ + fail(field: string): void; + /** + * Notify a webrequest of success + */ + end(field: string): void; + private signal; +} +export {}; diff --git a/src/ts/dist/requestTracker.js b/src/ts/dist/requestTracker.js new file mode 100644 index 00000000..e2cef64b --- /dev/null +++ b/src/ts/dist/requestTracker.js @@ -0,0 +1,107 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.RequestTracker = void 0; +const logging_1 = require("./logging"); +/** + * Represents the state of a single web request + */ +class Request { + constructor(field) { + this.status = 'active'; + this.loaded = 0; + this.total = 0; + this.lengthComputable = true; + this.field = field; + } +} +/** + * Represents a collection of webrequests + * Will only send update signal at most every delay + * Provides convenient aggregation of metrics. + */ +class RequestTracker { + constructor(source, logger = new logging_1.NoLog()) { + this.all = new Map(); + this.lastUpdate = 0; + this.delay = 500; + this.sleeping = false; + /** + * callback on update, called at most every delay time. + */ + this.onUpdate = undefined; + this.source = source; + this.logs = logger; + } + /** + * Returns the sum of .loaded across all requests + */ + get loaded() { + let result = 0; + this.all.forEach((request) => { + result += request.loaded; + }); + return result; + } + /** + * Returns the sum of .total across all requests + */ + get total() { + let result = 0; + this.all.forEach((request) => { + result += request.total; + }); + return result; + } + /** + * Starts tracking a new web request + */ + start(field) { + this.all.set(field, new Request(field)); + this.signal(); + } + /** + * Update an existing web request + */ + update(field, progress) { + const r = this.all.get(field); + if (!r) + throw new Error('Updating missing download'); + if (r.status !== 'active') + return; + r.loaded = progress.loaded; + r.total = progress.total; + r.lengthComputable = progress.lengthComputable; + this.signal(); + } + /** + * Notify a webrequest of failure + */ + fail(field) { + this.logs.error(`${field} failed`); + const download = this.all.get(field); + if (!download) + throw new Error('Failing missing download'); + download.status = 'failed'; + this.signal(); + } + /** + * Notify a webrequest of success + */ + end(field) { + this.logs.log(`${field} completed`); + const download = this.all.get(field); + if (!download) + throw new Error('Failing missing download'); + download.status = 'completed'; + // We don't want to throttle end update. + this.onUpdate?.(this); + } + signal() { + if (this.sleeping) + return; + this.sleeping = true; + setTimeout(() => (this.sleeping = false), this.delay); + this.onUpdate?.(this); + } +} +exports.RequestTracker = RequestTracker; diff --git a/src/ts/dist/requester.d.ts b/src/ts/dist/requester.d.ts new file mode 100644 index 00000000..7a29ae16 --- /dev/null +++ b/src/ts/dist/requester.d.ts @@ -0,0 +1,19 @@ +import { IProgressLogs } from "./requestTracker"; +/** + * Wrapper to provide tracking for all webrequests via request logger. + */ +export declare class Requester { + maxConcurency: number; + onProgress: (progress: IProgressLogs) => void; + private _tracker; + private _logs; + private _queue; + private _active; + constructor(verbose?: boolean); + abort(): void; + http(url: string, label?: string): Promise; + private enqueue; + private retry; + private end; + private next; +} diff --git a/src/ts/dist/requester.js b/src/ts/dist/requester.js new file mode 100644 index 00000000..707c9566 --- /dev/null +++ b/src/ts/dist/requester.js @@ -0,0 +1,73 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Requester = void 0; +const logging_1 = require("./logging"); +const remoteBuffer_1 = require("./remoteBuffer"); +const requestTracker_1 = require("./requestTracker"); +/** + * Wrapper to provide tracking for all webrequests via request logger. + */ +class Requester { + constructor(verbose = false) { + this.maxConcurency = 10; + this._queue = []; + this._active = new Set(); + this._logs = verbose ? new logging_1.DefaultLog() : new logging_1.NoLog(); + this._tracker = new requestTracker_1.RequestTracker(undefined, this._logs); + this._tracker.onUpdate = (p) => this.onProgress?.(p); + } + abort() { + this._active.forEach(request => { + request.abort(); + }); + this._active.clear(); + this._queue.length = 0; + } + async http(url, label) { + const request = new remoteBuffer_1.RetryRequest(url, undefined, 'arraybuffer'); + request.msg = url; + this.enqueue(request); + return new Promise((resolve, reject) => { + this._tracker.start(label); + request.onProgress = (e) => { + this._tracker.update(label, e); + }; + request.onLoad = (result) => { + this._tracker.end(label); + resolve(result); + this.end(request); + }; + request.onError = () => { + this._tracker.fail(label); + this.retry(request); + }; + }); + } + enqueue(xhr) { + this._queue.push(xhr); + this.next(); + } + retry(xhr) { + this._active.delete(xhr); + this.maxConcurency = Math.max(1, this.maxConcurency - 1); + setTimeout(() => this.enqueue(xhr), 2000); + } + end(xhr) { + this._active.delete(xhr); + this.next(); + } + next() { + if (this._queue.length === 0) { + return; + } + if (this._active.size >= this.maxConcurency) { + return; + } + const next = this._queue[0]; + this._queue.shift(); + this._active.add(next); + next.send(); + this._logs.log('Starting ' + next.msg); + } +} +exports.Requester = Requester; diff --git a/src/ts/dist/structures.d.ts b/src/ts/dist/structures.d.ts new file mode 100644 index 00000000..d0f8a987 --- /dev/null +++ b/src/ts/dist/structures.d.ts @@ -0,0 +1,48 @@ +/** + * @module vim-ts + */ +export declare type Vector2 = { + x: number; + y: number; +}; +export declare type Vector3 = { + x: number; + y: number; + z: number; +}; +export declare type Vector4 = { + x: number; + y: number; + z: number; + w: number; +}; +export declare type AABox = { + min: Vector3; + max: Vector3; +}; +export declare type AABox2D = { + min: Vector2; + max: Vector2; +}; +export declare type AABox4D = { + min: Vector4; + max: Vector4; +}; +export declare type Matrix4x4 = { + m11: number; + m12: number; + m13: number; + m14: number; + m21: number; + m22: number; + m23: number; + m24: number; + m31: number; + m32: number; + m33: number; + m34: number; + m41: number; + m42: number; + m43: number; + m44: number; +}; diff --git a/src/ts/dist/structures.js b/src/ts/dist/structures.js new file mode 100644 index 00000000..ecd01c36 --- /dev/null +++ b/src/ts/dist/structures.js @@ -0,0 +1,5 @@ +"use strict"; +/** + * @module vim-ts + */ +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/src/ts/dist/types/abstractG3d.d.ts b/src/ts/dist/types/abstractG3d.d.ts new file mode 100644 index 00000000..20af3b6e --- /dev/null +++ b/src/ts/dist/types/abstractG3d.d.ts @@ -0,0 +1,17 @@ +import { G3dAttribute } from './g3dAttributes'; +import { BFast } from './bfast'; +/** + * G3D is a simple, efficient, generic binary format for storing and transmitting geometry. + * The G3D format is designed to be used either as a serialization format or as an in-memory data structure. + * See https://github.com/vimaec/g3d + */ +export declare class AbstractG3d { + meta: string; + attributes: G3dAttribute[]; + constructor(meta: string, attributes: G3dAttribute[]); + findAttribute(descriptor: string): G3dAttribute | undefined; + /** + * Create g3d from bfast by requesting all necessary buffers individually. + */ + static createFromBfast(bfast: BFast, names: string[]): Promise; +} diff --git a/src/ts/dist/types/bfast.d.ts b/src/ts/dist/types/bfast.d.ts new file mode 100644 index 00000000..a75624bf --- /dev/null +++ b/src/ts/dist/types/bfast.d.ts @@ -0,0 +1,141 @@ +/** + * @module vim-ts + */ +import { RemoteBuffer } from './remoteBuffer'; +declare type NumericArrayConstructor = Int8ArrayConstructor | Uint8ArrayConstructor | Int16ArrayConstructor | Uint16ArrayConstructor | Int32ArrayConstructor | Uint32ArrayConstructor | BigInt64ArrayConstructor | BigUint64ArrayConstructor | Float32ArrayConstructor | Float64ArrayConstructor; +export declare type NumericArray = Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array | BigInt64Array | BigUint64Array; +export declare class Range { + start: number; + end: number; + get length(): number; + constructor(start: number, end: number); + offset(offset: number): Range; +} +/** + * Returns -1 size for undefined attributes. + */ +export declare function parseName(name: string): [number, NumericArrayConstructor]; +export declare function typeSize(type: string): 1 | 2 | 4 | 8; +/** + * Bfast header, mainly for validation. + * See https://github.com/vimaec/bfast + */ +export declare class BFastHeader { + magic: number; + dataStart: number; + dataEnd: number; + numArrays: number; + constructor(magic: number, dataStart: number, dataEnd: number, numArrays: number); + static createFromArray(array: Uint32Array): BFastHeader; + static createFromBuffer(array: ArrayBuffer): BFastHeader; +} +/** + * See https://github.com/vimaec/bfast for bfast format spec + * This implementation can either lazily request content as needed from http + * Or it can serve the data directly from an ArrayBuffer + * Remote mode can transition to buffer mode if server doesnt support partial http request + */ +export declare class BFast { + source: RemoteBuffer | ArrayBuffer; + offset: number; + name: string; + private _header; + private _ranges; + private _children; + constructor(source: RemoteBuffer | ArrayBuffer, offset?: number, name?: string); + /** + * Aborts all downloads from the underlying RemoteBuffer + */ + abort(): void; + /** + * @returns Bfast Header + */ + getHeader(): Promise; + /** + * @returns a map of all buffers by names + */ + getRanges(): Promise>; + /** + * Returns the buffer associated with name as a new bfast. + * This value is cached for future requests. + * @param name buffer name + */ + getBfast(name: string): Promise; + getLocalBfast(name: string, unzip?: boolean): Promise; + getLocalBfastRaw(name: string, unzip?: boolean): Promise; + /** + * Returns the raw buffer associated with a name + * This value is not cached. + * @param name buffer name + */ + getBuffer(name: string): Promise; + /** + * Returns a number array from the buffer associated with name + * @param name buffer name + */ + getArray(name: string): Promise; + /** + * Returns a single value from given buffer name + * @param name buffer name + * @param index row index + */ + getValue(name: string, index: number): Promise; + getRange(name: string): Promise; + /** + * Returns count subsequent values from given buffer name. + * @param name buffer name + * @param index row index + * @param count count of values to return + */ + getValues(name: string, index: number, count: number): Promise; + /** + + * Returns the buffer with given name as a byte array + * @param name buffer name + */ + getBytes(name: string): Promise; + /** + * Returns a map of name-values with the same index from all buffers. + * @param name buffer name + */ + getRow(index: number): Promise | undefined>; + /** + * Forces download of the full underlying buffer, from now on all calls will be local. + */ + forceDownload(): Promise; + /** + * Downloads the appropriate range and cast it as a new sub bfast. + */ + private requestBfast; + /** + * Downloads and parses ranges as a map of name->range + */ + private requestRanges; + /** + * Downloads and parse names from remote. + */ + private requestNames; + /** + * Downloads and parse header from remote. + */ + private requestHeader; + /** + * Gets array buffer from from cache, or partial http, fallback to full http + * @param range range to get, or get full resource if undefined + * @param label label for logs + */ + private request; + /** + * returns requested range from cache. + */ + private local; + /** + * returns requested range from remote. + */ + private remote; + /** + * Returns a new local bfast equivalent to this bfast. + */ + getSelf(): Promise; +} +export {}; diff --git a/src/ts/dist/types/converters.d.ts b/src/ts/dist/types/converters.d.ts new file mode 100644 index 00000000..4ce85f94 --- /dev/null +++ b/src/ts/dist/types/converters.d.ts @@ -0,0 +1,46 @@ +/** + * @module vim-ts + */ +import { Vector2, Vector3, Vector4, AABox, AABox2D, AABox4D, Matrix4x4 } from "./structures"; +export interface IConverter { + get columns(): string[]; + convertFromArray(array: number[]): T; + convertToArray(value: T): number[]; +} +export declare class Vector2Converter implements IConverter { + get columns(): string[]; + convertFromArray(array: number[]): Vector2; + convertToArray(value: Vector2): number[]; +} +export declare class Vector3Converter implements IConverter { + get columns(): string[]; + convertFromArray(array: number[]): Vector3; + convertToArray(value: Vector3): number[]; +} +export declare class Vector4Converter implements IConverter { + get columns(): string[]; + convertFromArray(array: number[]): Vector4; + convertToArray(value: Vector4): number[]; +} +export declare class AABox2DConverter implements IConverter { + get columns(): string[]; + convertFromArray(array: number[]): AABox2D; + convertToArray(value: AABox2D): number[]; +} +export declare class AABoxConverter implements IConverter { + get columns(): string[]; + convertFromArray(array: number[]): AABox; + convertToArray(value: AABox): number[]; +} +export declare class AABox4DConverter implements IConverter { + get columns(): string[]; + convertFromArray(array: number[]): AABox4D; + convertToArray(value: AABox4D): number[]; +} +export declare class Matrix4x4Converter implements IConverter { + get columns(): string[]; + convertFromArray(array: number[]): Matrix4x4; + convertToArray(value: Matrix4x4): number[]; +} +export declare function convert(converter: IConverter, array: (number | undefined)[]): T; +export declare function convertArray(converter: IConverter, arrays: (number[] | undefined)[]): T[]; diff --git a/src/ts/dist/types/entityTable.d.ts b/src/ts/dist/types/entityTable.d.ts new file mode 100644 index 00000000..da20ed57 --- /dev/null +++ b/src/ts/dist/types/entityTable.d.ts @@ -0,0 +1,22 @@ +/** + * @module vim-ts + */ +import { BFast, NumericArray } from './bfast'; +export declare class EntityTable { + private readonly bfast; + private readonly strings; + constructor(bfast: BFast, strings: string[] | undefined); + getLocal(): Promise; + static getTypeSize(colName: string): number; + getCount(): Promise; + getArray(columnName: string): Promise; + getNumberArray(columnName: string): Promise; + getNumber(elementIndex: number, columnName: string): Promise; + getBigIntArray(columnName: string): Promise; + getBigInt(elementIndex: number, columnName: string): Promise; + getBoolean(elementIndex: number, columnName: string): Promise; + getBooleanArray(columnName: string): Promise; + toIndex(value: number | bigint): number; + getString(elementIndex: number, columnName: string): Promise; + getStringArray(columnName: string): Promise; +} diff --git a/src/ts/dist/types/g3d.d.ts b/src/ts/dist/types/g3d.d.ts new file mode 100644 index 00000000..bba0b4a2 --- /dev/null +++ b/src/ts/dist/types/g3d.d.ts @@ -0,0 +1,178 @@ +/** + * @module vim-ts + */ +import { AbstractG3d } from './abstractG3d'; +import { BFast } from './bfast'; +export declare type MeshSection = 'opaque' | 'transparent' | 'all'; +/** + * See https://github.com/vimaec/vim#vim-geometry-attributes + */ +export declare class VimAttributes { + static positions: string; + static indices: string; + static instanceMeshes: string; + static instanceTransforms: string; + static instanceNodes: string; + static instanceFlags: string; + static meshSubmeshes: string; + static submeshIndexOffsets: string; + static submeshMaterials: string; + static materialColors: string; + static all: string[]; +} +/** + * G3D is a simple, efficient, generic binary format for storing and transmitting geometry. + * The G3D format is designed to be used either as a serialization format or as an in-memory data structure. + * A G3d with specific attributes according to the VIM format specification. + * See https://github.com/vimaec/vim#vim-geometry-attributes for the vim specification. + * See https://github.com/vimaec/g3d for the g3d specification. + */ +export declare class G3d { + positions: Float32Array; + indices: Uint32Array; + instanceMeshes: Int32Array; + instanceTransforms: Float32Array; + instanceFlags: Uint16Array; + meshSubmeshes: Int32Array; + submeshIndexOffset: Int32Array; + submeshMaterial: Int32Array; + materialColors: Float32Array; + instanceNodes: Int32Array; + meshVertexOffsets: Int32Array; + meshInstances: Array>; + meshOpaqueCount: Int32Array; + submeshVertexStart: Int32Array; + submeshVertexEnd: Int32Array; + rawG3d: AbstractG3d; + static MATRIX_SIZE: number; + static COLOR_SIZE: number; + static POSITION_SIZE: number; + /** + * Opaque white + */ + DEFAULT_COLOR: Float32Array; + constructor(instanceMeshes: Int32Array, instanceFlags: Uint16Array | undefined, instanceTransforms: Float32Array, instanceNodes: Int32Array | undefined, meshSubmeshes: Int32Array, submeshIndexOffsets: Int32Array, submeshMaterials: Int32Array, indices: Int32Array | Uint32Array, positions: Float32Array, materialColors: Float32Array); + private computeSubmeshVertexRange; + static createFromAbstract(g3d: AbstractG3d): G3d; + static createFromPath(path: string): Promise; + static createFromBfast(bfast: BFast): Promise; + /** + * Computes the index of the first vertex of each mesh + */ + private computeMeshVertexOffsets; + /** + * Computes all instances pointing to each mesh. + */ + private computeMeshInstances; + /** + * Reorders submeshIndexOffset, submeshMaterials and indices + * such that for each mesh, submeshes are sorted according to material alpha. + * This enables efficient splitting of arrays into opaque and transparent continuous ranges. + */ + private sortSubmeshes; + /** + * Stores result of getSubmeshIndexEnd for each submesh in an array + */ + private computeSubmeshEnd; + /** + * Stores result of getMeshIndexStart for each mesh in an array + */ + private computeMeshIndexOffsets; + /** + * Reorder submesh arrays and returns size of largest reordered mesh + */ + private reorderSubmeshes; + /** + * Sorts the range from start to end in every array provided in arrays in increasing criterion order. + * Using a simple bubble sort, there is a limited number of submeshes per mesh. + */ + private Sort; + /** + * Reorders the index buffer to match the new order of the submesh arrays. + */ + private reorderIndices; + /** + * Rebase indices to be relative to its own mesh instead of to the whole g3d + */ + private rebaseIndices; + private unbaseIndices; + /** + * Computes an array where true if any of the materials used by a mesh has transparency. + */ + private computeMeshOpaqueCount; + /**Given VIM instance indices returns the corresponding G3d indices */ + remapInstances(instances: number[]): number[]; + getVertexCount: () => number; + getIndexCount: () => number; + getMeshCount: () => number; + getMeshInstanceCount(mesh: number): number; + getMeshIndexStart(mesh: number, section?: MeshSection): number; + getMeshIndexEnd(mesh: number, section?: MeshSection): number; + getMeshIndexCount(mesh: number, section?: MeshSection): number; + getMeshVertexStart(mesh: number): number; + getMeshVertexEnd(mesh: number): number; + getMeshVertexCount(mesh: number): number; + getMeshSubmeshStart(mesh: number, section?: MeshSection): number; + getMeshSubmeshEnd(mesh: number, section?: MeshSection): number; + getMeshSubmeshCount(mesh: number, section?: MeshSection): number; + getMeshHasTransparency(mesh: number): boolean; + getSubmeshIndexStart(submesh: number): number; + getSubmeshIndexEnd(submesh: number): number; + getSubmeshIndexCount(submesh: number): number; + getSubmeshVertexStart(submesh: number): number; + getSubmeshVertexEnd(submesh: number): number; + getSubmeshVertexCount(submesh: number): number; + /** + * Returns color of given submesh as a 4-number array (RGBA) + * @param submesh g3d submesh index + */ + getSubmeshColor(submesh: number): Float32Array; + /** + * Returns color of given submesh as a 4-number array (RGBA) + * @param submesh g3d submesh index + */ + getSubmeshAlpha(submesh: number): number; + /** + * Returns true if submesh is transparent. + * @param submesh g3d submesh index + */ + getSubmeshIsTransparent(submesh: number): boolean; + /** + * Returns the total number of mesh in the g3d + */ + getSubmeshCount(): number; + getInstanceCount: () => number; + /** + * Returns true if instance has given flag enabled. + * @param instance instance to check. + * @param flag to check against. + */ + getInstanceHasFlag(instance: number, flag: number): boolean; + /** + * Returns mesh index of given instance + * @param instance g3d instance index + */ + getInstanceMesh(instance: number): number; + /** + * Returns an 16 number array representation of the matrix for given instance + * @param instance g3d instance index + */ + getInstanceMatrix(instance: number): Float32Array; + getMaterialCount: () => number; + /** + * Returns color of given material as a 4-number array (RGBA) + * @param material g3d material index + */ + getMaterialColor(material: number): Float32Array; + /** + * Returns the alpha component of given material + * @param material + */ + getMaterialAlpha(material: number): number; + /** + * Concatenates two g3ds into a new g3d. + * @deprecated + */ + append(other: G3d): G3d; + validate(): void; +} diff --git a/src/ts/dist/types/g3dAttributes.d.ts b/src/ts/dist/types/g3dAttributes.d.ts new file mode 100644 index 00000000..2258933d --- /dev/null +++ b/src/ts/dist/types/g3dAttributes.d.ts @@ -0,0 +1,20 @@ +export declare class G3dAttributeDescriptor { + description: string; + association: string; + semantic: string; + attributeTypeIndex: string; + dataType: string; + dataArity: number; + constructor(description: string, association: string, semantic: string, attributeTypeIndex: string, dataType: string, dataArity: string); + static fromString(descriptor: string): G3dAttributeDescriptor; + matches(other: G3dAttributeDescriptor): boolean; +} +export declare type TypedArray = Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Uint32Array | BigUint64Array | BigInt64Array | Float64Array; +export declare class G3dAttribute { + descriptor: G3dAttributeDescriptor; + bytes: Uint8Array; + data: TypedArray | undefined; + constructor(descriptor: G3dAttributeDescriptor, bytes: Uint8Array); + static fromString(descriptor: string, buffer: Uint8Array): G3dAttribute; + static castData(bytes: Uint8Array, dataType: string): TypedArray | undefined; +} diff --git a/src/ts/dist/types/g3dMaterials.d.ts b/src/ts/dist/types/g3dMaterials.d.ts new file mode 100644 index 00000000..8737e18d --- /dev/null +++ b/src/ts/dist/types/g3dMaterials.d.ts @@ -0,0 +1,38 @@ +/** + * @module vim-ts + */ +import { AbstractG3d } from './abstractG3d'; +import { BFast } from './bfast'; +/** + * See https://github.com/vimaec/vim#vim-geometry-attributes + */ +export declare class MaterialAttributes { + static materialColors: string; + static all: string[]; +} +/** + * G3D is a simple, efficient, generic binary format for storing and transmitting geometry. + * The G3D format is designed to be used either as a serialization format or as an in-memory data structure. + * A G3d with specific attributes according to the VIM format specification. + * See https://github.com/vimaec/vim#vim-geometry-attributes for the vim specification. + * See https://github.com/vimaec/g3d for the g3d specification. + */ +export declare class G3dMaterial { + static COLOR_SIZE: number; + rawG3d: AbstractG3d; + materialColors: Float32Array; + DEFAULT_COLOR: Float32Array; + constructor(materialColors: Float32Array); + static createFromAbstract(g3d: AbstractG3d): G3dMaterial; + static createFromPath(path: string): Promise; + static createFromBuffer(buffer: ArrayBuffer): Promise; + static createFromBfast(bfast: BFast): Promise; + toG3d(): G3dMaterial; + getMaterialCount: () => number; + /** + * Returns color of given material as a 4-number array (RGBA) + * @param material g3d material index + */ + getMaterialColor(material: number): Float32Array; + getMaterialAlpha(material: number): number; +} diff --git a/src/ts/dist/types/g3dMesh.d.ts b/src/ts/dist/types/g3dMesh.d.ts new file mode 100644 index 00000000..3f755f41 --- /dev/null +++ b/src/ts/dist/types/g3dMesh.d.ts @@ -0,0 +1,79 @@ +/** + * @module vim-ts + */ +import { AbstractG3d } from './abstractG3d'; +import { BFast } from './bfast'; +import { MeshSection } from './g3d'; +import { G3dScene } from './g3dScene'; +/** + * See https://github.com/vimaec/vim#vim-geometry-attributes + */ +export declare class MeshAttributes { + static instanceTransforms: string; + static meshOpaqueSubmeshCount: string; + static submeshIndexOffsets: string; + static submeshVertexOffsets: string; + static submeshMaterials: string; + static positions: string; + static indices: string; + static all: string[]; +} +/** + * G3D is a simple, efficient, generic binary format for storing and transmitting geometry. + * The G3D format is designed to be used either as a serialization format or as an in-memory data structure. + * A G3d with specific attributes according to the VIM format specification. + * See https://github.com/vimaec/vim#vim-geometry-attributes for the vim specification. + * See https://github.com/vimaec/g3d for the g3d specification. + */ +export declare class G3dMesh { + scene: G3dScene; + meshIndex: number; + rawG3d: AbstractG3d; + instanceTransforms: Float32Array; + meshOpaqueSubmeshCount: number; + submeshIndexOffset: Int32Array; + submeshVertexOffset: Int32Array; + submeshMaterial: Int32Array; + positions: Float32Array; + indices: Uint32Array; + static MATRIX_SIZE: number; + static COLOR_SIZE: number; + static POSITION_SIZE: number; + /** + * Opaque white + */ + DEFAULT_COLOR: Float32Array; + constructor(instanceTransforms: Float32Array, meshOpaqueSubmeshCount: number, submeshIndexOffsets: Int32Array, submeshVertexOffsets: Int32Array, submeshMaterials: Int32Array, indices: Int32Array | Uint32Array, positions: Float32Array); + static createFromAbstract(g3d: AbstractG3d): G3dMesh; + static createFromPath(path: string): Promise; + static createFromBuffer(buffer: ArrayBuffer): Promise; + static createFromBfast(bfast: BFast): Promise; + getBimInstance(meshInstance: number): number; + getInstanceMax(meshInstance: number): Float32Array; + getInstanceMin(meshInstance: number): Float32Array; + getInstanceGroup(meshInstance: number): number; + getInstanceTag(meshInstance: number): bigint; + getInstanceHasFlag(meshInstance: number, flag: number): boolean; + getInstanceCount: () => number; + /** + * Returns an 16 number array representation of the matrix for given instance + * @param instance g3d instance index + */ + getInstanceMatrix(instance: number): Float32Array; + getVertexStart(section?: MeshSection): number; + getVertexEnd(section?: MeshSection): number; + getVertexCount(section?: MeshSection): number; + getIndexStart(section?: MeshSection): number; + getIndexEnd(section?: MeshSection): number; + getIndexCount(section?: MeshSection): number; + getHasTransparency(): boolean; + getSubmeshStart(section: MeshSection): number; + getSubmeshEnd(section: MeshSection): number; + getSubmeshCount(section: MeshSection): number; + getSubmeshIndexStart(submesh: number): number; + getSubmeshIndexEnd(submesh: number): number; + getSubmeshIndexCount(submesh: number): number; + getSubmeshVertexStart(submesh: number): number; + getSubmeshVertexEnd(submesh: number): number; + getSubmeshVertexCount(submesh: number): number; +} diff --git a/src/ts/dist/types/g3dMeshIndex.d.ts b/src/ts/dist/types/g3dMeshIndex.d.ts new file mode 100644 index 00000000..4999eeea --- /dev/null +++ b/src/ts/dist/types/g3dMeshIndex.d.ts @@ -0,0 +1,61 @@ +/** + * @module vim-ts + */ +import { AbstractG3d } from './abstractG3d'; +import { BFast } from './bfast'; +import { MeshSection } from './g3d'; +export declare type FilterMode = undefined | 'mesh' | 'instance' | 'group' | 'tag'; +/** + * See https://github.com/vimaec/vim#vim-geometry-attributes + */ +export declare class MeshIndexAttributes { + static instanceFiles: string; + static instanceIndices: string; + static instanceNodes: string; + static instanceGroups: string; + static instanceTags: string; + static instanceMins: string; + static instanceMaxs: string; + static meshInstanceCounts: string; + static meshIndexCounts: string; + static meshVertexCounts: string; + static meshOpaqueIndexCount: string; + static meshOpaqueVertexCount: string; + static all: string[]; +} +/** + * Represents the index, as in book index, of a collection of G3dMesh. + * Allows to find and download G3dMesh as needed. + * Allows to preallocate geometry to render G3dMeshes. + */ +export declare class G3dMeshIndex { + rawG3d: AbstractG3d; + instanceMeshes: Int32Array; + instanceIndices: Int32Array; + instanceNodes: Int32Array; + instanceGroups: Int32Array; + instanceTags: BigInt64Array; + instanceMins: Float32Array; + instanceMaxs: Float32Array; + meshInstanceCounts: Int32Array; + meshIndexCounts: Int32Array; + meshVertexCounts: Int32Array; + meshOpaqueIndexCounts: Int32Array; + meshOpaqueVertexCounts: Int32Array; + private nodeToInstance; + private meshSceneInstances; + constructor(rawG3d: AbstractG3d, instanceFiles: Int32Array, instanceIndices: Int32Array, instanceNodes: Int32Array, instanceGroups: Int32Array, instanceTags: BigInt64Array, instanceMins: Float32Array, instanceMaxs: Float32Array, meshInstanceCounts: Int32Array, meshIndexCounts: Int32Array, meshVertexCounts: Int32Array, meshOpaqueIndexCounts: Int32Array, meshOpaqueVertexCounts: Int32Array); + private createMap; + static createFromAbstract(g3d: AbstractG3d): G3dMeshIndex; + static createFromPath(path: string): Promise; + static createFromBfast(bfast: BFast): Promise; + getMeshSceneInstance(mesh: number, meshIndex: number): number; + getMeshCount(): number; + getMeshIndexCount(mesh: number, section: MeshSection): number; + getMeshVertexCount(mesh: number, section: MeshSection): number; + getMeshInstanceCount(mesh: number): number; + getNodeMin(node: number): Float32Array; + getNodeMax(node: number): Float32Array; + getInstanceMin(instance: number): Float32Array; + getInstanceMax(instance: number): Float32Array; +} diff --git a/src/ts/dist/types/g3dMeshOffsets.d.ts b/src/ts/dist/types/g3dMeshOffsets.d.ts new file mode 100644 index 00000000..b9295313 --- /dev/null +++ b/src/ts/dist/types/g3dMeshOffsets.d.ts @@ -0,0 +1,41 @@ +import { MeshSection } from "./g3d"; +import { G3dSubset } from "./g3dSubset"; +export declare class G3dMeshCounts { + instances: number; + meshes: number; + indices: number; + vertices: number; +} +/** + * Holds the offsets needed to preallocate geometry for a given meshIndexSubset + */ +export declare class G3dMeshOffsets { + subset: G3dSubset; + section: MeshSection; + counts: G3dMeshCounts; + indexOffsets: Int32Array; + vertexOffsets: Int32Array; + /** + * Computes geometry offsets for given subset and section + * @param subset subset for which to compute offsets + * @param section on of 'opaque' | 'transparent' | 'all' + */ + static fromSubset(subset: G3dSubset, section: MeshSection): G3dMeshOffsets; + getIndexOffset(mesh: number): number; + getVertexOffset(mesh: number): number; + /** + * Returns how many instances of given meshes are the filtered view. + */ + getMeshInstanceCount(mesh: number): number; + /** + * Returns instance for given mesh. + * @mesh view-relative mesh index + * @at view-relative instance index for given mesh + * @returns mesh-relative instance index + */ + getMeshInstance(mesh: number, index: number): number; + /** + * Returns the vim-relative mesh index at given index + */ + getMesh(index: number): number; +} diff --git a/src/ts/dist/types/g3dScene.d.ts b/src/ts/dist/types/g3dScene.d.ts new file mode 100644 index 00000000..b501fb8a --- /dev/null +++ b/src/ts/dist/types/g3dScene.d.ts @@ -0,0 +1,63 @@ +/** + * @module vim-ts + */ +import { AbstractG3d } from './abstractG3d'; +import { BFast } from './bfast'; +import { MeshSection } from './g3d'; +export declare type FilterMode = undefined | 'mesh' | 'instance' | 'group' | 'tag'; +/** + * See https://github.com/vimaec/vim#vim-geometry-attributes + */ +export declare class SceneAttributes { + static instanceFiles: string; + static instanceIndices: string; + static instanceNodes: string; + static instanceGroups: string; + static instanceTags: string; + static instanceFlags: string; + static instanceMins: string; + static instanceMaxs: string; + static meshInstanceCounts: string; + static meshIndexCounts: string; + static meshVertexCounts: string; + static meshOpaqueIndexCount: string; + static meshOpaqueVertexCount: string; + static all: string[]; +} +/** + * Represents the index, as in book index, of a collection of G3dMesh. + * Allows to find and download G3dMesh as needed. + * Allows to preallocate geometry to render G3dMeshes. + */ +export declare class G3dScene { + rawG3d: AbstractG3d; + instanceMeshes: Int32Array; + instanceIndices: Int32Array; + instanceNodes: Int32Array; + instanceGroups: Int32Array; + instanceTags: BigInt64Array; + instanceFlags: Uint16Array; + instanceMins: Float32Array; + instanceMaxs: Float32Array; + meshInstanceCounts: Int32Array; + meshIndexCounts: Int32Array; + meshVertexCounts: Int32Array; + meshOpaqueIndexCounts: Int32Array; + meshOpaqueVertexCounts: Int32Array; + private nodeToInstance; + private meshSceneInstances; + constructor(rawG3d: AbstractG3d, instanceFiles: Int32Array, instanceIndices: Int32Array, instanceNodes: Int32Array, instanceGroups: Int32Array, instanceTags: BigInt64Array, instanceFlags: Uint16Array, instanceMins: Float32Array, instanceMaxs: Float32Array, meshInstanceCounts: Int32Array, meshIndexCounts: Int32Array, meshVertexCounts: Int32Array, meshOpaqueIndexCounts: Int32Array, meshOpaqueVertexCounts: Int32Array); + private createMap; + static createFromAbstract(g3d: AbstractG3d): G3dScene; + static createFromPath(path: string): Promise; + static createFromBfast(bfast: BFast): Promise; + getMeshSceneInstance(mesh: number, meshIndex: number): number; + getMeshCount(): number; + getMeshIndexCount(mesh: number, section: MeshSection): number; + getMeshVertexCount(mesh: number, section: MeshSection): number; + getMeshInstanceCount(mesh: number): number; + getNodeMin(node: number): Float32Array; + getNodeMax(node: number): Float32Array; + getInstanceMin(instance: number): Float32Array; + getInstanceMax(instance: number): Float32Array; +} diff --git a/src/ts/dist/types/g3dSubset.d.ts b/src/ts/dist/types/g3dSubset.d.ts new file mode 100644 index 00000000..c49c3cb7 --- /dev/null +++ b/src/ts/dist/types/g3dSubset.d.ts @@ -0,0 +1,108 @@ +import { G3d, MeshSection } from './g3d'; +import { FilterMode, G3dMeshIndex } from './g3dMeshIndex'; +import { G3dMeshCounts, G3dMeshOffsets } from './g3dMeshOffsets'; +export declare type G3dSubset = G3dSubsetOG | G3dSubset2; +export declare class G3dSubset2 { + private _source; + private _instances; + private _meshes; + private _meshInstances; + constructor(source: G3dMeshIndex | G3d, instances: number[]); + getMesh(index: number): number; + getMeshCount(): number; + /** + * Returns index count for given mesh and section. + */ + getMeshIndexCount(mesh: number, section: MeshSection): number; + /** + * Returns vertext count for given mesh and section. + */ + getMeshVertexCount(mesh: number, section: MeshSection): number; + /** + * Returns instance count for given mesh. + * @param mesh The index of the mesh from the g3dIndex. + */ + getMeshInstanceCount(mesh: number): number; + /** + * Returns the list of mesh-based instance indices for given mesh or undefined if all instances are included. + * @param mesh The index of the mesh from the g3dIndex. + */ + getMeshInstances(mesh: number): number[]; + /** + * Returns index-th mesh-based instance index for given mesh. + * @param mesh The index of the mesh from the g3dIndex. + */ + getMeshInstance(mesh: number, index: number): number; + /** + * Returns a new subset that only contains unique meshes. + */ + filterUniqueMeshes(): G3dSubset2; + /** + * Returns a new subset that only contains non-unique meshes. + */ + filterNonUniqueMeshes(): G3dSubset2; + private filterByCount; + /** + * Returns offsets needed to build geometry. + */ + getOffsets(section: MeshSection): G3dMeshOffsets; + getAttributeCounts(section?: MeshSection): G3dMeshCounts; + getBoudingBox(): Float32Array; + filter(mode: FilterMode, filter: number[]): G3dSubset2; + private filterOnArray; +} +/** + * Represents a filter applied to a G3dMeshIndex. + */ +export declare class G3dSubsetOG { + private _source; + private _instances; + private _meshes; + private _meshInstances; + /** + * @param index G3d source geometry. + * @param meshes indices of meshes to include or undefined if all meshes. + * @param meshToInstances indices of instances to include for each mesh or undefined if all meshes. + */ + constructor(index: G3dMeshIndex | G3d, instances: number[], meshes: number[], meshToInstances: number[][]); + getBoudingBox(): Float32Array; + getMesh(index: number): number; + getMeshCount(): number; + /** + * Returns index count for given mesh and section. + */ + getMeshIndexCount(mesh: number, section: MeshSection): number; + /** + * Returns vertext count for given mesh and section. + */ + getMeshVertexCount(mesh: number, section: MeshSection): number; + /** + * Returns instance count for given mesh. + * @param mesh The index of the mesh from the g3dIndex. + */ + getMeshInstanceCount(mesh: number): number; + /** + * Returns index-th mesh-based instance index for given mesh. Returns -1 otherwise. + * @param mesh The index of the mesh from the g3dIndex. + */ + getMeshInstance(mesh: number, index: number): number; + /** + * Returns the list of mesh-based instance indices for given mesh or undefined if all instances are included. + * @param mesh The index of the mesh from the g3dIndex. + */ + getMeshInstances(mesh: number): number[]; + /** + * Returns a new subset that only contains unique meshes. + */ + filterUniqueMeshes(): G3dSubsetOG; + /** + * Returns a new subset that only contains non-unique meshes. + */ + filterNonUniqueMeshes(): G3dSubsetOG; + private filterByCount; + /** + * Returns offsets needed to build geometry. + */ + getOffsets(section: MeshSection): G3dMeshOffsets; + getAttributeCounts(section?: MeshSection): G3dMeshCounts; +} diff --git a/src/ts/dist/types/index.d.ts b/src/ts/dist/types/index.d.ts new file mode 100644 index 00000000..8b034a7e --- /dev/null +++ b/src/ts/dist/types/index.d.ts @@ -0,0 +1,15 @@ +export * from './bfast'; +export * from './g3d'; +export * from './remoteVimx'; +export * from './g3dMaterials'; +export * from './g3dMesh'; +export * from './g3dScene'; +export * from './remoteG3d'; +export * from './remoteBuffer'; +export * from './requestTracker'; +export * from './requester'; +export * from './remoteValue'; +export * from './vimHeader'; +export * from './objectModel'; +export * from './structures'; +export * as VimHelpers from './vimHelpers'; diff --git a/src/ts/dist/types/logging.d.ts b/src/ts/dist/types/logging.d.ts new file mode 100644 index 00000000..1316f5b9 --- /dev/null +++ b/src/ts/dist/types/logging.d.ts @@ -0,0 +1,18 @@ +/** + * @module vim-ts + */ +export declare class Logger { + log: (s: any) => void; + warn: (s: any) => void; + error: (s: any) => void; +} +export declare class DefaultLog implements Logger { + log: (s: any) => void; + warn: (s: any) => void; + error: (s: any) => void; +} +export declare class NoLog implements Logger { + log: (s: any) => void; + warn: (s: any) => void; + error: (s: any) => void; +} diff --git a/src/ts/dist/types/objectModel.d.ts b/src/ts/dist/types/objectModel.d.ts new file mode 100644 index 00000000..73c72add --- /dev/null +++ b/src/ts/dist/types/objectModel.d.ts @@ -0,0 +1,3356 @@ +/** + * @module vim-ts + */ +import { BFast } from "./bfast"; +export interface IAsset { + index: number; + bufferName?: string; +} +export interface IAssetTable { + getCount(): Promise; + get(assetIndex: number): Promise; + getAll(): Promise; + getBufferName(assetIndex: number): Promise; + getAllBufferName(): Promise; +} +export declare class Asset implements IAsset { + index: number; + bufferName?: string; + static createFromTable(table: IAssetTable, index: number): Promise; +} +export declare class AssetTable implements IAssetTable { + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(assetIndex: number): Promise; + getAll(): Promise; + getBufferName(assetIndex: number): Promise; + getAllBufferName(): Promise; +} +export interface IDisplayUnit { + index: number; + spec?: string; + type?: string; + label?: string; +} +export interface IDisplayUnitTable { + getCount(): Promise; + get(displayUnitIndex: number): Promise; + getAll(): Promise; + getSpec(displayUnitIndex: number): Promise; + getAllSpec(): Promise; + getType(displayUnitIndex: number): Promise; + getAllType(): Promise; + getLabel(displayUnitIndex: number): Promise; + getAllLabel(): Promise; +} +export declare class DisplayUnit implements IDisplayUnit { + index: number; + spec?: string; + type?: string; + label?: string; + static createFromTable(table: IDisplayUnitTable, index: number): Promise; +} +export declare class DisplayUnitTable implements IDisplayUnitTable { + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(displayUnitIndex: number): Promise; + getAll(): Promise; + getSpec(displayUnitIndex: number): Promise; + getAllSpec(): Promise; + getType(displayUnitIndex: number): Promise; + getAllType(): Promise; + getLabel(displayUnitIndex: number): Promise; + getAllLabel(): Promise; +} +export interface IParameterDescriptor { + index: number; + name?: string; + group?: string; + parameterType?: string; + isInstance?: boolean; + isShared?: boolean; + isReadOnly?: boolean; + flags?: number; + guid?: string; + displayUnitIndex?: number; + displayUnit?: IDisplayUnit; +} +export interface IParameterDescriptorTable { + getCount(): Promise; + get(parameterDescriptorIndex: number): Promise; + getAll(): Promise; + getName(parameterDescriptorIndex: number): Promise; + getAllName(): Promise; + getGroup(parameterDescriptorIndex: number): Promise; + getAllGroup(): Promise; + getParameterType(parameterDescriptorIndex: number): Promise; + getAllParameterType(): Promise; + getIsInstance(parameterDescriptorIndex: number): Promise; + getAllIsInstance(): Promise; + getIsShared(parameterDescriptorIndex: number): Promise; + getAllIsShared(): Promise; + getIsReadOnly(parameterDescriptorIndex: number): Promise; + getAllIsReadOnly(): Promise; + getFlags(parameterDescriptorIndex: number): Promise; + getAllFlags(): Promise; + getGuid(parameterDescriptorIndex: number): Promise; + getAllGuid(): Promise; + getDisplayUnitIndex(parameterDescriptorIndex: number): Promise; + getAllDisplayUnitIndex(): Promise; + getDisplayUnit(parameterDescriptorIndex: number): Promise; +} +export declare class ParameterDescriptor implements IParameterDescriptor { + index: number; + name?: string; + group?: string; + parameterType?: string; + isInstance?: boolean; + isShared?: boolean; + isReadOnly?: boolean; + flags?: number; + guid?: string; + displayUnitIndex?: number; + displayUnit?: IDisplayUnit; + static createFromTable(table: IParameterDescriptorTable, index: number): Promise; +} +export declare class ParameterDescriptorTable implements IParameterDescriptorTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(parameterDescriptorIndex: number): Promise; + getAll(): Promise; + getName(parameterDescriptorIndex: number): Promise; + getAllName(): Promise; + getGroup(parameterDescriptorIndex: number): Promise; + getAllGroup(): Promise; + getParameterType(parameterDescriptorIndex: number): Promise; + getAllParameterType(): Promise; + getIsInstance(parameterDescriptorIndex: number): Promise; + getAllIsInstance(): Promise; + getIsShared(parameterDescriptorIndex: number): Promise; + getAllIsShared(): Promise; + getIsReadOnly(parameterDescriptorIndex: number): Promise; + getAllIsReadOnly(): Promise; + getFlags(parameterDescriptorIndex: number): Promise; + getAllFlags(): Promise; + getGuid(parameterDescriptorIndex: number): Promise; + getAllGuid(): Promise; + getDisplayUnitIndex(parameterDescriptorIndex: number): Promise; + getAllDisplayUnitIndex(): Promise; + getDisplayUnit(parameterDescriptorIndex: number): Promise; +} +export interface IParameter { + index: number; + value?: string; + parameterDescriptorIndex?: number; + parameterDescriptor?: IParameterDescriptor; + elementIndex?: number; + element?: IElement; +} +export interface IParameterTable { + getCount(): Promise; + get(parameterIndex: number): Promise; + getAll(): Promise; + getValue(parameterIndex: number): Promise; + getAllValue(): Promise; + getParameterDescriptorIndex(parameterIndex: number): Promise; + getAllParameterDescriptorIndex(): Promise; + getParameterDescriptor(parameterIndex: number): Promise; + getElementIndex(parameterIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(parameterIndex: number): Promise; +} +export declare class Parameter implements IParameter { + index: number; + value?: string; + parameterDescriptorIndex?: number; + parameterDescriptor?: IParameterDescriptor; + elementIndex?: number; + element?: IElement; + static createFromTable(table: IParameterTable, index: number): Promise; +} +export declare class ParameterTable implements IParameterTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(parameterIndex: number): Promise; + getAll(): Promise; + getValue(parameterIndex: number): Promise; + getAllValue(): Promise; + getParameterDescriptorIndex(parameterIndex: number): Promise; + getAllParameterDescriptorIndex(): Promise; + getParameterDescriptor(parameterIndex: number): Promise; + getElementIndex(parameterIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(parameterIndex: number): Promise; +} +export interface IElement { + index: number; + id?: bigint; + type?: string; + name?: string; + uniqueId?: string; + location_X?: number; + location_Y?: number; + location_Z?: number; + familyName?: string; + isPinned?: boolean; + levelIndex?: number; + level?: ILevel; + phaseCreatedIndex?: number; + phaseCreated?: IPhase; + phaseDemolishedIndex?: number; + phaseDemolished?: IPhase; + categoryIndex?: number; + category?: ICategory; + worksetIndex?: number; + workset?: IWorkset; + designOptionIndex?: number; + designOption?: IDesignOption; + ownerViewIndex?: number; + ownerView?: IView; + groupIndex?: number; + group?: IGroup; + assemblyInstanceIndex?: number; + assemblyInstance?: IAssemblyInstance; + bimDocumentIndex?: number; + bimDocument?: IBimDocument; + roomIndex?: number; + room?: IRoom; +} +export interface IElementTable { + getCount(): Promise; + get(elementIndex: number): Promise; + getAll(): Promise; + getId(elementIndex: number): Promise; + getAllId(): Promise; + getType(elementIndex: number): Promise; + getAllType(): Promise; + getName(elementIndex: number): Promise; + getAllName(): Promise; + getUniqueId(elementIndex: number): Promise; + getAllUniqueId(): Promise; + getLocation_X(elementIndex: number): Promise; + getAllLocation_X(): Promise; + getLocation_Y(elementIndex: number): Promise; + getAllLocation_Y(): Promise; + getLocation_Z(elementIndex: number): Promise; + getAllLocation_Z(): Promise; + getFamilyName(elementIndex: number): Promise; + getAllFamilyName(): Promise; + getIsPinned(elementIndex: number): Promise; + getAllIsPinned(): Promise; + getLevelIndex(elementIndex: number): Promise; + getAllLevelIndex(): Promise; + getLevel(elementIndex: number): Promise; + getPhaseCreatedIndex(elementIndex: number): Promise; + getAllPhaseCreatedIndex(): Promise; + getPhaseCreated(elementIndex: number): Promise; + getPhaseDemolishedIndex(elementIndex: number): Promise; + getAllPhaseDemolishedIndex(): Promise; + getPhaseDemolished(elementIndex: number): Promise; + getCategoryIndex(elementIndex: number): Promise; + getAllCategoryIndex(): Promise; + getCategory(elementIndex: number): Promise; + getWorksetIndex(elementIndex: number): Promise; + getAllWorksetIndex(): Promise; + getWorkset(elementIndex: number): Promise; + getDesignOptionIndex(elementIndex: number): Promise; + getAllDesignOptionIndex(): Promise; + getDesignOption(elementIndex: number): Promise; + getOwnerViewIndex(elementIndex: number): Promise; + getAllOwnerViewIndex(): Promise; + getOwnerView(elementIndex: number): Promise; + getGroupIndex(elementIndex: number): Promise; + getAllGroupIndex(): Promise; + getGroup(elementIndex: number): Promise; + getAssemblyInstanceIndex(elementIndex: number): Promise; + getAllAssemblyInstanceIndex(): Promise; + getAssemblyInstance(elementIndex: number): Promise; + getBimDocumentIndex(elementIndex: number): Promise; + getAllBimDocumentIndex(): Promise; + getBimDocument(elementIndex: number): Promise; + getRoomIndex(elementIndex: number): Promise; + getAllRoomIndex(): Promise; + getRoom(elementIndex: number): Promise; +} +export declare class Element implements IElement { + index: number; + id?: bigint; + type?: string; + name?: string; + uniqueId?: string; + location_X?: number; + location_Y?: number; + location_Z?: number; + familyName?: string; + isPinned?: boolean; + levelIndex?: number; + level?: ILevel; + phaseCreatedIndex?: number; + phaseCreated?: IPhase; + phaseDemolishedIndex?: number; + phaseDemolished?: IPhase; + categoryIndex?: number; + category?: ICategory; + worksetIndex?: number; + workset?: IWorkset; + designOptionIndex?: number; + designOption?: IDesignOption; + ownerViewIndex?: number; + ownerView?: IView; + groupIndex?: number; + group?: IGroup; + assemblyInstanceIndex?: number; + assemblyInstance?: IAssemblyInstance; + bimDocumentIndex?: number; + bimDocument?: IBimDocument; + roomIndex?: number; + room?: IRoom; + static createFromTable(table: IElementTable, index: number): Promise; +} +export declare class ElementTable implements IElementTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(elementIndex: number): Promise; + getAll(): Promise; + getId(elementIndex: number): Promise; + getAllId(): Promise; + getType(elementIndex: number): Promise; + getAllType(): Promise; + getName(elementIndex: number): Promise; + getAllName(): Promise; + getUniqueId(elementIndex: number): Promise; + getAllUniqueId(): Promise; + getLocation_X(elementIndex: number): Promise; + getAllLocation_X(): Promise; + getLocation_Y(elementIndex: number): Promise; + getAllLocation_Y(): Promise; + getLocation_Z(elementIndex: number): Promise; + getAllLocation_Z(): Promise; + getFamilyName(elementIndex: number): Promise; + getAllFamilyName(): Promise; + getIsPinned(elementIndex: number): Promise; + getAllIsPinned(): Promise; + getLevelIndex(elementIndex: number): Promise; + getAllLevelIndex(): Promise; + getLevel(elementIndex: number): Promise; + getPhaseCreatedIndex(elementIndex: number): Promise; + getAllPhaseCreatedIndex(): Promise; + getPhaseCreated(elementIndex: number): Promise; + getPhaseDemolishedIndex(elementIndex: number): Promise; + getAllPhaseDemolishedIndex(): Promise; + getPhaseDemolished(elementIndex: number): Promise; + getCategoryIndex(elementIndex: number): Promise; + getAllCategoryIndex(): Promise; + getCategory(elementIndex: number): Promise; + getWorksetIndex(elementIndex: number): Promise; + getAllWorksetIndex(): Promise; + getWorkset(elementIndex: number): Promise; + getDesignOptionIndex(elementIndex: number): Promise; + getAllDesignOptionIndex(): Promise; + getDesignOption(elementIndex: number): Promise; + getOwnerViewIndex(elementIndex: number): Promise; + getAllOwnerViewIndex(): Promise; + getOwnerView(elementIndex: number): Promise; + getGroupIndex(elementIndex: number): Promise; + getAllGroupIndex(): Promise; + getGroup(elementIndex: number): Promise; + getAssemblyInstanceIndex(elementIndex: number): Promise; + getAllAssemblyInstanceIndex(): Promise; + getAssemblyInstance(elementIndex: number): Promise; + getBimDocumentIndex(elementIndex: number): Promise; + getAllBimDocumentIndex(): Promise; + getBimDocument(elementIndex: number): Promise; + getRoomIndex(elementIndex: number): Promise; + getAllRoomIndex(): Promise; + getRoom(elementIndex: number): Promise; +} +export interface IWorkset { + index: number; + id?: number; + name?: string; + kind?: string; + isOpen?: boolean; + isEditable?: boolean; + owner?: string; + uniqueId?: string; + bimDocumentIndex?: number; + bimDocument?: IBimDocument; +} +export interface IWorksetTable { + getCount(): Promise; + get(worksetIndex: number): Promise; + getAll(): Promise; + getId(worksetIndex: number): Promise; + getAllId(): Promise; + getName(worksetIndex: number): Promise; + getAllName(): Promise; + getKind(worksetIndex: number): Promise; + getAllKind(): Promise; + getIsOpen(worksetIndex: number): Promise; + getAllIsOpen(): Promise; + getIsEditable(worksetIndex: number): Promise; + getAllIsEditable(): Promise; + getOwner(worksetIndex: number): Promise; + getAllOwner(): Promise; + getUniqueId(worksetIndex: number): Promise; + getAllUniqueId(): Promise; + getBimDocumentIndex(worksetIndex: number): Promise; + getAllBimDocumentIndex(): Promise; + getBimDocument(worksetIndex: number): Promise; +} +export declare class Workset implements IWorkset { + index: number; + id?: number; + name?: string; + kind?: string; + isOpen?: boolean; + isEditable?: boolean; + owner?: string; + uniqueId?: string; + bimDocumentIndex?: number; + bimDocument?: IBimDocument; + static createFromTable(table: IWorksetTable, index: number): Promise; +} +export declare class WorksetTable implements IWorksetTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(worksetIndex: number): Promise; + getAll(): Promise; + getId(worksetIndex: number): Promise; + getAllId(): Promise; + getName(worksetIndex: number): Promise; + getAllName(): Promise; + getKind(worksetIndex: number): Promise; + getAllKind(): Promise; + getIsOpen(worksetIndex: number): Promise; + getAllIsOpen(): Promise; + getIsEditable(worksetIndex: number): Promise; + getAllIsEditable(): Promise; + getOwner(worksetIndex: number): Promise; + getAllOwner(): Promise; + getUniqueId(worksetIndex: number): Promise; + getAllUniqueId(): Promise; + getBimDocumentIndex(worksetIndex: number): Promise; + getAllBimDocumentIndex(): Promise; + getBimDocument(worksetIndex: number): Promise; +} +export interface IAssemblyInstance { + index: number; + assemblyTypeName?: string; + position_X?: number; + position_Y?: number; + position_Z?: number; + elementIndex?: number; + element?: IElement; +} +export interface IAssemblyInstanceTable { + getCount(): Promise; + get(assemblyInstanceIndex: number): Promise; + getAll(): Promise; + getAssemblyTypeName(assemblyInstanceIndex: number): Promise; + getAllAssemblyTypeName(): Promise; + getPosition_X(assemblyInstanceIndex: number): Promise; + getAllPosition_X(): Promise; + getPosition_Y(assemblyInstanceIndex: number): Promise; + getAllPosition_Y(): Promise; + getPosition_Z(assemblyInstanceIndex: number): Promise; + getAllPosition_Z(): Promise; + getElementIndex(assemblyInstanceIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(assemblyInstanceIndex: number): Promise; +} +export declare class AssemblyInstance implements IAssemblyInstance { + index: number; + assemblyTypeName?: string; + position_X?: number; + position_Y?: number; + position_Z?: number; + elementIndex?: number; + element?: IElement; + static createFromTable(table: IAssemblyInstanceTable, index: number): Promise; +} +export declare class AssemblyInstanceTable implements IAssemblyInstanceTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(assemblyInstanceIndex: number): Promise; + getAll(): Promise; + getAssemblyTypeName(assemblyInstanceIndex: number): Promise; + getAllAssemblyTypeName(): Promise; + getPosition_X(assemblyInstanceIndex: number): Promise; + getAllPosition_X(): Promise; + getPosition_Y(assemblyInstanceIndex: number): Promise; + getAllPosition_Y(): Promise; + getPosition_Z(assemblyInstanceIndex: number): Promise; + getAllPosition_Z(): Promise; + getElementIndex(assemblyInstanceIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(assemblyInstanceIndex: number): Promise; +} +export interface IGroup { + index: number; + groupType?: string; + position_X?: number; + position_Y?: number; + position_Z?: number; + elementIndex?: number; + element?: IElement; +} +export interface IGroupTable { + getCount(): Promise; + get(groupIndex: number): Promise; + getAll(): Promise; + getGroupType(groupIndex: number): Promise; + getAllGroupType(): Promise; + getPosition_X(groupIndex: number): Promise; + getAllPosition_X(): Promise; + getPosition_Y(groupIndex: number): Promise; + getAllPosition_Y(): Promise; + getPosition_Z(groupIndex: number): Promise; + getAllPosition_Z(): Promise; + getElementIndex(groupIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(groupIndex: number): Promise; +} +export declare class Group implements IGroup { + index: number; + groupType?: string; + position_X?: number; + position_Y?: number; + position_Z?: number; + elementIndex?: number; + element?: IElement; + static createFromTable(table: IGroupTable, index: number): Promise; +} +export declare class GroupTable implements IGroupTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(groupIndex: number): Promise; + getAll(): Promise; + getGroupType(groupIndex: number): Promise; + getAllGroupType(): Promise; + getPosition_X(groupIndex: number): Promise; + getAllPosition_X(): Promise; + getPosition_Y(groupIndex: number): Promise; + getAllPosition_Y(): Promise; + getPosition_Z(groupIndex: number): Promise; + getAllPosition_Z(): Promise; + getElementIndex(groupIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(groupIndex: number): Promise; +} +export interface IDesignOption { + index: number; + isPrimary?: boolean; + elementIndex?: number; + element?: IElement; +} +export interface IDesignOptionTable { + getCount(): Promise; + get(designOptionIndex: number): Promise; + getAll(): Promise; + getIsPrimary(designOptionIndex: number): Promise; + getAllIsPrimary(): Promise; + getElementIndex(designOptionIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(designOptionIndex: number): Promise; +} +export declare class DesignOption implements IDesignOption { + index: number; + isPrimary?: boolean; + elementIndex?: number; + element?: IElement; + static createFromTable(table: IDesignOptionTable, index: number): Promise; +} +export declare class DesignOptionTable implements IDesignOptionTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(designOptionIndex: number): Promise; + getAll(): Promise; + getIsPrimary(designOptionIndex: number): Promise; + getAllIsPrimary(): Promise; + getElementIndex(designOptionIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(designOptionIndex: number): Promise; +} +export interface ILevel { + index: number; + elevation?: number; + familyTypeIndex?: number; + familyType?: IFamilyType; + elementIndex?: number; + element?: IElement; +} +export interface ILevelTable { + getCount(): Promise; + get(levelIndex: number): Promise; + getAll(): Promise; + getElevation(levelIndex: number): Promise; + getAllElevation(): Promise; + getFamilyTypeIndex(levelIndex: number): Promise; + getAllFamilyTypeIndex(): Promise; + getFamilyType(levelIndex: number): Promise; + getElementIndex(levelIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(levelIndex: number): Promise; +} +export declare class Level implements ILevel { + index: number; + elevation?: number; + familyTypeIndex?: number; + familyType?: IFamilyType; + elementIndex?: number; + element?: IElement; + static createFromTable(table: ILevelTable, index: number): Promise; +} +export declare class LevelTable implements ILevelTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(levelIndex: number): Promise; + getAll(): Promise; + getElevation(levelIndex: number): Promise; + getAllElevation(): Promise; + getFamilyTypeIndex(levelIndex: number): Promise; + getAllFamilyTypeIndex(): Promise; + getFamilyType(levelIndex: number): Promise; + getElementIndex(levelIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(levelIndex: number): Promise; +} +export interface IPhase { + index: number; + elementIndex?: number; + element?: IElement; +} +export interface IPhaseTable { + getCount(): Promise; + get(phaseIndex: number): Promise; + getAll(): Promise; + getElementIndex(phaseIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(phaseIndex: number): Promise; +} +export declare class Phase implements IPhase { + index: number; + elementIndex?: number; + element?: IElement; + static createFromTable(table: IPhaseTable, index: number): Promise; +} +export declare class PhaseTable implements IPhaseTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(phaseIndex: number): Promise; + getAll(): Promise; + getElementIndex(phaseIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(phaseIndex: number): Promise; +} +export interface IRoom { + index: number; + baseOffset?: number; + limitOffset?: number; + unboundedHeight?: number; + volume?: number; + perimeter?: number; + area?: number; + number?: string; + upperLimitIndex?: number; + upperLimit?: ILevel; + elementIndex?: number; + element?: IElement; +} +export interface IRoomTable { + getCount(): Promise; + get(roomIndex: number): Promise; + getAll(): Promise; + getBaseOffset(roomIndex: number): Promise; + getAllBaseOffset(): Promise; + getLimitOffset(roomIndex: number): Promise; + getAllLimitOffset(): Promise; + getUnboundedHeight(roomIndex: number): Promise; + getAllUnboundedHeight(): Promise; + getVolume(roomIndex: number): Promise; + getAllVolume(): Promise; + getPerimeter(roomIndex: number): Promise; + getAllPerimeter(): Promise; + getArea(roomIndex: number): Promise; + getAllArea(): Promise; + getNumber(roomIndex: number): Promise; + getAllNumber(): Promise; + getUpperLimitIndex(roomIndex: number): Promise; + getAllUpperLimitIndex(): Promise; + getUpperLimit(roomIndex: number): Promise; + getElementIndex(roomIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(roomIndex: number): Promise; +} +export declare class Room implements IRoom { + index: number; + baseOffset?: number; + limitOffset?: number; + unboundedHeight?: number; + volume?: number; + perimeter?: number; + area?: number; + number?: string; + upperLimitIndex?: number; + upperLimit?: ILevel; + elementIndex?: number; + element?: IElement; + static createFromTable(table: IRoomTable, index: number): Promise; +} +export declare class RoomTable implements IRoomTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(roomIndex: number): Promise; + getAll(): Promise; + getBaseOffset(roomIndex: number): Promise; + getAllBaseOffset(): Promise; + getLimitOffset(roomIndex: number): Promise; + getAllLimitOffset(): Promise; + getUnboundedHeight(roomIndex: number): Promise; + getAllUnboundedHeight(): Promise; + getVolume(roomIndex: number): Promise; + getAllVolume(): Promise; + getPerimeter(roomIndex: number): Promise; + getAllPerimeter(): Promise; + getArea(roomIndex: number): Promise; + getAllArea(): Promise; + getNumber(roomIndex: number): Promise; + getAllNumber(): Promise; + getUpperLimitIndex(roomIndex: number): Promise; + getAllUpperLimitIndex(): Promise; + getUpperLimit(roomIndex: number): Promise; + getElementIndex(roomIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(roomIndex: number): Promise; +} +export interface IBimDocument { + index: number; + title?: string; + isMetric?: boolean; + guid?: string; + numSaves?: number; + isLinked?: boolean; + isDetached?: boolean; + isWorkshared?: boolean; + pathName?: string; + latitude?: number; + longitude?: number; + timeZone?: number; + placeName?: string; + weatherStationName?: string; + elevation?: number; + projectLocation?: string; + issueDate?: string; + status?: string; + clientName?: string; + address?: string; + name?: string; + number?: string; + author?: string; + buildingName?: string; + organizationName?: string; + organizationDescription?: string; + product?: string; + version?: string; + user?: string; + activeViewIndex?: number; + activeView?: IView; + ownerFamilyIndex?: number; + ownerFamily?: IFamily; + parentIndex?: number; + parent?: IBimDocument; + elementIndex?: number; + element?: IElement; +} +export interface IBimDocumentTable { + getCount(): Promise; + get(bimDocumentIndex: number): Promise; + getAll(): Promise; + getTitle(bimDocumentIndex: number): Promise; + getAllTitle(): Promise; + getIsMetric(bimDocumentIndex: number): Promise; + getAllIsMetric(): Promise; + getGuid(bimDocumentIndex: number): Promise; + getAllGuid(): Promise; + getNumSaves(bimDocumentIndex: number): Promise; + getAllNumSaves(): Promise; + getIsLinked(bimDocumentIndex: number): Promise; + getAllIsLinked(): Promise; + getIsDetached(bimDocumentIndex: number): Promise; + getAllIsDetached(): Promise; + getIsWorkshared(bimDocumentIndex: number): Promise; + getAllIsWorkshared(): Promise; + getPathName(bimDocumentIndex: number): Promise; + getAllPathName(): Promise; + getLatitude(bimDocumentIndex: number): Promise; + getAllLatitude(): Promise; + getLongitude(bimDocumentIndex: number): Promise; + getAllLongitude(): Promise; + getTimeZone(bimDocumentIndex: number): Promise; + getAllTimeZone(): Promise; + getPlaceName(bimDocumentIndex: number): Promise; + getAllPlaceName(): Promise; + getWeatherStationName(bimDocumentIndex: number): Promise; + getAllWeatherStationName(): Promise; + getElevation(bimDocumentIndex: number): Promise; + getAllElevation(): Promise; + getProjectLocation(bimDocumentIndex: number): Promise; + getAllProjectLocation(): Promise; + getIssueDate(bimDocumentIndex: number): Promise; + getAllIssueDate(): Promise; + getStatus(bimDocumentIndex: number): Promise; + getAllStatus(): Promise; + getClientName(bimDocumentIndex: number): Promise; + getAllClientName(): Promise; + getAddress(bimDocumentIndex: number): Promise; + getAllAddress(): Promise; + getName(bimDocumentIndex: number): Promise; + getAllName(): Promise; + getNumber(bimDocumentIndex: number): Promise; + getAllNumber(): Promise; + getAuthor(bimDocumentIndex: number): Promise; + getAllAuthor(): Promise; + getBuildingName(bimDocumentIndex: number): Promise; + getAllBuildingName(): Promise; + getOrganizationName(bimDocumentIndex: number): Promise; + getAllOrganizationName(): Promise; + getOrganizationDescription(bimDocumentIndex: number): Promise; + getAllOrganizationDescription(): Promise; + getProduct(bimDocumentIndex: number): Promise; + getAllProduct(): Promise; + getVersion(bimDocumentIndex: number): Promise; + getAllVersion(): Promise; + getUser(bimDocumentIndex: number): Promise; + getAllUser(): Promise; + getActiveViewIndex(bimDocumentIndex: number): Promise; + getAllActiveViewIndex(): Promise; + getActiveView(bimDocumentIndex: number): Promise; + getOwnerFamilyIndex(bimDocumentIndex: number): Promise; + getAllOwnerFamilyIndex(): Promise; + getOwnerFamily(bimDocumentIndex: number): Promise; + getParentIndex(bimDocumentIndex: number): Promise; + getAllParentIndex(): Promise; + getParent(bimDocumentIndex: number): Promise; + getElementIndex(bimDocumentIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(bimDocumentIndex: number): Promise; +} +export declare class BimDocument implements IBimDocument { + index: number; + title?: string; + isMetric?: boolean; + guid?: string; + numSaves?: number; + isLinked?: boolean; + isDetached?: boolean; + isWorkshared?: boolean; + pathName?: string; + latitude?: number; + longitude?: number; + timeZone?: number; + placeName?: string; + weatherStationName?: string; + elevation?: number; + projectLocation?: string; + issueDate?: string; + status?: string; + clientName?: string; + address?: string; + name?: string; + number?: string; + author?: string; + buildingName?: string; + organizationName?: string; + organizationDescription?: string; + product?: string; + version?: string; + user?: string; + activeViewIndex?: number; + activeView?: IView; + ownerFamilyIndex?: number; + ownerFamily?: IFamily; + parentIndex?: number; + parent?: IBimDocument; + elementIndex?: number; + element?: IElement; + static createFromTable(table: IBimDocumentTable, index: number): Promise; +} +export declare class BimDocumentTable implements IBimDocumentTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(bimDocumentIndex: number): Promise; + getAll(): Promise; + getTitle(bimDocumentIndex: number): Promise; + getAllTitle(): Promise; + getIsMetric(bimDocumentIndex: number): Promise; + getAllIsMetric(): Promise; + getGuid(bimDocumentIndex: number): Promise; + getAllGuid(): Promise; + getNumSaves(bimDocumentIndex: number): Promise; + getAllNumSaves(): Promise; + getIsLinked(bimDocumentIndex: number): Promise; + getAllIsLinked(): Promise; + getIsDetached(bimDocumentIndex: number): Promise; + getAllIsDetached(): Promise; + getIsWorkshared(bimDocumentIndex: number): Promise; + getAllIsWorkshared(): Promise; + getPathName(bimDocumentIndex: number): Promise; + getAllPathName(): Promise; + getLatitude(bimDocumentIndex: number): Promise; + getAllLatitude(): Promise; + getLongitude(bimDocumentIndex: number): Promise; + getAllLongitude(): Promise; + getTimeZone(bimDocumentIndex: number): Promise; + getAllTimeZone(): Promise; + getPlaceName(bimDocumentIndex: number): Promise; + getAllPlaceName(): Promise; + getWeatherStationName(bimDocumentIndex: number): Promise; + getAllWeatherStationName(): Promise; + getElevation(bimDocumentIndex: number): Promise; + getAllElevation(): Promise; + getProjectLocation(bimDocumentIndex: number): Promise; + getAllProjectLocation(): Promise; + getIssueDate(bimDocumentIndex: number): Promise; + getAllIssueDate(): Promise; + getStatus(bimDocumentIndex: number): Promise; + getAllStatus(): Promise; + getClientName(bimDocumentIndex: number): Promise; + getAllClientName(): Promise; + getAddress(bimDocumentIndex: number): Promise; + getAllAddress(): Promise; + getName(bimDocumentIndex: number): Promise; + getAllName(): Promise; + getNumber(bimDocumentIndex: number): Promise; + getAllNumber(): Promise; + getAuthor(bimDocumentIndex: number): Promise; + getAllAuthor(): Promise; + getBuildingName(bimDocumentIndex: number): Promise; + getAllBuildingName(): Promise; + getOrganizationName(bimDocumentIndex: number): Promise; + getAllOrganizationName(): Promise; + getOrganizationDescription(bimDocumentIndex: number): Promise; + getAllOrganizationDescription(): Promise; + getProduct(bimDocumentIndex: number): Promise; + getAllProduct(): Promise; + getVersion(bimDocumentIndex: number): Promise; + getAllVersion(): Promise; + getUser(bimDocumentIndex: number): Promise; + getAllUser(): Promise; + getActiveViewIndex(bimDocumentIndex: number): Promise; + getAllActiveViewIndex(): Promise; + getActiveView(bimDocumentIndex: number): Promise; + getOwnerFamilyIndex(bimDocumentIndex: number): Promise; + getAllOwnerFamilyIndex(): Promise; + getOwnerFamily(bimDocumentIndex: number): Promise; + getParentIndex(bimDocumentIndex: number): Promise; + getAllParentIndex(): Promise; + getParent(bimDocumentIndex: number): Promise; + getElementIndex(bimDocumentIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(bimDocumentIndex: number): Promise; +} +export interface IDisplayUnitInBimDocument { + index: number; + displayUnitIndex?: number; + displayUnit?: IDisplayUnit; + bimDocumentIndex?: number; + bimDocument?: IBimDocument; +} +export interface IDisplayUnitInBimDocumentTable { + getCount(): Promise; + get(displayUnitInBimDocumentIndex: number): Promise; + getAll(): Promise; + getDisplayUnitIndex(displayUnitInBimDocumentIndex: number): Promise; + getAllDisplayUnitIndex(): Promise; + getDisplayUnit(displayUnitInBimDocumentIndex: number): Promise; + getBimDocumentIndex(displayUnitInBimDocumentIndex: number): Promise; + getAllBimDocumentIndex(): Promise; + getBimDocument(displayUnitInBimDocumentIndex: number): Promise; +} +export declare class DisplayUnitInBimDocument implements IDisplayUnitInBimDocument { + index: number; + displayUnitIndex?: number; + displayUnit?: IDisplayUnit; + bimDocumentIndex?: number; + bimDocument?: IBimDocument; + static createFromTable(table: IDisplayUnitInBimDocumentTable, index: number): Promise; +} +export declare class DisplayUnitInBimDocumentTable implements IDisplayUnitInBimDocumentTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(displayUnitInBimDocumentIndex: number): Promise; + getAll(): Promise; + getDisplayUnitIndex(displayUnitInBimDocumentIndex: number): Promise; + getAllDisplayUnitIndex(): Promise; + getDisplayUnit(displayUnitInBimDocumentIndex: number): Promise; + getBimDocumentIndex(displayUnitInBimDocumentIndex: number): Promise; + getAllBimDocumentIndex(): Promise; + getBimDocument(displayUnitInBimDocumentIndex: number): Promise; +} +export interface IPhaseOrderInBimDocument { + index: number; + orderIndex?: number; + phaseIndex?: number; + phase?: IPhase; + bimDocumentIndex?: number; + bimDocument?: IBimDocument; +} +export interface IPhaseOrderInBimDocumentTable { + getCount(): Promise; + get(phaseOrderInBimDocumentIndex: number): Promise; + getAll(): Promise; + getOrderIndex(phaseOrderInBimDocumentIndex: number): Promise; + getAllOrderIndex(): Promise; + getPhaseIndex(phaseOrderInBimDocumentIndex: number): Promise; + getAllPhaseIndex(): Promise; + getPhase(phaseOrderInBimDocumentIndex: number): Promise; + getBimDocumentIndex(phaseOrderInBimDocumentIndex: number): Promise; + getAllBimDocumentIndex(): Promise; + getBimDocument(phaseOrderInBimDocumentIndex: number): Promise; +} +export declare class PhaseOrderInBimDocument implements IPhaseOrderInBimDocument { + index: number; + orderIndex?: number; + phaseIndex?: number; + phase?: IPhase; + bimDocumentIndex?: number; + bimDocument?: IBimDocument; + static createFromTable(table: IPhaseOrderInBimDocumentTable, index: number): Promise; +} +export declare class PhaseOrderInBimDocumentTable implements IPhaseOrderInBimDocumentTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(phaseOrderInBimDocumentIndex: number): Promise; + getAll(): Promise; + getOrderIndex(phaseOrderInBimDocumentIndex: number): Promise; + getAllOrderIndex(): Promise; + getPhaseIndex(phaseOrderInBimDocumentIndex: number): Promise; + getAllPhaseIndex(): Promise; + getPhase(phaseOrderInBimDocumentIndex: number): Promise; + getBimDocumentIndex(phaseOrderInBimDocumentIndex: number): Promise; + getAllBimDocumentIndex(): Promise; + getBimDocument(phaseOrderInBimDocumentIndex: number): Promise; +} +export interface ICategory { + index: number; + name?: string; + id?: bigint; + categoryType?: string; + lineColor_X?: number; + lineColor_Y?: number; + lineColor_Z?: number; + builtInCategory?: string; + parentIndex?: number; + parent?: ICategory; + materialIndex?: number; + material?: IMaterial; +} +export interface ICategoryTable { + getCount(): Promise; + get(categoryIndex: number): Promise; + getAll(): Promise; + getName(categoryIndex: number): Promise; + getAllName(): Promise; + getId(categoryIndex: number): Promise; + getAllId(): Promise; + getCategoryType(categoryIndex: number): Promise; + getAllCategoryType(): Promise; + getLineColor_X(categoryIndex: number): Promise; + getAllLineColor_X(): Promise; + getLineColor_Y(categoryIndex: number): Promise; + getAllLineColor_Y(): Promise; + getLineColor_Z(categoryIndex: number): Promise; + getAllLineColor_Z(): Promise; + getBuiltInCategory(categoryIndex: number): Promise; + getAllBuiltInCategory(): Promise; + getParentIndex(categoryIndex: number): Promise; + getAllParentIndex(): Promise; + getParent(categoryIndex: number): Promise; + getMaterialIndex(categoryIndex: number): Promise; + getAllMaterialIndex(): Promise; + getMaterial(categoryIndex: number): Promise; +} +export declare class Category implements ICategory { + index: number; + name?: string; + id?: bigint; + categoryType?: string; + lineColor_X?: number; + lineColor_Y?: number; + lineColor_Z?: number; + builtInCategory?: string; + parentIndex?: number; + parent?: ICategory; + materialIndex?: number; + material?: IMaterial; + static createFromTable(table: ICategoryTable, index: number): Promise; +} +export declare class CategoryTable implements ICategoryTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(categoryIndex: number): Promise; + getAll(): Promise; + getName(categoryIndex: number): Promise; + getAllName(): Promise; + getId(categoryIndex: number): Promise; + getAllId(): Promise; + getCategoryType(categoryIndex: number): Promise; + getAllCategoryType(): Promise; + getLineColor_X(categoryIndex: number): Promise; + getAllLineColor_X(): Promise; + getLineColor_Y(categoryIndex: number): Promise; + getAllLineColor_Y(): Promise; + getLineColor_Z(categoryIndex: number): Promise; + getAllLineColor_Z(): Promise; + getBuiltInCategory(categoryIndex: number): Promise; + getAllBuiltInCategory(): Promise; + getParentIndex(categoryIndex: number): Promise; + getAllParentIndex(): Promise; + getParent(categoryIndex: number): Promise; + getMaterialIndex(categoryIndex: number): Promise; + getAllMaterialIndex(): Promise; + getMaterial(categoryIndex: number): Promise; +} +export interface IFamily { + index: number; + structuralMaterialType?: string; + structuralSectionShape?: string; + isSystemFamily?: boolean; + isInPlace?: boolean; + familyCategoryIndex?: number; + familyCategory?: ICategory; + elementIndex?: number; + element?: IElement; +} +export interface IFamilyTable { + getCount(): Promise; + get(familyIndex: number): Promise; + getAll(): Promise; + getStructuralMaterialType(familyIndex: number): Promise; + getAllStructuralMaterialType(): Promise; + getStructuralSectionShape(familyIndex: number): Promise; + getAllStructuralSectionShape(): Promise; + getIsSystemFamily(familyIndex: number): Promise; + getAllIsSystemFamily(): Promise; + getIsInPlace(familyIndex: number): Promise; + getAllIsInPlace(): Promise; + getFamilyCategoryIndex(familyIndex: number): Promise; + getAllFamilyCategoryIndex(): Promise; + getFamilyCategory(familyIndex: number): Promise; + getElementIndex(familyIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(familyIndex: number): Promise; +} +export declare class Family implements IFamily { + index: number; + structuralMaterialType?: string; + structuralSectionShape?: string; + isSystemFamily?: boolean; + isInPlace?: boolean; + familyCategoryIndex?: number; + familyCategory?: ICategory; + elementIndex?: number; + element?: IElement; + static createFromTable(table: IFamilyTable, index: number): Promise; +} +export declare class FamilyTable implements IFamilyTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(familyIndex: number): Promise; + getAll(): Promise; + getStructuralMaterialType(familyIndex: number): Promise; + getAllStructuralMaterialType(): Promise; + getStructuralSectionShape(familyIndex: number): Promise; + getAllStructuralSectionShape(): Promise; + getIsSystemFamily(familyIndex: number): Promise; + getAllIsSystemFamily(): Promise; + getIsInPlace(familyIndex: number): Promise; + getAllIsInPlace(): Promise; + getFamilyCategoryIndex(familyIndex: number): Promise; + getAllFamilyCategoryIndex(): Promise; + getFamilyCategory(familyIndex: number): Promise; + getElementIndex(familyIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(familyIndex: number): Promise; +} +export interface IFamilyType { + index: number; + isSystemFamilyType?: boolean; + familyIndex?: number; + family?: IFamily; + compoundStructureIndex?: number; + compoundStructure?: ICompoundStructure; + elementIndex?: number; + element?: IElement; +} +export interface IFamilyTypeTable { + getCount(): Promise; + get(familyTypeIndex: number): Promise; + getAll(): Promise; + getIsSystemFamilyType(familyTypeIndex: number): Promise; + getAllIsSystemFamilyType(): Promise; + getFamilyIndex(familyTypeIndex: number): Promise; + getAllFamilyIndex(): Promise; + getFamily(familyTypeIndex: number): Promise; + getCompoundStructureIndex(familyTypeIndex: number): Promise; + getAllCompoundStructureIndex(): Promise; + getCompoundStructure(familyTypeIndex: number): Promise; + getElementIndex(familyTypeIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(familyTypeIndex: number): Promise; +} +export declare class FamilyType implements IFamilyType { + index: number; + isSystemFamilyType?: boolean; + familyIndex?: number; + family?: IFamily; + compoundStructureIndex?: number; + compoundStructure?: ICompoundStructure; + elementIndex?: number; + element?: IElement; + static createFromTable(table: IFamilyTypeTable, index: number): Promise; +} +export declare class FamilyTypeTable implements IFamilyTypeTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(familyTypeIndex: number): Promise; + getAll(): Promise; + getIsSystemFamilyType(familyTypeIndex: number): Promise; + getAllIsSystemFamilyType(): Promise; + getFamilyIndex(familyTypeIndex: number): Promise; + getAllFamilyIndex(): Promise; + getFamily(familyTypeIndex: number): Promise; + getCompoundStructureIndex(familyTypeIndex: number): Promise; + getAllCompoundStructureIndex(): Promise; + getCompoundStructure(familyTypeIndex: number): Promise; + getElementIndex(familyTypeIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(familyTypeIndex: number): Promise; +} +export interface IFamilyInstance { + index: number; + facingFlipped?: boolean; + facingOrientation_X?: number; + facingOrientation_Y?: number; + facingOrientation_Z?: number; + handFlipped?: boolean; + mirrored?: boolean; + hasModifiedGeometry?: boolean; + scale?: number; + basisX_X?: number; + basisX_Y?: number; + basisX_Z?: number; + basisY_X?: number; + basisY_Y?: number; + basisY_Z?: number; + basisZ_X?: number; + basisZ_Y?: number; + basisZ_Z?: number; + translation_X?: number; + translation_Y?: number; + translation_Z?: number; + handOrientation_X?: number; + handOrientation_Y?: number; + handOrientation_Z?: number; + familyTypeIndex?: number; + familyType?: IFamilyType; + hostIndex?: number; + host?: IElement; + fromRoomIndex?: number; + fromRoom?: IRoom; + toRoomIndex?: number; + toRoom?: IRoom; + elementIndex?: number; + element?: IElement; +} +export interface IFamilyInstanceTable { + getCount(): Promise; + get(familyInstanceIndex: number): Promise; + getAll(): Promise; + getFacingFlipped(familyInstanceIndex: number): Promise; + getAllFacingFlipped(): Promise; + getFacingOrientation_X(familyInstanceIndex: number): Promise; + getAllFacingOrientation_X(): Promise; + getFacingOrientation_Y(familyInstanceIndex: number): Promise; + getAllFacingOrientation_Y(): Promise; + getFacingOrientation_Z(familyInstanceIndex: number): Promise; + getAllFacingOrientation_Z(): Promise; + getHandFlipped(familyInstanceIndex: number): Promise; + getAllHandFlipped(): Promise; + getMirrored(familyInstanceIndex: number): Promise; + getAllMirrored(): Promise; + getHasModifiedGeometry(familyInstanceIndex: number): Promise; + getAllHasModifiedGeometry(): Promise; + getScale(familyInstanceIndex: number): Promise; + getAllScale(): Promise; + getBasisX_X(familyInstanceIndex: number): Promise; + getAllBasisX_X(): Promise; + getBasisX_Y(familyInstanceIndex: number): Promise; + getAllBasisX_Y(): Promise; + getBasisX_Z(familyInstanceIndex: number): Promise; + getAllBasisX_Z(): Promise; + getBasisY_X(familyInstanceIndex: number): Promise; + getAllBasisY_X(): Promise; + getBasisY_Y(familyInstanceIndex: number): Promise; + getAllBasisY_Y(): Promise; + getBasisY_Z(familyInstanceIndex: number): Promise; + getAllBasisY_Z(): Promise; + getBasisZ_X(familyInstanceIndex: number): Promise; + getAllBasisZ_X(): Promise; + getBasisZ_Y(familyInstanceIndex: number): Promise; + getAllBasisZ_Y(): Promise; + getBasisZ_Z(familyInstanceIndex: number): Promise; + getAllBasisZ_Z(): Promise; + getTranslation_X(familyInstanceIndex: number): Promise; + getAllTranslation_X(): Promise; + getTranslation_Y(familyInstanceIndex: number): Promise; + getAllTranslation_Y(): Promise; + getTranslation_Z(familyInstanceIndex: number): Promise; + getAllTranslation_Z(): Promise; + getHandOrientation_X(familyInstanceIndex: number): Promise; + getAllHandOrientation_X(): Promise; + getHandOrientation_Y(familyInstanceIndex: number): Promise; + getAllHandOrientation_Y(): Promise; + getHandOrientation_Z(familyInstanceIndex: number): Promise; + getAllHandOrientation_Z(): Promise; + getFamilyTypeIndex(familyInstanceIndex: number): Promise; + getAllFamilyTypeIndex(): Promise; + getFamilyType(familyInstanceIndex: number): Promise; + getHostIndex(familyInstanceIndex: number): Promise; + getAllHostIndex(): Promise; + getHost(familyInstanceIndex: number): Promise; + getFromRoomIndex(familyInstanceIndex: number): Promise; + getAllFromRoomIndex(): Promise; + getFromRoom(familyInstanceIndex: number): Promise; + getToRoomIndex(familyInstanceIndex: number): Promise; + getAllToRoomIndex(): Promise; + getToRoom(familyInstanceIndex: number): Promise; + getElementIndex(familyInstanceIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(familyInstanceIndex: number): Promise; +} +export declare class FamilyInstance implements IFamilyInstance { + index: number; + facingFlipped?: boolean; + facingOrientation_X?: number; + facingOrientation_Y?: number; + facingOrientation_Z?: number; + handFlipped?: boolean; + mirrored?: boolean; + hasModifiedGeometry?: boolean; + scale?: number; + basisX_X?: number; + basisX_Y?: number; + basisX_Z?: number; + basisY_X?: number; + basisY_Y?: number; + basisY_Z?: number; + basisZ_X?: number; + basisZ_Y?: number; + basisZ_Z?: number; + translation_X?: number; + translation_Y?: number; + translation_Z?: number; + handOrientation_X?: number; + handOrientation_Y?: number; + handOrientation_Z?: number; + familyTypeIndex?: number; + familyType?: IFamilyType; + hostIndex?: number; + host?: IElement; + fromRoomIndex?: number; + fromRoom?: IRoom; + toRoomIndex?: number; + toRoom?: IRoom; + elementIndex?: number; + element?: IElement; + static createFromTable(table: IFamilyInstanceTable, index: number): Promise; +} +export declare class FamilyInstanceTable implements IFamilyInstanceTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(familyInstanceIndex: number): Promise; + getAll(): Promise; + getFacingFlipped(familyInstanceIndex: number): Promise; + getAllFacingFlipped(): Promise; + getFacingOrientation_X(familyInstanceIndex: number): Promise; + getAllFacingOrientation_X(): Promise; + getFacingOrientation_Y(familyInstanceIndex: number): Promise; + getAllFacingOrientation_Y(): Promise; + getFacingOrientation_Z(familyInstanceIndex: number): Promise; + getAllFacingOrientation_Z(): Promise; + getHandFlipped(familyInstanceIndex: number): Promise; + getAllHandFlipped(): Promise; + getMirrored(familyInstanceIndex: number): Promise; + getAllMirrored(): Promise; + getHasModifiedGeometry(familyInstanceIndex: number): Promise; + getAllHasModifiedGeometry(): Promise; + getScale(familyInstanceIndex: number): Promise; + getAllScale(): Promise; + getBasisX_X(familyInstanceIndex: number): Promise; + getAllBasisX_X(): Promise; + getBasisX_Y(familyInstanceIndex: number): Promise; + getAllBasisX_Y(): Promise; + getBasisX_Z(familyInstanceIndex: number): Promise; + getAllBasisX_Z(): Promise; + getBasisY_X(familyInstanceIndex: number): Promise; + getAllBasisY_X(): Promise; + getBasisY_Y(familyInstanceIndex: number): Promise; + getAllBasisY_Y(): Promise; + getBasisY_Z(familyInstanceIndex: number): Promise; + getAllBasisY_Z(): Promise; + getBasisZ_X(familyInstanceIndex: number): Promise; + getAllBasisZ_X(): Promise; + getBasisZ_Y(familyInstanceIndex: number): Promise; + getAllBasisZ_Y(): Promise; + getBasisZ_Z(familyInstanceIndex: number): Promise; + getAllBasisZ_Z(): Promise; + getTranslation_X(familyInstanceIndex: number): Promise; + getAllTranslation_X(): Promise; + getTranslation_Y(familyInstanceIndex: number): Promise; + getAllTranslation_Y(): Promise; + getTranslation_Z(familyInstanceIndex: number): Promise; + getAllTranslation_Z(): Promise; + getHandOrientation_X(familyInstanceIndex: number): Promise; + getAllHandOrientation_X(): Promise; + getHandOrientation_Y(familyInstanceIndex: number): Promise; + getAllHandOrientation_Y(): Promise; + getHandOrientation_Z(familyInstanceIndex: number): Promise; + getAllHandOrientation_Z(): Promise; + getFamilyTypeIndex(familyInstanceIndex: number): Promise; + getAllFamilyTypeIndex(): Promise; + getFamilyType(familyInstanceIndex: number): Promise; + getHostIndex(familyInstanceIndex: number): Promise; + getAllHostIndex(): Promise; + getHost(familyInstanceIndex: number): Promise; + getFromRoomIndex(familyInstanceIndex: number): Promise; + getAllFromRoomIndex(): Promise; + getFromRoom(familyInstanceIndex: number): Promise; + getToRoomIndex(familyInstanceIndex: number): Promise; + getAllToRoomIndex(): Promise; + getToRoom(familyInstanceIndex: number): Promise; + getElementIndex(familyInstanceIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(familyInstanceIndex: number): Promise; +} +export interface IView { + index: number; + title?: string; + viewType?: string; + up_X?: number; + up_Y?: number; + up_Z?: number; + right_X?: number; + right_Y?: number; + right_Z?: number; + origin_X?: number; + origin_Y?: number; + origin_Z?: number; + viewDirection_X?: number; + viewDirection_Y?: number; + viewDirection_Z?: number; + viewPosition_X?: number; + viewPosition_Y?: number; + viewPosition_Z?: number; + scale?: number; + outline_Min_X?: number; + outline_Min_Y?: number; + outline_Max_X?: number; + outline_Max_Y?: number; + detailLevel?: number; + cameraIndex?: number; + camera?: ICamera; + familyTypeIndex?: number; + familyType?: IFamilyType; + elementIndex?: number; + element?: IElement; +} +export interface IViewTable { + getCount(): Promise; + get(viewIndex: number): Promise; + getAll(): Promise; + getTitle(viewIndex: number): Promise; + getAllTitle(): Promise; + getViewType(viewIndex: number): Promise; + getAllViewType(): Promise; + getUp_X(viewIndex: number): Promise; + getAllUp_X(): Promise; + getUp_Y(viewIndex: number): Promise; + getAllUp_Y(): Promise; + getUp_Z(viewIndex: number): Promise; + getAllUp_Z(): Promise; + getRight_X(viewIndex: number): Promise; + getAllRight_X(): Promise; + getRight_Y(viewIndex: number): Promise; + getAllRight_Y(): Promise; + getRight_Z(viewIndex: number): Promise; + getAllRight_Z(): Promise; + getOrigin_X(viewIndex: number): Promise; + getAllOrigin_X(): Promise; + getOrigin_Y(viewIndex: number): Promise; + getAllOrigin_Y(): Promise; + getOrigin_Z(viewIndex: number): Promise; + getAllOrigin_Z(): Promise; + getViewDirection_X(viewIndex: number): Promise; + getAllViewDirection_X(): Promise; + getViewDirection_Y(viewIndex: number): Promise; + getAllViewDirection_Y(): Promise; + getViewDirection_Z(viewIndex: number): Promise; + getAllViewDirection_Z(): Promise; + getViewPosition_X(viewIndex: number): Promise; + getAllViewPosition_X(): Promise; + getViewPosition_Y(viewIndex: number): Promise; + getAllViewPosition_Y(): Promise; + getViewPosition_Z(viewIndex: number): Promise; + getAllViewPosition_Z(): Promise; + getScale(viewIndex: number): Promise; + getAllScale(): Promise; + getOutline_Min_X(viewIndex: number): Promise; + getAllOutline_Min_X(): Promise; + getOutline_Min_Y(viewIndex: number): Promise; + getAllOutline_Min_Y(): Promise; + getOutline_Max_X(viewIndex: number): Promise; + getAllOutline_Max_X(): Promise; + getOutline_Max_Y(viewIndex: number): Promise; + getAllOutline_Max_Y(): Promise; + getDetailLevel(viewIndex: number): Promise; + getAllDetailLevel(): Promise; + getCameraIndex(viewIndex: number): Promise; + getAllCameraIndex(): Promise; + getCamera(viewIndex: number): Promise; + getFamilyTypeIndex(viewIndex: number): Promise; + getAllFamilyTypeIndex(): Promise; + getFamilyType(viewIndex: number): Promise; + getElementIndex(viewIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(viewIndex: number): Promise; +} +export declare class View implements IView { + index: number; + title?: string; + viewType?: string; + up_X?: number; + up_Y?: number; + up_Z?: number; + right_X?: number; + right_Y?: number; + right_Z?: number; + origin_X?: number; + origin_Y?: number; + origin_Z?: number; + viewDirection_X?: number; + viewDirection_Y?: number; + viewDirection_Z?: number; + viewPosition_X?: number; + viewPosition_Y?: number; + viewPosition_Z?: number; + scale?: number; + outline_Min_X?: number; + outline_Min_Y?: number; + outline_Max_X?: number; + outline_Max_Y?: number; + detailLevel?: number; + cameraIndex?: number; + camera?: ICamera; + familyTypeIndex?: number; + familyType?: IFamilyType; + elementIndex?: number; + element?: IElement; + static createFromTable(table: IViewTable, index: number): Promise; +} +export declare class ViewTable implements IViewTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(viewIndex: number): Promise; + getAll(): Promise; + getTitle(viewIndex: number): Promise; + getAllTitle(): Promise; + getViewType(viewIndex: number): Promise; + getAllViewType(): Promise; + getUp_X(viewIndex: number): Promise; + getAllUp_X(): Promise; + getUp_Y(viewIndex: number): Promise; + getAllUp_Y(): Promise; + getUp_Z(viewIndex: number): Promise; + getAllUp_Z(): Promise; + getRight_X(viewIndex: number): Promise; + getAllRight_X(): Promise; + getRight_Y(viewIndex: number): Promise; + getAllRight_Y(): Promise; + getRight_Z(viewIndex: number): Promise; + getAllRight_Z(): Promise; + getOrigin_X(viewIndex: number): Promise; + getAllOrigin_X(): Promise; + getOrigin_Y(viewIndex: number): Promise; + getAllOrigin_Y(): Promise; + getOrigin_Z(viewIndex: number): Promise; + getAllOrigin_Z(): Promise; + getViewDirection_X(viewIndex: number): Promise; + getAllViewDirection_X(): Promise; + getViewDirection_Y(viewIndex: number): Promise; + getAllViewDirection_Y(): Promise; + getViewDirection_Z(viewIndex: number): Promise; + getAllViewDirection_Z(): Promise; + getViewPosition_X(viewIndex: number): Promise; + getAllViewPosition_X(): Promise; + getViewPosition_Y(viewIndex: number): Promise; + getAllViewPosition_Y(): Promise; + getViewPosition_Z(viewIndex: number): Promise; + getAllViewPosition_Z(): Promise; + getScale(viewIndex: number): Promise; + getAllScale(): Promise; + getOutline_Min_X(viewIndex: number): Promise; + getAllOutline_Min_X(): Promise; + getOutline_Min_Y(viewIndex: number): Promise; + getAllOutline_Min_Y(): Promise; + getOutline_Max_X(viewIndex: number): Promise; + getAllOutline_Max_X(): Promise; + getOutline_Max_Y(viewIndex: number): Promise; + getAllOutline_Max_Y(): Promise; + getDetailLevel(viewIndex: number): Promise; + getAllDetailLevel(): Promise; + getCameraIndex(viewIndex: number): Promise; + getAllCameraIndex(): Promise; + getCamera(viewIndex: number): Promise; + getFamilyTypeIndex(viewIndex: number): Promise; + getAllFamilyTypeIndex(): Promise; + getFamilyType(viewIndex: number): Promise; + getElementIndex(viewIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(viewIndex: number): Promise; +} +export interface IElementInView { + index: number; + viewIndex?: number; + view?: IView; + elementIndex?: number; + element?: IElement; +} +export interface IElementInViewTable { + getCount(): Promise; + get(elementInViewIndex: number): Promise; + getAll(): Promise; + getViewIndex(elementInViewIndex: number): Promise; + getAllViewIndex(): Promise; + getView(elementInViewIndex: number): Promise; + getElementIndex(elementInViewIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(elementInViewIndex: number): Promise; +} +export declare class ElementInView implements IElementInView { + index: number; + viewIndex?: number; + view?: IView; + elementIndex?: number; + element?: IElement; + static createFromTable(table: IElementInViewTable, index: number): Promise; +} +export declare class ElementInViewTable implements IElementInViewTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(elementInViewIndex: number): Promise; + getAll(): Promise; + getViewIndex(elementInViewIndex: number): Promise; + getAllViewIndex(): Promise; + getView(elementInViewIndex: number): Promise; + getElementIndex(elementInViewIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(elementInViewIndex: number): Promise; +} +export interface IShapeInView { + index: number; + shapeIndex?: number; + shape?: IShape; + viewIndex?: number; + view?: IView; +} +export interface IShapeInViewTable { + getCount(): Promise; + get(shapeInViewIndex: number): Promise; + getAll(): Promise; + getShapeIndex(shapeInViewIndex: number): Promise; + getAllShapeIndex(): Promise; + getShape(shapeInViewIndex: number): Promise; + getViewIndex(shapeInViewIndex: number): Promise; + getAllViewIndex(): Promise; + getView(shapeInViewIndex: number): Promise; +} +export declare class ShapeInView implements IShapeInView { + index: number; + shapeIndex?: number; + shape?: IShape; + viewIndex?: number; + view?: IView; + static createFromTable(table: IShapeInViewTable, index: number): Promise; +} +export declare class ShapeInViewTable implements IShapeInViewTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(shapeInViewIndex: number): Promise; + getAll(): Promise; + getShapeIndex(shapeInViewIndex: number): Promise; + getAllShapeIndex(): Promise; + getShape(shapeInViewIndex: number): Promise; + getViewIndex(shapeInViewIndex: number): Promise; + getAllViewIndex(): Promise; + getView(shapeInViewIndex: number): Promise; +} +export interface IAssetInView { + index: number; + assetIndex?: number; + asset?: IAsset; + viewIndex?: number; + view?: IView; +} +export interface IAssetInViewTable { + getCount(): Promise; + get(assetInViewIndex: number): Promise; + getAll(): Promise; + getAssetIndex(assetInViewIndex: number): Promise; + getAllAssetIndex(): Promise; + getAsset(assetInViewIndex: number): Promise; + getViewIndex(assetInViewIndex: number): Promise; + getAllViewIndex(): Promise; + getView(assetInViewIndex: number): Promise; +} +export declare class AssetInView implements IAssetInView { + index: number; + assetIndex?: number; + asset?: IAsset; + viewIndex?: number; + view?: IView; + static createFromTable(table: IAssetInViewTable, index: number): Promise; +} +export declare class AssetInViewTable implements IAssetInViewTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(assetInViewIndex: number): Promise; + getAll(): Promise; + getAssetIndex(assetInViewIndex: number): Promise; + getAllAssetIndex(): Promise; + getAsset(assetInViewIndex: number): Promise; + getViewIndex(assetInViewIndex: number): Promise; + getAllViewIndex(): Promise; + getView(assetInViewIndex: number): Promise; +} +export interface IAssetInViewSheet { + index: number; + assetIndex?: number; + asset?: IAsset; + viewSheetIndex?: number; + viewSheet?: IViewSheet; +} +export interface IAssetInViewSheetTable { + getCount(): Promise; + get(assetInViewSheetIndex: number): Promise; + getAll(): Promise; + getAssetIndex(assetInViewSheetIndex: number): Promise; + getAllAssetIndex(): Promise; + getAsset(assetInViewSheetIndex: number): Promise; + getViewSheetIndex(assetInViewSheetIndex: number): Promise; + getAllViewSheetIndex(): Promise; + getViewSheet(assetInViewSheetIndex: number): Promise; +} +export declare class AssetInViewSheet implements IAssetInViewSheet { + index: number; + assetIndex?: number; + asset?: IAsset; + viewSheetIndex?: number; + viewSheet?: IViewSheet; + static createFromTable(table: IAssetInViewSheetTable, index: number): Promise; +} +export declare class AssetInViewSheetTable implements IAssetInViewSheetTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(assetInViewSheetIndex: number): Promise; + getAll(): Promise; + getAssetIndex(assetInViewSheetIndex: number): Promise; + getAllAssetIndex(): Promise; + getAsset(assetInViewSheetIndex: number): Promise; + getViewSheetIndex(assetInViewSheetIndex: number): Promise; + getAllViewSheetIndex(): Promise; + getViewSheet(assetInViewSheetIndex: number): Promise; +} +export interface ILevelInView { + index: number; + extents_Min_X?: number; + extents_Min_Y?: number; + extents_Min_Z?: number; + extents_Max_X?: number; + extents_Max_Y?: number; + extents_Max_Z?: number; + levelIndex?: number; + level?: ILevel; + viewIndex?: number; + view?: IView; +} +export interface ILevelInViewTable { + getCount(): Promise; + get(levelInViewIndex: number): Promise; + getAll(): Promise; + getExtents_Min_X(levelInViewIndex: number): Promise; + getAllExtents_Min_X(): Promise; + getExtents_Min_Y(levelInViewIndex: number): Promise; + getAllExtents_Min_Y(): Promise; + getExtents_Min_Z(levelInViewIndex: number): Promise; + getAllExtents_Min_Z(): Promise; + getExtents_Max_X(levelInViewIndex: number): Promise; + getAllExtents_Max_X(): Promise; + getExtents_Max_Y(levelInViewIndex: number): Promise; + getAllExtents_Max_Y(): Promise; + getExtents_Max_Z(levelInViewIndex: number): Promise; + getAllExtents_Max_Z(): Promise; + getLevelIndex(levelInViewIndex: number): Promise; + getAllLevelIndex(): Promise; + getLevel(levelInViewIndex: number): Promise; + getViewIndex(levelInViewIndex: number): Promise; + getAllViewIndex(): Promise; + getView(levelInViewIndex: number): Promise; +} +export declare class LevelInView implements ILevelInView { + index: number; + extents_Min_X?: number; + extents_Min_Y?: number; + extents_Min_Z?: number; + extents_Max_X?: number; + extents_Max_Y?: number; + extents_Max_Z?: number; + levelIndex?: number; + level?: ILevel; + viewIndex?: number; + view?: IView; + static createFromTable(table: ILevelInViewTable, index: number): Promise; +} +export declare class LevelInViewTable implements ILevelInViewTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(levelInViewIndex: number): Promise; + getAll(): Promise; + getExtents_Min_X(levelInViewIndex: number): Promise; + getAllExtents_Min_X(): Promise; + getExtents_Min_Y(levelInViewIndex: number): Promise; + getAllExtents_Min_Y(): Promise; + getExtents_Min_Z(levelInViewIndex: number): Promise; + getAllExtents_Min_Z(): Promise; + getExtents_Max_X(levelInViewIndex: number): Promise; + getAllExtents_Max_X(): Promise; + getExtents_Max_Y(levelInViewIndex: number): Promise; + getAllExtents_Max_Y(): Promise; + getExtents_Max_Z(levelInViewIndex: number): Promise; + getAllExtents_Max_Z(): Promise; + getLevelIndex(levelInViewIndex: number): Promise; + getAllLevelIndex(): Promise; + getLevel(levelInViewIndex: number): Promise; + getViewIndex(levelInViewIndex: number): Promise; + getAllViewIndex(): Promise; + getView(levelInViewIndex: number): Promise; +} +export interface ICamera { + index: number; + id?: number; + isPerspective?: number; + verticalExtent?: number; + horizontalExtent?: number; + farDistance?: number; + nearDistance?: number; + targetDistance?: number; + rightOffset?: number; + upOffset?: number; +} +export interface ICameraTable { + getCount(): Promise; + get(cameraIndex: number): Promise; + getAll(): Promise; + getId(cameraIndex: number): Promise; + getAllId(): Promise; + getIsPerspective(cameraIndex: number): Promise; + getAllIsPerspective(): Promise; + getVerticalExtent(cameraIndex: number): Promise; + getAllVerticalExtent(): Promise; + getHorizontalExtent(cameraIndex: number): Promise; + getAllHorizontalExtent(): Promise; + getFarDistance(cameraIndex: number): Promise; + getAllFarDistance(): Promise; + getNearDistance(cameraIndex: number): Promise; + getAllNearDistance(): Promise; + getTargetDistance(cameraIndex: number): Promise; + getAllTargetDistance(): Promise; + getRightOffset(cameraIndex: number): Promise; + getAllRightOffset(): Promise; + getUpOffset(cameraIndex: number): Promise; + getAllUpOffset(): Promise; +} +export declare class Camera implements ICamera { + index: number; + id?: number; + isPerspective?: number; + verticalExtent?: number; + horizontalExtent?: number; + farDistance?: number; + nearDistance?: number; + targetDistance?: number; + rightOffset?: number; + upOffset?: number; + static createFromTable(table: ICameraTable, index: number): Promise; +} +export declare class CameraTable implements ICameraTable { + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(cameraIndex: number): Promise; + getAll(): Promise; + getId(cameraIndex: number): Promise; + getAllId(): Promise; + getIsPerspective(cameraIndex: number): Promise; + getAllIsPerspective(): Promise; + getVerticalExtent(cameraIndex: number): Promise; + getAllVerticalExtent(): Promise; + getHorizontalExtent(cameraIndex: number): Promise; + getAllHorizontalExtent(): Promise; + getFarDistance(cameraIndex: number): Promise; + getAllFarDistance(): Promise; + getNearDistance(cameraIndex: number): Promise; + getAllNearDistance(): Promise; + getTargetDistance(cameraIndex: number): Promise; + getAllTargetDistance(): Promise; + getRightOffset(cameraIndex: number): Promise; + getAllRightOffset(): Promise; + getUpOffset(cameraIndex: number): Promise; + getAllUpOffset(): Promise; +} +export interface IMaterial { + index: number; + name?: string; + materialCategory?: string; + color_X?: number; + color_Y?: number; + color_Z?: number; + colorUvScaling_X?: number; + colorUvScaling_Y?: number; + colorUvOffset_X?: number; + colorUvOffset_Y?: number; + normalUvScaling_X?: number; + normalUvScaling_Y?: number; + normalUvOffset_X?: number; + normalUvOffset_Y?: number; + normalAmount?: number; + glossiness?: number; + smoothness?: number; + transparency?: number; + colorTextureFileIndex?: number; + colorTextureFile?: IAsset; + normalTextureFileIndex?: number; + normalTextureFile?: IAsset; + elementIndex?: number; + element?: IElement; +} +export interface IMaterialTable { + getCount(): Promise; + get(materialIndex: number): Promise; + getAll(): Promise; + getName(materialIndex: number): Promise; + getAllName(): Promise; + getMaterialCategory(materialIndex: number): Promise; + getAllMaterialCategory(): Promise; + getColor_X(materialIndex: number): Promise; + getAllColor_X(): Promise; + getColor_Y(materialIndex: number): Promise; + getAllColor_Y(): Promise; + getColor_Z(materialIndex: number): Promise; + getAllColor_Z(): Promise; + getColorUvScaling_X(materialIndex: number): Promise; + getAllColorUvScaling_X(): Promise; + getColorUvScaling_Y(materialIndex: number): Promise; + getAllColorUvScaling_Y(): Promise; + getColorUvOffset_X(materialIndex: number): Promise; + getAllColorUvOffset_X(): Promise; + getColorUvOffset_Y(materialIndex: number): Promise; + getAllColorUvOffset_Y(): Promise; + getNormalUvScaling_X(materialIndex: number): Promise; + getAllNormalUvScaling_X(): Promise; + getNormalUvScaling_Y(materialIndex: number): Promise; + getAllNormalUvScaling_Y(): Promise; + getNormalUvOffset_X(materialIndex: number): Promise; + getAllNormalUvOffset_X(): Promise; + getNormalUvOffset_Y(materialIndex: number): Promise; + getAllNormalUvOffset_Y(): Promise; + getNormalAmount(materialIndex: number): Promise; + getAllNormalAmount(): Promise; + getGlossiness(materialIndex: number): Promise; + getAllGlossiness(): Promise; + getSmoothness(materialIndex: number): Promise; + getAllSmoothness(): Promise; + getTransparency(materialIndex: number): Promise; + getAllTransparency(): Promise; + getColorTextureFileIndex(materialIndex: number): Promise; + getAllColorTextureFileIndex(): Promise; + getColorTextureFile(materialIndex: number): Promise; + getNormalTextureFileIndex(materialIndex: number): Promise; + getAllNormalTextureFileIndex(): Promise; + getNormalTextureFile(materialIndex: number): Promise; + getElementIndex(materialIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(materialIndex: number): Promise; +} +export declare class Material implements IMaterial { + index: number; + name?: string; + materialCategory?: string; + color_X?: number; + color_Y?: number; + color_Z?: number; + colorUvScaling_X?: number; + colorUvScaling_Y?: number; + colorUvOffset_X?: number; + colorUvOffset_Y?: number; + normalUvScaling_X?: number; + normalUvScaling_Y?: number; + normalUvOffset_X?: number; + normalUvOffset_Y?: number; + normalAmount?: number; + glossiness?: number; + smoothness?: number; + transparency?: number; + colorTextureFileIndex?: number; + colorTextureFile?: IAsset; + normalTextureFileIndex?: number; + normalTextureFile?: IAsset; + elementIndex?: number; + element?: IElement; + static createFromTable(table: IMaterialTable, index: number): Promise; +} +export declare class MaterialTable implements IMaterialTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(materialIndex: number): Promise; + getAll(): Promise; + getName(materialIndex: number): Promise; + getAllName(): Promise; + getMaterialCategory(materialIndex: number): Promise; + getAllMaterialCategory(): Promise; + getColor_X(materialIndex: number): Promise; + getAllColor_X(): Promise; + getColor_Y(materialIndex: number): Promise; + getAllColor_Y(): Promise; + getColor_Z(materialIndex: number): Promise; + getAllColor_Z(): Promise; + getColorUvScaling_X(materialIndex: number): Promise; + getAllColorUvScaling_X(): Promise; + getColorUvScaling_Y(materialIndex: number): Promise; + getAllColorUvScaling_Y(): Promise; + getColorUvOffset_X(materialIndex: number): Promise; + getAllColorUvOffset_X(): Promise; + getColorUvOffset_Y(materialIndex: number): Promise; + getAllColorUvOffset_Y(): Promise; + getNormalUvScaling_X(materialIndex: number): Promise; + getAllNormalUvScaling_X(): Promise; + getNormalUvScaling_Y(materialIndex: number): Promise; + getAllNormalUvScaling_Y(): Promise; + getNormalUvOffset_X(materialIndex: number): Promise; + getAllNormalUvOffset_X(): Promise; + getNormalUvOffset_Y(materialIndex: number): Promise; + getAllNormalUvOffset_Y(): Promise; + getNormalAmount(materialIndex: number): Promise; + getAllNormalAmount(): Promise; + getGlossiness(materialIndex: number): Promise; + getAllGlossiness(): Promise; + getSmoothness(materialIndex: number): Promise; + getAllSmoothness(): Promise; + getTransparency(materialIndex: number): Promise; + getAllTransparency(): Promise; + getColorTextureFileIndex(materialIndex: number): Promise; + getAllColorTextureFileIndex(): Promise; + getColorTextureFile(materialIndex: number): Promise; + getNormalTextureFileIndex(materialIndex: number): Promise; + getAllNormalTextureFileIndex(): Promise; + getNormalTextureFile(materialIndex: number): Promise; + getElementIndex(materialIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(materialIndex: number): Promise; +} +export interface IMaterialInElement { + index: number; + area?: number; + volume?: number; + isPaint?: boolean; + materialIndex?: number; + material?: IMaterial; + elementIndex?: number; + element?: IElement; +} +export interface IMaterialInElementTable { + getCount(): Promise; + get(materialInElementIndex: number): Promise; + getAll(): Promise; + getArea(materialInElementIndex: number): Promise; + getAllArea(): Promise; + getVolume(materialInElementIndex: number): Promise; + getAllVolume(): Promise; + getIsPaint(materialInElementIndex: number): Promise; + getAllIsPaint(): Promise; + getMaterialIndex(materialInElementIndex: number): Promise; + getAllMaterialIndex(): Promise; + getMaterial(materialInElementIndex: number): Promise; + getElementIndex(materialInElementIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(materialInElementIndex: number): Promise; +} +export declare class MaterialInElement implements IMaterialInElement { + index: number; + area?: number; + volume?: number; + isPaint?: boolean; + materialIndex?: number; + material?: IMaterial; + elementIndex?: number; + element?: IElement; + static createFromTable(table: IMaterialInElementTable, index: number): Promise; +} +export declare class MaterialInElementTable implements IMaterialInElementTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(materialInElementIndex: number): Promise; + getAll(): Promise; + getArea(materialInElementIndex: number): Promise; + getAllArea(): Promise; + getVolume(materialInElementIndex: number): Promise; + getAllVolume(): Promise; + getIsPaint(materialInElementIndex: number): Promise; + getAllIsPaint(): Promise; + getMaterialIndex(materialInElementIndex: number): Promise; + getAllMaterialIndex(): Promise; + getMaterial(materialInElementIndex: number): Promise; + getElementIndex(materialInElementIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(materialInElementIndex: number): Promise; +} +export interface ICompoundStructureLayer { + index: number; + orderIndex?: number; + width?: number; + materialFunctionAssignment?: string; + materialIndex?: number; + material?: IMaterial; + compoundStructureIndex?: number; + compoundStructure?: ICompoundStructure; +} +export interface ICompoundStructureLayerTable { + getCount(): Promise; + get(compoundStructureLayerIndex: number): Promise; + getAll(): Promise; + getOrderIndex(compoundStructureLayerIndex: number): Promise; + getAllOrderIndex(): Promise; + getWidth(compoundStructureLayerIndex: number): Promise; + getAllWidth(): Promise; + getMaterialFunctionAssignment(compoundStructureLayerIndex: number): Promise; + getAllMaterialFunctionAssignment(): Promise; + getMaterialIndex(compoundStructureLayerIndex: number): Promise; + getAllMaterialIndex(): Promise; + getMaterial(compoundStructureLayerIndex: number): Promise; + getCompoundStructureIndex(compoundStructureLayerIndex: number): Promise; + getAllCompoundStructureIndex(): Promise; + getCompoundStructure(compoundStructureLayerIndex: number): Promise; +} +export declare class CompoundStructureLayer implements ICompoundStructureLayer { + index: number; + orderIndex?: number; + width?: number; + materialFunctionAssignment?: string; + materialIndex?: number; + material?: IMaterial; + compoundStructureIndex?: number; + compoundStructure?: ICompoundStructure; + static createFromTable(table: ICompoundStructureLayerTable, index: number): Promise; +} +export declare class CompoundStructureLayerTable implements ICompoundStructureLayerTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(compoundStructureLayerIndex: number): Promise; + getAll(): Promise; + getOrderIndex(compoundStructureLayerIndex: number): Promise; + getAllOrderIndex(): Promise; + getWidth(compoundStructureLayerIndex: number): Promise; + getAllWidth(): Promise; + getMaterialFunctionAssignment(compoundStructureLayerIndex: number): Promise; + getAllMaterialFunctionAssignment(): Promise; + getMaterialIndex(compoundStructureLayerIndex: number): Promise; + getAllMaterialIndex(): Promise; + getMaterial(compoundStructureLayerIndex: number): Promise; + getCompoundStructureIndex(compoundStructureLayerIndex: number): Promise; + getAllCompoundStructureIndex(): Promise; + getCompoundStructure(compoundStructureLayerIndex: number): Promise; +} +export interface ICompoundStructure { + index: number; + width?: number; + structuralLayerIndex?: number; + structuralLayer?: ICompoundStructureLayer; +} +export interface ICompoundStructureTable { + getCount(): Promise; + get(compoundStructureIndex: number): Promise; + getAll(): Promise; + getWidth(compoundStructureIndex: number): Promise; + getAllWidth(): Promise; + getStructuralLayerIndex(compoundStructureIndex: number): Promise; + getAllStructuralLayerIndex(): Promise; + getStructuralLayer(compoundStructureIndex: number): Promise; +} +export declare class CompoundStructure implements ICompoundStructure { + index: number; + width?: number; + structuralLayerIndex?: number; + structuralLayer?: ICompoundStructureLayer; + static createFromTable(table: ICompoundStructureTable, index: number): Promise; +} +export declare class CompoundStructureTable implements ICompoundStructureTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(compoundStructureIndex: number): Promise; + getAll(): Promise; + getWidth(compoundStructureIndex: number): Promise; + getAllWidth(): Promise; + getStructuralLayerIndex(compoundStructureIndex: number): Promise; + getAllStructuralLayerIndex(): Promise; + getStructuralLayer(compoundStructureIndex: number): Promise; +} +export interface INode { + index: number; + elementIndex?: number; + element?: IElement; +} +export interface INodeTable { + getCount(): Promise; + get(nodeIndex: number): Promise; + getAll(): Promise; + getElementIndex(nodeIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(nodeIndex: number): Promise; +} +export declare class Node implements INode { + index: number; + elementIndex?: number; + element?: IElement; + static createFromTable(table: INodeTable, index: number): Promise; +} +export declare class NodeTable implements INodeTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(nodeIndex: number): Promise; + getAll(): Promise; + getElementIndex(nodeIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(nodeIndex: number): Promise; +} +export interface IGeometry { + index: number; + box_Min_X?: number; + box_Min_Y?: number; + box_Min_Z?: number; + box_Max_X?: number; + box_Max_Y?: number; + box_Max_Z?: number; + vertexCount?: number; + faceCount?: number; +} +export interface IGeometryTable { + getCount(): Promise; + get(geometryIndex: number): Promise; + getAll(): Promise; + getBox_Min_X(geometryIndex: number): Promise; + getAllBox_Min_X(): Promise; + getBox_Min_Y(geometryIndex: number): Promise; + getAllBox_Min_Y(): Promise; + getBox_Min_Z(geometryIndex: number): Promise; + getAllBox_Min_Z(): Promise; + getBox_Max_X(geometryIndex: number): Promise; + getAllBox_Max_X(): Promise; + getBox_Max_Y(geometryIndex: number): Promise; + getAllBox_Max_Y(): Promise; + getBox_Max_Z(geometryIndex: number): Promise; + getAllBox_Max_Z(): Promise; + getVertexCount(geometryIndex: number): Promise; + getAllVertexCount(): Promise; + getFaceCount(geometryIndex: number): Promise; + getAllFaceCount(): Promise; +} +export declare class Geometry implements IGeometry { + index: number; + box_Min_X?: number; + box_Min_Y?: number; + box_Min_Z?: number; + box_Max_X?: number; + box_Max_Y?: number; + box_Max_Z?: number; + vertexCount?: number; + faceCount?: number; + static createFromTable(table: IGeometryTable, index: number): Promise; +} +export declare class GeometryTable implements IGeometryTable { + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(geometryIndex: number): Promise; + getAll(): Promise; + getBox_Min_X(geometryIndex: number): Promise; + getAllBox_Min_X(): Promise; + getBox_Min_Y(geometryIndex: number): Promise; + getAllBox_Min_Y(): Promise; + getBox_Min_Z(geometryIndex: number): Promise; + getAllBox_Min_Z(): Promise; + getBox_Max_X(geometryIndex: number): Promise; + getAllBox_Max_X(): Promise; + getBox_Max_Y(geometryIndex: number): Promise; + getAllBox_Max_Y(): Promise; + getBox_Max_Z(geometryIndex: number): Promise; + getAllBox_Max_Z(): Promise; + getVertexCount(geometryIndex: number): Promise; + getAllVertexCount(): Promise; + getFaceCount(geometryIndex: number): Promise; + getAllFaceCount(): Promise; +} +export interface IShape { + index: number; + elementIndex?: number; + element?: IElement; +} +export interface IShapeTable { + getCount(): Promise; + get(shapeIndex: number): Promise; + getAll(): Promise; + getElementIndex(shapeIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(shapeIndex: number): Promise; +} +export declare class Shape implements IShape { + index: number; + elementIndex?: number; + element?: IElement; + static createFromTable(table: IShapeTable, index: number): Promise; +} +export declare class ShapeTable implements IShapeTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(shapeIndex: number): Promise; + getAll(): Promise; + getElementIndex(shapeIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(shapeIndex: number): Promise; +} +export interface IShapeCollection { + index: number; + elementIndex?: number; + element?: IElement; +} +export interface IShapeCollectionTable { + getCount(): Promise; + get(shapeCollectionIndex: number): Promise; + getAll(): Promise; + getElementIndex(shapeCollectionIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(shapeCollectionIndex: number): Promise; +} +export declare class ShapeCollection implements IShapeCollection { + index: number; + elementIndex?: number; + element?: IElement; + static createFromTable(table: IShapeCollectionTable, index: number): Promise; +} +export declare class ShapeCollectionTable implements IShapeCollectionTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(shapeCollectionIndex: number): Promise; + getAll(): Promise; + getElementIndex(shapeCollectionIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(shapeCollectionIndex: number): Promise; +} +export interface IShapeInShapeCollection { + index: number; + shapeIndex?: number; + shape?: IShape; + shapeCollectionIndex?: number; + shapeCollection?: IShapeCollection; +} +export interface IShapeInShapeCollectionTable { + getCount(): Promise; + get(shapeInShapeCollectionIndex: number): Promise; + getAll(): Promise; + getShapeIndex(shapeInShapeCollectionIndex: number): Promise; + getAllShapeIndex(): Promise; + getShape(shapeInShapeCollectionIndex: number): Promise; + getShapeCollectionIndex(shapeInShapeCollectionIndex: number): Promise; + getAllShapeCollectionIndex(): Promise; + getShapeCollection(shapeInShapeCollectionIndex: number): Promise; +} +export declare class ShapeInShapeCollection implements IShapeInShapeCollection { + index: number; + shapeIndex?: number; + shape?: IShape; + shapeCollectionIndex?: number; + shapeCollection?: IShapeCollection; + static createFromTable(table: IShapeInShapeCollectionTable, index: number): Promise; +} +export declare class ShapeInShapeCollectionTable implements IShapeInShapeCollectionTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(shapeInShapeCollectionIndex: number): Promise; + getAll(): Promise; + getShapeIndex(shapeInShapeCollectionIndex: number): Promise; + getAllShapeIndex(): Promise; + getShape(shapeInShapeCollectionIndex: number): Promise; + getShapeCollectionIndex(shapeInShapeCollectionIndex: number): Promise; + getAllShapeCollectionIndex(): Promise; + getShapeCollection(shapeInShapeCollectionIndex: number): Promise; +} +export interface ISystem { + index: number; + systemType?: number; + familyTypeIndex?: number; + familyType?: IFamilyType; + elementIndex?: number; + element?: IElement; +} +export interface ISystemTable { + getCount(): Promise; + get(systemIndex: number): Promise; + getAll(): Promise; + getSystemType(systemIndex: number): Promise; + getAllSystemType(): Promise; + getFamilyTypeIndex(systemIndex: number): Promise; + getAllFamilyTypeIndex(): Promise; + getFamilyType(systemIndex: number): Promise; + getElementIndex(systemIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(systemIndex: number): Promise; +} +export declare class System implements ISystem { + index: number; + systemType?: number; + familyTypeIndex?: number; + familyType?: IFamilyType; + elementIndex?: number; + element?: IElement; + static createFromTable(table: ISystemTable, index: number): Promise; +} +export declare class SystemTable implements ISystemTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(systemIndex: number): Promise; + getAll(): Promise; + getSystemType(systemIndex: number): Promise; + getAllSystemType(): Promise; + getFamilyTypeIndex(systemIndex: number): Promise; + getAllFamilyTypeIndex(): Promise; + getFamilyType(systemIndex: number): Promise; + getElementIndex(systemIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(systemIndex: number): Promise; +} +export interface IElementInSystem { + index: number; + roles?: number; + systemIndex?: number; + system?: ISystem; + elementIndex?: number; + element?: IElement; +} +export interface IElementInSystemTable { + getCount(): Promise; + get(elementInSystemIndex: number): Promise; + getAll(): Promise; + getRoles(elementInSystemIndex: number): Promise; + getAllRoles(): Promise; + getSystemIndex(elementInSystemIndex: number): Promise; + getAllSystemIndex(): Promise; + getSystem(elementInSystemIndex: number): Promise; + getElementIndex(elementInSystemIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(elementInSystemIndex: number): Promise; +} +export declare class ElementInSystem implements IElementInSystem { + index: number; + roles?: number; + systemIndex?: number; + system?: ISystem; + elementIndex?: number; + element?: IElement; + static createFromTable(table: IElementInSystemTable, index: number): Promise; +} +export declare class ElementInSystemTable implements IElementInSystemTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(elementInSystemIndex: number): Promise; + getAll(): Promise; + getRoles(elementInSystemIndex: number): Promise; + getAllRoles(): Promise; + getSystemIndex(elementInSystemIndex: number): Promise; + getAllSystemIndex(): Promise; + getSystem(elementInSystemIndex: number): Promise; + getElementIndex(elementInSystemIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(elementInSystemIndex: number): Promise; +} +export interface IWarning { + index: number; + guid?: string; + severity?: string; + description?: string; + bimDocumentIndex?: number; + bimDocument?: IBimDocument; +} +export interface IWarningTable { + getCount(): Promise; + get(warningIndex: number): Promise; + getAll(): Promise; + getGuid(warningIndex: number): Promise; + getAllGuid(): Promise; + getSeverity(warningIndex: number): Promise; + getAllSeverity(): Promise; + getDescription(warningIndex: number): Promise; + getAllDescription(): Promise; + getBimDocumentIndex(warningIndex: number): Promise; + getAllBimDocumentIndex(): Promise; + getBimDocument(warningIndex: number): Promise; +} +export declare class Warning implements IWarning { + index: number; + guid?: string; + severity?: string; + description?: string; + bimDocumentIndex?: number; + bimDocument?: IBimDocument; + static createFromTable(table: IWarningTable, index: number): Promise; +} +export declare class WarningTable implements IWarningTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(warningIndex: number): Promise; + getAll(): Promise; + getGuid(warningIndex: number): Promise; + getAllGuid(): Promise; + getSeverity(warningIndex: number): Promise; + getAllSeverity(): Promise; + getDescription(warningIndex: number): Promise; + getAllDescription(): Promise; + getBimDocumentIndex(warningIndex: number): Promise; + getAllBimDocumentIndex(): Promise; + getBimDocument(warningIndex: number): Promise; +} +export interface IElementInWarning { + index: number; + warningIndex?: number; + warning?: IWarning; + elementIndex?: number; + element?: IElement; +} +export interface IElementInWarningTable { + getCount(): Promise; + get(elementInWarningIndex: number): Promise; + getAll(): Promise; + getWarningIndex(elementInWarningIndex: number): Promise; + getAllWarningIndex(): Promise; + getWarning(elementInWarningIndex: number): Promise; + getElementIndex(elementInWarningIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(elementInWarningIndex: number): Promise; +} +export declare class ElementInWarning implements IElementInWarning { + index: number; + warningIndex?: number; + warning?: IWarning; + elementIndex?: number; + element?: IElement; + static createFromTable(table: IElementInWarningTable, index: number): Promise; +} +export declare class ElementInWarningTable implements IElementInWarningTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(elementInWarningIndex: number): Promise; + getAll(): Promise; + getWarningIndex(elementInWarningIndex: number): Promise; + getAllWarningIndex(): Promise; + getWarning(elementInWarningIndex: number): Promise; + getElementIndex(elementInWarningIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(elementInWarningIndex: number): Promise; +} +export interface IBasePoint { + index: number; + isSurveyPoint?: boolean; + position_X?: number; + position_Y?: number; + position_Z?: number; + sharedPosition_X?: number; + sharedPosition_Y?: number; + sharedPosition_Z?: number; + elementIndex?: number; + element?: IElement; +} +export interface IBasePointTable { + getCount(): Promise; + get(basePointIndex: number): Promise; + getAll(): Promise; + getIsSurveyPoint(basePointIndex: number): Promise; + getAllIsSurveyPoint(): Promise; + getPosition_X(basePointIndex: number): Promise; + getAllPosition_X(): Promise; + getPosition_Y(basePointIndex: number): Promise; + getAllPosition_Y(): Promise; + getPosition_Z(basePointIndex: number): Promise; + getAllPosition_Z(): Promise; + getSharedPosition_X(basePointIndex: number): Promise; + getAllSharedPosition_X(): Promise; + getSharedPosition_Y(basePointIndex: number): Promise; + getAllSharedPosition_Y(): Promise; + getSharedPosition_Z(basePointIndex: number): Promise; + getAllSharedPosition_Z(): Promise; + getElementIndex(basePointIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(basePointIndex: number): Promise; +} +export declare class BasePoint implements IBasePoint { + index: number; + isSurveyPoint?: boolean; + position_X?: number; + position_Y?: number; + position_Z?: number; + sharedPosition_X?: number; + sharedPosition_Y?: number; + sharedPosition_Z?: number; + elementIndex?: number; + element?: IElement; + static createFromTable(table: IBasePointTable, index: number): Promise; +} +export declare class BasePointTable implements IBasePointTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(basePointIndex: number): Promise; + getAll(): Promise; + getIsSurveyPoint(basePointIndex: number): Promise; + getAllIsSurveyPoint(): Promise; + getPosition_X(basePointIndex: number): Promise; + getAllPosition_X(): Promise; + getPosition_Y(basePointIndex: number): Promise; + getAllPosition_Y(): Promise; + getPosition_Z(basePointIndex: number): Promise; + getAllPosition_Z(): Promise; + getSharedPosition_X(basePointIndex: number): Promise; + getAllSharedPosition_X(): Promise; + getSharedPosition_Y(basePointIndex: number): Promise; + getAllSharedPosition_Y(): Promise; + getSharedPosition_Z(basePointIndex: number): Promise; + getAllSharedPosition_Z(): Promise; + getElementIndex(basePointIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(basePointIndex: number): Promise; +} +export interface IPhaseFilter { + index: number; + _new?: number; + existing?: number; + demolished?: number; + temporary?: number; + elementIndex?: number; + element?: IElement; +} +export interface IPhaseFilterTable { + getCount(): Promise; + get(phaseFilterIndex: number): Promise; + getAll(): Promise; + getNew(phaseFilterIndex: number): Promise; + getAllNew(): Promise; + getExisting(phaseFilterIndex: number): Promise; + getAllExisting(): Promise; + getDemolished(phaseFilterIndex: number): Promise; + getAllDemolished(): Promise; + getTemporary(phaseFilterIndex: number): Promise; + getAllTemporary(): Promise; + getElementIndex(phaseFilterIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(phaseFilterIndex: number): Promise; +} +export declare class PhaseFilter implements IPhaseFilter { + index: number; + _new?: number; + existing?: number; + demolished?: number; + temporary?: number; + elementIndex?: number; + element?: IElement; + static createFromTable(table: IPhaseFilterTable, index: number): Promise; +} +export declare class PhaseFilterTable implements IPhaseFilterTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(phaseFilterIndex: number): Promise; + getAll(): Promise; + getNew(phaseFilterIndex: number): Promise; + getAllNew(): Promise; + getExisting(phaseFilterIndex: number): Promise; + getAllExisting(): Promise; + getDemolished(phaseFilterIndex: number): Promise; + getAllDemolished(): Promise; + getTemporary(phaseFilterIndex: number): Promise; + getAllTemporary(): Promise; + getElementIndex(phaseFilterIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(phaseFilterIndex: number): Promise; +} +export interface IGrid { + index: number; + startPoint_X?: number; + startPoint_Y?: number; + startPoint_Z?: number; + endPoint_X?: number; + endPoint_Y?: number; + endPoint_Z?: number; + isCurved?: boolean; + extents_Min_X?: number; + extents_Min_Y?: number; + extents_Min_Z?: number; + extents_Max_X?: number; + extents_Max_Y?: number; + extents_Max_Z?: number; + familyTypeIndex?: number; + familyType?: IFamilyType; + elementIndex?: number; + element?: IElement; +} +export interface IGridTable { + getCount(): Promise; + get(gridIndex: number): Promise; + getAll(): Promise; + getStartPoint_X(gridIndex: number): Promise; + getAllStartPoint_X(): Promise; + getStartPoint_Y(gridIndex: number): Promise; + getAllStartPoint_Y(): Promise; + getStartPoint_Z(gridIndex: number): Promise; + getAllStartPoint_Z(): Promise; + getEndPoint_X(gridIndex: number): Promise; + getAllEndPoint_X(): Promise; + getEndPoint_Y(gridIndex: number): Promise; + getAllEndPoint_Y(): Promise; + getEndPoint_Z(gridIndex: number): Promise; + getAllEndPoint_Z(): Promise; + getIsCurved(gridIndex: number): Promise; + getAllIsCurved(): Promise; + getExtents_Min_X(gridIndex: number): Promise; + getAllExtents_Min_X(): Promise; + getExtents_Min_Y(gridIndex: number): Promise; + getAllExtents_Min_Y(): Promise; + getExtents_Min_Z(gridIndex: number): Promise; + getAllExtents_Min_Z(): Promise; + getExtents_Max_X(gridIndex: number): Promise; + getAllExtents_Max_X(): Promise; + getExtents_Max_Y(gridIndex: number): Promise; + getAllExtents_Max_Y(): Promise; + getExtents_Max_Z(gridIndex: number): Promise; + getAllExtents_Max_Z(): Promise; + getFamilyTypeIndex(gridIndex: number): Promise; + getAllFamilyTypeIndex(): Promise; + getFamilyType(gridIndex: number): Promise; + getElementIndex(gridIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(gridIndex: number): Promise; +} +export declare class Grid implements IGrid { + index: number; + startPoint_X?: number; + startPoint_Y?: number; + startPoint_Z?: number; + endPoint_X?: number; + endPoint_Y?: number; + endPoint_Z?: number; + isCurved?: boolean; + extents_Min_X?: number; + extents_Min_Y?: number; + extents_Min_Z?: number; + extents_Max_X?: number; + extents_Max_Y?: number; + extents_Max_Z?: number; + familyTypeIndex?: number; + familyType?: IFamilyType; + elementIndex?: number; + element?: IElement; + static createFromTable(table: IGridTable, index: number): Promise; +} +export declare class GridTable implements IGridTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(gridIndex: number): Promise; + getAll(): Promise; + getStartPoint_X(gridIndex: number): Promise; + getAllStartPoint_X(): Promise; + getStartPoint_Y(gridIndex: number): Promise; + getAllStartPoint_Y(): Promise; + getStartPoint_Z(gridIndex: number): Promise; + getAllStartPoint_Z(): Promise; + getEndPoint_X(gridIndex: number): Promise; + getAllEndPoint_X(): Promise; + getEndPoint_Y(gridIndex: number): Promise; + getAllEndPoint_Y(): Promise; + getEndPoint_Z(gridIndex: number): Promise; + getAllEndPoint_Z(): Promise; + getIsCurved(gridIndex: number): Promise; + getAllIsCurved(): Promise; + getExtents_Min_X(gridIndex: number): Promise; + getAllExtents_Min_X(): Promise; + getExtents_Min_Y(gridIndex: number): Promise; + getAllExtents_Min_Y(): Promise; + getExtents_Min_Z(gridIndex: number): Promise; + getAllExtents_Min_Z(): Promise; + getExtents_Max_X(gridIndex: number): Promise; + getAllExtents_Max_X(): Promise; + getExtents_Max_Y(gridIndex: number): Promise; + getAllExtents_Max_Y(): Promise; + getExtents_Max_Z(gridIndex: number): Promise; + getAllExtents_Max_Z(): Promise; + getFamilyTypeIndex(gridIndex: number): Promise; + getAllFamilyTypeIndex(): Promise; + getFamilyType(gridIndex: number): Promise; + getElementIndex(gridIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(gridIndex: number): Promise; +} +export interface IArea { + index: number; + value?: number; + perimeter?: number; + number?: string; + isGrossInterior?: boolean; + areaSchemeIndex?: number; + areaScheme?: IAreaScheme; + elementIndex?: number; + element?: IElement; +} +export interface IAreaTable { + getCount(): Promise; + get(areaIndex: number): Promise; + getAll(): Promise; + getValue(areaIndex: number): Promise; + getAllValue(): Promise; + getPerimeter(areaIndex: number): Promise; + getAllPerimeter(): Promise; + getNumber(areaIndex: number): Promise; + getAllNumber(): Promise; + getIsGrossInterior(areaIndex: number): Promise; + getAllIsGrossInterior(): Promise; + getAreaSchemeIndex(areaIndex: number): Promise; + getAllAreaSchemeIndex(): Promise; + getAreaScheme(areaIndex: number): Promise; + getElementIndex(areaIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(areaIndex: number): Promise; +} +export declare class Area implements IArea { + index: number; + value?: number; + perimeter?: number; + number?: string; + isGrossInterior?: boolean; + areaSchemeIndex?: number; + areaScheme?: IAreaScheme; + elementIndex?: number; + element?: IElement; + static createFromTable(table: IAreaTable, index: number): Promise; +} +export declare class AreaTable implements IAreaTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(areaIndex: number): Promise; + getAll(): Promise; + getValue(areaIndex: number): Promise; + getAllValue(): Promise; + getPerimeter(areaIndex: number): Promise; + getAllPerimeter(): Promise; + getNumber(areaIndex: number): Promise; + getAllNumber(): Promise; + getIsGrossInterior(areaIndex: number): Promise; + getAllIsGrossInterior(): Promise; + getAreaSchemeIndex(areaIndex: number): Promise; + getAllAreaSchemeIndex(): Promise; + getAreaScheme(areaIndex: number): Promise; + getElementIndex(areaIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(areaIndex: number): Promise; +} +export interface IAreaScheme { + index: number; + isGrossBuildingArea?: boolean; + elementIndex?: number; + element?: IElement; +} +export interface IAreaSchemeTable { + getCount(): Promise; + get(areaSchemeIndex: number): Promise; + getAll(): Promise; + getIsGrossBuildingArea(areaSchemeIndex: number): Promise; + getAllIsGrossBuildingArea(): Promise; + getElementIndex(areaSchemeIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(areaSchemeIndex: number): Promise; +} +export declare class AreaScheme implements IAreaScheme { + index: number; + isGrossBuildingArea?: boolean; + elementIndex?: number; + element?: IElement; + static createFromTable(table: IAreaSchemeTable, index: number): Promise; +} +export declare class AreaSchemeTable implements IAreaSchemeTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(areaSchemeIndex: number): Promise; + getAll(): Promise; + getIsGrossBuildingArea(areaSchemeIndex: number): Promise; + getAllIsGrossBuildingArea(): Promise; + getElementIndex(areaSchemeIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(areaSchemeIndex: number): Promise; +} +export interface ISchedule { + index: number; + elementIndex?: number; + element?: IElement; +} +export interface IScheduleTable { + getCount(): Promise; + get(scheduleIndex: number): Promise; + getAll(): Promise; + getElementIndex(scheduleIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(scheduleIndex: number): Promise; +} +export declare class Schedule implements ISchedule { + index: number; + elementIndex?: number; + element?: IElement; + static createFromTable(table: IScheduleTable, index: number): Promise; +} +export declare class ScheduleTable implements IScheduleTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(scheduleIndex: number): Promise; + getAll(): Promise; + getElementIndex(scheduleIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(scheduleIndex: number): Promise; +} +export interface IScheduleColumn { + index: number; + name?: string; + columnIndex?: number; + scheduleIndex?: number; + schedule?: ISchedule; +} +export interface IScheduleColumnTable { + getCount(): Promise; + get(scheduleColumnIndex: number): Promise; + getAll(): Promise; + getName(scheduleColumnIndex: number): Promise; + getAllName(): Promise; + getColumnIndex(scheduleColumnIndex: number): Promise; + getAllColumnIndex(): Promise; + getScheduleIndex(scheduleColumnIndex: number): Promise; + getAllScheduleIndex(): Promise; + getSchedule(scheduleColumnIndex: number): Promise; +} +export declare class ScheduleColumn implements IScheduleColumn { + index: number; + name?: string; + columnIndex?: number; + scheduleIndex?: number; + schedule?: ISchedule; + static createFromTable(table: IScheduleColumnTable, index: number): Promise; +} +export declare class ScheduleColumnTable implements IScheduleColumnTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(scheduleColumnIndex: number): Promise; + getAll(): Promise; + getName(scheduleColumnIndex: number): Promise; + getAllName(): Promise; + getColumnIndex(scheduleColumnIndex: number): Promise; + getAllColumnIndex(): Promise; + getScheduleIndex(scheduleColumnIndex: number): Promise; + getAllScheduleIndex(): Promise; + getSchedule(scheduleColumnIndex: number): Promise; +} +export interface IScheduleCell { + index: number; + value?: string; + rowIndex?: number; + scheduleColumnIndex?: number; + scheduleColumn?: IScheduleColumn; +} +export interface IScheduleCellTable { + getCount(): Promise; + get(scheduleCellIndex: number): Promise; + getAll(): Promise; + getValue(scheduleCellIndex: number): Promise; + getAllValue(): Promise; + getRowIndex(scheduleCellIndex: number): Promise; + getAllRowIndex(): Promise; + getScheduleColumnIndex(scheduleCellIndex: number): Promise; + getAllScheduleColumnIndex(): Promise; + getScheduleColumn(scheduleCellIndex: number): Promise; +} +export declare class ScheduleCell implements IScheduleCell { + index: number; + value?: string; + rowIndex?: number; + scheduleColumnIndex?: number; + scheduleColumn?: IScheduleColumn; + static createFromTable(table: IScheduleCellTable, index: number): Promise; +} +export declare class ScheduleCellTable implements IScheduleCellTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(scheduleCellIndex: number): Promise; + getAll(): Promise; + getValue(scheduleCellIndex: number): Promise; + getAllValue(): Promise; + getRowIndex(scheduleCellIndex: number): Promise; + getAllRowIndex(): Promise; + getScheduleColumnIndex(scheduleCellIndex: number): Promise; + getAllScheduleColumnIndex(): Promise; + getScheduleColumn(scheduleCellIndex: number): Promise; +} +export interface IViewSheetSet { + index: number; + elementIndex?: number; + element?: IElement; +} +export interface IViewSheetSetTable { + getCount(): Promise; + get(viewSheetSetIndex: number): Promise; + getAll(): Promise; + getElementIndex(viewSheetSetIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(viewSheetSetIndex: number): Promise; +} +export declare class ViewSheetSet implements IViewSheetSet { + index: number; + elementIndex?: number; + element?: IElement; + static createFromTable(table: IViewSheetSetTable, index: number): Promise; +} +export declare class ViewSheetSetTable implements IViewSheetSetTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(viewSheetSetIndex: number): Promise; + getAll(): Promise; + getElementIndex(viewSheetSetIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(viewSheetSetIndex: number): Promise; +} +export interface IViewSheet { + index: number; + familyTypeIndex?: number; + familyType?: IFamilyType; + elementIndex?: number; + element?: IElement; +} +export interface IViewSheetTable { + getCount(): Promise; + get(viewSheetIndex: number): Promise; + getAll(): Promise; + getFamilyTypeIndex(viewSheetIndex: number): Promise; + getAllFamilyTypeIndex(): Promise; + getFamilyType(viewSheetIndex: number): Promise; + getElementIndex(viewSheetIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(viewSheetIndex: number): Promise; +} +export declare class ViewSheet implements IViewSheet { + index: number; + familyTypeIndex?: number; + familyType?: IFamilyType; + elementIndex?: number; + element?: IElement; + static createFromTable(table: IViewSheetTable, index: number): Promise; +} +export declare class ViewSheetTable implements IViewSheetTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(viewSheetIndex: number): Promise; + getAll(): Promise; + getFamilyTypeIndex(viewSheetIndex: number): Promise; + getAllFamilyTypeIndex(): Promise; + getFamilyType(viewSheetIndex: number): Promise; + getElementIndex(viewSheetIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(viewSheetIndex: number): Promise; +} +export interface IViewSheetInViewSheetSet { + index: number; + viewSheetIndex?: number; + viewSheet?: IViewSheet; + viewSheetSetIndex?: number; + viewSheetSet?: IViewSheetSet; +} +export interface IViewSheetInViewSheetSetTable { + getCount(): Promise; + get(viewSheetInViewSheetSetIndex: number): Promise; + getAll(): Promise; + getViewSheetIndex(viewSheetInViewSheetSetIndex: number): Promise; + getAllViewSheetIndex(): Promise; + getViewSheet(viewSheetInViewSheetSetIndex: number): Promise; + getViewSheetSetIndex(viewSheetInViewSheetSetIndex: number): Promise; + getAllViewSheetSetIndex(): Promise; + getViewSheetSet(viewSheetInViewSheetSetIndex: number): Promise; +} +export declare class ViewSheetInViewSheetSet implements IViewSheetInViewSheetSet { + index: number; + viewSheetIndex?: number; + viewSheet?: IViewSheet; + viewSheetSetIndex?: number; + viewSheetSet?: IViewSheetSet; + static createFromTable(table: IViewSheetInViewSheetSetTable, index: number): Promise; +} +export declare class ViewSheetInViewSheetSetTable implements IViewSheetInViewSheetSetTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(viewSheetInViewSheetSetIndex: number): Promise; + getAll(): Promise; + getViewSheetIndex(viewSheetInViewSheetSetIndex: number): Promise; + getAllViewSheetIndex(): Promise; + getViewSheet(viewSheetInViewSheetSetIndex: number): Promise; + getViewSheetSetIndex(viewSheetInViewSheetSetIndex: number): Promise; + getAllViewSheetSetIndex(): Promise; + getViewSheetSet(viewSheetInViewSheetSetIndex: number): Promise; +} +export interface IViewInViewSheetSet { + index: number; + viewIndex?: number; + view?: IView; + viewSheetSetIndex?: number; + viewSheetSet?: IViewSheetSet; +} +export interface IViewInViewSheetSetTable { + getCount(): Promise; + get(viewInViewSheetSetIndex: number): Promise; + getAll(): Promise; + getViewIndex(viewInViewSheetSetIndex: number): Promise; + getAllViewIndex(): Promise; + getView(viewInViewSheetSetIndex: number): Promise; + getViewSheetSetIndex(viewInViewSheetSetIndex: number): Promise; + getAllViewSheetSetIndex(): Promise; + getViewSheetSet(viewInViewSheetSetIndex: number): Promise; +} +export declare class ViewInViewSheetSet implements IViewInViewSheetSet { + index: number; + viewIndex?: number; + view?: IView; + viewSheetSetIndex?: number; + viewSheetSet?: IViewSheetSet; + static createFromTable(table: IViewInViewSheetSetTable, index: number): Promise; +} +export declare class ViewInViewSheetSetTable implements IViewInViewSheetSetTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(viewInViewSheetSetIndex: number): Promise; + getAll(): Promise; + getViewIndex(viewInViewSheetSetIndex: number): Promise; + getAllViewIndex(): Promise; + getView(viewInViewSheetSetIndex: number): Promise; + getViewSheetSetIndex(viewInViewSheetSetIndex: number): Promise; + getAllViewSheetSetIndex(): Promise; + getViewSheetSet(viewInViewSheetSetIndex: number): Promise; +} +export interface IViewInViewSheet { + index: number; + viewIndex?: number; + view?: IView; + viewSheetIndex?: number; + viewSheet?: IViewSheet; +} +export interface IViewInViewSheetTable { + getCount(): Promise; + get(viewInViewSheetIndex: number): Promise; + getAll(): Promise; + getViewIndex(viewInViewSheetIndex: number): Promise; + getAllViewIndex(): Promise; + getView(viewInViewSheetIndex: number): Promise; + getViewSheetIndex(viewInViewSheetIndex: number): Promise; + getAllViewSheetIndex(): Promise; + getViewSheet(viewInViewSheetIndex: number): Promise; +} +export declare class ViewInViewSheet implements IViewInViewSheet { + index: number; + viewIndex?: number; + view?: IView; + viewSheetIndex?: number; + viewSheet?: IViewSheet; + static createFromTable(table: IViewInViewSheetTable, index: number): Promise; +} +export declare class ViewInViewSheetTable implements IViewInViewSheetTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(viewInViewSheetIndex: number): Promise; + getAll(): Promise; + getViewIndex(viewInViewSheetIndex: number): Promise; + getAllViewIndex(): Promise; + getView(viewInViewSheetIndex: number): Promise; + getViewSheetIndex(viewInViewSheetIndex: number): Promise; + getAllViewSheetIndex(): Promise; + getViewSheet(viewInViewSheetIndex: number): Promise; +} +export declare class VimDocument { + asset: IAssetTable | undefined; + displayUnit: IDisplayUnitTable | undefined; + parameterDescriptor: IParameterDescriptorTable | undefined; + parameter: IParameterTable | undefined; + element: IElementTable | undefined; + workset: IWorksetTable | undefined; + assemblyInstance: IAssemblyInstanceTable | undefined; + group: IGroupTable | undefined; + designOption: IDesignOptionTable | undefined; + level: ILevelTable | undefined; + phase: IPhaseTable | undefined; + room: IRoomTable | undefined; + bimDocument: IBimDocumentTable | undefined; + displayUnitInBimDocument: IDisplayUnitInBimDocumentTable | undefined; + phaseOrderInBimDocument: IPhaseOrderInBimDocumentTable | undefined; + category: ICategoryTable | undefined; + family: IFamilyTable | undefined; + familyType: IFamilyTypeTable | undefined; + familyInstance: IFamilyInstanceTable | undefined; + view: IViewTable | undefined; + elementInView: IElementInViewTable | undefined; + shapeInView: IShapeInViewTable | undefined; + assetInView: IAssetInViewTable | undefined; + assetInViewSheet: IAssetInViewSheetTable | undefined; + levelInView: ILevelInViewTable | undefined; + camera: ICameraTable | undefined; + material: IMaterialTable | undefined; + materialInElement: IMaterialInElementTable | undefined; + compoundStructureLayer: ICompoundStructureLayerTable | undefined; + compoundStructure: ICompoundStructureTable | undefined; + node: INodeTable | undefined; + geometry: IGeometryTable | undefined; + shape: IShapeTable | undefined; + shapeCollection: IShapeCollectionTable | undefined; + shapeInShapeCollection: IShapeInShapeCollectionTable | undefined; + system: ISystemTable | undefined; + elementInSystem: IElementInSystemTable | undefined; + warning: IWarningTable | undefined; + elementInWarning: IElementInWarningTable | undefined; + basePoint: IBasePointTable | undefined; + phaseFilter: IPhaseFilterTable | undefined; + grid: IGridTable | undefined; + area: IAreaTable | undefined; + areaScheme: IAreaSchemeTable | undefined; + schedule: IScheduleTable | undefined; + scheduleColumn: IScheduleColumnTable | undefined; + scheduleCell: IScheduleCellTable | undefined; + viewSheetSet: IViewSheetSetTable | undefined; + viewSheet: IViewSheetTable | undefined; + viewSheetInViewSheetSet: IViewSheetInViewSheetSetTable | undefined; + viewInViewSheetSet: IViewInViewSheetSetTable | undefined; + viewInViewSheet: IViewInViewSheetTable | undefined; + entities: BFast; + strings: string[] | undefined; + private constructor(); + static createFromBfast(bfast: BFast, ignoreStrings?: boolean): Promise; +} diff --git a/src/ts/dist/types/remoteBuffer.d.ts b/src/ts/dist/types/remoteBuffer.d.ts new file mode 100644 index 00000000..eddb9302 --- /dev/null +++ b/src/ts/dist/types/remoteBuffer.d.ts @@ -0,0 +1,40 @@ +/** + * @module vim-ts + */ +import { Range } from './bfast'; +import { IProgressLogs } from './requestTracker'; +export declare function setRemoteBufferMaxConcurency(value: number): void; +export declare class RetryRequest { + url: string; + range: string | undefined; + responseType: XMLHttpRequestResponseType; + msg: string | undefined; + xhr: XMLHttpRequest | undefined; + constructor(url: string, range: string | undefined, responseType: XMLHttpRequestResponseType); + onLoad: ((result: any) => void) | undefined; + onError: (() => void) | undefined; + onProgress: ((e: ProgressEvent) => void) | undefined; + abort(): void; + send(): void; +} +/** + * Wrapper to provide tracking for all webrequests via request logger. + */ +export declare class RemoteBuffer { + url: string; + maxConcurency: number; + onProgress: (progress: IProgressLogs) => void; + private _tracker; + private _logs; + private _queue; + private _active; + private _encoded; + constructor(url: string, verbose?: boolean); + private requestEncoding; + abort(): void; + http(range: Range | undefined, label: string): Promise; + private enqueue; + private retry; + private end; + private next; +} diff --git a/src/ts/dist/types/remoteG3d.d.ts b/src/ts/dist/types/remoteG3d.d.ts new file mode 100644 index 00000000..c379d894 --- /dev/null +++ b/src/ts/dist/types/remoteG3d.d.ts @@ -0,0 +1,67 @@ +import { BFast } from "./bfast"; +import { G3d } from "./g3d"; +import { G3dAttributeDescriptor, TypedArray } from "./g3dAttributes"; +declare class G3dRemoteAttribute { + descriptor: G3dAttributeDescriptor; + bfast: BFast; + constructor(descriptor: G3dAttributeDescriptor, bfast: BFast); + getAll(): Promise; + getByte(index: number): Promise; + getNumber(index: number): Promise; + getValue(index: number): Promise; + getValues(index: number, count: number): Promise; + getCount(): Promise; + static fromString(description: string, bfast: BFast): G3dRemoteAttribute; +} +/** + * G3D is a simple, efficient, generic binary format for storing and transmitting geometry. + * The G3D format is designed to be used either as a serialization format or as an in-memory data structure. + * See https://github.com/vimaec/g3d + */ +export declare class RemoteAbstractG3d { + meta: string; + attributes: G3dRemoteAttribute[]; + constructor(meta: string, attributes: G3dRemoteAttribute[]); + findAttribute(descriptor: string): G3dRemoteAttribute | undefined; + /** + * Create g3d from bfast by requesting all necessary buffers individually. + */ + static createFromBfast(bfast: BFast): RemoteAbstractG3d; +} +export declare class RemoteG3d { + rawG3d: RemoteAbstractG3d; + positions: G3dRemoteAttribute; + indices: G3dRemoteAttribute; + instanceMeshes: G3dRemoteAttribute; + instanceTransforms: G3dRemoteAttribute; + instanceFlags: G3dRemoteAttribute; + meshSubmeshes: G3dRemoteAttribute; + submeshIndexOffsets: G3dRemoteAttribute; + submeshMaterials: G3dRemoteAttribute; + materialColors: G3dRemoteAttribute; + constructor(g3d: RemoteAbstractG3d); + static createFromBfast(bfast: BFast): RemoteG3d; + getVertexCount: () => Promise; + getMeshCount: () => Promise; + getSubmeshCount: () => Promise; + getMeshIndexStart(mesh: number): Promise; + getMeshIndexEnd(mesh: number): Promise; + getMeshIndexCount(mesh: number): Promise; + getMeshIndices(mesh: number): Promise; + getMeshSubmeshEnd(mesh: number): Promise; + getMeshSubmeshStart(mesh: number): Promise; + getMeshSubmeshCount(mesh: number): Promise; + getSubmeshIndexStart(submesh: number): Promise; + getSubmeshIndexEnd(submesh: number): Promise; + getSubmeshIndexCount(submesh: number): Promise; + toG3d(): Promise; + slice(instance: number): Promise; + filter(instances: number[]): Promise; + private filterInstances; + private filterMesh; + private filterSubmeshes; + private filterIndices; + private filterPositions; + private filterMaterials; +} +export {}; diff --git a/src/ts/dist/types/remoteGeometry.d.ts b/src/ts/dist/types/remoteGeometry.d.ts new file mode 100644 index 00000000..9c250d80 --- /dev/null +++ b/src/ts/dist/types/remoteGeometry.d.ts @@ -0,0 +1,43 @@ +import { BFast } from "./bfast"; +import { G3dMaterial as G3dMaterials } from "./g3dMaterials"; +import { G3dMesh } from "./g3dMesh"; +import { G3dScene } from "./g3dScene"; +import { RemoteValue } from "./remoteValue"; +export declare class RemoteGeometry { + bfast: BFast; + scene: RemoteValue; + sceneRaw: RemoteValue; + constructor(bfast: BFast); + static fromPath(path: string): Promise; + /** + * Aborts all downloads from the underlying BFAST. + */ + abort(): void; + /** + * Downloads underlying bfast making all subsequent request local. + */ + download(): Promise; + /** + * Fetches and returns the vimx G3dMeshIndex + */ + private requestIndex; + private requestIndexRaw; + getIndex(): Promise; + getIndexRaw(): Promise; + /** + * Fetches and returns the vimx G3dMaterials + */ + getMaterials(): Promise; + /** + * Fetches and returns the vimx G3dMesh with given index + */ + getMesh(mesh: number): Promise; + /** + * Fetches and returns the vimx G3dMaterials + */ + getMaterialsRaw(): Promise; + /** + * Fetches and returns the vimx G3dMesh with given index + */ + getMeshRaw(mesh: number): Promise; +} diff --git a/src/ts/dist/types/remoteValue.d.ts b/src/ts/dist/types/remoteValue.d.ts new file mode 100644 index 00000000..9aaed21a --- /dev/null +++ b/src/ts/dist/types/remoteValue.d.ts @@ -0,0 +1,17 @@ +/** + * @module vim-ts + */ +/** + * Returns a value from cache or queue up existing request or start a new requests + */ +export declare class RemoteValue { + label: string; + private _getter; + private _value; + private _request; + constructor(getter: () => Promise, label?: string); + /** + * Returns a value from cache or queue up existing request or start a new requests + */ + get(): Promise; +} diff --git a/src/ts/dist/types/remoteVimx.d.ts b/src/ts/dist/types/remoteVimx.d.ts new file mode 100644 index 00000000..a5c02aee --- /dev/null +++ b/src/ts/dist/types/remoteVimx.d.ts @@ -0,0 +1,43 @@ +import { BFast } from "./bfast"; +import { G3dMaterial as G3dMaterials } from "./g3dMaterials"; +import { G3dMesh } from "./g3dMesh"; +import { G3dScene } from "./g3dScene"; +import { RemoteValue } from "./remoteValue"; +export declare class RemoteVimx { + bfast: BFast; + scene: RemoteValue; + sceneRaw: RemoteValue; + constructor(bfast: BFast); + static fromPath(path: string): Promise; + /** + * Aborts all downloads from the underlying BFAST. + */ + abort(): void; + /** + * Downloads underlying bfast making all subsequent request local. + */ + download(): Promise; + /** + * Fetches and returns the vimx G3dMeshIndex + */ + private requestIndex; + private requestIndexRaw; + getIndex(): Promise; + getIndexRaw(): Promise; + /** + * Fetches and returns the vimx G3dMaterials + */ + getMaterials(): Promise; + /** + * Fetches and returns the vimx G3dMesh with given index + */ + getMesh(mesh: number): Promise; + /** + * Fetches and returns the vimx G3dMaterials + */ + getMaterialsRaw(): Promise; + /** + * Fetches and returns the vimx G3dMesh with given index + */ + getMeshRaw(mesh: number): Promise; +} diff --git a/src/ts/dist/types/requestTracker.d.ts b/src/ts/dist/types/requestTracker.d.ts new file mode 100644 index 00000000..18f38234 --- /dev/null +++ b/src/ts/dist/types/requestTracker.d.ts @@ -0,0 +1,61 @@ +import { Logger } from "./logging"; +/** + * Represents the state of a single web request + */ +declare class Request { + status: 'active' | 'completed' | 'failed'; + field: string; + loaded: number; + total: number; + lengthComputable: boolean; + constructor(field: string); +} +export interface IProgressLogs { + get loaded(): number; + get total(): number; + get all(): Map; +} +/** + * Represents a collection of webrequests + * Will only send update signal at most every delay + * Provides convenient aggregation of metrics. + */ +export declare class RequestTracker { + source: string; + all: Map; + lastUpdate: number; + delay: number; + sleeping: boolean; + logs: Logger; + /** + * callback on update, called at most every delay time. + */ + onUpdate: ((self: RequestTracker) => void) | undefined; + constructor(source?: string, logger?: Logger); + /** + * Returns the sum of .loaded across all requests + */ + get loaded(): number; + /** + * Returns the sum of .total across all requests + */ + get total(): number; + /** + * Starts tracking a new web request + */ + start(field: string): void; + /** + * Update an existing web request + */ + update(field: string, progress: ProgressEvent): void; + /** + * Notify a webrequest of failure + */ + fail(field: string): void; + /** + * Notify a webrequest of success + */ + end(field: string): void; + private signal; +} +export {}; diff --git a/src/ts/dist/types/requester.d.ts b/src/ts/dist/types/requester.d.ts new file mode 100644 index 00000000..7a29ae16 --- /dev/null +++ b/src/ts/dist/types/requester.d.ts @@ -0,0 +1,19 @@ +import { IProgressLogs } from "./requestTracker"; +/** + * Wrapper to provide tracking for all webrequests via request logger. + */ +export declare class Requester { + maxConcurency: number; + onProgress: (progress: IProgressLogs) => void; + private _tracker; + private _logs; + private _queue; + private _active; + constructor(verbose?: boolean); + abort(): void; + http(url: string, label?: string): Promise; + private enqueue; + private retry; + private end; + private next; +} diff --git a/src/ts/dist/types/structures.d.ts b/src/ts/dist/types/structures.d.ts new file mode 100644 index 00000000..d0f8a987 --- /dev/null +++ b/src/ts/dist/types/structures.d.ts @@ -0,0 +1,48 @@ +/** + * @module vim-ts + */ +export declare type Vector2 = { + x: number; + y: number; +}; +export declare type Vector3 = { + x: number; + y: number; + z: number; +}; +export declare type Vector4 = { + x: number; + y: number; + z: number; + w: number; +}; +export declare type AABox = { + min: Vector3; + max: Vector3; +}; +export declare type AABox2D = { + min: Vector2; + max: Vector2; +}; +export declare type AABox4D = { + min: Vector4; + max: Vector4; +}; +export declare type Matrix4x4 = { + m11: number; + m12: number; + m13: number; + m14: number; + m21: number; + m22: number; + m23: number; + m24: number; + m31: number; + m32: number; + m33: number; + m34: number; + m41: number; + m42: number; + m43: number; + m44: number; +}; diff --git a/src/ts/dist/types/vimHeader.d.ts b/src/ts/dist/types/vimHeader.d.ts new file mode 100644 index 00000000..e5a3e87f --- /dev/null +++ b/src/ts/dist/types/vimHeader.d.ts @@ -0,0 +1,14 @@ +import { BFast } from "./bfast"; +/** + * Representation of VimHeader from the Vim format + * See https://github.com/vimaec/vim#header-buffer + */ +export declare type VimHeader = { + vim: string | undefined; + id: string | undefined; + revision: string | undefined; + generator: string | undefined; + created: string | undefined; + schema: string | undefined; +}; +export declare function requestHeader(bfast: BFast): Promise; diff --git a/src/ts/dist/types/vimHelpers.d.ts b/src/ts/dist/types/vimHelpers.d.ts new file mode 100644 index 00000000..052cde0d --- /dev/null +++ b/src/ts/dist/types/vimHelpers.d.ts @@ -0,0 +1,19 @@ +import { VimDocument } from "./objectModel"; +/** + * Representation of ElementParamter entity from the entity model + * See https://github.com/vimaec/vim/blob/master/ObjectModel/object-model-schema.json + */ +export declare type ElementParameter = { + name: string | undefined; + value: string | undefined; + group: string | undefined; + isInstance: boolean; +}; +/** + * Returns all parameters of an element and of its family type and family + * @param element element index + * @returns An array of paramters with name, value, group + */ +export declare function getElementParameters(document: VimDocument, element: number): Promise; +export declare function getFamilyElements(document: VimDocument, element: number): Promise; +export declare function getElementsParameters(document: VimDocument, elements: Map): Promise; diff --git a/src/ts/dist/types/vimLoader.d.ts b/src/ts/dist/types/vimLoader.d.ts new file mode 100644 index 00000000..eb75cb85 --- /dev/null +++ b/src/ts/dist/types/vimLoader.d.ts @@ -0,0 +1,9 @@ +/** + * @module vim-ts + */ +import { BFast } from "./bfast"; +export declare class VimLoader { + static loadFromBfast(bfast: BFast, ignoreStrings: boolean): Promise<[BFast | undefined, string[] | undefined]>; + private static requestStrings; + private static requestEntities; +} diff --git a/src/ts/dist/vimHeader.d.ts b/src/ts/dist/vimHeader.d.ts new file mode 100644 index 00000000..e5a3e87f --- /dev/null +++ b/src/ts/dist/vimHeader.d.ts @@ -0,0 +1,14 @@ +import { BFast } from "./bfast"; +/** + * Representation of VimHeader from the Vim format + * See https://github.com/vimaec/vim#header-buffer + */ +export declare type VimHeader = { + vim: string | undefined; + id: string | undefined; + revision: string | undefined; + generator: string | undefined; + created: string | undefined; + schema: string | undefined; +}; +export declare function requestHeader(bfast: BFast): Promise; diff --git a/src/ts/dist/vimHeader.js b/src/ts/dist/vimHeader.js new file mode 100644 index 00000000..a98612f1 --- /dev/null +++ b/src/ts/dist/vimHeader.js @@ -0,0 +1,17 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.requestHeader = void 0; +async function requestHeader(bfast) { + const header = await bfast.getBuffer('header'); + const pairs = new TextDecoder('utf-8').decode(header).split('\n'); + const map = new Map(pairs.map((p) => p.split('=')).map((p) => [p[0], p[1]])); + return { + vim: map.get('vim'), + id: map.get('id'), + revision: map.get('revision'), + generator: map.get('generator'), + created: map.get('created'), + schema: map.get('schema') + }; +} +exports.requestHeader = requestHeader; diff --git a/src/ts/dist/vimHelpers.d.ts b/src/ts/dist/vimHelpers.d.ts new file mode 100644 index 00000000..052cde0d --- /dev/null +++ b/src/ts/dist/vimHelpers.d.ts @@ -0,0 +1,19 @@ +import { VimDocument } from "./objectModel"; +/** + * Representation of ElementParamter entity from the entity model + * See https://github.com/vimaec/vim/blob/master/ObjectModel/object-model-schema.json + */ +export declare type ElementParameter = { + name: string | undefined; + value: string | undefined; + group: string | undefined; + isInstance: boolean; +}; +/** + * Returns all parameters of an element and of its family type and family + * @param element element index + * @returns An array of paramters with name, value, group + */ +export declare function getElementParameters(document: VimDocument, element: number): Promise; +export declare function getFamilyElements(document: VimDocument, element: number): Promise; +export declare function getElementsParameters(document: VimDocument, elements: Map): Promise; diff --git a/src/ts/dist/vimHelpers.js b/src/ts/dist/vimHelpers.js new file mode 100644 index 00000000..1352ffbe --- /dev/null +++ b/src/ts/dist/vimHelpers.js @@ -0,0 +1,78 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.getElementsParameters = exports.getFamilyElements = exports.getElementParameters = void 0; +/** + * Returns all parameters of an element and of its family type and family + * @param element element index + * @returns An array of paramters with name, value, group + */ +async function getElementParameters(document, element) { + const elements = new Map(); + elements.set(element, true); + const familyElements = await getFamilyElements(document, element); + familyElements.forEach(element => elements.set(element, false)); + return getElementsParameters(document, elements); +} +exports.getElementParameters = getElementParameters; +async function getFamilyElements(document, element) { + const familyInstance = await getElementFamilyInstance(document, element); + const familyType = Number.isInteger(familyInstance) + ? await document.familyInstance.getFamilyTypeIndex(familyInstance) + : undefined; + const getFamilyElement = async (familyType) => { + const family = await document.familyType.getFamilyIndex(familyType); + return Number.isInteger(family) + ? await document.family.getElementIndex(family) + : undefined; + }; + return Number.isInteger(familyType) + ? await Promise.all([ + getFamilyElement(familyType), + document.familyType.getElementIndex(familyType) + ]) + : [undefined, undefined]; +} +exports.getFamilyElements = getFamilyElements; +async function getElementsParameters(document, elements) { + const [parameterElements, parameterValues, getParameterDescriptorIndices, parameterDescriptorNames, parameterDescriptorGroups] = await Promise.all([ + document.parameter.getAllElementIndex(), + document.parameter.getAllValue(), + document.parameter.getAllParameterDescriptorIndex(), + document.parameterDescriptor.getAllName(), + document.parameterDescriptor.getAllGroup() + ]); + if (!parameterElements) + return undefined; + const getParameterDisplayValue = (index) => { + const value = parameterValues[index]; + const split = value.indexOf('|'); + if (split >= 0) { + return value.substring(split + 1, value.length); + } + else + return value; + }; + const parameters = new Array(); + parameterElements.forEach((e, i) => { + if (elements.has(e)) { + parameters.push([i, elements.get(e)]); + } + }); + return parameters.map(([parameter, isInstance]) => { + const descriptor = getParameterDescriptorIndices[parameter]; + const value = getParameterDisplayValue(parameter); + const name = Number.isInteger(descriptor) + ? parameterDescriptorNames[descriptor] + : undefined; + const group = Number.isInteger(descriptor) + ? parameterDescriptorGroups[descriptor] + : undefined; + return { name, value, group, isInstance }; + }); +} +exports.getElementsParameters = getElementsParameters; +async function getElementFamilyInstance(document, element) { + const familyInstanceElement = await document.familyInstance.getAllElementIndex(); + const result = familyInstanceElement.findIndex(e => e === element); + return result < 0 ? undefined : result; +} diff --git a/src/ts/dist/vimLoader.d.ts b/src/ts/dist/vimLoader.d.ts new file mode 100644 index 00000000..eb75cb85 --- /dev/null +++ b/src/ts/dist/vimLoader.d.ts @@ -0,0 +1,9 @@ +/** + * @module vim-ts + */ +import { BFast } from "./bfast"; +export declare class VimLoader { + static loadFromBfast(bfast: BFast, ignoreStrings: boolean): Promise<[BFast | undefined, string[] | undefined]>; + private static requestStrings; + private static requestEntities; +} diff --git a/src/ts/dist/vimLoader.js b/src/ts/dist/vimLoader.js new file mode 100644 index 00000000..32bfc33b --- /dev/null +++ b/src/ts/dist/vimLoader.js @@ -0,0 +1,32 @@ +"use strict"; +/** + * @module vim-ts + */ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.VimLoader = void 0; +class VimLoader { + static async loadFromBfast(bfast, ignoreStrings) { + const [entity, strings] = await Promise.all([ + VimLoader.requestEntities(bfast), + ignoreStrings ? Promise.resolve(undefined) : VimLoader.requestStrings(bfast) + ]); + return [entity, strings]; + } + static async requestStrings(bfast) { + const buffer = await bfast.getBuffer('strings'); + if (!buffer) { + console.error('Could not get String Data from VIM file. Bim features will be disabled.'); + return; + } + const strings = new TextDecoder('utf-8').decode(buffer).split('\0'); + return strings; + } + static async requestEntities(bfast) { + const entities = await bfast.getBfast('entities'); + if (!entities) { + console.error('Could not get String Data from VIM file. Bim features will be disabled.'); + } + return entities; + } +} +exports.VimLoader = VimLoader; diff --git a/src/ts/package-lock.json b/src/ts/package-lock.json index 7d0da063..dc644427 100644 --- a/src/ts/package-lock.json +++ b/src/ts/package-lock.json @@ -1,16 +1,20 @@ { "name": "vim-format", - "version": "1.0.4", + "version": "1.0.6-dev.100", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "vim-format", - "version": "1.0.4", + "version": "1.0.6-dev.100", "license": "MIT", + "dependencies": { + "pako": "^2.1.0" + }, "devDependencies": { "@types/jest": "^29.5.2", "@types/node": "^18.16.16", + "@types/pako": "^2.0.0", "jest": "^29.2.2", "ts-jest": "^29.0.3", "typescript": "^4.8.4" @@ -1058,6 +1062,12 @@ "integrity": "sha512-NpaM49IGQQAUlBhHMF82QH80J08os4ZmyF9MkpCzWAGuOHqE4gTEbhzd7L3l5LmWuZ6E0OiC1FweQ4tsiW35+g==", "dev": true }, + "node_modules/@types/pako": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/pako/-/pako-2.0.0.tgz", + "integrity": "sha512-10+iaz93qR5WYxTo+PMifD5TSxiOtdRaxBf7INGGXMQgTCu8Z/7GYWYFUOS3q/G0nE5boj1r4FEB+WSy7s5gbA==", + "dev": true + }, "node_modules/@types/prettier": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.1.tgz", @@ -2842,6 +2852,11 @@ "node": ">=6" } }, + "node_modules/pako": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz", + "integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==" + }, "node_modules/parse-json": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", @@ -4328,6 +4343,12 @@ "integrity": "sha512-NpaM49IGQQAUlBhHMF82QH80J08os4ZmyF9MkpCzWAGuOHqE4gTEbhzd7L3l5LmWuZ6E0OiC1FweQ4tsiW35+g==", "dev": true }, + "@types/pako": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/pako/-/pako-2.0.0.tgz", + "integrity": "sha512-10+iaz93qR5WYxTo+PMifD5TSxiOtdRaxBf7INGGXMQgTCu8Z/7GYWYFUOS3q/G0nE5boj1r4FEB+WSy7s5gbA==", + "dev": true + }, "@types/prettier": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.1.tgz", @@ -5671,6 +5692,11 @@ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true }, + "pako": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz", + "integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==" + }, "parse-json": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", diff --git a/src/ts/package.json b/src/ts/package.json index a59a5e47..05d4c942 100644 --- a/src/ts/package.json +++ b/src/ts/package.json @@ -1,6 +1,6 @@ { "name": "vim-format", - "version": "1.0.6-dev.100", + "version": "1.0.6-dev.138", "description": "The VIM format is a modern and efficient open 3D data interchange format designed for BIM and manufacturing data optimized for efficient loading and rendering on low-power devices.", "directories": { "test": "tests" diff --git a/src/ts/src/bfast.ts b/src/ts/src/bfast.ts index 738d91aa..059c7a44 100644 --- a/src/ts/src/bfast.ts +++ b/src/ts/src/bfast.ts @@ -264,6 +264,15 @@ export function parseName(name: string): [number, NumericArrayConstructor]{ } return new BFast(buffer, 0, name) } + + async getLocalBfastRaw (name: string, unzip: boolean = false): Promise { + let buffer = await this.getBuffer(name) + if (!buffer) return undefined + if(unzip){ + buffer = pako.inflateRaw(buffer).buffer + } + return new BFast(buffer, 0, name) + } /** * Returns the raw buffer associated with a name diff --git a/src/ts/src/g3d.ts b/src/ts/src/g3d.ts index fb7743fa..8b7dbdc1 100644 --- a/src/ts/src/g3d.ts +++ b/src/ts/src/g3d.ts @@ -4,9 +4,6 @@ import { AbstractG3d } from './abstractG3d' import { BFast } from './bfast' -import { FilterMode } from './g3dMeshIndex' -import { G3dSubset } from './g3dSubset' - export type MeshSection = 'opaque' | 'transparent' | 'all' @@ -226,8 +223,9 @@ export class G3d { /** * Computes all instances pointing to each mesh. */ - private computeMeshInstances = (): number[][] => { - const result: number[][] = [] + private computeMeshInstances () { + + const result = new Array>(this.getMeshCount()) for (let i = 0; i < this.instanceMeshes.length; i++) { const mesh = this.instanceMeshes[i] @@ -801,7 +799,6 @@ export class G3d { 'Invalid material color buffer, must be divisible by ' + G3d.COLOR_SIZE ) } - console.assert(this.meshInstances.length === this.getMeshCount()) console.assert(this.meshOpaqueCount.length === this.getMeshCount()) @@ -822,49 +819,4 @@ export class G3d { ) } } - - filter(mode: FilterMode, filter: number[]){ - if(filter === undefined || mode === undefined){ - return new G3dSubset(this, undefined) - } - if(mode === 'instance'){ - return this.getMeshesFromInstances(filter) - } - - if(mode === 'mesh'){ - return new G3dSubset(this, filter) - } - if(mode === 'tag' || mode === 'group'){ - throw new Error("Filter Mode Not implemented") - } - } - - private getMeshesFromInstances(instances: number[]){ - // Compute the list of unique meshes to include - const meshSet = new Set() - const meshes = new Array() - instances.forEach((instance, i) => { - const mesh = this.instanceMeshes[instance] - if(!meshSet.has(mesh) && mesh >=0){ - meshes.push(mesh) - meshSet.add(mesh) - } - }) - - - // Compute the mesh-based instances indices for each mesh - const instanceSet = new Set(instances) - const meshInstances = new Array>(meshes.length) - meshes.forEach((mesh, i) => { - const indices = new Array() - this.meshInstances[mesh].forEach((instance, j) => { - if(instanceSet.has(instance)){ - indices.push(j) - } - meshInstances[i] = indices - }) - }) - - return new G3dSubset(this, meshes, meshInstances) - } } diff --git a/src/ts/src/g3dMesh.ts b/src/ts/src/g3dMesh.ts index 96b46f3a..1986c0ad 100644 --- a/src/ts/src/g3dMesh.ts +++ b/src/ts/src/g3dMesh.ts @@ -6,15 +6,14 @@ import { AbstractG3d } from './abstractG3d' import { BFast } from './bfast' import { G3d, MeshSection } from './g3d' import { G3dMaterial } from './g3dMaterials' +import { G3dScene } from './g3dScene' /** * See https://github.com/vimaec/vim#vim-geometry-attributes */ export class MeshAttributes { - static instanceNodes = 'g3d:instance:node:0:int32:1' static instanceTransforms = 'g3d:instance:transform:0:float32:16' - static instanceFlags = 'g3d:instance:flags:0:uint16:1' static meshOpaqueSubmeshCount = 'g3d:mesh:opaquesubmeshcount:0:int32:1' static submeshIndexOffsets = 'g3d:submesh:indexoffset:0:int32:1' static submeshVertexOffsets = 'g3d:submesh:vertexoffset:0:int32:1' @@ -23,9 +22,7 @@ export class MeshAttributes { static indices = 'g3d:corner:index:0:int32:1' static all = [ - MeshAttributes.instanceNodes, MeshAttributes.instanceTransforms, - MeshAttributes.instanceFlags, MeshAttributes.meshOpaqueSubmeshCount, MeshAttributes.submeshIndexOffsets, MeshAttributes.submeshVertexOffsets, @@ -43,11 +40,13 @@ export class MeshAttributes { * See https://github.com/vimaec/g3d for the g3d specification. */ export class G3dMesh { + + scene: G3dScene + meshIndex: number + rawG3d: AbstractG3d - instanceNodes: Int32Array instanceTransforms: Float32Array - instanceFlags: Uint16Array meshOpaqueSubmeshCount : number @@ -67,9 +66,7 @@ export class G3dMesh { DEFAULT_COLOR = new Float32Array([1, 1, 1, 1]) constructor( - instanceNodes: Int32Array | undefined, instanceTransforms: Float32Array, - instanceFlags: Uint16Array | undefined, meshOpaqueSubmeshCount : number, submeshIndexOffsets : Int32Array, submeshVertexOffsets : Int32Array, @@ -78,35 +75,21 @@ export class G3dMesh { positions: Float32Array, ){ - this.instanceNodes = instanceNodes this.instanceTransforms = instanceTransforms - this.instanceFlags = instanceFlags this.meshOpaqueSubmeshCount = meshOpaqueSubmeshCount this.submeshIndexOffset = submeshIndexOffsets this.submeshVertexOffset = submeshVertexOffsets this.submeshMaterial = submeshMaterials this.indices = indices instanceof Uint32Array ? indices : new Uint32Array(indices.buffer) this.positions = positions - - if(this.instanceFlags === undefined){ - this.instanceFlags = new Uint16Array(this.instanceNodes.length) - } } static createFromAbstract(g3d: AbstractG3d) { - const instanceNodes = g3d.findAttribute( - MeshAttributes.instanceNodes - )?.data as Int32Array - const instanceTransforms = g3d.findAttribute( MeshAttributes.instanceTransforms )?.data as Float32Array - const instanceFlags = - (g3d.findAttribute(MeshAttributes.instanceFlags)?.data as Uint16Array) ?? - new Uint16Array(instanceNodes.length) - const meshOpaqueSubmeshCountArray = g3d.findAttribute( MeshAttributes.meshOpaqueSubmeshCount )?.data as Int32Array @@ -129,9 +112,7 @@ export class G3dMesh { ?.data as Float32Array const result = new G3dMesh( - instanceNodes, instanceTransforms, - instanceFlags, meshOpaqueSubmeshCount, submeshIndexOffsets, submeshVertexOffsets, @@ -162,37 +143,49 @@ export class G3dMesh { return G3dMesh.createFromAbstract(g3d) } - toG3d(materials : G3dMaterial){ - return new G3d( - new Int32Array(this.getInstanceCount()), - this.instanceFlags, - this.instanceTransforms, - this.instanceNodes, - new Int32Array(1).fill(0), - this.submeshIndexOffset, - this.submeshMaterial, - this.indices, - this.positions, - materials.materialColors - ) + // -----------Instances--------------- + + getBimInstance(meshInstance: number){ + const sceneInstance = this.scene.getMeshSceneInstance(this.meshIndex, meshInstance) + return this.scene.instanceNodes[sceneInstance] + } + + getInstanceMax(meshInstance: number){ + const sceneInstance = this.scene.getMeshSceneInstance(this.meshIndex, meshInstance) + return this.scene.instanceMaxs.subarray(sceneInstance * 3, (sceneInstance +1) * 3) } - insert(g3d: G3dMesh, - instanceStart: number, - submesStart: number, - indexStart: number, - vertexStart: number, - materialStart: number - ){ - this.instanceNodes.set(g3d.instanceNodes, instanceStart) - this.instanceTransforms.set(g3d.instanceTransforms, instanceStart * G3dMesh.MATRIX_SIZE) - this.instanceFlags.set(g3d.instanceFlags, instanceStart) - - this.submeshIndexOffset.set(g3d.submeshIndexOffset, submesStart) - this.submeshMaterial.set(g3d.submeshMaterial, submesStart) - - this.indices.set(g3d.indices, indexStart) - this.positions.set(g3d.positions, vertexStart) + getInstanceMin(meshInstance: number){ + const sceneInstance = this.scene.getMeshSceneInstance(this.meshIndex, meshInstance) + return this.scene.instanceMins.subarray(sceneInstance * 3, (sceneInstance +1) * 3) + } + + getInstanceGroup(meshInstance: number){ + const sceneInstance = this.scene.getMeshSceneInstance(this.meshIndex, meshInstance) + return this.scene.instanceGroups[sceneInstance] + } + + getInstanceTag(meshInstance: number){ + const sceneInstance = this.scene.getMeshSceneInstance(this.meshIndex, meshInstance) + return this.scene.instanceTags[sceneInstance] + } + + getInstanceHasFlag(meshInstance: number, flag: number){ + const sceneInstance = this.scene.getMeshSceneInstance(this.meshIndex, meshInstance) + return (this.scene.instanceFlags[sceneInstance] & flag) > 0 + } + + getInstanceCount = () => this.instanceTransforms.length + + /** + * Returns an 16 number array representation of the matrix for given instance + * @param instance g3d instance index + */ + getInstanceMatrix (instance: number): Float32Array { + return this.instanceTransforms.subarray( + instance * G3dMesh.MATRIX_SIZE, + (instance + 1) * G3dMesh.MATRIX_SIZE + ) } // ------------- Mesh ----------------- @@ -279,21 +272,6 @@ export class G3dMesh { } // ------------- Instances ----------------- - getInstanceCount = () => this.instanceNodes.length - - getInstanceHasFlag(instance: number, flag: number){ - return (this.instanceFlags[instance] & flag) > 0 - } - /** - * Returns an 16 number array representation of the matrix for given instance - * @param instance g3d instance index - */ - getInstanceMatrix (instance: number): Float32Array { - return this.instanceTransforms.subarray( - instance * G3dMesh.MATRIX_SIZE, - (instance + 1) * G3dMesh.MATRIX_SIZE - ) - } } diff --git a/src/ts/src/g3dMeshIndex.ts b/src/ts/src/g3dMeshIndex.ts deleted file mode 100644 index bf0c70f9..00000000 --- a/src/ts/src/g3dMeshIndex.ts +++ /dev/null @@ -1,201 +0,0 @@ -/** - * @module vim-ts - */ - -import { AbstractG3d } from './abstractG3d' -import { BFast } from './bfast' -import { MeshSection } from './g3d' -import { G3dSubset } from './g3dSubset' - - -export type FilterMode = undefined | 'mesh' | 'instance' | 'group' | 'tag' - -/** - * See https://github.com/vimaec/vim#vim-geometry-attributes - */ -export class MeshIndexAttributes { - - static instanceFiles = 'g3d:instance:file:0:int32:1' - static instanceIndices = 'g3d:instance:index:0:int32:1' - static instanceNodes = 'g3d:instance:node:0:int32:1' - static instanceGroups = 'g3d:instance:group:0:int32:1' - static instanceTags = 'g3d:instance:tag:0:int64:1' - - static meshInstanceCounts = 'g3d:mesh:instancecount:0:int32:1' - static meshIndexCounts = 'g3d:mesh:indexcount:0:int32:1' - static meshVertexCounts = 'g3d:mesh:vertexcount:0:int32:1' - - static meshOpaqueIndexCount = "g3d:mesh:opaqueindexcount:0:int32:1" - static meshOpaqueVertexCount = "g3d:mesh:opaquevertexcount:0:int32:1" - - static all = [ - MeshIndexAttributes.instanceFiles, - MeshIndexAttributes.instanceIndices, - MeshIndexAttributes.instanceNodes, - MeshIndexAttributes.instanceGroups, - MeshIndexAttributes.instanceTags, - - MeshIndexAttributes.meshInstanceCounts, - MeshIndexAttributes.meshIndexCounts, - MeshIndexAttributes.meshVertexCounts, - - MeshIndexAttributes.meshOpaqueIndexCount, - MeshIndexAttributes.meshOpaqueVertexCount, - ] -} - -/** - * Represents the index, as in book index, of a collection of G3dMesh. - * Allows to find and download G3dMesh as needed. - * Allows to preallocate geometry to render G3dMeshes. - */ -export class G3dMeshIndex { - rawG3d: AbstractG3d - - instanceFiles: Int32Array - instanceIndices: Int32Array - instanceNodes: Int32Array - instanceGroups: Int32Array - instanceTags : BigInt64Array - - meshInstanceCounts: Int32Array - meshIndexCounts: Int32Array - meshVertexCounts: Int32Array - - meshOpaqueIndexCounts: Int32Array - meshOpaqueVertexCounts: Int32Array - - constructor( - rawG3d: AbstractG3d, - - instanceFiles: Int32Array, - instanceIndices: Int32Array, - instanceNodes: Int32Array, - instanceGroups: Int32Array, - instanceTags: BigInt64Array, - - meshInstanceCounts: Int32Array, - meshIndexCounts : Int32Array, - meshVertexCounts: Int32Array, - - meshOpaqueIndexCounts: Int32Array, - meshOpaqueVertexCounts: Int32Array, - ){ - - this.rawG3d = rawG3d - - this.instanceFiles = instanceFiles - this.instanceIndices = instanceIndices - this.instanceNodes = instanceNodes - this.instanceGroups = instanceGroups - this.instanceTags = instanceTags - - this.meshInstanceCounts = meshInstanceCounts - - this.meshIndexCounts = meshIndexCounts - this.meshVertexCounts = meshVertexCounts - - this.meshOpaqueIndexCounts = meshOpaqueIndexCounts - this.meshOpaqueVertexCounts = meshOpaqueVertexCounts - } - - static createFromAbstract(g3d: AbstractG3d) { - - function getArray(attribute: string){ - return g3d.findAttribute( - attribute - )?.data as T - } - - return new G3dMeshIndex( - g3d, - getArray(MeshIndexAttributes.instanceFiles), - getArray(MeshIndexAttributes.instanceIndices), - getArray(MeshIndexAttributes.instanceNodes), - getArray(MeshIndexAttributes.instanceGroups), - getArray(MeshIndexAttributes.instanceTags), - - getArray(MeshIndexAttributes.meshInstanceCounts), - - getArray(MeshIndexAttributes.meshIndexCounts), - getArray(MeshIndexAttributes.meshVertexCounts), - - getArray(MeshIndexAttributes.meshOpaqueIndexCount), - getArray(MeshIndexAttributes.meshOpaqueVertexCount), - ) - } - - static async createFromPath (path: string) { - const f = await fetch(path) - const buffer = await f.arrayBuffer() - const bfast = new BFast(buffer) - return this.createFromBfast(bfast) - } - - static async createFromBfast (bfast: BFast) { - const g3d = await AbstractG3d.createFromBfast(bfast, MeshIndexAttributes.all) - return G3dMeshIndex.createFromAbstract(g3d) - } - - getMeshCount() { - return this.meshInstanceCounts.length - } - - getMeshIndexCount(mesh: number, section: MeshSection){ - const all = this.meshIndexCounts[mesh] - if(section === 'all') return all; - const opaque = this.meshOpaqueIndexCounts[mesh] - return section === 'opaque' ? opaque : all - opaque - } - - getMeshVertexCount(mesh:number, section: MeshSection){ - const all = this.meshVertexCounts[mesh] - if(section === 'all') return all; - const opaque = this.meshOpaqueVertexCounts[mesh] - return section === 'opaque' ? opaque : all - opaque - } - - getMeshInstanceCount(mesh:number){ - return this.meshInstanceCounts[mesh] - } - - filter(mode: FilterMode, filter: number[]){ - if(filter === undefined || mode === undefined){ - return new G3dSubset(this, undefined) - } - if(mode === 'instance'){ - return this.getMeshesFromInstances(filter) - } - - if(mode === 'mesh'){ - return new G3dSubset(this, filter) - } - if(mode === 'tag' || mode === 'group'){ - throw new Error("Filter Mode Not implemented") - } - } - - private getMeshesFromInstances(instances: number[]){ - const set = new Set(instances) - const meshes = new Array() - const map = new Map() - for(let i=0; i < this.instanceNodes.length; i ++){ - const node = this.instanceNodes[i] - if(set.has(node)){ - const mesh = this.instanceFiles[i] - const index = this.instanceIndices[i] - - if(!map.has(mesh)){ - meshes.push(mesh) - map.set(mesh, [index]) - } - else{ - map.get(mesh).push(index) - } - } - } - const meshInstances = new Array>(meshes.length) - meshes.forEach((m, i) => meshInstances[i] = map.get(m)) - return new G3dSubset(this, meshes, meshInstances) - } -} diff --git a/src/ts/src/g3dMeshOffsets.ts b/src/ts/src/g3dMeshOffsets.ts deleted file mode 100644 index 1236b70d..00000000 --- a/src/ts/src/g3dMeshOffsets.ts +++ /dev/null @@ -1,88 +0,0 @@ -import { G3d, MeshSection } from "./g3d" -import { G3dSubset } from "./g3dSubset" - -export class G3dMeshCounts{ - instances : number = 0 - meshes: number = 0 - indices : number = 0 - vertices : number = 0 -} - -/** - * Holds the offsets needed to preallocate geometry for a given meshIndexSubset - */ -export class G3dMeshOffsets { - // inputs - subset: G3dSubset - section: MeshSection - - // computed - counts : G3dMeshCounts - indexOffsets: Int32Array - vertexOffsets: Int32Array - - /** - * Computes geometry offsets for given subset and section - * @param subset subset for which to compute offsets - * @param section on of 'opaque' | 'transparent' | 'all' - */ - static fromSubset ( - subset: G3dSubset, - section: MeshSection){ - var result = new G3dMeshOffsets() - result.subset = subset - result.section = section - - function computeOffsets(getter: (mesh: number) => number){ - const meshCount = subset.getMeshCount() - const offsets = new Int32Array(meshCount) - - for(let i=1; i < meshCount; i ++){ - offsets[i] = offsets[i-1] + getter(i-1) - } - return offsets - } - - result.counts = subset.getAttributeCounts(section) - result.indexOffsets = computeOffsets((m) => subset.getMeshIndexCount(m, section)) - result.vertexOffsets = computeOffsets((m) => subset.getMeshVertexCount(m, section)) - - return result - } - - getIndexOffset(mesh: number){ - return mesh < this.counts.meshes - ? this.indexOffsets[mesh] - : this.counts.indices - } - - getVertexOffset(mesh: number){ - return mesh < this.counts.meshes - ? this.vertexOffsets[mesh] - : this.counts.vertices - } - - /** - * Returns how many instances of given meshes are the filtered view. - */ - getMeshInstanceCount(mesh: number){ - return this.subset.getMeshInstanceCount(mesh) - } - - /** - * Returns instance for given mesh. - * @mesh view-relative mesh index - * @at view-relative instance index for given mesh - * @returns mesh-relative instance index - */ - getMeshInstance(mesh: number, index: number){ - return this.subset.getMeshInstance(mesh, index) - } - - /** - * Returns the vim-relative mesh index at given index - */ - getMesh(index: number){ - return this.subset.getMesh(index) - } -} \ No newline at end of file diff --git a/src/ts/src/g3dScene.ts b/src/ts/src/g3dScene.ts new file mode 100644 index 00000000..24b0cc60 --- /dev/null +++ b/src/ts/src/g3dScene.ts @@ -0,0 +1,230 @@ +/** + * @module vim-ts + */ + +import { AbstractG3d } from './abstractG3d' +import { BFast } from './bfast' +import { G3d, MeshSection } from './g3d' + +export type FilterMode = undefined | 'mesh' | 'instance' | 'group' | 'tag' + +/** + * See https://github.com/vimaec/vim#vim-geometry-attributes + */ +export class SceneAttributes { + + static instanceFiles = 'g3d:instance:file:0:int32:1' + static instanceIndices = 'g3d:instance:index:0:int32:1' + static instanceNodes = 'g3d:instance:node:0:int32:1' + static instanceGroups = 'g3d:instance:group:0:int32:1' + static instanceTags = 'g3d:instance:tag:0:int64:1' + static instanceFlags = 'g3d:instance:tag:0:uint16:1' + static instanceMins = 'g3d:instance:min:0:float32:3' + static instanceMaxs = 'g3d:instance:max:0:float32:3' + + static meshInstanceCounts = 'g3d:mesh:instancecount:0:int32:1' + static meshIndexCounts = 'g3d:mesh:indexcount:0:int32:1' + static meshVertexCounts = 'g3d:mesh:vertexcount:0:int32:1' + + static meshOpaqueIndexCount = "g3d:mesh:opaqueindexcount:0:int32:1" + static meshOpaqueVertexCount = "g3d:mesh:opaquevertexcount:0:int32:1" + + static all = [ + SceneAttributes.instanceFiles, + SceneAttributes.instanceIndices, + SceneAttributes.instanceNodes, + SceneAttributes.instanceGroups, + SceneAttributes.instanceTags, + SceneAttributes.instanceFlags, + SceneAttributes.instanceMins, + SceneAttributes.instanceMaxs, + + SceneAttributes.meshInstanceCounts, + SceneAttributes.meshIndexCounts, + SceneAttributes.meshVertexCounts, + + SceneAttributes.meshOpaqueIndexCount, + SceneAttributes.meshOpaqueVertexCount, + ] +} + +/** + * Represents the index, as in book index, of a collection of G3dMesh. + * Allows to find and download G3dMesh as needed. + * Allows to preallocate geometry to render G3dMeshes. + */ +export class G3dScene { + rawG3d: AbstractG3d + + instanceMeshes: Int32Array + instanceIndices: Int32Array + instanceNodes: Int32Array + instanceGroups: Int32Array + instanceTags : BigInt64Array + instanceFlags : Uint16Array + instanceMins: Float32Array + instanceMaxs: Float32Array + + meshInstanceCounts: Int32Array + meshIndexCounts: Int32Array + meshVertexCounts: Int32Array + + meshOpaqueIndexCounts: Int32Array + meshOpaqueVertexCounts: Int32Array + + private nodeToInstance : Map + private meshSceneInstances: Map> + + constructor( + rawG3d: AbstractG3d, + + instanceFiles: Int32Array, + instanceIndices: Int32Array, + instanceNodes: Int32Array, + instanceGroups: Int32Array, + instanceTags: BigInt64Array, + instanceFlags: Uint16Array, + instanceMins: Float32Array, + instanceMaxs: Float32Array, + + meshInstanceCounts: Int32Array, + meshIndexCounts : Int32Array, + meshVertexCounts: Int32Array, + + meshOpaqueIndexCounts: Int32Array, + meshOpaqueVertexCounts: Int32Array, + ){ + + this.rawG3d = rawG3d + + this.instanceMeshes = instanceFiles + this.instanceIndices = instanceIndices + this.instanceNodes = instanceNodes + this.instanceGroups = instanceGroups + this.instanceTags = instanceTags + this.instanceFlags = instanceFlags + this.instanceMins = instanceMins + this.instanceMaxs = instanceMaxs + + this.meshInstanceCounts = meshInstanceCounts + + this.meshIndexCounts = meshIndexCounts + this.meshVertexCounts = meshVertexCounts + + this.meshOpaqueIndexCounts = meshOpaqueIndexCounts + this.meshOpaqueVertexCounts = meshOpaqueVertexCounts + + // Reverse instanceNodes + this.nodeToInstance = new Map() + for(let i = 0; i < this.instanceNodes.length; i ++){ + this.nodeToInstance.set(this.instanceNodes[i], i) + } + this.meshSceneInstances = this.createMap() + } + + private createMap(){ + // From : (mesh, scene-index) -> mesh-index + // To: (mesh, mesh-index) -> scene-index + const map = new Map>() + for(let i =0; i < this.instanceMeshes.length; i++){ + const mesh = this.instanceMeshes[i] + const index = this.instanceIndices[i] + const indices = map.get(mesh) ?? new Map() + indices.set(index, i) + map.set(mesh, indices) + } + return map + } + + static createFromAbstract(g3d: AbstractG3d) { + + function getArray(attribute: string){ + return g3d.findAttribute( + attribute + )?.data as T + } + + return new G3dScene( + g3d, + getArray(SceneAttributes.instanceFiles), + getArray(SceneAttributes.instanceIndices), + getArray(SceneAttributes.instanceNodes), + getArray(SceneAttributes.instanceGroups), + getArray(SceneAttributes.instanceTags), + getArray(SceneAttributes.instanceFlags), + getArray(SceneAttributes.instanceMins), + getArray(SceneAttributes.instanceMaxs), + + getArray(SceneAttributes.meshInstanceCounts), + + getArray(SceneAttributes.meshIndexCounts), + getArray(SceneAttributes.meshVertexCounts), + + getArray(SceneAttributes.meshOpaqueIndexCount), + getArray(SceneAttributes.meshOpaqueVertexCount), + ) + } + + static async createFromPath (path: string) { + const f = await fetch(path) + const buffer = await f.arrayBuffer() + const bfast = new BFast(buffer) + return this.createFromBfast(bfast) + } + + static async createFromBfast (bfast: BFast) { + const g3d = await AbstractG3d.createFromBfast(bfast, SceneAttributes.all) + return G3dScene.createFromAbstract(g3d) + } + + getMeshSceneInstance(mesh: number, meshIndex: number){ + return this.meshSceneInstances.get(mesh)?.get(meshIndex) + } + + getMeshCount() { + return this.meshInstanceCounts.length + } + + getMeshIndexCount(mesh: number, section: MeshSection){ + const all = this.meshIndexCounts[mesh] + if(section === 'all') return all; + const opaque = this.meshOpaqueIndexCounts[mesh] + return section === 'opaque' ? opaque : all - opaque + } + + getMeshVertexCount(mesh:number, section: MeshSection){ + const all = this.meshVertexCounts[mesh] + if(section === 'all') return all; + const opaque = this.meshOpaqueVertexCounts[mesh] + return section === 'opaque' ? opaque : all - opaque + } + + getMeshInstanceCount(mesh:number){ + return this.meshInstanceCounts[mesh] + } + + getNodeMin(node: number){ + const instance = this.nodeToInstance.get(node) + if(!node){ + return undefined + } + return this.getInstanceMin(instance) + } + + getNodeMax(node: number){ + const instance = this.nodeToInstance.get(node) + if(!node){ + return undefined + } + return this.getInstanceMax(instance) + } + + getInstanceMin(instance: number){ + return this.instanceMins.subarray(instance * G3d.POSITION_SIZE) + } + + getInstanceMax(instance: number){ + return this.instanceMaxs.subarray(instance * G3d.POSITION_SIZE) + } + +} diff --git a/src/ts/src/g3dSubset.ts b/src/ts/src/g3dSubset.ts deleted file mode 100644 index ab0371fd..00000000 --- a/src/ts/src/g3dSubset.ts +++ /dev/null @@ -1,133 +0,0 @@ -import { G3d, MeshSection } from './g3d' -import { G3dMeshIndex } from './g3dMeshIndex' -import { G3dMeshCounts, G3dMeshOffsets } from './g3dMeshOffsets' - -/** - * Represents a filter applied to a G3dMeshIndex. - */ -export class G3dSubset -{ - private _source: G3dMeshIndex | G3d - private _meshes: number[] | undefined - private _meshInstances : (number[] | undefined)[] | undefined - -/** - * @param index G3d source geometry. - * @param meshes indices of meshes to include or undefined if all meshes. - * @param meshToInstances indices of instances to include for each mesh or undefined if all meshes. - */ - constructor(index: G3dMeshIndex | G3d, meshes?: number[], meshToInstances? : number[][]){ - this._source = index - this._meshes = meshes - this._meshInstances = meshToInstances - } - - getMesh(index: number){ - return this._meshes?.[index] ?? index - } - - getMeshCount(){ - return this._meshes?.length ?? this._source.getMeshCount() - } - - /** - * Returns index count for given mesh and section. - */ - getMeshIndexCount(mesh: number, section: MeshSection){ - const instances = this.getMeshInstanceCount(mesh) - const indices = this._source.getMeshIndexCount(this.getMesh(mesh), section) - return indices * instances - } - - /** - * Returns vertext count for given mesh and section. - */ - getMeshVertexCount(mesh: number, section: MeshSection){ - const instances = this.getMeshInstanceCount(mesh) - const vertices = this._source.getMeshVertexCount(this.getMesh(mesh), section) - return vertices * instances - } - - /** - * Returns instance count for given mesh. - * @param mesh The index of the mesh from the g3dIndex. - */ - getMeshInstanceCount(mesh: number){ - return this._meshInstances - ? this._meshInstances[mesh].length - : this._source.getMeshInstanceCount(this.getMesh(mesh)) - } - - /** - * Returns index-th mesh-based instance index for given mesh. - * @param mesh The index of the mesh from the g3dIndex. - */ - getMeshInstance(mesh: number, index:number){ - const instance = this._meshInstances - ? this._meshInstances[mesh][index] - : index - - if(this._source instanceof G3d){ - // Dereference one more time. - return this._source.meshInstances[mesh][instance] - } - - return instance - } - - /** - * Returns the list of mesh-based instance indices for given mesh or undefined if all instances are included. - * @param mesh The index of the mesh from the g3dIndex. - */ - getMeshInstances(mesh: number){ - return this._meshInstances?.[mesh] - } - - /** - * Returns a new subset that only contains unique meshes. - */ - filterUniqueMeshes(){ - return this.filterByCount(count => count === 1) - } - - /** - * Returns a new subset that only contains non-unique meshes. - */ - filterNonUniqueMeshes(){ - return this.filterByCount(count =>count > 1) - } - - private filterByCount(predicate : (i: number) => boolean){ - const filteredMeshes = new Array() - const filteredInstances = this._meshInstances ? new Array>() : undefined - const count = this.getMeshCount() - for(let m =0; m < count; m++){ - if(predicate(this.getMeshInstanceCount(m))){ - filteredMeshes.push(this.getMesh(m)) - filteredInstances?.push(this.getMeshInstances(m)) - } - } - return new G3dSubset(this._source, filteredMeshes, filteredInstances) - } - - /** - * Returns offsets needed to build geometry. - */ - getOffsets(section: MeshSection){ - return G3dMeshOffsets.fromSubset(this, section) - } - - getAttributeCounts(section: MeshSection = 'all'){ - - const result = new G3dMeshCounts() - const count = this.getMeshCount() - for(let i = 0; i < count; i ++){ - result.instances += this.getMeshInstanceCount(i) - result.indices += this.getMeshIndexCount(i, section) - result.vertices += this.getMeshVertexCount(i, section) - } - result.meshes = count - - return result - } -} diff --git a/src/ts/src/index.ts b/src/ts/src/index.ts index 82600355..19e62929 100644 --- a/src/ts/src/index.ts +++ b/src/ts/src/index.ts @@ -1,12 +1,10 @@ // Links files to generate package type exports export * from './bfast' export * from './g3d' -export * from './remoteGeometry' +export * from './remoteVimx' export * from './g3dMaterials' export * from './g3dMesh' -export * from './g3dMeshIndex' -export * from './g3dSubset' -export * from './g3dMeshOffsets' +export * from './g3dScene' export * from './remoteG3d' export * from './remoteBuffer' export * from './requestTracker' diff --git a/src/ts/src/remoteGeometry.ts b/src/ts/src/remoteGeometry.ts deleted file mode 100644 index ae9a0828..00000000 --- a/src/ts/src/remoteGeometry.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { BFast } from "./bfast"; -import { G3dMaterial as G3dMaterials } from "./g3dMaterials"; -import { G3dMesh } from "./g3dMesh"; -import { G3dMeshIndex } from "./g3dMeshIndex"; -import { RemoteBuffer } from "./remoteBuffer"; - - -export class RemoteGeometry{ - bfast : BFast - - constructor(bfast : BFast){ - this.bfast = bfast - } - - - - static async fromPath(path: string){ - const buffer = new RemoteBuffer(path) - const bfast = new BFast(buffer) - return new RemoteGeometry(bfast) - } - - /** - * Aborts all downloads from the underlying BFAST. - */ - abort(){ - this.bfast.abort() - } - - /** - * Downloads underlying bfast making all subsequent request local. - */ - async download(){ - this.bfast.forceDownload() - } - - /** - * Fetches and returns the vimx G3dMeshIndex - */ - async getIndex(){ - const index = await this.bfast.getLocalBfast('index', true) - return G3dMeshIndex.createFromBfast(index) - } - - /** - * Fetches and returns the vimx G3dMaterials - */ - async getMaterials(){ - const mat = await this.bfast.getLocalBfast('materials', true) - return G3dMaterials.createFromBfast(mat) - } - - /** - * Fetches and returns the vimx G3dMesh with given index - */ - async getMesh(mesh: number){ - const m = await this.bfast.getLocalBfast(`mesh_${mesh}`, true) - return G3dMesh.createFromBfast(m) - } - -} \ No newline at end of file diff --git a/src/ts/src/remoteVimx.ts b/src/ts/src/remoteVimx.ts new file mode 100644 index 00000000..6770cea1 --- /dev/null +++ b/src/ts/src/remoteVimx.ts @@ -0,0 +1,102 @@ +import { BFast } from "./bfast"; +import { G3dMaterial as G3dMaterials } from "./g3dMaterials"; +import { G3dMesh } from "./g3dMesh"; +import { G3dScene } from "./g3dScene"; +import { RemoteBuffer } from "./remoteBuffer"; +import { RemoteValue } from "./remoteValue"; + +export class RemoteVimx{ + bfast : BFast + scene : RemoteValue + sceneRaw : RemoteValue + + constructor(bfast : BFast){ + this.bfast = bfast + this.scene = new RemoteValue(() => this.requestIndex()) + this.sceneRaw = new RemoteValue(() => this.requestIndexRaw()) + } + + static async fromPath(path: string){ + const buffer = new RemoteBuffer(path) + const bfast = new BFast(buffer) + return new RemoteVimx(bfast) + } + + /** + * Aborts all downloads from the underlying BFAST. + */ + abort(){ + this.bfast.abort() + } + + /** + * Downloads underlying bfast making all subsequent request local. + */ + async download(){ + this.bfast.forceDownload() + } + + /** + * Fetches and returns the vimx G3dMeshIndex + */ + private async requestIndex(){ + const index = await this.bfast.getLocalBfast('scene', true) + return G3dScene.createFromBfast(index) + } + + private async requestIndexRaw(){ + const index = await this.bfast.getLocalBfastRaw('scene', true) + return G3dScene.createFromBfast(index) + } + + async getIndex(){ + return this.scene.get() + } + + async getIndexRaw(){ + return this.sceneRaw.get() + } + + + /** + * Fetches and returns the vimx G3dMaterials + */ + async getMaterials(){ + const mat = await this.bfast.getLocalBfast('materials', true) + return G3dMaterials.createFromBfast(mat) + } + + /** + * Fetches and returns the vimx G3dMesh with given index + */ + async getMesh(mesh: number){ + const m = await this.bfast.getLocalBfast(`mesh_${mesh}`, true) + const result = await G3dMesh.createFromBfast(m) + const scene = await this.scene.get() + result.scene = scene + result.meshIndex = mesh + return result + } + + + /** + * Fetches and returns the vimx G3dMaterials + */ + async getMaterialsRaw(){ + const mat = await this.bfast.getLocalBfastRaw('materials', true) + return G3dMaterials.createFromBfast(mat) + } + + /** + * Fetches and returns the vimx G3dMesh with given index + */ + async getMeshRaw(mesh: number){ + const m = await this.bfast.getLocalBfastRaw(`mesh_${mesh}`, true) + const result = await G3dMesh.createFromBfast(m) + const scene = await this.sceneRaw.get() + result.scene = scene + result.meshIndex = mesh + return result + } + +} \ No newline at end of file From 5d556b4d7dd352437bc80503a9f0a962261754c6 Mon Sep 17 00:00:00 2001 From: simon Date: Fri, 29 Sep 2023 10:27:00 -0400 Subject: [PATCH 005/111] Vimx good state for integration into vimtool --- src/cs/.editorconfig | 215 +++ src/cs/Vim.BFast.Next/BFastNext.cs | 19 +- src/cs/Vim.BFast.Next/BFastNextExtensions.cs | 6 +- src/cs/Vim.BFast.Next/BFastNextNode.cs | 2 +- src/cs/Vim.BFast.Next/IBFastNextNode.cs | 2 +- src/cs/Vim.BFastNext.Tests/BFastNextTests.cs | 68 +- .../MeshesToScene.cs} | 24 +- .../Vim.Format.Vimx.Conversion.csproj | 15 + .../VimToMeshes.cs} | 47 +- .../VimxConverter.cs | 37 + .../VimxOrdering.cs} | 40 +- .../Vim.G3dNext.Attributes/Attributes.g.cs | 1216 +++++++++-------- .../Vim.G3dNext.Attributes/G3dMaterials.cs | 10 + src/cs/g3d/Vim.G3dNext.Attributes/G3dMesh.cs | 151 ++ src/cs/g3d/Vim.G3dNext.Attributes/G3dScene.cs | 10 + src/cs/g3d/Vim.G3dNext.Attributes/G3dVim.cs | 153 +++ ...alAttributes.cs => MaterialsAttributes.cs} | 6 +- .../Vim.G3dNext.Attributes/MeshAttributes.cs | 49 +- .../Vim.G3dNext.Attributes/VimAttributes.cs | 68 +- .../G3dAttributeCollectionGenerator.cs | 69 +- .../Vim.G3dNext.CodeGen.csproj | 9 +- src/cs/g3d/Vim.G3dNext/AttributeType.cs | 6 +- src/cs/g3d/Vim.G3dNext/CodeGenAttributes.cs | 17 +- src/cs/g3d/Vim.G3dNext/G3DNext.cs | 111 -- src/cs/g3d/Vim.G3dNext/IAttribute.cs | 5 +- .../g3d/Vim.G3dNext/IAttributeCollection.cs | 76 +- src/cs/g3d/Vim.G3dNext/MetaHeader.cs | 26 - src/cs/vim-format.sln | 11 +- src/cs/vim/Vim.Format.Vimx/FileUtils.cs | 38 - src/cs/vim/Vim.Format.Vimx/G3dMaterials.cs | 48 - src/cs/vim/Vim.Format.Vimx/G3dMesh.cs | 255 ---- src/cs/vim/Vim.Format.Vimx/G3dScene.cs | 70 - src/cs/vim/Vim.Format.Vimx/G3dVim.cs | 288 ---- src/cs/vim/Vim.Format.Vimx/G3dVimFilter.cs | 152 --- src/cs/vim/Vim.Format.Vimx/Vimx.cs | 103 +- src/cs/vim/Vim.Format.Vimx/VimxHeader.cs | 20 +- src/cs/vim/Vim.Vimx.Test/TestUtils.cs | 37 +- .../Vim.Vimx.Test/Vim.Format.Vimx.Test.csproj | 3 +- src/cs/vim/Vim.Vimx.Test/VimG3dTests.cs | 118 +- src/cs/vim/Vim.Vimx.Test/VimxActions.cs | 21 +- src/cs/vim/Vim.Vimx.Test/VimxTests.cs | 18 +- 41 files changed, 1618 insertions(+), 2021 deletions(-) create mode 100644 src/cs/.editorconfig rename src/cs/{vim/Vim.Format.Vimx/G3dVimScene.cs => Vim.Format.Vimx.Conversion/MeshesToScene.cs} (83%) create mode 100644 src/cs/Vim.Format.Vimx.Conversion/Vim.Format.Vimx.Conversion.csproj rename src/cs/{vim/Vim.Format.Vimx/G3dVimMeshes.cs => Vim.Format.Vimx.Conversion/VimToMeshes.cs} (78%) create mode 100644 src/cs/Vim.Format.Vimx.Conversion/VimxConverter.cs rename src/cs/{vim/Vim.Format.Vimx/G3dMeshExtensions.cs => Vim.Format.Vimx.Conversion/VimxOrdering.cs} (58%) create mode 100644 src/cs/g3d/Vim.G3dNext.Attributes/G3dMaterials.cs create mode 100644 src/cs/g3d/Vim.G3dNext.Attributes/G3dMesh.cs create mode 100644 src/cs/g3d/Vim.G3dNext.Attributes/G3dScene.cs create mode 100644 src/cs/g3d/Vim.G3dNext.Attributes/G3dVim.cs rename src/cs/g3d/Vim.G3dNext.Attributes/{MaterialAttributes.cs => MaterialsAttributes.cs} (77%) delete mode 100644 src/cs/g3d/Vim.G3dNext/G3DNext.cs delete mode 100644 src/cs/vim/Vim.Format.Vimx/FileUtils.cs delete mode 100644 src/cs/vim/Vim.Format.Vimx/G3dMaterials.cs delete mode 100644 src/cs/vim/Vim.Format.Vimx/G3dMesh.cs delete mode 100644 src/cs/vim/Vim.Format.Vimx/G3dScene.cs delete mode 100644 src/cs/vim/Vim.Format.Vimx/G3dVim.cs delete mode 100644 src/cs/vim/Vim.Format.Vimx/G3dVimFilter.cs diff --git a/src/cs/.editorconfig b/src/cs/.editorconfig new file mode 100644 index 00000000..7f629237 --- /dev/null +++ b/src/cs/.editorconfig @@ -0,0 +1,215 @@ +# Remove the line below if you want to inherit .editorconfig settings from higher directories +root = true + +# C# files +[*.cs] + +# Default severity for analyzer diagnostics with category 'Style' (escalated to build warnings) +# This causes the build to fail for the cases below that are suffixed with :error +dotnet_analyzer_diagnostic.category-Style.severity = default + +#### Core EditorConfig Options #### + +# Indentation and spacing +indent_size = 4 +indent_style = space +tab_width = 4 + +# New line preferences +end_of_line = crlf +insert_final_newline = true + +#### .NET Coding Conventions #### + +# Organize usings +dotnet_separate_import_directive_groups = false +dotnet_sort_system_directives_first = false +file_header_template = unset + +# this. and Me. preferences +dotnet_style_qualification_for_event = false:error +dotnet_style_qualification_for_field = false:error +dotnet_style_qualification_for_method = false:error +dotnet_style_qualification_for_property = false:error + +# Language keywords vs BCL types preferences +dotnet_style_predefined_type_for_locals_parameters_members = true +dotnet_style_predefined_type_for_member_access = true + +# Parentheses preferences +dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity +dotnet_style_parentheses_in_other_binary_operators = always_for_clarity +dotnet_style_parentheses_in_other_operators = never_if_unnecessary +dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity + +# Modifier preferences +dotnet_style_require_accessibility_modifiers = for_non_interface_members + +# Expression-level preferences +dotnet_style_coalesce_expression = true +dotnet_style_collection_initializer = true +dotnet_style_explicit_tuple_names = true +dotnet_style_null_propagation = true +dotnet_style_object_initializer = true +dotnet_style_operator_placement_when_wrapping = beginning_of_line +dotnet_style_prefer_auto_properties = true:error +dotnet_style_prefer_compound_assignment = true +dotnet_style_prefer_conditional_expression_over_assignment = true +dotnet_style_prefer_conditional_expression_over_return = true +dotnet_style_prefer_inferred_anonymous_type_member_names = true +dotnet_style_prefer_inferred_tuple_names = true +dotnet_style_prefer_is_null_check_over_reference_equality_method = true +dotnet_style_prefer_simplified_boolean_expressions = true +dotnet_style_prefer_simplified_interpolation = true + +# Field preferences +dotnet_style_readonly_field = true + +# Parameter preferences +dotnet_code_quality_unused_parameters = all + +# Suppression preferences +dotnet_remove_unnecessary_suppression_exclusions = none + +#### C# Coding Conventions #### + +# var preferences +csharp_style_var_elsewhere = true:error +csharp_style_var_for_built_in_types = true:error +csharp_style_var_when_type_is_apparent = true:error + +# Expression-bodied members +csharp_style_expression_bodied_accessors = true:silent +csharp_style_expression_bodied_constructors = true:silent +csharp_style_expression_bodied_indexers = true:silent +csharp_style_expression_bodied_lambdas = true:silent +csharp_style_expression_bodied_local_functions = true:silent +csharp_style_expression_bodied_methods = true:silent +csharp_style_expression_bodied_operators = true:silent +csharp_style_expression_bodied_properties = true:silent + +# Pattern matching preferences +csharp_style_pattern_matching_over_as_with_null_check = true +csharp_style_pattern_matching_over_is_with_cast_check = true +csharp_style_prefer_not_pattern = true +csharp_style_prefer_pattern_matching = true +csharp_style_prefer_switch_expression = true + +# Null-checking preferences +csharp_style_conditional_delegate_call = true + +# Modifier preferences +csharp_prefer_static_local_function = true +csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async + +# Code-block preferences +csharp_prefer_braces = when_multiline:error +csharp_prefer_simple_using_statement = true + +# Expression-level preferences +csharp_prefer_simple_default_expression = true +csharp_style_deconstructed_variable_declaration = true +csharp_style_implicit_object_creation_when_type_is_apparent = true +csharp_style_inlined_variable_declaration = true +csharp_style_pattern_local_over_anonymous_function = true +csharp_style_prefer_index_operator = true +csharp_style_prefer_range_operator = true +csharp_style_throw_expression = true +csharp_style_unused_value_assignment_preference = discard_variable +csharp_style_unused_value_expression_statement_preference = discard_variable + +# 'using' directive preferences +csharp_using_directive_placement = outside_namespace + +#### C# Formatting Rules #### + +# New line preferences +csharp_new_line_before_catch = true +csharp_new_line_before_else = true +csharp_new_line_before_finally = true +csharp_new_line_before_members_in_anonymous_types = true +csharp_new_line_before_members_in_object_initializers = true +csharp_new_line_before_open_brace = all +csharp_new_line_between_query_expression_clauses = true + +# Indentation preferences +csharp_indent_block_contents = true +csharp_indent_braces = false +csharp_indent_case_contents = true +csharp_indent_case_contents_when_block = true +csharp_indent_labels = one_less_than_current +csharp_indent_switch_labels = true + +# Space preferences +csharp_space_after_cast = false +csharp_space_after_colon_in_inheritance_clause = true +csharp_space_after_comma = true +csharp_space_after_dot = false +csharp_space_after_keywords_in_control_flow_statements = true +csharp_space_after_semicolon_in_for_statement = true +csharp_space_around_binary_operators = before_and_after +csharp_space_around_declaration_statements = false +csharp_space_before_colon_in_inheritance_clause = true +csharp_space_before_comma = false +csharp_space_before_dot = false +csharp_space_before_open_square_brackets = false +csharp_space_before_semicolon_in_for_statement = false +csharp_space_between_empty_square_brackets = false +csharp_space_between_method_call_empty_parameter_list_parentheses = false +csharp_space_between_method_call_name_and_opening_parenthesis = false +csharp_space_between_method_call_parameter_list_parentheses = false +csharp_space_between_method_declaration_empty_parameter_list_parentheses = false +csharp_space_between_method_declaration_name_and_open_parenthesis = false +csharp_space_between_method_declaration_parameter_list_parentheses = false +csharp_space_between_parentheses = false +csharp_space_between_square_brackets = false + +# Wrapping preferences +csharp_preserve_single_line_blocks = true +csharp_preserve_single_line_statements = true + +#### Naming styles #### + +# Naming rules + +dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion +dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface +dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i + +dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.types_should_be_pascal_case.symbols = types +dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case + +dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members +dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case + +# Symbol specifications + +dotnet_naming_symbols.interface.applicable_kinds = interface +dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.interface.required_modifiers = + +dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum +dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.types.required_modifiers = + +dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method +dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.non_field_members.required_modifiers = + +# Naming styles + +dotnet_naming_style.pascal_case.required_prefix = +dotnet_naming_style.pascal_case.required_suffix = +dotnet_naming_style.pascal_case.word_separator = +dotnet_naming_style.pascal_case.capitalization = pascal_case + +dotnet_naming_style.begins_with_i.required_prefix = I +dotnet_naming_style.begins_with_i.required_suffix = +dotnet_naming_style.begins_with_i.word_separator = +dotnet_naming_style.begins_with_i.capitalization = pascal_case + +# Web development files use 2 spaces +[*.{js,jsx,ts,tsx,py,css,json}] +indent_size = 2 diff --git a/src/cs/Vim.BFast.Next/BFastNext.cs b/src/cs/Vim.BFast.Next/BFastNext.cs index 566d0669..81bb1556 100644 --- a/src/cs/Vim.BFast.Next/BFastNext.cs +++ b/src/cs/Vim.BFast.Next/BFastNext.cs @@ -1,15 +1,14 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.IO; using System.Linq; using Vim.BFast; -namespace Vim.BFastNext +namespace Vim.BFastNextNS { public class BFastNext : IBFastNextNode { - private Dictionary _children = new Dictionary(); + private readonly Dictionary _children = new Dictionary(); public IEnumerable Entries => _children.Keys; private IEnumerable<(string, IWritable)> Writables => _children.Select(kvp => (kvp.Key, kvp.Value as IWritable)); @@ -20,26 +19,30 @@ public BFastNext(Stream stream) _children = node.ToDictionary(c => c.name, c => c.value as IBFastNextNode); } - public void AddBFast(string name, BFastNext bfast) + public void SetBFast(string name, BFastNext bfast) => _children[name] = bfast; - public void AddArray(string name, T[] array) where T : unmanaged + public void SetArray(string name, T[] array) where T : unmanaged => _children[name] = BFastNextNode.FromArray(array); - public void AddArray(Func getName, IEnumerable arrays) where T : unmanaged + public void SetArrays(Func getName, IEnumerable arrays) where T : unmanaged { var index = 0; foreach (var array in arrays) { - AddArray(getName(index++), array); + SetArray(getName(index++), array); } } + public void SetNode(string name, BFastNextNode node) + { + _children[name] = node; + } + public BFastNext GetBFast(string name) { if (!_children.ContainsKey(name)) return null; var bfast = _children[name].AsBFast(); - _children[name] = bfast; return bfast; } diff --git a/src/cs/Vim.BFast.Next/BFastNextExtensions.cs b/src/cs/Vim.BFast.Next/BFastNextExtensions.cs index 0b75b91a..012c12a2 100644 --- a/src/cs/Vim.BFast.Next/BFastNextExtensions.cs +++ b/src/cs/Vim.BFast.Next/BFastNextExtensions.cs @@ -3,7 +3,7 @@ using System.IO; using System.Collections.Generic; -namespace Vim.BFastNext +namespace Vim.BFastNextNS { public static class BFastNextExtensions { @@ -26,7 +26,7 @@ public static BFastNext GetBFast(this BFastNext bfast, string name, bool inflate public static void SetBFast(this BFastNext bfast, string name, BFastNext other, bool deflate) { - if (deflate == false) bfast.AddBFast(name, other); + if (deflate == false) bfast.SetBFast(name, other); using (var output = new MemoryStream()) { @@ -36,7 +36,7 @@ public static void SetBFast(this BFastNext bfast, string name, BFastNext other, } var a = output.ToArray(); - bfast.AddArray(name, a); + bfast.SetArray(name, a); } } diff --git a/src/cs/Vim.BFast.Next/BFastNextNode.cs b/src/cs/Vim.BFast.Next/BFastNextNode.cs index 3120e93e..458fa8ca 100644 --- a/src/cs/Vim.BFast.Next/BFastNextNode.cs +++ b/src/cs/Vim.BFast.Next/BFastNextNode.cs @@ -2,7 +2,7 @@ using System.IO; using Vim.BFast; -namespace Vim.BFastNext +namespace Vim.BFastNextNS { public class BFastNextNode : IBFastNextNode { diff --git a/src/cs/Vim.BFast.Next/IBFastNextNode.cs b/src/cs/Vim.BFast.Next/IBFastNextNode.cs index e4cb8ab0..a46a9eec 100644 --- a/src/cs/Vim.BFast.Next/IBFastNextNode.cs +++ b/src/cs/Vim.BFast.Next/IBFastNextNode.cs @@ -1,6 +1,6 @@ using System.IO; -namespace Vim.BFastNext +namespace Vim.BFastNextNS { /// /// Anything that can be added to a BFAST must have a size and write to a stream. diff --git a/src/cs/Vim.BFastNext.Tests/BFastNextTests.cs b/src/cs/Vim.BFastNext.Tests/BFastNextTests.cs index 5ef14ced..beb82353 100644 --- a/src/cs/Vim.BFastNext.Tests/BFastNextTests.cs +++ b/src/cs/Vim.BFastNext.Tests/BFastNextTests.cs @@ -1,7 +1,7 @@ using NUnit.Framework; using Vim.Util.Tests; -namespace Vim.BFastNext.Tests +namespace Vim.BFastNextNS.Tests { public class BFastNextTests { @@ -68,7 +68,7 @@ public void EmptyBFast_Writes_Header() public void SetArray_Adds_Entry() { var bfast = new BFastNext(); - bfast.AddArray("A", new int[3] { 0, 1, 2 }); + bfast.SetArray("A", new int[3] { 0, 1, 2 }); Assert.That(bfast.Entries.Count(), Is.EqualTo(1)); } @@ -77,7 +77,7 @@ public void SetArray_Adds_Entry() public void SetArray_Then_GetArray() { var bfast = new BFastNext(); - bfast.AddArray("A", new int[3] { 0, 1, 2 }); + bfast.SetArray("A", new int[3] { 0, 1, 2 }); var result = bfast.GetArray("A"); Assert.That(result, Is.EqualTo(new int[3] { 0, 1, 2 })); @@ -87,7 +87,7 @@ public void SetArray_Then_GetArray() public void SetArray_Then_GetArray_Bytes() { var bfast = new BFastNext(); - bfast.AddArray("A", new int[3] { 0, 1, 2 }); + bfast.SetArray("A", new int[3] { 0, 1, 2 }); var result = bfast.GetArray("A"); var bytes = (new int[3] { 0, 1, 2 }).SelectMany(i => BitConverter.GetBytes(i)); @@ -98,7 +98,7 @@ public void SetArray_Then_GetArray_Bytes() public void SetArray_Then_GetArray_Float() { var bfast = new BFastNext(); - bfast.AddArray("A", new int[3] { 0, 1, 2 }); + bfast.SetArray("A", new int[3] { 0, 1, 2 }); var result = bfast.GetArray("A"); var floats = (new int[3] { 0, 1, 2 }).Select(i => BitConverter.Int32BitsToSingle(i)); @@ -109,7 +109,7 @@ public void SetArray_Then_GetArray_Float() public void SetArray_Then_GetBFast_Returns_Null() { var bfast = new BFastNext(); - bfast.AddArray("A", new int[3] { 0, 1, 2 }); + bfast.SetArray("A", new int[3] { 0, 1, 2 }); var result = bfast.GetBFast("A"); Assert.IsNull(result); @@ -119,8 +119,8 @@ public void SetArray_Then_GetBFast_Returns_Null() public void SetArray_Then_SetArray_Replaces() { var bfast = new BFastNext(); - bfast.AddArray("A", new int[3] { 0, 1, 2 }); - bfast.AddArray("A", new float[3] { 0.1f, 0.2f, 0.3f }); + bfast.SetArray("A", new int[3] { 0, 1, 2 }); + bfast.SetArray("A", new float[3] { 0.1f, 0.2f, 0.3f }); var result = bfast.GetArray("A"); Assert.That(result, Is.EqualTo(new float[3] { 0.1f, 0.2f, 0.3f })); @@ -131,8 +131,8 @@ public void SetArray_Then_SetBFast_Replaces() { var bfast = new BFastNext(); - bfast.AddArray("A", new int[3] { 0, 1, 2 }); - bfast.AddBFast("A", new BFastNext()); + bfast.SetArray("A", new int[3] { 0, 1, 2 }); + bfast.SetBFast("A", new BFastNext()); var result = bfast.GetArray("A"); Assert.That(result.Length > 3); } @@ -141,7 +141,7 @@ public void SetArray_Then_SetBFast_Replaces() public void SetBFast_Adds_Entry() { var bfast = new BFastNext(); - bfast.AddBFast("A", new BFastNext()); + bfast.SetBFast("A", new BFastNext()); Assert.That(bfast.Entries.Count(), Is.EqualTo(1)); } @@ -151,7 +151,7 @@ public void SetBFast_Then_GetBFast_Returns_Same() { var bfast = new BFastNext(); var b = new BFastNext(); - bfast.AddBFast("A", b); + bfast.SetBFast("A", b); var result = bfast.GetBFast("A"); Assert.That(result, Is.EqualTo(b)); @@ -163,8 +163,8 @@ public void SetBFast_Then_SetBFast_Replaces() var bfast = new BFastNext(); var a = new BFastNext(); var b = new BFastNext(); - bfast.AddBFast("A", a); - bfast.AddBFast("A", b); + bfast.SetBFast("A", a); + bfast.SetBFast("A", b); var result = bfast.GetBFast("A"); Assert.That(a != b); Assert.That(result == b); @@ -174,8 +174,8 @@ public void SetBFast_Then_SetBFast_Replaces() public void SetBFast_Then_SetArray_Replaces() { var bfast = new BFastNext(); - bfast.AddBFast("A", new BFastNext()); - bfast.AddArray("A", new int[3] { 0, 1, 2 }); + bfast.SetBFast("A", new BFastNext()); + bfast.SetArray("A", new int[3] { 0, 1, 2 }); var result = bfast.GetBFast("A"); Assert.IsNull(result); } @@ -192,7 +192,7 @@ public void Remove_Missing_DoesNothing() public void Remove_Array() { var bfast = new BFastNext(); - bfast.AddArray("A", new int[3] { 0, 1, 2 }); + bfast.SetArray("A", new int[3] { 0, 1, 2 }); bfast.Remove("A"); Assert.IsNull(bfast.GetArray("A")); Assert.That(bfast.Entries.Count() == 0); @@ -202,7 +202,7 @@ public void Remove_Array() public void Remove_BFast() { var bfast = new BFastNext(); - bfast.AddBFast("A", new BFastNext()); + bfast.SetBFast("A", new BFastNext()); bfast.Remove("A"); Assert.IsNull(bfast.GetBFast("A")); Assert.That(bfast.Entries.Count() == 0); @@ -212,7 +212,7 @@ public void Remove_BFast() public void Removed_BFast_Not_Written() { var bfast = new BFastNext(); - bfast.AddBFast("A", new BFastNext()); + bfast.SetBFast("A", new BFastNext()); bfast.Remove("A"); bfast.Write(Path); @@ -229,7 +229,7 @@ public void Removed_BFast_Not_Written() public void Removed_Array_Not_Written() { var bfast = new BFastNext(); - bfast.AddArray("A", new int[3] { 0, 1, 2 }); + bfast.SetArray("A", new int[3] { 0, 1, 2 }); bfast.Remove("A"); bfast.Write(Path); @@ -249,7 +249,7 @@ public void Removed_InChild_Not_Written() var input = new BFastNext(residence); var geometry = input.GetBFast("geometry"); geometry.Remove("g3d:vertex:position:0:float32:3"); - input.AddBFast("geometry", geometry); + input.SetBFast("geometry", geometry); input.Write(Path); } @@ -268,7 +268,7 @@ public void Write_Then_Read_Array() { var bfast = new BFastNext(); - bfast.AddArray("A", new int[3] { 0, 1, 2 }); + bfast.SetArray("A", new int[3] { 0, 1, 2 }); bfast.Write(Path); using (var stream = File.OpenRead(Path)) @@ -285,8 +285,8 @@ public void Write_Then_Read_SimpleBFast() var bfast = new BFastNext(); var child = new BFastNext(); - bfast.AddBFast("child", child); - child.AddArray("A", new int[3] { 0, 1, 2 }); + bfast.SetBFast("child", child); + child.SetArray("A", new int[3] { 0, 1, 2 }); bfast.Write(Path); using (var stream = File.OpenRead(Path)) @@ -308,8 +308,8 @@ public void Write_Then_Read_NestedBFast() var child = new BFastNext(); var grandChild = new BFastNext(); - bfast.AddBFast("child", child); - child.AddBFast("grandChild", grandChild); + bfast.SetBFast("child", child); + child.SetBFast("grandChild", grandChild); bfast.Write(Path); using (var stream = File.OpenRead(Path)) @@ -331,9 +331,9 @@ public void Write_Then_Read_NestedBFast_WithArray() var child = new BFastNext(); var grandChild = new BFastNext(); - bfast.AddBFast("child", child); - child.AddBFast("grandChild", grandChild); - grandChild.AddArray("A", new int[3] { 0, 1, 2 }); + bfast.SetBFast("child", child); + child.SetBFast("grandChild", grandChild); + grandChild.SetArray("A", new int[3] { 0, 1, 2 }); bfast.Write(Path); @@ -355,8 +355,8 @@ public void Write_Then_Read_NestedBFast_WithArray() public void Write_Then_Read_Mixed_Sources() { var basic = new BFastNext(); - basic.AddArray("ints", new int[1] { 1 }); - basic.AddArray("floats", new float[1] { 2.0f }); + basic.SetArray("ints", new int[1] { 1 }); + basic.SetArray("floats", new float[1] { 2.0f }); basic.Write(Path); using (var stream = File.OpenRead(Path)) @@ -367,8 +367,8 @@ public void Write_Then_Read_Mixed_Sources() var inputResidence = new BFastNext(residence); var output = new BFastNext(); - output.AddBFast("input", input); - output.AddBFast("residence", inputResidence); + output.SetBFast("input", input); + output.SetBFast("residence", inputResidence); output.Write(OutputPath); } } @@ -387,4 +387,4 @@ public void Write_Then_Read_Mixed_Sources() } } } -} \ No newline at end of file +} diff --git a/src/cs/vim/Vim.Format.Vimx/G3dVimScene.cs b/src/cs/Vim.Format.Vimx.Conversion/MeshesToScene.cs similarity index 83% rename from src/cs/vim/Vim.Format.Vimx/G3dVimScene.cs rename to src/cs/Vim.Format.Vimx.Conversion/MeshesToScene.cs index ecf8c361..a86f18e6 100644 --- a/src/cs/vim/Vim.Format.Vimx/G3dVimScene.cs +++ b/src/cs/Vim.Format.Vimx.Conversion/MeshesToScene.cs @@ -6,16 +6,13 @@ using Vim.LinqArray; using Vim.Math3d; -namespace Vim.Format.Vimx +namespace Vim.Format.VimxNS.Conversion { - public static class G3dVimScene + public static class MeshesToScene { - /// - /// - /// - public static G3dScene2 ToG3dScene(this G3dVim g3d, DocumentModel bim, G3dMesh[] meshes) + public static G3dScene CreateScene(G3dVim g3d, DocumentModel bim, G3dMesh[] meshes) { - var scene = new G3dScene2(); + var scene = new G3dScene(); var nodeElements = bim.NodeElementIndex.ToArray(); var nodeElementIds = nodeElements .Select(n => n < 0 || n > bim.ElementId.Count @@ -27,7 +24,7 @@ public static G3dScene2 ToG3dScene(this G3dVim g3d, DocumentModel bim, G3dMesh[] scene.InstanceGroups = scene.InstanceNodes.Select(n => nodeElements[n]).ToArray(); scene.InstanceTags = scene.InstanceNodes.Select(n => nodeElementIds[n]).ToArray(); (scene.InstanceMins, scene.InstanceMaxs) = ComputeBoundingBoxes(meshes, scene.InstanceFiles, scene.InstanceIndices); - scene.InstanceFlags = scene.InstanceNodes.Select(i => g3d.instanceFlags[i]).ToArray(); + scene.InstanceFlags = scene.InstanceNodes.Select(i => g3d.InstanceFlags[i]).ToArray(); // meshes scene.MeshInstanceCounts = new int[meshes.Length]; @@ -35,7 +32,6 @@ public static G3dScene2 ToG3dScene(this G3dVim g3d, DocumentModel bim, G3dMesh[] scene.MeshVertexCounts = new int[meshes.Length]; scene.MeshOpaqueIndexCounts = new int[meshes.Length]; scene.MeshOpaqueVertexCounts = new int[meshes.Length]; - var opaqueVertices = new int[meshes.Length]; for (var i = 0; i < meshes.Length; i++) { @@ -44,7 +40,7 @@ public static G3dScene2 ToG3dScene(this G3dVim g3d, DocumentModel bim, G3dMesh[] scene.MeshIndexCounts[i] = mesh.GetIndexCount(); scene.MeshVertexCounts[i] = mesh.GetVertexCount(); scene.MeshOpaqueIndexCounts[i] = mesh.GetIndexCount(MeshSection.Opaque); - opaqueVertices[i] = mesh.GetVertexCount(MeshSection.Opaque); + scene.MeshOpaqueVertexCounts[i] = mesh.GetVertexCount(MeshSection.Opaque); } return scene; } @@ -64,8 +60,8 @@ private static (Vector3[] min, Vector3[] max) ComputeBoundingBoxes(G3dMesh[] mes var vertexCount = mesh.GetVertexCount(); for (var j = 0; j < vertexCount; j++) { - var pos = mesh.positions[j]; - var matrix = mesh.instanceTransforms[index]; + var pos = mesh.Positions[j]; + var matrix = mesh.InstanceTransforms[index]; var pos2 = pos.Transform(matrix); min = min.Min(pos2); max = max.Max(pos2); @@ -86,11 +82,11 @@ private static (int[], int[], int[]) GetInstanceFiles(this G3dMesh[] meshes) for (var i = 0; i < meshes.Length; i++) { var mesh = meshes[i]; - for (var j = 0; j < mesh.instanceNodes.Length; j++) + for (var j = 0; j < mesh.InstanceNodes.Length; j++) { instanceFiles.Add(i); instanceIndices.Add(j); - instanceNodes.Add(mesh.instanceNodes[j]); + instanceNodes.Add(mesh.InstanceNodes[j]); } } return (instanceFiles.ToArray(), instanceIndices.ToArray(), instanceNodes.ToArray()); diff --git a/src/cs/Vim.Format.Vimx.Conversion/Vim.Format.Vimx.Conversion.csproj b/src/cs/Vim.Format.Vimx.Conversion/Vim.Format.Vimx.Conversion.csproj new file mode 100644 index 00000000..2fe0ebbd --- /dev/null +++ b/src/cs/Vim.Format.Vimx.Conversion/Vim.Format.Vimx.Conversion.csproj @@ -0,0 +1,15 @@ + + + + netstandard2.0 + + + + + + + + + + + diff --git a/src/cs/vim/Vim.Format.Vimx/G3dVimMeshes.cs b/src/cs/Vim.Format.Vimx.Conversion/VimToMeshes.cs similarity index 78% rename from src/cs/vim/Vim.Format.Vimx/G3dVimMeshes.cs rename to src/cs/Vim.Format.Vimx.Conversion/VimToMeshes.cs index 6cdb773e..add9efe7 100644 --- a/src/cs/vim/Vim.Format.Vimx/G3dVimMeshes.cs +++ b/src/cs/Vim.Format.Vimx.Conversion/VimToMeshes.cs @@ -4,15 +4,16 @@ using Vim.Util; using Vim.BFast; using Vim.Math3d; +using Vim.G3dNext.Attributes; -namespace Vim.Format.Vimx +namespace Vim.Format.VimxNS.Conversion { - internal static class G3dVimMeshes + public static class VimToMeshes { /// /// Splits a g3dVim into a sequence of vimx getMesh. /// - public static IEnumerable ToG3dMeshes(this G3dVim g3d) + public static IEnumerable ExtractMeshes(G3dVim g3d) { var meshInstances = g3d.GetMeshInstances(); @@ -29,9 +30,9 @@ private static List[] GetMeshInstances(this G3dVim g3d) result[i] = new List(); } - for (var i = 0; i < g3d.instanceMeshes.Length; i++) + for (var i = 0; i < g3d.InstanceMeshes.Length; i++) { - var mesh = g3d.instanceMeshes[i]; + var mesh = g3d.InstanceMeshes[i]; if (mesh >= 0) { result[mesh].Add(i); @@ -62,8 +63,8 @@ private static G3dMesh GetMesh(this G3dVim g3d, int mesh, List instances) { var instance = instances[i]; instanceNodes[i] = instances[i]; - instanceTransforms[i] = g3d.instanceTransforms[instance]; - instanceFlags[i] = g3d.instanceFlags[instance]; + instanceTransforms[i] = g3d.InstanceTransforms[instance]; + instanceFlags[i] = g3d.InstanceFlags[instance]; } var opaqueCount = AppendSubmeshes( @@ -88,17 +89,17 @@ private static G3dMesh GetMesh(this G3dVim g3d, int mesh, List instances) vertices ); - var result = G3dMesh.FromArrays( - instanceNodes.ToArray(), - instanceTransforms.ToArray(), - opaqueCount, - submeshIndexOffsets.ToArray(), - submeshVertexOffsets.ToArray(), - submeshMaterials.ToArray(), - indices.ToArray(), - vertices.ToArray() - ); - return result; + return new G3dMesh() + { + InstanceNodes = instanceNodes.ToArray(), + InstanceTransforms = instanceTransforms.ToArray(), + OpaqueSubmeshCounts = new int[] { opaqueCount }, + SubmeshIndexOffsets = submeshIndexOffsets.ToArray(), + SubmeshVertexOffsets = submeshVertexOffsets.ToArray(), + SubmeshMaterials = submeshMaterials.ToArray(), + Indices = indices.ToArray(), + Positions = vertices.ToArray() + }; } private static int AppendSubmeshes( @@ -117,8 +118,8 @@ List vertices var count = 0; for (var sub = subStart; sub < subEnd; sub++) { - var currentMat = g3d.submeshMaterials[sub]; - var color = currentMat > 0 ? g3d.materialColors[currentMat] : Vector4.One; + var currentMat = g3d.SubmeshMaterials[sub]; + var color = currentMat > 0 ? g3d.MaterialColors[currentMat] : Vector4.One; var accept = color.W < 1 == transparent; if (!accept) continue; @@ -144,7 +145,7 @@ private static (List, List) GetSubmesh(this G3dVim g3d, int submes for (var i = start; i < end; i++) { - var v = g3d.indices[i]; + var v = g3d.Indices[i]; if (dict.ContainsKey(v)) { indices.Add(dict[v]); @@ -153,10 +154,10 @@ private static (List, List) GetSubmesh(this G3dVim g3d, int submes { indices.Add(vertices.Count); dict.Add(v, vertices.Count); - vertices.Add(g3d.vertices[v]); + vertices.Add(g3d.Positions[v]); } } return (indices, vertices); } } -} \ No newline at end of file +} diff --git a/src/cs/Vim.Format.Vimx.Conversion/VimxConverter.cs b/src/cs/Vim.Format.Vimx.Conversion/VimxConverter.cs new file mode 100644 index 00000000..758893a1 --- /dev/null +++ b/src/cs/Vim.Format.Vimx.Conversion/VimxConverter.cs @@ -0,0 +1,37 @@ +using System.Linq; +using Vim.LinqArray; +using Vim.BFast; +using Vim.G3dNext.Attributes; +using Vim.Format.ObjectModel; +using Vim.G3dNext; + +namespace Vim.Format.VimxNS.Conversion +{ + public static class VimxConverter + { + public static Vimx FromVimPath(string vimPath) + { + var vim = VimScene.LoadVim(vimPath, new LoadOptions() + { + SkipAssets = true, + SkipGeometry = true, + }); + + var g3d = G3dVim.FromVim(vimPath); + return FromVim(g3d, vim.DocumentModel); + } + + public static Vimx FromVim(G3dVim g3d, DocumentModel bim) + { + var meshes = VimToMeshes.ExtractMeshes(g3d) + .OrderByBim(bim) + .ToArray(); + + var scene = MeshesToScene.CreateScene(g3d, bim, meshes); + var materials = new G3dMaterials(g3d.ToBFast()); + var header = VimxHeader.CreateDefault(); + + return new Vimx(header, MetaHeader.Default, scene, materials, meshes); + } + } +} diff --git a/src/cs/vim/Vim.Format.Vimx/G3dMeshExtensions.cs b/src/cs/Vim.Format.Vimx.Conversion/VimxOrdering.cs similarity index 58% rename from src/cs/vim/Vim.Format.Vimx/G3dMeshExtensions.cs rename to src/cs/Vim.Format.Vimx.Conversion/VimxOrdering.cs index 0defaa41..cf9ff791 100644 --- a/src/cs/vim/Vim.Format.Vimx/G3dMeshExtensions.cs +++ b/src/cs/Vim.Format.Vimx.Conversion/VimxOrdering.cs @@ -1,40 +1,12 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; using Vim.Format.ObjectModel; -using Vim.Math3d; +using Vim.G3dNext.Attributes; -namespace Vim.Format.Vimx +namespace Vim.Format.VimxNS.Conversion { - public static class G3dMeshExtensions + public static class VimxOrdering { - public static AABox GetAABB(this G3dMesh mesh) - { - var box = new AABox(mesh.positions[0], mesh.positions[0]); - for (var p = 1; p < mesh.positions.Length; p++) - { - var pos = mesh.positions[p]; - box = box.Expand(pos); - } - return box; - } - - private static AABox Expand(this AABox box, Vector3 pos) - { - return new AABox( - new Vector3( - Math.Min(box.Min.X, pos.X), - Math.Min(box.Min.Y, pos.Y), - Math.Min(box.Min.Z, pos.Z) - ), - new Vector3( - Math.Max(box.Max.X, pos.X), - Math.Max(box.Max.Y, pos.Y), - Math.Max(box.Max.Z, pos.Z) - ) - ); - } - public static IEnumerable OrderByBim(this IEnumerable meshes, DocumentModel bim) { return meshes.OrderByDescending((m) => ( @@ -43,9 +15,9 @@ public static IEnumerable OrderByBim(this IEnumerable meshes, ); } - public static string GetMeshName(this G3dMesh mesh, DocumentModel bim) + static string GetMeshName(this G3dMesh mesh, DocumentModel bim) { - var node = mesh.instanceNodes[0]; + var node = mesh.InstanceNodes[0]; if (node < 0 || node >= bim.NodeElementIndex.Count) return ""; var element = bim.NodeElementIndex[node]; diff --git a/src/cs/g3d/Vim.G3dNext.Attributes/Attributes.g.cs b/src/cs/g3d/Vim.G3dNext.Attributes/Attributes.g.cs index 4630ef5f..1b837ee2 100644 --- a/src/cs/g3d/Vim.G3dNext.Attributes/Attributes.g.cs +++ b/src/cs/g3d/Vim.G3dNext.Attributes/Attributes.g.cs @@ -5,56 +5,12 @@ using System.Collections.Generic; using System.Linq; using Vim.BFast; +using Vim.BFastNextNS; namespace Vim.G3dNext.Attributes { - public partial class CornersPerFaceAttribute : IAttribute - { - public const string AttributeName = "g3d:all:facesize:0:int32:1"; - - public string Name - => AttributeName; - - public int Count => TypedData?.Length ?? 0; - - public void AddTo(BFastNext.BFastNext bfast) - { - if(TypedData != null) - { - bfast.AddArray(Name, TypedData); - } - } - - public void ReadBFast(BFastNext.BFastNext bfast) - { - TypedData = bfast.GetArray("g3d:all:facesize:0:int32:1"); - } - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Singleton; - - public Type IndexInto { get; } - = null; - - public System.Int32[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - - public partial class VertexAttribute : IAttribute + public partial class PositionsAttribute : IAttribute { public const string AttributeName = "g3d:vertex:position:0:float32:3"; @@ -63,15 +19,15 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext.BFastNext bfast) + public void AddTo(BFastNext bfast) { if(TypedData != null) { - bfast.AddArray(Name, TypedData); + bfast.SetArray(Name, TypedData); } } - public void ReadBFast(BFastNext.BFastNext bfast) + public void ReadBFast(BFastNext bfast) { TypedData = bfast.GetArray("g3d:vertex:position:0:float32:3"); } @@ -99,7 +55,7 @@ public void Write(Stream stream) } } - public partial class IndexAttribute : IAttribute + public partial class IndicesAttribute : IAttribute { public const string AttributeName = "g3d:corner:index:0:int32:1"; @@ -108,15 +64,15 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext.BFastNext bfast) + public void AddTo(BFastNext bfast) { if(TypedData != null) { - bfast.AddArray(Name, TypedData); + bfast.SetArray(Name, TypedData); } } - public void ReadBFast(BFastNext.BFastNext bfast) + public void ReadBFast(BFastNext bfast) { TypedData = bfast.GetArray("g3d:corner:index:0:int32:1"); } @@ -128,7 +84,7 @@ public void ReadBFast(BFastNext.BFastNext bfast) = AttributeType.Index; public Type IndexInto { get; } - = typeof(Vim.G3dNext.Attributes.VertexAttribute); + = typeof(Vim.G3dNext.Attributes.PositionsAttribute); public System.Int32[] TypedData { get; set; } = Array.Empty(); @@ -144,7 +100,7 @@ public void Write(Stream stream) } } - public partial class InstanceTransformAttribute : IAttribute + public partial class InstanceTransformsAttribute : IAttribute { public const string AttributeName = "g3d:instance:transform:0:float32:16"; @@ -153,15 +109,15 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext.BFastNext bfast) + public void AddTo(BFastNext bfast) { if(TypedData != null) { - bfast.AddArray(Name, TypedData); + bfast.SetArray(Name, TypedData); } } - public void ReadBFast(BFastNext.BFastNext bfast) + public void ReadBFast(BFastNext bfast) { TypedData = bfast.GetArray("g3d:instance:transform:0:float32:16"); } @@ -189,7 +145,7 @@ public void Write(Stream stream) } } - public partial class InstanceParentAttribute : IAttribute + public partial class InstanceParentsAttribute : IAttribute { public const string AttributeName = "g3d:instance:parent:0:int32:1"; @@ -198,15 +154,15 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext.BFastNext bfast) + public void AddTo(BFastNext bfast) { if(TypedData != null) { - bfast.AddArray(Name, TypedData); + bfast.SetArray(Name, TypedData); } } - public void ReadBFast(BFastNext.BFastNext bfast) + public void ReadBFast(BFastNext bfast) { TypedData = bfast.GetArray("g3d:instance:parent:0:int32:1"); } @@ -218,7 +174,7 @@ public void ReadBFast(BFastNext.BFastNext bfast) = AttributeType.Index; public Type IndexInto { get; } - = typeof(Vim.G3dNext.Attributes.InstanceTransformAttribute); + = typeof(Vim.G3dNext.Attributes.InstanceTransformsAttribute); public System.Int32[] TypedData { get; set; } = Array.Empty(); @@ -243,15 +199,15 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext.BFastNext bfast) + public void AddTo(BFastNext bfast) { if(TypedData != null) { - bfast.AddArray(Name, TypedData); + bfast.SetArray(Name, TypedData); } } - public void ReadBFast(BFastNext.BFastNext bfast) + public void ReadBFast(BFastNext bfast) { TypedData = bfast.GetArray("g3d:instance:flags:0:uint16:1"); } @@ -279,7 +235,7 @@ public void Write(Stream stream) } } - public partial class InstanceMeshAttribute : IAttribute + public partial class InstanceMeshesAttribute : IAttribute { public const string AttributeName = "g3d:instance:mesh:0:int32:1"; @@ -288,15 +244,15 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext.BFastNext bfast) + public void AddTo(BFastNext bfast) { if(TypedData != null) { - bfast.AddArray(Name, TypedData); + bfast.SetArray(Name, TypedData); } } - public void ReadBFast(BFastNext.BFastNext bfast) + public void ReadBFast(BFastNext bfast) { TypedData = bfast.GetArray("g3d:instance:mesh:0:int32:1"); } @@ -308,7 +264,7 @@ public void ReadBFast(BFastNext.BFastNext bfast) = AttributeType.Index; public Type IndexInto { get; } - = typeof(Vim.G3dNext.Attributes.MeshSubmeshOffsetAttribute); + = typeof(Vim.G3dNext.Attributes.MeshSubmeshOffsetsAttribute); public System.Int32[] TypedData { get; set; } = Array.Empty(); @@ -324,7 +280,7 @@ public void Write(Stream stream) } } - public partial class MeshSubmeshOffsetAttribute : IAttribute + public partial class MeshSubmeshOffsetsAttribute : IAttribute { public const string AttributeName = "g3d:mesh:submeshoffset:0:int32:1"; @@ -333,15 +289,15 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext.BFastNext bfast) + public void AddTo(BFastNext bfast) { if(TypedData != null) { - bfast.AddArray(Name, TypedData); + bfast.SetArray(Name, TypedData); } } - public void ReadBFast(BFastNext.BFastNext bfast) + public void ReadBFast(BFastNext bfast) { TypedData = bfast.GetArray("g3d:mesh:submeshoffset:0:int32:1"); } @@ -353,7 +309,7 @@ public void ReadBFast(BFastNext.BFastNext bfast) = AttributeType.Index; public Type IndexInto { get; } - = typeof(Vim.G3dNext.Attributes.SubmeshIndexOffsetAttribute); + = typeof(Vim.G3dNext.Attributes.SubmeshIndexOffsetsAttribute); public System.Int32[] TypedData { get; set; } = Array.Empty(); @@ -369,7 +325,7 @@ public void Write(Stream stream) } } - public partial class SubmeshIndexOffsetAttribute : IAttribute + public partial class SubmeshIndexOffsetsAttribute : IAttribute { public const string AttributeName = "g3d:submesh:indexoffset:0:int32:1"; @@ -378,15 +334,15 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext.BFastNext bfast) + public void AddTo(BFastNext bfast) { if(TypedData != null) { - bfast.AddArray(Name, TypedData); + bfast.SetArray(Name, TypedData); } } - public void ReadBFast(BFastNext.BFastNext bfast) + public void ReadBFast(BFastNext bfast) { TypedData = bfast.GetArray("g3d:submesh:indexoffset:0:int32:1"); } @@ -398,7 +354,7 @@ public void ReadBFast(BFastNext.BFastNext bfast) = AttributeType.Index; public Type IndexInto { get; } - = typeof(Vim.G3dNext.Attributes.IndexAttribute); + = typeof(Vim.G3dNext.Attributes.IndicesAttribute); public System.Int32[] TypedData { get; set; } = Array.Empty(); @@ -414,7 +370,7 @@ public void Write(Stream stream) } } - public partial class SubmeshMaterialAttribute : IAttribute + public partial class SubmeshMaterialsAttribute : IAttribute { public const string AttributeName = "g3d:submesh:material:0:int32:1"; @@ -423,15 +379,15 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext.BFastNext bfast) + public void AddTo(BFastNext bfast) { if(TypedData != null) { - bfast.AddArray(Name, TypedData); + bfast.SetArray(Name, TypedData); } } - public void ReadBFast(BFastNext.BFastNext bfast) + public void ReadBFast(BFastNext bfast) { TypedData = bfast.GetArray("g3d:submesh:material:0:int32:1"); } @@ -443,7 +399,7 @@ public void ReadBFast(BFastNext.BFastNext bfast) = AttributeType.Index; public Type IndexInto { get; } - = typeof(Vim.G3dNext.Attributes.MaterialColorAttribute); + = typeof(Vim.G3dNext.Attributes.MaterialColorsAttribute); public System.Int32[] TypedData { get; set; } = Array.Empty(); @@ -459,7 +415,7 @@ public void Write(Stream stream) } } - public partial class ShapeVertexAttribute : IAttribute + public partial class ShapeVerticesAttribute : IAttribute { public const string AttributeName = "g3d:shapevertex:position:0:float32:3"; @@ -468,15 +424,15 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext.BFastNext bfast) + public void AddTo(BFastNext bfast) { if(TypedData != null) { - bfast.AddArray(Name, TypedData); + bfast.SetArray(Name, TypedData); } } - public void ReadBFast(BFastNext.BFastNext bfast) + public void ReadBFast(BFastNext bfast) { TypedData = bfast.GetArray("g3d:shapevertex:position:0:float32:3"); } @@ -504,7 +460,7 @@ public void Write(Stream stream) } } - public partial class ShapeVertexOffsetAttribute : IAttribute + public partial class ShapeVertexOffsetsAttribute : IAttribute { public const string AttributeName = "g3d:shape:vertexoffset:0:int32:1"; @@ -513,15 +469,15 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext.BFastNext bfast) + public void AddTo(BFastNext bfast) { if(TypedData != null) { - bfast.AddArray(Name, TypedData); + bfast.SetArray(Name, TypedData); } } - public void ReadBFast(BFastNext.BFastNext bfast) + public void ReadBFast(BFastNext bfast) { TypedData = bfast.GetArray("g3d:shape:vertexoffset:0:int32:1"); } @@ -533,7 +489,7 @@ public void ReadBFast(BFastNext.BFastNext bfast) = AttributeType.Index; public Type IndexInto { get; } - = typeof(Vim.G3dNext.Attributes.ShapeVertexAttribute); + = typeof(Vim.G3dNext.Attributes.ShapeVerticesAttribute); public System.Int32[] TypedData { get; set; } = Array.Empty(); @@ -549,7 +505,7 @@ public void Write(Stream stream) } } - public partial class ShapeColorAttribute : IAttribute + public partial class ShapeColorsAttribute : IAttribute { public const string AttributeName = "g3d:shape:color:0:float32:4"; @@ -558,15 +514,15 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext.BFastNext bfast) + public void AddTo(BFastNext bfast) { if(TypedData != null) { - bfast.AddArray(Name, TypedData); + bfast.SetArray(Name, TypedData); } } - public void ReadBFast(BFastNext.BFastNext bfast) + public void ReadBFast(BFastNext bfast) { TypedData = bfast.GetArray("g3d:shape:color:0:float32:4"); } @@ -594,7 +550,7 @@ public void Write(Stream stream) } } - public partial class ShapeWidthAttribute : IAttribute + public partial class ShapeWidthsAttribute : IAttribute { public const string AttributeName = "g3d:shape:width:0:float32:1"; @@ -603,15 +559,15 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext.BFastNext bfast) + public void AddTo(BFastNext bfast) { if(TypedData != null) { - bfast.AddArray(Name, TypedData); + bfast.SetArray(Name, TypedData); } } - public void ReadBFast(BFastNext.BFastNext bfast) + public void ReadBFast(BFastNext bfast) { TypedData = bfast.GetArray("g3d:shape:width:0:float32:1"); } @@ -639,7 +595,7 @@ public void Write(Stream stream) } } - public partial class MaterialColorAttribute : IAttribute + public partial class MaterialColorsAttribute : IAttribute { public const string AttributeName = "g3d:material:color:0:float32:4"; @@ -648,15 +604,15 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext.BFastNext bfast) + public void AddTo(BFastNext bfast) { if(TypedData != null) { - bfast.AddArray(Name, TypedData); + bfast.SetArray(Name, TypedData); } } - public void ReadBFast(BFastNext.BFastNext bfast) + public void ReadBFast(BFastNext bfast) { TypedData = bfast.GetArray("g3d:material:color:0:float32:4"); } @@ -693,15 +649,15 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext.BFastNext bfast) + public void AddTo(BFastNext bfast) { if(TypedData != null) { - bfast.AddArray(Name, TypedData); + bfast.SetArray(Name, TypedData); } } - public void ReadBFast(BFastNext.BFastNext bfast) + public void ReadBFast(BFastNext bfast) { TypedData = bfast.GetArray("g3d:material:glossiness:0:float32:1"); } @@ -738,15 +694,15 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext.BFastNext bfast) + public void AddTo(BFastNext bfast) { if(TypedData != null) { - bfast.AddArray(Name, TypedData); + bfast.SetArray(Name, TypedData); } } - public void ReadBFast(BFastNext.BFastNext bfast) + public void ReadBFast(BFastNext bfast) { TypedData = bfast.GetArray("g3d:material:smoothness:0:float32:1"); } @@ -783,15 +739,15 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext.BFastNext bfast) + public void AddTo(BFastNext bfast) { if(TypedData != null) { - bfast.AddArray(Name, TypedData); + bfast.SetArray(Name, TypedData); } } - public void ReadBFast(BFastNext.BFastNext bfast) + public void ReadBFast(BFastNext bfast) { TypedData = bfast.GetArray("g3d:instance:file:0:int32:1"); } @@ -828,15 +784,15 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext.BFastNext bfast) + public void AddTo(BFastNext bfast) { if(TypedData != null) { - bfast.AddArray(Name, TypedData); + bfast.SetArray(Name, TypedData); } } - public void ReadBFast(BFastNext.BFastNext bfast) + public void ReadBFast(BFastNext bfast) { TypedData = bfast.GetArray("g3d:instance:node:0:int32:1"); } @@ -873,15 +829,15 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext.BFastNext bfast) + public void AddTo(BFastNext bfast) { if(TypedData != null) { - bfast.AddArray(Name, TypedData); + bfast.SetArray(Name, TypedData); } } - public void ReadBFast(BFastNext.BFastNext bfast) + public void ReadBFast(BFastNext bfast) { TypedData = bfast.GetArray("g3d:instance:index:0:int32:1"); } @@ -918,15 +874,15 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext.BFastNext bfast) + public void AddTo(BFastNext bfast) { if(TypedData != null) { - bfast.AddArray(Name, TypedData); + bfast.SetArray(Name, TypedData); } } - public void ReadBFast(BFastNext.BFastNext bfast) + public void ReadBFast(BFastNext bfast) { TypedData = bfast.GetArray("g3d:instance:group:0:int32:1"); } @@ -963,15 +919,15 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext.BFastNext bfast) + public void AddTo(BFastNext bfast) { if(TypedData != null) { - bfast.AddArray(Name, TypedData); + bfast.SetArray(Name, TypedData); } } - public void ReadBFast(BFastNext.BFastNext bfast) + public void ReadBFast(BFastNext bfast) { TypedData = bfast.GetArray("g3d:instance:tag:0:int64:1"); } @@ -1008,15 +964,15 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext.BFastNext bfast) + public void AddTo(BFastNext bfast) { if(TypedData != null) { - bfast.AddArray(Name, TypedData); + bfast.SetArray(Name, TypedData); } } - public void ReadBFast(BFastNext.BFastNext bfast) + public void ReadBFast(BFastNext bfast) { TypedData = bfast.GetArray("g3d:instance:min:0:float32:3"); } @@ -1053,15 +1009,15 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext.BFastNext bfast) + public void AddTo(BFastNext bfast) { if(TypedData != null) { - bfast.AddArray(Name, TypedData); + bfast.SetArray(Name, TypedData); } } - public void ReadBFast(BFastNext.BFastNext bfast) + public void ReadBFast(BFastNext bfast) { TypedData = bfast.GetArray("g3d:instance:max:0:float32:3"); } @@ -1098,15 +1054,15 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext.BFastNext bfast) + public void AddTo(BFastNext bfast) { if(TypedData != null) { - bfast.AddArray(Name, TypedData); + bfast.SetArray(Name, TypedData); } } - public void ReadBFast(BFastNext.BFastNext bfast) + public void ReadBFast(BFastNext bfast) { TypedData = bfast.GetArray("g3d:mesh:instancecount:0:int32:1"); } @@ -1143,15 +1099,15 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext.BFastNext bfast) + public void AddTo(BFastNext bfast) { if(TypedData != null) { - bfast.AddArray(Name, TypedData); + bfast.SetArray(Name, TypedData); } } - public void ReadBFast(BFastNext.BFastNext bfast) + public void ReadBFast(BFastNext bfast) { TypedData = bfast.GetArray("g3d:mesh:vertexcount:0:int32:1"); } @@ -1188,15 +1144,15 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext.BFastNext bfast) + public void AddTo(BFastNext bfast) { if(TypedData != null) { - bfast.AddArray(Name, TypedData); + bfast.SetArray(Name, TypedData); } } - public void ReadBFast(BFastNext.BFastNext bfast) + public void ReadBFast(BFastNext bfast) { TypedData = bfast.GetArray("g3d:mesh:indexcount:0:int32:1"); } @@ -1233,15 +1189,15 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext.BFastNext bfast) + public void AddTo(BFastNext bfast) { if(TypedData != null) { - bfast.AddArray(Name, TypedData); + bfast.SetArray(Name, TypedData); } } - public void ReadBFast(BFastNext.BFastNext bfast) + public void ReadBFast(BFastNext bfast) { TypedData = bfast.GetArray("g3d:mesh:opaquevertexcount:0:int32:1"); } @@ -1278,15 +1234,15 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext.BFastNext bfast) + public void AddTo(BFastNext bfast) { if(TypedData != null) { - bfast.AddArray(Name, TypedData); + bfast.SetArray(Name, TypedData); } } - public void ReadBFast(BFastNext.BFastNext bfast) + public void ReadBFast(BFastNext bfast) { TypedData = bfast.GetArray("g3d:mesh:opaqueindexcount:0:int32:1"); } @@ -1314,7 +1270,7 @@ public void Write(Stream stream) } } - public partial class MeshInstanceTransformAttribute : IAttribute + public partial class MeshInstanceTransformsAttribute : IAttribute { public const string AttributeName = "g3d:instance:transform:0:float32:16"; @@ -1323,15 +1279,15 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext.BFastNext bfast) + public void AddTo(BFastNext bfast) { if(TypedData != null) { - bfast.AddArray(Name, TypedData); + bfast.SetArray(Name, TypedData); } } - public void ReadBFast(BFastNext.BFastNext bfast) + public void ReadBFast(BFastNext bfast) { TypedData = bfast.GetArray("g3d:instance:transform:0:float32:16"); } @@ -1359,7 +1315,7 @@ public void Write(Stream stream) } } - public partial class MeshOpaqueSubmeshCountAttribute : IAttribute + public partial class MeshOpaqueSubmeshCountsAttribute : IAttribute { public const string AttributeName = "g3d:mesh:opaquesubmeshcount:0:int32:1"; @@ -1368,15 +1324,15 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext.BFastNext bfast) + public void AddTo(BFastNext bfast) { if(TypedData != null) { - bfast.AddArray(Name, TypedData); + bfast.SetArray(Name, TypedData); } } - public void ReadBFast(BFastNext.BFastNext bfast) + public void ReadBFast(BFastNext bfast) { TypedData = bfast.GetArray("g3d:mesh:opaquesubmeshcount:0:int32:1"); } @@ -1404,7 +1360,7 @@ public void Write(Stream stream) } } - public partial class MeshSubmeshIndexOffsetAttribute : IAttribute + public partial class MeshSubmeshIndexOffsetsAttribute : IAttribute { public const string AttributeName = "g3d:submesh:indexoffset:0:int32:1"; @@ -1413,15 +1369,15 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext.BFastNext bfast) + public void AddTo(BFastNext bfast) { if(TypedData != null) { - bfast.AddArray(Name, TypedData); + bfast.SetArray(Name, TypedData); } } - public void ReadBFast(BFastNext.BFastNext bfast) + public void ReadBFast(BFastNext bfast) { TypedData = bfast.GetArray("g3d:submesh:indexoffset:0:int32:1"); } @@ -1433,7 +1389,7 @@ public void ReadBFast(BFastNext.BFastNext bfast) = AttributeType.Index; public Type IndexInto { get; } - = typeof(Vim.G3dNext.Attributes.IndexAttribute); + = typeof(Vim.G3dNext.Attributes.IndicesAttribute); public System.Int32[] TypedData { get; set; } = Array.Empty(); @@ -1449,7 +1405,7 @@ public void Write(Stream stream) } } - public partial class MeshSubmeshVertexOffsetAttribute : IAttribute + public partial class MeshSubmeshVertexOffsetsAttribute : IAttribute { public const string AttributeName = "g3d:submesh:vertexoffset:0:int32:1"; @@ -1458,15 +1414,15 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext.BFastNext bfast) + public void AddTo(BFastNext bfast) { if(TypedData != null) { - bfast.AddArray(Name, TypedData); + bfast.SetArray(Name, TypedData); } } - public void ReadBFast(BFastNext.BFastNext bfast) + public void ReadBFast(BFastNext bfast) { TypedData = bfast.GetArray("g3d:submesh:vertexoffset:0:int32:1"); } @@ -1478,7 +1434,7 @@ public void ReadBFast(BFastNext.BFastNext bfast) = AttributeType.Index; public Type IndexInto { get; } - = typeof(Vim.G3dNext.Attributes.IndexAttribute); + = typeof(Vim.G3dNext.Attributes.IndicesAttribute); public System.Int32[] TypedData { get; set; } = Array.Empty(); @@ -1494,7 +1450,7 @@ public void Write(Stream stream) } } - public partial class MeshSubmeshMaterialAttribute : IAttribute + public partial class MeshSubmeshMaterialsAttribute : IAttribute { public const string AttributeName = "g3d:submesh:material:0:int32:1"; @@ -1503,15 +1459,15 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext.BFastNext bfast) + public void AddTo(BFastNext bfast) { if(TypedData != null) { - bfast.AddArray(Name, TypedData); + bfast.SetArray(Name, TypedData); } } - public void ReadBFast(BFastNext.BFastNext bfast) + public void ReadBFast(BFastNext bfast) { TypedData = bfast.GetArray("g3d:submesh:material:0:int32:1"); } @@ -1523,7 +1479,7 @@ public void ReadBFast(BFastNext.BFastNext bfast) = AttributeType.Index; public Type IndexInto { get; } - = typeof(Vim.G3dNext.Attributes.MaterialColorAttribute); + = typeof(Vim.G3dNext.Attributes.MaterialColorsAttribute); public System.Int32[] TypedData { get; set; } = Array.Empty(); @@ -1539,7 +1495,7 @@ public void Write(Stream stream) } } - public partial class MeshVertexAttribute : IAttribute + public partial class MeshPositionsAttribute : IAttribute { public const string AttributeName = "g3d:vertex:position:0:float32:3"; @@ -1548,15 +1504,15 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext.BFastNext bfast) + public void AddTo(BFastNext bfast) { if(TypedData != null) { - bfast.AddArray(Name, TypedData); + bfast.SetArray(Name, TypedData); } } - public void ReadBFast(BFastNext.BFastNext bfast) + public void ReadBFast(BFastNext bfast) { TypedData = bfast.GetArray("g3d:vertex:position:0:float32:3"); } @@ -1584,7 +1540,7 @@ public void Write(Stream stream) } } - public partial class MeshIndexAttribute : IAttribute + public partial class MeshIndicesAttribute : IAttribute { public const string AttributeName = "g3d:corner:index:0:int32:1"; @@ -1593,15 +1549,15 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext.BFastNext bfast) + public void AddTo(BFastNext bfast) { if(TypedData != null) { - bfast.AddArray(Name, TypedData); + bfast.SetArray(Name, TypedData); } } - public void ReadBFast(BFastNext.BFastNext bfast) + public void ReadBFast(BFastNext bfast) { TypedData = bfast.GetArray("g3d:corner:index:0:int32:1"); } @@ -1613,7 +1569,7 @@ public void ReadBFast(BFastNext.BFastNext bfast) = AttributeType.Index; public Type IndexInto { get; } - = typeof(Vim.G3dNext.Attributes.VertexAttribute); + = typeof(Vim.G3dNext.Attributes.PositionsAttribute); public System.Int32[] TypedData { get; set; } = Array.Empty(); @@ -1629,300 +1585,303 @@ public void Write(Stream stream) } } - public class G3dVim2 + // Please provide an explicit implementation in another partial class file. + public partial class G3dVim : ISetup { - public G3DNext source; + public VimAttributeCollection Attributes; - public G3dVim2() + public G3dVim() : this(new VimAttributeCollection()) { - this.source = new G3DNext (); + // empty } - public G3dVim2(G3DNext source) + public G3dVim(BFastNext bfast) : this(new VimAttributeCollection(bfast)) { - this.source = source; + // empty } - public G3dVim2(BFastNext.BFastNext bfast) + public G3dVim(VimAttributeCollection attributes) { - this.source = new G3DNext(bfast); - } + Attributes = attributes; - - public System.Int32[] CornersPerFace - { - get => source.AttributeCollection.CornersPerFaceAttribute.TypedData; - set => source.AttributeCollection.CornersPerFaceAttribute.TypedData = value; + // Method to implement in another partial class + (this as ISetup).Setup(); } - public Vim.Math3d.Vector3[] Vertex + public BFastNext ToBFast() + => Attributes.ToBFast(); + + + public Vim.Math3d.Vector3[] Positions { - get => source.AttributeCollection.VertexAttribute.TypedData; - set => source.AttributeCollection.VertexAttribute.TypedData = value; + get => Attributes.PositionsAttribute.TypedData; + set => Attributes.PositionsAttribute.TypedData = value; } - public System.Int32[] Index + public System.Int32[] Indices { - get => source.AttributeCollection.IndexAttribute.TypedData; - set => source.AttributeCollection.IndexAttribute.TypedData = value; + get => Attributes.IndicesAttribute.TypedData; + set => Attributes.IndicesAttribute.TypedData = value; } - public Vim.Math3d.Matrix4x4[] InstanceTransform + public Vim.Math3d.Matrix4x4[] InstanceTransforms { - get => source.AttributeCollection.InstanceTransformAttribute.TypedData; - set => source.AttributeCollection.InstanceTransformAttribute.TypedData = value; + get => Attributes.InstanceTransformsAttribute.TypedData; + set => Attributes.InstanceTransformsAttribute.TypedData = value; } - public System.Int32[] InstanceParent + public System.Int32[] InstanceParents { - get => source.AttributeCollection.InstanceParentAttribute.TypedData; - set => source.AttributeCollection.InstanceParentAttribute.TypedData = value; + get => Attributes.InstanceParentsAttribute.TypedData; + set => Attributes.InstanceParentsAttribute.TypedData = value; } public System.UInt16[] InstanceFlags { - get => source.AttributeCollection.InstanceFlagsAttribute.TypedData; - set => source.AttributeCollection.InstanceFlagsAttribute.TypedData = value; + get => Attributes.InstanceFlagsAttribute.TypedData; + set => Attributes.InstanceFlagsAttribute.TypedData = value; } - public System.Int32[] InstanceMesh + public System.Int32[] InstanceMeshes { - get => source.AttributeCollection.InstanceMeshAttribute.TypedData; - set => source.AttributeCollection.InstanceMeshAttribute.TypedData = value; + get => Attributes.InstanceMeshesAttribute.TypedData; + set => Attributes.InstanceMeshesAttribute.TypedData = value; } - public System.Int32[] MeshSubmeshOffset + public System.Int32[] MeshSubmeshOffsets { - get => source.AttributeCollection.MeshSubmeshOffsetAttribute.TypedData; - set => source.AttributeCollection.MeshSubmeshOffsetAttribute.TypedData = value; + get => Attributes.MeshSubmeshOffsetsAttribute.TypedData; + set => Attributes.MeshSubmeshOffsetsAttribute.TypedData = value; } - public System.Int32[] SubmeshIndexOffset + public System.Int32[] SubmeshIndexOffsets { - get => source.AttributeCollection.SubmeshIndexOffsetAttribute.TypedData; - set => source.AttributeCollection.SubmeshIndexOffsetAttribute.TypedData = value; + get => Attributes.SubmeshIndexOffsetsAttribute.TypedData; + set => Attributes.SubmeshIndexOffsetsAttribute.TypedData = value; } - public System.Int32[] SubmeshMaterial + public System.Int32[] SubmeshMaterials { - get => source.AttributeCollection.SubmeshMaterialAttribute.TypedData; - set => source.AttributeCollection.SubmeshMaterialAttribute.TypedData = value; + get => Attributes.SubmeshMaterialsAttribute.TypedData; + set => Attributes.SubmeshMaterialsAttribute.TypedData = value; } - public Vim.Math3d.Vector4[] MaterialColor + public Vim.Math3d.Vector4[] MaterialColors { - get => source.AttributeCollection.MaterialColorAttribute.TypedData; - set => source.AttributeCollection.MaterialColorAttribute.TypedData = value; + get => Attributes.MaterialColorsAttribute.TypedData; + set => Attributes.MaterialColorsAttribute.TypedData = value; } public System.Single[] MaterialGlossiness { - get => source.AttributeCollection.MaterialGlossinessAttribute.TypedData; - set => source.AttributeCollection.MaterialGlossinessAttribute.TypedData = value; + get => Attributes.MaterialGlossinessAttribute.TypedData; + set => Attributes.MaterialGlossinessAttribute.TypedData = value; } public System.Single[] MaterialSmoothness { - get => source.AttributeCollection.MaterialSmoothnessAttribute.TypedData; - set => source.AttributeCollection.MaterialSmoothnessAttribute.TypedData = value; + get => Attributes.MaterialSmoothnessAttribute.TypedData; + set => Attributes.MaterialSmoothnessAttribute.TypedData = value; } - public Vim.Math3d.Vector3[] ShapeVertex + public Vim.Math3d.Vector3[] ShapeVertices { - get => source.AttributeCollection.ShapeVertexAttribute.TypedData; - set => source.AttributeCollection.ShapeVertexAttribute.TypedData = value; + get => Attributes.ShapeVerticesAttribute.TypedData; + set => Attributes.ShapeVerticesAttribute.TypedData = value; } - public System.Int32[] ShapeVertexOffset + public System.Int32[] ShapeVertexOffsets { - get => source.AttributeCollection.ShapeVertexOffsetAttribute.TypedData; - set => source.AttributeCollection.ShapeVertexOffsetAttribute.TypedData = value; + get => Attributes.ShapeVertexOffsetsAttribute.TypedData; + set => Attributes.ShapeVertexOffsetsAttribute.TypedData = value; } - public Vim.Math3d.Vector4[] ShapeColor + public Vim.Math3d.Vector4[] ShapeColors { - get => source.AttributeCollection.ShapeColorAttribute.TypedData; - set => source.AttributeCollection.ShapeColorAttribute.TypedData = value; + get => Attributes.ShapeColorsAttribute.TypedData; + set => Attributes.ShapeColorsAttribute.TypedData = value; } - public System.Single[] ShapeWidth + public System.Single[] ShapeWidths { - get => source.AttributeCollection.ShapeWidthAttribute.TypedData; - set => source.AttributeCollection.ShapeWidthAttribute.TypedData = value; + get => Attributes.ShapeWidthsAttribute.TypedData; + set => Attributes.ShapeWidthsAttribute.TypedData = value; } } public partial class VimAttributeCollection : IAttributeCollection { - public IEnumerable AttributeNames - => Attributes.Keys; + public VimAttributeCollection() + { + // empty + } + + public VimAttributeCollection(BFastNext bfast) + { + this.ReadAttributes(bfast); + } - public long GetSize() - => Attributes.Values.Sum(a => a.Data.LongLength * a.AttributeDescriptor.DataElementSize); + public void ReadAttributes(BFastNext bfast) + { + foreach (var attribute in Map.Values) + { + attribute.ReadBFast(bfast); + } + } - public IDictionary Attributes { get; } + public IDictionary Map { get; } = new Dictionary { - [Vim.G3dNext.Attributes.CornersPerFaceAttribute.AttributeName] = new Vim.G3dNext.Attributes.CornersPerFaceAttribute(), - [Vim.G3dNext.Attributes.VertexAttribute.AttributeName] = new Vim.G3dNext.Attributes.VertexAttribute(), - [Vim.G3dNext.Attributes.IndexAttribute.AttributeName] = new Vim.G3dNext.Attributes.IndexAttribute(), - [Vim.G3dNext.Attributes.InstanceTransformAttribute.AttributeName] = new Vim.G3dNext.Attributes.InstanceTransformAttribute(), - [Vim.G3dNext.Attributes.InstanceParentAttribute.AttributeName] = new Vim.G3dNext.Attributes.InstanceParentAttribute(), + [Vim.G3dNext.Attributes.PositionsAttribute.AttributeName] = new Vim.G3dNext.Attributes.PositionsAttribute(), + [Vim.G3dNext.Attributes.IndicesAttribute.AttributeName] = new Vim.G3dNext.Attributes.IndicesAttribute(), + [Vim.G3dNext.Attributes.InstanceTransformsAttribute.AttributeName] = new Vim.G3dNext.Attributes.InstanceTransformsAttribute(), + [Vim.G3dNext.Attributes.InstanceParentsAttribute.AttributeName] = new Vim.G3dNext.Attributes.InstanceParentsAttribute(), [Vim.G3dNext.Attributes.InstanceFlagsAttribute.AttributeName] = new Vim.G3dNext.Attributes.InstanceFlagsAttribute(), - [Vim.G3dNext.Attributes.InstanceMeshAttribute.AttributeName] = new Vim.G3dNext.Attributes.InstanceMeshAttribute(), - [Vim.G3dNext.Attributes.MeshSubmeshOffsetAttribute.AttributeName] = new Vim.G3dNext.Attributes.MeshSubmeshOffsetAttribute(), - [Vim.G3dNext.Attributes.SubmeshIndexOffsetAttribute.AttributeName] = new Vim.G3dNext.Attributes.SubmeshIndexOffsetAttribute(), - [Vim.G3dNext.Attributes.SubmeshMaterialAttribute.AttributeName] = new Vim.G3dNext.Attributes.SubmeshMaterialAttribute(), - [Vim.G3dNext.Attributes.MaterialColorAttribute.AttributeName] = new Vim.G3dNext.Attributes.MaterialColorAttribute(), + [Vim.G3dNext.Attributes.InstanceMeshesAttribute.AttributeName] = new Vim.G3dNext.Attributes.InstanceMeshesAttribute(), + [Vim.G3dNext.Attributes.MeshSubmeshOffsetsAttribute.AttributeName] = new Vim.G3dNext.Attributes.MeshSubmeshOffsetsAttribute(), + [Vim.G3dNext.Attributes.SubmeshIndexOffsetsAttribute.AttributeName] = new Vim.G3dNext.Attributes.SubmeshIndexOffsetsAttribute(), + [Vim.G3dNext.Attributes.SubmeshMaterialsAttribute.AttributeName] = new Vim.G3dNext.Attributes.SubmeshMaterialsAttribute(), + [Vim.G3dNext.Attributes.MaterialColorsAttribute.AttributeName] = new Vim.G3dNext.Attributes.MaterialColorsAttribute(), [Vim.G3dNext.Attributes.MaterialGlossinessAttribute.AttributeName] = new Vim.G3dNext.Attributes.MaterialGlossinessAttribute(), [Vim.G3dNext.Attributes.MaterialSmoothnessAttribute.AttributeName] = new Vim.G3dNext.Attributes.MaterialSmoothnessAttribute(), - [Vim.G3dNext.Attributes.ShapeVertexAttribute.AttributeName] = new Vim.G3dNext.Attributes.ShapeVertexAttribute(), - [Vim.G3dNext.Attributes.ShapeVertexOffsetAttribute.AttributeName] = new Vim.G3dNext.Attributes.ShapeVertexOffsetAttribute(), - [Vim.G3dNext.Attributes.ShapeColorAttribute.AttributeName] = new Vim.G3dNext.Attributes.ShapeColorAttribute(), - [Vim.G3dNext.Attributes.ShapeWidthAttribute.AttributeName] = new Vim.G3dNext.Attributes.ShapeWidthAttribute(), + [Vim.G3dNext.Attributes.ShapeVerticesAttribute.AttributeName] = new Vim.G3dNext.Attributes.ShapeVerticesAttribute(), + [Vim.G3dNext.Attributes.ShapeVertexOffsetsAttribute.AttributeName] = new Vim.G3dNext.Attributes.ShapeVertexOffsetsAttribute(), + [Vim.G3dNext.Attributes.ShapeColorsAttribute.AttributeName] = new Vim.G3dNext.Attributes.ShapeColorsAttribute(), + [Vim.G3dNext.Attributes.ShapeWidthsAttribute.AttributeName] = new Vim.G3dNext.Attributes.ShapeWidthsAttribute(), }; // Named Attributes. - public Vim.G3dNext.Attributes.CornersPerFaceAttribute CornersPerFaceAttribute + public Vim.G3dNext.Attributes.PositionsAttribute PositionsAttribute { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.CornersPerFaceAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.CornersPerFaceAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.CornersPerFaceAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.PositionsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.PositionsAttribute : default; + set => Map[Vim.G3dNext.Attributes.PositionsAttribute.AttributeName] = value as IAttribute; } - public Vim.G3dNext.Attributes.VertexAttribute VertexAttribute + public Vim.G3dNext.Attributes.IndicesAttribute IndicesAttribute { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.VertexAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.VertexAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.VertexAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.IndicesAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.IndicesAttribute : default; + set => Map[Vim.G3dNext.Attributes.IndicesAttribute.AttributeName] = value as IAttribute; } - public Vim.G3dNext.Attributes.IndexAttribute IndexAttribute + public Vim.G3dNext.Attributes.InstanceTransformsAttribute InstanceTransformsAttribute { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.IndexAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.IndexAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.IndexAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.InstanceTransformsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceTransformsAttribute : default; + set => Map[Vim.G3dNext.Attributes.InstanceTransformsAttribute.AttributeName] = value as IAttribute; } - public Vim.G3dNext.Attributes.InstanceTransformAttribute InstanceTransformAttribute + public Vim.G3dNext.Attributes.InstanceParentsAttribute InstanceParentsAttribute { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.InstanceTransformAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceTransformAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.InstanceTransformAttribute.AttributeName] = value as IAttribute; - } - - public Vim.G3dNext.Attributes.InstanceParentAttribute InstanceParentAttribute - { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.InstanceParentAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceParentAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.InstanceParentAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.InstanceParentsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceParentsAttribute : default; + set => Map[Vim.G3dNext.Attributes.InstanceParentsAttribute.AttributeName] = value as IAttribute; } public Vim.G3dNext.Attributes.InstanceFlagsAttribute InstanceFlagsAttribute { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.InstanceFlagsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceFlagsAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.InstanceFlagsAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.InstanceFlagsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceFlagsAttribute : default; + set => Map[Vim.G3dNext.Attributes.InstanceFlagsAttribute.AttributeName] = value as IAttribute; } - public Vim.G3dNext.Attributes.InstanceMeshAttribute InstanceMeshAttribute + public Vim.G3dNext.Attributes.InstanceMeshesAttribute InstanceMeshesAttribute { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.InstanceMeshAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceMeshAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.InstanceMeshAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.InstanceMeshesAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceMeshesAttribute : default; + set => Map[Vim.G3dNext.Attributes.InstanceMeshesAttribute.AttributeName] = value as IAttribute; } - public Vim.G3dNext.Attributes.MeshSubmeshOffsetAttribute MeshSubmeshOffsetAttribute + public Vim.G3dNext.Attributes.MeshSubmeshOffsetsAttribute MeshSubmeshOffsetsAttribute { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.MeshSubmeshOffsetAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshSubmeshOffsetAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.MeshSubmeshOffsetAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.MeshSubmeshOffsetsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshSubmeshOffsetsAttribute : default; + set => Map[Vim.G3dNext.Attributes.MeshSubmeshOffsetsAttribute.AttributeName] = value as IAttribute; } - public Vim.G3dNext.Attributes.SubmeshIndexOffsetAttribute SubmeshIndexOffsetAttribute + public Vim.G3dNext.Attributes.SubmeshIndexOffsetsAttribute SubmeshIndexOffsetsAttribute { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.SubmeshIndexOffsetAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.SubmeshIndexOffsetAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.SubmeshIndexOffsetAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.SubmeshIndexOffsetsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.SubmeshIndexOffsetsAttribute : default; + set => Map[Vim.G3dNext.Attributes.SubmeshIndexOffsetsAttribute.AttributeName] = value as IAttribute; } - public Vim.G3dNext.Attributes.SubmeshMaterialAttribute SubmeshMaterialAttribute + public Vim.G3dNext.Attributes.SubmeshMaterialsAttribute SubmeshMaterialsAttribute { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.SubmeshMaterialAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.SubmeshMaterialAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.SubmeshMaterialAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.SubmeshMaterialsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.SubmeshMaterialsAttribute : default; + set => Map[Vim.G3dNext.Attributes.SubmeshMaterialsAttribute.AttributeName] = value as IAttribute; } - public Vim.G3dNext.Attributes.MaterialColorAttribute MaterialColorAttribute + public Vim.G3dNext.Attributes.MaterialColorsAttribute MaterialColorsAttribute { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.MaterialColorAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MaterialColorAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.MaterialColorAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.MaterialColorsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MaterialColorsAttribute : default; + set => Map[Vim.G3dNext.Attributes.MaterialColorsAttribute.AttributeName] = value as IAttribute; } public Vim.G3dNext.Attributes.MaterialGlossinessAttribute MaterialGlossinessAttribute { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.MaterialGlossinessAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MaterialGlossinessAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.MaterialGlossinessAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.MaterialGlossinessAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MaterialGlossinessAttribute : default; + set => Map[Vim.G3dNext.Attributes.MaterialGlossinessAttribute.AttributeName] = value as IAttribute; } public Vim.G3dNext.Attributes.MaterialSmoothnessAttribute MaterialSmoothnessAttribute { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.MaterialSmoothnessAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MaterialSmoothnessAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.MaterialSmoothnessAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.MaterialSmoothnessAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MaterialSmoothnessAttribute : default; + set => Map[Vim.G3dNext.Attributes.MaterialSmoothnessAttribute.AttributeName] = value as IAttribute; } - public Vim.G3dNext.Attributes.ShapeVertexAttribute ShapeVertexAttribute + public Vim.G3dNext.Attributes.ShapeVerticesAttribute ShapeVerticesAttribute { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.ShapeVertexAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.ShapeVertexAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.ShapeVertexAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.ShapeVerticesAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.ShapeVerticesAttribute : default; + set => Map[Vim.G3dNext.Attributes.ShapeVerticesAttribute.AttributeName] = value as IAttribute; } - public Vim.G3dNext.Attributes.ShapeVertexOffsetAttribute ShapeVertexOffsetAttribute + public Vim.G3dNext.Attributes.ShapeVertexOffsetsAttribute ShapeVertexOffsetsAttribute { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.ShapeVertexOffsetAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.ShapeVertexOffsetAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.ShapeVertexOffsetAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.ShapeVertexOffsetsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.ShapeVertexOffsetsAttribute : default; + set => Map[Vim.G3dNext.Attributes.ShapeVertexOffsetsAttribute.AttributeName] = value as IAttribute; } - public Vim.G3dNext.Attributes.ShapeColorAttribute ShapeColorAttribute + public Vim.G3dNext.Attributes.ShapeColorsAttribute ShapeColorsAttribute { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.ShapeColorAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.ShapeColorAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.ShapeColorAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.ShapeColorsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.ShapeColorsAttribute : default; + set => Map[Vim.G3dNext.Attributes.ShapeColorsAttribute.AttributeName] = value as IAttribute; } - public Vim.G3dNext.Attributes.ShapeWidthAttribute ShapeWidthAttribute + public Vim.G3dNext.Attributes.ShapeWidthsAttribute ShapeWidthsAttribute { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.ShapeWidthAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.ShapeWidthAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.ShapeWidthAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.ShapeWidthsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.ShapeWidthsAttribute : default; + set => Map[Vim.G3dNext.Attributes.ShapeWidthsAttribute.AttributeName] = value as IAttribute; } /// public IAttribute GetAttribute(Type attributeType) { - if (attributeType == typeof(Vim.G3dNext.Attributes.CornersPerFaceAttribute)) - return CornersPerFaceAttribute; + if (attributeType == typeof(Vim.G3dNext.Attributes.PositionsAttribute)) + return PositionsAttribute; - if (attributeType == typeof(Vim.G3dNext.Attributes.VertexAttribute)) - return VertexAttribute; + if (attributeType == typeof(Vim.G3dNext.Attributes.IndicesAttribute)) + return IndicesAttribute; - if (attributeType == typeof(Vim.G3dNext.Attributes.IndexAttribute)) - return IndexAttribute; + if (attributeType == typeof(Vim.G3dNext.Attributes.InstanceTransformsAttribute)) + return InstanceTransformsAttribute; - if (attributeType == typeof(Vim.G3dNext.Attributes.InstanceTransformAttribute)) - return InstanceTransformAttribute; - - if (attributeType == typeof(Vim.G3dNext.Attributes.InstanceParentAttribute)) - return InstanceParentAttribute; + if (attributeType == typeof(Vim.G3dNext.Attributes.InstanceParentsAttribute)) + return InstanceParentsAttribute; if (attributeType == typeof(Vim.G3dNext.Attributes.InstanceFlagsAttribute)) return InstanceFlagsAttribute; - if (attributeType == typeof(Vim.G3dNext.Attributes.InstanceMeshAttribute)) - return InstanceMeshAttribute; + if (attributeType == typeof(Vim.G3dNext.Attributes.InstanceMeshesAttribute)) + return InstanceMeshesAttribute; - if (attributeType == typeof(Vim.G3dNext.Attributes.MeshSubmeshOffsetAttribute)) - return MeshSubmeshOffsetAttribute; + if (attributeType == typeof(Vim.G3dNext.Attributes.MeshSubmeshOffsetsAttribute)) + return MeshSubmeshOffsetsAttribute; - if (attributeType == typeof(Vim.G3dNext.Attributes.SubmeshIndexOffsetAttribute)) - return SubmeshIndexOffsetAttribute; + if (attributeType == typeof(Vim.G3dNext.Attributes.SubmeshIndexOffsetsAttribute)) + return SubmeshIndexOffsetsAttribute; - if (attributeType == typeof(Vim.G3dNext.Attributes.SubmeshMaterialAttribute)) - return SubmeshMaterialAttribute; + if (attributeType == typeof(Vim.G3dNext.Attributes.SubmeshMaterialsAttribute)) + return SubmeshMaterialsAttribute; - if (attributeType == typeof(Vim.G3dNext.Attributes.MaterialColorAttribute)) - return MaterialColorAttribute; + if (attributeType == typeof(Vim.G3dNext.Attributes.MaterialColorsAttribute)) + return MaterialColorsAttribute; if (attributeType == typeof(Vim.G3dNext.Attributes.MaterialGlossinessAttribute)) return MaterialGlossinessAttribute; @@ -1930,17 +1889,17 @@ public IAttribute GetAttribute(Type attributeType) if (attributeType == typeof(Vim.G3dNext.Attributes.MaterialSmoothnessAttribute)) return MaterialSmoothnessAttribute; - if (attributeType == typeof(Vim.G3dNext.Attributes.ShapeVertexAttribute)) - return ShapeVertexAttribute; + if (attributeType == typeof(Vim.G3dNext.Attributes.ShapeVerticesAttribute)) + return ShapeVerticesAttribute; - if (attributeType == typeof(Vim.G3dNext.Attributes.ShapeVertexOffsetAttribute)) - return ShapeVertexOffsetAttribute; + if (attributeType == typeof(Vim.G3dNext.Attributes.ShapeVertexOffsetsAttribute)) + return ShapeVertexOffsetsAttribute; - if (attributeType == typeof(Vim.G3dNext.Attributes.ShapeColorAttribute)) - return ShapeColorAttribute; + if (attributeType == typeof(Vim.G3dNext.Attributes.ShapeColorsAttribute)) + return ShapeColorsAttribute; - if (attributeType == typeof(Vim.G3dNext.Attributes.ShapeWidthAttribute)) - return ShapeWidthAttribute; + if (attributeType == typeof(Vim.G3dNext.Attributes.ShapeWidthsAttribute)) + return ShapeWidthsAttribute; throw new ArgumentException("Type {attributeType.ToString()} is not supported."); } @@ -1951,34 +1910,28 @@ public IAttribute MergeAttribute(string attributeName, IReadOnlyList().ToArray().MergeDataAttributes(); + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); } - case Vim.G3dNext.Attributes.IndexAttribute.AttributeName: + case Vim.G3dNext.Attributes.IndicesAttribute.AttributeName: { // Index Attribute - return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); + return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); } - case Vim.G3dNext.Attributes.InstanceTransformAttribute.AttributeName: + case Vim.G3dNext.Attributes.InstanceTransformsAttribute.AttributeName: { // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); } - case Vim.G3dNext.Attributes.InstanceParentAttribute.AttributeName: + case Vim.G3dNext.Attributes.InstanceParentsAttribute.AttributeName: { // Index Attribute - return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); + return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); } case Vim.G3dNext.Attributes.InstanceFlagsAttribute.AttributeName: @@ -1987,34 +1940,34 @@ public IAttribute MergeAttribute(string attributeName, IReadOnlyList().ToArray().MergeDataAttributes(); } - case Vim.G3dNext.Attributes.InstanceMeshAttribute.AttributeName: + case Vim.G3dNext.Attributes.InstanceMeshesAttribute.AttributeName: { // Index Attribute - return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); + return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); } - case Vim.G3dNext.Attributes.MeshSubmeshOffsetAttribute.AttributeName: + case Vim.G3dNext.Attributes.MeshSubmeshOffsetsAttribute.AttributeName: { // Index Attribute - return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); + return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); } - case Vim.G3dNext.Attributes.SubmeshIndexOffsetAttribute.AttributeName: + case Vim.G3dNext.Attributes.SubmeshIndexOffsetsAttribute.AttributeName: { // Index Attribute - return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); + return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); } - case Vim.G3dNext.Attributes.SubmeshMaterialAttribute.AttributeName: + case Vim.G3dNext.Attributes.SubmeshMaterialsAttribute.AttributeName: { // Index Attribute - return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); + return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); } - case Vim.G3dNext.Attributes.MaterialColorAttribute.AttributeName: + case Vim.G3dNext.Attributes.MaterialColorsAttribute.AttributeName: { // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); } case Vim.G3dNext.Attributes.MaterialGlossinessAttribute.AttributeName: @@ -2029,28 +1982,28 @@ public IAttribute MergeAttribute(string attributeName, IReadOnlyList().ToArray().MergeDataAttributes(); } - case Vim.G3dNext.Attributes.ShapeVertexAttribute.AttributeName: + case Vim.G3dNext.Attributes.ShapeVerticesAttribute.AttributeName: { // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); } - case Vim.G3dNext.Attributes.ShapeVertexOffsetAttribute.AttributeName: + case Vim.G3dNext.Attributes.ShapeVertexOffsetsAttribute.AttributeName: { // Index Attribute - return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); + return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); } - case Vim.G3dNext.Attributes.ShapeColorAttribute.AttributeName: + case Vim.G3dNext.Attributes.ShapeColorsAttribute.AttributeName: { // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); } - case Vim.G3dNext.Attributes.ShapeWidthAttribute.AttributeName: + case Vim.G3dNext.Attributes.ShapeWidthsAttribute.AttributeName: { // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); } default: @@ -2063,187 +2016,206 @@ public void Validate() // Ensure all the indices are either -1 or within the bounds of the attributes they are indexing into. { - var maxIndex = GetAttribute(IndexAttribute.IndexInto).Data.Length - 1; - for (var i = 0; i < IndexAttribute.TypedData.Length; ++i) + var maxIndex = GetAttribute(IndicesAttribute.IndexInto).Data.Length - 1; + for (var i = 0; i < IndicesAttribute.TypedData.Length; ++i) { - var index = IndexAttribute.TypedData[i]; + var index = IndicesAttribute.TypedData[i]; if (index == -1) continue; // no relation. if (index < -1 || index > maxIndex) - throw new Exception($"Index out of range in Vim.G3dNext.Attributes.IndexAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); + throw new Exception($"Index out of range in Vim.G3dNext.Attributes.IndicesAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); } } { - var maxIndex = GetAttribute(InstanceParentAttribute.IndexInto).Data.Length - 1; - for (var i = 0; i < InstanceParentAttribute.TypedData.Length; ++i) + var maxIndex = GetAttribute(InstanceParentsAttribute.IndexInto).Data.Length - 1; + for (var i = 0; i < InstanceParentsAttribute.TypedData.Length; ++i) { - var index = InstanceParentAttribute.TypedData[i]; + var index = InstanceParentsAttribute.TypedData[i]; if (index == -1) continue; // no relation. if (index < -1 || index > maxIndex) - throw new Exception($"Index out of range in Vim.G3dNext.Attributes.InstanceParentAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); + throw new Exception($"Index out of range in Vim.G3dNext.Attributes.InstanceParentsAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); } } { - var maxIndex = GetAttribute(InstanceMeshAttribute.IndexInto).Data.Length - 1; - for (var i = 0; i < InstanceMeshAttribute.TypedData.Length; ++i) + var maxIndex = GetAttribute(InstanceMeshesAttribute.IndexInto).Data.Length - 1; + for (var i = 0; i < InstanceMeshesAttribute.TypedData.Length; ++i) { - var index = InstanceMeshAttribute.TypedData[i]; + var index = InstanceMeshesAttribute.TypedData[i]; if (index == -1) continue; // no relation. if (index < -1 || index > maxIndex) - throw new Exception($"Index out of range in Vim.G3dNext.Attributes.InstanceMeshAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); + throw new Exception($"Index out of range in Vim.G3dNext.Attributes.InstanceMeshesAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); } } { - var maxIndex = GetAttribute(MeshSubmeshOffsetAttribute.IndexInto).Data.Length - 1; - for (var i = 0; i < MeshSubmeshOffsetAttribute.TypedData.Length; ++i) + var maxIndex = GetAttribute(MeshSubmeshOffsetsAttribute.IndexInto).Data.Length - 1; + for (var i = 0; i < MeshSubmeshOffsetsAttribute.TypedData.Length; ++i) { - var index = MeshSubmeshOffsetAttribute.TypedData[i]; + var index = MeshSubmeshOffsetsAttribute.TypedData[i]; if (index == -1) continue; // no relation. if (index < -1 || index > maxIndex) - throw new Exception($"Index out of range in Vim.G3dNext.Attributes.MeshSubmeshOffsetAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); + throw new Exception($"Index out of range in Vim.G3dNext.Attributes.MeshSubmeshOffsetsAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); } } { - var maxIndex = GetAttribute(SubmeshIndexOffsetAttribute.IndexInto).Data.Length - 1; - for (var i = 0; i < SubmeshIndexOffsetAttribute.TypedData.Length; ++i) + var maxIndex = GetAttribute(SubmeshIndexOffsetsAttribute.IndexInto).Data.Length - 1; + for (var i = 0; i < SubmeshIndexOffsetsAttribute.TypedData.Length; ++i) { - var index = SubmeshIndexOffsetAttribute.TypedData[i]; + var index = SubmeshIndexOffsetsAttribute.TypedData[i]; if (index == -1) continue; // no relation. if (index < -1 || index > maxIndex) - throw new Exception($"Index out of range in Vim.G3dNext.Attributes.SubmeshIndexOffsetAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); + throw new Exception($"Index out of range in Vim.G3dNext.Attributes.SubmeshIndexOffsetsAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); } } { - var maxIndex = GetAttribute(SubmeshMaterialAttribute.IndexInto).Data.Length - 1; - for (var i = 0; i < SubmeshMaterialAttribute.TypedData.Length; ++i) + var maxIndex = GetAttribute(SubmeshMaterialsAttribute.IndexInto).Data.Length - 1; + for (var i = 0; i < SubmeshMaterialsAttribute.TypedData.Length; ++i) { - var index = SubmeshMaterialAttribute.TypedData[i]; + var index = SubmeshMaterialsAttribute.TypedData[i]; if (index == -1) continue; // no relation. if (index < -1 || index > maxIndex) - throw new Exception($"Index out of range in Vim.G3dNext.Attributes.SubmeshMaterialAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); + throw new Exception($"Index out of range in Vim.G3dNext.Attributes.SubmeshMaterialsAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); } } { - var maxIndex = GetAttribute(ShapeVertexOffsetAttribute.IndexInto).Data.Length - 1; - for (var i = 0; i < ShapeVertexOffsetAttribute.TypedData.Length; ++i) + var maxIndex = GetAttribute(ShapeVertexOffsetsAttribute.IndexInto).Data.Length - 1; + for (var i = 0; i < ShapeVertexOffsetsAttribute.TypedData.Length; ++i) { - var index = ShapeVertexOffsetAttribute.TypedData[i]; + var index = ShapeVertexOffsetsAttribute.TypedData[i]; if (index == -1) continue; // no relation. if (index < -1 || index > maxIndex) - throw new Exception($"Index out of range in Vim.G3dNext.Attributes.ShapeVertexOffsetAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); + throw new Exception($"Index out of range in Vim.G3dNext.Attributes.ShapeVertexOffsetsAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); } } } } - public class G3dMaterial2 + // Please provide an explicit implementation in another partial class file. + public partial class G3dMaterials : ISetup { - public G3DNext source; + public MaterialsAttributeCollection Attributes; - public G3dMaterial2() + public G3dMaterials() : this(new MaterialsAttributeCollection()) { - this.source = new G3DNext (); + // empty } - public G3dMaterial2(G3DNext source) + public G3dMaterials(BFastNext bfast) : this(new MaterialsAttributeCollection(bfast)) { - this.source = source; + // empty } - public G3dMaterial2(BFastNext.BFastNext bfast) + public G3dMaterials(MaterialsAttributeCollection attributes) { - this.source = new G3DNext(bfast); + Attributes = attributes; + + // Method to implement in another partial class + (this as ISetup).Setup(); } + public BFastNext ToBFast() + => Attributes.ToBFast(); + - public Vim.Math3d.Vector4[] MaterialColor + public Vim.Math3d.Vector4[] MaterialColors { - get => source.AttributeCollection.MaterialColorAttribute.TypedData; - set => source.AttributeCollection.MaterialColorAttribute.TypedData = value; + get => Attributes.MaterialColorsAttribute.TypedData; + set => Attributes.MaterialColorsAttribute.TypedData = value; } public System.Single[] MaterialGlossiness { - get => source.AttributeCollection.MaterialGlossinessAttribute.TypedData; - set => source.AttributeCollection.MaterialGlossinessAttribute.TypedData = value; + get => Attributes.MaterialGlossinessAttribute.TypedData; + set => Attributes.MaterialGlossinessAttribute.TypedData = value; } public System.Single[] MaterialSmoothness { - get => source.AttributeCollection.MaterialSmoothnessAttribute.TypedData; - set => source.AttributeCollection.MaterialSmoothnessAttribute.TypedData = value; + get => Attributes.MaterialSmoothnessAttribute.TypedData; + set => Attributes.MaterialSmoothnessAttribute.TypedData = value; } } - public partial class MaterialAttributeCollection : IAttributeCollection + public partial class MaterialsAttributeCollection : IAttributeCollection { - public IEnumerable AttributeNames - => Attributes.Keys; + public MaterialsAttributeCollection() + { + // empty + } - public long GetSize() - => Attributes.Values.Sum(a => a.Data.LongLength * a.AttributeDescriptor.DataElementSize); + public MaterialsAttributeCollection(BFastNext bfast) + { + this.ReadAttributes(bfast); + } + + public void ReadAttributes(BFastNext bfast) + { + foreach (var attribute in Map.Values) + { + attribute.ReadBFast(bfast); + } + } - public IDictionary Attributes { get; } + public IDictionary Map { get; } = new Dictionary { - [Vim.G3dNext.Attributes.MaterialColorAttribute.AttributeName] = new Vim.G3dNext.Attributes.MaterialColorAttribute(), + [Vim.G3dNext.Attributes.MaterialColorsAttribute.AttributeName] = new Vim.G3dNext.Attributes.MaterialColorsAttribute(), [Vim.G3dNext.Attributes.MaterialGlossinessAttribute.AttributeName] = new Vim.G3dNext.Attributes.MaterialGlossinessAttribute(), [Vim.G3dNext.Attributes.MaterialSmoothnessAttribute.AttributeName] = new Vim.G3dNext.Attributes.MaterialSmoothnessAttribute(), }; // Named Attributes. - public Vim.G3dNext.Attributes.MaterialColorAttribute MaterialColorAttribute + public Vim.G3dNext.Attributes.MaterialColorsAttribute MaterialColorsAttribute { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.MaterialColorAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MaterialColorAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.MaterialColorAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.MaterialColorsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MaterialColorsAttribute : default; + set => Map[Vim.G3dNext.Attributes.MaterialColorsAttribute.AttributeName] = value as IAttribute; } public Vim.G3dNext.Attributes.MaterialGlossinessAttribute MaterialGlossinessAttribute { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.MaterialGlossinessAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MaterialGlossinessAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.MaterialGlossinessAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.MaterialGlossinessAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MaterialGlossinessAttribute : default; + set => Map[Vim.G3dNext.Attributes.MaterialGlossinessAttribute.AttributeName] = value as IAttribute; } public Vim.G3dNext.Attributes.MaterialSmoothnessAttribute MaterialSmoothnessAttribute { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.MaterialSmoothnessAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MaterialSmoothnessAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.MaterialSmoothnessAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.MaterialSmoothnessAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MaterialSmoothnessAttribute : default; + set => Map[Vim.G3dNext.Attributes.MaterialSmoothnessAttribute.AttributeName] = value as IAttribute; } /// public IAttribute GetAttribute(Type attributeType) { - if (attributeType == typeof(Vim.G3dNext.Attributes.MaterialColorAttribute)) - return MaterialColorAttribute; + if (attributeType == typeof(Vim.G3dNext.Attributes.MaterialColorsAttribute)) + return MaterialColorsAttribute; if (attributeType == typeof(Vim.G3dNext.Attributes.MaterialGlossinessAttribute)) return MaterialGlossinessAttribute; @@ -2260,10 +2232,10 @@ public IAttribute MergeAttribute(string attributeName, IReadOnlyList().ToArray().MergeDataAttributes(); + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); } case Vim.G3dNext.Attributes.MaterialGlossinessAttribute.AttributeName: @@ -2290,115 +2262,134 @@ public void Validate() } } - public class G3dScene2 + // Please provide an explicit implementation in another partial class file. + public partial class G3dScene : ISetup { - public G3DNext source; + public SceneAttributeCollection Attributes; - public G3dScene2() + public G3dScene() : this(new SceneAttributeCollection()) { - this.source = new G3DNext (); + // empty } - public G3dScene2(G3DNext source) + public G3dScene(BFastNext bfast) : this(new SceneAttributeCollection(bfast)) { - this.source = source; + // empty } - public G3dScene2(BFastNext.BFastNext bfast) + public G3dScene(SceneAttributeCollection attributes) { - this.source = new G3DNext(bfast); + Attributes = attributes; + + // Method to implement in another partial class + (this as ISetup).Setup(); } + public BFastNext ToBFast() + => Attributes.ToBFast(); + public System.Int32[] InstanceFiles { - get => source.AttributeCollection.InstanceFilesAttribute.TypedData; - set => source.AttributeCollection.InstanceFilesAttribute.TypedData = value; + get => Attributes.InstanceFilesAttribute.TypedData; + set => Attributes.InstanceFilesAttribute.TypedData = value; } public System.Int32[] InstanceIndices { - get => source.AttributeCollection.InstanceIndicesAttribute.TypedData; - set => source.AttributeCollection.InstanceIndicesAttribute.TypedData = value; + get => Attributes.InstanceIndicesAttribute.TypedData; + set => Attributes.InstanceIndicesAttribute.TypedData = value; } public System.Int32[] InstanceNodes { - get => source.AttributeCollection.InstanceNodesAttribute.TypedData; - set => source.AttributeCollection.InstanceNodesAttribute.TypedData = value; + get => Attributes.InstanceNodesAttribute.TypedData; + set => Attributes.InstanceNodesAttribute.TypedData = value; } public System.Int32[] InstanceGroups { - get => source.AttributeCollection.InstanceGroupsAttribute.TypedData; - set => source.AttributeCollection.InstanceGroupsAttribute.TypedData = value; + get => Attributes.InstanceGroupsAttribute.TypedData; + set => Attributes.InstanceGroupsAttribute.TypedData = value; } public System.Int64[] InstanceTags { - get => source.AttributeCollection.InstanceTagsAttribute.TypedData; - set => source.AttributeCollection.InstanceTagsAttribute.TypedData = value; + get => Attributes.InstanceTagsAttribute.TypedData; + set => Attributes.InstanceTagsAttribute.TypedData = value; } public System.UInt16[] InstanceFlags { - get => source.AttributeCollection.InstanceFlagsAttribute.TypedData; - set => source.AttributeCollection.InstanceFlagsAttribute.TypedData = value; + get => Attributes.InstanceFlagsAttribute.TypedData; + set => Attributes.InstanceFlagsAttribute.TypedData = value; } public Vim.Math3d.Vector3[] InstanceMins { - get => source.AttributeCollection.InstanceMinsAttribute.TypedData; - set => source.AttributeCollection.InstanceMinsAttribute.TypedData = value; + get => Attributes.InstanceMinsAttribute.TypedData; + set => Attributes.InstanceMinsAttribute.TypedData = value; } public Vim.Math3d.Vector3[] InstanceMaxs { - get => source.AttributeCollection.InstanceMaxsAttribute.TypedData; - set => source.AttributeCollection.InstanceMaxsAttribute.TypedData = value; + get => Attributes.InstanceMaxsAttribute.TypedData; + set => Attributes.InstanceMaxsAttribute.TypedData = value; } public System.Int32[] MeshInstanceCounts { - get => source.AttributeCollection.MeshInstanceCountsAttribute.TypedData; - set => source.AttributeCollection.MeshInstanceCountsAttribute.TypedData = value; + get => Attributes.MeshInstanceCountsAttribute.TypedData; + set => Attributes.MeshInstanceCountsAttribute.TypedData = value; } public System.Int32[] MeshIndexCounts { - get => source.AttributeCollection.MeshIndexCountsAttribute.TypedData; - set => source.AttributeCollection.MeshIndexCountsAttribute.TypedData = value; + get => Attributes.MeshIndexCountsAttribute.TypedData; + set => Attributes.MeshIndexCountsAttribute.TypedData = value; } public System.Int32[] MeshVertexCounts { - get => source.AttributeCollection.MeshVertexCountsAttribute.TypedData; - set => source.AttributeCollection.MeshVertexCountsAttribute.TypedData = value; + get => Attributes.MeshVertexCountsAttribute.TypedData; + set => Attributes.MeshVertexCountsAttribute.TypedData = value; } public System.Int32[] MeshOpaqueIndexCounts { - get => source.AttributeCollection.MeshOpaqueIndexCountsAttribute.TypedData; - set => source.AttributeCollection.MeshOpaqueIndexCountsAttribute.TypedData = value; + get => Attributes.MeshOpaqueIndexCountsAttribute.TypedData; + set => Attributes.MeshOpaqueIndexCountsAttribute.TypedData = value; } public System.Int32[] MeshOpaqueVertexCounts { - get => source.AttributeCollection.MeshOpaqueVertexCountsAttribute.TypedData; - set => source.AttributeCollection.MeshOpaqueVertexCountsAttribute.TypedData = value; + get => Attributes.MeshOpaqueVertexCountsAttribute.TypedData; + set => Attributes.MeshOpaqueVertexCountsAttribute.TypedData = value; } } public partial class SceneAttributeCollection : IAttributeCollection { - public IEnumerable AttributeNames - => Attributes.Keys; + public SceneAttributeCollection() + { + // empty + } + + public SceneAttributeCollection(BFastNext bfast) + { + this.ReadAttributes(bfast); + } - public long GetSize() - => Attributes.Values.Sum(a => a.Data.LongLength * a.AttributeDescriptor.DataElementSize); + public void ReadAttributes(BFastNext bfast) + { + foreach (var attribute in Map.Values) + { + attribute.ReadBFast(bfast); + } + } - public IDictionary Attributes { get; } + public IDictionary Map { get; } = new Dictionary { [Vim.G3dNext.Attributes.InstanceFilesAttribute.AttributeName] = new Vim.G3dNext.Attributes.InstanceFilesAttribute(), @@ -2420,80 +2411,80 @@ public long GetSize() public Vim.G3dNext.Attributes.InstanceFilesAttribute InstanceFilesAttribute { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.InstanceFilesAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceFilesAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.InstanceFilesAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.InstanceFilesAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceFilesAttribute : default; + set => Map[Vim.G3dNext.Attributes.InstanceFilesAttribute.AttributeName] = value as IAttribute; } public Vim.G3dNext.Attributes.InstanceIndicesAttribute InstanceIndicesAttribute { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.InstanceIndicesAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceIndicesAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.InstanceIndicesAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.InstanceIndicesAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceIndicesAttribute : default; + set => Map[Vim.G3dNext.Attributes.InstanceIndicesAttribute.AttributeName] = value as IAttribute; } public Vim.G3dNext.Attributes.InstanceNodesAttribute InstanceNodesAttribute { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.InstanceNodesAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceNodesAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.InstanceNodesAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.InstanceNodesAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceNodesAttribute : default; + set => Map[Vim.G3dNext.Attributes.InstanceNodesAttribute.AttributeName] = value as IAttribute; } public Vim.G3dNext.Attributes.InstanceGroupsAttribute InstanceGroupsAttribute { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.InstanceGroupsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceGroupsAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.InstanceGroupsAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.InstanceGroupsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceGroupsAttribute : default; + set => Map[Vim.G3dNext.Attributes.InstanceGroupsAttribute.AttributeName] = value as IAttribute; } public Vim.G3dNext.Attributes.InstanceTagsAttribute InstanceTagsAttribute { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.InstanceTagsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceTagsAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.InstanceTagsAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.InstanceTagsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceTagsAttribute : default; + set => Map[Vim.G3dNext.Attributes.InstanceTagsAttribute.AttributeName] = value as IAttribute; } public Vim.G3dNext.Attributes.InstanceFlagsAttribute InstanceFlagsAttribute { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.InstanceFlagsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceFlagsAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.InstanceFlagsAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.InstanceFlagsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceFlagsAttribute : default; + set => Map[Vim.G3dNext.Attributes.InstanceFlagsAttribute.AttributeName] = value as IAttribute; } public Vim.G3dNext.Attributes.InstanceMinsAttribute InstanceMinsAttribute { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.InstanceMinsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceMinsAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.InstanceMinsAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.InstanceMinsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceMinsAttribute : default; + set => Map[Vim.G3dNext.Attributes.InstanceMinsAttribute.AttributeName] = value as IAttribute; } public Vim.G3dNext.Attributes.InstanceMaxsAttribute InstanceMaxsAttribute { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.InstanceMaxsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceMaxsAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.InstanceMaxsAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.InstanceMaxsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceMaxsAttribute : default; + set => Map[Vim.G3dNext.Attributes.InstanceMaxsAttribute.AttributeName] = value as IAttribute; } public Vim.G3dNext.Attributes.MeshInstanceCountsAttribute MeshInstanceCountsAttribute { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.MeshInstanceCountsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshInstanceCountsAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.MeshInstanceCountsAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.MeshInstanceCountsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshInstanceCountsAttribute : default; + set => Map[Vim.G3dNext.Attributes.MeshInstanceCountsAttribute.AttributeName] = value as IAttribute; } public Vim.G3dNext.Attributes.MeshIndexCountsAttribute MeshIndexCountsAttribute { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.MeshIndexCountsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshIndexCountsAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.MeshIndexCountsAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.MeshIndexCountsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshIndexCountsAttribute : default; + set => Map[Vim.G3dNext.Attributes.MeshIndexCountsAttribute.AttributeName] = value as IAttribute; } public Vim.G3dNext.Attributes.MeshVertexCountsAttribute MeshVertexCountsAttribute { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.MeshVertexCountsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshVertexCountsAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.MeshVertexCountsAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.MeshVertexCountsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshVertexCountsAttribute : default; + set => Map[Vim.G3dNext.Attributes.MeshVertexCountsAttribute.AttributeName] = value as IAttribute; } public Vim.G3dNext.Attributes.MeshOpaqueIndexCountsAttribute MeshOpaqueIndexCountsAttribute { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.MeshOpaqueIndexCountsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshOpaqueIndexCountsAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.MeshOpaqueIndexCountsAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.MeshOpaqueIndexCountsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshOpaqueIndexCountsAttribute : default; + set => Map[Vim.G3dNext.Attributes.MeshOpaqueIndexCountsAttribute.AttributeName] = value as IAttribute; } public Vim.G3dNext.Attributes.MeshOpaqueVertexCountsAttribute MeshOpaqueVertexCountsAttribute { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.MeshOpaqueVertexCountsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshOpaqueVertexCountsAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.MeshOpaqueVertexCountsAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.MeshOpaqueVertexCountsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshOpaqueVertexCountsAttribute : default; + set => Map[Vim.G3dNext.Attributes.MeshOpaqueVertexCountsAttribute.AttributeName] = value as IAttribute; } /// @@ -2638,158 +2629,177 @@ public void Validate() } } - public class G3dMesh2 + // Please provide an explicit implementation in another partial class file. + public partial class G3dMesh : ISetup { - public G3DNext source; + public MeshAttributeCollection Attributes; - public G3dMesh2() + public G3dMesh() : this(new MeshAttributeCollection()) { - this.source = new G3DNext (); + // empty } - public G3dMesh2(G3DNext source) + public G3dMesh(BFastNext bfast) : this(new MeshAttributeCollection(bfast)) { - this.source = source; + // empty } - public G3dMesh2(BFastNext.BFastNext bfast) + public G3dMesh(MeshAttributeCollection attributes) { - this.source = new G3DNext(bfast); + Attributes = attributes; + + // Method to implement in another partial class + (this as ISetup).Setup(); } + public BFastNext ToBFast() + => Attributes.ToBFast(); + - public Vim.Math3d.Matrix4x4[] MeshInstanceTransform + public Vim.Math3d.Matrix4x4[] InstanceTransforms { - get => source.AttributeCollection.MeshInstanceTransformAttribute.TypedData; - set => source.AttributeCollection.MeshInstanceTransformAttribute.TypedData = value; + get => Attributes.MeshInstanceTransformsAttribute.TypedData; + set => Attributes.MeshInstanceTransformsAttribute.TypedData = value; } - public System.Int32[] MeshOpaqueSubmeshCount + public System.Int32[] OpaqueSubmeshCounts { - get => source.AttributeCollection.MeshOpaqueSubmeshCountAttribute.TypedData; - set => source.AttributeCollection.MeshOpaqueSubmeshCountAttribute.TypedData = value; + get => Attributes.MeshOpaqueSubmeshCountsAttribute.TypedData; + set => Attributes.MeshOpaqueSubmeshCountsAttribute.TypedData = value; } - public System.Int32[] MeshSubmeshIndexOffset + public System.Int32[] SubmeshIndexOffsets { - get => source.AttributeCollection.MeshSubmeshIndexOffsetAttribute.TypedData; - set => source.AttributeCollection.MeshSubmeshIndexOffsetAttribute.TypedData = value; + get => Attributes.MeshSubmeshIndexOffsetsAttribute.TypedData; + set => Attributes.MeshSubmeshIndexOffsetsAttribute.TypedData = value; } - public System.Int32[] MeshSubmeshVertexOffset + public System.Int32[] SubmeshVertexOffsets { - get => source.AttributeCollection.MeshSubmeshVertexOffsetAttribute.TypedData; - set => source.AttributeCollection.MeshSubmeshVertexOffsetAttribute.TypedData = value; + get => Attributes.MeshSubmeshVertexOffsetsAttribute.TypedData; + set => Attributes.MeshSubmeshVertexOffsetsAttribute.TypedData = value; } - public System.Int32[] MeshSubmeshMaterial + public System.Int32[] SubmeshMaterials { - get => source.AttributeCollection.MeshSubmeshMaterialAttribute.TypedData; - set => source.AttributeCollection.MeshSubmeshMaterialAttribute.TypedData = value; + get => Attributes.MeshSubmeshMaterialsAttribute.TypedData; + set => Attributes.MeshSubmeshMaterialsAttribute.TypedData = value; } - public Vim.Math3d.Vector3[] MeshVertex + public Vim.Math3d.Vector3[] Positions { - get => source.AttributeCollection.MeshVertexAttribute.TypedData; - set => source.AttributeCollection.MeshVertexAttribute.TypedData = value; + get => Attributes.MeshPositionsAttribute.TypedData; + set => Attributes.MeshPositionsAttribute.TypedData = value; } - public System.Int32[] MeshIndex + public System.Int32[] Indices { - get => source.AttributeCollection.MeshIndexAttribute.TypedData; - set => source.AttributeCollection.MeshIndexAttribute.TypedData = value; + get => Attributes.MeshIndicesAttribute.TypedData; + set => Attributes.MeshIndicesAttribute.TypedData = value; } } public partial class MeshAttributeCollection : IAttributeCollection { - public IEnumerable AttributeNames - => Attributes.Keys; + public MeshAttributeCollection() + { + // empty + } - public long GetSize() - => Attributes.Values.Sum(a => a.Data.LongLength * a.AttributeDescriptor.DataElementSize); + public MeshAttributeCollection(BFastNext bfast) + { + this.ReadAttributes(bfast); + } + + public void ReadAttributes(BFastNext bfast) + { + foreach (var attribute in Map.Values) + { + attribute.ReadBFast(bfast); + } + } - public IDictionary Attributes { get; } + public IDictionary Map { get; } = new Dictionary { - [Vim.G3dNext.Attributes.MeshInstanceTransformAttribute.AttributeName] = new Vim.G3dNext.Attributes.MeshInstanceTransformAttribute(), - [Vim.G3dNext.Attributes.MeshOpaqueSubmeshCountAttribute.AttributeName] = new Vim.G3dNext.Attributes.MeshOpaqueSubmeshCountAttribute(), - [Vim.G3dNext.Attributes.MeshSubmeshIndexOffsetAttribute.AttributeName] = new Vim.G3dNext.Attributes.MeshSubmeshIndexOffsetAttribute(), - [Vim.G3dNext.Attributes.MeshSubmeshVertexOffsetAttribute.AttributeName] = new Vim.G3dNext.Attributes.MeshSubmeshVertexOffsetAttribute(), - [Vim.G3dNext.Attributes.MeshSubmeshMaterialAttribute.AttributeName] = new Vim.G3dNext.Attributes.MeshSubmeshMaterialAttribute(), - [Vim.G3dNext.Attributes.MeshVertexAttribute.AttributeName] = new Vim.G3dNext.Attributes.MeshVertexAttribute(), - [Vim.G3dNext.Attributes.MeshIndexAttribute.AttributeName] = new Vim.G3dNext.Attributes.MeshIndexAttribute(), + [Vim.G3dNext.Attributes.MeshInstanceTransformsAttribute.AttributeName] = new Vim.G3dNext.Attributes.MeshInstanceTransformsAttribute(), + [Vim.G3dNext.Attributes.MeshOpaqueSubmeshCountsAttribute.AttributeName] = new Vim.G3dNext.Attributes.MeshOpaqueSubmeshCountsAttribute(), + [Vim.G3dNext.Attributes.MeshSubmeshIndexOffsetsAttribute.AttributeName] = new Vim.G3dNext.Attributes.MeshSubmeshIndexOffsetsAttribute(), + [Vim.G3dNext.Attributes.MeshSubmeshVertexOffsetsAttribute.AttributeName] = new Vim.G3dNext.Attributes.MeshSubmeshVertexOffsetsAttribute(), + [Vim.G3dNext.Attributes.MeshSubmeshMaterialsAttribute.AttributeName] = new Vim.G3dNext.Attributes.MeshSubmeshMaterialsAttribute(), + [Vim.G3dNext.Attributes.MeshPositionsAttribute.AttributeName] = new Vim.G3dNext.Attributes.MeshPositionsAttribute(), + [Vim.G3dNext.Attributes.MeshIndicesAttribute.AttributeName] = new Vim.G3dNext.Attributes.MeshIndicesAttribute(), }; // Named Attributes. - public Vim.G3dNext.Attributes.MeshInstanceTransformAttribute MeshInstanceTransformAttribute + public Vim.G3dNext.Attributes.MeshInstanceTransformsAttribute MeshInstanceTransformsAttribute { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.MeshInstanceTransformAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshInstanceTransformAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.MeshInstanceTransformAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.MeshInstanceTransformsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshInstanceTransformsAttribute : default; + set => Map[Vim.G3dNext.Attributes.MeshInstanceTransformsAttribute.AttributeName] = value as IAttribute; } - public Vim.G3dNext.Attributes.MeshOpaqueSubmeshCountAttribute MeshOpaqueSubmeshCountAttribute + public Vim.G3dNext.Attributes.MeshOpaqueSubmeshCountsAttribute MeshOpaqueSubmeshCountsAttribute { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.MeshOpaqueSubmeshCountAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshOpaqueSubmeshCountAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.MeshOpaqueSubmeshCountAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.MeshOpaqueSubmeshCountsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshOpaqueSubmeshCountsAttribute : default; + set => Map[Vim.G3dNext.Attributes.MeshOpaqueSubmeshCountsAttribute.AttributeName] = value as IAttribute; } - public Vim.G3dNext.Attributes.MeshSubmeshIndexOffsetAttribute MeshSubmeshIndexOffsetAttribute + public Vim.G3dNext.Attributes.MeshSubmeshIndexOffsetsAttribute MeshSubmeshIndexOffsetsAttribute { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.MeshSubmeshIndexOffsetAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshSubmeshIndexOffsetAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.MeshSubmeshIndexOffsetAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.MeshSubmeshIndexOffsetsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshSubmeshIndexOffsetsAttribute : default; + set => Map[Vim.G3dNext.Attributes.MeshSubmeshIndexOffsetsAttribute.AttributeName] = value as IAttribute; } - public Vim.G3dNext.Attributes.MeshSubmeshVertexOffsetAttribute MeshSubmeshVertexOffsetAttribute + public Vim.G3dNext.Attributes.MeshSubmeshVertexOffsetsAttribute MeshSubmeshVertexOffsetsAttribute { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.MeshSubmeshVertexOffsetAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshSubmeshVertexOffsetAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.MeshSubmeshVertexOffsetAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.MeshSubmeshVertexOffsetsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshSubmeshVertexOffsetsAttribute : default; + set => Map[Vim.G3dNext.Attributes.MeshSubmeshVertexOffsetsAttribute.AttributeName] = value as IAttribute; } - public Vim.G3dNext.Attributes.MeshSubmeshMaterialAttribute MeshSubmeshMaterialAttribute + public Vim.G3dNext.Attributes.MeshSubmeshMaterialsAttribute MeshSubmeshMaterialsAttribute { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.MeshSubmeshMaterialAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshSubmeshMaterialAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.MeshSubmeshMaterialAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.MeshSubmeshMaterialsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshSubmeshMaterialsAttribute : default; + set => Map[Vim.G3dNext.Attributes.MeshSubmeshMaterialsAttribute.AttributeName] = value as IAttribute; } - public Vim.G3dNext.Attributes.MeshVertexAttribute MeshVertexAttribute + public Vim.G3dNext.Attributes.MeshPositionsAttribute MeshPositionsAttribute { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.MeshVertexAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshVertexAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.MeshVertexAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.MeshPositionsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshPositionsAttribute : default; + set => Map[Vim.G3dNext.Attributes.MeshPositionsAttribute.AttributeName] = value as IAttribute; } - public Vim.G3dNext.Attributes.MeshIndexAttribute MeshIndexAttribute + public Vim.G3dNext.Attributes.MeshIndicesAttribute MeshIndicesAttribute { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.MeshIndexAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshIndexAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.MeshIndexAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.MeshIndicesAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshIndicesAttribute : default; + set => Map[Vim.G3dNext.Attributes.MeshIndicesAttribute.AttributeName] = value as IAttribute; } /// public IAttribute GetAttribute(Type attributeType) { - if (attributeType == typeof(Vim.G3dNext.Attributes.MeshInstanceTransformAttribute)) - return MeshInstanceTransformAttribute; + if (attributeType == typeof(Vim.G3dNext.Attributes.MeshInstanceTransformsAttribute)) + return MeshInstanceTransformsAttribute; - if (attributeType == typeof(Vim.G3dNext.Attributes.MeshOpaqueSubmeshCountAttribute)) - return MeshOpaqueSubmeshCountAttribute; + if (attributeType == typeof(Vim.G3dNext.Attributes.MeshOpaqueSubmeshCountsAttribute)) + return MeshOpaqueSubmeshCountsAttribute; - if (attributeType == typeof(Vim.G3dNext.Attributes.MeshSubmeshIndexOffsetAttribute)) - return MeshSubmeshIndexOffsetAttribute; + if (attributeType == typeof(Vim.G3dNext.Attributes.MeshSubmeshIndexOffsetsAttribute)) + return MeshSubmeshIndexOffsetsAttribute; - if (attributeType == typeof(Vim.G3dNext.Attributes.MeshSubmeshVertexOffsetAttribute)) - return MeshSubmeshVertexOffsetAttribute; + if (attributeType == typeof(Vim.G3dNext.Attributes.MeshSubmeshVertexOffsetsAttribute)) + return MeshSubmeshVertexOffsetsAttribute; - if (attributeType == typeof(Vim.G3dNext.Attributes.MeshSubmeshMaterialAttribute)) - return MeshSubmeshMaterialAttribute; + if (attributeType == typeof(Vim.G3dNext.Attributes.MeshSubmeshMaterialsAttribute)) + return MeshSubmeshMaterialsAttribute; - if (attributeType == typeof(Vim.G3dNext.Attributes.MeshVertexAttribute)) - return MeshVertexAttribute; + if (attributeType == typeof(Vim.G3dNext.Attributes.MeshPositionsAttribute)) + return MeshPositionsAttribute; - if (attributeType == typeof(Vim.G3dNext.Attributes.MeshIndexAttribute)) - return MeshIndexAttribute; + if (attributeType == typeof(Vim.G3dNext.Attributes.MeshIndicesAttribute)) + return MeshIndicesAttribute; throw new ArgumentException("Type {attributeType.ToString()} is not supported."); } @@ -2800,46 +2810,46 @@ public IAttribute MergeAttribute(string attributeName, IReadOnlyList().ToArray().MergeDataAttributes(); + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); } - case Vim.G3dNext.Attributes.MeshOpaqueSubmeshCountAttribute.AttributeName: + case Vim.G3dNext.Attributes.MeshOpaqueSubmeshCountsAttribute.AttributeName: { // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); } - case Vim.G3dNext.Attributes.MeshSubmeshIndexOffsetAttribute.AttributeName: + case Vim.G3dNext.Attributes.MeshSubmeshIndexOffsetsAttribute.AttributeName: { // Index Attribute - return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); + return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); } - case Vim.G3dNext.Attributes.MeshSubmeshVertexOffsetAttribute.AttributeName: + case Vim.G3dNext.Attributes.MeshSubmeshVertexOffsetsAttribute.AttributeName: { // Index Attribute - return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); + return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); } - case Vim.G3dNext.Attributes.MeshSubmeshMaterialAttribute.AttributeName: + case Vim.G3dNext.Attributes.MeshSubmeshMaterialsAttribute.AttributeName: { // Index Attribute - return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); + return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); } - case Vim.G3dNext.Attributes.MeshVertexAttribute.AttributeName: + case Vim.G3dNext.Attributes.MeshPositionsAttribute.AttributeName: { // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); } - case Vim.G3dNext.Attributes.MeshIndexAttribute.AttributeName: + case Vim.G3dNext.Attributes.MeshIndicesAttribute.AttributeName: { // Index Attribute - return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); + return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); } default: @@ -2852,58 +2862,58 @@ public void Validate() // Ensure all the indices are either -1 or within the bounds of the attributes they are indexing into. { - var maxIndex = GetAttribute(MeshSubmeshIndexOffsetAttribute.IndexInto).Data.Length - 1; - for (var i = 0; i < MeshSubmeshIndexOffsetAttribute.TypedData.Length; ++i) + var maxIndex = GetAttribute(MeshSubmeshIndexOffsetsAttribute.IndexInto).Data.Length - 1; + for (var i = 0; i < MeshSubmeshIndexOffsetsAttribute.TypedData.Length; ++i) { - var index = MeshSubmeshIndexOffsetAttribute.TypedData[i]; + var index = MeshSubmeshIndexOffsetsAttribute.TypedData[i]; if (index == -1) continue; // no relation. if (index < -1 || index > maxIndex) - throw new Exception($"Index out of range in Vim.G3dNext.Attributes.MeshSubmeshIndexOffsetAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); + throw new Exception($"Index out of range in Vim.G3dNext.Attributes.MeshSubmeshIndexOffsetsAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); } } { - var maxIndex = GetAttribute(MeshSubmeshVertexOffsetAttribute.IndexInto).Data.Length - 1; - for (var i = 0; i < MeshSubmeshVertexOffsetAttribute.TypedData.Length; ++i) + var maxIndex = GetAttribute(MeshSubmeshVertexOffsetsAttribute.IndexInto).Data.Length - 1; + for (var i = 0; i < MeshSubmeshVertexOffsetsAttribute.TypedData.Length; ++i) { - var index = MeshSubmeshVertexOffsetAttribute.TypedData[i]; + var index = MeshSubmeshVertexOffsetsAttribute.TypedData[i]; if (index == -1) continue; // no relation. if (index < -1 || index > maxIndex) - throw new Exception($"Index out of range in Vim.G3dNext.Attributes.MeshSubmeshVertexOffsetAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); + throw new Exception($"Index out of range in Vim.G3dNext.Attributes.MeshSubmeshVertexOffsetsAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); } } { - var maxIndex = GetAttribute(MeshSubmeshMaterialAttribute.IndexInto).Data.Length - 1; - for (var i = 0; i < MeshSubmeshMaterialAttribute.TypedData.Length; ++i) + var maxIndex = GetAttribute(MeshSubmeshMaterialsAttribute.IndexInto).Data.Length - 1; + for (var i = 0; i < MeshSubmeshMaterialsAttribute.TypedData.Length; ++i) { - var index = MeshSubmeshMaterialAttribute.TypedData[i]; + var index = MeshSubmeshMaterialsAttribute.TypedData[i]; if (index == -1) continue; // no relation. if (index < -1 || index > maxIndex) - throw new Exception($"Index out of range in Vim.G3dNext.Attributes.MeshSubmeshMaterialAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); + throw new Exception($"Index out of range in Vim.G3dNext.Attributes.MeshSubmeshMaterialsAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); } } { - var maxIndex = GetAttribute(MeshIndexAttribute.IndexInto).Data.Length - 1; - for (var i = 0; i < MeshIndexAttribute.TypedData.Length; ++i) + var maxIndex = GetAttribute(MeshIndicesAttribute.IndexInto).Data.Length - 1; + for (var i = 0; i < MeshIndicesAttribute.TypedData.Length; ++i) { - var index = MeshIndexAttribute.TypedData[i]; + var index = MeshIndicesAttribute.TypedData[i]; if (index == -1) continue; // no relation. if (index < -1 || index > maxIndex) - throw new Exception($"Index out of range in Vim.G3dNext.Attributes.MeshIndexAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); + throw new Exception($"Index out of range in Vim.G3dNext.Attributes.MeshIndicesAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); } } } diff --git a/src/cs/g3d/Vim.G3dNext.Attributes/G3dMaterials.cs b/src/cs/g3d/Vim.G3dNext.Attributes/G3dMaterials.cs new file mode 100644 index 00000000..249879cd --- /dev/null +++ b/src/cs/g3d/Vim.G3dNext.Attributes/G3dMaterials.cs @@ -0,0 +1,10 @@ +namespace Vim.G3dNext.Attributes +{ + public partial class G3dMaterials + { + void ISetup.Setup() + { + // empty + } + } +} \ No newline at end of file diff --git a/src/cs/g3d/Vim.G3dNext.Attributes/G3dMesh.cs b/src/cs/g3d/Vim.G3dNext.Attributes/G3dMesh.cs new file mode 100644 index 00000000..f2ab2244 --- /dev/null +++ b/src/cs/g3d/Vim.G3dNext.Attributes/G3dMesh.cs @@ -0,0 +1,151 @@ +using System; +using Vim.Math3d; + +namespace Vim.G3dNext.Attributes +{ + public partial class G3dMesh + { + // Field doesn't get written but is useful in builing a Vimx. + public int[] InstanceNodes; + + void ISetup.Setup() + { + // empty + } + + /// + /// The total number of instances. + /// + public int GetInstanceCount() => InstanceTransforms?.Length ?? 0; + + /// + /// The total number of submeshes. + /// + public int GetSubmeshCount() => SubmeshIndexOffsets?.Length ?? 0; + + /// + /// The total number of submeshes. + /// + public int GetSubmeshCount(MeshSection section) + { + var count = GetSubmeshCount(); + if (OpaqueSubmeshCounts == null) return count; + var opaque = OpaqueSubmeshCounts[0]; + + return section == MeshSection.Opaque + ? opaque + : count - opaque; + } + + public int GetIndexStart(MeshSection section) + { + if (OpaqueSubmeshCounts == null) return 0; + if (section == MeshSection.Opaque) return 0; + var opaque = OpaqueSubmeshCounts[0]; + return GetSubmeshIndexStart(opaque); + } + + public int GetIndexEnd(MeshSection section) + { + if (OpaqueSubmeshCounts == null) return Indices.Length; + if (section == MeshSection.Transparent) return Indices.Length; + var opaque = OpaqueSubmeshCounts[0]; + return GetSubmeshIndexEnd(opaque - 1); + } + + public int GetIndexCount(MeshSection section) + { + return GetIndexEnd(section) - GetIndexStart(section); + } + + /// + /// The total number of indices. + /// + public int GetIndexCount() => Indices?.Length ?? 0; + + public int GetVertexStart(MeshSection section) + { + if (OpaqueSubmeshCounts == null) return 0; + if (SubmeshVertexOffsets == null) return 0; + if (section == MeshSection.Opaque) return 0; + var opaque = OpaqueSubmeshCounts[0]; + return GetSubmeshVertexStart(opaque); + } + + public int GetVertexEnd(MeshSection section) + { + if (OpaqueSubmeshCounts == null) return Positions.Length; + if (SubmeshVertexOffsets == null) return Positions.Length; + if (section == MeshSection.Transparent) return Positions.Length; + var opaque = OpaqueSubmeshCounts[0]; + return GetSubmeshVertexEnd(opaque - 1); + } + + public int GetVertexCount(MeshSection section) + { + return GetVertexEnd(section) - GetVertexStart(section); + } + + /// + /// The total number of vertices. + /// + public int GetVertexCount() => (Positions?.Length ?? 0); + + public int GetSubmeshIndexStart(int submesh) + { + return SubmeshIndexOffsets[submesh]; + } + + public int GetSubmeshIndexEnd(int submesh) + { + return submesh + 1 < GetSubmeshCount() ? SubmeshIndexOffsets[submesh + 1] : GetIndexCount(); + } + + public int GetSubmeshIndexCount(int submesh) + { + return GetSubmeshIndexEnd(submesh) - GetSubmeshIndexStart(submesh); + } + + public int GetSubmeshVertexStart(int submesh) + { + return SubmeshVertexOffsets[submesh]; + } + + public int GetSubmeshVertexEnd(int submesh) + { + return submesh + 1 < GetSubmeshCount() ? SubmeshVertexOffsets[submesh + 1] : GetVertexCount(); + } + + public int GetSubmeshVertexCount(int submesh) + { + return GetSubmeshVertexEnd(submesh) - GetSubmeshVertexStart(submesh); + } + + public AABox GetAABB() + { + var box = new AABox(Positions[0], Positions[0]); + for (var p = 1; p < Positions.Length; p++) + { + var pos = Positions[p]; + box = Expand(box, pos); + } + return box; + } + + static AABox Expand(AABox box, Vector3 pos) + { + return new AABox( + new Vector3( + Math.Min(box.Min.X, pos.X), + Math.Min(box.Min.Y, pos.Y), + Math.Min(box.Min.Z, pos.Z) + ), + new Vector3( + Math.Max(box.Max.X, pos.X), + Math.Max(box.Max.Y, pos.Y), + Math.Max(box.Max.Z, pos.Z) + ) + ); + } + } +} diff --git a/src/cs/g3d/Vim.G3dNext.Attributes/G3dScene.cs b/src/cs/g3d/Vim.G3dNext.Attributes/G3dScene.cs new file mode 100644 index 00000000..769b7fff --- /dev/null +++ b/src/cs/g3d/Vim.G3dNext.Attributes/G3dScene.cs @@ -0,0 +1,10 @@ +namespace Vim.G3dNext.Attributes +{ + public partial class G3dScene + { + void ISetup.Setup() + { + // empty + } + } +} \ No newline at end of file diff --git a/src/cs/g3d/Vim.G3dNext.Attributes/G3dVim.cs b/src/cs/g3d/Vim.G3dNext.Attributes/G3dVim.cs new file mode 100644 index 00000000..dbd84962 --- /dev/null +++ b/src/cs/g3d/Vim.G3dNext.Attributes/G3dVim.cs @@ -0,0 +1,153 @@ +using System; +using Vim.BFast; +using Vim.BFastNextNS; + +namespace Vim.G3dNext.Attributes +{ + public partial class G3dVim + { + // Computed field + public int[] MeshVertexOffsets; + + void ISetup.Setup() + { + MeshVertexOffsets = ComputeMeshVertexOffsets(); + } + + public static G3dVim FromVim(string vimPath) + => vimPath.ReadBFast(b => new G3dVim(b.GetBFast("geometry"))); + + private int[] ComputeMeshVertexOffsets() + { + var result = new int[GetMeshCount()]; + for (var m = 0; m < result.Length; m++) + { + var min = int.MaxValue; + var start = GetMeshIndexStart(m); + var end = GetMeshIndexEnd(m); + for (var i = start; i < end; i++) + { + min = Math.Min(min, Indices[i]); + } + result[m] = min; + } + return result; + } + + public int GetTriangleCount() + { + return GetIndexCount() / 3; + } + + /// + /// The total number of instances. + /// + public int GetInstanceCount() => InstanceTransforms?.Length ?? 0; + + #region meshes + /// + /// The total number of meshes. + /// + public int GetMeshCount() => MeshSubmeshOffsets?.Length ?? 0; + + public int GetMeshIndexStart(int mesh) + { + var submesh = GetMeshSubmeshStart(mesh); + return GetSubmeshIndexStart(submesh); + } + + public int GetMeshIndexEnd(int mesh) + { + var submesh = GetMeshSubmeshEnd(mesh) - 1; + return GetSubmeshIndexEnd(submesh); + } + + public int GetMeshIndexCount(int mesh) + { + return GetMeshIndexEnd(mesh) - GetMeshIndexStart(mesh); + } + + public int GetMeshVertexStart(int mesh) + { + return MeshVertexOffsets[mesh]; + } + + public int GetMeshVertexEnd(int mesh) + { + return mesh + 1 < GetMeshCount() ? MeshVertexOffsets[mesh + 1] : Positions.Length; + } + + public int GetMeshVertexCount(int mesh) + { + return GetMeshVertexEnd(mesh) - GetMeshVertexStart(mesh); + } + + public int GetMeshSubmeshStart(int mesh) + { + return MeshSubmeshOffsets[mesh]; + } + + public int GetMeshSubmeshEnd(int mesh) + { + return mesh + 1 < GetMeshCount() + ? MeshSubmeshOffsets[mesh + 1] + : GetSubmeshCount(); + } + + public int GetMeshSubmeshCount(int mesh) + { + return GetMeshSubmeshEnd(mesh) - GetMeshSubmeshStart(mesh); + } + + #endregion + + #region submesh + + /// + /// The total number of submeshes. + /// + public int GetSubmeshCount() => SubmeshIndexOffsets?.Length ?? 0; + + public int GetSubmeshIndexStart(int submesh) + { + return SubmeshIndexOffsets[submesh]; + } + + public int GetSubmeshIndexEnd(int submesh) + { + return submesh + 1 < GetSubmeshCount() ? SubmeshIndexOffsets[submesh + 1] : GetIndexCount(); + } + + public int GetSubmeshIndexCount(int submesh) + { + return GetSubmeshIndexEnd(submesh) - GetSubmeshIndexStart(submesh); + } + + #endregion + + /// + /// The total number of indices. + /// + public int GetIndexCount() => Indices?.Length ?? 0; + + /// + /// The total number of vertices. + /// + public int GetVertexCount() => Positions?.Length ?? 0; + + /// + /// The total number of materials. + /// + public int GetMaterialCount() => MaterialColors?.Length ?? 0; + + /// + /// The total number of shapes. + /// + public int GetShapeCount() => ShapeVertexOffsets?.Length ?? 0; + + /// + /// The total number of shape vertices. + /// + public int GetShapeVertexCount() => ShapeVertices?.Length ?? 0; + } +} diff --git a/src/cs/g3d/Vim.G3dNext.Attributes/MaterialAttributes.cs b/src/cs/g3d/Vim.G3dNext.Attributes/MaterialsAttributes.cs similarity index 77% rename from src/cs/g3d/Vim.G3dNext.Attributes/MaterialAttributes.cs rename to src/cs/g3d/Vim.G3dNext.Attributes/MaterialsAttributes.cs index 55060da5..e72d67f1 100644 --- a/src/cs/g3d/Vim.G3dNext.Attributes/MaterialAttributes.cs +++ b/src/cs/g3d/Vim.G3dNext.Attributes/MaterialsAttributes.cs @@ -3,17 +3,17 @@ namespace Vim.G3dNext.Attributes { [AttributeCollection( - typeof(MaterialColorAttribute), + typeof(MaterialColorsAttribute), typeof(MaterialGlossinessAttribute), typeof(MaterialSmoothnessAttribute) )] - public partial class MaterialAttributeCollection // : IAttributeCollection + public partial class MaterialsAttributeCollection // : IAttributeCollection { } [AttributeDescriptor("g3d:material:color:0:float32:4", AttributeType.Data, ArrayType = typeof(Vector4))] - public partial class MaterialColorAttribute { } + public partial class MaterialColorsAttribute { } [AttributeDescriptor("g3d:material:glossiness:0:float32:1", AttributeType.Data)] public partial class MaterialGlossinessAttribute { } diff --git a/src/cs/g3d/Vim.G3dNext.Attributes/MeshAttributes.cs b/src/cs/g3d/Vim.G3dNext.Attributes/MeshAttributes.cs index a18ad02e..f52a69db 100644 --- a/src/cs/g3d/Vim.G3dNext.Attributes/MeshAttributes.cs +++ b/src/cs/g3d/Vim.G3dNext.Attributes/MeshAttributes.cs @@ -3,37 +3,44 @@ namespace Vim.G3dNext.Attributes { [AttributeCollection( - typeof(MeshInstanceTransformAttribute), - typeof(MeshOpaqueSubmeshCountAttribute), - typeof(MeshSubmeshIndexOffsetAttribute), - typeof(MeshSubmeshVertexOffsetAttribute), - typeof(MeshSubmeshMaterialAttribute), - typeof(MeshVertexAttribute), - typeof(MeshIndexAttribute) + typeof(MeshInstanceTransformsAttribute), + typeof(MeshOpaqueSubmeshCountsAttribute), + typeof(MeshSubmeshIndexOffsetsAttribute), + typeof(MeshSubmeshVertexOffsetsAttribute), + typeof(MeshSubmeshMaterialsAttribute), + typeof(MeshPositionsAttribute), + typeof(MeshIndicesAttribute) )] public partial class MeshAttributeCollection // : IAttributeCollection { } - [AttributeDescriptor("g3d:instance:transform:0:float32:16", AttributeType.Data, ArrayType = typeof(Matrix4x4))] - public partial class MeshInstanceTransformAttribute { } + [AttributeDescriptor("Mesh", "g3d:instance:transform:0:float32:16", AttributeType.Data, ArrayType = typeof(Matrix4x4))] + public partial class MeshInstanceTransformsAttribute { } - [AttributeDescriptor("g3d:mesh:opaquesubmeshcount:0:int32:1", AttributeType.Data)] - public partial class MeshOpaqueSubmeshCountAttribute { } + [AttributeDescriptor("Mesh", "g3d:mesh:opaquesubmeshcount:0:int32:1", AttributeType.Data)] + public partial class MeshOpaqueSubmeshCountsAttribute { } - [AttributeDescriptor("g3d:submesh:indexoffset:0:int32:1", AttributeType.Index, IndexInto = typeof(IndexAttribute))] - public partial class MeshSubmeshIndexOffsetAttribute { } + [AttributeDescriptor("Mesh", "g3d:submesh:indexoffset:0:int32:1", AttributeType.Index, IndexInto = typeof(IndicesAttribute))] + public partial class MeshSubmeshIndexOffsetsAttribute { } - [AttributeDescriptor("g3d:submesh:vertexoffset:0:int32:1", AttributeType.Index, IndexInto = typeof(IndexAttribute))] - public partial class MeshSubmeshVertexOffsetAttribute { } + [AttributeDescriptor("Mesh", "g3d:submesh:vertexoffset:0:int32:1", AttributeType.Index, IndexInto = typeof(IndicesAttribute))] + public partial class MeshSubmeshVertexOffsetsAttribute { } - [AttributeDescriptor("g3d:submesh:material:0:int32:1", AttributeType.Index, IndexInto = typeof(MaterialColorAttribute))] - public partial class MeshSubmeshMaterialAttribute { } + [AttributeDescriptor("Mesh", "g3d:submesh:material:0:int32:1", AttributeType.Index, IndexInto = typeof(MaterialColorsAttribute))] + public partial class MeshSubmeshMaterialsAttribute { } - [AttributeDescriptor("g3d:vertex:position:0:float32:3", AttributeType.Data, ArrayType = typeof(Vector3))] - public partial class MeshVertexAttribute { } + [AttributeDescriptor("Mesh", "g3d:vertex:position:0:float32:3", AttributeType.Data, ArrayType = typeof(Vector3))] + public partial class MeshPositionsAttribute { } - [AttributeDescriptor("g3d:corner:index:0:int32:1", AttributeType.Index, IndexInto = typeof(VertexAttribute))] - public partial class MeshIndexAttribute { } + [AttributeDescriptor("Mesh", "g3d:corner:index:0:int32:1", AttributeType.Index, IndexInto = typeof(PositionsAttribute))] + public partial class MeshIndicesAttribute { } +} + + +public enum MeshSection +{ + Opaque, + Transparent } diff --git a/src/cs/g3d/Vim.G3dNext.Attributes/VimAttributes.cs b/src/cs/g3d/Vim.G3dNext.Attributes/VimAttributes.cs index bbbd5145..fc7cf186 100644 --- a/src/cs/g3d/Vim.G3dNext.Attributes/VimAttributes.cs +++ b/src/cs/g3d/Vim.G3dNext.Attributes/VimAttributes.cs @@ -3,68 +3,64 @@ namespace Vim.G3dNext.Attributes { [AttributeCollection( - typeof(CornersPerFaceAttribute), - typeof(VertexAttribute), - typeof(IndexAttribute), - typeof(InstanceTransformAttribute), - typeof(InstanceParentAttribute), + typeof(PositionsAttribute), + typeof(IndicesAttribute), + typeof(InstanceTransformsAttribute), + typeof(InstanceParentsAttribute), typeof(InstanceFlagsAttribute), - typeof(InstanceMeshAttribute), - typeof(MeshSubmeshOffsetAttribute), - typeof(SubmeshIndexOffsetAttribute), - typeof(SubmeshMaterialAttribute), - typeof(MaterialColorAttribute), + typeof(InstanceMeshesAttribute), + typeof(MeshSubmeshOffsetsAttribute), + typeof(SubmeshIndexOffsetsAttribute), + typeof(SubmeshMaterialsAttribute), + typeof(MaterialColorsAttribute), typeof(MaterialGlossinessAttribute), typeof(MaterialSmoothnessAttribute), - typeof(ShapeVertexAttribute), - typeof(ShapeVertexOffsetAttribute), - typeof(ShapeColorAttribute), - typeof(ShapeWidthAttribute) + typeof(ShapeVerticesAttribute), + typeof(ShapeVertexOffsetsAttribute), + typeof(ShapeColorsAttribute), + typeof(ShapeWidthsAttribute) )] public partial class VimAttributeCollection // : IAttributeCollection { } - [AttributeDescriptor("g3d:all:facesize:0:int32:1", AttributeType.Singleton)] - public partial class CornersPerFaceAttribute { } - [AttributeDescriptor("g3d:vertex:position:0:float32:3", AttributeType.Data, ArrayType = typeof(Vector3))] - public partial class VertexAttribute { } + public partial class PositionsAttribute { } - [AttributeDescriptor("g3d:corner:index:0:int32:1", AttributeType.Index, IndexInto = typeof(VertexAttribute))] - public partial class IndexAttribute { } + [AttributeDescriptor("g3d:corner:index:0:int32:1", AttributeType.Index, IndexInto = typeof(PositionsAttribute))] + public partial class IndicesAttribute { } [AttributeDescriptor("g3d:instance:transform:0:float32:16", AttributeType.Data, ArrayType = typeof(Matrix4x4))] - public partial class InstanceTransformAttribute { } + public partial class InstanceTransformsAttribute { } - [AttributeDescriptor("g3d:instance:parent:0:int32:1", AttributeType.Index, IndexInto = typeof(InstanceTransformAttribute))] - public partial class InstanceParentAttribute { } + [AttributeDescriptor("g3d:instance:parent:0:int32:1", AttributeType.Index, IndexInto = typeof(InstanceTransformsAttribute))] + public partial class InstanceParentsAttribute { } [AttributeDescriptor("g3d:instance:flags:0:uint16:1", AttributeType.Data)] public partial class InstanceFlagsAttribute { } - [AttributeDescriptor("g3d:instance:mesh:0:int32:1", AttributeType.Index, IndexInto = typeof(MeshSubmeshOffsetAttribute))] - public partial class InstanceMeshAttribute { } + [AttributeDescriptor("g3d:instance:mesh:0:int32:1", AttributeType.Index, IndexInto = typeof(MeshSubmeshOffsetsAttribute))] + public partial class InstanceMeshesAttribute { } - [AttributeDescriptor("g3d:mesh:submeshoffset:0:int32:1", AttributeType.Index, IndexInto = typeof(SubmeshIndexOffsetAttribute))] - public partial class MeshSubmeshOffsetAttribute { } + [AttributeDescriptor("g3d:mesh:submeshoffset:0:int32:1", AttributeType.Index, IndexInto = typeof(SubmeshIndexOffsetsAttribute))] + public partial class MeshSubmeshOffsetsAttribute { } - [AttributeDescriptor("g3d:submesh:indexoffset:0:int32:1", AttributeType.Index, IndexInto = typeof(IndexAttribute))] - public partial class SubmeshIndexOffsetAttribute { } + [AttributeDescriptor("g3d:submesh:indexoffset:0:int32:1", AttributeType.Index, IndexInto = typeof(IndicesAttribute))] + public partial class SubmeshIndexOffsetsAttribute { } - [AttributeDescriptor("g3d:submesh:material:0:int32:1", AttributeType.Index, IndexInto = typeof(MaterialColorAttribute))] - public partial class SubmeshMaterialAttribute { } + [AttributeDescriptor("g3d:submesh:material:0:int32:1", AttributeType.Index, IndexInto = typeof(MaterialColorsAttribute))] + public partial class SubmeshMaterialsAttribute { } [AttributeDescriptor("g3d:shapevertex:position:0:float32:3", AttributeType.Data, ArrayType = typeof(Vector3))] - public partial class ShapeVertexAttribute { } + public partial class ShapeVerticesAttribute { } - [AttributeDescriptor("g3d:shape:vertexoffset:0:int32:1", AttributeType.Index, IndexInto = typeof(ShapeVertexAttribute))] - public partial class ShapeVertexOffsetAttribute { } + [AttributeDescriptor("g3d:shape:vertexoffset:0:int32:1", AttributeType.Index, IndexInto = typeof(ShapeVerticesAttribute))] + public partial class ShapeVertexOffsetsAttribute { } [AttributeDescriptor("g3d:shape:color:0:float32:4", AttributeType.Data, ArrayType = typeof(Vector4))] - public partial class ShapeColorAttribute { } + public partial class ShapeColorsAttribute { } [AttributeDescriptor("g3d:shape:width:0:float32:1", AttributeType.Data)] - public partial class ShapeWidthAttribute { } + public partial class ShapeWidthsAttribute { } } diff --git a/src/cs/g3d/Vim.G3dNext.CodeGen/G3dAttributeCollectionGenerator.cs b/src/cs/g3d/Vim.G3dNext.CodeGen/G3dAttributeCollectionGenerator.cs index b92d660f..0b95dbfa 100644 --- a/src/cs/g3d/Vim.G3dNext.CodeGen/G3dAttributeCollectionGenerator.cs +++ b/src/cs/g3d/Vim.G3dNext.CodeGen/G3dAttributeCollectionGenerator.cs @@ -22,6 +22,7 @@ public static void WriteDocument(string filePath) cb.AppendLine("using System.Collections.Generic;"); cb.AppendLine("using System.Linq;"); cb.AppendLine("using Vim.BFast;"); + cb.AppendLine("using Vim.BFastNextNS;"); cb.AppendLine(); cb.AppendLine("namespace Vim.G3dNext.Attributes"); cb.AppendLine("{"); @@ -92,15 +93,15 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext.BFastNext bfast) + public void AddTo(BFastNext bfast) {{ if(TypedData != null) {{ - bfast.AddArray(Name, TypedData); + bfast.SetArray(Name, TypedData); }} }} - public void ReadBFast(BFastNext.BFastNext bfast) + public void ReadBFast(BFastNext bfast) {{ TypedData = bfast.GetArray<{typedDataType}>(""{attributeName}""); }} @@ -146,38 +147,46 @@ public static void WriteVimG3dAttributeCollection(CodeBuilder cb, Type acClass) throw new Exception($"No attribute of type {(nameof(AttributeCollectionAttribute))} found on {className}"); var attributeClasses = ac.AttributeClasses; - var g3dName = "G3d" + className.Replace("AttributeCollection", "2"); + var g3dName = "G3d" + className.Replace("AttributeCollection", ""); cb.AppendLine($@" - public class {g3dName} + // Please provide an explicit implementation in another partial class file. + public partial class {g3dName} : ISetup {{ - public G3DNext<{className}> source; + public {className} Attributes; - public {g3dName}() + public {g3dName}() : this(new {className}()) {{ - this.source = new G3DNext<{className}> (); + // empty }} - public {g3dName}(G3DNext<{className}> source) + public {g3dName}(BFastNext bfast) : this(new {className}(bfast)) {{ - this.source = source; + // empty }} - public {g3dName}(BFastNext.BFastNext bfast) + public {g3dName}({className} attributes) {{ - this.source = new G3DNext<{className}>(bfast); + Attributes = attributes; + + // Method to implement in another partial class + (this as ISetup).Setup(); }} + public BFastNext ToBFast() + => Attributes.ToBFast(); + { string.Join(Environment.NewLine, attributeClasses.Select(c => { - var ada = c.GetCustomAttribute(); - var typedDataType = ada.GetTypedDataType(); + var attribute = c.GetCustomAttribute(); + var typedDataType = attribute.GetTypedDataType(); + return $@" - public {typedDataType}[] {c.Name.Replace("Attribute","")} + public {typedDataType}[] {attribute.FormatClassName(c.Name)} {{ - get => source.AttributeCollection.{c.Name}.TypedData; - set => source.AttributeCollection.{c.Name}.TypedData = value; + get => Attributes.{c.Name}.TypedData; + set => Attributes.{c.Name}.TypedData = value; }}";})) } }} @@ -187,13 +196,25 @@ public class {g3dName} cb.AppendLine($@" public partial class {className} : IAttributeCollection {{ - public IEnumerable AttributeNames - => Attributes.Keys; + public {className}() + {{ + // empty + }} + + public {className}(BFastNext bfast) + {{ + this.ReadAttributes(bfast); + }} - public long GetSize() - => Attributes.Values.Sum(a => a.Data.LongLength * a.AttributeDescriptor.DataElementSize); + public void ReadAttributes(BFastNext bfast) + {{ + foreach (var attribute in Map.Values) + {{ + attribute.ReadBFast(bfast); + }} + }} - public IDictionary Attributes {{ get; }} + public IDictionary Map {{ get; }} = new Dictionary {{ {string.Join(Environment.NewLine, attributeClasses.Select(c => @@ -204,8 +225,8 @@ public long GetSize() {string.Join(Environment.NewLine, attributeClasses.Select(c => $@" public {c} {c.Name} {{ - get => Attributes.TryGetValue({c}.AttributeName, out var attr) ? attr as {c} : default; - set => Attributes[{c}.AttributeName] = value as IAttribute; + get => Map.TryGetValue({c}.AttributeName, out var attr) ? attr as {c} : default; + set => Map[{c}.AttributeName] = value as IAttribute; }}"))} /// diff --git a/src/cs/g3d/Vim.G3dNext.CodeGen/Vim.G3dNext.CodeGen.csproj b/src/cs/g3d/Vim.G3dNext.CodeGen/Vim.G3dNext.CodeGen.csproj index ddc17234..50f3a778 100644 --- a/src/cs/g3d/Vim.G3dNext.CodeGen/Vim.G3dNext.CodeGen.csproj +++ b/src/cs/g3d/Vim.G3dNext.CodeGen/Vim.G3dNext.CodeGen.csproj @@ -11,14 +11,15 @@ - - - - + + + + + diff --git a/src/cs/g3d/Vim.G3dNext/AttributeType.cs b/src/cs/g3d/Vim.G3dNext/AttributeType.cs index 0c484534..03568640 100644 --- a/src/cs/g3d/Vim.G3dNext/AttributeType.cs +++ b/src/cs/g3d/Vim.G3dNext/AttributeType.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace Vim.G3dNext +namespace Vim.G3dNext { public enum AttributeType { diff --git a/src/cs/g3d/Vim.G3dNext/CodeGenAttributes.cs b/src/cs/g3d/Vim.G3dNext/CodeGenAttributes.cs index ab8f1285..2ea57bc2 100644 --- a/src/cs/g3d/Vim.G3dNext/CodeGenAttributes.cs +++ b/src/cs/g3d/Vim.G3dNext/CodeGenAttributes.cs @@ -1,5 +1,4 @@ using System; -using System.Linq.Expressions; namespace Vim.G3dNext { @@ -7,15 +6,29 @@ namespace Vim.G3dNext public class AttributeDescriptorAttribute : Attribute { public string Name { get; set; } + public string Prefix { get; set; } = null; public Type ArrayType { get; set; } = null; public AttributeType AttributeType { get; set; } = AttributeType.Data; public Type IndexInto { get; set; } = null; + public string FormatClassName(string name) + { + var result = name.Replace("Attribute", ""); + return Prefix != null + ? result.Replace(Prefix,"") + : result; + } public AttributeDescriptorAttribute(string name, AttributeType attributeType) { Name = name; AttributeType = attributeType; } + public AttributeDescriptorAttribute(string prefix, string name, AttributeType attributeType) + { + Prefix = prefix; + Name = name; + AttributeType = attributeType; + } } [AttributeUsage(AttributeTargets.Class)] @@ -35,4 +48,4 @@ public class G3dDefinitionAttribute : Attribute public G3dDefinitionAttribute(params Type[] attributeClasses) => AttributeClasses = attributeClasses; } -} \ No newline at end of file +} diff --git a/src/cs/g3d/Vim.G3dNext/G3DNext.cs b/src/cs/g3d/Vim.G3dNext/G3DNext.cs deleted file mode 100644 index d7f24f45..00000000 --- a/src/cs/g3d/Vim.G3dNext/G3DNext.cs +++ /dev/null @@ -1,111 +0,0 @@ -using System.IO; -using Vim.BFast; -using System.Linq; -using Vim.BFastNext; - -namespace Vim.G3dNext -{ - /// - /// A G3d is composed of a header and a collection of attributes containing descriptors and their data. - /// - public class G3DNext where TAttributeCollection : IAttributeCollection, new() - { - /// - /// The meta header of the G3d. Corresponds to the "meta" segment. - /// - public readonly MetaHeader MetaHeader; - - /// - /// The attributes of the G3d. - /// - public readonly TAttributeCollection AttributeCollection; - - /// - /// Constructor. - /// - public G3DNext(MetaHeader metaHeader, TAttributeCollection attributeCollection) - { - MetaHeader = metaHeader; - AttributeCollection = attributeCollection; - } - - public G3DNext(BFastNext.BFastNext bfast) - { - AttributeCollection = new TAttributeCollection(); - AttributeCollection.ReadAttributes(bfast); - MetaHeader = MetaHeader.FromBytes(bfast.GetArray("meta")); - } - - /// - /// Constructor. Uses the default header. - /// - public G3DNext(TAttributeCollection attributeCollection) - : this(MetaHeader.Default, attributeCollection) - { } - - /// - /// Constructor. Uses the default header and instantiates an attribute collection. - /// - public G3DNext() - : this(MetaHeader.Default, new TAttributeCollection()) - { } - - public static G3DNext Empty() where T : IAttributeCollection, new() - => new G3DNext(); - - /// - /// Reads the stream using the attribute collection's readers and outputs a G3d upon success. - /// - - public static G3DNext ReadBFast(BFastNext.BFastNext bfast) - { - var attributeCollection = new TAttributeCollection(); - attributeCollection.ReadAttributes(bfast); - var header = MetaHeader.FromBytes(bfast.GetArray("meta")); - - // Instantiate the object and return. - return new G3DNext(header, attributeCollection); - } - - public static G3DNext ReadBFast(string path) - { - return path.ReadBFast(ReadBFast); - } - - public long GetSize() { - return AttributeCollection.GetSize() + Constants.MetaHeaderSegmentNumBytes; - } - - public BFastNext.BFastNext ToBFast() - { - var attributes = AttributeCollection.Attributes.Values.OrderBy(n => n.Name).ToArray(); // Order the attributes by name for consistency - var bfast = new BFastNext.BFastNext(); - bfast.AddArray(Constants.MetaHeaderSegmentName, MetaHeader.ToBytes()); - foreach (var a in attributes) - { - a.AddTo(bfast); - } - return bfast; - } - - /// - /// Returns a byte array representing the G3d. - /// - public byte[] ToBytes() - { - using (var memoryStream = new MemoryStream()) - { - var b = ToBFast(); - b.Write(memoryStream); - return memoryStream.ToArray(); - } - } - - /// - /// Validates the G3d. - /// - public void Validate() - => AttributeCollection.Validate(); - - } -} diff --git a/src/cs/g3d/Vim.G3dNext/IAttribute.cs b/src/cs/g3d/Vim.G3dNext/IAttribute.cs index 891f88af..ec5554ff 100644 --- a/src/cs/g3d/Vim.G3dNext/IAttribute.cs +++ b/src/cs/g3d/Vim.G3dNext/IAttribute.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using Vim.BFastNextNS; namespace Vim.G3dNext { @@ -13,8 +14,8 @@ public interface IAttribute Type IndexInto { get; } Array Data { get; } void Write(Stream stream); - void AddTo(BFastNext.BFastNext bfast); - void ReadBFast(BFastNext.BFastNext bfast); + void AddTo(BFastNext bfast); + void ReadBFast(BFastNext bfast); } public interface IAttribute : IAttribute diff --git a/src/cs/g3d/Vim.G3dNext/IAttributeCollection.cs b/src/cs/g3d/Vim.G3dNext/IAttributeCollection.cs index 9e5ac03e..c1785aae 100644 --- a/src/cs/g3d/Vim.G3dNext/IAttributeCollection.cs +++ b/src/cs/g3d/Vim.G3dNext/IAttributeCollection.cs @@ -1,16 +1,18 @@ using System; using System.Collections.Generic; -using System.IO; using System.Linq; using Vim.BFast; +using Vim.BFastNextNS; namespace Vim.G3dNext { /// - /// A function which reads an attribute from the given stream and size. + /// Defines method for additionnal setup after constructors in generated G3d classes. /// - public delegate IAttribute AttributeReader(Stream stream, long sizeInBytes); - public delegate IAttribute AttributeReader2(BFastNext.BFastNext bfast); + public interface ISetup + { + void Setup(); + } /// /// A collection of attributes and readers which can be used to deserialize attributes from a stream.
@@ -22,23 +24,11 @@ namespace Vim.G3dNext ///
public interface IAttributeCollection { - long GetSize(); - - /// - /// Returns the set of attribute names supported by the AttributeCollection. - /// - IEnumerable AttributeNames { get; } - /// /// A mapping from attribute name to its corresponding attribute.
/// This is populated when reading attributes from a stream. ///
- IDictionary Attributes { get; } - - /// - /// Validates the attribute collection. May throw an exception if the collection is invalid. - /// - void Validate(); + IDictionary Map { get; } /// /// Returns the attribute corresponding to the given type. @@ -49,6 +39,12 @@ public interface IAttributeCollection /// Merges the attribute with the given name with any other matching attributes in the other collections. /// IAttribute MergeAttribute(string attributeName, IReadOnlyList otherCollections); + + /// + /// Validates the attribute collection. May throw an exception if the collection is invalid. + /// + void Validate(); + } /// @@ -56,19 +52,32 @@ public interface IAttributeCollection /// public static class AttributeCollectionExtensions { - public static void ReadAttributes(this IAttributeCollection attributeCollection, BFastNext.BFastNext bfast) + public static IEnumerable GetAttributeNames(this IAttributeCollection attributeCollection) + => attributeCollection.Map.Keys; + + public static long GetSize(this IAttributeCollection attributeCollection) + => attributeCollection.Map.Values + .Sum(a => a.GetSizeInBytes()); + + public static BFastNext ToBFast(this IAttributeCollection attributeCollection) { - foreach (var attribute in attributeCollection.Attributes.Values) + var attributes = attributeCollection.Map.Values + .OrderBy(n => n.Name) + .ToArray(); // Order the attributes by name for consistency + + var bfast = new BFastNext(); + foreach (var a in attributes) { - attribute.ReadBFast(bfast); + a.AddTo(bfast); } + return bfast; } public static IEnumerable GetAttributesOfType( this IReadOnlyList collections) where TAttr : IAttribute => collections - .Select(c => c.Attributes.Values.OfType().FirstOrDefault()) + .Select(c => c.Map.Values.OfType().FirstOrDefault()) .Where(a => a != null); public static IEnumerable<(TAttr Attribute, int IndexedCount)> GetIndexedAttributesOfType( @@ -77,7 +86,7 @@ public static IEnumerable GetAttributesOfType( => collections .Select(c => { - var attr = c.Attributes.Values.OfType().FirstOrDefault(); + var attr = c.Map.Values.OfType().FirstOrDefault(); if (attr == null || attr.IndexInto == null) return (attr, 0); @@ -106,35 +115,16 @@ public static T Merge(this IReadOnlyList collections) var result = new T(); - foreach (var item in @base.Attributes) + foreach (var item in @base.Map) { var name = item.Key; var merged = @base.MergeAttribute(name, others); - result.Attributes[name] = merged; + result.Map[name] = merged; } return result; } - - /// - /// Merges the given list of G3ds.
- /// - If there is no g3d, returns a new empty g3d.
- /// - If there is only one g3d, returns that g3d. - ///
- public static G3DNext Merge(this IReadOnlyList> g3ds) - where T : IAttributeCollection, new() - { - switch (g3ds.Count) - { - case 0: - return new G3DNext(); - case 1: - return g3ds.First(); - default: - return new G3DNext(g3ds.Select(g => g.AttributeCollection).ToArray().Merge()); - } - } } } diff --git a/src/cs/g3d/Vim.G3dNext/MetaHeader.cs b/src/cs/g3d/Vim.G3dNext/MetaHeader.cs index 2a40dd24..a58a3a6f 100644 --- a/src/cs/g3d/Vim.G3dNext/MetaHeader.cs +++ b/src/cs/g3d/Vim.G3dNext/MetaHeader.cs @@ -1,7 +1,5 @@ using System; -using System.IO; using System.Text; -using Vim.BFast; namespace Vim.G3dNext { @@ -20,16 +18,11 @@ public struct MetaHeader public byte Handedness; // 0=left-handed, 1=right-handed public byte Padding; // 0 - - public string Unit => Encoding.ASCII.GetString(new byte[] { UnitA, UnitB }); public byte[] ToBytes() => new[] { MagicA, MagicB, UnitA, UnitB, UpAxis, ForwardVector, Handedness, Padding }; - public NamedBuffer ToNamedBuffer() - => ToBytes().ToNamedBuffer(Constants.MetaHeaderSegmentName); - public static MetaHeader FromBytes(byte[] bytes) => new MetaHeader { @@ -66,24 +59,5 @@ public MetaHeader Validate() if (Handedness < 0 || Handedness > 1) throw new Exception("Handedness must be 0 (left) or 1 (right"); return this; } - - public static bool IsSegmentMetaHeader(string name, long size) - => name == Constants.MetaHeaderSegmentName && size == Constants.MetaHeaderSegmentNumBytes; - - public static bool TryRead(Stream stream, long size, out MetaHeader outMetaHeader) - { - var buffer = stream.ReadArray((int)size); - - if (buffer[0] == Constants.MetaHeaderMagicA && buffer[1] == Constants.MetaHeaderMagicB) - { - outMetaHeader = FromBytes(buffer); - return true; - } - else - { - outMetaHeader = default; - return false; - } - } } } diff --git a/src/cs/vim-format.sln b/src/cs/vim-format.sln index 855d075a..950f4fff 100644 --- a/src/cs/vim-format.sln +++ b/src/cs/vim-format.sln @@ -57,9 +57,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vim.Format.Vimx", "vim\Vim. EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vim.Format.Vimx.Test", "vim\Vim.Vimx.Test\Vim.Format.Vimx.Test.csproj", "{BBF94CBD-CD39-49F5-979A-5C9E52C29330}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Vim.BFastNext", "Vim.BFast.Next\Vim.BFastNext.csproj", "{4854AD71-8023-43DE-AB2F-D5F6DCFE4974}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vim.BFastNext", "Vim.BFast.Next\Vim.BFastNext.csproj", "{4854AD71-8023-43DE-AB2F-D5F6DCFE4974}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Vim.BFastNext.Tests", "Vim.BFastNext.Tests\Vim.BFastNext.Tests.csproj", "{3DBA3070-FCB7-405B-9272-F7C112BD92A8}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vim.BFastNext.Tests", "Vim.BFastNext.Tests\Vim.BFastNext.Tests.csproj", "{3DBA3070-FCB7-405B-9272-F7C112BD92A8}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Vim.Format.Vimx.Conversion", "Vim.Format.Vimx.Conversion\Vim.Format.Vimx.Conversion.csproj", "{5527BC13-9D25-45A1-A52D-8656336542C0}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -159,6 +161,10 @@ Global {3DBA3070-FCB7-405B-9272-F7C112BD92A8}.Debug|Any CPU.Build.0 = Debug|Any CPU {3DBA3070-FCB7-405B-9272-F7C112BD92A8}.Release|Any CPU.ActiveCfg = Release|Any CPU {3DBA3070-FCB7-405B-9272-F7C112BD92A8}.Release|Any CPU.Build.0 = Release|Any CPU + {5527BC13-9D25-45A1-A52D-8656336542C0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5527BC13-9D25-45A1-A52D-8656336542C0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5527BC13-9D25-45A1-A52D-8656336542C0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5527BC13-9D25-45A1-A52D-8656336542C0}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -187,6 +193,7 @@ Global {BBF94CBD-CD39-49F5-979A-5C9E52C29330} = {D639C635-01D1-48C4-89B5-1FD70F1AFEE9} {4854AD71-8023-43DE-AB2F-D5F6DCFE4974} = {F3260C54-834F-4C74-A3B7-EAB622AFA492} {3DBA3070-FCB7-405B-9272-F7C112BD92A8} = {F3260C54-834F-4C74-A3B7-EAB622AFA492} + {5527BC13-9D25-45A1-A52D-8656336542C0} = {D639C635-01D1-48C4-89B5-1FD70F1AFEE9} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {7D1BF641-26E8-4809-B638-029241C51BE2} diff --git a/src/cs/vim/Vim.Format.Vimx/FileUtils.cs b/src/cs/vim/Vim.Format.Vimx/FileUtils.cs deleted file mode 100644 index 79a9cd95..00000000 --- a/src/cs/vim/Vim.Format.Vimx/FileUtils.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System; -using System.IO; -using System.IO.Compression; - -namespace Vim.Format.Vimx -{ - public static class FileUtils - { - public static byte[] Deflate(this byte[] inputBytes) - { - using (var memoryStream = new MemoryStream()) - { - using (var gzipStream = new DeflateStream(memoryStream, CompressionMode.Compress, true)) - { - gzipStream.Write(inputBytes, 0, inputBytes.Length); - } - return memoryStream.ToArray(); - } - } - - public static byte[] Inflate(this byte[] inputBytes) - { - using (var input = new MemoryStream(inputBytes)) - { - using (var output = new MemoryStream()) - { - using (var deflate = new DeflateStream(input, CompressionMode.Decompress, true)) - { - deflate.CopyTo(output); - return output.ToArray(); - } - } - } - - } - - } -} diff --git a/src/cs/vim/Vim.Format.Vimx/G3dMaterials.cs b/src/cs/vim/Vim.Format.Vimx/G3dMaterials.cs deleted file mode 100644 index aafdd775..00000000 --- a/src/cs/vim/Vim.Format.Vimx/G3dMaterials.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System.IO; -using Vim.Math3d; -using Vim.G3dNext.Attributes; -using Vim.G3dNext; - -namespace Vim.Format.Vimx -{ - public class G3dMaterials - { - public G3DNext source; - - // materials - public Vector4[] materialColors; - public float[] materialGlossiness; - public float[] materialSmoothness; - - public static G3dMaterials FromArrays( - Vector4[] materialColors, - float[] materialGlossiness, - float[] materialSmoothness) - { - var collection = new MaterialAttributeCollection(); - - collection.MaterialColorAttribute.TypedData = materialColors ?? new Vector4[0]; - collection.MaterialGlossinessAttribute.TypedData = materialGlossiness ?? new float[0]; - collection.MaterialSmoothnessAttribute.TypedData = materialSmoothness ?? new float[0]; - - var g3d = new G3DNext(collection); - return new G3dMaterials(g3d); - } - - public static G3dMaterials FromBFast(BFastNext.BFastNext bfast) - { - var g3d = G3DNext.ReadBFast(bfast); - return new G3dMaterials(g3d); - } - - public G3dMaterials(G3DNext g3d) - { - this.source = g3d; - - // materials - materialColors = g3d.AttributeCollection.MaterialColorAttribute.TypedData; - materialGlossiness = g3d.AttributeCollection.MaterialGlossinessAttribute.TypedData; - materialSmoothness = g3d.AttributeCollection.MaterialSmoothnessAttribute.TypedData; - } - } -} diff --git a/src/cs/vim/Vim.Format.Vimx/G3dMesh.cs b/src/cs/vim/Vim.Format.Vimx/G3dMesh.cs deleted file mode 100644 index af468b7e..00000000 --- a/src/cs/vim/Vim.Format.Vimx/G3dMesh.cs +++ /dev/null @@ -1,255 +0,0 @@ -using System.Collections.Generic; -using System.IO; -using Vim.Math3d; -using Vim.G3dNext.Attributes; -using Vim.G3dNext; - -namespace Vim.Format.Vimx -{ - public enum MeshSection - { - Opaque, - Transparent - } - - public class G3dMesh - { - public const int POSITION_SIZE = 3; - - public G3DNext source; - - // instances - public int[] instanceNodes; // This field does not get written on purpose. - public Matrix4x4[] instanceTransforms; - - //mesh - public int[] opaqueSubmeshCount; - - //submesh - public int[] submeshIndexOffsets; - public int[] submeshVertexOffsets; - public int[] submeshMaterials; - - public int[] indices; - public Vector3[] positions; - - // materials - public Vector4[] materialColors; - public float[] materialGlossiness; - public float[] materialSmoothness; - - public static G3dMesh FromArrays( - int[] instanceNode, - Matrix4x4[] instanceTransforms, - int meshOpaqueCount, - int[] submeshIndexOffsets, - int[] submeshVertexOffsets, - int[] submeshMaterials, - int[] indices, - Vector3[] vertices) - { - var collection = new MeshAttributeCollection(); - - // instances - collection.MeshInstanceTransformAttribute.TypedData = instanceTransforms ?? new Matrix4x4[0]; - - //mesh - collection.MeshOpaqueSubmeshCountAttribute.TypedData = new int[] { meshOpaqueCount }; - - // submeshes - collection.MeshSubmeshIndexOffsetAttribute.TypedData = submeshIndexOffsets ?? new int[0]; - collection.MeshSubmeshVertexOffsetAttribute.TypedData = submeshVertexOffsets ?? new int[0]; - collection.MeshSubmeshMaterialAttribute.TypedData = submeshMaterials ?? new int[0]; - - // vertices - collection.MeshIndexAttribute.TypedData = indices ?? new int[0]; - collection.MeshVertexAttribute.TypedData = vertices ?? new Vector3[0]; - - var g3d = new G3DNext(collection); - var mesh = new G3dMesh(g3d); - mesh.instanceNodes = instanceNode; - return mesh; - } - - public bool Equals(G3dVim other) - { - // instances - return - MemberwiseEquals(instanceNodes, other.instanceMeshes) && - MemberwiseEquals(instanceTransforms, other.instanceTransforms) && - - //submesh - MemberwiseEquals(submeshIndexOffsets, other.submeshIndexOffsets) && - MemberwiseEquals(submeshMaterials, other.submeshMaterials) && - - MemberwiseEquals(indices, other.indices) && - MemberwiseEquals(positions, other.vertices) && - - // materials - MemberwiseEquals(materialColors, other.materialColors) && - MemberwiseEquals(materialGlossiness, other.materialGlossiness) && - MemberwiseEquals(materialSmoothness, other.materialSmoothness); - - } - - public static bool MemberwiseEquals(T[] array1, T[] array2) - { - if (array1 == null || array2 == null) return array1 == array2; - - if (array1.Length != array2.Length) return false; - - for (var i = 0; i < array1.Length; i++) - { - if (!EqualityComparer.Default.Equals(array1[i], array2[i])) - { - return false; - } - } - - return true; - } - - public G3dMesh(G3DNext g3d) - { - this.source = g3d; - - // instances - instanceTransforms = g3d.AttributeCollection.MeshInstanceTransformAttribute.TypedData; - - // submeshes - opaqueSubmeshCount = g3d.AttributeCollection.MeshOpaqueSubmeshCountAttribute.TypedData; - submeshIndexOffsets = g3d.AttributeCollection.MeshSubmeshIndexOffsetAttribute.TypedData; - submeshVertexOffsets = g3d.AttributeCollection.MeshSubmeshVertexOffsetAttribute.TypedData; - submeshMaterials = g3d.AttributeCollection.MeshSubmeshMaterialAttribute.TypedData; - - // vertices - indices = g3d.AttributeCollection.MeshIndexAttribute.TypedData; - positions = g3d.AttributeCollection.MeshVertexAttribute.TypedData; - } - - public static G3dMesh FromBFast(BFastNext.BFastNext bfast) - { - var g3d = G3DNext.ReadBFast(bfast); - return new G3dMesh(g3d); - } - - public int GetTriangleCount() - { - return GetIndexCount() / 3; - } - - /// - /// The total number of instances. - /// - public int GetInstanceCount() => instanceTransforms?.Length ?? 0; - - /// - /// The total number of submeshes. - /// - public int GetSubmeshCount() => submeshIndexOffsets?.Length ?? 0; - - /// - /// The total number of submeshes. - /// - public int GetSubmeshCount(MeshSection section) - { - var count = GetSubmeshCount(); - if (opaqueSubmeshCount == null) return count; - var opaque = opaqueSubmeshCount[0]; - - return section == MeshSection.Opaque - ? opaque - : count - opaque; - } - - public int GetIndexStart(MeshSection section) - { - if (opaqueSubmeshCount == null) return 0; - if (section == MeshSection.Opaque) return 0; - var opaque = opaqueSubmeshCount[0]; - return GetSubmeshIndexStart(opaque); - } - - public int GetIndexEnd(MeshSection section) - { - if (opaqueSubmeshCount == null) return indices.Length; - if (section == MeshSection.Transparent) return indices.Length; - var opaque = opaqueSubmeshCount[0]; - return GetSubmeshIndexEnd(opaque - 1); - } - - public int GetIndexCount(MeshSection section) - { - return GetIndexEnd(section) - GetIndexStart(section); - } - - /// - /// The total number of indices. - /// - public int GetIndexCount() => indices?.Length ?? 0; - - public int GetVertexStart(MeshSection section) - { - if (opaqueSubmeshCount == null) return 0; - if (submeshVertexOffsets == null) return 0; - if (section == MeshSection.Opaque) return 0; - var opaque = opaqueSubmeshCount[0]; - return GetSubmeshVertexStart(opaque); - } - - public int GetVertexEnd(MeshSection section) - { - if (opaqueSubmeshCount == null) return positions.Length; - if (submeshVertexOffsets == null) return positions.Length; - if (section == MeshSection.Transparent) return positions.Length; - var opaque = opaqueSubmeshCount[0]; - return GetSubmeshVertexEnd(opaque - 1); - } - - public int GetVertexCount(MeshSection section) - { - return GetVertexEnd(section) - GetVertexStart(section); - } - - /// - /// The total number of vertices. - /// - public int GetVertexCount() => (positions?.Length ?? 0); - - - /// - /// The total number of materials. - /// - public int GetMaterialCount() => materialColors?.Length ?? 0; - - public int GetSubmeshIndexStart(int submesh) - { - return submeshIndexOffsets[submesh]; - } - - public int GetSubmeshIndexEnd(int submesh) - { - return submesh + 1 < GetSubmeshCount() ? submeshIndexOffsets[submesh + 1] : GetIndexCount(); - } - - public int GetSubmeshIndexCount(int submesh) - { - return GetSubmeshIndexEnd(submesh) - GetSubmeshIndexStart(submesh); - } - - public int GetSubmeshVertexStart(int submesh) - { - return submeshVertexOffsets[submesh]; - } - - public int GetSubmeshVertexEnd(int submesh) - { - return submesh + 1 < GetSubmeshCount() ? submeshVertexOffsets[submesh + 1] : GetVertexCount(); - } - - public int GetSubmeshVertexCount(int submesh) - { - return GetSubmeshVertexEnd(submesh) - GetSubmeshVertexStart(submesh); - } - } -} diff --git a/src/cs/vim/Vim.Format.Vimx/G3dScene.cs b/src/cs/vim/Vim.Format.Vimx/G3dScene.cs deleted file mode 100644 index ad4522ea..00000000 --- a/src/cs/vim/Vim.Format.Vimx/G3dScene.cs +++ /dev/null @@ -1,70 +0,0 @@ -using System.IO; -using Vim.G3dNext.Attributes; -using Vim.Math3d; -using Vim.G3dNext; -using Vim.BFast; -/* -namespace Vim.Format.Vimx -{ - public class G3dScene - { - public G3DNext source; - - // instances - public int[] instanceFiles; - public int[] instanceIndices; - public int[] instanceNodes; - public int[] instanceGroups; - public long[] instanceTags; - public ushort[] instanceFlags; - public Vector3[] instanceMins; - public Vector3[] instanceMaxs; - - //mesh - public int[] meshInstanceCounts; - public int[] meshVertexCounts; - public int[] meshIndexCounts; - - // mesh opaque - public int[] meshOpaqueVertexCounts; - public int[] meshOpaqueIndexCounts; - - public G3dScene() - { - this.source = new G3DNext(); - } - - public G3dScene(G3DNext g3d) - { - this.source = g3d; - - // instances - instanceFiles = g3d.AttributeCollection.InstanceFilesAttribute.TypedData; - instanceIndices = g3d.AttributeCollection.InstanceIndicesAttribute.TypedData; - instanceNodes = g3d.AttributeCollection.InstanceNodesAttribute.TypedData; - instanceGroups = g3d.AttributeCollection.InstanceGroupsAttribute.TypedData; - instanceTags = g3d.AttributeCollection.InstanceTagsAttribute.TypedData; - instanceFlags = g3d.AttributeCollection.InstanceFlagsAttribute.TypedData; - instanceMins = g3d.AttributeCollection.InstanceMinsAttribute.TypedData; - instanceMaxs = g3d.AttributeCollection.InstanceMaxsAttribute.TypedData; - - // meshes - meshInstanceCounts = g3d.AttributeCollection.MeshInstanceCountsAttribute.TypedData; - meshIndexCounts = g3d.AttributeCollection.MeshIndexCountsAttribute.TypedData; - meshVertexCounts = g3d.AttributeCollection.MeshVertexCountsAttribute.TypedData; - - // meshes opaque - meshOpaqueIndexCounts = g3d.AttributeCollection.MeshOpaqueIndexCountsAttribute.TypedData; - meshOpaqueVertexCounts = g3d.AttributeCollection.MeshOpaqueVertexCountsAttribute.TypedData; - } - - public void Write(string path, string name) - { - var p = Path.Combine(path, $"{name}_index.g3d"); - source.ToBFast().Write(p); - } - - public int MeshCount => this.meshInstanceCounts.Length; - } -} -*/ \ No newline at end of file diff --git a/src/cs/vim/Vim.Format.Vimx/G3dVim.cs b/src/cs/vim/Vim.Format.Vimx/G3dVim.cs deleted file mode 100644 index 351f5a1a..00000000 --- a/src/cs/vim/Vim.Format.Vimx/G3dVim.cs +++ /dev/null @@ -1,288 +0,0 @@ -using System; -using System.IO; -using System.Linq; -using Vim.Math3d; -using Vim.G3dNext.Attributes; -using Vim.G3dNext; - -namespace Vim.Format.Vimx -{ - public class G3dVim - { - public G3DNext source; - - // instances - public int[] instanceMeshes; - public Matrix4x4[] instanceTransforms; - public int[] instanceParents; - public ushort[] instanceFlags; - - //mesh - public int[] meshSubmeshOffsets; - - //submesh - public int[] submeshIndexOffsets; - public int[] submeshMaterials; - - public int[] indices; - public Vector3[] vertices; - - // materials - public Vector4[] materialColors; - public float[] materialGlossiness; - public float[] materialSmoothness; - - // shapes - public Vector3[] shapeVertices; - public int[] shapeVertexOffsets; - public Vector4[] shapeColors; - public float[] shapeWidth; - - // Computed fields - public int[] meshVertexOffsets; - - - public G3dVim() - { - this.source = new G3DNext(); - } - public G3dVim(G3DNext g3d) - { - this.source = g3d; - - // instances - instanceMeshes = g3d.AttributeCollection.InstanceMeshAttribute.TypedData; - instanceTransforms = g3d.AttributeCollection.InstanceTransformAttribute.TypedData; - instanceParents = g3d.AttributeCollection.InstanceParentAttribute.TypedData; - instanceFlags = g3d.AttributeCollection.InstanceFlagsAttribute.TypedData; - if (instanceFlags.Length < instanceMeshes.Length) - { - instanceFlags = new ushort[instanceMeshes.Length]; - } - - // meshes - meshSubmeshOffsets = g3d.AttributeCollection.MeshSubmeshOffsetAttribute.TypedData; - - // submeshes - submeshIndexOffsets = g3d.AttributeCollection.SubmeshIndexOffsetAttribute.TypedData; - submeshMaterials = g3d.AttributeCollection.SubmeshMaterialAttribute.TypedData; - - // vertices - indices = g3d.AttributeCollection.IndexAttribute.TypedData; - vertices = g3d.AttributeCollection.VertexAttribute.TypedData; - - // materials - materialColors = g3d.AttributeCollection.MaterialColorAttribute.TypedData; - materialGlossiness = g3d.AttributeCollection.MaterialGlossinessAttribute.TypedData; - materialSmoothness = g3d.AttributeCollection.MaterialSmoothnessAttribute.TypedData; - - // shapes - shapeVertexOffsets = g3d.AttributeCollection.ShapeVertexOffsetAttribute.TypedData; - shapeVertices = g3d.AttributeCollection.ShapeVertexAttribute.TypedData; - shapeColors = g3d.AttributeCollection.ShapeColorAttribute.TypedData; - shapeWidth = g3d.AttributeCollection.ShapeWidthAttribute.TypedData; - - // computed fields - meshVertexOffsets = ComputeMeshVertexOffsets(); - } - - public bool Equals(G3dVim other) - { - // instances - return - instanceMeshes.SequenceEqual(other.instanceMeshes) && - instanceTransforms.SequenceEqual(other.instanceTransforms) && - instanceParents.SequenceEqual(other.instanceParents) && - instanceFlags.SequenceEqual(other.instanceFlags) && - - //mesh - meshSubmeshOffsets.SequenceEqual(other.meshSubmeshOffsets) && - - //submesh - submeshIndexOffsets.SequenceEqual(other.submeshIndexOffsets) && - submeshMaterials.SequenceEqual(other.submeshMaterials) && - - indices.SequenceEqual(other.indices) && - vertices.SequenceEqual(other.vertices) && - - // materials - materialColors.SequenceEqual(other.materialColors) && - materialGlossiness.SequenceEqual(other.materialGlossiness) && - materialSmoothness.SequenceEqual(other.materialSmoothness) && - - // shapes - shapeVertices.SequenceEqual(other.shapeVertices) && - shapeVertexOffsets.SequenceEqual(other.shapeVertexOffsets) && - shapeColors.SequenceEqual(shapeColors) && - shapeWidth.SequenceEqual(other.shapeWidth); - } - - public G3dMaterials ToG3dMaterials() - { - return G3dMaterials.FromArrays( - materialColors, - materialGlossiness, - materialSmoothness - ); - } - - public static G3dVim FromBFast2(BFastNext.BFastNext bfast) - { - var next = G3DNext.ReadBFast(bfast); - return new G3dVim(next); - } - - public static G3dVim FromPath2(string path) - { - var next = G3DNext.ReadBFast(path); - return new G3dVim(next); - } - - public static G3dVim ReadFromVim(string vimPath) - { - var file = new FileStream(vimPath, FileMode.Open); - var bfast = new BFastNext.BFastNext(file); - var geometry = bfast.GetBFast("geometry"); - return FromBFast(geometry); - } - - public static G3dVim FromBFast(BFastNext.BFastNext bfast) - { - var g3d = G3DNext.ReadBFast(bfast); - return new G3dVim(g3d); - } - - private int[] ComputeMeshVertexOffsets() - { - var result = new int[GetMeshCount()]; - for (var m = 0; m < result.Length; m++) - { - var min = int.MaxValue; - var start = GetMeshIndexStart(m); - var end = GetMeshIndexEnd(m); - for (var i = start; i < end; i++) - { - min = Math.Min(min, indices[i]); - } - result[m] = min; - } - return result; - } - - public int GetTriangleCount() - { - return GetIndexCount() / 3; - } - - /// - /// The total number of instances. - /// - public int GetInstanceCount() => instanceTransforms?.Length ?? 0; - - #region meshes - /// - /// The total number of meshes. - /// - public int GetMeshCount() => meshSubmeshOffsets?.Length ?? 0; - - public int GetMeshIndexStart(int mesh) - { - var submesh = GetMeshSubmeshStart(mesh); - return GetSubmeshIndexStart(submesh); - } - - public int GetMeshIndexEnd(int mesh) - { - var submesh = GetMeshSubmeshEnd(mesh) - 1; - return GetSubmeshIndexEnd(submesh); - } - - public int GetMeshIndexCount(int mesh) - { - return GetMeshIndexEnd(mesh) - GetMeshIndexStart(mesh); - } - - public int GetMeshVertexStart(int mesh) - { - return meshVertexOffsets[mesh]; - } - - public int GetMeshVertexEnd(int mesh) - { - return mesh + 1 < GetMeshCount() ? meshVertexOffsets[mesh + 1] : vertices.Length; - } - - public int GetMeshVertexCount(int mesh) - { - return GetMeshVertexEnd(mesh) - GetMeshVertexStart(mesh); - } - - public int GetMeshSubmeshStart(int mesh) - { - return meshSubmeshOffsets[mesh]; - } - - public int GetMeshSubmeshEnd(int mesh) - { - return mesh + 1 < GetMeshCount() - ? meshSubmeshOffsets[mesh + 1] - : GetSubmeshCount(); - } - - public int GetMeshSubmeshCount(int mesh) - { - return GetMeshSubmeshEnd(mesh) - GetMeshSubmeshStart(mesh); - } - - #endregion - - #region submesh - - /// - /// The total number of submeshes. - /// - public int GetSubmeshCount() => submeshIndexOffsets?.Length ?? 0; - - public int GetSubmeshIndexStart(int submesh) - { - return submeshIndexOffsets[submesh]; - } - - public int GetSubmeshIndexEnd(int submesh) - { - return submesh + 1 < GetSubmeshCount() ? submeshIndexOffsets[submesh + 1] : GetIndexCount(); - } - - public int GetSubmeshIndexCount(int submesh) - { - return GetSubmeshIndexEnd(submesh) - GetSubmeshIndexStart(submesh); - } - - #endregion - - /// - /// The total number of indices. - /// - public int GetIndexCount() => indices?.Length ?? 0; - - /// - /// The total number of vertices. - /// - public int GetVertexCount() => vertices?.Length ?? 0; - - /// - /// The total number of materials. - /// - public int GetMaterialCount() => materialColors?.Length ?? 0; - - /// - /// The total number of shapes. - /// - public int GetShapeCount() => shapeVertexOffsets?.Length ?? 0; - - /// - /// The total number of shape vertices. - /// - public int GetShapeVertexCount() => shapeVertices?.Length ?? 0; - } -} diff --git a/src/cs/vim/Vim.Format.Vimx/G3dVimFilter.cs b/src/cs/vim/Vim.Format.Vimx/G3dVimFilter.cs deleted file mode 100644 index 9a6f55b1..00000000 --- a/src/cs/vim/Vim.Format.Vimx/G3dVimFilter.cs +++ /dev/null @@ -1,152 +0,0 @@ -using System.Collections.Generic; -using Vim.Math3d; - -namespace Vim.Format.Vimx -{ - internal static class G3dVimFilter - { - /// - /// Returns a new G3d which only contains the instances provided as filter. - /// Delete this eventually if it finds no usage. - /// Was developped for server side file splitting spike. - /// - public static G3dVim Filter(this G3dVim g3d, int[] instances) - { - var vim = new G3dVim(); - var instanceSet = new HashSet(instances); - - // Instances - var instanceMeshes = new int[instances.Length]; - var instanceFlags = new ushort[instances.Length]; - var instanceTransforms = new Matrix4x4[instances.Length]; - var instance_i = 0; - for (var i = 0; i < g3d.GetInstanceCount(); i++) - { - if (!instanceSet.Contains(i)) continue; - instanceFlags[instance_i] = g3d.instanceFlags[i]; - instanceMeshes[instance_i] = g3d.instanceMeshes[i]; - instanceTransforms[instance_i] = g3d.instanceTransforms[i]; - instance_i++; - } - - // Meshes - var meshMap = new Dictionary(); - var meshSet = new HashSet(instanceMeshes); - meshSet.Remove(-1); - var meshSubmeshes = new int[meshSet.Count]; - - var last = -1; - var mesh_i = 0; - for (var i = 0; i < g3d.GetMeshCount(); i++) - { - if (!meshSet.Contains(i)) continue; - - var offset = mesh_i > 0 ? meshSubmeshes[mesh_i - 1] : 0; - var lastCount = last < 0 ? 0 : g3d.GetMeshSubmeshCount(last); - meshSubmeshes[mesh_i] = lastCount + offset; - meshMap[i] = mesh_i; - last = i; - mesh_i++; - } - - // Remap Instance Meshes - for (var i = 0; i < instanceMeshes.Length; i++) - { - instanceMeshes[i] = meshMap.TryGetValue(instanceMeshes[i], out var value) ? value : -1; - } - - // Mesh Attributes Count - var submeshCount = 0; - var positionCount = 0; - var indiceCount = 0; - for (var m = 0; m < g3d.GetMeshCount(); m++) - { - if (!meshSet.Contains(m)) continue; - positionCount += g3d.GetMeshVertexCount(m); - indiceCount += g3d.GetMeshIndexCount(m); - submeshCount += g3d.GetMeshSubmeshCount(m); - } - - // Meshes - var indices_i = 0; - var positions_i = 0; - var submesh_i = 0; - var submeshOffset = 0; - var meshOffset = 0; - var submeshIndexOffsets = new int[submeshCount]; - var submeshMaterials = new int[submeshCount]; - var positions = new Vector3[positionCount]; - var indices = new int[indiceCount]; - - for (var mesh = 0; mesh < g3d.GetMeshCount(); mesh++) - { - if (!meshSet.Contains(mesh)) continue; - - // submeshes - var subStart = g3d.GetMeshSubmeshStart(mesh); - var subEnd = g3d.GetMeshSubmeshEnd(mesh); - - for (var j = subStart; j < subEnd; j++) - { - var start = g3d.submeshIndexOffsets[subStart]; - submeshIndexOffsets[submesh_i] = g3d.submeshIndexOffsets[j] - start + submeshOffset; - submeshMaterials[submesh_i] = g3d.submeshMaterials[j]; - submesh_i++; - } - submeshOffset += g3d.GetMeshIndexCount(mesh); - - // indices - var indexStart = g3d.GetMeshIndexStart(mesh); - var indexEnd = g3d.GetMeshIndexEnd(mesh); - for (var j = indexStart; j < indexEnd; j++) - { - indices[indices_i++] = g3d.indices[j] - g3d.GetMeshVertexStart(mesh) + meshOffset; - } - meshOffset += g3d.GetMeshVertexCount(mesh); - - // vertices - var vertexStart = g3d.GetMeshVertexStart(mesh); - var vertexEnd = g3d.GetMeshVertexEnd(mesh); - for (var j = vertexStart; j < vertexEnd; j++) - { - positions[positions_i++] = g3d.vertices[j]; - } - } - - // Material Colors - var color_i = 0; - var materialSet = new HashSet(submeshMaterials); - var materialMap = new Dictionary(); - var materialColors = new Vector4[materialSet.Count]; - - for (var i = 0; i < g3d.GetMaterialCount(); i++) - { - if (materialSet.Contains(i)) - { - materialMap[i] = color_i; - materialColors[color_i] = g3d.materialColors[i]; - color_i++; - } - } - - // Remap Submesh Materials - for (var i = 0; i < submeshMaterials.Length; i++) - { - submeshMaterials[i] = submeshMaterials[i] < 0 ? -1 : materialMap[submeshMaterials[i]]; - } - - return new G3dVim() - { - instanceFlags= instanceFlags, - instanceMeshes= instanceMeshes, - instanceTransforms= instanceTransforms, - meshSubmeshOffsets= meshSubmeshes, - submeshIndexOffsets= submeshIndexOffsets, - submeshMaterials= submeshMaterials, - indices= indices, - vertices= positions, - materialColors= materialColors - }; - } - } -} \ No newline at end of file diff --git a/src/cs/vim/Vim.Format.Vimx/Vimx.cs b/src/cs/vim/Vim.Format.Vimx/Vimx.cs index 5c78a200..f90e4c2e 100644 --- a/src/cs/vim/Vim.Format.Vimx/Vimx.cs +++ b/src/cs/vim/Vim.Format.Vimx/Vimx.cs @@ -1,85 +1,74 @@ -using System.Collections.Generic; -using System.Linq; -using Vim.BFastNext; -using Vim.Format.ObjectModel; +using System.Linq; +using Vim.BFastNextNS; +using Vim.G3dNext; using Vim.G3dNext.Attributes; -namespace Vim.Format.Vimx +namespace Vim.Format.VimxNS { public static class BufferNames { - public const string Header = Format.BufferNames.Header; + public const string Header = "header"; + public const string Meta = "meta"; public const string Scene = "scene"; public const string Materials = "materials"; public static string Mesh(int mesh) => $"mesh_{mesh}"; } - public class Vimx + public static class BufferCompression { - public VimxHeader header; - public G3dScene2 scene; - public G3dMaterials materials; - public G3dMesh[] meshes; - - Vimx(VimxHeader header, G3dScene2 scene, G3dMaterials materials, G3dMesh[] meshes) - { - this.header = header; - this.scene = scene; - this.materials = materials; - this.meshes = meshes; - } + public const bool Header = false; + public const bool Meta = false; + public const bool Scene = true; + public const bool Materials = true; + public const bool Meshes = true; + } - public static Vimx FromVim(string vimPath) - { - var vim = VimScene.LoadVim(vimPath, new Format.LoadOptions() - { - SkipAssets = true, - SkipGeometry = true, - }); - var g3d = G3dVim.ReadFromVim(vimPath); - return FromVim(g3d, vim.DocumentModel); - } + public class Vimx + { + public readonly VimxHeader Header; + public readonly MetaHeader Meta; + public readonly G3dScene Scene; + public readonly G3dMaterials Materials; + public readonly G3dMesh[] Meshes; - public static Vimx FromVim(G3dVim g3d, DocumentModel bim) + public Vimx(VimxHeader header, MetaHeader meta, G3dScene scene, G3dMaterials materials, G3dMesh[] meshes) { - var meshes = g3d.ToG3dMeshes().OrderByBim(bim).ToArray(); - var scene = g3d.ToG3dScene(bim, meshes); - var materials = g3d.ToG3dMaterials(); - var header = VimxHeader.CreateDefault(); - return new Vimx(header, scene, materials, meshes); + Meta = meta; + Header = header; + Scene = scene; + Materials = materials; + Meshes = meshes; } - public static Vimx FromBFast(BFastNext.BFastNext bfast) + public Vimx(BFastNext bfast) { - var headerBytes = bfast.GetArray("header"); - var header = VimxHeader.FromBytes(headerBytes); - - var bfastScene = bfast.GetBFast("scene", inflate: true); - var scene = new G3dScene2(bfastScene); + Header = new VimxHeader(bfast.GetArray(BufferNames.Header)); - var bfastMaterials = bfast.GetBFast("materials", inflate: true); - var materials = G3dMaterials.FromBFast(bfastMaterials); + Scene = new G3dScene( + bfast.GetBFast(BufferNames.Scene, BufferCompression.Scene) + ); - var meshes = Enumerable.Range(0, scene.MeshIndexCounts.Length).Select(i => - { - var bfastMesh = bfast.GetBFast(BufferNames.Mesh(i), inflate: true); - return G3dMesh.FromBFast(bfastMesh); - }).ToArray(); + Materials = new G3dMaterials( + bfast.GetBFast(BufferNames.Materials, BufferCompression.Materials) + ); - return new Vimx(header, scene, materials, meshes); + Meshes = Enumerable.Range(0, Scene.MeshIndexCounts.Length).Select(i => + new G3dMesh(bfast.GetBFast(BufferNames.Mesh(i), BufferCompression.Meshes)) + ).ToArray(); } public static Vimx FromPath(string path) - => path.ReadBFast(FromBFast); + => path.ReadBFast((b) => new Vimx(b)); - public void Write(string path) + public BFastNext ToBFast() { - var bfast = new BFastNext.BFastNext(); - bfast.AddArray(BufferNames.Header, header.ToBytes()); - bfast.SetBFast(BufferNames.Scene, scene.source.ToBFast(), deflate: true); - bfast.SetBFast(BufferNames.Materials, materials.source.ToBFast(), deflate: true); - bfast.SetBFast(BufferNames.Mesh, meshes.Select(m => m.source.ToBFast()), deflate: true); - bfast.Write(path); + var bfast = new BFastNext(); + bfast.SetArray(BufferNames.Meta, MetaHeader.Default.ToBytes()); + bfast.SetArray(BufferNames.Header, Header.ToBytes()); + bfast.SetBFast(BufferNames.Scene, Scene.ToBFast(), BufferCompression.Scene); + bfast.SetBFast(BufferNames.Materials, Materials.ToBFast(), BufferCompression.Materials); + bfast.SetBFast(BufferNames.Mesh, Meshes.Select(m => m.ToBFast()), BufferCompression.Meshes); + return bfast; } } } diff --git a/src/cs/vim/Vim.Format.Vimx/VimxHeader.cs b/src/cs/vim/Vim.Format.Vimx/VimxHeader.cs index fe8fdd20..c723688b 100644 --- a/src/cs/vim/Vim.Format.Vimx/VimxHeader.cs +++ b/src/cs/vim/Vim.Format.Vimx/VimxHeader.cs @@ -1,11 +1,8 @@ -using System; -using System.Collections.Generic; -using System.IO; +using System.Collections.Generic; using System.Text; -using Vim.BFast; using Vim.Util; -namespace Vim.Format.Vimx +namespace Vim.Format.VimxNS { public class VimxHeader : SerializableHeader { @@ -16,7 +13,14 @@ public VimxHeader(string generator, SerializableVersion schema, string versionSt public VimxHeader(SerializableHeader header) : this(header.Generator, header.Schema, header.FileFormatVersion.ToString()) { + } + + public VimxHeader(string header) : this(Parse(header)) + { + } + public VimxHeader(byte[] bytes) : this(Encoding.UTF8.GetString(bytes)) + { } public static VimxHeader CreateDefault() @@ -27,11 +31,5 @@ public static VimxHeader CreateDefault() CurrentVimFormatVersion.ToString() ); } - - public static VimxHeader FromBytes(byte[] bytes) - { - var str = Encoding.UTF8.GetString(bytes); - return new VimxHeader(Parse(str)); - } } } diff --git a/src/cs/vim/Vim.Vimx.Test/TestUtils.cs b/src/cs/vim/Vim.Vimx.Test/TestUtils.cs index f995dc4e..6d77f6a8 100644 --- a/src/cs/vim/Vim.Vimx.Test/TestUtils.cs +++ b/src/cs/vim/Vim.Vimx.Test/TestUtils.cs @@ -8,10 +8,7 @@ namespace Vim.G3dNext.Tests { public static class TestUtils { - public static readonly string ProjectFolder = VimFormatRepoPaths.ProjDir; - public static string RootFolder = Path.Combine(ProjectFolder, "..", ".."); - public static string TestInputFolder = Path.Combine(RootFolder, "data"); - public static string TestOutputFolder = Path.Combine(RootFolder, "out"); + public static string ResidencePath = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); /// @@ -22,7 +19,7 @@ public static string PrepareTestDir([CallerMemberName] string testName = null) if (testName == null) throw new ArgumentException(nameof(testName)); - var testDir = Path.Combine(TestOutputFolder, testName); + var testDir = Path.Combine(VimFormatRepoPaths.OutDir, testName); // Prepare the test directory if (Directory.Exists(testDir)) @@ -98,23 +95,21 @@ private static long GetMemoryConsumption(Action action) return GC.GetTotalMemory(true) - memBefore; } - public static G3DNext CreateTestG3d() + public static VimAttributeCollection CreateTestG3d() { - var g3d = new G3DNext(); - var attrs = g3d.AttributeCollection; - - attrs.CornersPerFaceAttribute.TypedData = new int[] { 3 }; - attrs.VertexAttribute.TypedData = new Vector3[] { Vector3.Zero, Vector3.UnitX, Vector3.UnitY, Vector3.UnitZ }; - attrs.IndexAttribute.TypedData = new int[] { 0, 1, 2, 0, 3, 2, 1, 3, 2 }; - attrs.SubmeshIndexOffsetAttribute.TypedData = new int[] { 0, 3, 6 }; - attrs.SubmeshMaterialAttribute.TypedData = new int[] { 0 }; - attrs.MeshSubmeshOffsetAttribute.TypedData = new int[] { 0 }; - attrs.InstanceTransformAttribute.TypedData = new Matrix4x4[] { Matrix4x4.Identity }; - attrs.InstanceMeshAttribute.TypedData = new int[] { 0 }; - attrs.InstanceParentAttribute.TypedData = new int[] { -1 }; - attrs.MaterialColorAttribute.TypedData = new Vector4[] { new Vector4(0.25f, 0.5f, 0.75f, 1) }; - attrs.MaterialGlossinessAttribute.TypedData = new float[] { .95f }; - attrs.MaterialSmoothnessAttribute.TypedData = new float[] { .5f }; + var g3d = new VimAttributeCollection(); + + g3d.PositionsAttribute.TypedData = new Vector3[] { Vector3.Zero, Vector3.UnitX, Vector3.UnitY, Vector3.UnitZ }; + g3d.IndicesAttribute.TypedData = new int[] { 0, 1, 2, 0, 3, 2, 1, 3, 2 }; + g3d.SubmeshIndexOffsetsAttribute.TypedData = new int[] { 0, 3, 6 }; + g3d.SubmeshMaterialsAttribute.TypedData = new int[] { 0 }; + g3d.MeshSubmeshOffsetsAttribute.TypedData = new int[] { 0 }; + g3d.InstanceTransformsAttribute.TypedData = new Matrix4x4[] { Matrix4x4.Identity }; + g3d.InstanceMeshesAttribute.TypedData = new int[] { 0 }; + g3d.InstanceParentsAttribute.TypedData = new int[] { -1 }; + g3d.MaterialColorsAttribute.TypedData = new Vector4[] { new Vector4(0.25f, 0.5f, 0.75f, 1) }; + g3d.MaterialGlossinessAttribute.TypedData = new float[] { .95f }; + g3d.MaterialSmoothnessAttribute.TypedData = new float[] { .5f }; g3d.Validate(); diff --git a/src/cs/vim/Vim.Vimx.Test/Vim.Format.Vimx.Test.csproj b/src/cs/vim/Vim.Vimx.Test/Vim.Format.Vimx.Test.csproj index d918e4f3..8e4384f2 100644 --- a/src/cs/vim/Vim.Vimx.Test/Vim.Format.Vimx.Test.csproj +++ b/src/cs/vim/Vim.Vimx.Test/Vim.Format.Vimx.Test.csproj @@ -1,4 +1,4 @@ - + net6.0 @@ -20,6 +20,7 @@ + diff --git a/src/cs/vim/Vim.Vimx.Test/VimG3dTests.cs b/src/cs/vim/Vim.Vimx.Test/VimG3dTests.cs index 12380f2b..13286724 100644 --- a/src/cs/vim/Vim.Vimx.Test/VimG3dTests.cs +++ b/src/cs/vim/Vim.Vimx.Test/VimG3dTests.cs @@ -1,9 +1,9 @@ using NUnit.Framework; using NUnit.Framework.Internal; using Vim.BFast; -using Vim.Format.Vimx; using Vim.G3dNext.Attributes; using Vim.Math3d; +using Vim.BFastNextNS; namespace Vim.G3dNext.Tests { @@ -13,7 +13,7 @@ public static class VimG3dTests [Test] public static void Can_Parse_Attributes() { - var attributeNames = new VimAttributeCollection().AttributeNames; + var attributeNames = new VimAttributeCollection().GetAttributeNames(); foreach (var name in attributeNames) { // Test that the attribute descriptor parsing works as intended. @@ -36,34 +36,31 @@ public static void Can_Read_Write_Triangle() var indices = new[] { 0, 1, 2 }; - var g3d1 = new G3DNext(); - var ac1 = g3d1.AttributeCollection; - ac1.CornersPerFaceAttribute.TypedData = new[] { 3 }; - ac1.VertexAttribute.TypedData = vertices; - ac1.IndexAttribute.TypedData = indices; + var g3d1 = new VimAttributeCollection(); + g3d1.PositionsAttribute.TypedData = vertices; + g3d1.IndicesAttribute.TypedData = indices; var memoryStream = new MemoryStream(); g3d1.ToBFast().Write(memoryStream); memoryStream.Seek(0, SeekOrigin.Begin); - var bfast = new BFastNext.BFastNext(memoryStream); + var bfast = new BFastNext(memoryStream); - var g3d2 = G3DNext.ReadBFast(bfast); + var g3d2 = new VimAttributeCollection(bfast); Assert.IsNotNull(g3d2); - var ac2 = g3d2.AttributeCollection; - Assert.AreEqual(3, ac2.VertexAttribute.Count); - Assert.AreEqual(3, ac2.IndexAttribute.Count); - Assert.AreEqual(0, ac2.MeshSubmeshOffsetAttribute.Count); - Assert.AreEqual(0, ac2.InstanceTransformAttribute.Count); + Assert.AreEqual(3, g3d2.PositionsAttribute.Count); + Assert.AreEqual(3, g3d2.IndicesAttribute.Count); + Assert.AreEqual(0, g3d2.MeshSubmeshOffsetsAttribute.Count); + Assert.AreEqual(0, g3d2.InstanceTransformsAttribute.Count); - Assert.AreEqual(vertices, ac2.VertexAttribute.TypedData); - Assert.AreEqual(indices, ac2.IndexAttribute.TypedData); + Assert.AreEqual(vertices, g3d2.PositionsAttribute.TypedData); + Assert.AreEqual(indices, g3d2.IndicesAttribute.TypedData); } [Test] public static void Can_Read_G3d_From_Vim() { - var g3d = G3dVim.ReadFromVim(TestUtils.ResidencePath); + var g3d = G3dVim.FromVim(TestUtils.ResidencePath); Assert.IsNotNull(g3d); } @@ -76,16 +73,16 @@ public static void Can_Ignore_Extra_Attributes() // Shows that extra attributes are ignored as they should. var memoryStream = new MemoryStream(); - var g3d = G3dVim.ReadFromVim(TestUtils.ResidencePath); - g3d.source.ToBFast().Write(memoryStream); + var g3d = G3dVim.FromVim(TestUtils.ResidencePath); + g3d.ToBFast().Write(memoryStream); memoryStream.Seek(0, SeekOrigin.Begin); - var bfast = new BFastNext.BFastNext(memoryStream); - var g3dMats = G3dMaterials.FromBFast(bfast); + var bfast = new BFastNext(memoryStream); + var g3dMats = new G3dMaterials(bfast); Assert.IsNotNull(g3dMats); - Assert.AreEqual(g3d.materialColors, g3dMats.materialColors); - Assert.AreEqual(g3d.materialGlossiness, g3dMats.materialGlossiness); - Assert.AreEqual(g3d.materialSmoothness, g3dMats.materialSmoothness); + Assert.AreEqual(g3d.MaterialColors, g3dMats.MaterialColors); + Assert.AreEqual(g3d.MaterialGlossiness, g3dMats.MaterialGlossiness); + Assert.AreEqual(g3d.MaterialSmoothness, g3dMats.MaterialSmoothness); } [Test] @@ -96,12 +93,12 @@ public static void Can_Write_And_Read() var g3dFilePath = Path.Combine(testDir, "test.g3d"); g3d.ToBFast().Write(g3dFilePath); - var result = G3DNext.ReadBFast(g3dFilePath); + var result = g3dFilePath.ReadBFast((b) => new VimAttributeCollection(b)); - foreach (var attributeName in result.AttributeCollection.AttributeNames) + foreach (var attributeName in result.GetAttributeNames()) { - var attr0 = g3d.AttributeCollection.Attributes[attributeName]; - var attr1 = result.AttributeCollection.Attributes[attributeName]; + var attr0 = g3d.Map[attributeName]; + var attr1 = result.Map[attributeName]; Assert.AreEqual(attr0.Data, attr1.Data); } } @@ -118,77 +115,70 @@ public static void Can_Merge_two_g3d() var g3dFilePath = Path.Combine(testDir!, "merged.g3d"); mergedG3d.ToBFast().Write(memoryStream); memoryStream.Seek(0, SeekOrigin.Begin); - var bfast = new BFastNext.BFastNext(memoryStream); + var bfast = new BFastNext(memoryStream); - var g3dResult = G3DNext.ReadBFast(bfast); + var g3dResult = new VimAttributeCollection(bfast); Assert.NotNull(g3d); - var mac = g3dResult.AttributeCollection; - - { - var merged = g3d.AttributeCollection.CornersPerFaceAttribute.TypedData; - Assert.AreEqual(merged, mac.CornersPerFaceAttribute.TypedData); - } - { - var merged = Enumerable.Repeat(g3d.AttributeCollection.VertexAttribute.TypedData, 2).SelectMany(v => v).ToArray(); - Assert.AreEqual(merged, mac.VertexAttribute.TypedData); + var merged = Enumerable.Repeat(g3d.PositionsAttribute.TypedData, 2).SelectMany(v => v).ToArray(); + Assert.AreEqual(merged, g3dResult.PositionsAttribute.TypedData); } { - var tmp = g3d.AttributeCollection.IndexAttribute.TypedData; - var merged = new[] { tmp, tmp.Select(i => i + g3d.AttributeCollection.VertexAttribute.Count).ToArray() }.SelectMany(v => v).ToArray(); - Assert.AreEqual(merged, mac.IndexAttribute.TypedData); + var tmp = g3d.IndicesAttribute.TypedData; + var merged = new[] { tmp, tmp.Select(i => i + g3d.PositionsAttribute.Count).ToArray() }.SelectMany(v => v).ToArray(); + Assert.AreEqual(merged, g3dResult.IndicesAttribute.TypedData); } { - var tmp = g3d.AttributeCollection.SubmeshIndexOffsetAttribute.TypedData; - var merged = new[] { tmp, tmp.Select(i => i + g3d.AttributeCollection.IndexAttribute.Count).ToArray() }.SelectMany(v => v).ToArray(); - Assert.AreEqual(merged, mac.SubmeshIndexOffsetAttribute.TypedData); + var tmp = g3d.SubmeshIndexOffsetsAttribute.TypedData; + var merged = new[] { tmp, tmp.Select(i => i + g3d.IndicesAttribute.Count).ToArray() }.SelectMany(v => v).ToArray(); + Assert.AreEqual(merged, g3dResult.SubmeshIndexOffsetsAttribute.TypedData); } { - var tmp = g3d.AttributeCollection.SubmeshMaterialAttribute.TypedData; - var merged = new[] { tmp, tmp.Select(i => i + g3d.AttributeCollection.MaterialColorAttribute.Count).ToArray() }.SelectMany(v => v).ToArray(); - Assert.AreEqual(merged, mac.SubmeshMaterialAttribute.TypedData); + var tmp = g3d.SubmeshMaterialsAttribute.TypedData; + var merged = new[] { tmp, tmp.Select(i => i + g3d.MaterialColorsAttribute.Count).ToArray() }.SelectMany(v => v).ToArray(); + Assert.AreEqual(merged, g3dResult.SubmeshMaterialsAttribute.TypedData); } { - var tmp = g3d.AttributeCollection.MeshSubmeshOffsetAttribute.TypedData; - var merged = new[] { tmp, tmp.Select(i => i + g3d.AttributeCollection.SubmeshIndexOffsetAttribute.Count).ToArray() }.SelectMany(v => v).ToArray(); - Assert.AreEqual(merged, mac.MeshSubmeshOffsetAttribute.TypedData); + var tmp = g3d.MeshSubmeshOffsetsAttribute.TypedData; + var merged = new[] { tmp, tmp.Select(i => i + g3d.SubmeshIndexOffsetsAttribute.Count).ToArray() }.SelectMany(v => v).ToArray(); + Assert.AreEqual(merged, g3dResult.MeshSubmeshOffsetsAttribute.TypedData); } { - var merged = Enumerable.Repeat(g3d.AttributeCollection.InstanceTransformAttribute.TypedData, 2).SelectMany(v => v).ToArray(); - Assert.AreEqual(merged, mac.InstanceTransformAttribute.TypedData); + var merged = Enumerable.Repeat(g3d.InstanceTransformsAttribute.TypedData, 2).SelectMany(v => v).ToArray(); + Assert.AreEqual(merged, g3dResult.InstanceTransformsAttribute.TypedData); } { - var tmp = g3d.AttributeCollection.InstanceMeshAttribute.TypedData; - var merged = new[] { tmp, tmp.Select(i => i + g3d.AttributeCollection.MeshSubmeshOffsetAttribute.Count).ToArray() }.SelectMany(v => v).ToArray(); - Assert.AreEqual(merged, mac.InstanceMeshAttribute.TypedData); + var tmp = g3d.InstanceMeshesAttribute.TypedData; + var merged = new[] { tmp, tmp.Select(i => i + g3d.MeshSubmeshOffsetsAttribute.Count).ToArray() }.SelectMany(v => v).ToArray(); + Assert.AreEqual(merged, g3dResult.InstanceMeshesAttribute.TypedData); } { - var merged = Enumerable.Repeat(g3d.AttributeCollection.InstanceParentAttribute.TypedData, 2).SelectMany(v => v).ToArray(); - Assert.AreEqual(merged, mac.InstanceParentAttribute.TypedData); + var merged = Enumerable.Repeat(g3d.InstanceParentsAttribute.TypedData, 2).SelectMany(v => v).ToArray(); + Assert.AreEqual(merged, g3dResult.InstanceParentsAttribute.TypedData); } { - var merged = Enumerable.Repeat(g3d.AttributeCollection.MaterialColorAttribute.TypedData, 2).SelectMany(v => v).ToArray(); - Assert.AreEqual(merged, mac.MaterialColorAttribute.TypedData); + var merged = Enumerable.Repeat(g3d.MaterialColorsAttribute.TypedData, 2).SelectMany(v => v).ToArray(); + Assert.AreEqual(merged, g3dResult.MaterialColorsAttribute.TypedData); } { - var merged = Enumerable.Repeat(g3d.AttributeCollection.MaterialGlossinessAttribute.TypedData, 2).SelectMany(v => v).ToArray(); - Assert.AreEqual(merged, mac.MaterialGlossinessAttribute.TypedData); + var merged = Enumerable.Repeat(g3d.MaterialGlossinessAttribute.TypedData, 2).SelectMany(v => v).ToArray(); + Assert.AreEqual(merged, g3dResult.MaterialGlossinessAttribute.TypedData); } { - var merged = Enumerable.Repeat(g3d.AttributeCollection.MaterialSmoothnessAttribute.TypedData, 2).SelectMany(v => v).ToArray(); - Assert.AreEqual(merged, mac.MaterialSmoothnessAttribute.TypedData); + var merged = Enumerable.Repeat(g3d.MaterialSmoothnessAttribute.TypedData, 2).SelectMany(v => v).ToArray(); + Assert.AreEqual(merged, g3dResult.MaterialSmoothnessAttribute.TypedData); } } } diff --git a/src/cs/vim/Vim.Vimx.Test/VimxActions.cs b/src/cs/vim/Vim.Vimx.Test/VimxActions.cs index 5d13cd74..73777e27 100644 --- a/src/cs/vim/Vim.Vimx.Test/VimxActions.cs +++ b/src/cs/vim/Vim.Vimx.Test/VimxActions.cs @@ -1,20 +1,27 @@ using NUnit.Framework; -using Vim.G3dNext.Tests; +using Vim.Format.VimxNS.Conversion; +using Vim.Util.Tests; -namespace Vim.Format.Vimx.Test +namespace Vim.Format.VimxNS.Actions { [TestFixture] public static class VimxActions { + + const string whiteleys = "_WHITELEYS-VIM-MAIN_detached.v1.2.42.vim"; + [Test] public static void ConvertVimToVimx() { - var input = TestUtils.ResidencePath; - var name = Path.GetFileNameWithoutExtension(TestUtils.ResidencePath); - var output = Path.Combine(TestUtils.TestOutputFolder, name + ".vimx"); + //var input = TestUtils.ResidencePath; + + var input = Path.Join(VimFormatRepoPaths.DataDir, whiteleys); + + var name = Path.GetFileNameWithoutExtension(input); + var output = Path.Combine(VimFormatRepoPaths.OutDir, name + ".vimx"); - var vimx = Vimx.FromVim(input); - vimx.Write(output); + var vimx = VimxConverter.FromVimPath(input); + vimx.ToBFast().Write(output); } } } diff --git a/src/cs/vim/Vim.Vimx.Test/VimxTests.cs b/src/cs/vim/Vim.Vimx.Test/VimxTests.cs index b18ab0db..8211144b 100644 --- a/src/cs/vim/Vim.Vimx.Test/VimxTests.cs +++ b/src/cs/vim/Vim.Vimx.Test/VimxTests.cs @@ -1,12 +1,12 @@ using NUnit.Framework; using NUnit.Framework.Internal; using Vim.BFast; -using Vim.Format.Vimx; -using Vim.G3dNext.Attributes; using Vim.G3dNext.Tests; using Vim.Math3d; +using Vim.Format.VimxNS.Conversion; +using Vim.Util.Tests; -namespace Vim.Format.Vimx.Tests +namespace Vim.Format.VimxNS.Tests { [TestFixture] public static class VimxTests @@ -16,15 +16,15 @@ public static void Can_Convert_And_Read_Vimx() { var input = TestUtils.ResidencePath; var name = Path.GetFileNameWithoutExtension(TestUtils.ResidencePath); - var output = Path.Combine(TestUtils.TestOutputFolder, name + ".vimx"); + var output = Path.Combine(VimFormatRepoPaths.OutDir, name + ".vimx"); - var vimx = Vimx.FromVim(input); - vimx.Write(output); + var vimx = VimxConverter.FromVimPath(input); + vimx.ToBFast().Write(output); var result = Vimx.FromPath(output); - Assert.AreEqual(vimx.scene.InstanceFiles, result.scene.InstanceFiles); - Assert.AreEqual(vimx.materials.materialColors, result.materials.materialColors); - Assert.AreEqual(vimx.meshes.Length, result.meshes.Length); + Assert.AreEqual(vimx.Scene.InstanceFiles, result.Scene.InstanceFiles); + Assert.AreEqual(vimx.Materials.MaterialColors, result.Materials.MaterialColors); + Assert.AreEqual(vimx.Meshes.Length, result.Meshes.Length); } From 61cfdafc98ea4d97a718a985c367c27e08db8245 Mon Sep 17 00:00:00 2001 From: simon Date: Fri, 29 Sep 2023 11:12:55 -0400 Subject: [PATCH 006/111] moved BFast.Next to bfast folder --- .../Vim.BFastNext.Tests.csproj | 2 +- src/cs/{ => bfast}/Vim.BFast.Next/BFastNext.cs | 0 .../Vim.BFast.Next/BFastNextExtensions.cs | 0 .../{ => bfast}/Vim.BFast.Next/BFastNextNode.cs | 6 +++--- .../{ => bfast}/Vim.BFast.Next/IBFastNextNode.cs | 0 .../Vim.BFast.Next/Vim.BFastNext.csproj | 2 +- src/cs/g3d/Vim.G3dNext/Vim.G3dNext.csproj | 2 +- src/cs/vim-format.sln | 16 ++++++++-------- .../vim/Vim.Format.Vimx/Vim.Format.Vimx.csproj | 2 +- 9 files changed, 15 insertions(+), 15 deletions(-) rename src/cs/{ => bfast}/Vim.BFast.Next/BFastNext.cs (100%) rename src/cs/{ => bfast}/Vim.BFast.Next/BFastNextExtensions.cs (100%) rename src/cs/{ => bfast}/Vim.BFast.Next/BFastNextNode.cs (96%) rename src/cs/{ => bfast}/Vim.BFast.Next/IBFastNextNode.cs (100%) rename src/cs/{ => bfast}/Vim.BFast.Next/Vim.BFastNext.csproj (75%) diff --git a/src/cs/Vim.BFastNext.Tests/Vim.BFastNext.Tests.csproj b/src/cs/Vim.BFastNext.Tests/Vim.BFastNext.Tests.csproj index fc43f265..40d6d429 100644 --- a/src/cs/Vim.BFastNext.Tests/Vim.BFastNext.Tests.csproj +++ b/src/cs/Vim.BFastNext.Tests/Vim.BFastNext.Tests.csproj @@ -18,8 +18,8 @@ + - diff --git a/src/cs/Vim.BFast.Next/BFastNext.cs b/src/cs/bfast/Vim.BFast.Next/BFastNext.cs similarity index 100% rename from src/cs/Vim.BFast.Next/BFastNext.cs rename to src/cs/bfast/Vim.BFast.Next/BFastNext.cs diff --git a/src/cs/Vim.BFast.Next/BFastNextExtensions.cs b/src/cs/bfast/Vim.BFast.Next/BFastNextExtensions.cs similarity index 100% rename from src/cs/Vim.BFast.Next/BFastNextExtensions.cs rename to src/cs/bfast/Vim.BFast.Next/BFastNextExtensions.cs diff --git a/src/cs/Vim.BFast.Next/BFastNextNode.cs b/src/cs/bfast/Vim.BFast.Next/BFastNextNode.cs similarity index 96% rename from src/cs/Vim.BFast.Next/BFastNextNode.cs rename to src/cs/bfast/Vim.BFast.Next/BFastNextNode.cs index 458fa8ca..b9776167 100644 --- a/src/cs/Vim.BFast.Next/BFastNextNode.cs +++ b/src/cs/bfast/Vim.BFast.Next/BFastNextNode.cs @@ -27,8 +27,8 @@ You won't leak anything - at least in the current implementation. public BFastNextNode(Stream stream, BFastRange range) { - this._stream = stream; - this._range = range; + _stream = stream; + _range = range; } public BFastNext AsBFast() @@ -64,7 +64,7 @@ public void Write(Stream stream) private static void CopyStream(Stream input, Stream output, int bytes) { - byte[] buffer = new byte[32768]; + var buffer = new byte[32768]; int read; while (bytes > 0 && (read = input.Read(buffer, 0, Math.Min(buffer.Length, bytes))) > 0) diff --git a/src/cs/Vim.BFast.Next/IBFastNextNode.cs b/src/cs/bfast/Vim.BFast.Next/IBFastNextNode.cs similarity index 100% rename from src/cs/Vim.BFast.Next/IBFastNextNode.cs rename to src/cs/bfast/Vim.BFast.Next/IBFastNextNode.cs diff --git a/src/cs/Vim.BFast.Next/Vim.BFastNext.csproj b/src/cs/bfast/Vim.BFast.Next/Vim.BFastNext.csproj similarity index 75% rename from src/cs/Vim.BFast.Next/Vim.BFastNext.csproj rename to src/cs/bfast/Vim.BFast.Next/Vim.BFastNext.csproj index 9c678ee3..9f8c5197 100644 --- a/src/cs/Vim.BFast.Next/Vim.BFastNext.csproj +++ b/src/cs/bfast/Vim.BFast.Next/Vim.BFastNext.csproj @@ -6,7 +6,7 @@ - + diff --git a/src/cs/g3d/Vim.G3dNext/Vim.G3dNext.csproj b/src/cs/g3d/Vim.G3dNext/Vim.G3dNext.csproj index 36394089..426db2f3 100644 --- a/src/cs/g3d/Vim.G3dNext/Vim.G3dNext.csproj +++ b/src/cs/g3d/Vim.G3dNext/Vim.G3dNext.csproj @@ -9,8 +9,8 @@ + - diff --git a/src/cs/vim-format.sln b/src/cs/vim-format.sln index 950f4fff..c7adbb82 100644 --- a/src/cs/vim-format.sln +++ b/src/cs/vim-format.sln @@ -57,11 +57,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vim.Format.Vimx", "vim\Vim. EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vim.Format.Vimx.Test", "vim\Vim.Vimx.Test\Vim.Format.Vimx.Test.csproj", "{BBF94CBD-CD39-49F5-979A-5C9E52C29330}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vim.BFastNext", "Vim.BFast.Next\Vim.BFastNext.csproj", "{4854AD71-8023-43DE-AB2F-D5F6DCFE4974}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vim.BFastNext.Tests", "Vim.BFastNext.Tests\Vim.BFastNext.Tests.csproj", "{3DBA3070-FCB7-405B-9272-F7C112BD92A8}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Vim.Format.Vimx.Conversion", "Vim.Format.Vimx.Conversion\Vim.Format.Vimx.Conversion.csproj", "{5527BC13-9D25-45A1-A52D-8656336542C0}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vim.Format.Vimx.Conversion", "Vim.Format.Vimx.Conversion\Vim.Format.Vimx.Conversion.csproj", "{5527BC13-9D25-45A1-A52D-8656336542C0}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vim.BFastNext", "bfast\Vim.BFast.Next\Vim.BFastNext.csproj", "{408884EA-3CE5-4A34-97F6-1F2D64A0E745}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -153,10 +153,6 @@ Global {BBF94CBD-CD39-49F5-979A-5C9E52C29330}.Debug|Any CPU.Build.0 = Debug|Any CPU {BBF94CBD-CD39-49F5-979A-5C9E52C29330}.Release|Any CPU.ActiveCfg = Release|Any CPU {BBF94CBD-CD39-49F5-979A-5C9E52C29330}.Release|Any CPU.Build.0 = Release|Any CPU - {4854AD71-8023-43DE-AB2F-D5F6DCFE4974}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4854AD71-8023-43DE-AB2F-D5F6DCFE4974}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4854AD71-8023-43DE-AB2F-D5F6DCFE4974}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4854AD71-8023-43DE-AB2F-D5F6DCFE4974}.Release|Any CPU.Build.0 = Release|Any CPU {3DBA3070-FCB7-405B-9272-F7C112BD92A8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {3DBA3070-FCB7-405B-9272-F7C112BD92A8}.Debug|Any CPU.Build.0 = Debug|Any CPU {3DBA3070-FCB7-405B-9272-F7C112BD92A8}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -165,6 +161,10 @@ Global {5527BC13-9D25-45A1-A52D-8656336542C0}.Debug|Any CPU.Build.0 = Debug|Any CPU {5527BC13-9D25-45A1-A52D-8656336542C0}.Release|Any CPU.ActiveCfg = Release|Any CPU {5527BC13-9D25-45A1-A52D-8656336542C0}.Release|Any CPU.Build.0 = Release|Any CPU + {408884EA-3CE5-4A34-97F6-1F2D64A0E745}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {408884EA-3CE5-4A34-97F6-1F2D64A0E745}.Debug|Any CPU.Build.0 = Debug|Any CPU + {408884EA-3CE5-4A34-97F6-1F2D64A0E745}.Release|Any CPU.ActiveCfg = Release|Any CPU + {408884EA-3CE5-4A34-97F6-1F2D64A0E745}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -191,9 +191,9 @@ Global {F0FFC990-6358-4B17-B878-C6CA087CDF3F} = {705B8FB2-D707-4527-91FC-0AADEDBA4D80} {B5C8E733-8D3F-45BD-BBBE-09A9F1965545} = {D639C635-01D1-48C4-89B5-1FD70F1AFEE9} {BBF94CBD-CD39-49F5-979A-5C9E52C29330} = {D639C635-01D1-48C4-89B5-1FD70F1AFEE9} - {4854AD71-8023-43DE-AB2F-D5F6DCFE4974} = {F3260C54-834F-4C74-A3B7-EAB622AFA492} {3DBA3070-FCB7-405B-9272-F7C112BD92A8} = {F3260C54-834F-4C74-A3B7-EAB622AFA492} {5527BC13-9D25-45A1-A52D-8656336542C0} = {D639C635-01D1-48C4-89B5-1FD70F1AFEE9} + {408884EA-3CE5-4A34-97F6-1F2D64A0E745} = {F3260C54-834F-4C74-A3B7-EAB622AFA492} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {7D1BF641-26E8-4809-B638-029241C51BE2} diff --git a/src/cs/vim/Vim.Format.Vimx/Vim.Format.Vimx.csproj b/src/cs/vim/Vim.Format.Vimx/Vim.Format.Vimx.csproj index 9831295a..c008c5ea 100644 --- a/src/cs/vim/Vim.Format.Vimx/Vim.Format.Vimx.csproj +++ b/src/cs/vim/Vim.Format.Vimx/Vim.Format.Vimx.csproj @@ -9,10 +9,10 @@ + - From 30ed18a9e3f7dbbda3a3c1b2d6f093d3ebe51b4b Mon Sep 17 00:00:00 2001 From: simon Date: Fri, 29 Sep 2023 11:16:29 -0400 Subject: [PATCH 007/111] moved BfastNext.Test to bfast folder --- .../Vim.BFastNext.Tests/BFastNextTests.cs | 0 .../Vim.BFastNext.Tests/Vim.BFastNext.Tests.csproj | 4 ++-- src/cs/vim-format.sln | 14 +++++++------- 3 files changed, 9 insertions(+), 9 deletions(-) rename src/cs/{ => bfast}/Vim.BFastNext.Tests/BFastNextTests.cs (100%) rename src/cs/{ => bfast}/Vim.BFastNext.Tests/Vim.BFastNext.Tests.csproj (80%) diff --git a/src/cs/Vim.BFastNext.Tests/BFastNextTests.cs b/src/cs/bfast/Vim.BFastNext.Tests/BFastNextTests.cs similarity index 100% rename from src/cs/Vim.BFastNext.Tests/BFastNextTests.cs rename to src/cs/bfast/Vim.BFastNext.Tests/BFastNextTests.cs diff --git a/src/cs/Vim.BFastNext.Tests/Vim.BFastNext.Tests.csproj b/src/cs/bfast/Vim.BFastNext.Tests/Vim.BFastNext.Tests.csproj similarity index 80% rename from src/cs/Vim.BFastNext.Tests/Vim.BFastNext.Tests.csproj rename to src/cs/bfast/Vim.BFastNext.Tests/Vim.BFastNext.Tests.csproj index 40d6d429..91f1af4e 100644 --- a/src/cs/Vim.BFastNext.Tests/Vim.BFastNext.Tests.csproj +++ b/src/cs/bfast/Vim.BFastNext.Tests/Vim.BFastNext.Tests.csproj @@ -18,8 +18,8 @@ - - + + diff --git a/src/cs/vim-format.sln b/src/cs/vim-format.sln index c7adbb82..e76e795f 100644 --- a/src/cs/vim-format.sln +++ b/src/cs/vim-format.sln @@ -57,12 +57,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vim.Format.Vimx", "vim\Vim. EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vim.Format.Vimx.Test", "vim\Vim.Vimx.Test\Vim.Format.Vimx.Test.csproj", "{BBF94CBD-CD39-49F5-979A-5C9E52C29330}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vim.BFastNext.Tests", "Vim.BFastNext.Tests\Vim.BFastNext.Tests.csproj", "{3DBA3070-FCB7-405B-9272-F7C112BD92A8}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vim.Format.Vimx.Conversion", "Vim.Format.Vimx.Conversion\Vim.Format.Vimx.Conversion.csproj", "{5527BC13-9D25-45A1-A52D-8656336542C0}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vim.BFastNext", "bfast\Vim.BFast.Next\Vim.BFastNext.csproj", "{408884EA-3CE5-4A34-97F6-1F2D64A0E745}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vim.BFastNext.Tests", "bfast\Vim.BFastNext.Tests\Vim.BFastNext.Tests.csproj", "{FD149D64-5905-4F7D-97A8-9F7DA18A257D}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -153,10 +153,6 @@ Global {BBF94CBD-CD39-49F5-979A-5C9E52C29330}.Debug|Any CPU.Build.0 = Debug|Any CPU {BBF94CBD-CD39-49F5-979A-5C9E52C29330}.Release|Any CPU.ActiveCfg = Release|Any CPU {BBF94CBD-CD39-49F5-979A-5C9E52C29330}.Release|Any CPU.Build.0 = Release|Any CPU - {3DBA3070-FCB7-405B-9272-F7C112BD92A8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {3DBA3070-FCB7-405B-9272-F7C112BD92A8}.Debug|Any CPU.Build.0 = Debug|Any CPU - {3DBA3070-FCB7-405B-9272-F7C112BD92A8}.Release|Any CPU.ActiveCfg = Release|Any CPU - {3DBA3070-FCB7-405B-9272-F7C112BD92A8}.Release|Any CPU.Build.0 = Release|Any CPU {5527BC13-9D25-45A1-A52D-8656336542C0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {5527BC13-9D25-45A1-A52D-8656336542C0}.Debug|Any CPU.Build.0 = Debug|Any CPU {5527BC13-9D25-45A1-A52D-8656336542C0}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -165,6 +161,10 @@ Global {408884EA-3CE5-4A34-97F6-1F2D64A0E745}.Debug|Any CPU.Build.0 = Debug|Any CPU {408884EA-3CE5-4A34-97F6-1F2D64A0E745}.Release|Any CPU.ActiveCfg = Release|Any CPU {408884EA-3CE5-4A34-97F6-1F2D64A0E745}.Release|Any CPU.Build.0 = Release|Any CPU + {FD149D64-5905-4F7D-97A8-9F7DA18A257D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FD149D64-5905-4F7D-97A8-9F7DA18A257D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FD149D64-5905-4F7D-97A8-9F7DA18A257D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FD149D64-5905-4F7D-97A8-9F7DA18A257D}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -191,9 +191,9 @@ Global {F0FFC990-6358-4B17-B878-C6CA087CDF3F} = {705B8FB2-D707-4527-91FC-0AADEDBA4D80} {B5C8E733-8D3F-45BD-BBBE-09A9F1965545} = {D639C635-01D1-48C4-89B5-1FD70F1AFEE9} {BBF94CBD-CD39-49F5-979A-5C9E52C29330} = {D639C635-01D1-48C4-89B5-1FD70F1AFEE9} - {3DBA3070-FCB7-405B-9272-F7C112BD92A8} = {F3260C54-834F-4C74-A3B7-EAB622AFA492} {5527BC13-9D25-45A1-A52D-8656336542C0} = {D639C635-01D1-48C4-89B5-1FD70F1AFEE9} {408884EA-3CE5-4A34-97F6-1F2D64A0E745} = {F3260C54-834F-4C74-A3B7-EAB622AFA492} + {FD149D64-5905-4F7D-97A8-9F7DA18A257D} = {F3260C54-834F-4C74-A3B7-EAB622AFA492} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {7D1BF641-26E8-4809-B638-029241C51BE2} From 84c9ce6b3f2afa7a986600b00ecddabdb9dbe06c Mon Sep 17 00:00:00 2001 From: simon Date: Fri, 29 Sep 2023 11:20:09 -0400 Subject: [PATCH 008/111] moved vimx.conversion to format folder --- .../Vim.Format.Vimx.Conversion.csproj | 15 --------------- src/cs/vim-format.sln | 14 +++++++------- .../Vim.Format.Vimx.Conversion/MeshesToScene.cs | 0 .../Vim.Format.Vimx.Conversion.csproj | 15 +++++++++++++++ .../Vim.Format.Vimx.Conversion/VimToMeshes.cs | 0 .../Vim.Format.Vimx.Conversion/VimxConverter.cs | 0 .../Vim.Format.Vimx.Conversion/VimxOrdering.cs | 0 .../vim/Vim.Vimx.Test/Vim.Format.Vimx.Test.csproj | 2 +- 8 files changed, 23 insertions(+), 23 deletions(-) delete mode 100644 src/cs/Vim.Format.Vimx.Conversion/Vim.Format.Vimx.Conversion.csproj rename src/cs/{ => vim}/Vim.Format.Vimx.Conversion/MeshesToScene.cs (100%) create mode 100644 src/cs/vim/Vim.Format.Vimx.Conversion/Vim.Format.Vimx.Conversion.csproj rename src/cs/{ => vim}/Vim.Format.Vimx.Conversion/VimToMeshes.cs (100%) rename src/cs/{ => vim}/Vim.Format.Vimx.Conversion/VimxConverter.cs (100%) rename src/cs/{ => vim}/Vim.Format.Vimx.Conversion/VimxOrdering.cs (100%) diff --git a/src/cs/Vim.Format.Vimx.Conversion/Vim.Format.Vimx.Conversion.csproj b/src/cs/Vim.Format.Vimx.Conversion/Vim.Format.Vimx.Conversion.csproj deleted file mode 100644 index 2fe0ebbd..00000000 --- a/src/cs/Vim.Format.Vimx.Conversion/Vim.Format.Vimx.Conversion.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - - netstandard2.0 - - - - - - - - - - - diff --git a/src/cs/vim-format.sln b/src/cs/vim-format.sln index e76e795f..9d839dae 100644 --- a/src/cs/vim-format.sln +++ b/src/cs/vim-format.sln @@ -57,12 +57,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vim.Format.Vimx", "vim\Vim. EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vim.Format.Vimx.Test", "vim\Vim.Vimx.Test\Vim.Format.Vimx.Test.csproj", "{BBF94CBD-CD39-49F5-979A-5C9E52C29330}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vim.Format.Vimx.Conversion", "Vim.Format.Vimx.Conversion\Vim.Format.Vimx.Conversion.csproj", "{5527BC13-9D25-45A1-A52D-8656336542C0}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vim.BFastNext", "bfast\Vim.BFast.Next\Vim.BFastNext.csproj", "{408884EA-3CE5-4A34-97F6-1F2D64A0E745}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vim.BFastNext.Tests", "bfast\Vim.BFastNext.Tests\Vim.BFastNext.Tests.csproj", "{FD149D64-5905-4F7D-97A8-9F7DA18A257D}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vim.Format.Vimx.Conversion", "vim\Vim.Format.Vimx.Conversion\Vim.Format.Vimx.Conversion.csproj", "{4C4F9826-0DEF-4A39-BFC8-A834522694A0}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -153,10 +153,6 @@ Global {BBF94CBD-CD39-49F5-979A-5C9E52C29330}.Debug|Any CPU.Build.0 = Debug|Any CPU {BBF94CBD-CD39-49F5-979A-5C9E52C29330}.Release|Any CPU.ActiveCfg = Release|Any CPU {BBF94CBD-CD39-49F5-979A-5C9E52C29330}.Release|Any CPU.Build.0 = Release|Any CPU - {5527BC13-9D25-45A1-A52D-8656336542C0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {5527BC13-9D25-45A1-A52D-8656336542C0}.Debug|Any CPU.Build.0 = Debug|Any CPU - {5527BC13-9D25-45A1-A52D-8656336542C0}.Release|Any CPU.ActiveCfg = Release|Any CPU - {5527BC13-9D25-45A1-A52D-8656336542C0}.Release|Any CPU.Build.0 = Release|Any CPU {408884EA-3CE5-4A34-97F6-1F2D64A0E745}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {408884EA-3CE5-4A34-97F6-1F2D64A0E745}.Debug|Any CPU.Build.0 = Debug|Any CPU {408884EA-3CE5-4A34-97F6-1F2D64A0E745}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -165,6 +161,10 @@ Global {FD149D64-5905-4F7D-97A8-9F7DA18A257D}.Debug|Any CPU.Build.0 = Debug|Any CPU {FD149D64-5905-4F7D-97A8-9F7DA18A257D}.Release|Any CPU.ActiveCfg = Release|Any CPU {FD149D64-5905-4F7D-97A8-9F7DA18A257D}.Release|Any CPU.Build.0 = Release|Any CPU + {4C4F9826-0DEF-4A39-BFC8-A834522694A0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4C4F9826-0DEF-4A39-BFC8-A834522694A0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4C4F9826-0DEF-4A39-BFC8-A834522694A0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4C4F9826-0DEF-4A39-BFC8-A834522694A0}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -191,9 +191,9 @@ Global {F0FFC990-6358-4B17-B878-C6CA087CDF3F} = {705B8FB2-D707-4527-91FC-0AADEDBA4D80} {B5C8E733-8D3F-45BD-BBBE-09A9F1965545} = {D639C635-01D1-48C4-89B5-1FD70F1AFEE9} {BBF94CBD-CD39-49F5-979A-5C9E52C29330} = {D639C635-01D1-48C4-89B5-1FD70F1AFEE9} - {5527BC13-9D25-45A1-A52D-8656336542C0} = {D639C635-01D1-48C4-89B5-1FD70F1AFEE9} {408884EA-3CE5-4A34-97F6-1F2D64A0E745} = {F3260C54-834F-4C74-A3B7-EAB622AFA492} {FD149D64-5905-4F7D-97A8-9F7DA18A257D} = {F3260C54-834F-4C74-A3B7-EAB622AFA492} + {4C4F9826-0DEF-4A39-BFC8-A834522694A0} = {D639C635-01D1-48C4-89B5-1FD70F1AFEE9} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {7D1BF641-26E8-4809-B638-029241C51BE2} diff --git a/src/cs/Vim.Format.Vimx.Conversion/MeshesToScene.cs b/src/cs/vim/Vim.Format.Vimx.Conversion/MeshesToScene.cs similarity index 100% rename from src/cs/Vim.Format.Vimx.Conversion/MeshesToScene.cs rename to src/cs/vim/Vim.Format.Vimx.Conversion/MeshesToScene.cs diff --git a/src/cs/vim/Vim.Format.Vimx.Conversion/Vim.Format.Vimx.Conversion.csproj b/src/cs/vim/Vim.Format.Vimx.Conversion/Vim.Format.Vimx.Conversion.csproj new file mode 100644 index 00000000..bb63c8ef --- /dev/null +++ b/src/cs/vim/Vim.Format.Vimx.Conversion/Vim.Format.Vimx.Conversion.csproj @@ -0,0 +1,15 @@ + + + + netstandard2.0 + + + + + + + + + + + diff --git a/src/cs/Vim.Format.Vimx.Conversion/VimToMeshes.cs b/src/cs/vim/Vim.Format.Vimx.Conversion/VimToMeshes.cs similarity index 100% rename from src/cs/Vim.Format.Vimx.Conversion/VimToMeshes.cs rename to src/cs/vim/Vim.Format.Vimx.Conversion/VimToMeshes.cs diff --git a/src/cs/Vim.Format.Vimx.Conversion/VimxConverter.cs b/src/cs/vim/Vim.Format.Vimx.Conversion/VimxConverter.cs similarity index 100% rename from src/cs/Vim.Format.Vimx.Conversion/VimxConverter.cs rename to src/cs/vim/Vim.Format.Vimx.Conversion/VimxConverter.cs diff --git a/src/cs/Vim.Format.Vimx.Conversion/VimxOrdering.cs b/src/cs/vim/Vim.Format.Vimx.Conversion/VimxOrdering.cs similarity index 100% rename from src/cs/Vim.Format.Vimx.Conversion/VimxOrdering.cs rename to src/cs/vim/Vim.Format.Vimx.Conversion/VimxOrdering.cs diff --git a/src/cs/vim/Vim.Vimx.Test/Vim.Format.Vimx.Test.csproj b/src/cs/vim/Vim.Vimx.Test/Vim.Format.Vimx.Test.csproj index 8e4384f2..ef5ed008 100644 --- a/src/cs/vim/Vim.Vimx.Test/Vim.Format.Vimx.Test.csproj +++ b/src/cs/vim/Vim.Vimx.Test/Vim.Format.Vimx.Test.csproj @@ -20,7 +20,7 @@ - + From c7fdba0a9e02bdd14858e29818f5e724ea509d2b Mon Sep 17 00:00:00 2001 From: simon Date: Fri, 29 Sep 2023 15:25:01 -0400 Subject: [PATCH 009/111] missing project --- src/cs/vim/Vim.Vimx.Test/Vim.Format.Vimx.Test.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cs/vim/Vim.Vimx.Test/Vim.Format.Vimx.Test.csproj b/src/cs/vim/Vim.Vimx.Test/Vim.Format.Vimx.Test.csproj index ef5ed008..7f74954c 100644 --- a/src/cs/vim/Vim.Vimx.Test/Vim.Format.Vimx.Test.csproj +++ b/src/cs/vim/Vim.Vimx.Test/Vim.Format.Vimx.Test.csproj @@ -17,6 +17,7 @@ + From 90964238741bfbe446aa4dda66f2c686c1cfbe6a Mon Sep 17 00:00:00 2001 From: simon Date: Fri, 29 Sep 2023 15:37:25 -0400 Subject: [PATCH 010/111] removed log --- src/cs/bfast/Vim.BFast.Next/BFastNextExtensions.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/cs/bfast/Vim.BFast.Next/BFastNextExtensions.cs b/src/cs/bfast/Vim.BFast.Next/BFastNextExtensions.cs index 012c12a2..5390c69f 100644 --- a/src/cs/bfast/Vim.BFast.Next/BFastNextExtensions.cs +++ b/src/cs/bfast/Vim.BFast.Next/BFastNextExtensions.cs @@ -45,7 +45,6 @@ public static void SetBFast(this BFastNext bfast, Func getName, IEnu var i = 0; foreach(var b in others) { - Console.WriteLine(i); bfast.SetBFast(getName(i++), b, deflate); } } From 28d98bff4b688a3d0bde85f5c57283e345d0156b Mon Sep 17 00:00:00 2001 From: simon Date: Fri, 29 Sep 2023 15:37:41 -0400 Subject: [PATCH 011/111] removed temp files from import --- .../temp/Vim.G3dNext.Attributes/Attributes.cs | 178 -- .../Vim.G3dNext.Attributes/Attributes.g.cs | 2042 ----------------- .../Vim.G3dNext.Attributes.csproj | 34 - .../VimAttributeCollectionExtensions.cs | 86 - .../g3d/temp/Vim.G3dNext.Tests/AssimpTests.cs | 237 -- .../g3d/temp/Vim.G3dNext.Tests/FileUtils.cs | 183 -- .../g3d/temp/Vim.G3dNext.Tests/TestUtils.cs | 113 - .../Vim.G3dNext.Tests.csproj | 46 - .../g3d/temp/Vim.G3dNext.Tests/VimG3dTests.cs | 270 --- 9 files changed, 3189 deletions(-) delete mode 100644 src/cs/g3d/temp/Vim.G3dNext.Attributes/Attributes.cs delete mode 100644 src/cs/g3d/temp/Vim.G3dNext.Attributes/Attributes.g.cs delete mode 100644 src/cs/g3d/temp/Vim.G3dNext.Attributes/Vim.G3dNext.Attributes.csproj delete mode 100644 src/cs/g3d/temp/Vim.G3dNext.Attributes/VimAttributeCollectionExtensions.cs delete mode 100644 src/cs/g3d/temp/Vim.G3dNext.Tests/AssimpTests.cs delete mode 100644 src/cs/g3d/temp/Vim.G3dNext.Tests/FileUtils.cs delete mode 100644 src/cs/g3d/temp/Vim.G3dNext.Tests/TestUtils.cs delete mode 100644 src/cs/g3d/temp/Vim.G3dNext.Tests/Vim.G3dNext.Tests.csproj delete mode 100644 src/cs/g3d/temp/Vim.G3dNext.Tests/VimG3dTests.cs diff --git a/src/cs/g3d/temp/Vim.G3dNext.Attributes/Attributes.cs b/src/cs/g3d/temp/Vim.G3dNext.Attributes/Attributes.cs deleted file mode 100644 index df17687e..00000000 --- a/src/cs/g3d/temp/Vim.G3dNext.Attributes/Attributes.cs +++ /dev/null @@ -1,178 +0,0 @@ -using Vim.Math3d; - -namespace Vim.G3dNext.Attributes -{ - #region vim - [AttributeDescriptor("g3d:all:facesize:0:int32:1", AttributeType.Singleton)] - public partial class CornersPerFaceAttribute { } - - [AttributeDescriptor("g3d:vertex:position:0:float32:3", AttributeType.Data, ArrayType = typeof(Vector3))] - public partial class VertexAttribute { } - - [AttributeDescriptor("g3d:corner:index:0:int32:1", AttributeType.Index, IndexInto = typeof(VertexAttribute))] - public partial class IndexAttribute { } - - [AttributeDescriptor("g3d:instance:transform:0:float32:16", AttributeType.Data, ArrayType = typeof(Matrix4x4))] - public partial class InstanceTransformAttribute { } - - [AttributeDescriptor("g3d:instance:parent:0:int32:1", AttributeType.Index, IndexInto = typeof(InstanceTransformAttribute))] - public partial class InstanceParentAttribute { } - - [AttributeDescriptor("g3d:instance:flags:0:uint16:1", AttributeType.Data)] - public partial class InstanceFlagsAttribute { } - - [AttributeDescriptor("g3d:instance:mesh:0:int32:1", AttributeType.Index, IndexInto = typeof(MeshSubmeshOffsetAttribute))] - public partial class InstanceMeshAttribute { } - - [AttributeDescriptor("g3d:mesh:submeshoffset:0:int32:1", AttributeType.Index, IndexInto = typeof(SubmeshIndexOffsetAttribute))] - public partial class MeshSubmeshOffsetAttribute { } - - [AttributeDescriptor("g3d:submesh:indexoffset:0:int32:1", AttributeType.Index, IndexInto = typeof(IndexAttribute))] - public partial class SubmeshIndexOffsetAttribute { } - - [AttributeDescriptor("g3d:submesh:material:0:int32:1", AttributeType.Index, IndexInto = typeof(MaterialColorAttribute))] - public partial class SubmeshMaterialAttribute { } - - - - [AttributeDescriptor("g3d:shapevertex:position:0:float32:3", AttributeType.Data, ArrayType = typeof(Vector3))] - public partial class ShapeVertexAttribute { } - - [AttributeDescriptor("g3d:shape:vertexoffset:0:int32:1", AttributeType.Index, IndexInto = typeof(ShapeVertexAttribute))] - public partial class ShapeVertexOffsetAttribute { } - - [AttributeDescriptor("g3d:shape:color:0:float32:4", AttributeType.Data, ArrayType = typeof(Vector4))] - public partial class ShapeColorAttribute { } - - [AttributeDescriptor("g3d:shape:width:0:float32:1", AttributeType.Data)] - public partial class ShapeWidthAttribute { } - - [AttributeCollection( - typeof(CornersPerFaceAttribute), - typeof(VertexAttribute), - typeof(IndexAttribute), - typeof(InstanceTransformAttribute), - typeof(InstanceParentAttribute), - typeof(InstanceFlagsAttribute), - typeof(InstanceMeshAttribute), - typeof(MeshSubmeshOffsetAttribute), - typeof(SubmeshIndexOffsetAttribute), - typeof(SubmeshMaterialAttribute), - typeof(MaterialColorAttribute), - typeof(MaterialGlossinessAttribute), - typeof(MaterialSmoothnessAttribute), - typeof(ShapeVertexAttribute), - typeof(ShapeVertexOffsetAttribute), - typeof(ShapeColorAttribute), - typeof(ShapeWidthAttribute))] - public partial class VimAttributeCollection // : IAttributeCollection - { - - } - - #endregion - - #region mesh - - [AttributeDescriptor("g3d:submesh:vertexoffset:0:int32:1", AttributeType.Index, IndexInto = typeof(IndexAttribute))] - public partial class SubmeshVertexOffsetAttribute { } - - [AttributeDescriptor("g3d:mesh:opaquesubmeshcount:0:int32:1", AttributeType.Data)] - public partial class MeshOpaqueSubmeshCountAttribute { } - - [AttributeCollection( - typeof(InstanceTransformAttribute), - typeof(MeshOpaqueSubmeshCountAttribute), - typeof(SubmeshIndexOffsetAttribute), - typeof(SubmeshVertexOffsetAttribute), - typeof(SubmeshMaterialAttribute), - typeof(VertexAttribute), - typeof(IndexAttribute) - )] - public partial class MeshAttributeCollection // : IAttributeCollection - { - - } - #endregion - - #region scene - [AttributeDescriptor("g3d:instance:file:0:int32:1", AttributeType.Data)] - public partial class InstanceFileAttribute { } - - [AttributeDescriptor("g3d:instance:node:0:int32:1", AttributeType.Data)] - public partial class InstanceNodeAttribute { } - - - [AttributeDescriptor("g3d:instance:index:0:int32:1", AttributeType.Data)] - public partial class InstanceIndexAttribute { } - - [AttributeDescriptor("g3d:instance:group:0:int32:1", AttributeType.Data)] - public partial class InstanceGroupAttribute { } - - [AttributeDescriptor("g3d:instance:tag:0:int64:1", AttributeType.Data)] - public partial class InstanceTagAttribute { } - - [AttributeDescriptor("g3d:instance:min:0:float32:3", AttributeType.Data, ArrayType = typeof(Vector3))] - public partial class InstanceMinAttribute { } - - [AttributeDescriptor("g3d:instance:max:0:float32:3", AttributeType.Data, ArrayType = typeof(Vector3))] - public partial class InstanceMaxAttribute { } - - [AttributeDescriptor("g3d:mesh:instancecount:0:int32:1", AttributeType.Data)] - public partial class MeshInstanceCountAttribute { } - - [AttributeDescriptor("g3d:mesh:vertexcount:0:int32:1", AttributeType.Data)] - public partial class MeshVertexCountAttribute { } - - [AttributeDescriptor("g3d:mesh:indexcount:0:int32:1", AttributeType.Data)] - public partial class MeshIndexCountAttribute { } - - [AttributeDescriptor("g3d:mesh:opaquevertexcount:0:int32:1", AttributeType.Data)] - public partial class MeshOpaqueVertexCountAttribute { } - - [AttributeDescriptor("g3d:mesh:opaqueindexcount:0:int32:1", AttributeType.Data)] - public partial class MeshOpaqueIndexCountAttribute { } - - [AttributeCollection( - typeof(InstanceFileAttribute), - typeof(InstanceIndexAttribute), - typeof(InstanceNodeAttribute), - typeof(InstanceGroupAttribute), - typeof(InstanceTagAttribute), - typeof(InstanceFlagsAttribute), - typeof(InstanceMinAttribute), - typeof(InstanceMaxAttribute), - typeof(MeshInstanceCountAttribute), - typeof(MeshIndexCountAttribute), - typeof(MeshVertexCountAttribute), - typeof(MeshOpaqueIndexCountAttribute), - typeof(MeshOpaqueVertexCountAttribute) - )] - public partial class SceneAttributeCollection // : IAttributeCollection - { - - } - #endregion - - #region materials - // Material - [AttributeDescriptor("g3d:material:color:0:float32:4", AttributeType.Data, ArrayType = typeof(Vector4))] - public partial class MaterialColorAttribute { } - - [AttributeDescriptor("g3d:material:glossiness:0:float32:1", AttributeType.Data)] - public partial class MaterialGlossinessAttribute { } - - [AttributeDescriptor("g3d:material:smoothness:0:float32:1", AttributeType.Data)] - public partial class MaterialSmoothnessAttribute { } - - [AttributeCollection( - typeof(MaterialColorAttribute), - typeof(MaterialGlossinessAttribute), - typeof(MaterialSmoothnessAttribute) - )] - public partial class MaterialAttributeCollection // : IAttributeCollection - { - - } - #endregion -} diff --git a/src/cs/g3d/temp/Vim.G3dNext.Attributes/Attributes.g.cs b/src/cs/g3d/temp/Vim.G3dNext.Attributes/Attributes.g.cs deleted file mode 100644 index c6fdca00..00000000 --- a/src/cs/g3d/temp/Vim.G3dNext.Attributes/Attributes.g.cs +++ /dev/null @@ -1,2042 +0,0 @@ -// AUTO-GENERATED FILE, DO NOT MODIFY. -// ReSharper disable All -using System; -using System.IO; -using System.Collections.Generic; -using System.Linq; -using Vim.BFast; - -namespace Vim.G3dNext.Attributes -{ - - public partial class CornersPerFaceAttribute : IAttribute - { - public const string AttributeName = "g3d:all:facesize:0:int32:1"; - - public string Name - => AttributeName; - - public static AttributeReader CreateAttributeReader() - => AttributeCollectionExtensions.CreateAttributeReader(); - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Singleton; - - public Type IndexInto { get; } - = null; - - public System.Int32[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - - public partial class VertexAttribute : IAttribute - { - public const string AttributeName = "g3d:vertex:position:0:float32:3"; - - public string Name - => AttributeName; - - public static AttributeReader CreateAttributeReader() - => AttributeCollectionExtensions.CreateAttributeReader(); - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Data; - - public Type IndexInto { get; } - = null; - - public Vim.Math3d.Vector3[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - - public partial class IndexAttribute : IAttribute - { - public const string AttributeName = "g3d:corner:index:0:int32:1"; - - public string Name - => AttributeName; - - public static AttributeReader CreateAttributeReader() - => AttributeCollectionExtensions.CreateAttributeReader(); - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Index; - - public Type IndexInto { get; } - = typeof(Vim.G3dNext.Attributes.VertexAttribute); - - public System.Int32[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - - public partial class InstanceTransformAttribute : IAttribute - { - public const string AttributeName = "g3d:instance:transform:0:float32:16"; - - public string Name - => AttributeName; - - public static AttributeReader CreateAttributeReader() - => AttributeCollectionExtensions.CreateAttributeReader(); - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Data; - - public Type IndexInto { get; } - = null; - - public Vim.Math3d.Matrix4x4[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - - public partial class InstanceParentAttribute : IAttribute - { - public const string AttributeName = "g3d:instance:parent:0:int32:1"; - - public string Name - => AttributeName; - - public static AttributeReader CreateAttributeReader() - => AttributeCollectionExtensions.CreateAttributeReader(); - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Index; - - public Type IndexInto { get; } - = typeof(Vim.G3dNext.Attributes.InstanceTransformAttribute); - - public System.Int32[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - - public partial class InstanceFlagsAttribute : IAttribute - { - public const string AttributeName = "g3d:instance:flags:0:uint16:1"; - - public string Name - => AttributeName; - - public static AttributeReader CreateAttributeReader() - => AttributeCollectionExtensions.CreateAttributeReader(); - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Data; - - public Type IndexInto { get; } - = null; - - public System.UInt16[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - - public partial class InstanceMeshAttribute : IAttribute - { - public const string AttributeName = "g3d:instance:mesh:0:int32:1"; - - public string Name - => AttributeName; - - public static AttributeReader CreateAttributeReader() - => AttributeCollectionExtensions.CreateAttributeReader(); - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Index; - - public Type IndexInto { get; } - = typeof(Vim.G3dNext.Attributes.MeshSubmeshOffsetAttribute); - - public System.Int32[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - - public partial class MeshSubmeshOffsetAttribute : IAttribute - { - public const string AttributeName = "g3d:mesh:submeshoffset:0:int32:1"; - - public string Name - => AttributeName; - - public static AttributeReader CreateAttributeReader() - => AttributeCollectionExtensions.CreateAttributeReader(); - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Index; - - public Type IndexInto { get; } - = typeof(Vim.G3dNext.Attributes.SubmeshIndexOffsetAttribute); - - public System.Int32[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - - public partial class SubmeshIndexOffsetAttribute : IAttribute - { - public const string AttributeName = "g3d:submesh:indexoffset:0:int32:1"; - - public string Name - => AttributeName; - - public static AttributeReader CreateAttributeReader() - => AttributeCollectionExtensions.CreateAttributeReader(); - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Index; - - public Type IndexInto { get; } - = typeof(Vim.G3dNext.Attributes.IndexAttribute); - - public System.Int32[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - - public partial class SubmeshMaterialAttribute : IAttribute - { - public const string AttributeName = "g3d:submesh:material:0:int32:1"; - - public string Name - => AttributeName; - - public static AttributeReader CreateAttributeReader() - => AttributeCollectionExtensions.CreateAttributeReader(); - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Index; - - public Type IndexInto { get; } - = typeof(Vim.G3dNext.Attributes.MaterialColorAttribute); - - public System.Int32[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - - public partial class ShapeVertexAttribute : IAttribute - { - public const string AttributeName = "g3d:shapevertex:position:0:float32:3"; - - public string Name - => AttributeName; - - public static AttributeReader CreateAttributeReader() - => AttributeCollectionExtensions.CreateAttributeReader(); - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Data; - - public Type IndexInto { get; } - = null; - - public Vim.Math3d.Vector3[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - - public partial class ShapeVertexOffsetAttribute : IAttribute - { - public const string AttributeName = "g3d:shape:vertexoffset:0:int32:1"; - - public string Name - => AttributeName; - - public static AttributeReader CreateAttributeReader() - => AttributeCollectionExtensions.CreateAttributeReader(); - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Index; - - public Type IndexInto { get; } - = typeof(Vim.G3dNext.Attributes.ShapeVertexAttribute); - - public System.Int32[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - - public partial class ShapeColorAttribute : IAttribute - { - public const string AttributeName = "g3d:shape:color:0:float32:4"; - - public string Name - => AttributeName; - - public static AttributeReader CreateAttributeReader() - => AttributeCollectionExtensions.CreateAttributeReader(); - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Data; - - public Type IndexInto { get; } - = null; - - public Vim.Math3d.Vector4[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - - public partial class ShapeWidthAttribute : IAttribute - { - public const string AttributeName = "g3d:shape:width:0:float32:1"; - - public string Name - => AttributeName; - - public static AttributeReader CreateAttributeReader() - => AttributeCollectionExtensions.CreateAttributeReader(); - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Data; - - public Type IndexInto { get; } - = null; - - public System.Single[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - - public partial class SubmeshVertexOffsetAttribute : IAttribute - { - public const string AttributeName = "g3d:submesh:vertexoffset:0:int32:1"; - - public string Name - => AttributeName; - - public static AttributeReader CreateAttributeReader() - => AttributeCollectionExtensions.CreateAttributeReader(); - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Index; - - public Type IndexInto { get; } - = typeof(Vim.G3dNext.Attributes.IndexAttribute); - - public System.Int32[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - - public partial class MeshOpaqueSubmeshCountAttribute : IAttribute - { - public const string AttributeName = "g3d:mesh:opaquesubmeshcount:0:int32:1"; - - public string Name - => AttributeName; - - public static AttributeReader CreateAttributeReader() - => AttributeCollectionExtensions.CreateAttributeReader(); - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Data; - - public Type IndexInto { get; } - = null; - - public System.Int32[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - - public partial class InstanceFileAttribute : IAttribute - { - public const string AttributeName = "g3d:instance:file:0:int32:1"; - - public string Name - => AttributeName; - - public static AttributeReader CreateAttributeReader() - => AttributeCollectionExtensions.CreateAttributeReader(); - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Data; - - public Type IndexInto { get; } - = null; - - public System.Int32[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - - public partial class InstanceNodeAttribute : IAttribute - { - public const string AttributeName = "g3d:instance:node:0:int32:1"; - - public string Name - => AttributeName; - - public static AttributeReader CreateAttributeReader() - => AttributeCollectionExtensions.CreateAttributeReader(); - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Data; - - public Type IndexInto { get; } - = null; - - public System.Int32[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - - public partial class InstanceIndexAttribute : IAttribute - { - public const string AttributeName = "g3d:instance:index:0:int32:1"; - - public string Name - => AttributeName; - - public static AttributeReader CreateAttributeReader() - => AttributeCollectionExtensions.CreateAttributeReader(); - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Data; - - public Type IndexInto { get; } - = null; - - public System.Int32[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - - public partial class InstanceGroupAttribute : IAttribute - { - public const string AttributeName = "g3d:instance:group:0:int32:1"; - - public string Name - => AttributeName; - - public static AttributeReader CreateAttributeReader() - => AttributeCollectionExtensions.CreateAttributeReader(); - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Data; - - public Type IndexInto { get; } - = null; - - public System.Int32[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - - public partial class InstanceTagAttribute : IAttribute - { - public const string AttributeName = "g3d:instance:tag:0:int64:1"; - - public string Name - => AttributeName; - - public static AttributeReader CreateAttributeReader() - => AttributeCollectionExtensions.CreateAttributeReader(); - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Data; - - public Type IndexInto { get; } - = null; - - public System.Int64[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - - public partial class InstanceMinAttribute : IAttribute - { - public const string AttributeName = "g3d:instance:min:0:float32:3"; - - public string Name - => AttributeName; - - public static AttributeReader CreateAttributeReader() - => AttributeCollectionExtensions.CreateAttributeReader(); - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Data; - - public Type IndexInto { get; } - = null; - - public Vim.Math3d.Vector3[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - - public partial class InstanceMaxAttribute : IAttribute - { - public const string AttributeName = "g3d:instance:max:0:float32:3"; - - public string Name - => AttributeName; - - public static AttributeReader CreateAttributeReader() - => AttributeCollectionExtensions.CreateAttributeReader(); - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Data; - - public Type IndexInto { get; } - = null; - - public Vim.Math3d.Vector3[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - - public partial class MeshInstanceCountAttribute : IAttribute - { - public const string AttributeName = "g3d:mesh:instancecount:0:int32:1"; - - public string Name - => AttributeName; - - public static AttributeReader CreateAttributeReader() - => AttributeCollectionExtensions.CreateAttributeReader(); - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Data; - - public Type IndexInto { get; } - = null; - - public System.Int32[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - - public partial class MeshVertexCountAttribute : IAttribute - { - public const string AttributeName = "g3d:mesh:vertexcount:0:int32:1"; - - public string Name - => AttributeName; - - public static AttributeReader CreateAttributeReader() - => AttributeCollectionExtensions.CreateAttributeReader(); - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Data; - - public Type IndexInto { get; } - = null; - - public System.Int32[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - - public partial class MeshIndexCountAttribute : IAttribute - { - public const string AttributeName = "g3d:mesh:indexcount:0:int32:1"; - - public string Name - => AttributeName; - - public static AttributeReader CreateAttributeReader() - => AttributeCollectionExtensions.CreateAttributeReader(); - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Data; - - public Type IndexInto { get; } - = null; - - public System.Int32[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - - public partial class MeshOpaqueVertexCountAttribute : IAttribute - { - public const string AttributeName = "g3d:mesh:opaquevertexcount:0:int32:1"; - - public string Name - => AttributeName; - - public static AttributeReader CreateAttributeReader() - => AttributeCollectionExtensions.CreateAttributeReader(); - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Data; - - public Type IndexInto { get; } - = null; - - public System.Int32[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - - public partial class MeshOpaqueIndexCountAttribute : IAttribute - { - public const string AttributeName = "g3d:mesh:opaqueindexcount:0:int32:1"; - - public string Name - => AttributeName; - - public static AttributeReader CreateAttributeReader() - => AttributeCollectionExtensions.CreateAttributeReader(); - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Data; - - public Type IndexInto { get; } - = null; - - public System.Int32[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - - public partial class MaterialColorAttribute : IAttribute - { - public const string AttributeName = "g3d:material:color:0:float32:4"; - - public string Name - => AttributeName; - - public static AttributeReader CreateAttributeReader() - => AttributeCollectionExtensions.CreateAttributeReader(); - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Data; - - public Type IndexInto { get; } - = null; - - public Vim.Math3d.Vector4[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - - public partial class MaterialGlossinessAttribute : IAttribute - { - public const string AttributeName = "g3d:material:glossiness:0:float32:1"; - - public string Name - => AttributeName; - - public static AttributeReader CreateAttributeReader() - => AttributeCollectionExtensions.CreateAttributeReader(); - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Data; - - public Type IndexInto { get; } - = null; - - public System.Single[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - - public partial class MaterialSmoothnessAttribute : IAttribute - { - public const string AttributeName = "g3d:material:smoothness:0:float32:1"; - - public string Name - => AttributeName; - - public static AttributeReader CreateAttributeReader() - => AttributeCollectionExtensions.CreateAttributeReader(); - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Data; - - public Type IndexInto { get; } - = null; - - public System.Single[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - public partial class VimAttributeCollection : IAttributeCollection - { - public IEnumerable AttributeNames - => Attributes.Keys; - - public long GetSize() - => Attributes.Values.Sum(a => a.Data.LongLength * a.AttributeDescriptor.DataElementSize); - - public IDictionary Attributes { get; } - = new Dictionary - { - [Vim.G3dNext.Attributes.CornersPerFaceAttribute.AttributeName] = new Vim.G3dNext.Attributes.CornersPerFaceAttribute(), - [Vim.G3dNext.Attributes.VertexAttribute.AttributeName] = new Vim.G3dNext.Attributes.VertexAttribute(), - [Vim.G3dNext.Attributes.IndexAttribute.AttributeName] = new Vim.G3dNext.Attributes.IndexAttribute(), - [Vim.G3dNext.Attributes.InstanceTransformAttribute.AttributeName] = new Vim.G3dNext.Attributes.InstanceTransformAttribute(), - [Vim.G3dNext.Attributes.InstanceParentAttribute.AttributeName] = new Vim.G3dNext.Attributes.InstanceParentAttribute(), - [Vim.G3dNext.Attributes.InstanceFlagsAttribute.AttributeName] = new Vim.G3dNext.Attributes.InstanceFlagsAttribute(), - [Vim.G3dNext.Attributes.InstanceMeshAttribute.AttributeName] = new Vim.G3dNext.Attributes.InstanceMeshAttribute(), - [Vim.G3dNext.Attributes.MeshSubmeshOffsetAttribute.AttributeName] = new Vim.G3dNext.Attributes.MeshSubmeshOffsetAttribute(), - [Vim.G3dNext.Attributes.SubmeshIndexOffsetAttribute.AttributeName] = new Vim.G3dNext.Attributes.SubmeshIndexOffsetAttribute(), - [Vim.G3dNext.Attributes.SubmeshMaterialAttribute.AttributeName] = new Vim.G3dNext.Attributes.SubmeshMaterialAttribute(), - [Vim.G3dNext.Attributes.MaterialColorAttribute.AttributeName] = new Vim.G3dNext.Attributes.MaterialColorAttribute(), - [Vim.G3dNext.Attributes.MaterialGlossinessAttribute.AttributeName] = new Vim.G3dNext.Attributes.MaterialGlossinessAttribute(), - [Vim.G3dNext.Attributes.MaterialSmoothnessAttribute.AttributeName] = new Vim.G3dNext.Attributes.MaterialSmoothnessAttribute(), - [Vim.G3dNext.Attributes.ShapeVertexAttribute.AttributeName] = new Vim.G3dNext.Attributes.ShapeVertexAttribute(), - [Vim.G3dNext.Attributes.ShapeVertexOffsetAttribute.AttributeName] = new Vim.G3dNext.Attributes.ShapeVertexOffsetAttribute(), - [Vim.G3dNext.Attributes.ShapeColorAttribute.AttributeName] = new Vim.G3dNext.Attributes.ShapeColorAttribute(), - [Vim.G3dNext.Attributes.ShapeWidthAttribute.AttributeName] = new Vim.G3dNext.Attributes.ShapeWidthAttribute(), - }; - - public IDictionary AttributeReaders { get; } - = new Dictionary - { - [Vim.G3dNext.Attributes.CornersPerFaceAttribute.AttributeName] = Vim.G3dNext.Attributes.CornersPerFaceAttribute.CreateAttributeReader(), - [Vim.G3dNext.Attributes.VertexAttribute.AttributeName] = Vim.G3dNext.Attributes.VertexAttribute.CreateAttributeReader(), - [Vim.G3dNext.Attributes.IndexAttribute.AttributeName] = Vim.G3dNext.Attributes.IndexAttribute.CreateAttributeReader(), - [Vim.G3dNext.Attributes.InstanceTransformAttribute.AttributeName] = Vim.G3dNext.Attributes.InstanceTransformAttribute.CreateAttributeReader(), - [Vim.G3dNext.Attributes.InstanceParentAttribute.AttributeName] = Vim.G3dNext.Attributes.InstanceParentAttribute.CreateAttributeReader(), - [Vim.G3dNext.Attributes.InstanceFlagsAttribute.AttributeName] = Vim.G3dNext.Attributes.InstanceFlagsAttribute.CreateAttributeReader(), - [Vim.G3dNext.Attributes.InstanceMeshAttribute.AttributeName] = Vim.G3dNext.Attributes.InstanceMeshAttribute.CreateAttributeReader(), - [Vim.G3dNext.Attributes.MeshSubmeshOffsetAttribute.AttributeName] = Vim.G3dNext.Attributes.MeshSubmeshOffsetAttribute.CreateAttributeReader(), - [Vim.G3dNext.Attributes.SubmeshIndexOffsetAttribute.AttributeName] = Vim.G3dNext.Attributes.SubmeshIndexOffsetAttribute.CreateAttributeReader(), - [Vim.G3dNext.Attributes.SubmeshMaterialAttribute.AttributeName] = Vim.G3dNext.Attributes.SubmeshMaterialAttribute.CreateAttributeReader(), - [Vim.G3dNext.Attributes.MaterialColorAttribute.AttributeName] = Vim.G3dNext.Attributes.MaterialColorAttribute.CreateAttributeReader(), - [Vim.G3dNext.Attributes.MaterialGlossinessAttribute.AttributeName] = Vim.G3dNext.Attributes.MaterialGlossinessAttribute.CreateAttributeReader(), - [Vim.G3dNext.Attributes.MaterialSmoothnessAttribute.AttributeName] = Vim.G3dNext.Attributes.MaterialSmoothnessAttribute.CreateAttributeReader(), - [Vim.G3dNext.Attributes.ShapeVertexAttribute.AttributeName] = Vim.G3dNext.Attributes.ShapeVertexAttribute.CreateAttributeReader(), - [Vim.G3dNext.Attributes.ShapeVertexOffsetAttribute.AttributeName] = Vim.G3dNext.Attributes.ShapeVertexOffsetAttribute.CreateAttributeReader(), - [Vim.G3dNext.Attributes.ShapeColorAttribute.AttributeName] = Vim.G3dNext.Attributes.ShapeColorAttribute.CreateAttributeReader(), - [Vim.G3dNext.Attributes.ShapeWidthAttribute.AttributeName] = Vim.G3dNext.Attributes.ShapeWidthAttribute.CreateAttributeReader(), - }; - - // Named Attributes. - - public Vim.G3dNext.Attributes.CornersPerFaceAttribute CornersPerFaceAttribute - { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.CornersPerFaceAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.CornersPerFaceAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.CornersPerFaceAttribute.AttributeName] = value as IAttribute; - } - - public Vim.G3dNext.Attributes.VertexAttribute VertexAttribute - { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.VertexAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.VertexAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.VertexAttribute.AttributeName] = value as IAttribute; - } - - public Vim.G3dNext.Attributes.IndexAttribute IndexAttribute - { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.IndexAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.IndexAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.IndexAttribute.AttributeName] = value as IAttribute; - } - - public Vim.G3dNext.Attributes.InstanceTransformAttribute InstanceTransformAttribute - { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.InstanceTransformAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceTransformAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.InstanceTransformAttribute.AttributeName] = value as IAttribute; - } - - public Vim.G3dNext.Attributes.InstanceParentAttribute InstanceParentAttribute - { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.InstanceParentAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceParentAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.InstanceParentAttribute.AttributeName] = value as IAttribute; - } - - public Vim.G3dNext.Attributes.InstanceFlagsAttribute InstanceFlagsAttribute - { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.InstanceFlagsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceFlagsAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.InstanceFlagsAttribute.AttributeName] = value as IAttribute; - } - - public Vim.G3dNext.Attributes.InstanceMeshAttribute InstanceMeshAttribute - { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.InstanceMeshAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceMeshAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.InstanceMeshAttribute.AttributeName] = value as IAttribute; - } - - public Vim.G3dNext.Attributes.MeshSubmeshOffsetAttribute MeshSubmeshOffsetAttribute - { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.MeshSubmeshOffsetAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshSubmeshOffsetAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.MeshSubmeshOffsetAttribute.AttributeName] = value as IAttribute; - } - - public Vim.G3dNext.Attributes.SubmeshIndexOffsetAttribute SubmeshIndexOffsetAttribute - { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.SubmeshIndexOffsetAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.SubmeshIndexOffsetAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.SubmeshIndexOffsetAttribute.AttributeName] = value as IAttribute; - } - - public Vim.G3dNext.Attributes.SubmeshMaterialAttribute SubmeshMaterialAttribute - { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.SubmeshMaterialAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.SubmeshMaterialAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.SubmeshMaterialAttribute.AttributeName] = value as IAttribute; - } - - public Vim.G3dNext.Attributes.MaterialColorAttribute MaterialColorAttribute - { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.MaterialColorAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MaterialColorAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.MaterialColorAttribute.AttributeName] = value as IAttribute; - } - - public Vim.G3dNext.Attributes.MaterialGlossinessAttribute MaterialGlossinessAttribute - { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.MaterialGlossinessAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MaterialGlossinessAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.MaterialGlossinessAttribute.AttributeName] = value as IAttribute; - } - - public Vim.G3dNext.Attributes.MaterialSmoothnessAttribute MaterialSmoothnessAttribute - { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.MaterialSmoothnessAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MaterialSmoothnessAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.MaterialSmoothnessAttribute.AttributeName] = value as IAttribute; - } - - public Vim.G3dNext.Attributes.ShapeVertexAttribute ShapeVertexAttribute - { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.ShapeVertexAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.ShapeVertexAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.ShapeVertexAttribute.AttributeName] = value as IAttribute; - } - - public Vim.G3dNext.Attributes.ShapeVertexOffsetAttribute ShapeVertexOffsetAttribute - { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.ShapeVertexOffsetAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.ShapeVertexOffsetAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.ShapeVertexOffsetAttribute.AttributeName] = value as IAttribute; - } - - public Vim.G3dNext.Attributes.ShapeColorAttribute ShapeColorAttribute - { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.ShapeColorAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.ShapeColorAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.ShapeColorAttribute.AttributeName] = value as IAttribute; - } - - public Vim.G3dNext.Attributes.ShapeWidthAttribute ShapeWidthAttribute - { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.ShapeWidthAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.ShapeWidthAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.ShapeWidthAttribute.AttributeName] = value as IAttribute; - } - - /// - public IAttribute GetAttribute(Type attributeType) - { - - if (attributeType == typeof(Vim.G3dNext.Attributes.CornersPerFaceAttribute)) - return CornersPerFaceAttribute; - - if (attributeType == typeof(Vim.G3dNext.Attributes.VertexAttribute)) - return VertexAttribute; - - if (attributeType == typeof(Vim.G3dNext.Attributes.IndexAttribute)) - return IndexAttribute; - - if (attributeType == typeof(Vim.G3dNext.Attributes.InstanceTransformAttribute)) - return InstanceTransformAttribute; - - if (attributeType == typeof(Vim.G3dNext.Attributes.InstanceParentAttribute)) - return InstanceParentAttribute; - - if (attributeType == typeof(Vim.G3dNext.Attributes.InstanceFlagsAttribute)) - return InstanceFlagsAttribute; - - if (attributeType == typeof(Vim.G3dNext.Attributes.InstanceMeshAttribute)) - return InstanceMeshAttribute; - - if (attributeType == typeof(Vim.G3dNext.Attributes.MeshSubmeshOffsetAttribute)) - return MeshSubmeshOffsetAttribute; - - if (attributeType == typeof(Vim.G3dNext.Attributes.SubmeshIndexOffsetAttribute)) - return SubmeshIndexOffsetAttribute; - - if (attributeType == typeof(Vim.G3dNext.Attributes.SubmeshMaterialAttribute)) - return SubmeshMaterialAttribute; - - if (attributeType == typeof(Vim.G3dNext.Attributes.MaterialColorAttribute)) - return MaterialColorAttribute; - - if (attributeType == typeof(Vim.G3dNext.Attributes.MaterialGlossinessAttribute)) - return MaterialGlossinessAttribute; - - if (attributeType == typeof(Vim.G3dNext.Attributes.MaterialSmoothnessAttribute)) - return MaterialSmoothnessAttribute; - - if (attributeType == typeof(Vim.G3dNext.Attributes.ShapeVertexAttribute)) - return ShapeVertexAttribute; - - if (attributeType == typeof(Vim.G3dNext.Attributes.ShapeVertexOffsetAttribute)) - return ShapeVertexOffsetAttribute; - - if (attributeType == typeof(Vim.G3dNext.Attributes.ShapeColorAttribute)) - return ShapeColorAttribute; - - if (attributeType == typeof(Vim.G3dNext.Attributes.ShapeWidthAttribute)) - return ShapeWidthAttribute; - - throw new ArgumentException("Type {attributeType.ToString()} is not supported."); - } - - public IAttribute MergeAttribute(string attributeName, IReadOnlyList otherCollections) - { - var collections = otherCollections.Prepend(this).ToArray(); - switch (attributeName) - { - - case Vim.G3dNext.Attributes.CornersPerFaceAttribute.AttributeName: - { - // Singleton Attribute (no merging) - return CornersPerFaceAttribute; - } - - case Vim.G3dNext.Attributes.VertexAttribute.AttributeName: - { - // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); - } - - case Vim.G3dNext.Attributes.IndexAttribute.AttributeName: - { - // Index Attribute - return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); - } - - case Vim.G3dNext.Attributes.InstanceTransformAttribute.AttributeName: - { - // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); - } - - case Vim.G3dNext.Attributes.InstanceParentAttribute.AttributeName: - { - // Index Attribute - return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); - } - - case Vim.G3dNext.Attributes.InstanceFlagsAttribute.AttributeName: - { - // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); - } - - case Vim.G3dNext.Attributes.InstanceMeshAttribute.AttributeName: - { - // Index Attribute - return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); - } - - case Vim.G3dNext.Attributes.MeshSubmeshOffsetAttribute.AttributeName: - { - // Index Attribute - return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); - } - - case Vim.G3dNext.Attributes.SubmeshIndexOffsetAttribute.AttributeName: - { - // Index Attribute - return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); - } - - case Vim.G3dNext.Attributes.SubmeshMaterialAttribute.AttributeName: - { - // Index Attribute - return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); - } - - case Vim.G3dNext.Attributes.MaterialColorAttribute.AttributeName: - { - // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); - } - - case Vim.G3dNext.Attributes.MaterialGlossinessAttribute.AttributeName: - { - // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); - } - - case Vim.G3dNext.Attributes.MaterialSmoothnessAttribute.AttributeName: - { - // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); - } - - case Vim.G3dNext.Attributes.ShapeVertexAttribute.AttributeName: - { - // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); - } - - case Vim.G3dNext.Attributes.ShapeVertexOffsetAttribute.AttributeName: - { - // Index Attribute - return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); - } - - case Vim.G3dNext.Attributes.ShapeColorAttribute.AttributeName: - { - // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); - } - - case Vim.G3dNext.Attributes.ShapeWidthAttribute.AttributeName: - { - // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); - } - - default: - throw new ArgumentException(nameof(attributeName)); - } - } - - public void Validate() - { - // Ensure all the indices are either -1 or within the bounds of the attributes they are indexing into. - - { - var maxIndex = GetAttribute(IndexAttribute.IndexInto).Data.Length - 1; - for (var i = 0; i < IndexAttribute.TypedData.Length; ++i) - { - var index = IndexAttribute.TypedData[i]; - - if (index == -1) - continue; // no relation. - - if (index < -1 || index > maxIndex) - throw new Exception($"Index out of range in Vim.G3dNext.Attributes.IndexAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); - } - } - - { - var maxIndex = GetAttribute(InstanceParentAttribute.IndexInto).Data.Length - 1; - for (var i = 0; i < InstanceParentAttribute.TypedData.Length; ++i) - { - var index = InstanceParentAttribute.TypedData[i]; - - if (index == -1) - continue; // no relation. - - if (index < -1 || index > maxIndex) - throw new Exception($"Index out of range in Vim.G3dNext.Attributes.InstanceParentAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); - } - } - - { - var maxIndex = GetAttribute(InstanceMeshAttribute.IndexInto).Data.Length - 1; - for (var i = 0; i < InstanceMeshAttribute.TypedData.Length; ++i) - { - var index = InstanceMeshAttribute.TypedData[i]; - - if (index == -1) - continue; // no relation. - - if (index < -1 || index > maxIndex) - throw new Exception($"Index out of range in Vim.G3dNext.Attributes.InstanceMeshAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); - } - } - - { - var maxIndex = GetAttribute(MeshSubmeshOffsetAttribute.IndexInto).Data.Length - 1; - for (var i = 0; i < MeshSubmeshOffsetAttribute.TypedData.Length; ++i) - { - var index = MeshSubmeshOffsetAttribute.TypedData[i]; - - if (index == -1) - continue; // no relation. - - if (index < -1 || index > maxIndex) - throw new Exception($"Index out of range in Vim.G3dNext.Attributes.MeshSubmeshOffsetAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); - } - } - - { - var maxIndex = GetAttribute(SubmeshIndexOffsetAttribute.IndexInto).Data.Length - 1; - for (var i = 0; i < SubmeshIndexOffsetAttribute.TypedData.Length; ++i) - { - var index = SubmeshIndexOffsetAttribute.TypedData[i]; - - if (index == -1) - continue; // no relation. - - if (index < -1 || index > maxIndex) - throw new Exception($"Index out of range in Vim.G3dNext.Attributes.SubmeshIndexOffsetAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); - } - } - - { - var maxIndex = GetAttribute(SubmeshMaterialAttribute.IndexInto).Data.Length - 1; - for (var i = 0; i < SubmeshMaterialAttribute.TypedData.Length; ++i) - { - var index = SubmeshMaterialAttribute.TypedData[i]; - - if (index == -1) - continue; // no relation. - - if (index < -1 || index > maxIndex) - throw new Exception($"Index out of range in Vim.G3dNext.Attributes.SubmeshMaterialAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); - } - } - - { - var maxIndex = GetAttribute(ShapeVertexOffsetAttribute.IndexInto).Data.Length - 1; - for (var i = 0; i < ShapeVertexOffsetAttribute.TypedData.Length; ++i) - { - var index = ShapeVertexOffsetAttribute.TypedData[i]; - - if (index == -1) - continue; // no relation. - - if (index < -1 || index > maxIndex) - throw new Exception($"Index out of range in Vim.G3dNext.Attributes.ShapeVertexOffsetAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); - } - } - } - } - public partial class MeshAttributeCollection : IAttributeCollection - { - public IEnumerable AttributeNames - => Attributes.Keys; - - public long GetSize() - => Attributes.Values.Sum(a => a.Data.LongLength * a.AttributeDescriptor.DataElementSize); - - public IDictionary Attributes { get; } - = new Dictionary - { - [Vim.G3dNext.Attributes.InstanceTransformAttribute.AttributeName] = new Vim.G3dNext.Attributes.InstanceTransformAttribute(), - [Vim.G3dNext.Attributes.MeshOpaqueSubmeshCountAttribute.AttributeName] = new Vim.G3dNext.Attributes.MeshOpaqueSubmeshCountAttribute(), - [Vim.G3dNext.Attributes.SubmeshIndexOffsetAttribute.AttributeName] = new Vim.G3dNext.Attributes.SubmeshIndexOffsetAttribute(), - [Vim.G3dNext.Attributes.SubmeshVertexOffsetAttribute.AttributeName] = new Vim.G3dNext.Attributes.SubmeshVertexOffsetAttribute(), - [Vim.G3dNext.Attributes.SubmeshMaterialAttribute.AttributeName] = new Vim.G3dNext.Attributes.SubmeshMaterialAttribute(), - [Vim.G3dNext.Attributes.VertexAttribute.AttributeName] = new Vim.G3dNext.Attributes.VertexAttribute(), - [Vim.G3dNext.Attributes.IndexAttribute.AttributeName] = new Vim.G3dNext.Attributes.IndexAttribute(), - }; - - public IDictionary AttributeReaders { get; } - = new Dictionary - { - [Vim.G3dNext.Attributes.InstanceTransformAttribute.AttributeName] = Vim.G3dNext.Attributes.InstanceTransformAttribute.CreateAttributeReader(), - [Vim.G3dNext.Attributes.MeshOpaqueSubmeshCountAttribute.AttributeName] = Vim.G3dNext.Attributes.MeshOpaqueSubmeshCountAttribute.CreateAttributeReader(), - [Vim.G3dNext.Attributes.SubmeshIndexOffsetAttribute.AttributeName] = Vim.G3dNext.Attributes.SubmeshIndexOffsetAttribute.CreateAttributeReader(), - [Vim.G3dNext.Attributes.SubmeshVertexOffsetAttribute.AttributeName] = Vim.G3dNext.Attributes.SubmeshVertexOffsetAttribute.CreateAttributeReader(), - [Vim.G3dNext.Attributes.SubmeshMaterialAttribute.AttributeName] = Vim.G3dNext.Attributes.SubmeshMaterialAttribute.CreateAttributeReader(), - [Vim.G3dNext.Attributes.VertexAttribute.AttributeName] = Vim.G3dNext.Attributes.VertexAttribute.CreateAttributeReader(), - [Vim.G3dNext.Attributes.IndexAttribute.AttributeName] = Vim.G3dNext.Attributes.IndexAttribute.CreateAttributeReader(), - }; - - // Named Attributes. - - public Vim.G3dNext.Attributes.InstanceTransformAttribute InstanceTransformAttribute - { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.InstanceTransformAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceTransformAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.InstanceTransformAttribute.AttributeName] = value as IAttribute; - } - - public Vim.G3dNext.Attributes.MeshOpaqueSubmeshCountAttribute MeshOpaqueSubmeshCountAttribute - { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.MeshOpaqueSubmeshCountAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshOpaqueSubmeshCountAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.MeshOpaqueSubmeshCountAttribute.AttributeName] = value as IAttribute; - } - - public Vim.G3dNext.Attributes.SubmeshIndexOffsetAttribute SubmeshIndexOffsetAttribute - { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.SubmeshIndexOffsetAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.SubmeshIndexOffsetAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.SubmeshIndexOffsetAttribute.AttributeName] = value as IAttribute; - } - - public Vim.G3dNext.Attributes.SubmeshVertexOffsetAttribute SubmeshVertexOffsetAttribute - { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.SubmeshVertexOffsetAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.SubmeshVertexOffsetAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.SubmeshVertexOffsetAttribute.AttributeName] = value as IAttribute; - } - - public Vim.G3dNext.Attributes.SubmeshMaterialAttribute SubmeshMaterialAttribute - { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.SubmeshMaterialAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.SubmeshMaterialAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.SubmeshMaterialAttribute.AttributeName] = value as IAttribute; - } - - public Vim.G3dNext.Attributes.VertexAttribute VertexAttribute - { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.VertexAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.VertexAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.VertexAttribute.AttributeName] = value as IAttribute; - } - - public Vim.G3dNext.Attributes.IndexAttribute IndexAttribute - { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.IndexAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.IndexAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.IndexAttribute.AttributeName] = value as IAttribute; - } - - /// - public IAttribute GetAttribute(Type attributeType) - { - - if (attributeType == typeof(Vim.G3dNext.Attributes.InstanceTransformAttribute)) - return InstanceTransformAttribute; - - if (attributeType == typeof(Vim.G3dNext.Attributes.MeshOpaqueSubmeshCountAttribute)) - return MeshOpaqueSubmeshCountAttribute; - - if (attributeType == typeof(Vim.G3dNext.Attributes.SubmeshIndexOffsetAttribute)) - return SubmeshIndexOffsetAttribute; - - if (attributeType == typeof(Vim.G3dNext.Attributes.SubmeshVertexOffsetAttribute)) - return SubmeshVertexOffsetAttribute; - - if (attributeType == typeof(Vim.G3dNext.Attributes.SubmeshMaterialAttribute)) - return SubmeshMaterialAttribute; - - if (attributeType == typeof(Vim.G3dNext.Attributes.VertexAttribute)) - return VertexAttribute; - - if (attributeType == typeof(Vim.G3dNext.Attributes.IndexAttribute)) - return IndexAttribute; - - throw new ArgumentException("Type {attributeType.ToString()} is not supported."); - } - - public IAttribute MergeAttribute(string attributeName, IReadOnlyList otherCollections) - { - var collections = otherCollections.Prepend(this).ToArray(); - switch (attributeName) - { - - case Vim.G3dNext.Attributes.InstanceTransformAttribute.AttributeName: - { - // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); - } - - case Vim.G3dNext.Attributes.MeshOpaqueSubmeshCountAttribute.AttributeName: - { - // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); - } - - case Vim.G3dNext.Attributes.SubmeshIndexOffsetAttribute.AttributeName: - { - // Index Attribute - return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); - } - - case Vim.G3dNext.Attributes.SubmeshVertexOffsetAttribute.AttributeName: - { - // Index Attribute - return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); - } - - case Vim.G3dNext.Attributes.SubmeshMaterialAttribute.AttributeName: - { - // Index Attribute - return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); - } - - case Vim.G3dNext.Attributes.VertexAttribute.AttributeName: - { - // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); - } - - case Vim.G3dNext.Attributes.IndexAttribute.AttributeName: - { - // Index Attribute - return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); - } - - default: - throw new ArgumentException(nameof(attributeName)); - } - } - - public void Validate() - { - // Ensure all the indices are either -1 or within the bounds of the attributes they are indexing into. - - { - var maxIndex = GetAttribute(SubmeshIndexOffsetAttribute.IndexInto).Data.Length - 1; - for (var i = 0; i < SubmeshIndexOffsetAttribute.TypedData.Length; ++i) - { - var index = SubmeshIndexOffsetAttribute.TypedData[i]; - - if (index == -1) - continue; // no relation. - - if (index < -1 || index > maxIndex) - throw new Exception($"Index out of range in Vim.G3dNext.Attributes.SubmeshIndexOffsetAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); - } - } - - { - var maxIndex = GetAttribute(SubmeshVertexOffsetAttribute.IndexInto).Data.Length - 1; - for (var i = 0; i < SubmeshVertexOffsetAttribute.TypedData.Length; ++i) - { - var index = SubmeshVertexOffsetAttribute.TypedData[i]; - - if (index == -1) - continue; // no relation. - - if (index < -1 || index > maxIndex) - throw new Exception($"Index out of range in Vim.G3dNext.Attributes.SubmeshVertexOffsetAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); - } - } - - { - var maxIndex = GetAttribute(SubmeshMaterialAttribute.IndexInto).Data.Length - 1; - for (var i = 0; i < SubmeshMaterialAttribute.TypedData.Length; ++i) - { - var index = SubmeshMaterialAttribute.TypedData[i]; - - if (index == -1) - continue; // no relation. - - if (index < -1 || index > maxIndex) - throw new Exception($"Index out of range in Vim.G3dNext.Attributes.SubmeshMaterialAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); - } - } - - { - var maxIndex = GetAttribute(IndexAttribute.IndexInto).Data.Length - 1; - for (var i = 0; i < IndexAttribute.TypedData.Length; ++i) - { - var index = IndexAttribute.TypedData[i]; - - if (index == -1) - continue; // no relation. - - if (index < -1 || index > maxIndex) - throw new Exception($"Index out of range in Vim.G3dNext.Attributes.IndexAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); - } - } - } - } - public partial class SceneAttributeCollection : IAttributeCollection - { - public IEnumerable AttributeNames - => Attributes.Keys; - - public long GetSize() - => Attributes.Values.Sum(a => a.Data.LongLength * a.AttributeDescriptor.DataElementSize); - - public IDictionary Attributes { get; } - = new Dictionary - { - [Vim.G3dNext.Attributes.InstanceFileAttribute.AttributeName] = new Vim.G3dNext.Attributes.InstanceFileAttribute(), - [Vim.G3dNext.Attributes.InstanceIndexAttribute.AttributeName] = new Vim.G3dNext.Attributes.InstanceIndexAttribute(), - [Vim.G3dNext.Attributes.InstanceNodeAttribute.AttributeName] = new Vim.G3dNext.Attributes.InstanceNodeAttribute(), - [Vim.G3dNext.Attributes.InstanceGroupAttribute.AttributeName] = new Vim.G3dNext.Attributes.InstanceGroupAttribute(), - [Vim.G3dNext.Attributes.InstanceTagAttribute.AttributeName] = new Vim.G3dNext.Attributes.InstanceTagAttribute(), - [Vim.G3dNext.Attributes.InstanceFlagsAttribute.AttributeName] = new Vim.G3dNext.Attributes.InstanceFlagsAttribute(), - [Vim.G3dNext.Attributes.InstanceMinAttribute.AttributeName] = new Vim.G3dNext.Attributes.InstanceMinAttribute(), - [Vim.G3dNext.Attributes.InstanceMaxAttribute.AttributeName] = new Vim.G3dNext.Attributes.InstanceMaxAttribute(), - [Vim.G3dNext.Attributes.MeshInstanceCountAttribute.AttributeName] = new Vim.G3dNext.Attributes.MeshInstanceCountAttribute(), - [Vim.G3dNext.Attributes.MeshIndexCountAttribute.AttributeName] = new Vim.G3dNext.Attributes.MeshIndexCountAttribute(), - [Vim.G3dNext.Attributes.MeshVertexCountAttribute.AttributeName] = new Vim.G3dNext.Attributes.MeshVertexCountAttribute(), - [Vim.G3dNext.Attributes.MeshOpaqueIndexCountAttribute.AttributeName] = new Vim.G3dNext.Attributes.MeshOpaqueIndexCountAttribute(), - [Vim.G3dNext.Attributes.MeshOpaqueVertexCountAttribute.AttributeName] = new Vim.G3dNext.Attributes.MeshOpaqueVertexCountAttribute(), - }; - - public IDictionary AttributeReaders { get; } - = new Dictionary - { - [Vim.G3dNext.Attributes.InstanceFileAttribute.AttributeName] = Vim.G3dNext.Attributes.InstanceFileAttribute.CreateAttributeReader(), - [Vim.G3dNext.Attributes.InstanceIndexAttribute.AttributeName] = Vim.G3dNext.Attributes.InstanceIndexAttribute.CreateAttributeReader(), - [Vim.G3dNext.Attributes.InstanceNodeAttribute.AttributeName] = Vim.G3dNext.Attributes.InstanceNodeAttribute.CreateAttributeReader(), - [Vim.G3dNext.Attributes.InstanceGroupAttribute.AttributeName] = Vim.G3dNext.Attributes.InstanceGroupAttribute.CreateAttributeReader(), - [Vim.G3dNext.Attributes.InstanceTagAttribute.AttributeName] = Vim.G3dNext.Attributes.InstanceTagAttribute.CreateAttributeReader(), - [Vim.G3dNext.Attributes.InstanceFlagsAttribute.AttributeName] = Vim.G3dNext.Attributes.InstanceFlagsAttribute.CreateAttributeReader(), - [Vim.G3dNext.Attributes.InstanceMinAttribute.AttributeName] = Vim.G3dNext.Attributes.InstanceMinAttribute.CreateAttributeReader(), - [Vim.G3dNext.Attributes.InstanceMaxAttribute.AttributeName] = Vim.G3dNext.Attributes.InstanceMaxAttribute.CreateAttributeReader(), - [Vim.G3dNext.Attributes.MeshInstanceCountAttribute.AttributeName] = Vim.G3dNext.Attributes.MeshInstanceCountAttribute.CreateAttributeReader(), - [Vim.G3dNext.Attributes.MeshIndexCountAttribute.AttributeName] = Vim.G3dNext.Attributes.MeshIndexCountAttribute.CreateAttributeReader(), - [Vim.G3dNext.Attributes.MeshVertexCountAttribute.AttributeName] = Vim.G3dNext.Attributes.MeshVertexCountAttribute.CreateAttributeReader(), - [Vim.G3dNext.Attributes.MeshOpaqueIndexCountAttribute.AttributeName] = Vim.G3dNext.Attributes.MeshOpaqueIndexCountAttribute.CreateAttributeReader(), - [Vim.G3dNext.Attributes.MeshOpaqueVertexCountAttribute.AttributeName] = Vim.G3dNext.Attributes.MeshOpaqueVertexCountAttribute.CreateAttributeReader(), - }; - - // Named Attributes. - - public Vim.G3dNext.Attributes.InstanceFileAttribute InstanceFileAttribute - { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.InstanceFileAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceFileAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.InstanceFileAttribute.AttributeName] = value as IAttribute; - } - - public Vim.G3dNext.Attributes.InstanceIndexAttribute InstanceIndexAttribute - { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.InstanceIndexAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceIndexAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.InstanceIndexAttribute.AttributeName] = value as IAttribute; - } - - public Vim.G3dNext.Attributes.InstanceNodeAttribute InstanceNodeAttribute - { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.InstanceNodeAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceNodeAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.InstanceNodeAttribute.AttributeName] = value as IAttribute; - } - - public Vim.G3dNext.Attributes.InstanceGroupAttribute InstanceGroupAttribute - { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.InstanceGroupAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceGroupAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.InstanceGroupAttribute.AttributeName] = value as IAttribute; - } - - public Vim.G3dNext.Attributes.InstanceTagAttribute InstanceTagAttribute - { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.InstanceTagAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceTagAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.InstanceTagAttribute.AttributeName] = value as IAttribute; - } - - public Vim.G3dNext.Attributes.InstanceFlagsAttribute InstanceFlagsAttribute - { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.InstanceFlagsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceFlagsAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.InstanceFlagsAttribute.AttributeName] = value as IAttribute; - } - - public Vim.G3dNext.Attributes.InstanceMinAttribute InstanceMinAttribute - { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.InstanceMinAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceMinAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.InstanceMinAttribute.AttributeName] = value as IAttribute; - } - - public Vim.G3dNext.Attributes.InstanceMaxAttribute InstanceMaxAttribute - { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.InstanceMaxAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceMaxAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.InstanceMaxAttribute.AttributeName] = value as IAttribute; - } - - public Vim.G3dNext.Attributes.MeshInstanceCountAttribute MeshInstanceCountAttribute - { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.MeshInstanceCountAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshInstanceCountAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.MeshInstanceCountAttribute.AttributeName] = value as IAttribute; - } - - public Vim.G3dNext.Attributes.MeshIndexCountAttribute MeshIndexCountAttribute - { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.MeshIndexCountAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshIndexCountAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.MeshIndexCountAttribute.AttributeName] = value as IAttribute; - } - - public Vim.G3dNext.Attributes.MeshVertexCountAttribute MeshVertexCountAttribute - { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.MeshVertexCountAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshVertexCountAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.MeshVertexCountAttribute.AttributeName] = value as IAttribute; - } - - public Vim.G3dNext.Attributes.MeshOpaqueIndexCountAttribute MeshOpaqueIndexCountAttribute - { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.MeshOpaqueIndexCountAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshOpaqueIndexCountAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.MeshOpaqueIndexCountAttribute.AttributeName] = value as IAttribute; - } - - public Vim.G3dNext.Attributes.MeshOpaqueVertexCountAttribute MeshOpaqueVertexCountAttribute - { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.MeshOpaqueVertexCountAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshOpaqueVertexCountAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.MeshOpaqueVertexCountAttribute.AttributeName] = value as IAttribute; - } - - /// - public IAttribute GetAttribute(Type attributeType) - { - - if (attributeType == typeof(Vim.G3dNext.Attributes.InstanceFileAttribute)) - return InstanceFileAttribute; - - if (attributeType == typeof(Vim.G3dNext.Attributes.InstanceIndexAttribute)) - return InstanceIndexAttribute; - - if (attributeType == typeof(Vim.G3dNext.Attributes.InstanceNodeAttribute)) - return InstanceNodeAttribute; - - if (attributeType == typeof(Vim.G3dNext.Attributes.InstanceGroupAttribute)) - return InstanceGroupAttribute; - - if (attributeType == typeof(Vim.G3dNext.Attributes.InstanceTagAttribute)) - return InstanceTagAttribute; - - if (attributeType == typeof(Vim.G3dNext.Attributes.InstanceFlagsAttribute)) - return InstanceFlagsAttribute; - - if (attributeType == typeof(Vim.G3dNext.Attributes.InstanceMinAttribute)) - return InstanceMinAttribute; - - if (attributeType == typeof(Vim.G3dNext.Attributes.InstanceMaxAttribute)) - return InstanceMaxAttribute; - - if (attributeType == typeof(Vim.G3dNext.Attributes.MeshInstanceCountAttribute)) - return MeshInstanceCountAttribute; - - if (attributeType == typeof(Vim.G3dNext.Attributes.MeshIndexCountAttribute)) - return MeshIndexCountAttribute; - - if (attributeType == typeof(Vim.G3dNext.Attributes.MeshVertexCountAttribute)) - return MeshVertexCountAttribute; - - if (attributeType == typeof(Vim.G3dNext.Attributes.MeshOpaqueIndexCountAttribute)) - return MeshOpaqueIndexCountAttribute; - - if (attributeType == typeof(Vim.G3dNext.Attributes.MeshOpaqueVertexCountAttribute)) - return MeshOpaqueVertexCountAttribute; - - throw new ArgumentException("Type {attributeType.ToString()} is not supported."); - } - - public IAttribute MergeAttribute(string attributeName, IReadOnlyList otherCollections) - { - var collections = otherCollections.Prepend(this).ToArray(); - switch (attributeName) - { - - case Vim.G3dNext.Attributes.InstanceFileAttribute.AttributeName: - { - // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); - } - - case Vim.G3dNext.Attributes.InstanceIndexAttribute.AttributeName: - { - // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); - } - - case Vim.G3dNext.Attributes.InstanceNodeAttribute.AttributeName: - { - // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); - } - - case Vim.G3dNext.Attributes.InstanceGroupAttribute.AttributeName: - { - // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); - } - - case Vim.G3dNext.Attributes.InstanceTagAttribute.AttributeName: - { - // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); - } - - case Vim.G3dNext.Attributes.InstanceFlagsAttribute.AttributeName: - { - // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); - } - - case Vim.G3dNext.Attributes.InstanceMinAttribute.AttributeName: - { - // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); - } - - case Vim.G3dNext.Attributes.InstanceMaxAttribute.AttributeName: - { - // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); - } - - case Vim.G3dNext.Attributes.MeshInstanceCountAttribute.AttributeName: - { - // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); - } - - case Vim.G3dNext.Attributes.MeshIndexCountAttribute.AttributeName: - { - // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); - } - - case Vim.G3dNext.Attributes.MeshVertexCountAttribute.AttributeName: - { - // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); - } - - case Vim.G3dNext.Attributes.MeshOpaqueIndexCountAttribute.AttributeName: - { - // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); - } - - case Vim.G3dNext.Attributes.MeshOpaqueVertexCountAttribute.AttributeName: - { - // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); - } - - default: - throw new ArgumentException(nameof(attributeName)); - } - } - - public void Validate() - { - // Ensure all the indices are either -1 or within the bounds of the attributes they are indexing into. - - } - } - public partial class MaterialAttributeCollection : IAttributeCollection - { - public IEnumerable AttributeNames - => Attributes.Keys; - - public long GetSize() - => Attributes.Values.Sum(a => a.Data.LongLength * a.AttributeDescriptor.DataElementSize); - - public IDictionary Attributes { get; } - = new Dictionary - { - [Vim.G3dNext.Attributes.MaterialColorAttribute.AttributeName] = new Vim.G3dNext.Attributes.MaterialColorAttribute(), - [Vim.G3dNext.Attributes.MaterialGlossinessAttribute.AttributeName] = new Vim.G3dNext.Attributes.MaterialGlossinessAttribute(), - [Vim.G3dNext.Attributes.MaterialSmoothnessAttribute.AttributeName] = new Vim.G3dNext.Attributes.MaterialSmoothnessAttribute(), - }; - - public IDictionary AttributeReaders { get; } - = new Dictionary - { - [Vim.G3dNext.Attributes.MaterialColorAttribute.AttributeName] = Vim.G3dNext.Attributes.MaterialColorAttribute.CreateAttributeReader(), - [Vim.G3dNext.Attributes.MaterialGlossinessAttribute.AttributeName] = Vim.G3dNext.Attributes.MaterialGlossinessAttribute.CreateAttributeReader(), - [Vim.G3dNext.Attributes.MaterialSmoothnessAttribute.AttributeName] = Vim.G3dNext.Attributes.MaterialSmoothnessAttribute.CreateAttributeReader(), - }; - - // Named Attributes. - - public Vim.G3dNext.Attributes.MaterialColorAttribute MaterialColorAttribute - { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.MaterialColorAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MaterialColorAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.MaterialColorAttribute.AttributeName] = value as IAttribute; - } - - public Vim.G3dNext.Attributes.MaterialGlossinessAttribute MaterialGlossinessAttribute - { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.MaterialGlossinessAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MaterialGlossinessAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.MaterialGlossinessAttribute.AttributeName] = value as IAttribute; - } - - public Vim.G3dNext.Attributes.MaterialSmoothnessAttribute MaterialSmoothnessAttribute - { - get => Attributes.TryGetValue(Vim.G3dNext.Attributes.MaterialSmoothnessAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MaterialSmoothnessAttribute : default; - set => Attributes[Vim.G3dNext.Attributes.MaterialSmoothnessAttribute.AttributeName] = value as IAttribute; - } - - /// - public IAttribute GetAttribute(Type attributeType) - { - - if (attributeType == typeof(Vim.G3dNext.Attributes.MaterialColorAttribute)) - return MaterialColorAttribute; - - if (attributeType == typeof(Vim.G3dNext.Attributes.MaterialGlossinessAttribute)) - return MaterialGlossinessAttribute; - - if (attributeType == typeof(Vim.G3dNext.Attributes.MaterialSmoothnessAttribute)) - return MaterialSmoothnessAttribute; - - throw new ArgumentException("Type {attributeType.ToString()} is not supported."); - } - - public IAttribute MergeAttribute(string attributeName, IReadOnlyList otherCollections) - { - var collections = otherCollections.Prepend(this).ToArray(); - switch (attributeName) - { - - case Vim.G3dNext.Attributes.MaterialColorAttribute.AttributeName: - { - // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); - } - - case Vim.G3dNext.Attributes.MaterialGlossinessAttribute.AttributeName: - { - // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); - } - - case Vim.G3dNext.Attributes.MaterialSmoothnessAttribute.AttributeName: - { - // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); - } - - default: - throw new ArgumentException(nameof(attributeName)); - } - } - - public void Validate() - { - // Ensure all the indices are either -1 or within the bounds of the attributes they are indexing into. - - } - } -} diff --git a/src/cs/g3d/temp/Vim.G3dNext.Attributes/Vim.G3dNext.Attributes.csproj b/src/cs/g3d/temp/Vim.G3dNext.Attributes/Vim.G3dNext.Attributes.csproj deleted file mode 100644 index 2bded7f0..00000000 --- a/src/cs/g3d/temp/Vim.G3dNext.Attributes/Vim.G3dNext.Attributes.csproj +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - netstandard2.0 - true - - G3D is a simple, efficient, generic binary format for storing and transmitting geometry. The G3D format is designed to be used either as a serialization format or as an in-memory data structure. G3D can represent triangular meshes, quadrilateral meshes, polygonal meshes, point clouds, and line segments. - It can be easily and efficiently deserialized and rendered in different languages and on different platforms. - - LICENSE.txt - https://github.com/vimaec/g3d - https://github.com/vimaec/g3d - GitHub - 2.0.0 - true - true - true - snupkg - - - - - - - - - - - - - - diff --git a/src/cs/g3d/temp/Vim.G3dNext.Attributes/VimAttributeCollectionExtensions.cs b/src/cs/g3d/temp/Vim.G3dNext.Attributes/VimAttributeCollectionExtensions.cs deleted file mode 100644 index 75498793..00000000 --- a/src/cs/g3d/temp/Vim.G3dNext.Attributes/VimAttributeCollectionExtensions.cs +++ /dev/null @@ -1,86 +0,0 @@ -using System.Linq; - -namespace Vim.G3dNext.Attributes -{ - public static class VimAttributeCollectionExtensions - { - public static int GetMeshSubmeshStart(this VimAttributeCollection c, int mesh) - { - return c.MeshSubmeshOffsetAttribute.TypedData[mesh]; - } - - public static int GetMeshSubmeshEnd(this VimAttributeCollection c, int mesh) - { - return mesh + 1 < c.GetMeshCount() - ? c.MeshSubmeshOffsetAttribute.TypedData[mesh +1] - : c.GetSubmeshCount(); - } - - public static int GetMeshSubmeshCount(this VimAttributeCollection c, int mesh) - { - return c.GetMeshSubmeshEnd(mesh) - c.GetMeshSubmeshStart(mesh); - } - - public static int GetFaceCount(this VimAttributeCollection c) - { - var cornersPerFace = c.GetCornersPerFaceCount(); - var indexCount = c.GetIndexCount(); - - return cornersPerFace != 0 ? indexCount / cornersPerFace : -1; - } - - /// - /// The number of corners per face. A value of 3 designates that all faces are triangles (a triangle has 3 corners). - /// - public static int GetCornersPerFaceCount(this VimAttributeCollection c) - => c.CornersPerFaceAttribute?.TypedData?.FirstOrDefault() ?? 0; - - /// - /// The total number of indices. - /// - public static int GetIndexCount(this VimAttributeCollection c) - => c.IndexAttribute?.TypedData?.Length ?? 0; - - /// - /// The total number of vertices. - /// - public static int GetVertexCount(this VimAttributeCollection c) - => c.VertexAttribute?.TypedData?.Length ?? 0; - - /// - /// The total number of instances. - /// - public static int GetInstanceCount(this VimAttributeCollection c) - => c.InstanceTransformAttribute?.TypedData?.Length ?? 0; - - /// - /// The total number of meshes. - /// - public static int GetMeshCount(this VimAttributeCollection c) - => c.MeshSubmeshOffsetAttribute?.TypedData?.Length ?? 0; - - /// - /// The total number of submeshes. - /// - public static int GetSubmeshCount(this VimAttributeCollection c) - => c.SubmeshIndexOffsetAttribute?.TypedData?.Length ?? 0; - - /// - /// The total number of materials. - /// - public static int GetMaterialCount(this VimAttributeCollection c) - => c.MaterialColorAttribute?.TypedData?.Length ?? 0; - - /// - /// The total number of shape vertices. - /// - public static int GetShapeVertexCount(this VimAttributeCollection c) - => c.ShapeVertexAttribute?.TypedData?.Length ?? 0; - - /// - /// The total number of shapes. - /// - public static int GetShapeCount(this VimAttributeCollection c) - => c.ShapeVertexOffsetAttribute?.TypedData?.Length ?? 0; - } -} diff --git a/src/cs/g3d/temp/Vim.G3dNext.Tests/AssimpTests.cs b/src/cs/g3d/temp/Vim.G3dNext.Tests/AssimpTests.cs deleted file mode 100644 index e64b4563..00000000 --- a/src/cs/g3d/temp/Vim.G3dNext.Tests/AssimpTests.cs +++ /dev/null @@ -1,237 +0,0 @@ -using Assimp; -using NUnit.Framework; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using Vim.G3dNext.AssimpWrapper; -using Vim.G3dNext.Attributes; -using Vim.Math3d; - -using NextG3d = Vim.G3dNext.G3DNext; - -namespace Vim.G3dNext.Tests -{ - [TestFixture] - public static class AssimpTests - { - public class FileLoadData - { - public FileLoadData(string filePath) - => SourceFile = new FileInfo(filePath); - - public string ShortName => Path.GetFileName(SourceFile.FullName); - public int NumMeshes => Scene?.MeshCount ?? 0; - public FileInfo SourceFile; - public FileInfo G3DFile; - public long MSecToOpen; - public long MSecToSaveG3d; - public long MSecToOpenG3d; - public long MSecToConvert; - public long MemoryConsumption; - public long MemoryConsumptionG3d; - public Exception Error; - public Scene Scene; - public NextG3d G3d; - } - - public static readonly string ProjectFolder = new DirectoryInfo(Properties.Resources.ProjDir.Trim()).FullName; - public static string RootFolder = Path.Combine(ProjectFolder, "..", ".."); - public static string TestInputFolder = Path.Combine(RootFolder, "data", "models"); - public static string TestOutputFolder = Path.Combine(RootFolder, "out"); - - public static IEnumerable GetInputFiles() - => Directory.GetFiles(TestInputFolder, "*.*", SearchOption.AllDirectories); - - public static void ValidateSame(Object a, Object b, string name = "") - { - if (!a.Equals(b)) - throw new Exception($"Values {a} and {b} are different {name}"); - } - - public static void ValidateSameG3D(NextG3d g1, NextG3d g2) - { - var (ac1, ac2) = (g1.AttributeCollection, g2.AttributeCollection); - - ValidateSame(ac1.GetCornersPerFaceCount(), ac2.GetCornersPerFaceCount(), "GetCornersPerFaceCount"); - ValidateSame(ac1.GetIndexCount(), ac2.GetIndexCount(), "GetIndexCount"); - ValidateSame(ac1.GetVertexCount(), ac2.GetVertexCount(), "GetVertexCount"); - ValidateSame(ac1.GetInstanceCount(), ac2.GetInstanceCount(), "GetInstanceCount"); - ValidateSame(ac1.GetMeshCount(), ac2.GetMeshCount(), "GetMeshCount"); - ValidateSame(ac1.Attributes.Count, ac2.Attributes.Count, "Attribute Count"); - - foreach (var (k, attr1) in ac1.Attributes) - { - var attr2 = ac2.Attributes[k]; - ValidateSame(attr1.Name, attr2.Name, $"Attribute[{k}].Name"); - ValidateSame(attr1.Data.Length, attr2.Data.Length, $"Attribute[{k}].Data.Length"); - } - } - - [Test] - [Platform(Exclude = "Linux,Unix", Reason = "AssimpNet is failing to load its dependency on 'libdl.so'.")] - public static void OpenAndConvertAssimpFiles() - { - var testDir = "";//PrepareTestDir(); - - var files = GetInputFiles() - .Where(AssimpLoader.CanLoad) - .Select(f => new FileLoadData(f)) - .ToArray(); - - // Load all the files - foreach (var f in files) - { - try - { - (f.MemoryConsumption, f.MSecToOpen) = - TestUtils.GetMemoryConsumptionAndMSecElapsed(() => - f.Scene = AssimpLoader.Load(f.SourceFile.FullName)); - } - catch (Exception e) - { - f.Error = e; - } - } - - // Convert all the Assimp scenes to G3D - foreach (var f in files) - { - if (f.Scene == null) continue; - - try - { - f.MSecToConvert = TestUtils.GetMSecElapsed(() => - f.G3d = f.Scene.ToG3d()); - } - catch (Exception e) - { - f.Error = e; - } - } - - // Save all the G3D scenes - foreach (var f in files) - { - if (f.G3d == null) continue; - - try - { - var outputFilePath = Path.Combine(testDir, f.ShortName + ".g3d"); - f.G3DFile = new FileInfo(outputFilePath); - - f.MSecToSaveG3d = TestUtils.GetMSecElapsed(() => - f.G3d.Write(outputFilePath)); - } - catch (Exception e) - { - f.Error = e; - } - } - - // Try reading back in all of the G3D scenes, measure load times and the memory consumption - foreach (var f in files) - { - if (f.G3DFile == null) continue; - - try - { - NextG3d localG3d = null; - - (f.MemoryConsumptionG3d, f.MSecToOpenG3d) = - TestUtils.GetMemoryConsumptionAndMSecElapsed(() => - NextG3d.TryRead(f.G3DFile.FullName, out localG3d)); - - ValidateSameG3D(f.G3d, localG3d); - } - catch (Exception e) - { - f.Error = e; - } - } - - // Output the header for data - Console.WriteLine( - "Importer," + - "Extension," + - "File Name," + - "File Size(KB)," + - "Load Time(s)," + - "Memory(KB)," + - "# Meshes," + - "Time to Convert," + - "Time to Write G3D," + - "G3D File Size(KB)," + - "G3D Memory(KB)", - "G3D Load Time(s)", - "Error"); - - // Output the data rows - foreach (var f in files) - { - Console.WriteLine( - "Assimp," + - $"{Path.GetExtension(f.ShortName)}," + - $"{f.ShortName}," + - $"{f.SourceFile?.Length / 1000}," + - $"{f.MSecToOpen / 100f}," + - $"{f.MemoryConsumption / 1000}," + - $"{f.NumMeshes}," + - $"{f.MSecToConvert / 100f}," + - $"{f.MSecToSaveG3d / 100f}," + - $"{f.G3DFile?.Length / 1000}," + - $"{f.MemoryConsumptionG3d / 1000}," + - $"{f.MSecToOpenG3d / 100f}," + - $"{f.Error}"); - } - - Assert.AreEqual(0, files.Count(f => f.Error != null), "Errors occurred"); - } - - public static NextG3d LoadAssimpFile(string filePath) - { - using (var context = new AssimpContext()) - { - var scene = context.ImportFile(filePath); - Assert.AreEqual(1, scene.Meshes.Count); - return scene.Meshes[0].ToVimG3d(); - } - } - - [Test] - [Platform(Exclude = "Linux,Unix", Reason = "AssimpNet is failing to load its dependency on 'libdl.so'.")] - public static void TestWriters() - { - var testDir = "";//PrepareTestDir(); - - var fileName = Path.Combine(TestInputFolder, "PLY", "Wuson.ply"); - - var outputFileName = @"test"; - outputFileName = Path.Combine(testDir, outputFileName); - - var g3d = LoadAssimpFile(fileName); - - g3d.WritePly(outputFileName + ".ply"); - g3d.WriteObj(outputFileName + ".obj"); - - // TODO compare the PLY, the OBJ and the original file. - - var g3dFromPly = LoadAssimpFile(outputFileName + ".ply"); - var g3dFromObj = LoadAssimpFile(outputFileName + ".obj"); - - { - var ac1 = g3d.AttributeCollection; - var ac2 = g3dFromPly.AttributeCollection; - Assert.AreEqual(ac1.GetCornersPerFaceCount(), ac2.GetCornersPerFaceCount()); - Assert.AreEqual(ac1.GetFaceCount(), ac2.GetFaceCount()); - Assert.AreEqual(ac1.GetIndexCount(), ac2.GetIndexCount()); - Assert.AreEqual(ac1.GetVertexCount(), ac2.GetVertexCount()); - Assert.AreEqual(ac1.GetInstanceCount(), ac2.GetInstanceCount()); - Assert.AreEqual(ac1.GetMeshCount(), ac2.GetMeshCount()); - } - - // BUG: Assimp ignores the OBJ index buffer. God knows why. - //CompareG3D(g3d, g3dFromObj); - } - } -} diff --git a/src/cs/g3d/temp/Vim.G3dNext.Tests/FileUtils.cs b/src/cs/g3d/temp/Vim.G3dNext.Tests/FileUtils.cs deleted file mode 100644 index 6ee3b602..00000000 --- a/src/cs/g3d/temp/Vim.G3dNext.Tests/FileUtils.cs +++ /dev/null @@ -1,183 +0,0 @@ -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading.Tasks; -using System.Diagnostics; -using System.Threading; -using Azure.Storage.Blobs; -using Azure.Storage.Blobs.Models; -using Vim.BFast; -using Vim.LinqArray; -using Vim.G3d; -using System.IO.Compression; -using Vim.Math3d; -using System; - -namespace Vim.G3dNext -{ - public static class FileUtils - { - public static void ResetFolder(string path) - { - - if (Directory.Exists(path)) - { - Directory.Delete(path, true); - } - Directory.CreateDirectory(path); - } - - public static VimG3d LoadG3d(string path) - { - var time = Stopwatch.StartNew(); - var file = new FileStream(path, FileMode.Open); - var geometry = file.GetBFastBufferReader("geometry"); - geometry.Seek(); - var g3d = VimG3d.FromStream(file); - Console.WriteLine("LoadG3d " + time.ElapsedMilliseconds / 1000f); - return g3d; - } - - public static void SplitVim(string path, string name) - { - var time = Stopwatch.StartNew(); - var vim = VimScene.LoadVim(path, new DataFormat.LoadOptions() { - SkipAssets = true, - SkipGeometry = true, - SkipHeader = true} - ); - Console.WriteLine("LoadVim " + time.ElapsedMilliseconds / 1000f); - - time.Restart(); - var g3d = LoadG3d(path); - Console.WriteLine("VimG3d " + time.ElapsedMilliseconds / 1000f); - - time.Restart(); - var meshes = g3d.GetMeshes().ToArray(); - PolyStopwatch.instance.Print(); - Console.WriteLine("GetMeshes " + time.ElapsedMilliseconds / 1000f); - - time.Restart(); - var nodeElements = vim.DocumentModel.NodeElementIndex.ToArray(); - var categoryName = vim.DocumentModel.CategoryName; - var elementCategory = vim.DocumentModel.ElementCategoryIndex; - - // Remove select => long once using latest data model. - var nodeElementIds = nodeElements.Select(n => n < 0 || n > vim.DocumentModel.ElementId.Count - ? (long)-1 - : (long)vim.DocumentModel.ElementId[n] - ).ToArray(); - Console.WriteLine("nodes " + time.ElapsedMilliseconds / 1000f); - - time.Restart(); - var getMeshName = (MeshG3d mesh) => - { - var node = mesh.instanceNodes[0]; - - if (node < 0 || node >= nodeElements.Length) return ""; - var element = nodeElements [node]; - - if (element < 0 || element >= elementCategory.Count) return ""; - var category = elementCategory[element]; - - if (category < 0 || category >= categoryName.Count) return ""; - var name = categoryName[category]; - - return name; - }; - - meshes = meshes.OrderByDescending((m) => ( - GetPriority(getMeshName(m)), - m.GetAABB().MaxSide) - ).ToArray(); - Console.WriteLine("OrderByDescending " + time.ElapsedMilliseconds / 1000f); - - time.Restart(); - var meshBuffers = meshes.Select((m, i) => - { - return m.g3d.ToBytes() - .GzipBytes() - .ToNamedBuffer($"mesh_{i}"); - }); - Console.WriteLine("meshBuffers " + time.ElapsedMilliseconds / 1000f); - - time.Restart(); - var index = meshes.ToMeshIndex(g3d, nodeElements, nodeElementIds); - var indexBuffer = index.g3d.ToBytes() - .GzipBytes() - .ToNamedBuffer("index"); - Console.WriteLine("indexBuffer " + time.ElapsedMilliseconds / 1000f); - - time.Restart(); - var mat = g3d.getMaterials(); - var matBuffer = mat.g3d.ToBytes() - .GzipBytes() - .ToNamedBuffer("materials"); - Console.WriteLine("matBuffer " + time.ElapsedMilliseconds / 1000f); - - time.Restart(); - var bfastBuilder = new BFastBuilder(); - bfastBuilder.Add(indexBuffer); - bfastBuilder.Add(matBuffer); - - foreach (var mesh in meshBuffers) - { - bfastBuilder.Add(mesh); - } - - bfastBuilder.Write($"./{name}.vimx"); - Console.WriteLine("Write " + time.ElapsedMilliseconds / 1000f); - - } - - - static int GetPriority(string value) - { - if (string.IsNullOrWhiteSpace(value)) return 0; - - if (value.Contains("Topography")) return 110; - if (value.Contains("Floor")) return 100; - if (value.Contains("Slab")) return 100; - if (value.Contains("Ceiling")) return 90; - if (value.Contains("Roof")) return 90; - - if (value.Contains("Curtain")) return 80; - if (value.Contains("Wall")) return 80; - if (value.Contains("Window")) return 70; - - if (value.Contains("Column")) return 60; - if (value.Contains("Structural")) return 60; - - if (value.Contains("Stair")) return 40; - if (value.Contains("Doors")) return 30; - - return 1; - } - - static AABox[] ComputeBoxes(SceneG3d index, MeshG3d[] meshes) - { - var boxes = new List(); - for (var i = 0; i < index.instanceFiles.Length; i++) - { - var m = index.instanceFiles[i]; - var instance = index.instanceIndices[i]; - var mesh = meshes[m]; - boxes.Add(mesh.GetInstanceAABB(instance)); - } - return boxes.ToArray(); - } - - public static byte[] GzipBytes(this byte[] inputBytes) - { - using (var memoryStream = new MemoryStream()) - { - using (var gzipStream = new DeflateStream(memoryStream, CompressionMode.Compress, true)) - { - gzipStream.Write(inputBytes, 0, inputBytes.Length); - } - return memoryStream.ToArray(); - } - } - } - -} diff --git a/src/cs/g3d/temp/Vim.G3dNext.Tests/TestUtils.cs b/src/cs/g3d/temp/Vim.G3dNext.Tests/TestUtils.cs deleted file mode 100644 index 7f7322fd..00000000 --- a/src/cs/g3d/temp/Vim.G3dNext.Tests/TestUtils.cs +++ /dev/null @@ -1,113 +0,0 @@ -using System; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Net.Http; -using System.Runtime.CompilerServices; -using System.Threading.Tasks; - -namespace Vim.G3dNext.Tests; - -public static class TestUtils -{ - public static readonly string ProjectFolder = new DirectoryInfo(Properties.Resources.ProjDir.Trim()).FullName; - public static string RootFolder = Path.Combine(ProjectFolder, "..", ".."); - public static string TestInputFolder = Path.Combine(RootFolder, "data", "models"); - public static string TestOutputFolder = Path.Combine(RootFolder, "out"); - - public static async Task DownloadFileAsync(string url) - { - using (var httpClient = new HttpClient()) - { - using (var response = await httpClient.GetAsync(url, HttpCompletionOption.ResponseHeadersRead)) - { - response.EnsureSuccessStatusCode(); - var memoryStream = new MemoryStream(); - await response.Content.CopyToAsync(memoryStream); - memoryStream.Seek(0, SeekOrigin.Begin); - return memoryStream; - } - } - } - - public static string PrepareTestDir([CallerMemberName] string? testName = null) - { - if (testName == null) - throw new ArgumentException(nameof(testName)); - - var testDir = Path.Combine(TestOutputFolder, testName); - - // Prepare the test directory - if (Directory.Exists(testDir)) - Directory.Delete(testDir, true); - Directory.CreateDirectory(testDir); - - return testDir; - } - - public static (long, long) GetMemoryConsumptionAndMSecElapsed(Action action) - { - var time = 0L; - var mem = GetMemoryConsumption( - () => time = GetMSecElapsed(action)); - return (mem, time); - } - - public static long GetMSecElapsed(Action action) - { - var sw = Stopwatch.StartNew(); - action(); - return sw.ElapsedMilliseconds; - } - - /// - /// Creates a directory if needed, or clears all of its contents otherwise - /// - public static string CreateAndClearDirectory(string dirPath) - { - if (!Directory.Exists(dirPath)) - Directory.CreateDirectory(dirPath); - else - DeleteFolderContents(dirPath); - return dirPath; - } - - /// - /// Deletes all contents in a folder - /// - /// - /// https://stackoverflow.com/questions/1288718/how-to-delete-all-files-and-folders-in-a-directory - /// - private static void DeleteFolderContents(string folderPath) - { - var di = new DirectoryInfo(folderPath); - foreach (var dir in di.EnumerateDirectories().AsParallel()) - DeleteFolderAndAllContents(dir.FullName); - foreach (var file in di.EnumerateFiles().AsParallel()) - file.Delete(); - } - - /// - /// Deletes everything in a folder and then the folder. - /// - private static void DeleteFolderAndAllContents(string folderPath) - { - if (!Directory.Exists(folderPath)) - return; - - DeleteFolderContents(folderPath); - Directory.Delete(folderPath); - } - - // NOTE: Calling a function generates additional memory - private static long GetMemoryConsumption(Action action) - { - GC.Collect(); - GC.WaitForPendingFinalizers(); - var memBefore = GC.GetTotalMemory(true); - action(); - GC.Collect(); - GC.WaitForPendingFinalizers(); - return GC.GetTotalMemory(true) - memBefore; - } -} diff --git a/src/cs/g3d/temp/Vim.G3dNext.Tests/Vim.G3dNext.Tests.csproj b/src/cs/g3d/temp/Vim.G3dNext.Tests/Vim.G3dNext.Tests.csproj deleted file mode 100644 index e9e647cf..00000000 --- a/src/cs/g3d/temp/Vim.G3dNext.Tests/Vim.G3dNext.Tests.csproj +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - net6.0 - enable - - false - - - - - - - - - - - - - - - - - - - - - True - True - Resources.resx - - - - - - ResXFileCodeGenerator - Resources.Designer.cs - - - - - - - diff --git a/src/cs/g3d/temp/Vim.G3dNext.Tests/VimG3dTests.cs b/src/cs/g3d/temp/Vim.G3dNext.Tests/VimG3dTests.cs deleted file mode 100644 index 19777128..00000000 --- a/src/cs/g3d/temp/Vim.G3dNext.Tests/VimG3dTests.cs +++ /dev/null @@ -1,270 +0,0 @@ -using NUnit.Framework; -using NUnit.Framework.Internal; -using System.IO; -using System.Linq; -using System.Threading.Tasks; -using Vim.BFast; -using Vim.LinqArray; -using Vim.G3d; -using Vim.G3dNext.Attributes; -using Vim.Math3d; - -using static Vim.G3dNext.Tests.TestUtils; - -namespace Vim.G3dNext.Tests; - -[TestFixture] -public static class VimG3dTests -{ - [Test] - public static void FileRepackage() - { - //var name = "_MAIN-AEI_HSIB-R20.v1.2.73"; - var name = "residence"; - //var name = "tower"; - var path = $"./{name}.vim"; - - FileUtils.SplitVim(path, name); - } - - [Test] - public static async Task Filter() - { - var file = await DownloadFileAsync("https://vimdevelopment01storage.blob.core.windows.net/samples/residence_nozip.vim"); - var options = new DataFormat.LoadOptions() - { - SkipAssets = true, - SkipEntities = true, - SkipHeader = true, - SkipStrings = true - }; - - var vim = VimScene.LoadVim(file, options); - var bytes = vim.Document.Geometry.WriteToBytes(); - G3DNext.TryRead(bytes, out var g3d); - var next = new VimG3d(g3d); - var instances = Enumerable.Range(1, 1000).ToArray(); - var filtered = next.Filter(instances); - } - - [Test] - public static void AttributeDescriptorTest() - { - var attributeNames = new VimAttributeCollection().AttributeNames; - foreach (var name in attributeNames) - { - // Test that the attribute descriptor parsing works as intended. - var parsed = AttributeDescriptor.TryParse(name, out var desc); - Assert.IsTrue(parsed); - Assert.AreEqual(name, desc.Name); - } - } - - [Test] - public static void TriangleTest() - { - // Serialize a triangle g3d as bytes and read it back. - var vertices = new[] - { - new Vector3(0, 0, 0), - new Vector3(0, 1, 0), - new Vector3(0, 1, 1) - }; - - var indices = new[] { 0, 1, 2 }; - - //var g3d = new G3DBuilder() - // .AddVertices(vertices.ToIArray()) - // .AddIndices(indices.ToIArray()) - // .Add(materialIndices.ToIArray().ToFaceMaterialAttribute()) - // .ToVimG3d(); - var g3d1 = new G3DNext(); - var ac1 = g3d1.AttributeCollection; - ac1.CornersPerFaceAttribute.TypedData = new[] { 3 }; - ac1.VertexAttribute.TypedData = vertices; - ac1.IndexAttribute.TypedData = indices; - - var bytes = g3d1.ToBytes(); - - if (!G3DNext.TryRead(bytes, out var g)) - Assert.Fail("Could not read g3d bytes."); - - Assert.IsNotNull(g); - - var ac2 = g.AttributeCollection; - - Assert.AreEqual(3, ac2.GetVertexCount()); - Assert.AreEqual(3, ac2.GetIndexCount()); - Assert.AreEqual(3, ac2.GetCornersPerFaceCount()); - Assert.AreEqual(0, ac2.GetMeshCount()); - Assert.AreEqual(0, ac2.GetInstanceCount()); - - Assert.AreEqual(vertices, ac2.VertexAttribute.TypedData); - Assert.AreEqual(indices, ac2.IndexAttribute.TypedData); - } - - [Test] - public static void UnexpectedG3dTest() - { - var testDir = PrepareTestDir(); - var input = new FileInfo(Path.Combine(TestInputFolder, "G3D", "unexpected.g3d")); - - using var stream = input.OpenRead(); - - var result = G3DNext.TryRead(stream, out var g3d); - Assert.IsTrue(result); - - var cornerAttribute = g3d.AttributeCollection.Attributes[IndexAttribute.AttributeName]; - Assert.IsNotNull(cornerAttribute); - } - - [Test] - public static void ReadG3dInVimTest() - { - var testDir = PrepareTestDir(); - var inputVim = new FileInfo(Path.Combine(TestInputFolder, "VIM", "Mechanical_Room.r2017.vim")); - - using var stream = inputVim.OpenRead(); - - G3DNext? g3d = null; - stream.ReadBFast((s, name, size) => - { - if (name == "geometry") - G3DNext.TryRead(s, out g3d); - else - stream.Seek(size, SeekOrigin.Current); - - return null; - }); - - Assert.IsNotNull(g3d); - } - - public static G3DNext CreateTestG3d() - { - var g3d = new G3DNext(); - var attrs = g3d.AttributeCollection; - - attrs.CornersPerFaceAttribute.TypedData = new int[] { 3 }; - attrs.VertexAttribute.TypedData = new Vector3[] { Vector3.Zero, Vector3.UnitX, Vector3.UnitY, Vector3.UnitZ }; - attrs.IndexAttribute.TypedData = new int[] { 0, 1, 2, 0, 3, 2, 1, 3, 2 }; - attrs.SubmeshIndexOffsetAttribute.TypedData = new int[] { 0, 3, 6 }; - attrs.SubmeshMaterialAttribute.TypedData = new int[] { 0 }; - attrs.MeshSubmeshOffsetAttribute.TypedData = new int[] { 0 }; - attrs.InstanceTransformAttribute.TypedData = new Matrix4x4[] { Matrix4x4.Identity }; - attrs.InstanceMeshAttribute.TypedData = new int[] { 0 }; - attrs.InstanceParentAttribute.TypedData = new int[] { -1 }; - attrs.MaterialColorAttribute.TypedData = new Vector4[] { new Vector4(0.25f, 0.5f, 0.75f, 1) }; - attrs.MaterialGlossinessAttribute.TypedData = new float[] { .95f }; - attrs.MaterialSmoothnessAttribute.TypedData = new float[] { .5f }; - - g3d.Validate(); - - return g3d; - } - - [Test] - public static void WriteG3dTest() - { - var testDir = PrepareTestDir(); - - var g3d = CreateTestG3d(); - - var g3dFilePath = Path.Combine(testDir!, "test.g3d"); - g3d.Write(g3dFilePath); - - var readResult = G3DNext.TryRead(g3dFilePath, out var readG3d); - Assert.IsTrue(readResult); - - // Compare the buffers. - foreach (var attributeName in readG3d.AttributeCollection.AttributeNames) - { - var attr0 = g3d.AttributeCollection.Attributes[attributeName]; - var attr1 = readG3d.AttributeCollection.Attributes[attributeName]; - Assert.AreEqual(attr0.Data, attr1.Data); - } - } - - [Test] - public static void MergeG3dTest() - { - var testDir = PrepareTestDir(); - - var g3d = CreateTestG3d(); - - var mergedG3d = new[] { g3d, g3d }.Merge(); - - var g3dFilePath = Path.Combine(testDir!, "merged.g3d"); - mergedG3d.Write(g3dFilePath); - - var readResult = G3DNext.TryRead(g3dFilePath, out var readG3d); - Assert.IsTrue(readResult); - - var mac = readG3d.AttributeCollection; - - { - var merged = g3d.AttributeCollection.CornersPerFaceAttribute.TypedData; - Assert.AreEqual(merged, mac.CornersPerFaceAttribute.TypedData); - } - - { - var merged = Enumerable.Repeat(g3d.AttributeCollection.VertexAttribute.TypedData, 2).SelectMany(v => v).ToArray(); - Assert.AreEqual(merged, mac.VertexAttribute.TypedData); - } - - { - var tmp = g3d.AttributeCollection.IndexAttribute.TypedData; - var merged = new[] { tmp, tmp.Select(i => i + g3d.AttributeCollection.GetVertexCount()).ToArray() }.SelectMany(v => v).ToArray(); - Assert.AreEqual(merged, mac.IndexAttribute.TypedData); - } - - { - var tmp = g3d.AttributeCollection.SubmeshIndexOffsetAttribute.TypedData; - var merged = new[] { tmp, tmp.Select(i => i + g3d.AttributeCollection.GetIndexCount()).ToArray() }.SelectMany(v => v).ToArray(); - Assert.AreEqual(merged, mac.SubmeshIndexOffsetAttribute.TypedData); - } - - { - var tmp = g3d.AttributeCollection.SubmeshMaterialAttribute.TypedData; - var merged = new[] { tmp, tmp.Select(i => i + g3d.AttributeCollection.GetMaterialCount()).ToArray() }.SelectMany(v => v).ToArray(); - Assert.AreEqual(merged, mac.SubmeshMaterialAttribute.TypedData); - } - - { - var tmp = g3d.AttributeCollection.MeshSubmeshOffsetAttribute.TypedData; - var merged = new[] { tmp, tmp.Select(i => i + g3d.AttributeCollection.GetSubmeshCount()).ToArray() }.SelectMany(v => v).ToArray(); - Assert.AreEqual(merged, mac.MeshSubmeshOffsetAttribute.TypedData); - } - - { - var merged = Enumerable.Repeat(g3d.AttributeCollection.InstanceTransformAttribute.TypedData, 2).SelectMany(v => v).ToArray(); - Assert.AreEqual(merged, mac.InstanceTransformAttribute.TypedData); - } - - { - var tmp = g3d.AttributeCollection.InstanceMeshAttribute.TypedData; - var merged = new[] { tmp, tmp.Select(i => i + g3d.AttributeCollection.GetMeshCount()).ToArray() }.SelectMany(v => v).ToArray(); - Assert.AreEqual(merged, mac.InstanceMeshAttribute.TypedData); - } - - { - var merged = Enumerable.Repeat(g3d.AttributeCollection.InstanceParentAttribute.TypedData, 2).SelectMany(v => v).ToArray(); - Assert.AreEqual(merged, mac.InstanceParentAttribute.TypedData); - } - - { - var merged = Enumerable.Repeat(g3d.AttributeCollection.MaterialColorAttribute.TypedData, 2).SelectMany(v => v).ToArray(); - Assert.AreEqual(merged, mac.MaterialColorAttribute.TypedData); - } - - { - var merged = Enumerable.Repeat(g3d.AttributeCollection.MaterialGlossinessAttribute.TypedData, 2).SelectMany(v => v).ToArray(); - Assert.AreEqual(merged, mac.MaterialGlossinessAttribute.TypedData); - } - - { - var merged = Enumerable.Repeat(g3d.AttributeCollection.MaterialSmoothnessAttribute.TypedData, 2).SelectMany(v => v).ToArray(); - Assert.AreEqual(merged, mac.MaterialSmoothnessAttribute.TypedData); - } - } -} From dd14b8cf95650d3a2707989e9bfea613596a30dc Mon Sep 17 00:00:00 2001 From: simon Date: Mon, 2 Oct 2023 11:51:30 -0400 Subject: [PATCH 012/111] Moved compression stuff into BFastNext --- src/cs/bfast/Vim.BFast.Next/BFastNext.cs | 74 +++++++++++++++++-- .../Vim.BFast.Next/BFastNextExtensions.cs | 63 ---------------- src/cs/vim/Vim.Vimx.Test/VimxActions.cs | 5 +- 3 files changed, 70 insertions(+), 72 deletions(-) delete mode 100644 src/cs/bfast/Vim.BFast.Next/BFastNextExtensions.cs diff --git a/src/cs/bfast/Vim.BFast.Next/BFastNext.cs b/src/cs/bfast/Vim.BFast.Next/BFastNext.cs index 81bb1556..597b5f41 100644 --- a/src/cs/bfast/Vim.BFast.Next/BFastNext.cs +++ b/src/cs/bfast/Vim.BFast.Next/BFastNext.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.IO.Compression; using System.Linq; using Vim.BFast; @@ -19,8 +20,39 @@ public BFastNext(Stream stream) _children = node.ToDictionary(c => c.name, c => c.value as IBFastNextNode); } - public void SetBFast(string name, BFastNext bfast) - => _children[name] = bfast; + public void SetBFast(Func getName, IEnumerable others, bool deflate = false) + { + var i = 0; + foreach (var b in others) + { + SetBFast(getName(i++), b, deflate); + } + } + + public void SetBFast(string name, BFastNext bfast, bool deflate = false) + { + if (deflate == false) + { + bfast.SetBFast(name, bfast); + } + else + { + var a = Deflate(bfast); + bfast.SetArray(name, a); + } + } + + private byte[] Deflate(BFastNext bfast) + { + using (var output = new MemoryStream()) + { + using (var decompress = new DeflateStream(output, CompressionMode.Compress, true)) + { + bfast.Write(decompress); + } + return output.ToArray(); + } + } public void SetArray(string name, T[] array) where T : unmanaged => _children[name] = BFastNextNode.FromArray(array); @@ -39,11 +71,28 @@ public void SetNode(string name, BFastNextNode node) _children[name] = node; } - public BFastNext GetBFast(string name) + public BFastNext GetBFast(string name, bool inflate = false) { - if (!_children.ContainsKey(name)) return null; - var bfast = _children[name].AsBFast(); - return bfast; + var node = GetNode(name); + if (node == null) return null; + if (inflate == false) return node.AsBFast(); + return InflateNode(node); + } + + private BFastNext InflateNode(IBFastNextNode node) + { + var output = new MemoryStream(); + using (var input = new MemoryStream()) + { + node.Write(input); + input.Seek(0, SeekOrigin.Begin); + using (var compress = new DeflateStream(input, CompressionMode.Decompress, true)) + { + compress.CopyTo(output); + output.Seek(0, SeekOrigin.Begin); + return new BFastNext(output); + } + } } public T[] GetArray(string name) where T : unmanaged @@ -129,4 +178,17 @@ private static long GetBFastSize(IEnumerable<(string name, IWritable value)> wri return header.Preamble.DataEnd; } } + + public static class BFastNextExtensions + { + public static T ReadBFast(this string path, Func process) + { + using (var file = new FileStream(path, FileMode.Open)) + { + var bfast = new BFastNext(file); + return process(bfast); + } + } + } } + diff --git a/src/cs/bfast/Vim.BFast.Next/BFastNextExtensions.cs b/src/cs/bfast/Vim.BFast.Next/BFastNextExtensions.cs deleted file mode 100644 index 5390c69f..00000000 --- a/src/cs/bfast/Vim.BFast.Next/BFastNextExtensions.cs +++ /dev/null @@ -1,63 +0,0 @@ -using System; -using System.IO.Compression; -using System.IO; -using System.Collections.Generic; - -namespace Vim.BFastNextNS -{ - public static class BFastNextExtensions - { - public static BFastNext GetBFast(this BFastNext bfast, string name, bool inflate) - { - if (inflate == false) return bfast.GetBFast(name); - var output = new MemoryStream(); - using (var input = new MemoryStream()) - { - bfast.GetNode(name).Write(input); - input.Seek(0, SeekOrigin.Begin); - using (var compress = new DeflateStream(input, CompressionMode.Decompress, true)) - { - compress.CopyTo(output); - output.Seek(0, SeekOrigin.Begin); - return new BFastNext(output); - } - } - } - - public static void SetBFast(this BFastNext bfast, string name, BFastNext other, bool deflate) - { - if (deflate == false) bfast.SetBFast(name, other); - - using (var output = new MemoryStream()) - { - using (var decompress = new DeflateStream(output, CompressionMode.Compress, true)) - { - other.Write(decompress); - } - - var a = output.ToArray(); - bfast.SetArray(name, a); - } - } - - public static void SetBFast(this BFastNext bfast, Func getName, IEnumerable others, bool deflate) - { - var i = 0; - foreach(var b in others) - { - bfast.SetBFast(getName(i++), b, deflate); - } - } - - public static T ReadBFast(this string path, Func process) - { - using (var file = new FileStream(path, FileMode.Open)) - { - var bfast = new BFastNext(file); - return process(bfast); - } - } - - - } -} diff --git a/src/cs/vim/Vim.Vimx.Test/VimxActions.cs b/src/cs/vim/Vim.Vimx.Test/VimxActions.cs index 73777e27..7b8a16cb 100644 --- a/src/cs/vim/Vim.Vimx.Test/VimxActions.cs +++ b/src/cs/vim/Vim.Vimx.Test/VimxActions.cs @@ -13,9 +13,8 @@ public static class VimxActions [Test] public static void ConvertVimToVimx() { - //var input = TestUtils.ResidencePath; - - var input = Path.Join(VimFormatRepoPaths.DataDir, whiteleys); + var input = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); + //var input = Path.Join(VimFormatRepoPaths.DataDir, input); var name = Path.GetFileNameWithoutExtension(input); var output = Path.Combine(VimFormatRepoPaths.OutDir, name + ".vimx"); From eacd70236c990c4b3bbcbb525ca6c48c5d0d80c9 Mon Sep 17 00:00:00 2001 From: simon Date: Tue, 3 Oct 2023 16:44:11 -0400 Subject: [PATCH 013/111] renamed attributes to avoid conflicts --- src/cs/bfast/Vim.BFast.Next/BFastNext.cs | 4 +- .../Vim.BFastNext.Tests/BFastNextTests.cs | 26 +- .../Vim.G3dNext.Attributes/Attributes.g.cs | 1205 +++++++++++------ src/cs/g3d/Vim.G3dNext.Attributes/G3dMesh.cs | 1 + src/cs/g3d/Vim.G3dNext.Attributes/G3dScene.cs | 3 +- .../Vim.G3dNext.Attributes/MeshAttributes.cs | 8 +- .../Vim.G3dNext.Attributes/SceneAttributes.cs | 84 +- .../Vim.G3dNext.Attributes/VimAttributes.cs | 93 +- .../G3dAttributeCollectionGenerator.cs | 41 +- .../MeshesToScene.cs | 18 +- .../VimxConverter.cs | 21 +- .../Vim.Format.Vimx/Vim.Format.Vimx.csproj | 1 - src/cs/vim/Vim.Format.Vimx/Vimx.cs | 23 +- src/cs/vim/Vim.Format.Vimx/VimxChunk.cs | 34 + src/cs/vim/Vim.Vimx.Test/TestUtils.cs | 34 +- src/cs/vim/Vim.Vimx.Test/VimG3dTests.cs | 70 +- src/cs/vim/Vim.Vimx.Test/VimxActions.cs | 2 +- src/cs/vim/Vim.Vimx.Test/VimxTests.cs | 4 +- 18 files changed, 1073 insertions(+), 599 deletions(-) create mode 100644 src/cs/vim/Vim.Format.Vimx/VimxChunk.cs diff --git a/src/cs/bfast/Vim.BFast.Next/BFastNext.cs b/src/cs/bfast/Vim.BFast.Next/BFastNext.cs index 597b5f41..e7678e57 100644 --- a/src/cs/bfast/Vim.BFast.Next/BFastNext.cs +++ b/src/cs/bfast/Vim.BFast.Next/BFastNext.cs @@ -33,12 +33,12 @@ public void SetBFast(string name, BFastNext bfast, bool deflate = false) { if (deflate == false) { - bfast.SetBFast(name, bfast); + _children[name] = bfast; } else { var a = Deflate(bfast); - bfast.SetArray(name, a); + SetArray(name, a); } } diff --git a/src/cs/bfast/Vim.BFastNext.Tests/BFastNextTests.cs b/src/cs/bfast/Vim.BFastNext.Tests/BFastNextTests.cs index beb82353..14199ffa 100644 --- a/src/cs/bfast/Vim.BFastNext.Tests/BFastNextTests.cs +++ b/src/cs/bfast/Vim.BFastNext.Tests/BFastNextTests.cs @@ -1,4 +1,5 @@ using NUnit.Framework; +using Vim.Util; using Vim.Util.Tests; namespace Vim.BFastNextNS.Tests @@ -46,7 +47,7 @@ public void EmptyBFast_Remove_Does_Nothing() } [Test] - public void EmptyBFast_GetSize_Return_64() + public void EmptyBFast_GetSize_Return_64() { var bfast = new BFastNext(); Assert.That(bfast.GetSize(), Is.EqualTo(64)); @@ -157,6 +158,29 @@ public void SetBFast_Then_GetBFast_Returns_Same() Assert.That(result, Is.EqualTo(b)); } + [Test] + public void Inflate_NonDeflated_Throws() + { + var bfast = new BFastNext(); + var b = new BFastNext(); + bfast.SetBFast("A", b); + Assert.That(() => bfast.GetBFast("A", inflate: true), Throws.Exception); + } + + [Test] + public void Deflate_Inflate_Works() + { + var bfast = new BFastNext(); + var b = new BFastNext(); + b.SetArray("B", new int[3] { 0, 1, 2 }); + bfast.SetBFast("A", b, deflate : true); + + var result = bfast.GetBFast("A", inflate: true); + var b2 = result.GetArray("B"); + Assert.That(result.Entries.Count(), Is.EqualTo(1)); + Assert.That(b2, Is.EqualTo(new int[3] { 0, 1, 2 })); + } + [Test] public void SetBFast_Then_SetBFast_Replaces() { diff --git a/src/cs/g3d/Vim.G3dNext.Attributes/Attributes.g.cs b/src/cs/g3d/Vim.G3dNext.Attributes/Attributes.g.cs index 1b837ee2..8bb2af61 100644 --- a/src/cs/g3d/Vim.G3dNext.Attributes/Attributes.g.cs +++ b/src/cs/g3d/Vim.G3dNext.Attributes/Attributes.g.cs @@ -1,4 +1,4 @@ -// AUTO-GENERATED FILE, DO NOT MODIFY. +// AUTO-GENERATED FILE, DO NOT MODIFY WACKO3. // ReSharper disable All using System; using System.IO; @@ -10,7 +10,7 @@ namespace Vim.G3dNext.Attributes { - public partial class PositionsAttribute : IAttribute + public partial class VimPositionsAttribute : IAttribute { public const string AttributeName = "g3d:vertex:position:0:float32:3"; @@ -55,7 +55,7 @@ public void Write(Stream stream) } } - public partial class IndicesAttribute : IAttribute + public partial class VimIndicesAttribute : IAttribute { public const string AttributeName = "g3d:corner:index:0:int32:1"; @@ -84,7 +84,7 @@ public void ReadBFast(BFastNext bfast) = AttributeType.Index; public Type IndexInto { get; } - = typeof(Vim.G3dNext.Attributes.PositionsAttribute); + = typeof(Vim.G3dNext.Attributes.VimPositionsAttribute); public System.Int32[] TypedData { get; set; } = Array.Empty(); @@ -100,7 +100,7 @@ public void Write(Stream stream) } } - public partial class InstanceTransformsAttribute : IAttribute + public partial class VimInstanceTransformsAttribute : IAttribute { public const string AttributeName = "g3d:instance:transform:0:float32:16"; @@ -145,7 +145,7 @@ public void Write(Stream stream) } } - public partial class InstanceParentsAttribute : IAttribute + public partial class VimInstanceParentsAttribute : IAttribute { public const string AttributeName = "g3d:instance:parent:0:int32:1"; @@ -174,7 +174,7 @@ public void ReadBFast(BFastNext bfast) = AttributeType.Index; public Type IndexInto { get; } - = typeof(Vim.G3dNext.Attributes.InstanceTransformsAttribute); + = typeof(Vim.G3dNext.Attributes.VimInstanceTransformsAttribute); public System.Int32[] TypedData { get; set; } = Array.Empty(); @@ -190,7 +190,7 @@ public void Write(Stream stream) } } - public partial class InstanceFlagsAttribute : IAttribute + public partial class VimInstanceFlagsAttribute : IAttribute { public const string AttributeName = "g3d:instance:flags:0:uint16:1"; @@ -235,7 +235,7 @@ public void Write(Stream stream) } } - public partial class InstanceMeshesAttribute : IAttribute + public partial class VimInstanceMeshesAttribute : IAttribute { public const string AttributeName = "g3d:instance:mesh:0:int32:1"; @@ -264,7 +264,7 @@ public void ReadBFast(BFastNext bfast) = AttributeType.Index; public Type IndexInto { get; } - = typeof(Vim.G3dNext.Attributes.MeshSubmeshOffsetsAttribute); + = typeof(Vim.G3dNext.Attributes.VimMeshSubmeshOffsetsAttribute); public System.Int32[] TypedData { get; set; } = Array.Empty(); @@ -280,7 +280,7 @@ public void Write(Stream stream) } } - public partial class MeshSubmeshOffsetsAttribute : IAttribute + public partial class VimMeshSubmeshOffsetsAttribute : IAttribute { public const string AttributeName = "g3d:mesh:submeshoffset:0:int32:1"; @@ -309,7 +309,7 @@ public void ReadBFast(BFastNext bfast) = AttributeType.Index; public Type IndexInto { get; } - = typeof(Vim.G3dNext.Attributes.SubmeshIndexOffsetsAttribute); + = typeof(Vim.G3dNext.Attributes.VimSubmeshIndexOffsetsAttribute); public System.Int32[] TypedData { get; set; } = Array.Empty(); @@ -325,7 +325,7 @@ public void Write(Stream stream) } } - public partial class SubmeshIndexOffsetsAttribute : IAttribute + public partial class VimSubmeshIndexOffsetsAttribute : IAttribute { public const string AttributeName = "g3d:submesh:indexoffset:0:int32:1"; @@ -354,7 +354,7 @@ public void ReadBFast(BFastNext bfast) = AttributeType.Index; public Type IndexInto { get; } - = typeof(Vim.G3dNext.Attributes.IndicesAttribute); + = typeof(Vim.G3dNext.Attributes.VimIndicesAttribute); public System.Int32[] TypedData { get; set; } = Array.Empty(); @@ -370,7 +370,7 @@ public void Write(Stream stream) } } - public partial class SubmeshMaterialsAttribute : IAttribute + public partial class VimSubmeshMaterialsAttribute : IAttribute { public const string AttributeName = "g3d:submesh:material:0:int32:1"; @@ -399,7 +399,7 @@ public void ReadBFast(BFastNext bfast) = AttributeType.Index; public Type IndexInto { get; } - = typeof(Vim.G3dNext.Attributes.MaterialColorsAttribute); + = typeof(Vim.G3dNext.Attributes.VimMaterialColorsAttribute); public System.Int32[] TypedData { get; set; } = Array.Empty(); @@ -415,7 +415,142 @@ public void Write(Stream stream) } } - public partial class ShapeVerticesAttribute : IAttribute + public partial class VimMaterialColorsAttribute : IAttribute + { + public const string AttributeName = "g3d:material:color:0:float32:4"; + + public string Name + => AttributeName; + + public int Count => TypedData?.Length ?? 0; + + public void AddTo(BFastNext bfast) + { + if(TypedData != null) + { + bfast.SetArray(Name, TypedData); + } + } + + public void ReadBFast(BFastNext bfast) + { + TypedData = bfast.GetArray("g3d:material:color:0:float32:4"); + } + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Data; + + public Type IndexInto { get; } + = null; + + public Vim.Math3d.Vector4[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + + public partial class VimMaterialGlossinessAttribute : IAttribute + { + public const string AttributeName = "g3d:material:glossiness:0:float32:1"; + + public string Name + => AttributeName; + + public int Count => TypedData?.Length ?? 0; + + public void AddTo(BFastNext bfast) + { + if(TypedData != null) + { + bfast.SetArray(Name, TypedData); + } + } + + public void ReadBFast(BFastNext bfast) + { + TypedData = bfast.GetArray("g3d:material:glossiness:0:float32:1"); + } + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Data; + + public Type IndexInto { get; } + = null; + + public System.Single[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + + public partial class VimMaterialSmoothnessAttribute : IAttribute + { + public const string AttributeName = "g3d:material:smoothness:0:float32:1"; + + public string Name + => AttributeName; + + public int Count => TypedData?.Length ?? 0; + + public void AddTo(BFastNext bfast) + { + if(TypedData != null) + { + bfast.SetArray(Name, TypedData); + } + } + + public void ReadBFast(BFastNext bfast) + { + TypedData = bfast.GetArray("g3d:material:smoothness:0:float32:1"); + } + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Data; + + public Type IndexInto { get; } + = null; + + public System.Single[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + + public partial class VimShapeVerticesAttribute : IAttribute { public const string AttributeName = "g3d:shapevertex:position:0:float32:3"; @@ -460,7 +595,7 @@ public void Write(Stream stream) } } - public partial class ShapeVertexOffsetsAttribute : IAttribute + public partial class VimShapeVertexOffsetsAttribute : IAttribute { public const string AttributeName = "g3d:shape:vertexoffset:0:int32:1"; @@ -489,7 +624,7 @@ public void ReadBFast(BFastNext bfast) = AttributeType.Index; public Type IndexInto { get; } - = typeof(Vim.G3dNext.Attributes.ShapeVerticesAttribute); + = typeof(Vim.G3dNext.Attributes.VimShapeVerticesAttribute); public System.Int32[] TypedData { get; set; } = Array.Empty(); @@ -505,7 +640,7 @@ public void Write(Stream stream) } } - public partial class ShapeColorsAttribute : IAttribute + public partial class VimShapeColorsAttribute : IAttribute { public const string AttributeName = "g3d:shape:color:0:float32:4"; @@ -550,7 +685,7 @@ public void Write(Stream stream) } } - public partial class ShapeWidthsAttribute : IAttribute + public partial class VimShapeWidthsAttribute : IAttribute { public const string AttributeName = "g3d:shape:width:0:float32:1"; @@ -730,9 +865,9 @@ public void Write(Stream stream) } } - public partial class InstanceFilesAttribute : IAttribute + public partial class SceneChunkCountAttribute : IAttribute { - public const string AttributeName = "g3d:instance:file:0:int32:1"; + public const string AttributeName = "g3d:chunk:count:0:int32:1"; public string Name => AttributeName; @@ -749,7 +884,7 @@ public void AddTo(BFastNext bfast) public void ReadBFast(BFastNext bfast) { - TypedData = bfast.GetArray("g3d:instance:file:0:int32:1"); + TypedData = bfast.GetArray("g3d:chunk:count:0:int32:1"); } public IAttributeDescriptor AttributeDescriptor { get; } @@ -775,9 +910,9 @@ public void Write(Stream stream) } } - public partial class InstanceNodesAttribute : IAttribute + public partial class SceneInstanceMeshesAttribute : IAttribute { - public const string AttributeName = "g3d:instance:node:0:int32:1"; + public const string AttributeName = "g3d:instance:mesh:0:int32:1"; public string Name => AttributeName; @@ -794,7 +929,52 @@ public void AddTo(BFastNext bfast) public void ReadBFast(BFastNext bfast) { - TypedData = bfast.GetArray("g3d:instance:node:0:int32:1"); + TypedData = bfast.GetArray("g3d:instance:mesh:0:int32:1"); + } + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Data; + + public Type IndexInto { get; } + = null; + + public System.Int32[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + + public partial class SceneInstanceTransformsAttribute : IAttribute + { + public const string AttributeName = "g3d:instance:transform:0:int32:1"; + + public string Name + => AttributeName; + + public int Count => TypedData?.Length ?? 0; + + public void AddTo(BFastNext bfast) + { + if(TypedData != null) + { + bfast.SetArray(Name, TypedData); + } + } + + public void ReadBFast(BFastNext bfast) + { + TypedData = bfast.GetArray("g3d:instance:transform:0:int32:1"); } public IAttributeDescriptor AttributeDescriptor { get; } @@ -820,9 +1000,9 @@ public void Write(Stream stream) } } - public partial class InstanceIndicesAttribute : IAttribute + public partial class SceneInstanceNodesAttribute : IAttribute { - public const string AttributeName = "g3d:instance:index:0:int32:1"; + public const string AttributeName = "g3d:instance:node:0:int32:1"; public string Name => AttributeName; @@ -839,7 +1019,7 @@ public void AddTo(BFastNext bfast) public void ReadBFast(BFastNext bfast) { - TypedData = bfast.GetArray("g3d:instance:index:0:int32:1"); + TypedData = bfast.GetArray("g3d:instance:node:0:int32:1"); } public IAttributeDescriptor AttributeDescriptor { get; } @@ -865,7 +1045,7 @@ public void Write(Stream stream) } } - public partial class InstanceGroupsAttribute : IAttribute + public partial class SceneInstanceGroupsAttribute : IAttribute { public const string AttributeName = "g3d:instance:group:0:int32:1"; @@ -910,7 +1090,7 @@ public void Write(Stream stream) } } - public partial class InstanceTagsAttribute : IAttribute + public partial class SceneInstanceTagsAttribute : IAttribute { public const string AttributeName = "g3d:instance:tag:0:int64:1"; @@ -955,7 +1135,52 @@ public void Write(Stream stream) } } - public partial class InstanceMinsAttribute : IAttribute + public partial class SceneInstanceFlagsAttribute : IAttribute + { + public const string AttributeName = "g3d:instance:flags:0:uint16:1"; + + public string Name + => AttributeName; + + public int Count => TypedData?.Length ?? 0; + + public void AddTo(BFastNext bfast) + { + if(TypedData != null) + { + bfast.SetArray(Name, TypedData); + } + } + + public void ReadBFast(BFastNext bfast) + { + TypedData = bfast.GetArray("g3d:instance:flags:0:uint16:1"); + } + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Data; + + public Type IndexInto { get; } + = null; + + public System.UInt16[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + + public partial class SceneInstanceMinsAttribute : IAttribute { public const string AttributeName = "g3d:instance:min:0:float32:3"; @@ -1000,7 +1225,7 @@ public void Write(Stream stream) } } - public partial class InstanceMaxsAttribute : IAttribute + public partial class SceneInstanceMaxsAttribute : IAttribute { public const string AttributeName = "g3d:instance:max:0:float32:3"; @@ -1045,7 +1270,52 @@ public void Write(Stream stream) } } - public partial class MeshInstanceCountsAttribute : IAttribute + public partial class SceneMeshChunksAttribute : IAttribute + { + public const string AttributeName = "g3d:mesh:chunk:0:int32:1"; + + public string Name + => AttributeName; + + public int Count => TypedData?.Length ?? 0; + + public void AddTo(BFastNext bfast) + { + if(TypedData != null) + { + bfast.SetArray(Name, TypedData); + } + } + + public void ReadBFast(BFastNext bfast) + { + TypedData = bfast.GetArray("g3d:mesh:chunk:0:int32:1"); + } + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Data; + + public Type IndexInto { get; } + = null; + + public System.Int32[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + + public partial class SceneMeshInstanceCountsAttribute : IAttribute { public const string AttributeName = "g3d:mesh:instancecount:0:int32:1"; @@ -1090,7 +1360,7 @@ public void Write(Stream stream) } } - public partial class MeshVertexCountsAttribute : IAttribute + public partial class SceneMeshVertexCountsAttribute : IAttribute { public const string AttributeName = "g3d:mesh:vertexcount:0:int32:1"; @@ -1135,7 +1405,7 @@ public void Write(Stream stream) } } - public partial class MeshIndexCountsAttribute : IAttribute + public partial class SceneMeshIndexCountsAttribute : IAttribute { public const string AttributeName = "g3d:mesh:indexcount:0:int32:1"; @@ -1180,7 +1450,7 @@ public void Write(Stream stream) } } - public partial class MeshOpaqueVertexCountsAttribute : IAttribute + public partial class SceneMeshOpaqueVertexCountsAttribute : IAttribute { public const string AttributeName = "g3d:mesh:opaquevertexcount:0:int32:1"; @@ -1225,7 +1495,7 @@ public void Write(Stream stream) } } - public partial class MeshOpaqueIndexCountsAttribute : IAttribute + public partial class SceneMeshOpaqueIndexCountsAttribute : IAttribute { public const string AttributeName = "g3d:mesh:opaqueindexcount:0:int32:1"; @@ -1389,7 +1659,7 @@ public void ReadBFast(BFastNext bfast) = AttributeType.Index; public Type IndexInto { get; } - = typeof(Vim.G3dNext.Attributes.IndicesAttribute); + = typeof(Vim.G3dNext.Attributes.MeshIndicesAttribute); public System.Int32[] TypedData { get; set; } = Array.Empty(); @@ -1434,7 +1704,7 @@ public void ReadBFast(BFastNext bfast) = AttributeType.Index; public Type IndexInto { get; } - = typeof(Vim.G3dNext.Attributes.IndicesAttribute); + = typeof(Vim.G3dNext.Attributes.MeshIndicesAttribute); public System.Int32[] TypedData { get; set; } = Array.Empty(); @@ -1479,7 +1749,7 @@ public void ReadBFast(BFastNext bfast) = AttributeType.Index; public Type IndexInto { get; } - = typeof(Vim.G3dNext.Attributes.MaterialColorsAttribute); + = null; public System.Int32[] TypedData { get; set; } = Array.Empty(); @@ -1569,7 +1839,7 @@ public void ReadBFast(BFastNext bfast) = AttributeType.Index; public Type IndexInto { get; } - = typeof(Vim.G3dNext.Attributes.PositionsAttribute); + = typeof(Vim.G3dNext.Attributes.MeshPositionsAttribute); public System.Int32[] TypedData { get; set; } = Array.Empty(); @@ -1614,98 +1884,98 @@ public BFastNext ToBFast() public Vim.Math3d.Vector3[] Positions { - get => Attributes.PositionsAttribute.TypedData; - set => Attributes.PositionsAttribute.TypedData = value; + get => Attributes.Positions.TypedData; + set => Attributes.Positions.TypedData = value; } public System.Int32[] Indices { - get => Attributes.IndicesAttribute.TypedData; - set => Attributes.IndicesAttribute.TypedData = value; + get => Attributes.Indices.TypedData; + set => Attributes.Indices.TypedData = value; } public Vim.Math3d.Matrix4x4[] InstanceTransforms { - get => Attributes.InstanceTransformsAttribute.TypedData; - set => Attributes.InstanceTransformsAttribute.TypedData = value; + get => Attributes.InstanceTransforms.TypedData; + set => Attributes.InstanceTransforms.TypedData = value; } public System.Int32[] InstanceParents { - get => Attributes.InstanceParentsAttribute.TypedData; - set => Attributes.InstanceParentsAttribute.TypedData = value; + get => Attributes.InstanceParents.TypedData; + set => Attributes.InstanceParents.TypedData = value; } public System.UInt16[] InstanceFlags { - get => Attributes.InstanceFlagsAttribute.TypedData; - set => Attributes.InstanceFlagsAttribute.TypedData = value; + get => Attributes.InstanceFlags.TypedData; + set => Attributes.InstanceFlags.TypedData = value; } public System.Int32[] InstanceMeshes { - get => Attributes.InstanceMeshesAttribute.TypedData; - set => Attributes.InstanceMeshesAttribute.TypedData = value; + get => Attributes.InstanceMeshes.TypedData; + set => Attributes.InstanceMeshes.TypedData = value; } public System.Int32[] MeshSubmeshOffsets { - get => Attributes.MeshSubmeshOffsetsAttribute.TypedData; - set => Attributes.MeshSubmeshOffsetsAttribute.TypedData = value; + get => Attributes.MeshSubmeshOffsets.TypedData; + set => Attributes.MeshSubmeshOffsets.TypedData = value; } public System.Int32[] SubmeshIndexOffsets { - get => Attributes.SubmeshIndexOffsetsAttribute.TypedData; - set => Attributes.SubmeshIndexOffsetsAttribute.TypedData = value; + get => Attributes.SubmeshIndexOffsets.TypedData; + set => Attributes.SubmeshIndexOffsets.TypedData = value; } public System.Int32[] SubmeshMaterials { - get => Attributes.SubmeshMaterialsAttribute.TypedData; - set => Attributes.SubmeshMaterialsAttribute.TypedData = value; + get => Attributes.SubmeshMaterials.TypedData; + set => Attributes.SubmeshMaterials.TypedData = value; } public Vim.Math3d.Vector4[] MaterialColors { - get => Attributes.MaterialColorsAttribute.TypedData; - set => Attributes.MaterialColorsAttribute.TypedData = value; + get => Attributes.MaterialColors.TypedData; + set => Attributes.MaterialColors.TypedData = value; } public System.Single[] MaterialGlossiness { - get => Attributes.MaterialGlossinessAttribute.TypedData; - set => Attributes.MaterialGlossinessAttribute.TypedData = value; + get => Attributes.MaterialGlossiness.TypedData; + set => Attributes.MaterialGlossiness.TypedData = value; } public System.Single[] MaterialSmoothness { - get => Attributes.MaterialSmoothnessAttribute.TypedData; - set => Attributes.MaterialSmoothnessAttribute.TypedData = value; + get => Attributes.MaterialSmoothness.TypedData; + set => Attributes.MaterialSmoothness.TypedData = value; } public Vim.Math3d.Vector3[] ShapeVertices { - get => Attributes.ShapeVerticesAttribute.TypedData; - set => Attributes.ShapeVerticesAttribute.TypedData = value; + get => Attributes.ShapeVertices.TypedData; + set => Attributes.ShapeVertices.TypedData = value; } public System.Int32[] ShapeVertexOffsets { - get => Attributes.ShapeVertexOffsetsAttribute.TypedData; - set => Attributes.ShapeVertexOffsetsAttribute.TypedData = value; + get => Attributes.ShapeVertexOffsets.TypedData; + set => Attributes.ShapeVertexOffsets.TypedData = value; } public Vim.Math3d.Vector4[] ShapeColors { - get => Attributes.ShapeColorsAttribute.TypedData; - set => Attributes.ShapeColorsAttribute.TypedData = value; + get => Attributes.ShapeColors.TypedData; + set => Attributes.ShapeColors.TypedData = value; } public System.Single[] ShapeWidths { - get => Attributes.ShapeWidthsAttribute.TypedData; - set => Attributes.ShapeWidthsAttribute.TypedData = value; + get => Attributes.ShapeWidths.TypedData; + set => Attributes.ShapeWidths.TypedData = value; } } @@ -1733,173 +2003,189 @@ public void ReadAttributes(BFastNext bfast) public IDictionary Map { get; } = new Dictionary { - [Vim.G3dNext.Attributes.PositionsAttribute.AttributeName] = new Vim.G3dNext.Attributes.PositionsAttribute(), - [Vim.G3dNext.Attributes.IndicesAttribute.AttributeName] = new Vim.G3dNext.Attributes.IndicesAttribute(), - [Vim.G3dNext.Attributes.InstanceTransformsAttribute.AttributeName] = new Vim.G3dNext.Attributes.InstanceTransformsAttribute(), - [Vim.G3dNext.Attributes.InstanceParentsAttribute.AttributeName] = new Vim.G3dNext.Attributes.InstanceParentsAttribute(), - [Vim.G3dNext.Attributes.InstanceFlagsAttribute.AttributeName] = new Vim.G3dNext.Attributes.InstanceFlagsAttribute(), - [Vim.G3dNext.Attributes.InstanceMeshesAttribute.AttributeName] = new Vim.G3dNext.Attributes.InstanceMeshesAttribute(), - [Vim.G3dNext.Attributes.MeshSubmeshOffsetsAttribute.AttributeName] = new Vim.G3dNext.Attributes.MeshSubmeshOffsetsAttribute(), - [Vim.G3dNext.Attributes.SubmeshIndexOffsetsAttribute.AttributeName] = new Vim.G3dNext.Attributes.SubmeshIndexOffsetsAttribute(), - [Vim.G3dNext.Attributes.SubmeshMaterialsAttribute.AttributeName] = new Vim.G3dNext.Attributes.SubmeshMaterialsAttribute(), - [Vim.G3dNext.Attributes.MaterialColorsAttribute.AttributeName] = new Vim.G3dNext.Attributes.MaterialColorsAttribute(), - [Vim.G3dNext.Attributes.MaterialGlossinessAttribute.AttributeName] = new Vim.G3dNext.Attributes.MaterialGlossinessAttribute(), - [Vim.G3dNext.Attributes.MaterialSmoothnessAttribute.AttributeName] = new Vim.G3dNext.Attributes.MaterialSmoothnessAttribute(), - [Vim.G3dNext.Attributes.ShapeVerticesAttribute.AttributeName] = new Vim.G3dNext.Attributes.ShapeVerticesAttribute(), - [Vim.G3dNext.Attributes.ShapeVertexOffsetsAttribute.AttributeName] = new Vim.G3dNext.Attributes.ShapeVertexOffsetsAttribute(), - [Vim.G3dNext.Attributes.ShapeColorsAttribute.AttributeName] = new Vim.G3dNext.Attributes.ShapeColorsAttribute(), - [Vim.G3dNext.Attributes.ShapeWidthsAttribute.AttributeName] = new Vim.G3dNext.Attributes.ShapeWidthsAttribute(), + [Vim.G3dNext.Attributes.VimPositionsAttribute.AttributeName] = new Vim.G3dNext.Attributes.VimPositionsAttribute(), + [Vim.G3dNext.Attributes.VimIndicesAttribute.AttributeName] = new Vim.G3dNext.Attributes.VimIndicesAttribute(), + [Vim.G3dNext.Attributes.VimInstanceTransformsAttribute.AttributeName] = new Vim.G3dNext.Attributes.VimInstanceTransformsAttribute(), + [Vim.G3dNext.Attributes.VimInstanceParentsAttribute.AttributeName] = new Vim.G3dNext.Attributes.VimInstanceParentsAttribute(), + [Vim.G3dNext.Attributes.VimInstanceFlagsAttribute.AttributeName] = new Vim.G3dNext.Attributes.VimInstanceFlagsAttribute(), + [Vim.G3dNext.Attributes.VimInstanceMeshesAttribute.AttributeName] = new Vim.G3dNext.Attributes.VimInstanceMeshesAttribute(), + [Vim.G3dNext.Attributes.VimMeshSubmeshOffsetsAttribute.AttributeName] = new Vim.G3dNext.Attributes.VimMeshSubmeshOffsetsAttribute(), + [Vim.G3dNext.Attributes.VimSubmeshIndexOffsetsAttribute.AttributeName] = new Vim.G3dNext.Attributes.VimSubmeshIndexOffsetsAttribute(), + [Vim.G3dNext.Attributes.VimSubmeshMaterialsAttribute.AttributeName] = new Vim.G3dNext.Attributes.VimSubmeshMaterialsAttribute(), + [Vim.G3dNext.Attributes.VimMaterialColorsAttribute.AttributeName] = new Vim.G3dNext.Attributes.VimMaterialColorsAttribute(), + [Vim.G3dNext.Attributes.VimMaterialGlossinessAttribute.AttributeName] = new Vim.G3dNext.Attributes.VimMaterialGlossinessAttribute(), + [Vim.G3dNext.Attributes.VimMaterialSmoothnessAttribute.AttributeName] = new Vim.G3dNext.Attributes.VimMaterialSmoothnessAttribute(), + [Vim.G3dNext.Attributes.VimShapeVerticesAttribute.AttributeName] = new Vim.G3dNext.Attributes.VimShapeVerticesAttribute(), + [Vim.G3dNext.Attributes.VimShapeVertexOffsetsAttribute.AttributeName] = new Vim.G3dNext.Attributes.VimShapeVertexOffsetsAttribute(), + [Vim.G3dNext.Attributes.VimShapeColorsAttribute.AttributeName] = new Vim.G3dNext.Attributes.VimShapeColorsAttribute(), + [Vim.G3dNext.Attributes.VimShapeWidthsAttribute.AttributeName] = new Vim.G3dNext.Attributes.VimShapeWidthsAttribute(), }; // Named Attributes. - public Vim.G3dNext.Attributes.PositionsAttribute PositionsAttribute + public Vim.G3dNext.Attributes.VimPositionsAttribute Positions { - get => Map.TryGetValue(Vim.G3dNext.Attributes.PositionsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.PositionsAttribute : default; - set => Map[Vim.G3dNext.Attributes.PositionsAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.VimPositionsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.VimPositionsAttribute : default; + set => Map[Vim.G3dNext.Attributes.VimPositionsAttribute.AttributeName] = value as IAttribute; } - public Vim.G3dNext.Attributes.IndicesAttribute IndicesAttribute + public Vim.G3dNext.Attributes.VimIndicesAttribute Indices { - get => Map.TryGetValue(Vim.G3dNext.Attributes.IndicesAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.IndicesAttribute : default; - set => Map[Vim.G3dNext.Attributes.IndicesAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.VimIndicesAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.VimIndicesAttribute : default; + set => Map[Vim.G3dNext.Attributes.VimIndicesAttribute.AttributeName] = value as IAttribute; } - public Vim.G3dNext.Attributes.InstanceTransformsAttribute InstanceTransformsAttribute + public Vim.G3dNext.Attributes.VimInstanceTransformsAttribute InstanceTransforms { - get => Map.TryGetValue(Vim.G3dNext.Attributes.InstanceTransformsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceTransformsAttribute : default; - set => Map[Vim.G3dNext.Attributes.InstanceTransformsAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.VimInstanceTransformsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.VimInstanceTransformsAttribute : default; + set => Map[Vim.G3dNext.Attributes.VimInstanceTransformsAttribute.AttributeName] = value as IAttribute; } - public Vim.G3dNext.Attributes.InstanceParentsAttribute InstanceParentsAttribute + public Vim.G3dNext.Attributes.VimInstanceParentsAttribute InstanceParents { - get => Map.TryGetValue(Vim.G3dNext.Attributes.InstanceParentsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceParentsAttribute : default; - set => Map[Vim.G3dNext.Attributes.InstanceParentsAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.VimInstanceParentsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.VimInstanceParentsAttribute : default; + set => Map[Vim.G3dNext.Attributes.VimInstanceParentsAttribute.AttributeName] = value as IAttribute; } - public Vim.G3dNext.Attributes.InstanceFlagsAttribute InstanceFlagsAttribute + public Vim.G3dNext.Attributes.VimInstanceFlagsAttribute InstanceFlags { - get => Map.TryGetValue(Vim.G3dNext.Attributes.InstanceFlagsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceFlagsAttribute : default; - set => Map[Vim.G3dNext.Attributes.InstanceFlagsAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.VimInstanceFlagsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.VimInstanceFlagsAttribute : default; + set => Map[Vim.G3dNext.Attributes.VimInstanceFlagsAttribute.AttributeName] = value as IAttribute; } - public Vim.G3dNext.Attributes.InstanceMeshesAttribute InstanceMeshesAttribute + public Vim.G3dNext.Attributes.VimInstanceMeshesAttribute InstanceMeshes { - get => Map.TryGetValue(Vim.G3dNext.Attributes.InstanceMeshesAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceMeshesAttribute : default; - set => Map[Vim.G3dNext.Attributes.InstanceMeshesAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.VimInstanceMeshesAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.VimInstanceMeshesAttribute : default; + set => Map[Vim.G3dNext.Attributes.VimInstanceMeshesAttribute.AttributeName] = value as IAttribute; } - public Vim.G3dNext.Attributes.MeshSubmeshOffsetsAttribute MeshSubmeshOffsetsAttribute + public Vim.G3dNext.Attributes.VimMeshSubmeshOffsetsAttribute MeshSubmeshOffsets { - get => Map.TryGetValue(Vim.G3dNext.Attributes.MeshSubmeshOffsetsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshSubmeshOffsetsAttribute : default; - set => Map[Vim.G3dNext.Attributes.MeshSubmeshOffsetsAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.VimMeshSubmeshOffsetsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.VimMeshSubmeshOffsetsAttribute : default; + set => Map[Vim.G3dNext.Attributes.VimMeshSubmeshOffsetsAttribute.AttributeName] = value as IAttribute; } - public Vim.G3dNext.Attributes.SubmeshIndexOffsetsAttribute SubmeshIndexOffsetsAttribute + public Vim.G3dNext.Attributes.VimSubmeshIndexOffsetsAttribute SubmeshIndexOffsets { - get => Map.TryGetValue(Vim.G3dNext.Attributes.SubmeshIndexOffsetsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.SubmeshIndexOffsetsAttribute : default; - set => Map[Vim.G3dNext.Attributes.SubmeshIndexOffsetsAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.VimSubmeshIndexOffsetsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.VimSubmeshIndexOffsetsAttribute : default; + set => Map[Vim.G3dNext.Attributes.VimSubmeshIndexOffsetsAttribute.AttributeName] = value as IAttribute; } - public Vim.G3dNext.Attributes.SubmeshMaterialsAttribute SubmeshMaterialsAttribute + public Vim.G3dNext.Attributes.VimSubmeshMaterialsAttribute SubmeshMaterials { - get => Map.TryGetValue(Vim.G3dNext.Attributes.SubmeshMaterialsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.SubmeshMaterialsAttribute : default; - set => Map[Vim.G3dNext.Attributes.SubmeshMaterialsAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.VimSubmeshMaterialsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.VimSubmeshMaterialsAttribute : default; + set => Map[Vim.G3dNext.Attributes.VimSubmeshMaterialsAttribute.AttributeName] = value as IAttribute; } - public Vim.G3dNext.Attributes.MaterialColorsAttribute MaterialColorsAttribute + public Vim.G3dNext.Attributes.VimMaterialColorsAttribute MaterialColors { - get => Map.TryGetValue(Vim.G3dNext.Attributes.MaterialColorsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MaterialColorsAttribute : default; - set => Map[Vim.G3dNext.Attributes.MaterialColorsAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.VimMaterialColorsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.VimMaterialColorsAttribute : default; + set => Map[Vim.G3dNext.Attributes.VimMaterialColorsAttribute.AttributeName] = value as IAttribute; } - public Vim.G3dNext.Attributes.MaterialGlossinessAttribute MaterialGlossinessAttribute + public Vim.G3dNext.Attributes.VimMaterialGlossinessAttribute MaterialGlossiness { - get => Map.TryGetValue(Vim.G3dNext.Attributes.MaterialGlossinessAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MaterialGlossinessAttribute : default; - set => Map[Vim.G3dNext.Attributes.MaterialGlossinessAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.VimMaterialGlossinessAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.VimMaterialGlossinessAttribute : default; + set => Map[Vim.G3dNext.Attributes.VimMaterialGlossinessAttribute.AttributeName] = value as IAttribute; } - public Vim.G3dNext.Attributes.MaterialSmoothnessAttribute MaterialSmoothnessAttribute + public Vim.G3dNext.Attributes.VimMaterialSmoothnessAttribute MaterialSmoothness { - get => Map.TryGetValue(Vim.G3dNext.Attributes.MaterialSmoothnessAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MaterialSmoothnessAttribute : default; - set => Map[Vim.G3dNext.Attributes.MaterialSmoothnessAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.VimMaterialSmoothnessAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.VimMaterialSmoothnessAttribute : default; + set => Map[Vim.G3dNext.Attributes.VimMaterialSmoothnessAttribute.AttributeName] = value as IAttribute; } - public Vim.G3dNext.Attributes.ShapeVerticesAttribute ShapeVerticesAttribute + public Vim.G3dNext.Attributes.VimShapeVerticesAttribute ShapeVertices { - get => Map.TryGetValue(Vim.G3dNext.Attributes.ShapeVerticesAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.ShapeVerticesAttribute : default; - set => Map[Vim.G3dNext.Attributes.ShapeVerticesAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.VimShapeVerticesAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.VimShapeVerticesAttribute : default; + set => Map[Vim.G3dNext.Attributes.VimShapeVerticesAttribute.AttributeName] = value as IAttribute; } - public Vim.G3dNext.Attributes.ShapeVertexOffsetsAttribute ShapeVertexOffsetsAttribute + public Vim.G3dNext.Attributes.VimShapeVertexOffsetsAttribute ShapeVertexOffsets { - get => Map.TryGetValue(Vim.G3dNext.Attributes.ShapeVertexOffsetsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.ShapeVertexOffsetsAttribute : default; - set => Map[Vim.G3dNext.Attributes.ShapeVertexOffsetsAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.VimShapeVertexOffsetsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.VimShapeVertexOffsetsAttribute : default; + set => Map[Vim.G3dNext.Attributes.VimShapeVertexOffsetsAttribute.AttributeName] = value as IAttribute; } - public Vim.G3dNext.Attributes.ShapeColorsAttribute ShapeColorsAttribute + public Vim.G3dNext.Attributes.VimShapeColorsAttribute ShapeColors { - get => Map.TryGetValue(Vim.G3dNext.Attributes.ShapeColorsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.ShapeColorsAttribute : default; - set => Map[Vim.G3dNext.Attributes.ShapeColorsAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.VimShapeColorsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.VimShapeColorsAttribute : default; + set => Map[Vim.G3dNext.Attributes.VimShapeColorsAttribute.AttributeName] = value as IAttribute; } - public Vim.G3dNext.Attributes.ShapeWidthsAttribute ShapeWidthsAttribute + public Vim.G3dNext.Attributes.VimShapeWidthsAttribute ShapeWidths { - get => Map.TryGetValue(Vim.G3dNext.Attributes.ShapeWidthsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.ShapeWidthsAttribute : default; - set => Map[Vim.G3dNext.Attributes.ShapeWidthsAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.VimShapeWidthsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.VimShapeWidthsAttribute : default; + set => Map[Vim.G3dNext.Attributes.VimShapeWidthsAttribute.AttributeName] = value as IAttribute; } /// public IAttribute GetAttribute(Type attributeType) { - if (attributeType == typeof(Vim.G3dNext.Attributes.PositionsAttribute)) - return PositionsAttribute; - if (attributeType == typeof(Vim.G3dNext.Attributes.IndicesAttribute)) - return IndicesAttribute; + if (attributeType == typeof(Vim.G3dNext.Attributes.VimPositionsAttribute)) + return Positions; + + + if (attributeType == typeof(Vim.G3dNext.Attributes.VimIndicesAttribute)) + return Indices; + + + if (attributeType == typeof(Vim.G3dNext.Attributes.VimInstanceTransformsAttribute)) + return InstanceTransforms; + + + if (attributeType == typeof(Vim.G3dNext.Attributes.VimInstanceParentsAttribute)) + return InstanceParents; - if (attributeType == typeof(Vim.G3dNext.Attributes.InstanceTransformsAttribute)) - return InstanceTransformsAttribute; - if (attributeType == typeof(Vim.G3dNext.Attributes.InstanceParentsAttribute)) - return InstanceParentsAttribute; + if (attributeType == typeof(Vim.G3dNext.Attributes.VimInstanceFlagsAttribute)) + return InstanceFlags; - if (attributeType == typeof(Vim.G3dNext.Attributes.InstanceFlagsAttribute)) - return InstanceFlagsAttribute; - if (attributeType == typeof(Vim.G3dNext.Attributes.InstanceMeshesAttribute)) - return InstanceMeshesAttribute; + if (attributeType == typeof(Vim.G3dNext.Attributes.VimInstanceMeshesAttribute)) + return InstanceMeshes; - if (attributeType == typeof(Vim.G3dNext.Attributes.MeshSubmeshOffsetsAttribute)) - return MeshSubmeshOffsetsAttribute; - if (attributeType == typeof(Vim.G3dNext.Attributes.SubmeshIndexOffsetsAttribute)) - return SubmeshIndexOffsetsAttribute; + if (attributeType == typeof(Vim.G3dNext.Attributes.VimMeshSubmeshOffsetsAttribute)) + return MeshSubmeshOffsets; - if (attributeType == typeof(Vim.G3dNext.Attributes.SubmeshMaterialsAttribute)) - return SubmeshMaterialsAttribute; - if (attributeType == typeof(Vim.G3dNext.Attributes.MaterialColorsAttribute)) - return MaterialColorsAttribute; + if (attributeType == typeof(Vim.G3dNext.Attributes.VimSubmeshIndexOffsetsAttribute)) + return SubmeshIndexOffsets; - if (attributeType == typeof(Vim.G3dNext.Attributes.MaterialGlossinessAttribute)) - return MaterialGlossinessAttribute; - if (attributeType == typeof(Vim.G3dNext.Attributes.MaterialSmoothnessAttribute)) - return MaterialSmoothnessAttribute; + if (attributeType == typeof(Vim.G3dNext.Attributes.VimSubmeshMaterialsAttribute)) + return SubmeshMaterials; - if (attributeType == typeof(Vim.G3dNext.Attributes.ShapeVerticesAttribute)) - return ShapeVerticesAttribute; - if (attributeType == typeof(Vim.G3dNext.Attributes.ShapeVertexOffsetsAttribute)) - return ShapeVertexOffsetsAttribute; + if (attributeType == typeof(Vim.G3dNext.Attributes.VimMaterialColorsAttribute)) + return MaterialColors; - if (attributeType == typeof(Vim.G3dNext.Attributes.ShapeColorsAttribute)) - return ShapeColorsAttribute; - if (attributeType == typeof(Vim.G3dNext.Attributes.ShapeWidthsAttribute)) - return ShapeWidthsAttribute; + if (attributeType == typeof(Vim.G3dNext.Attributes.VimMaterialGlossinessAttribute)) + return MaterialGlossiness; + + + if (attributeType == typeof(Vim.G3dNext.Attributes.VimMaterialSmoothnessAttribute)) + return MaterialSmoothness; + + + if (attributeType == typeof(Vim.G3dNext.Attributes.VimShapeVerticesAttribute)) + return ShapeVertices; + + + if (attributeType == typeof(Vim.G3dNext.Attributes.VimShapeVertexOffsetsAttribute)) + return ShapeVertexOffsets; + + + if (attributeType == typeof(Vim.G3dNext.Attributes.VimShapeColorsAttribute)) + return ShapeColors; + + + if (attributeType == typeof(Vim.G3dNext.Attributes.VimShapeWidthsAttribute)) + return ShapeWidths; throw new ArgumentException("Type {attributeType.ToString()} is not supported."); } @@ -1910,100 +2196,100 @@ public IAttribute MergeAttribute(string attributeName, IReadOnlyList().ToArray().MergeDataAttributes(); + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); } - case Vim.G3dNext.Attributes.IndicesAttribute.AttributeName: + case Vim.G3dNext.Attributes.VimIndicesAttribute.AttributeName: { // Index Attribute - return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); + return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); } - case Vim.G3dNext.Attributes.InstanceTransformsAttribute.AttributeName: + case Vim.G3dNext.Attributes.VimInstanceTransformsAttribute.AttributeName: { // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); } - case Vim.G3dNext.Attributes.InstanceParentsAttribute.AttributeName: + case Vim.G3dNext.Attributes.VimInstanceParentsAttribute.AttributeName: { // Index Attribute - return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); + return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); } - case Vim.G3dNext.Attributes.InstanceFlagsAttribute.AttributeName: + case Vim.G3dNext.Attributes.VimInstanceFlagsAttribute.AttributeName: { // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); } - case Vim.G3dNext.Attributes.InstanceMeshesAttribute.AttributeName: + case Vim.G3dNext.Attributes.VimInstanceMeshesAttribute.AttributeName: { // Index Attribute - return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); + return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); } - case Vim.G3dNext.Attributes.MeshSubmeshOffsetsAttribute.AttributeName: + case Vim.G3dNext.Attributes.VimMeshSubmeshOffsetsAttribute.AttributeName: { // Index Attribute - return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); + return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); } - case Vim.G3dNext.Attributes.SubmeshIndexOffsetsAttribute.AttributeName: + case Vim.G3dNext.Attributes.VimSubmeshIndexOffsetsAttribute.AttributeName: { // Index Attribute - return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); + return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); } - case Vim.G3dNext.Attributes.SubmeshMaterialsAttribute.AttributeName: + case Vim.G3dNext.Attributes.VimSubmeshMaterialsAttribute.AttributeName: { // Index Attribute - return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); + return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); } - case Vim.G3dNext.Attributes.MaterialColorsAttribute.AttributeName: + case Vim.G3dNext.Attributes.VimMaterialColorsAttribute.AttributeName: { // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); } - case Vim.G3dNext.Attributes.MaterialGlossinessAttribute.AttributeName: + case Vim.G3dNext.Attributes.VimMaterialGlossinessAttribute.AttributeName: { // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); } - case Vim.G3dNext.Attributes.MaterialSmoothnessAttribute.AttributeName: + case Vim.G3dNext.Attributes.VimMaterialSmoothnessAttribute.AttributeName: { // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); } - case Vim.G3dNext.Attributes.ShapeVerticesAttribute.AttributeName: + case Vim.G3dNext.Attributes.VimShapeVerticesAttribute.AttributeName: { // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); } - case Vim.G3dNext.Attributes.ShapeVertexOffsetsAttribute.AttributeName: + case Vim.G3dNext.Attributes.VimShapeVertexOffsetsAttribute.AttributeName: { // Index Attribute - return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); + return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); } - case Vim.G3dNext.Attributes.ShapeColorsAttribute.AttributeName: + case Vim.G3dNext.Attributes.VimShapeColorsAttribute.AttributeName: { // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); } - case Vim.G3dNext.Attributes.ShapeWidthsAttribute.AttributeName: + case Vim.G3dNext.Attributes.VimShapeWidthsAttribute.AttributeName: { // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); } default: @@ -2016,100 +2302,100 @@ public void Validate() // Ensure all the indices are either -1 or within the bounds of the attributes they are indexing into. { - var maxIndex = GetAttribute(IndicesAttribute.IndexInto).Data.Length - 1; - for (var i = 0; i < IndicesAttribute.TypedData.Length; ++i) + var maxIndex = GetAttribute(Indices.IndexInto).Data.Length - 1; + for (var i = 0; i < Indices.TypedData.Length; ++i) { - var index = IndicesAttribute.TypedData[i]; + var index = Indices.TypedData[i]; if (index == -1) continue; // no relation. if (index < -1 || index > maxIndex) - throw new Exception($"Index out of range in Vim.G3dNext.Attributes.IndicesAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); + throw new Exception($"Index out of range in Vim.G3dNext.Attributes.VimIndicesAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); } } { - var maxIndex = GetAttribute(InstanceParentsAttribute.IndexInto).Data.Length - 1; - for (var i = 0; i < InstanceParentsAttribute.TypedData.Length; ++i) + var maxIndex = GetAttribute(InstanceParents.IndexInto).Data.Length - 1; + for (var i = 0; i < InstanceParents.TypedData.Length; ++i) { - var index = InstanceParentsAttribute.TypedData[i]; + var index = InstanceParents.TypedData[i]; if (index == -1) continue; // no relation. if (index < -1 || index > maxIndex) - throw new Exception($"Index out of range in Vim.G3dNext.Attributes.InstanceParentsAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); + throw new Exception($"Index out of range in Vim.G3dNext.Attributes.VimInstanceParentsAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); } } { - var maxIndex = GetAttribute(InstanceMeshesAttribute.IndexInto).Data.Length - 1; - for (var i = 0; i < InstanceMeshesAttribute.TypedData.Length; ++i) + var maxIndex = GetAttribute(InstanceMeshes.IndexInto).Data.Length - 1; + for (var i = 0; i < InstanceMeshes.TypedData.Length; ++i) { - var index = InstanceMeshesAttribute.TypedData[i]; + var index = InstanceMeshes.TypedData[i]; if (index == -1) continue; // no relation. if (index < -1 || index > maxIndex) - throw new Exception($"Index out of range in Vim.G3dNext.Attributes.InstanceMeshesAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); + throw new Exception($"Index out of range in Vim.G3dNext.Attributes.VimInstanceMeshesAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); } } { - var maxIndex = GetAttribute(MeshSubmeshOffsetsAttribute.IndexInto).Data.Length - 1; - for (var i = 0; i < MeshSubmeshOffsetsAttribute.TypedData.Length; ++i) + var maxIndex = GetAttribute(MeshSubmeshOffsets.IndexInto).Data.Length - 1; + for (var i = 0; i < MeshSubmeshOffsets.TypedData.Length; ++i) { - var index = MeshSubmeshOffsetsAttribute.TypedData[i]; + var index = MeshSubmeshOffsets.TypedData[i]; if (index == -1) continue; // no relation. if (index < -1 || index > maxIndex) - throw new Exception($"Index out of range in Vim.G3dNext.Attributes.MeshSubmeshOffsetsAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); + throw new Exception($"Index out of range in Vim.G3dNext.Attributes.VimMeshSubmeshOffsetsAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); } } { - var maxIndex = GetAttribute(SubmeshIndexOffsetsAttribute.IndexInto).Data.Length - 1; - for (var i = 0; i < SubmeshIndexOffsetsAttribute.TypedData.Length; ++i) + var maxIndex = GetAttribute(SubmeshIndexOffsets.IndexInto).Data.Length - 1; + for (var i = 0; i < SubmeshIndexOffsets.TypedData.Length; ++i) { - var index = SubmeshIndexOffsetsAttribute.TypedData[i]; + var index = SubmeshIndexOffsets.TypedData[i]; if (index == -1) continue; // no relation. if (index < -1 || index > maxIndex) - throw new Exception($"Index out of range in Vim.G3dNext.Attributes.SubmeshIndexOffsetsAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); + throw new Exception($"Index out of range in Vim.G3dNext.Attributes.VimSubmeshIndexOffsetsAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); } } { - var maxIndex = GetAttribute(SubmeshMaterialsAttribute.IndexInto).Data.Length - 1; - for (var i = 0; i < SubmeshMaterialsAttribute.TypedData.Length; ++i) + var maxIndex = GetAttribute(SubmeshMaterials.IndexInto).Data.Length - 1; + for (var i = 0; i < SubmeshMaterials.TypedData.Length; ++i) { - var index = SubmeshMaterialsAttribute.TypedData[i]; + var index = SubmeshMaterials.TypedData[i]; if (index == -1) continue; // no relation. if (index < -1 || index > maxIndex) - throw new Exception($"Index out of range in Vim.G3dNext.Attributes.SubmeshMaterialsAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); + throw new Exception($"Index out of range in Vim.G3dNext.Attributes.VimSubmeshMaterialsAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); } } { - var maxIndex = GetAttribute(ShapeVertexOffsetsAttribute.IndexInto).Data.Length - 1; - for (var i = 0; i < ShapeVertexOffsetsAttribute.TypedData.Length; ++i) + var maxIndex = GetAttribute(ShapeVertexOffsets.IndexInto).Data.Length - 1; + for (var i = 0; i < ShapeVertexOffsets.TypedData.Length; ++i) { - var index = ShapeVertexOffsetsAttribute.TypedData[i]; + var index = ShapeVertexOffsets.TypedData[i]; if (index == -1) continue; // no relation. if (index < -1 || index > maxIndex) - throw new Exception($"Index out of range in Vim.G3dNext.Attributes.ShapeVertexOffsetsAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); + throw new Exception($"Index out of range in Vim.G3dNext.Attributes.VimShapeVertexOffsetsAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); } } } @@ -2144,20 +2430,20 @@ public BFastNext ToBFast() public Vim.Math3d.Vector4[] MaterialColors { - get => Attributes.MaterialColorsAttribute.TypedData; - set => Attributes.MaterialColorsAttribute.TypedData = value; + get => Attributes.MaterialColors.TypedData; + set => Attributes.MaterialColors.TypedData = value; } public System.Single[] MaterialGlossiness { - get => Attributes.MaterialGlossinessAttribute.TypedData; - set => Attributes.MaterialGlossinessAttribute.TypedData = value; + get => Attributes.MaterialGlossiness.TypedData; + set => Attributes.MaterialGlossiness.TypedData = value; } public System.Single[] MaterialSmoothness { - get => Attributes.MaterialSmoothnessAttribute.TypedData; - set => Attributes.MaterialSmoothnessAttribute.TypedData = value; + get => Attributes.MaterialSmoothness.TypedData; + set => Attributes.MaterialSmoothness.TypedData = value; } } @@ -2192,19 +2478,19 @@ public void ReadAttributes(BFastNext bfast) // Named Attributes. - public Vim.G3dNext.Attributes.MaterialColorsAttribute MaterialColorsAttribute + public Vim.G3dNext.Attributes.MaterialColorsAttribute MaterialColors { get => Map.TryGetValue(Vim.G3dNext.Attributes.MaterialColorsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MaterialColorsAttribute : default; set => Map[Vim.G3dNext.Attributes.MaterialColorsAttribute.AttributeName] = value as IAttribute; } - public Vim.G3dNext.Attributes.MaterialGlossinessAttribute MaterialGlossinessAttribute + public Vim.G3dNext.Attributes.MaterialGlossinessAttribute MaterialGlossiness { get => Map.TryGetValue(Vim.G3dNext.Attributes.MaterialGlossinessAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MaterialGlossinessAttribute : default; set => Map[Vim.G3dNext.Attributes.MaterialGlossinessAttribute.AttributeName] = value as IAttribute; } - public Vim.G3dNext.Attributes.MaterialSmoothnessAttribute MaterialSmoothnessAttribute + public Vim.G3dNext.Attributes.MaterialSmoothnessAttribute MaterialSmoothness { get => Map.TryGetValue(Vim.G3dNext.Attributes.MaterialSmoothnessAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MaterialSmoothnessAttribute : default; set => Map[Vim.G3dNext.Attributes.MaterialSmoothnessAttribute.AttributeName] = value as IAttribute; @@ -2214,14 +2500,17 @@ public Vim.G3dNext.Attributes.MaterialSmoothnessAttribute MaterialSmoothnessAttr public IAttribute GetAttribute(Type attributeType) { - if (attributeType == typeof(Vim.G3dNext.Attributes.MaterialColorsAttribute)) - return MaterialColorsAttribute; - if (attributeType == typeof(Vim.G3dNext.Attributes.MaterialGlossinessAttribute)) - return MaterialGlossinessAttribute; + if (attributeType == typeof(Vim.G3dNext.Attributes.MaterialColorsAttribute)) + return MaterialColors; - if (attributeType == typeof(Vim.G3dNext.Attributes.MaterialSmoothnessAttribute)) - return MaterialSmoothnessAttribute; + + if (attributeType == typeof(Vim.G3dNext.Attributes.MaterialGlossinessAttribute)) + return MaterialGlossiness; + + + if (attributeType == typeof(Vim.G3dNext.Attributes.MaterialSmoothnessAttribute)) + return MaterialSmoothness; throw new ArgumentException("Type {attributeType.ToString()} is not supported."); } @@ -2289,82 +2578,94 @@ public BFastNext ToBFast() => Attributes.ToBFast(); - public System.Int32[] InstanceFiles + public System.Int32[] ChunkCount + { + get => Attributes.ChunkCount.TypedData; + set => Attributes.ChunkCount.TypedData = value; + } + + public System.Int32[] InstanceMeshes { - get => Attributes.InstanceFilesAttribute.TypedData; - set => Attributes.InstanceFilesAttribute.TypedData = value; + get => Attributes.InstanceMeshes.TypedData; + set => Attributes.InstanceMeshes.TypedData = value; } - public System.Int32[] InstanceIndices + public System.Int32[] InstanceTransforms { - get => Attributes.InstanceIndicesAttribute.TypedData; - set => Attributes.InstanceIndicesAttribute.TypedData = value; + get => Attributes.InstanceTransforms.TypedData; + set => Attributes.InstanceTransforms.TypedData = value; } public System.Int32[] InstanceNodes { - get => Attributes.InstanceNodesAttribute.TypedData; - set => Attributes.InstanceNodesAttribute.TypedData = value; + get => Attributes.InstanceNodes.TypedData; + set => Attributes.InstanceNodes.TypedData = value; } public System.Int32[] InstanceGroups { - get => Attributes.InstanceGroupsAttribute.TypedData; - set => Attributes.InstanceGroupsAttribute.TypedData = value; + get => Attributes.InstanceGroups.TypedData; + set => Attributes.InstanceGroups.TypedData = value; } public System.Int64[] InstanceTags { - get => Attributes.InstanceTagsAttribute.TypedData; - set => Attributes.InstanceTagsAttribute.TypedData = value; + get => Attributes.InstanceTags.TypedData; + set => Attributes.InstanceTags.TypedData = value; } public System.UInt16[] InstanceFlags { - get => Attributes.InstanceFlagsAttribute.TypedData; - set => Attributes.InstanceFlagsAttribute.TypedData = value; + get => Attributes.InstanceFlags.TypedData; + set => Attributes.InstanceFlags.TypedData = value; } public Vim.Math3d.Vector3[] InstanceMins { - get => Attributes.InstanceMinsAttribute.TypedData; - set => Attributes.InstanceMinsAttribute.TypedData = value; + get => Attributes.InstanceMins.TypedData; + set => Attributes.InstanceMins.TypedData = value; } public Vim.Math3d.Vector3[] InstanceMaxs { - get => Attributes.InstanceMaxsAttribute.TypedData; - set => Attributes.InstanceMaxsAttribute.TypedData = value; + get => Attributes.InstanceMaxs.TypedData; + set => Attributes.InstanceMaxs.TypedData = value; + } + + public System.Int32[] MeshChunks + { + get => Attributes.MeshChunks.TypedData; + set => Attributes.MeshChunks.TypedData = value; } public System.Int32[] MeshInstanceCounts { - get => Attributes.MeshInstanceCountsAttribute.TypedData; - set => Attributes.MeshInstanceCountsAttribute.TypedData = value; + get => Attributes.MeshInstanceCounts.TypedData; + set => Attributes.MeshInstanceCounts.TypedData = value; } public System.Int32[] MeshIndexCounts { - get => Attributes.MeshIndexCountsAttribute.TypedData; - set => Attributes.MeshIndexCountsAttribute.TypedData = value; + get => Attributes.MeshIndexCounts.TypedData; + set => Attributes.MeshIndexCounts.TypedData = value; } public System.Int32[] MeshVertexCounts { - get => Attributes.MeshVertexCountsAttribute.TypedData; - set => Attributes.MeshVertexCountsAttribute.TypedData = value; + get => Attributes.MeshVertexCounts.TypedData; + set => Attributes.MeshVertexCounts.TypedData = value; } public System.Int32[] MeshOpaqueIndexCounts { - get => Attributes.MeshOpaqueIndexCountsAttribute.TypedData; - set => Attributes.MeshOpaqueIndexCountsAttribute.TypedData = value; + get => Attributes.MeshOpaqueIndexCounts.TypedData; + set => Attributes.MeshOpaqueIndexCounts.TypedData = value; } public System.Int32[] MeshOpaqueVertexCounts { - get => Attributes.MeshOpaqueVertexCountsAttribute.TypedData; - set => Attributes.MeshOpaqueVertexCountsAttribute.TypedData = value; + get => Attributes.MeshOpaqueVertexCounts.TypedData; + set => Attributes.MeshOpaqueVertexCounts.TypedData = value; } } @@ -2392,143 +2693,178 @@ public void ReadAttributes(BFastNext bfast) public IDictionary Map { get; } = new Dictionary { - [Vim.G3dNext.Attributes.InstanceFilesAttribute.AttributeName] = new Vim.G3dNext.Attributes.InstanceFilesAttribute(), - [Vim.G3dNext.Attributes.InstanceIndicesAttribute.AttributeName] = new Vim.G3dNext.Attributes.InstanceIndicesAttribute(), - [Vim.G3dNext.Attributes.InstanceNodesAttribute.AttributeName] = new Vim.G3dNext.Attributes.InstanceNodesAttribute(), - [Vim.G3dNext.Attributes.InstanceGroupsAttribute.AttributeName] = new Vim.G3dNext.Attributes.InstanceGroupsAttribute(), - [Vim.G3dNext.Attributes.InstanceTagsAttribute.AttributeName] = new Vim.G3dNext.Attributes.InstanceTagsAttribute(), - [Vim.G3dNext.Attributes.InstanceFlagsAttribute.AttributeName] = new Vim.G3dNext.Attributes.InstanceFlagsAttribute(), - [Vim.G3dNext.Attributes.InstanceMinsAttribute.AttributeName] = new Vim.G3dNext.Attributes.InstanceMinsAttribute(), - [Vim.G3dNext.Attributes.InstanceMaxsAttribute.AttributeName] = new Vim.G3dNext.Attributes.InstanceMaxsAttribute(), - [Vim.G3dNext.Attributes.MeshInstanceCountsAttribute.AttributeName] = new Vim.G3dNext.Attributes.MeshInstanceCountsAttribute(), - [Vim.G3dNext.Attributes.MeshIndexCountsAttribute.AttributeName] = new Vim.G3dNext.Attributes.MeshIndexCountsAttribute(), - [Vim.G3dNext.Attributes.MeshVertexCountsAttribute.AttributeName] = new Vim.G3dNext.Attributes.MeshVertexCountsAttribute(), - [Vim.G3dNext.Attributes.MeshOpaqueIndexCountsAttribute.AttributeName] = new Vim.G3dNext.Attributes.MeshOpaqueIndexCountsAttribute(), - [Vim.G3dNext.Attributes.MeshOpaqueVertexCountsAttribute.AttributeName] = new Vim.G3dNext.Attributes.MeshOpaqueVertexCountsAttribute(), + [Vim.G3dNext.Attributes.SceneChunkCountAttribute.AttributeName] = new Vim.G3dNext.Attributes.SceneChunkCountAttribute(), + [Vim.G3dNext.Attributes.SceneInstanceMeshesAttribute.AttributeName] = new Vim.G3dNext.Attributes.SceneInstanceMeshesAttribute(), + [Vim.G3dNext.Attributes.SceneInstanceTransformsAttribute.AttributeName] = new Vim.G3dNext.Attributes.SceneInstanceTransformsAttribute(), + [Vim.G3dNext.Attributes.SceneInstanceNodesAttribute.AttributeName] = new Vim.G3dNext.Attributes.SceneInstanceNodesAttribute(), + [Vim.G3dNext.Attributes.SceneInstanceGroupsAttribute.AttributeName] = new Vim.G3dNext.Attributes.SceneInstanceGroupsAttribute(), + [Vim.G3dNext.Attributes.SceneInstanceTagsAttribute.AttributeName] = new Vim.G3dNext.Attributes.SceneInstanceTagsAttribute(), + [Vim.G3dNext.Attributes.SceneInstanceFlagsAttribute.AttributeName] = new Vim.G3dNext.Attributes.SceneInstanceFlagsAttribute(), + [Vim.G3dNext.Attributes.SceneInstanceMinsAttribute.AttributeName] = new Vim.G3dNext.Attributes.SceneInstanceMinsAttribute(), + [Vim.G3dNext.Attributes.SceneInstanceMaxsAttribute.AttributeName] = new Vim.G3dNext.Attributes.SceneInstanceMaxsAttribute(), + [Vim.G3dNext.Attributes.SceneMeshChunksAttribute.AttributeName] = new Vim.G3dNext.Attributes.SceneMeshChunksAttribute(), + [Vim.G3dNext.Attributes.SceneMeshInstanceCountsAttribute.AttributeName] = new Vim.G3dNext.Attributes.SceneMeshInstanceCountsAttribute(), + [Vim.G3dNext.Attributes.SceneMeshIndexCountsAttribute.AttributeName] = new Vim.G3dNext.Attributes.SceneMeshIndexCountsAttribute(), + [Vim.G3dNext.Attributes.SceneMeshVertexCountsAttribute.AttributeName] = new Vim.G3dNext.Attributes.SceneMeshVertexCountsAttribute(), + [Vim.G3dNext.Attributes.SceneMeshOpaqueIndexCountsAttribute.AttributeName] = new Vim.G3dNext.Attributes.SceneMeshOpaqueIndexCountsAttribute(), + [Vim.G3dNext.Attributes.SceneMeshOpaqueVertexCountsAttribute.AttributeName] = new Vim.G3dNext.Attributes.SceneMeshOpaqueVertexCountsAttribute(), }; // Named Attributes. - public Vim.G3dNext.Attributes.InstanceFilesAttribute InstanceFilesAttribute + public Vim.G3dNext.Attributes.SceneChunkCountAttribute ChunkCount + { + get => Map.TryGetValue(Vim.G3dNext.Attributes.SceneChunkCountAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.SceneChunkCountAttribute : default; + set => Map[Vim.G3dNext.Attributes.SceneChunkCountAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.SceneInstanceMeshesAttribute InstanceMeshes + { + get => Map.TryGetValue(Vim.G3dNext.Attributes.SceneInstanceMeshesAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.SceneInstanceMeshesAttribute : default; + set => Map[Vim.G3dNext.Attributes.SceneInstanceMeshesAttribute.AttributeName] = value as IAttribute; + } + + public Vim.G3dNext.Attributes.SceneInstanceTransformsAttribute InstanceTransforms { - get => Map.TryGetValue(Vim.G3dNext.Attributes.InstanceFilesAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceFilesAttribute : default; - set => Map[Vim.G3dNext.Attributes.InstanceFilesAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.SceneInstanceTransformsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.SceneInstanceTransformsAttribute : default; + set => Map[Vim.G3dNext.Attributes.SceneInstanceTransformsAttribute.AttributeName] = value as IAttribute; } - public Vim.G3dNext.Attributes.InstanceIndicesAttribute InstanceIndicesAttribute + public Vim.G3dNext.Attributes.SceneInstanceNodesAttribute InstanceNodes { - get => Map.TryGetValue(Vim.G3dNext.Attributes.InstanceIndicesAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceIndicesAttribute : default; - set => Map[Vim.G3dNext.Attributes.InstanceIndicesAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.SceneInstanceNodesAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.SceneInstanceNodesAttribute : default; + set => Map[Vim.G3dNext.Attributes.SceneInstanceNodesAttribute.AttributeName] = value as IAttribute; } - public Vim.G3dNext.Attributes.InstanceNodesAttribute InstanceNodesAttribute + public Vim.G3dNext.Attributes.SceneInstanceGroupsAttribute InstanceGroups { - get => Map.TryGetValue(Vim.G3dNext.Attributes.InstanceNodesAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceNodesAttribute : default; - set => Map[Vim.G3dNext.Attributes.InstanceNodesAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.SceneInstanceGroupsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.SceneInstanceGroupsAttribute : default; + set => Map[Vim.G3dNext.Attributes.SceneInstanceGroupsAttribute.AttributeName] = value as IAttribute; } - public Vim.G3dNext.Attributes.InstanceGroupsAttribute InstanceGroupsAttribute + public Vim.G3dNext.Attributes.SceneInstanceTagsAttribute InstanceTags { - get => Map.TryGetValue(Vim.G3dNext.Attributes.InstanceGroupsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceGroupsAttribute : default; - set => Map[Vim.G3dNext.Attributes.InstanceGroupsAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.SceneInstanceTagsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.SceneInstanceTagsAttribute : default; + set => Map[Vim.G3dNext.Attributes.SceneInstanceTagsAttribute.AttributeName] = value as IAttribute; } - public Vim.G3dNext.Attributes.InstanceTagsAttribute InstanceTagsAttribute + public Vim.G3dNext.Attributes.SceneInstanceFlagsAttribute InstanceFlags { - get => Map.TryGetValue(Vim.G3dNext.Attributes.InstanceTagsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceTagsAttribute : default; - set => Map[Vim.G3dNext.Attributes.InstanceTagsAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.SceneInstanceFlagsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.SceneInstanceFlagsAttribute : default; + set => Map[Vim.G3dNext.Attributes.SceneInstanceFlagsAttribute.AttributeName] = value as IAttribute; } - public Vim.G3dNext.Attributes.InstanceFlagsAttribute InstanceFlagsAttribute + public Vim.G3dNext.Attributes.SceneInstanceMinsAttribute InstanceMins { - get => Map.TryGetValue(Vim.G3dNext.Attributes.InstanceFlagsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceFlagsAttribute : default; - set => Map[Vim.G3dNext.Attributes.InstanceFlagsAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.SceneInstanceMinsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.SceneInstanceMinsAttribute : default; + set => Map[Vim.G3dNext.Attributes.SceneInstanceMinsAttribute.AttributeName] = value as IAttribute; } - public Vim.G3dNext.Attributes.InstanceMinsAttribute InstanceMinsAttribute + public Vim.G3dNext.Attributes.SceneInstanceMaxsAttribute InstanceMaxs { - get => Map.TryGetValue(Vim.G3dNext.Attributes.InstanceMinsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceMinsAttribute : default; - set => Map[Vim.G3dNext.Attributes.InstanceMinsAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.SceneInstanceMaxsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.SceneInstanceMaxsAttribute : default; + set => Map[Vim.G3dNext.Attributes.SceneInstanceMaxsAttribute.AttributeName] = value as IAttribute; } - public Vim.G3dNext.Attributes.InstanceMaxsAttribute InstanceMaxsAttribute + public Vim.G3dNext.Attributes.SceneMeshChunksAttribute MeshChunks { - get => Map.TryGetValue(Vim.G3dNext.Attributes.InstanceMaxsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.InstanceMaxsAttribute : default; - set => Map[Vim.G3dNext.Attributes.InstanceMaxsAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.SceneMeshChunksAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.SceneMeshChunksAttribute : default; + set => Map[Vim.G3dNext.Attributes.SceneMeshChunksAttribute.AttributeName] = value as IAttribute; } - public Vim.G3dNext.Attributes.MeshInstanceCountsAttribute MeshInstanceCountsAttribute + public Vim.G3dNext.Attributes.SceneMeshInstanceCountsAttribute MeshInstanceCounts { - get => Map.TryGetValue(Vim.G3dNext.Attributes.MeshInstanceCountsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshInstanceCountsAttribute : default; - set => Map[Vim.G3dNext.Attributes.MeshInstanceCountsAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.SceneMeshInstanceCountsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.SceneMeshInstanceCountsAttribute : default; + set => Map[Vim.G3dNext.Attributes.SceneMeshInstanceCountsAttribute.AttributeName] = value as IAttribute; } - public Vim.G3dNext.Attributes.MeshIndexCountsAttribute MeshIndexCountsAttribute + public Vim.G3dNext.Attributes.SceneMeshIndexCountsAttribute MeshIndexCounts { - get => Map.TryGetValue(Vim.G3dNext.Attributes.MeshIndexCountsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshIndexCountsAttribute : default; - set => Map[Vim.G3dNext.Attributes.MeshIndexCountsAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.SceneMeshIndexCountsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.SceneMeshIndexCountsAttribute : default; + set => Map[Vim.G3dNext.Attributes.SceneMeshIndexCountsAttribute.AttributeName] = value as IAttribute; } - public Vim.G3dNext.Attributes.MeshVertexCountsAttribute MeshVertexCountsAttribute + public Vim.G3dNext.Attributes.SceneMeshVertexCountsAttribute MeshVertexCounts { - get => Map.TryGetValue(Vim.G3dNext.Attributes.MeshVertexCountsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshVertexCountsAttribute : default; - set => Map[Vim.G3dNext.Attributes.MeshVertexCountsAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.SceneMeshVertexCountsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.SceneMeshVertexCountsAttribute : default; + set => Map[Vim.G3dNext.Attributes.SceneMeshVertexCountsAttribute.AttributeName] = value as IAttribute; } - public Vim.G3dNext.Attributes.MeshOpaqueIndexCountsAttribute MeshOpaqueIndexCountsAttribute + public Vim.G3dNext.Attributes.SceneMeshOpaqueIndexCountsAttribute MeshOpaqueIndexCounts { - get => Map.TryGetValue(Vim.G3dNext.Attributes.MeshOpaqueIndexCountsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshOpaqueIndexCountsAttribute : default; - set => Map[Vim.G3dNext.Attributes.MeshOpaqueIndexCountsAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.SceneMeshOpaqueIndexCountsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.SceneMeshOpaqueIndexCountsAttribute : default; + set => Map[Vim.G3dNext.Attributes.SceneMeshOpaqueIndexCountsAttribute.AttributeName] = value as IAttribute; } - public Vim.G3dNext.Attributes.MeshOpaqueVertexCountsAttribute MeshOpaqueVertexCountsAttribute + public Vim.G3dNext.Attributes.SceneMeshOpaqueVertexCountsAttribute MeshOpaqueVertexCounts { - get => Map.TryGetValue(Vim.G3dNext.Attributes.MeshOpaqueVertexCountsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshOpaqueVertexCountsAttribute : default; - set => Map[Vim.G3dNext.Attributes.MeshOpaqueVertexCountsAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.SceneMeshOpaqueVertexCountsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.SceneMeshOpaqueVertexCountsAttribute : default; + set => Map[Vim.G3dNext.Attributes.SceneMeshOpaqueVertexCountsAttribute.AttributeName] = value as IAttribute; } /// public IAttribute GetAttribute(Type attributeType) { - if (attributeType == typeof(Vim.G3dNext.Attributes.InstanceFilesAttribute)) - return InstanceFilesAttribute; - if (attributeType == typeof(Vim.G3dNext.Attributes.InstanceIndicesAttribute)) - return InstanceIndicesAttribute; + if (attributeType == typeof(Vim.G3dNext.Attributes.SceneChunkCountAttribute)) + return ChunkCount; + + + if (attributeType == typeof(Vim.G3dNext.Attributes.SceneInstanceMeshesAttribute)) + return InstanceMeshes; + + + if (attributeType == typeof(Vim.G3dNext.Attributes.SceneInstanceTransformsAttribute)) + return InstanceTransforms; + + + if (attributeType == typeof(Vim.G3dNext.Attributes.SceneInstanceNodesAttribute)) + return InstanceNodes; + + + if (attributeType == typeof(Vim.G3dNext.Attributes.SceneInstanceGroupsAttribute)) + return InstanceGroups; + + + if (attributeType == typeof(Vim.G3dNext.Attributes.SceneInstanceTagsAttribute)) + return InstanceTags; + - if (attributeType == typeof(Vim.G3dNext.Attributes.InstanceNodesAttribute)) - return InstanceNodesAttribute; + if (attributeType == typeof(Vim.G3dNext.Attributes.SceneInstanceFlagsAttribute)) + return InstanceFlags; - if (attributeType == typeof(Vim.G3dNext.Attributes.InstanceGroupsAttribute)) - return InstanceGroupsAttribute; - if (attributeType == typeof(Vim.G3dNext.Attributes.InstanceTagsAttribute)) - return InstanceTagsAttribute; + if (attributeType == typeof(Vim.G3dNext.Attributes.SceneInstanceMinsAttribute)) + return InstanceMins; - if (attributeType == typeof(Vim.G3dNext.Attributes.InstanceFlagsAttribute)) - return InstanceFlagsAttribute; - if (attributeType == typeof(Vim.G3dNext.Attributes.InstanceMinsAttribute)) - return InstanceMinsAttribute; + if (attributeType == typeof(Vim.G3dNext.Attributes.SceneInstanceMaxsAttribute)) + return InstanceMaxs; - if (attributeType == typeof(Vim.G3dNext.Attributes.InstanceMaxsAttribute)) - return InstanceMaxsAttribute; - if (attributeType == typeof(Vim.G3dNext.Attributes.MeshInstanceCountsAttribute)) - return MeshInstanceCountsAttribute; + if (attributeType == typeof(Vim.G3dNext.Attributes.SceneMeshChunksAttribute)) + return MeshChunks; - if (attributeType == typeof(Vim.G3dNext.Attributes.MeshIndexCountsAttribute)) - return MeshIndexCountsAttribute; - if (attributeType == typeof(Vim.G3dNext.Attributes.MeshVertexCountsAttribute)) - return MeshVertexCountsAttribute; + if (attributeType == typeof(Vim.G3dNext.Attributes.SceneMeshInstanceCountsAttribute)) + return MeshInstanceCounts; - if (attributeType == typeof(Vim.G3dNext.Attributes.MeshOpaqueIndexCountsAttribute)) - return MeshOpaqueIndexCountsAttribute; - if (attributeType == typeof(Vim.G3dNext.Attributes.MeshOpaqueVertexCountsAttribute)) - return MeshOpaqueVertexCountsAttribute; + if (attributeType == typeof(Vim.G3dNext.Attributes.SceneMeshIndexCountsAttribute)) + return MeshIndexCounts; + + + if (attributeType == typeof(Vim.G3dNext.Attributes.SceneMeshVertexCountsAttribute)) + return MeshVertexCounts; + + + if (attributeType == typeof(Vim.G3dNext.Attributes.SceneMeshOpaqueIndexCountsAttribute)) + return MeshOpaqueIndexCounts; + + + if (attributeType == typeof(Vim.G3dNext.Attributes.SceneMeshOpaqueVertexCountsAttribute)) + return MeshOpaqueVertexCounts; throw new ArgumentException("Type {attributeType.ToString()} is not supported."); } @@ -2539,82 +2875,94 @@ public IAttribute MergeAttribute(string attributeName, IReadOnlyList().ToArray().MergeDataAttributes(); + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); } - case Vim.G3dNext.Attributes.InstanceIndicesAttribute.AttributeName: + case Vim.G3dNext.Attributes.SceneInstanceMeshesAttribute.AttributeName: { // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); } - case Vim.G3dNext.Attributes.InstanceNodesAttribute.AttributeName: + case Vim.G3dNext.Attributes.SceneInstanceTransformsAttribute.AttributeName: { // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); } - case Vim.G3dNext.Attributes.InstanceGroupsAttribute.AttributeName: + case Vim.G3dNext.Attributes.SceneInstanceNodesAttribute.AttributeName: { // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); } - case Vim.G3dNext.Attributes.InstanceTagsAttribute.AttributeName: + case Vim.G3dNext.Attributes.SceneInstanceGroupsAttribute.AttributeName: { // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); } - case Vim.G3dNext.Attributes.InstanceFlagsAttribute.AttributeName: + case Vim.G3dNext.Attributes.SceneInstanceTagsAttribute.AttributeName: { // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); } - case Vim.G3dNext.Attributes.InstanceMinsAttribute.AttributeName: + case Vim.G3dNext.Attributes.SceneInstanceFlagsAttribute.AttributeName: { // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); } - case Vim.G3dNext.Attributes.InstanceMaxsAttribute.AttributeName: + case Vim.G3dNext.Attributes.SceneInstanceMinsAttribute.AttributeName: { // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); } - case Vim.G3dNext.Attributes.MeshInstanceCountsAttribute.AttributeName: + case Vim.G3dNext.Attributes.SceneInstanceMaxsAttribute.AttributeName: { // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); } - case Vim.G3dNext.Attributes.MeshIndexCountsAttribute.AttributeName: + case Vim.G3dNext.Attributes.SceneMeshChunksAttribute.AttributeName: { // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); } - case Vim.G3dNext.Attributes.MeshVertexCountsAttribute.AttributeName: + case Vim.G3dNext.Attributes.SceneMeshInstanceCountsAttribute.AttributeName: { // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); } - case Vim.G3dNext.Attributes.MeshOpaqueIndexCountsAttribute.AttributeName: + case Vim.G3dNext.Attributes.SceneMeshIndexCountsAttribute.AttributeName: { // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); } - case Vim.G3dNext.Attributes.MeshOpaqueVertexCountsAttribute.AttributeName: + case Vim.G3dNext.Attributes.SceneMeshVertexCountsAttribute.AttributeName: { // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + } + + case Vim.G3dNext.Attributes.SceneMeshOpaqueIndexCountsAttribute.AttributeName: + { + // Data Attribute + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + } + + case Vim.G3dNext.Attributes.SceneMeshOpaqueVertexCountsAttribute.AttributeName: + { + // Data Attribute + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); } default: @@ -2658,44 +3006,44 @@ public BFastNext ToBFast() public Vim.Math3d.Matrix4x4[] InstanceTransforms { - get => Attributes.MeshInstanceTransformsAttribute.TypedData; - set => Attributes.MeshInstanceTransformsAttribute.TypedData = value; + get => Attributes.InstanceTransforms.TypedData; + set => Attributes.InstanceTransforms.TypedData = value; } public System.Int32[] OpaqueSubmeshCounts { - get => Attributes.MeshOpaqueSubmeshCountsAttribute.TypedData; - set => Attributes.MeshOpaqueSubmeshCountsAttribute.TypedData = value; + get => Attributes.OpaqueSubmeshCounts.TypedData; + set => Attributes.OpaqueSubmeshCounts.TypedData = value; } public System.Int32[] SubmeshIndexOffsets { - get => Attributes.MeshSubmeshIndexOffsetsAttribute.TypedData; - set => Attributes.MeshSubmeshIndexOffsetsAttribute.TypedData = value; + get => Attributes.SubmeshIndexOffsets.TypedData; + set => Attributes.SubmeshIndexOffsets.TypedData = value; } public System.Int32[] SubmeshVertexOffsets { - get => Attributes.MeshSubmeshVertexOffsetsAttribute.TypedData; - set => Attributes.MeshSubmeshVertexOffsetsAttribute.TypedData = value; + get => Attributes.SubmeshVertexOffsets.TypedData; + set => Attributes.SubmeshVertexOffsets.TypedData = value; } public System.Int32[] SubmeshMaterials { - get => Attributes.MeshSubmeshMaterialsAttribute.TypedData; - set => Attributes.MeshSubmeshMaterialsAttribute.TypedData = value; + get => Attributes.SubmeshMaterials.TypedData; + set => Attributes.SubmeshMaterials.TypedData = value; } public Vim.Math3d.Vector3[] Positions { - get => Attributes.MeshPositionsAttribute.TypedData; - set => Attributes.MeshPositionsAttribute.TypedData = value; + get => Attributes.Positions.TypedData; + set => Attributes.Positions.TypedData = value; } public System.Int32[] Indices { - get => Attributes.MeshIndicesAttribute.TypedData; - set => Attributes.MeshIndicesAttribute.TypedData = value; + get => Attributes.Indices.TypedData; + set => Attributes.Indices.TypedData = value; } } @@ -2734,43 +3082,43 @@ public void ReadAttributes(BFastNext bfast) // Named Attributes. - public Vim.G3dNext.Attributes.MeshInstanceTransformsAttribute MeshInstanceTransformsAttribute + public Vim.G3dNext.Attributes.MeshInstanceTransformsAttribute InstanceTransforms { get => Map.TryGetValue(Vim.G3dNext.Attributes.MeshInstanceTransformsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshInstanceTransformsAttribute : default; set => Map[Vim.G3dNext.Attributes.MeshInstanceTransformsAttribute.AttributeName] = value as IAttribute; } - public Vim.G3dNext.Attributes.MeshOpaqueSubmeshCountsAttribute MeshOpaqueSubmeshCountsAttribute + public Vim.G3dNext.Attributes.MeshOpaqueSubmeshCountsAttribute OpaqueSubmeshCounts { get => Map.TryGetValue(Vim.G3dNext.Attributes.MeshOpaqueSubmeshCountsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshOpaqueSubmeshCountsAttribute : default; set => Map[Vim.G3dNext.Attributes.MeshOpaqueSubmeshCountsAttribute.AttributeName] = value as IAttribute; } - public Vim.G3dNext.Attributes.MeshSubmeshIndexOffsetsAttribute MeshSubmeshIndexOffsetsAttribute + public Vim.G3dNext.Attributes.MeshSubmeshIndexOffsetsAttribute SubmeshIndexOffsets { get => Map.TryGetValue(Vim.G3dNext.Attributes.MeshSubmeshIndexOffsetsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshSubmeshIndexOffsetsAttribute : default; set => Map[Vim.G3dNext.Attributes.MeshSubmeshIndexOffsetsAttribute.AttributeName] = value as IAttribute; } - public Vim.G3dNext.Attributes.MeshSubmeshVertexOffsetsAttribute MeshSubmeshVertexOffsetsAttribute + public Vim.G3dNext.Attributes.MeshSubmeshVertexOffsetsAttribute SubmeshVertexOffsets { get => Map.TryGetValue(Vim.G3dNext.Attributes.MeshSubmeshVertexOffsetsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshSubmeshVertexOffsetsAttribute : default; set => Map[Vim.G3dNext.Attributes.MeshSubmeshVertexOffsetsAttribute.AttributeName] = value as IAttribute; } - public Vim.G3dNext.Attributes.MeshSubmeshMaterialsAttribute MeshSubmeshMaterialsAttribute + public Vim.G3dNext.Attributes.MeshSubmeshMaterialsAttribute SubmeshMaterials { get => Map.TryGetValue(Vim.G3dNext.Attributes.MeshSubmeshMaterialsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshSubmeshMaterialsAttribute : default; set => Map[Vim.G3dNext.Attributes.MeshSubmeshMaterialsAttribute.AttributeName] = value as IAttribute; } - public Vim.G3dNext.Attributes.MeshPositionsAttribute MeshPositionsAttribute + public Vim.G3dNext.Attributes.MeshPositionsAttribute Positions { get => Map.TryGetValue(Vim.G3dNext.Attributes.MeshPositionsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshPositionsAttribute : default; set => Map[Vim.G3dNext.Attributes.MeshPositionsAttribute.AttributeName] = value as IAttribute; } - public Vim.G3dNext.Attributes.MeshIndicesAttribute MeshIndicesAttribute + public Vim.G3dNext.Attributes.MeshIndicesAttribute Indices { get => Map.TryGetValue(Vim.G3dNext.Attributes.MeshIndicesAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshIndicesAttribute : default; set => Map[Vim.G3dNext.Attributes.MeshIndicesAttribute.AttributeName] = value as IAttribute; @@ -2780,26 +3128,33 @@ public Vim.G3dNext.Attributes.MeshIndicesAttribute MeshIndicesAttribute public IAttribute GetAttribute(Type attributeType) { - if (attributeType == typeof(Vim.G3dNext.Attributes.MeshInstanceTransformsAttribute)) - return MeshInstanceTransformsAttribute; - if (attributeType == typeof(Vim.G3dNext.Attributes.MeshOpaqueSubmeshCountsAttribute)) - return MeshOpaqueSubmeshCountsAttribute; + if (attributeType == typeof(Vim.G3dNext.Attributes.MeshInstanceTransformsAttribute)) + return InstanceTransforms; + + + if (attributeType == typeof(Vim.G3dNext.Attributes.MeshOpaqueSubmeshCountsAttribute)) + return OpaqueSubmeshCounts; + + + if (attributeType == typeof(Vim.G3dNext.Attributes.MeshSubmeshIndexOffsetsAttribute)) + return SubmeshIndexOffsets; + + + if (attributeType == typeof(Vim.G3dNext.Attributes.MeshSubmeshVertexOffsetsAttribute)) + return SubmeshVertexOffsets; + - if (attributeType == typeof(Vim.G3dNext.Attributes.MeshSubmeshIndexOffsetsAttribute)) - return MeshSubmeshIndexOffsetsAttribute; + if (attributeType == typeof(Vim.G3dNext.Attributes.MeshSubmeshMaterialsAttribute)) + return SubmeshMaterials; - if (attributeType == typeof(Vim.G3dNext.Attributes.MeshSubmeshVertexOffsetsAttribute)) - return MeshSubmeshVertexOffsetsAttribute; - if (attributeType == typeof(Vim.G3dNext.Attributes.MeshSubmeshMaterialsAttribute)) - return MeshSubmeshMaterialsAttribute; + if (attributeType == typeof(Vim.G3dNext.Attributes.MeshPositionsAttribute)) + return Positions; - if (attributeType == typeof(Vim.G3dNext.Attributes.MeshPositionsAttribute)) - return MeshPositionsAttribute; - if (attributeType == typeof(Vim.G3dNext.Attributes.MeshIndicesAttribute)) - return MeshIndicesAttribute; + if (attributeType == typeof(Vim.G3dNext.Attributes.MeshIndicesAttribute)) + return Indices; throw new ArgumentException("Type {attributeType.ToString()} is not supported."); } @@ -2862,10 +3217,10 @@ public void Validate() // Ensure all the indices are either -1 or within the bounds of the attributes they are indexing into. { - var maxIndex = GetAttribute(MeshSubmeshIndexOffsetsAttribute.IndexInto).Data.Length - 1; - for (var i = 0; i < MeshSubmeshIndexOffsetsAttribute.TypedData.Length; ++i) + var maxIndex = GetAttribute(SubmeshIndexOffsets.IndexInto).Data.Length - 1; + for (var i = 0; i < SubmeshIndexOffsets.TypedData.Length; ++i) { - var index = MeshSubmeshIndexOffsetsAttribute.TypedData[i]; + var index = SubmeshIndexOffsets.TypedData[i]; if (index == -1) continue; // no relation. @@ -2876,10 +3231,10 @@ public void Validate() } { - var maxIndex = GetAttribute(MeshSubmeshVertexOffsetsAttribute.IndexInto).Data.Length - 1; - for (var i = 0; i < MeshSubmeshVertexOffsetsAttribute.TypedData.Length; ++i) + var maxIndex = GetAttribute(SubmeshVertexOffsets.IndexInto).Data.Length - 1; + for (var i = 0; i < SubmeshVertexOffsets.TypedData.Length; ++i) { - var index = MeshSubmeshVertexOffsetsAttribute.TypedData[i]; + var index = SubmeshVertexOffsets.TypedData[i]; if (index == -1) continue; // no relation. @@ -2890,10 +3245,10 @@ public void Validate() } { - var maxIndex = GetAttribute(MeshSubmeshMaterialsAttribute.IndexInto).Data.Length - 1; - for (var i = 0; i < MeshSubmeshMaterialsAttribute.TypedData.Length; ++i) + var maxIndex = GetAttribute(SubmeshMaterials.IndexInto).Data.Length - 1; + for (var i = 0; i < SubmeshMaterials.TypedData.Length; ++i) { - var index = MeshSubmeshMaterialsAttribute.TypedData[i]; + var index = SubmeshMaterials.TypedData[i]; if (index == -1) continue; // no relation. @@ -2904,10 +3259,10 @@ public void Validate() } { - var maxIndex = GetAttribute(MeshIndicesAttribute.IndexInto).Data.Length - 1; - for (var i = 0; i < MeshIndicesAttribute.TypedData.Length; ++i) + var maxIndex = GetAttribute(Indices.IndexInto).Data.Length - 1; + for (var i = 0; i < Indices.TypedData.Length; ++i) { - var index = MeshIndicesAttribute.TypedData[i]; + var index = Indices.TypedData[i]; if (index == -1) continue; // no relation. diff --git a/src/cs/g3d/Vim.G3dNext.Attributes/G3dMesh.cs b/src/cs/g3d/Vim.G3dNext.Attributes/G3dMesh.cs index f2ab2244..b55553fc 100644 --- a/src/cs/g3d/Vim.G3dNext.Attributes/G3dMesh.cs +++ b/src/cs/g3d/Vim.G3dNext.Attributes/G3dMesh.cs @@ -7,6 +7,7 @@ public partial class G3dMesh { // Field doesn't get written but is useful in builing a Vimx. public int[] InstanceNodes; + public int Chunk; void ISetup.Setup() { diff --git a/src/cs/g3d/Vim.G3dNext.Attributes/G3dScene.cs b/src/cs/g3d/Vim.G3dNext.Attributes/G3dScene.cs index 769b7fff..1f0612e5 100644 --- a/src/cs/g3d/Vim.G3dNext.Attributes/G3dScene.cs +++ b/src/cs/g3d/Vim.G3dNext.Attributes/G3dScene.cs @@ -2,9 +2,10 @@ { public partial class G3dScene { + //public int GetChunksCount() => ChunksCount[0]; void ISetup.Setup() { // empty } } -} \ No newline at end of file +} diff --git a/src/cs/g3d/Vim.G3dNext.Attributes/MeshAttributes.cs b/src/cs/g3d/Vim.G3dNext.Attributes/MeshAttributes.cs index f52a69db..c0dd4a66 100644 --- a/src/cs/g3d/Vim.G3dNext.Attributes/MeshAttributes.cs +++ b/src/cs/g3d/Vim.G3dNext.Attributes/MeshAttributes.cs @@ -22,19 +22,19 @@ public partial class MeshInstanceTransformsAttribute { } [AttributeDescriptor("Mesh", "g3d:mesh:opaquesubmeshcount:0:int32:1", AttributeType.Data)] public partial class MeshOpaqueSubmeshCountsAttribute { } - [AttributeDescriptor("Mesh", "g3d:submesh:indexoffset:0:int32:1", AttributeType.Index, IndexInto = typeof(IndicesAttribute))] + [AttributeDescriptor("Mesh", "g3d:submesh:indexoffset:0:int32:1", AttributeType.Index, IndexInto = typeof(MeshIndicesAttribute))] public partial class MeshSubmeshIndexOffsetsAttribute { } - [AttributeDescriptor("Mesh", "g3d:submesh:vertexoffset:0:int32:1", AttributeType.Index, IndexInto = typeof(IndicesAttribute))] + [AttributeDescriptor("Mesh", "g3d:submesh:vertexoffset:0:int32:1", AttributeType.Index, IndexInto = typeof(MeshIndicesAttribute))] public partial class MeshSubmeshVertexOffsetsAttribute { } - [AttributeDescriptor("Mesh", "g3d:submesh:material:0:int32:1", AttributeType.Index, IndexInto = typeof(MaterialColorsAttribute))] + [AttributeDescriptor("Mesh", "g3d:submesh:material:0:int32:1", AttributeType.Index)] public partial class MeshSubmeshMaterialsAttribute { } [AttributeDescriptor("Mesh", "g3d:vertex:position:0:float32:3", AttributeType.Data, ArrayType = typeof(Vector3))] public partial class MeshPositionsAttribute { } - [AttributeDescriptor("Mesh", "g3d:corner:index:0:int32:1", AttributeType.Index, IndexInto = typeof(PositionsAttribute))] + [AttributeDescriptor("Mesh", "g3d:corner:index:0:int32:1", AttributeType.Index, IndexInto = typeof(MeshPositionsAttribute))] public partial class MeshIndicesAttribute { } } diff --git a/src/cs/g3d/Vim.G3dNext.Attributes/SceneAttributes.cs b/src/cs/g3d/Vim.G3dNext.Attributes/SceneAttributes.cs index 9a2c5245..c745c128 100644 --- a/src/cs/g3d/Vim.G3dNext.Attributes/SceneAttributes.cs +++ b/src/cs/g3d/Vim.G3dNext.Attributes/SceneAttributes.cs @@ -3,59 +3,69 @@ namespace Vim.G3dNext.Attributes { [AttributeCollection( - typeof(InstanceFilesAttribute), - typeof(InstanceIndicesAttribute), - typeof(InstanceNodesAttribute), - typeof(InstanceGroupsAttribute), - typeof(InstanceTagsAttribute), - typeof(InstanceFlagsAttribute), - typeof(InstanceMinsAttribute), - typeof(InstanceMaxsAttribute), - typeof(MeshInstanceCountsAttribute), - typeof(MeshIndexCountsAttribute), - typeof(MeshVertexCountsAttribute), - typeof(MeshOpaqueIndexCountsAttribute), - typeof(MeshOpaqueVertexCountsAttribute) + typeof(SceneChunkCountAttribute), + typeof(SceneInstanceMeshesAttribute), + typeof(SceneInstanceTransformsAttribute), + typeof(SceneInstanceNodesAttribute), + typeof(SceneInstanceGroupsAttribute), + typeof(SceneInstanceTagsAttribute), + typeof(SceneInstanceFlagsAttribute), + typeof(SceneInstanceMinsAttribute), + typeof(SceneInstanceMaxsAttribute), + typeof(SceneMeshChunksAttribute), + typeof(SceneMeshInstanceCountsAttribute), + typeof(SceneMeshIndexCountsAttribute), + typeof(SceneMeshVertexCountsAttribute), + typeof(SceneMeshOpaqueIndexCountsAttribute), + typeof(SceneMeshOpaqueVertexCountsAttribute) )] public partial class SceneAttributeCollection // : IAttributeCollection { } - [AttributeDescriptor("g3d:instance:file:0:int32:1", AttributeType.Data)] - public partial class InstanceFilesAttribute { } + [AttributeDescriptor("Scene", "g3d:chunk:count:0:int32:1", AttributeType.Data)] + public partial class SceneChunkCountAttribute { } - [AttributeDescriptor("g3d:instance:node:0:int32:1", AttributeType.Data)] - public partial class InstanceNodesAttribute { } + [AttributeDescriptor("Scene", "g3d:instance:mesh:0:int32:1", AttributeType.Data)] + public partial class SceneInstanceMeshesAttribute { } - [AttributeDescriptor("g3d:instance:index:0:int32:1", AttributeType.Data)] - public partial class InstanceIndicesAttribute { } + [AttributeDescriptor("Scene", "g3d:instance:transform:0:int32:1", AttributeType.Data)] + public partial class SceneInstanceTransformsAttribute { } - [AttributeDescriptor("g3d:instance:group:0:int32:1", AttributeType.Data)] - public partial class InstanceGroupsAttribute { } + [AttributeDescriptor("Scene", "g3d:instance:node:0:int32:1", AttributeType.Data)] + public partial class SceneInstanceNodesAttribute { } - [AttributeDescriptor("g3d:instance:tag:0:int64:1", AttributeType.Data)] - public partial class InstanceTagsAttribute { } + [AttributeDescriptor("Scene", "g3d:instance:group:0:int32:1", AttributeType.Data)] + public partial class SceneInstanceGroupsAttribute { } - [AttributeDescriptor("g3d:instance:min:0:float32:3", AttributeType.Data, ArrayType = typeof(Vector3))] - public partial class InstanceMinsAttribute { } + [AttributeDescriptor("Scene", "g3d:instance:tag:0:int64:1", AttributeType.Data)] + public partial class SceneInstanceTagsAttribute { } - [AttributeDescriptor("g3d:instance:max:0:float32:3", AttributeType.Data, ArrayType = typeof(Vector3))] - public partial class InstanceMaxsAttribute { } + [AttributeDescriptor("Scene", "g3d:instance:flags:0:uint16:1", AttributeType.Data)] + public partial class SceneInstanceFlagsAttribute { } - [AttributeDescriptor("g3d:mesh:instancecount:0:int32:1", AttributeType.Data)] - public partial class MeshInstanceCountsAttribute { } + [AttributeDescriptor("Scene", "g3d:instance:min:0:float32:3", AttributeType.Data, ArrayType = typeof(Vector3))] + public partial class SceneInstanceMinsAttribute { } - [AttributeDescriptor("g3d:mesh:vertexcount:0:int32:1", AttributeType.Data)] - public partial class MeshVertexCountsAttribute { } + [AttributeDescriptor("Scene", "g3d:instance:max:0:float32:3", AttributeType.Data, ArrayType = typeof(Vector3))] + public partial class SceneInstanceMaxsAttribute { } - [AttributeDescriptor("g3d:mesh:indexcount:0:int32:1", AttributeType.Data)] - public partial class MeshIndexCountsAttribute { } + [AttributeDescriptor("Scene", "g3d:mesh:chunk:0:int32:1", AttributeType.Data)] + public partial class SceneMeshChunksAttribute { } - [AttributeDescriptor("g3d:mesh:opaquevertexcount:0:int32:1", AttributeType.Data)] - public partial class MeshOpaqueVertexCountsAttribute { } + [AttributeDescriptor("Scene", "g3d:mesh:instancecount:0:int32:1", AttributeType.Data)] + public partial class SceneMeshInstanceCountsAttribute { } - [AttributeDescriptor("g3d:mesh:opaqueindexcount:0:int32:1", AttributeType.Data)] - public partial class MeshOpaqueIndexCountsAttribute { } + [AttributeDescriptor("Scene", "g3d:mesh:vertexcount:0:int32:1", AttributeType.Data)] + public partial class SceneMeshVertexCountsAttribute { } + [AttributeDescriptor("Scene", "g3d:mesh:indexcount:0:int32:1", AttributeType.Data)] + public partial class SceneMeshIndexCountsAttribute { } + + [AttributeDescriptor("Scene", "g3d:mesh:opaquevertexcount:0:int32:1", AttributeType.Data)] + public partial class SceneMeshOpaqueVertexCountsAttribute { } + + [AttributeDescriptor("Scene", "g3d:mesh:opaqueindexcount:0:int32:1", AttributeType.Data)] + public partial class SceneMeshOpaqueIndexCountsAttribute { } } diff --git a/src/cs/g3d/Vim.G3dNext.Attributes/VimAttributes.cs b/src/cs/g3d/Vim.G3dNext.Attributes/VimAttributes.cs index fc7cf186..95586801 100644 --- a/src/cs/g3d/Vim.G3dNext.Attributes/VimAttributes.cs +++ b/src/cs/g3d/Vim.G3dNext.Attributes/VimAttributes.cs @@ -3,64 +3,73 @@ namespace Vim.G3dNext.Attributes { [AttributeCollection( - typeof(PositionsAttribute), - typeof(IndicesAttribute), - typeof(InstanceTransformsAttribute), - typeof(InstanceParentsAttribute), - typeof(InstanceFlagsAttribute), - typeof(InstanceMeshesAttribute), - typeof(MeshSubmeshOffsetsAttribute), - typeof(SubmeshIndexOffsetsAttribute), - typeof(SubmeshMaterialsAttribute), - typeof(MaterialColorsAttribute), - typeof(MaterialGlossinessAttribute), - typeof(MaterialSmoothnessAttribute), - typeof(ShapeVerticesAttribute), - typeof(ShapeVertexOffsetsAttribute), - typeof(ShapeColorsAttribute), - typeof(ShapeWidthsAttribute) + typeof(VimPositionsAttribute), + typeof(VimIndicesAttribute), + typeof(VimInstanceTransformsAttribute), + typeof(VimInstanceParentsAttribute), + typeof(VimInstanceFlagsAttribute), + typeof(VimInstanceMeshesAttribute), + typeof(VimMeshSubmeshOffsetsAttribute), + typeof(VimSubmeshIndexOffsetsAttribute), + typeof(VimSubmeshMaterialsAttribute), + typeof(VimMaterialColorsAttribute), + typeof(VimMaterialGlossinessAttribute), + typeof(VimMaterialSmoothnessAttribute), + typeof(VimShapeVerticesAttribute), + typeof(VimShapeVertexOffsetsAttribute), + typeof(VimShapeColorsAttribute), + typeof(VimShapeWidthsAttribute) )] public partial class VimAttributeCollection // : IAttributeCollection { } - [AttributeDescriptor("g3d:vertex:position:0:float32:3", AttributeType.Data, ArrayType = typeof(Vector3))] - public partial class PositionsAttribute { } + [AttributeDescriptor("Vim", "g3d:vertex:position:0:float32:3", AttributeType.Data, ArrayType = typeof(Vector3))] + public partial class VimPositionsAttribute { } - [AttributeDescriptor("g3d:corner:index:0:int32:1", AttributeType.Index, IndexInto = typeof(PositionsAttribute))] - public partial class IndicesAttribute { } + [AttributeDescriptor("Vim", "g3d:corner:index:0:int32:1", AttributeType.Index, IndexInto = typeof(VimPositionsAttribute))] + public partial class VimIndicesAttribute { } - [AttributeDescriptor("g3d:instance:transform:0:float32:16", AttributeType.Data, ArrayType = typeof(Matrix4x4))] - public partial class InstanceTransformsAttribute { } + [AttributeDescriptor("Vim", "g3d:instance:transform:0:float32:16", AttributeType.Data, ArrayType = typeof(Matrix4x4))] + public partial class VimInstanceTransformsAttribute { } - [AttributeDescriptor("g3d:instance:parent:0:int32:1", AttributeType.Index, IndexInto = typeof(InstanceTransformsAttribute))] - public partial class InstanceParentsAttribute { } + [AttributeDescriptor("Vim", "g3d:instance:parent:0:int32:1", AttributeType.Index, IndexInto = typeof(VimInstanceTransformsAttribute))] + public partial class VimInstanceParentsAttribute { } - [AttributeDescriptor("g3d:instance:flags:0:uint16:1", AttributeType.Data)] - public partial class InstanceFlagsAttribute { } + [AttributeDescriptor("Vim", "g3d:instance:flags:0:uint16:1", AttributeType.Data)] + public partial class VimInstanceFlagsAttribute { } - [AttributeDescriptor("g3d:instance:mesh:0:int32:1", AttributeType.Index, IndexInto = typeof(MeshSubmeshOffsetsAttribute))] - public partial class InstanceMeshesAttribute { } + [AttributeDescriptor("Vim", "g3d:instance:mesh:0:int32:1", AttributeType.Index, IndexInto = typeof(VimMeshSubmeshOffsetsAttribute))] + public partial class VimInstanceMeshesAttribute { } - [AttributeDescriptor("g3d:mesh:submeshoffset:0:int32:1", AttributeType.Index, IndexInto = typeof(SubmeshIndexOffsetsAttribute))] - public partial class MeshSubmeshOffsetsAttribute { } + [AttributeDescriptor("Vim", "g3d:mesh:submeshoffset:0:int32:1", AttributeType.Index, IndexInto = typeof(VimSubmeshIndexOffsetsAttribute))] + public partial class VimMeshSubmeshOffsetsAttribute { } - [AttributeDescriptor("g3d:submesh:indexoffset:0:int32:1", AttributeType.Index, IndexInto = typeof(IndicesAttribute))] - public partial class SubmeshIndexOffsetsAttribute { } + [AttributeDescriptor("Vim", "g3d:submesh:indexoffset:0:int32:1", AttributeType.Index, IndexInto = typeof(VimIndicesAttribute))] + public partial class VimSubmeshIndexOffsetsAttribute { } - [AttributeDescriptor("g3d:submesh:material:0:int32:1", AttributeType.Index, IndexInto = typeof(MaterialColorsAttribute))] - public partial class SubmeshMaterialsAttribute { } + [AttributeDescriptor("Vim", "g3d:submesh:material:0:int32:1", AttributeType.Index, IndexInto = typeof(VimMaterialColorsAttribute))] + public partial class VimSubmeshMaterialsAttribute { } - [AttributeDescriptor("g3d:shapevertex:position:0:float32:3", AttributeType.Data, ArrayType = typeof(Vector3))] - public partial class ShapeVerticesAttribute { } + [AttributeDescriptor("Vim", "g3d:material:color:0:float32:4", AttributeType.Data, ArrayType = typeof(Vector4))] + public partial class VimMaterialColorsAttribute { } - [AttributeDescriptor("g3d:shape:vertexoffset:0:int32:1", AttributeType.Index, IndexInto = typeof(ShapeVerticesAttribute))] - public partial class ShapeVertexOffsetsAttribute { } + [AttributeDescriptor("Vim", "g3d:material:glossiness:0:float32:1", AttributeType.Data)] + public partial class VimMaterialGlossinessAttribute { } - [AttributeDescriptor("g3d:shape:color:0:float32:4", AttributeType.Data, ArrayType = typeof(Vector4))] - public partial class ShapeColorsAttribute { } + [AttributeDescriptor("Vim", "g3d:material:smoothness:0:float32:1", AttributeType.Data)] + public partial class VimMaterialSmoothnessAttribute { } - [AttributeDescriptor("g3d:shape:width:0:float32:1", AttributeType.Data)] - public partial class ShapeWidthsAttribute { } + [AttributeDescriptor("Vim", "g3d:shapevertex:position:0:float32:3", AttributeType.Data, ArrayType = typeof(Vector3))] + public partial class VimShapeVerticesAttribute { } + + [AttributeDescriptor("Vim", "g3d:shape:vertexoffset:0:int32:1", AttributeType.Index, IndexInto = typeof(VimShapeVerticesAttribute))] + public partial class VimShapeVertexOffsetsAttribute { } + + [AttributeDescriptor("Vim", "g3d:shape:color:0:float32:4", AttributeType.Data, ArrayType = typeof(Vector4))] + public partial class VimShapeColorsAttribute { } + + [AttributeDescriptor("Vim", "g3d:shape:width:0:float32:1", AttributeType.Data)] + public partial class VimShapeWidthsAttribute { } } diff --git a/src/cs/g3d/Vim.G3dNext.CodeGen/G3dAttributeCollectionGenerator.cs b/src/cs/g3d/Vim.G3dNext.CodeGen/G3dAttributeCollectionGenerator.cs index 0b95dbfa..492e0e52 100644 --- a/src/cs/g3d/Vim.G3dNext.CodeGen/G3dAttributeCollectionGenerator.cs +++ b/src/cs/g3d/Vim.G3dNext.CodeGen/G3dAttributeCollectionGenerator.cs @@ -15,7 +15,7 @@ public static void WriteDocument(string filePath) { var cb = new CodeBuilder(); - cb.AppendLine("// AUTO-GENERATED FILE, DO NOT MODIFY."); + cb.AppendLine("// AUTO-GENERATED FILE, DO NOT MODIFY WACKO3."); cb.AppendLine("// ReSharper disable All"); cb.AppendLine("using System;"); cb.AppendLine("using System.IO;"); @@ -181,12 +181,12 @@ public BFastNext ToBFast() { var attribute = c.GetCustomAttribute(); var typedDataType = attribute.GetTypedDataType(); - + var name = attribute.FormatClassName(c.Name); return $@" - public {typedDataType}[] {attribute.FormatClassName(c.Name)} + public {typedDataType}[] {attribute.FormatClassName(name)} {{ - get => Attributes.{c.Name}.TypedData; - set => Attributes.{c.Name}.TypedData = value; + get => Attributes.{name}.TypedData; + set => Attributes.{name}.TypedData = value; }}";})) } }} @@ -222,19 +222,31 @@ public void ReadAttributes(BFastNext bfast) }}; // Named Attributes. -{string.Join(Environment.NewLine, attributeClasses.Select(c => $@" - public {c} {c.Name} +{string.Join(Environment.NewLine, attributeClasses.Select(c => + { + var attribute = c.GetCustomAttribute(); + var name = attribute.FormatClassName(c.Name); + return $@" + public {c} {name} {{ get => Map.TryGetValue({c}.AttributeName, out var attr) ? attr as {c} : default; set => Map[{c}.AttributeName] = value as IAttribute; - }}"))} + }}"; + }) +)} /// public IAttribute GetAttribute(Type attributeType) {{ -{string.Join(Environment.NewLine, attributeClasses.Select(c => $@" - if (attributeType == typeof({c})) - return {c.Name};"))} +{string.Join(Environment.NewLine, attributeClasses.Select(c => { + var attribute = c.GetCustomAttribute(); + var name = attribute.FormatClassName(c.Name); + return $@" + + if (attributeType == typeof({c})) + return {name};"; + + }))} throw new ArgumentException(""Type {{attributeType.ToString()}} is not supported.""); }} @@ -285,6 +297,7 @@ public void Validate() { var ada = c.GetCustomAttribute(); var typedDataType = ada.GetTypedDataType(); + var name = ada.FormatClassName(c.Name); switch (ada.AttributeType) { @@ -294,10 +307,10 @@ public void Validate() case AttributeType.Index: return $@" {{ - var maxIndex = GetAttribute({c.Name}.IndexInto).Data.Length - 1; - for (var i = 0; i < {c.Name}.TypedData.Length; ++i) + var maxIndex = GetAttribute({name}.IndexInto).Data.Length - 1; + for (var i = 0; i < {name}.TypedData.Length; ++i) {{ - var index = {c.Name}.TypedData[i]; + var index = {name}.TypedData[i]; if (index == -1) continue; // no relation. diff --git a/src/cs/vim/Vim.Format.Vimx.Conversion/MeshesToScene.cs b/src/cs/vim/Vim.Format.Vimx.Conversion/MeshesToScene.cs index a86f18e6..c80f8460 100644 --- a/src/cs/vim/Vim.Format.Vimx.Conversion/MeshesToScene.cs +++ b/src/cs/vim/Vim.Format.Vimx.Conversion/MeshesToScene.cs @@ -10,9 +10,11 @@ namespace Vim.Format.VimxNS.Conversion { public static class MeshesToScene { - public static G3dScene CreateScene(G3dVim g3d, DocumentModel bim, G3dMesh[] meshes) + public static G3dScene CreateScene(G3dVim g3d, DocumentModel bim, VimxChunk[] chunks, G3dMesh[] meshes) { var scene = new G3dScene(); + //scene.ChunksCount = new int[1] { chunks.Length }; + var nodeElements = bim.NodeElementIndex.ToArray(); var nodeElementIds = nodeElements .Select(n => n < 0 || n > bim.ElementId.Count @@ -20,13 +22,14 @@ public static G3dScene CreateScene(G3dVim g3d, DocumentModel bim, G3dMesh[] mesh : bim.ElementId[n] ).ToArray(); - (scene.InstanceFiles, scene.InstanceIndices, scene.InstanceNodes) = meshes.GetInstanceFiles(); + (scene.InstanceMeshes, scene.InstanceTransforms, scene.InstanceNodes) = meshes.GetInstanceIds(); scene.InstanceGroups = scene.InstanceNodes.Select(n => nodeElements[n]).ToArray(); scene.InstanceTags = scene.InstanceNodes.Select(n => nodeElementIds[n]).ToArray(); - (scene.InstanceMins, scene.InstanceMaxs) = ComputeBoundingBoxes(meshes, scene.InstanceFiles, scene.InstanceIndices); + (scene.InstanceMins, scene.InstanceMaxs) = ComputeBoundingBoxes(meshes, scene.InstanceMeshes, scene.InstanceTransforms); scene.InstanceFlags = scene.InstanceNodes.Select(i => g3d.InstanceFlags[i]).ToArray(); // meshes + //scene.MeshChunk = new int[meshes.Length]; scene.MeshInstanceCounts = new int[meshes.Length]; scene.MeshIndexCounts = new int[meshes.Length]; scene.MeshVertexCounts = new int[meshes.Length]; @@ -36,6 +39,7 @@ public static G3dScene CreateScene(G3dVim g3d, DocumentModel bim, G3dMesh[] mesh for (var i = 0; i < meshes.Length; i++) { var mesh = meshes[i]; + //scene.MeshChunk[i] = mesh.Chunk; scene.MeshInstanceCounts[i] = mesh.GetInstanceCount(); scene.MeshIndexCounts[i] = mesh.GetIndexCount(); scene.MeshVertexCounts[i] = mesh.GetVertexCount(); @@ -72,9 +76,9 @@ private static (Vector3[] min, Vector3[] max) ComputeBoundingBoxes(G3dMesh[] mes return (instanceMins, instanceMaxs); } - private static (int[], int[], int[]) GetInstanceFiles(this G3dMesh[] meshes) + private static (int[], int[], int[]) GetInstanceIds(this G3dMesh[] meshes) { - var instanceFiles = new List(); + var instanceMeshes = new List(); var instanceIndices = new List(); var instanceNodes = new List(); @@ -84,12 +88,12 @@ private static (int[], int[], int[]) GetInstanceFiles(this G3dMesh[] meshes) var mesh = meshes[i]; for (var j = 0; j < mesh.InstanceNodes.Length; j++) { - instanceFiles.Add(i); + instanceMeshes.Add(i); instanceIndices.Add(j); instanceNodes.Add(mesh.InstanceNodes[j]); } } - return (instanceFiles.ToArray(), instanceIndices.ToArray(), instanceNodes.ToArray()); + return (instanceMeshes.ToArray(), instanceIndices.ToArray(), instanceNodes.ToArray()); } } } diff --git a/src/cs/vim/Vim.Format.Vimx.Conversion/VimxConverter.cs b/src/cs/vim/Vim.Format.Vimx.Conversion/VimxConverter.cs index 758893a1..a1e77ba4 100644 --- a/src/cs/vim/Vim.Format.Vimx.Conversion/VimxConverter.cs +++ b/src/cs/vim/Vim.Format.Vimx.Conversion/VimxConverter.cs @@ -4,6 +4,7 @@ using Vim.G3dNext.Attributes; using Vim.Format.ObjectModel; using Vim.G3dNext; +using System.Collections.Generic; namespace Vim.Format.VimxNS.Conversion { @@ -27,11 +28,27 @@ public static Vimx FromVim(G3dVim g3d, DocumentModel bim) .OrderByBim(bim) .ToArray(); - var scene = MeshesToScene.CreateScene(g3d, bim, meshes); + var chunks = meshes.SplitChunks(); + var scene = MeshesToScene.CreateScene(g3d, bim, chunks, meshes); + var materials = new G3dMaterials(g3d.ToBFast()); var header = VimxHeader.CreateDefault(); - return new Vimx(header, MetaHeader.Default, scene, materials, meshes); + return new Vimx(header, MetaHeader.Default, scene, materials, chunks); + } + + public static VimxChunk[] SplitChunks(this IEnumerable meshes) + { + var chunks = new List(); + var chunk = new VimxChunk(); + foreach (var mesh in meshes) + { + chunk.Meshes.Add(mesh); + mesh.Chunk = 0; + } + chunks.Add(chunk); + + return chunks.ToArray(); } } } diff --git a/src/cs/vim/Vim.Format.Vimx/Vim.Format.Vimx.csproj b/src/cs/vim/Vim.Format.Vimx/Vim.Format.Vimx.csproj index c008c5ea..7b01d77a 100644 --- a/src/cs/vim/Vim.Format.Vimx/Vim.Format.Vimx.csproj +++ b/src/cs/vim/Vim.Format.Vimx/Vim.Format.Vimx.csproj @@ -14,7 +14,6 @@ - diff --git a/src/cs/vim/Vim.Format.Vimx/Vimx.cs b/src/cs/vim/Vim.Format.Vimx/Vimx.cs index f90e4c2e..55b2dff4 100644 --- a/src/cs/vim/Vim.Format.Vimx/Vimx.cs +++ b/src/cs/vim/Vim.Format.Vimx/Vimx.cs @@ -12,6 +12,7 @@ public static class BufferNames public const string Scene = "scene"; public const string Materials = "materials"; public static string Mesh(int mesh) => $"mesh_{mesh}"; + public static string Chunk(int mesh) => $"chunk_{mesh}"; } public static class BufferCompression @@ -20,7 +21,8 @@ public static class BufferCompression public const bool Meta = false; public const bool Scene = true; public const bool Materials = true; - public const bool Meshes = true; + public const bool Meshes = false; + public const bool Chunks = true; } public class Vimx @@ -29,15 +31,15 @@ public class Vimx public readonly MetaHeader Meta; public readonly G3dScene Scene; public readonly G3dMaterials Materials; - public readonly G3dMesh[] Meshes; + public readonly VimxChunk[] Chunks; - public Vimx(VimxHeader header, MetaHeader meta, G3dScene scene, G3dMaterials materials, G3dMesh[] meshes) + public Vimx(VimxHeader header, MetaHeader meta, G3dScene scene, G3dMaterials materials, VimxChunk[] chunks) { Meta = meta; Header = header; Scene = scene; Materials = materials; - Meshes = meshes; + Chunks = chunks; } public Vimx(BFastNext bfast) @@ -52,9 +54,12 @@ public Vimx(BFastNext bfast) bfast.GetBFast(BufferNames.Materials, BufferCompression.Materials) ); - Meshes = Enumerable.Range(0, Scene.MeshIndexCounts.Length).Select(i => - new G3dMesh(bfast.GetBFast(BufferNames.Mesh(i), BufferCompression.Meshes)) - ).ToArray(); + /* + Chunks = Enumerable.Range(0, Scene.GetChunksCount()) + .Select(c => bfast.GetBFast(BufferNames.Chunk(c), BufferCompression.Chunks)) + .Select(b => new VimxChunk(b)) + .ToArray(); + */ } public static Vimx FromPath(string path) @@ -67,8 +72,10 @@ public BFastNext ToBFast() bfast.SetArray(BufferNames.Header, Header.ToBytes()); bfast.SetBFast(BufferNames.Scene, Scene.ToBFast(), BufferCompression.Scene); bfast.SetBFast(BufferNames.Materials, Materials.ToBFast(), BufferCompression.Materials); - bfast.SetBFast(BufferNames.Mesh, Meshes.Select(m => m.ToBFast()), BufferCompression.Meshes); + bfast.SetBFast(BufferNames.Chunk, Chunks.Select(c => c.ToBFast()), BufferCompression.Chunks); return bfast; } + + } } diff --git a/src/cs/vim/Vim.Format.Vimx/VimxChunk.cs b/src/cs/vim/Vim.Format.Vimx/VimxChunk.cs new file mode 100644 index 00000000..f769a791 --- /dev/null +++ b/src/cs/vim/Vim.Format.Vimx/VimxChunk.cs @@ -0,0 +1,34 @@ +using System.Collections.Generic; +using System.Linq; +using Vim.BFastNextNS; +using Vim.G3dNext.Attributes; + +namespace Vim.Format.VimxNS +{ + public class VimxChunk + { + public List Meshes = new List(); + + public VimxChunk() { } + public VimxChunk(List meshes) { Meshes = meshes; } + + public VimxChunk(BFastNext bfast) + { + Meshes = bfast.Entries + .Select(e => new G3dMesh(bfast.GetBFast(e))) + .ToList(); + } + + public BFastNext ToBFast() + { + var chunk = new BFastNext(); + chunk.SetBFast( + BufferNames.Mesh, + Meshes.Select(m => m.ToBFast()) + ); + return chunk; + } + + + } +} diff --git a/src/cs/vim/Vim.Vimx.Test/TestUtils.cs b/src/cs/vim/Vim.Vimx.Test/TestUtils.cs index 6d77f6a8..e3a6dcd0 100644 --- a/src/cs/vim/Vim.Vimx.Test/TestUtils.cs +++ b/src/cs/vim/Vim.Vimx.Test/TestUtils.cs @@ -97,23 +97,23 @@ private static long GetMemoryConsumption(Action action) public static VimAttributeCollection CreateTestG3d() { - var g3d = new VimAttributeCollection(); - - g3d.PositionsAttribute.TypedData = new Vector3[] { Vector3.Zero, Vector3.UnitX, Vector3.UnitY, Vector3.UnitZ }; - g3d.IndicesAttribute.TypedData = new int[] { 0, 1, 2, 0, 3, 2, 1, 3, 2 }; - g3d.SubmeshIndexOffsetsAttribute.TypedData = new int[] { 0, 3, 6 }; - g3d.SubmeshMaterialsAttribute.TypedData = new int[] { 0 }; - g3d.MeshSubmeshOffsetsAttribute.TypedData = new int[] { 0 }; - g3d.InstanceTransformsAttribute.TypedData = new Matrix4x4[] { Matrix4x4.Identity }; - g3d.InstanceMeshesAttribute.TypedData = new int[] { 0 }; - g3d.InstanceParentsAttribute.TypedData = new int[] { -1 }; - g3d.MaterialColorsAttribute.TypedData = new Vector4[] { new Vector4(0.25f, 0.5f, 0.75f, 1) }; - g3d.MaterialGlossinessAttribute.TypedData = new float[] { .95f }; - g3d.MaterialSmoothnessAttribute.TypedData = new float[] { .5f }; - - g3d.Validate(); - - return g3d; + var attributes = new VimAttributeCollection(); + + attributes.Positions.TypedData = new Vector3[] { Vector3.Zero, Vector3.UnitX, Vector3.UnitY, Vector3.UnitZ }; + attributes.Indices.TypedData = new int[] { 0, 1, 2, 0, 3, 2, 1, 3, 2 }; + attributes.SubmeshIndexOffsets.TypedData = new int[] { 0, 3, 6 }; + attributes.SubmeshMaterials.TypedData = new int[] { 0 }; + attributes.MeshSubmeshOffsets.TypedData = new int[] { 0 }; + attributes.InstanceTransforms.TypedData = new Matrix4x4[] { Matrix4x4.Identity }; + attributes.InstanceMeshes.TypedData = new int[] { 0 }; + attributes.InstanceParents.TypedData = new int[] { -1 }; + attributes.MaterialColors.TypedData = new Vector4[] { new Vector4(0.25f, 0.5f, 0.75f, 1) }; + attributes.MaterialGlossiness.TypedData = new float[] { .95f }; + attributes.MaterialSmoothness.TypedData = new float[] { .5f }; + + attributes.Validate(); + + return attributes; } } } diff --git a/src/cs/vim/Vim.Vimx.Test/VimG3dTests.cs b/src/cs/vim/Vim.Vimx.Test/VimG3dTests.cs index 13286724..79543c72 100644 --- a/src/cs/vim/Vim.Vimx.Test/VimG3dTests.cs +++ b/src/cs/vim/Vim.Vimx.Test/VimG3dTests.cs @@ -37,8 +37,8 @@ public static void Can_Read_Write_Triangle() var indices = new[] { 0, 1, 2 }; var g3d1 = new VimAttributeCollection(); - g3d1.PositionsAttribute.TypedData = vertices; - g3d1.IndicesAttribute.TypedData = indices; + g3d1.Positions.TypedData = vertices; + g3d1.Indices.TypedData = indices; var memoryStream = new MemoryStream(); g3d1.ToBFast().Write(memoryStream); @@ -48,13 +48,13 @@ public static void Can_Read_Write_Triangle() var g3d2 = new VimAttributeCollection(bfast); Assert.IsNotNull(g3d2); - Assert.AreEqual(3, g3d2.PositionsAttribute.Count); - Assert.AreEqual(3, g3d2.IndicesAttribute.Count); - Assert.AreEqual(0, g3d2.MeshSubmeshOffsetsAttribute.Count); - Assert.AreEqual(0, g3d2.InstanceTransformsAttribute.Count); + Assert.AreEqual(3, g3d2.Positions.Count); + Assert.AreEqual(3, g3d2.Indices.Count); + Assert.AreEqual(0, g3d2.MeshSubmeshOffsets.Count); + Assert.AreEqual(0, (object)g3d2.InstanceTransforms.Count); - Assert.AreEqual(vertices, g3d2.PositionsAttribute.TypedData); - Assert.AreEqual(indices, g3d2.IndicesAttribute.TypedData); + Assert.AreEqual(vertices, g3d2.Positions.TypedData); + Assert.AreEqual(indices, g3d2.Indices.TypedData); } [Test] @@ -122,63 +122,63 @@ public static void Can_Merge_two_g3d() Assert.NotNull(g3d); { - var merged = Enumerable.Repeat(g3d.PositionsAttribute.TypedData, 2).SelectMany(v => v).ToArray(); - Assert.AreEqual(merged, g3dResult.PositionsAttribute.TypedData); + var merged = Enumerable.Repeat(g3d.Positions.TypedData, 2).SelectMany(v => v).ToArray(); + Assert.AreEqual(merged, g3dResult.Positions.TypedData); } { - var tmp = g3d.IndicesAttribute.TypedData; - var merged = new[] { tmp, tmp.Select(i => i + g3d.PositionsAttribute.Count).ToArray() }.SelectMany(v => v).ToArray(); - Assert.AreEqual(merged, g3dResult.IndicesAttribute.TypedData); + var tmp = g3d.Indices.TypedData; + var merged = new[] { tmp, tmp.Select(i => i + g3d.Positions.Count).ToArray() }.SelectMany(v => v).ToArray(); + Assert.AreEqual(merged, g3dResult.Indices.TypedData); } { - var tmp = g3d.SubmeshIndexOffsetsAttribute.TypedData; - var merged = new[] { tmp, tmp.Select(i => i + g3d.IndicesAttribute.Count).ToArray() }.SelectMany(v => v).ToArray(); - Assert.AreEqual(merged, g3dResult.SubmeshIndexOffsetsAttribute.TypedData); + var tmp = g3d.SubmeshIndexOffsets.TypedData; + var merged = new[] { tmp, tmp.Select(i => i + g3d.Indices.Count).ToArray() }.SelectMany(v => v).ToArray(); + Assert.AreEqual(merged, g3dResult.SubmeshIndexOffsets.TypedData); } { - var tmp = g3d.SubmeshMaterialsAttribute.TypedData; - var merged = new[] { tmp, tmp.Select(i => i + g3d.MaterialColorsAttribute.Count).ToArray() }.SelectMany(v => v).ToArray(); - Assert.AreEqual(merged, g3dResult.SubmeshMaterialsAttribute.TypedData); + var tmp = g3d.SubmeshMaterials.TypedData; + var merged = new[] { tmp, tmp.Select(i => i + g3d.MaterialColors.Count).ToArray() }.SelectMany(v => v).ToArray(); + Assert.AreEqual(merged, g3dResult.SubmeshMaterials.TypedData); } { - var tmp = g3d.MeshSubmeshOffsetsAttribute.TypedData; - var merged = new[] { tmp, tmp.Select(i => i + g3d.SubmeshIndexOffsetsAttribute.Count).ToArray() }.SelectMany(v => v).ToArray(); - Assert.AreEqual(merged, g3dResult.MeshSubmeshOffsetsAttribute.TypedData); + var tmp = g3d.MeshSubmeshOffsets.TypedData; + var merged = new[] { tmp, tmp.Select(i => i + g3d.SubmeshIndexOffsets.Count).ToArray() }.SelectMany(v => v).ToArray(); + Assert.AreEqual(merged, g3dResult.MeshSubmeshOffsets.TypedData); } { - var merged = Enumerable.Repeat(g3d.InstanceTransformsAttribute.TypedData, 2).SelectMany(v => v).ToArray(); - Assert.AreEqual(merged, g3dResult.InstanceTransformsAttribute.TypedData); + var merged = Enumerable.Repeat(g3d.InstanceTransforms.TypedData, 2).SelectMany(v => v).ToArray(); + Assert.AreEqual((object)merged, (object)g3dResult.InstanceTransforms.TypedData); } { - var tmp = g3d.InstanceMeshesAttribute.TypedData; - var merged = new[] { tmp, tmp.Select(i => i + g3d.MeshSubmeshOffsetsAttribute.Count).ToArray() }.SelectMany(v => v).ToArray(); - Assert.AreEqual(merged, g3dResult.InstanceMeshesAttribute.TypedData); + var tmp = g3d.InstanceMeshes.TypedData; + var merged = new[] { tmp, tmp.Select(i => i + g3d.MeshSubmeshOffsets.Count).ToArray() }.SelectMany(v => v).ToArray(); + Assert.AreEqual(merged, g3dResult.InstanceMeshes.TypedData); } { - var merged = Enumerable.Repeat(g3d.InstanceParentsAttribute.TypedData, 2).SelectMany(v => v).ToArray(); - Assert.AreEqual(merged, g3dResult.InstanceParentsAttribute.TypedData); + var merged = Enumerable.Repeat(g3d.InstanceParents.TypedData, 2).SelectMany(v => v).ToArray(); + Assert.AreEqual(merged, g3dResult.InstanceParents.TypedData); } { - var merged = Enumerable.Repeat(g3d.MaterialColorsAttribute.TypedData, 2).SelectMany(v => v).ToArray(); - Assert.AreEqual(merged, g3dResult.MaterialColorsAttribute.TypedData); + var merged = Enumerable.Repeat(g3d.MaterialColors.TypedData, 2).SelectMany(v => v).ToArray(); + Assert.AreEqual(merged, g3dResult.MaterialColors.TypedData); } { - var merged = Enumerable.Repeat(g3d.MaterialGlossinessAttribute.TypedData, 2).SelectMany(v => v).ToArray(); - Assert.AreEqual(merged, g3dResult.MaterialGlossinessAttribute.TypedData); + var merged = Enumerable.Repeat(g3d.MaterialGlossiness.TypedData, 2).SelectMany(v => v).ToArray(); + Assert.AreEqual(merged, g3dResult.MaterialGlossiness.TypedData); } { - var merged = Enumerable.Repeat(g3d.MaterialSmoothnessAttribute.TypedData, 2).SelectMany(v => v).ToArray(); - Assert.AreEqual(merged, g3dResult.MaterialSmoothnessAttribute.TypedData); + var merged = Enumerable.Repeat(g3d.MaterialSmoothness.TypedData, 2).SelectMany(v => v).ToArray(); + Assert.AreEqual(merged, g3dResult.MaterialSmoothness.TypedData); } } } diff --git a/src/cs/vim/Vim.Vimx.Test/VimxActions.cs b/src/cs/vim/Vim.Vimx.Test/VimxActions.cs index 7b8a16cb..c85ea6b0 100644 --- a/src/cs/vim/Vim.Vimx.Test/VimxActions.cs +++ b/src/cs/vim/Vim.Vimx.Test/VimxActions.cs @@ -10,7 +10,7 @@ public static class VimxActions const string whiteleys = "_WHITELEYS-VIM-MAIN_detached.v1.2.42.vim"; - [Test] + [Test, Explicit] public static void ConvertVimToVimx() { var input = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); diff --git a/src/cs/vim/Vim.Vimx.Test/VimxTests.cs b/src/cs/vim/Vim.Vimx.Test/VimxTests.cs index 8211144b..aa5515f0 100644 --- a/src/cs/vim/Vim.Vimx.Test/VimxTests.cs +++ b/src/cs/vim/Vim.Vimx.Test/VimxTests.cs @@ -22,9 +22,9 @@ public static void Can_Convert_And_Read_Vimx() vimx.ToBFast().Write(output); var result = Vimx.FromPath(output); - Assert.AreEqual(vimx.Scene.InstanceFiles, result.Scene.InstanceFiles); + Assert.AreEqual(vimx.Scene.InstanceMeshes, result.Scene.InstanceMeshes); Assert.AreEqual(vimx.Materials.MaterialColors, result.Materials.MaterialColors); - Assert.AreEqual(vimx.Meshes.Length, result.Meshes.Length); + Assert.AreEqual(vimx.Chunks.Length, result.Chunks.Length); } From 0de6feb145c96551be45bb0a932e29a989ab1d21 Mon Sep 17 00:00:00 2001 From: simon Date: Wed, 4 Oct 2023 15:19:52 -0400 Subject: [PATCH 014/111] ts update to match vimx chunks --- src/ts/dist/bfast.d.ts | 3 +- src/ts/dist/bfast.js | 13 ++------ src/ts/dist/g3dScene.d.ts | 12 +++++--- src/ts/dist/g3dScene.js | 28 ++++++++++------- src/ts/dist/index.d.ts | 1 + src/ts/dist/index.js | 1 + src/ts/dist/remoteBuffer.js | 2 +- src/ts/dist/remoteVimx.d.ts | 21 ++++--------- src/ts/dist/remoteVimx.js | 52 ++++++++------------------------ src/ts/package-lock.json | 4 +-- src/ts/package.json | 2 +- src/ts/src/bfast.ts | 13 ++------ src/ts/src/g3dScene.ts | 45 +++++++++++++++++----------- src/ts/src/index.ts | 1 + src/ts/src/remoteBuffer.ts | 2 +- src/ts/src/remoteVimx.ts | 60 ++++++++----------------------------- src/ts/tests/helpers.ts | 9 +++--- 17 files changed, 100 insertions(+), 169 deletions(-) diff --git a/src/ts/dist/bfast.d.ts b/src/ts/dist/bfast.d.ts index a75624bf..fe93201f 100644 --- a/src/ts/dist/bfast.d.ts +++ b/src/ts/dist/bfast.d.ts @@ -61,8 +61,7 @@ export declare class BFast { * @param name buffer name */ getBfast(name: string): Promise; - getLocalBfast(name: string, unzip?: boolean): Promise; - getLocalBfastRaw(name: string, unzip?: boolean): Promise; + getLocalBfast(name: string, inflate?: boolean): Promise; /** * Returns the raw buffer associated with a name * This value is not cached. diff --git a/src/ts/dist/bfast.js b/src/ts/dist/bfast.js index e6457db5..4d6797e4 100644 --- a/src/ts/dist/bfast.js +++ b/src/ts/dist/bfast.js @@ -217,20 +217,11 @@ class BFast { } return request.get(); } - async getLocalBfast(name, unzip = false) { + async getLocalBfast(name, inflate = false) { let buffer = await this.getBuffer(name); if (!buffer) return undefined; - if (unzip) { - buffer = pako.inflate(buffer).buffer; - } - return new BFast(buffer, 0, name); - } - async getLocalBfastRaw(name, unzip = false) { - let buffer = await this.getBuffer(name); - if (!buffer) - return undefined; - if (unzip) { + if (inflate) { buffer = pako.inflateRaw(buffer).buffer; } return new BFast(buffer, 0, name); diff --git a/src/ts/dist/g3dScene.d.ts b/src/ts/dist/g3dScene.d.ts index b501fb8a..92e7ee4e 100644 --- a/src/ts/dist/g3dScene.d.ts +++ b/src/ts/dist/g3dScene.d.ts @@ -9,14 +9,16 @@ export declare type FilterMode = undefined | 'mesh' | 'instance' | 'group' | 'ta * See https://github.com/vimaec/vim#vim-geometry-attributes */ export declare class SceneAttributes { - static instanceFiles: string; - static instanceIndices: string; + static chunkCount: string; + static instanceMesh: string; + static instanceTransform: string; static instanceNodes: string; static instanceGroups: string; static instanceTags: string; static instanceFlags: string; static instanceMins: string; static instanceMaxs: string; + static meshChunk: string; static meshInstanceCounts: string; static meshIndexCounts: string; static meshVertexCounts: string; @@ -31,14 +33,16 @@ export declare class SceneAttributes { */ export declare class G3dScene { rawG3d: AbstractG3d; + chunksCount: number; instanceMeshes: Int32Array; - instanceIndices: Int32Array; + instanceTransforms: Int32Array; instanceNodes: Int32Array; instanceGroups: Int32Array; instanceTags: BigInt64Array; instanceFlags: Uint16Array; instanceMins: Float32Array; instanceMaxs: Float32Array; + meshChunks: Int32Array; meshInstanceCounts: Int32Array; meshIndexCounts: Int32Array; meshVertexCounts: Int32Array; @@ -46,7 +50,7 @@ export declare class G3dScene { meshOpaqueVertexCounts: Int32Array; private nodeToInstance; private meshSceneInstances; - constructor(rawG3d: AbstractG3d, instanceFiles: Int32Array, instanceIndices: Int32Array, instanceNodes: Int32Array, instanceGroups: Int32Array, instanceTags: BigInt64Array, instanceFlags: Uint16Array, instanceMins: Float32Array, instanceMaxs: Float32Array, meshInstanceCounts: Int32Array, meshIndexCounts: Int32Array, meshVertexCounts: Int32Array, meshOpaqueIndexCounts: Int32Array, meshOpaqueVertexCounts: Int32Array); + constructor(rawG3d: AbstractG3d, chunksCount: Int32Array, instanceMeshes: Int32Array, instanceTransform: Int32Array, instanceNodes: Int32Array, instanceGroups: Int32Array, instanceTags: BigInt64Array, instanceFlags: Uint16Array, instanceMins: Float32Array, instanceMaxs: Float32Array, meshChunks: Int32Array, meshInstanceCounts: Int32Array, meshIndexCounts: Int32Array, meshVertexCounts: Int32Array, meshOpaqueIndexCounts: Int32Array, meshOpaqueVertexCounts: Int32Array); private createMap; static createFromAbstract(g3d: AbstractG3d): G3dScene; static createFromPath(path: string): Promise; diff --git a/src/ts/dist/g3dScene.js b/src/ts/dist/g3dScene.js index 0a9a55b1..e95938ae 100644 --- a/src/ts/dist/g3dScene.js +++ b/src/ts/dist/g3dScene.js @@ -13,28 +13,32 @@ const g3d_1 = require("./g3d"); class SceneAttributes { } exports.SceneAttributes = SceneAttributes; -SceneAttributes.instanceFiles = 'g3d:instance:file:0:int32:1'; -SceneAttributes.instanceIndices = 'g3d:instance:index:0:int32:1'; +SceneAttributes.chunkCount = 'g3d:chunk:count:0:int32:1'; +SceneAttributes.instanceMesh = 'g3d:instance:mesh:0:int32:1'; +SceneAttributes.instanceTransform = 'g3d:instance:transform:0:int32:1'; SceneAttributes.instanceNodes = 'g3d:instance:node:0:int32:1'; SceneAttributes.instanceGroups = 'g3d:instance:group:0:int32:1'; SceneAttributes.instanceTags = 'g3d:instance:tag:0:int64:1'; SceneAttributes.instanceFlags = 'g3d:instance:tag:0:uint16:1'; SceneAttributes.instanceMins = 'g3d:instance:min:0:float32:3'; SceneAttributes.instanceMaxs = 'g3d:instance:max:0:float32:3'; +SceneAttributes.meshChunk = 'g3d:mesh:chunk:0:int32:1'; SceneAttributes.meshInstanceCounts = 'g3d:mesh:instancecount:0:int32:1'; SceneAttributes.meshIndexCounts = 'g3d:mesh:indexcount:0:int32:1'; SceneAttributes.meshVertexCounts = 'g3d:mesh:vertexcount:0:int32:1'; SceneAttributes.meshOpaqueIndexCount = "g3d:mesh:opaqueindexcount:0:int32:1"; SceneAttributes.meshOpaqueVertexCount = "g3d:mesh:opaquevertexcount:0:int32:1"; SceneAttributes.all = [ - SceneAttributes.instanceFiles, - SceneAttributes.instanceIndices, + SceneAttributes.chunkCount, + SceneAttributes.instanceMesh, + SceneAttributes.instanceTransform, SceneAttributes.instanceNodes, SceneAttributes.instanceGroups, SceneAttributes.instanceTags, SceneAttributes.instanceFlags, SceneAttributes.instanceMins, SceneAttributes.instanceMaxs, + SceneAttributes.meshChunk, SceneAttributes.meshInstanceCounts, SceneAttributes.meshIndexCounts, SceneAttributes.meshVertexCounts, @@ -47,16 +51,18 @@ SceneAttributes.all = [ * Allows to preallocate geometry to render G3dMeshes. */ class G3dScene { - constructor(rawG3d, instanceFiles, instanceIndices, instanceNodes, instanceGroups, instanceTags, instanceFlags, instanceMins, instanceMaxs, meshInstanceCounts, meshIndexCounts, meshVertexCounts, meshOpaqueIndexCounts, meshOpaqueVertexCounts) { + constructor(rawG3d, chunksCount, instanceMeshes, instanceTransform, instanceNodes, instanceGroups, instanceTags, instanceFlags, instanceMins, instanceMaxs, meshChunks, meshInstanceCounts, meshIndexCounts, meshVertexCounts, meshOpaqueIndexCounts, meshOpaqueVertexCounts) { this.rawG3d = rawG3d; - this.instanceMeshes = instanceFiles; - this.instanceIndices = instanceIndices; + this.chunksCount = chunksCount[0]; + this.instanceMeshes = instanceMeshes; + this.instanceTransforms = instanceTransform; this.instanceNodes = instanceNodes; this.instanceGroups = instanceGroups; this.instanceTags = instanceTags; this.instanceFlags = instanceFlags; this.instanceMins = instanceMins; this.instanceMaxs = instanceMaxs; + this.meshChunks = meshChunks; this.meshInstanceCounts = meshInstanceCounts; this.meshIndexCounts = meshIndexCounts; this.meshVertexCounts = meshVertexCounts; @@ -75,7 +81,7 @@ class G3dScene { const map = new Map(); for (let i = 0; i < this.instanceMeshes.length; i++) { const mesh = this.instanceMeshes[i]; - const index = this.instanceIndices[i]; + const index = this.instanceTransforms[i]; const indices = map.get(mesh) ?? new Map(); indices.set(index, i); map.set(mesh, indices); @@ -86,7 +92,7 @@ class G3dScene { function getArray(attribute) { return g3d.findAttribute(attribute)?.data; } - return new G3dScene(g3d, getArray(SceneAttributes.instanceFiles), getArray(SceneAttributes.instanceIndices), getArray(SceneAttributes.instanceNodes), getArray(SceneAttributes.instanceGroups), getArray(SceneAttributes.instanceTags), getArray(SceneAttributes.instanceFlags), getArray(SceneAttributes.instanceMins), getArray(SceneAttributes.instanceMaxs), getArray(SceneAttributes.meshInstanceCounts), getArray(SceneAttributes.meshIndexCounts), getArray(SceneAttributes.meshVertexCounts), getArray(SceneAttributes.meshOpaqueIndexCount), getArray(SceneAttributes.meshOpaqueVertexCount)); + return new G3dScene(g3d, getArray(SceneAttributes.instanceMesh), getArray(SceneAttributes.instanceMesh), getArray(SceneAttributes.instanceTransform), getArray(SceneAttributes.instanceNodes), getArray(SceneAttributes.instanceGroups), getArray(SceneAttributes.instanceTags), getArray(SceneAttributes.instanceFlags), getArray(SceneAttributes.instanceMins), getArray(SceneAttributes.instanceMaxs), getArray(SceneAttributes.meshChunk), getArray(SceneAttributes.meshInstanceCounts), getArray(SceneAttributes.meshIndexCounts), getArray(SceneAttributes.meshVertexCounts), getArray(SceneAttributes.meshOpaqueIndexCount), getArray(SceneAttributes.meshOpaqueVertexCount)); } static async createFromPath(path) { const f = await fetch(path); @@ -123,14 +129,14 @@ class G3dScene { } getNodeMin(node) { const instance = this.nodeToInstance.get(node); - if (!node) { + if (!instance) { return undefined; } return this.getInstanceMin(instance); } getNodeMax(node) { const instance = this.nodeToInstance.get(node); - if (!node) { + if (!instance) { return undefined; } return this.getInstanceMax(instance); diff --git a/src/ts/dist/index.d.ts b/src/ts/dist/index.d.ts index 8b034a7e..e3775c32 100644 --- a/src/ts/dist/index.d.ts +++ b/src/ts/dist/index.d.ts @@ -1,4 +1,5 @@ export * from './bfast'; +export * from './abstractG3d'; export * from './g3d'; export * from './remoteVimx'; export * from './g3dMaterials'; diff --git a/src/ts/dist/index.js b/src/ts/dist/index.js index 35a61b6b..a922c8ef 100644 --- a/src/ts/dist/index.js +++ b/src/ts/dist/index.js @@ -29,6 +29,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.VimHelpers = void 0; // Links files to generate package type exports __exportStar(require("./bfast"), exports); +__exportStar(require("./abstractG3d"), exports); __exportStar(require("./g3d"), exports); __exportStar(require("./remoteVimx"), exports); __exportStar(require("./g3dMaterials"), exports); diff --git a/src/ts/dist/remoteBuffer.js b/src/ts/dist/remoteBuffer.js index a477049c..13a9b1f2 100644 --- a/src/ts/dist/remoteBuffer.js +++ b/src/ts/dist/remoteBuffer.js @@ -21,7 +21,7 @@ class RetryRequest { this.responseType = responseType; } abort() { - this.xhr.abort(); + this.xhr?.abort(); } send() { this.xhr?.abort(); diff --git a/src/ts/dist/remoteVimx.d.ts b/src/ts/dist/remoteVimx.d.ts index a5c02aee..47b3169f 100644 --- a/src/ts/dist/remoteVimx.d.ts +++ b/src/ts/dist/remoteVimx.d.ts @@ -6,7 +6,6 @@ import { RemoteValue } from "./remoteValue"; export declare class RemoteVimx { bfast: BFast; scene: RemoteValue; - sceneRaw: RemoteValue; constructor(bfast: BFast); static fromPath(path: string): Promise; /** @@ -17,13 +16,11 @@ export declare class RemoteVimx { * Downloads underlying bfast making all subsequent request local. */ download(): Promise; + private requestScene; /** - * Fetches and returns the vimx G3dMeshIndex - */ - private requestIndex; - private requestIndexRaw; - getIndex(): Promise; - getIndexRaw(): Promise; + * Fetches and returns the vimx G3dScene + */ + getScene(): Promise; /** * Fetches and returns the vimx G3dMaterials */ @@ -31,13 +28,5 @@ export declare class RemoteVimx { /** * Fetches and returns the vimx G3dMesh with given index */ - getMesh(mesh: number): Promise; - /** - * Fetches and returns the vimx G3dMaterials - */ - getMaterialsRaw(): Promise; - /** - * Fetches and returns the vimx G3dMesh with given index - */ - getMeshRaw(mesh: number): Promise; + getChunk(chunk: number): Promise; } diff --git a/src/ts/dist/remoteVimx.js b/src/ts/dist/remoteVimx.js index c97299aa..2509600b 100644 --- a/src/ts/dist/remoteVimx.js +++ b/src/ts/dist/remoteVimx.js @@ -10,8 +10,7 @@ const remoteValue_1 = require("./remoteValue"); class RemoteVimx { constructor(bfast) { this.bfast = bfast; - this.scene = new remoteValue_1.RemoteValue(() => this.requestIndex()); - this.sceneRaw = new remoteValue_1.RemoteValue(() => this.requestIndexRaw()); + this.scene = new remoteValue_1.RemoteValue(() => this.requestScene()); } static async fromPath(path) { const buffer = new remoteBuffer_1.RemoteBuffer(path); @@ -30,23 +29,16 @@ class RemoteVimx { async download() { this.bfast.forceDownload(); } - /** - * Fetches and returns the vimx G3dMeshIndex - */ - async requestIndex() { + async requestScene() { const index = await this.bfast.getLocalBfast('scene', true); return g3dScene_1.G3dScene.createFromBfast(index); } - async requestIndexRaw() { - const index = await this.bfast.getLocalBfastRaw('scene', true); - return g3dScene_1.G3dScene.createFromBfast(index); - } - async getIndex() { + /** + * Fetches and returns the vimx G3dScene + */ + async getScene() { return this.scene.get(); } - async getIndexRaw() { - return this.sceneRaw.get(); - } /** * Fetches and returns the vimx G3dMaterials */ @@ -57,31 +49,13 @@ class RemoteVimx { /** * Fetches and returns the vimx G3dMesh with given index */ - async getMesh(mesh) { - const m = await this.bfast.getLocalBfast(`mesh_${mesh}`, true); - const result = await g3dMesh_1.G3dMesh.createFromBfast(m); - const scene = await this.scene.get(); - result.scene = scene; - result.meshIndex = mesh; - return result; - } - /** - * Fetches and returns the vimx G3dMaterials - */ - async getMaterialsRaw() { - const mat = await this.bfast.getLocalBfastRaw('materials', true); - return g3dMaterials_1.G3dMaterial.createFromBfast(mat); - } - /** - * Fetches and returns the vimx G3dMesh with given index - */ - async getMeshRaw(mesh) { - const m = await this.bfast.getLocalBfastRaw(`mesh_${mesh}`, true); - const result = await g3dMesh_1.G3dMesh.createFromBfast(m); - const scene = await this.sceneRaw.get(); - result.scene = scene; - result.meshIndex = mesh; - return result; + async getChunk(chunk) { + const chunkBFast = await this.bfast.getLocalBfast(`chunk_${chunk}`, true); + var ranges = await chunkBFast.getRanges(); + const keys = [...ranges.keys()]; + var bfasts = await Promise.all(keys.map(k => chunkBFast.getBfast(k))); + var meshes = await Promise.all(bfasts.map(b => g3dMesh_1.G3dMesh.createFromBfast(b))); + return meshes; } } exports.RemoteVimx = RemoteVimx; diff --git a/src/ts/package-lock.json b/src/ts/package-lock.json index dc644427..6befc896 100644 --- a/src/ts/package-lock.json +++ b/src/ts/package-lock.json @@ -1,12 +1,12 @@ { "name": "vim-format", - "version": "1.0.6-dev.100", + "version": "1.0.6-dev.138", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "vim-format", - "version": "1.0.6-dev.100", + "version": "1.0.6-dev.138", "license": "MIT", "dependencies": { "pako": "^2.1.0" diff --git a/src/ts/package.json b/src/ts/package.json index 05d4c942..75fe171f 100644 --- a/src/ts/package.json +++ b/src/ts/package.json @@ -1,6 +1,6 @@ { "name": "vim-format", - "version": "1.0.6-dev.138", + "version": "1.0.6-dev.201", "description": "The VIM format is a modern and efficient open 3D data interchange format designed for BIM and manufacturing data optimized for efficient loading and rendering on low-power devices.", "directories": { "test": "tests" diff --git a/src/ts/src/bfast.ts b/src/ts/src/bfast.ts index 059c7a44..7b78ab65 100644 --- a/src/ts/src/bfast.ts +++ b/src/ts/src/bfast.ts @@ -256,19 +256,10 @@ export function parseName(name: string): [number, NumericArrayConstructor]{ return request.get() } - async getLocalBfast (name: string, unzip: boolean = false): Promise { - let buffer = await this.getBuffer(name) - if (!buffer) return undefined - if(unzip){ - buffer = pako.inflate(buffer).buffer - } - return new BFast(buffer, 0, name) - } - - async getLocalBfastRaw (name: string, unzip: boolean = false): Promise { + async getLocalBfast (name: string, inflate: boolean = false): Promise { let buffer = await this.getBuffer(name) if (!buffer) return undefined - if(unzip){ + if(inflate){ buffer = pako.inflateRaw(buffer).buffer } return new BFast(buffer, 0, name) diff --git a/src/ts/src/g3dScene.ts b/src/ts/src/g3dScene.ts index 24b0cc60..b50a86a7 100644 --- a/src/ts/src/g3dScene.ts +++ b/src/ts/src/g3dScene.ts @@ -13,8 +13,9 @@ export type FilterMode = undefined | 'mesh' | 'instance' | 'group' | 'tag' */ export class SceneAttributes { - static instanceFiles = 'g3d:instance:file:0:int32:1' - static instanceIndices = 'g3d:instance:index:0:int32:1' + static chunkCount = 'g3d:chunk:count:0:int32:1' + static instanceMesh = 'g3d:instance:mesh:0:int32:1' + static instanceTransform = 'g3d:instance:transform:0:int32:1' static instanceNodes = 'g3d:instance:node:0:int32:1' static instanceGroups = 'g3d:instance:group:0:int32:1' static instanceTags = 'g3d:instance:tag:0:int64:1' @@ -22,6 +23,8 @@ export class SceneAttributes { static instanceMins = 'g3d:instance:min:0:float32:3' static instanceMaxs = 'g3d:instance:max:0:float32:3' + + static meshChunk = 'g3d:mesh:chunk:0:int32:1' static meshInstanceCounts = 'g3d:mesh:instancecount:0:int32:1' static meshIndexCounts = 'g3d:mesh:indexcount:0:int32:1' static meshVertexCounts = 'g3d:mesh:vertexcount:0:int32:1' @@ -30,8 +33,9 @@ export class SceneAttributes { static meshOpaqueVertexCount = "g3d:mesh:opaquevertexcount:0:int32:1" static all = [ - SceneAttributes.instanceFiles, - SceneAttributes.instanceIndices, + SceneAttributes.chunkCount, + SceneAttributes.instanceMesh, + SceneAttributes.instanceTransform, SceneAttributes.instanceNodes, SceneAttributes.instanceGroups, SceneAttributes.instanceTags, @@ -39,6 +43,7 @@ export class SceneAttributes { SceneAttributes.instanceMins, SceneAttributes.instanceMaxs, + SceneAttributes.meshChunk, SceneAttributes.meshInstanceCounts, SceneAttributes.meshIndexCounts, SceneAttributes.meshVertexCounts, @@ -56,8 +61,9 @@ export class SceneAttributes { export class G3dScene { rawG3d: AbstractG3d + chunkCount: number instanceMeshes: Int32Array - instanceIndices: Int32Array + instanceTransforms: Int32Array instanceNodes: Int32Array instanceGroups: Int32Array instanceTags : BigInt64Array @@ -65,6 +71,7 @@ export class G3dScene { instanceMins: Float32Array instanceMaxs: Float32Array + meshChunks : Int32Array meshInstanceCounts: Int32Array meshIndexCounts: Int32Array meshVertexCounts: Int32Array @@ -78,8 +85,9 @@ export class G3dScene { constructor( rawG3d: AbstractG3d, - instanceFiles: Int32Array, - instanceIndices: Int32Array, + chunkCount: Int32Array, + instanceMeshes: Int32Array, + instanceTransform: Int32Array, instanceNodes: Int32Array, instanceGroups: Int32Array, instanceTags: BigInt64Array, @@ -87,6 +95,7 @@ export class G3dScene { instanceMins: Float32Array, instanceMaxs: Float32Array, + meshChunks: Int32Array, meshInstanceCounts: Int32Array, meshIndexCounts : Int32Array, meshVertexCounts: Int32Array, @@ -97,8 +106,9 @@ export class G3dScene { this.rawG3d = rawG3d - this.instanceMeshes = instanceFiles - this.instanceIndices = instanceIndices + this.chunkCount = chunkCount[0] + this.instanceMeshes = instanceMeshes + this.instanceTransforms = instanceTransform this.instanceNodes = instanceNodes this.instanceGroups = instanceGroups this.instanceTags = instanceTags @@ -106,11 +116,10 @@ export class G3dScene { this.instanceMins = instanceMins this.instanceMaxs = instanceMaxs + this.meshChunks = meshChunks this.meshInstanceCounts = meshInstanceCounts - this.meshIndexCounts = meshIndexCounts this.meshVertexCounts = meshVertexCounts - this.meshOpaqueIndexCounts = meshOpaqueIndexCounts this.meshOpaqueVertexCounts = meshOpaqueVertexCounts @@ -128,7 +137,7 @@ export class G3dScene { const map = new Map>() for(let i =0; i < this.instanceMeshes.length; i++){ const mesh = this.instanceMeshes[i] - const index = this.instanceIndices[i] + const index = this.instanceTransforms[i] const indices = map.get(mesh) ?? new Map() indices.set(index, i) map.set(mesh, indices) @@ -146,8 +155,9 @@ export class G3dScene { return new G3dScene( g3d, - getArray(SceneAttributes.instanceFiles), - getArray(SceneAttributes.instanceIndices), + getArray(SceneAttributes.chunkCount), + getArray(SceneAttributes.instanceMesh), + getArray(SceneAttributes.instanceTransform), getArray(SceneAttributes.instanceNodes), getArray(SceneAttributes.instanceGroups), getArray(SceneAttributes.instanceTags), @@ -155,11 +165,10 @@ export class G3dScene { getArray(SceneAttributes.instanceMins), getArray(SceneAttributes.instanceMaxs), + getArray(SceneAttributes.meshChunk), getArray(SceneAttributes.meshInstanceCounts), - getArray(SceneAttributes.meshIndexCounts), getArray(SceneAttributes.meshVertexCounts), - getArray(SceneAttributes.meshOpaqueIndexCount), getArray(SceneAttributes.meshOpaqueVertexCount), ) @@ -205,7 +214,7 @@ export class G3dScene { getNodeMin(node: number){ const instance = this.nodeToInstance.get(node) - if(!node){ + if(!instance){ return undefined } return this.getInstanceMin(instance) @@ -213,7 +222,7 @@ export class G3dScene { getNodeMax(node: number){ const instance = this.nodeToInstance.get(node) - if(!node){ + if(!instance){ return undefined } return this.getInstanceMax(instance) diff --git a/src/ts/src/index.ts b/src/ts/src/index.ts index 19e62929..8309f425 100644 --- a/src/ts/src/index.ts +++ b/src/ts/src/index.ts @@ -1,5 +1,6 @@ // Links files to generate package type exports export * from './bfast' +export * from './abstractG3d' export * from './g3d' export * from './remoteVimx' export * from './g3dMaterials' diff --git a/src/ts/src/remoteBuffer.ts b/src/ts/src/remoteBuffer.ts index c350a235..3ef4ac61 100644 --- a/src/ts/src/remoteBuffer.ts +++ b/src/ts/src/remoteBuffer.ts @@ -37,7 +37,7 @@ export class RetryRequest { onProgress: ((e: ProgressEvent) => void) | undefined abort(){ - this.xhr.abort() + this.xhr?.abort() } send () { diff --git a/src/ts/src/remoteVimx.ts b/src/ts/src/remoteVimx.ts index 6770cea1..b2b39933 100644 --- a/src/ts/src/remoteVimx.ts +++ b/src/ts/src/remoteVimx.ts @@ -8,12 +8,10 @@ import { RemoteValue } from "./remoteValue"; export class RemoteVimx{ bfast : BFast scene : RemoteValue - sceneRaw : RemoteValue constructor(bfast : BFast){ this.bfast = bfast - this.scene = new RemoteValue(() => this.requestIndex()) - this.sceneRaw = new RemoteValue(() => this.requestIndexRaw()) + this.scene = new RemoteValue(() => this.requestScene()) } static async fromPath(path: string){ @@ -36,28 +34,18 @@ export class RemoteVimx{ this.bfast.forceDownload() } - /** - * Fetches and returns the vimx G3dMeshIndex - */ - private async requestIndex(){ + private async requestScene(){ const index = await this.bfast.getLocalBfast('scene', true) return G3dScene.createFromBfast(index) } - private async requestIndexRaw(){ - const index = await this.bfast.getLocalBfastRaw('scene', true) - return G3dScene.createFromBfast(index) - } - - async getIndex(){ + /** + * Fetches and returns the vimx G3dScene + */ + async getScene(){ return this.scene.get() } - async getIndexRaw(){ - return this.sceneRaw.get() - } - - /** * Fetches and returns the vimx G3dMaterials */ @@ -69,34 +57,12 @@ export class RemoteVimx{ /** * Fetches and returns the vimx G3dMesh with given index */ - async getMesh(mesh: number){ - const m = await this.bfast.getLocalBfast(`mesh_${mesh}`, true) - const result = await G3dMesh.createFromBfast(m) - const scene = await this.scene.get() - result.scene = scene - result.meshIndex = mesh - return result - } - - - /** - * Fetches and returns the vimx G3dMaterials - */ - async getMaterialsRaw(){ - const mat = await this.bfast.getLocalBfastRaw('materials', true) - return G3dMaterials.createFromBfast(mat) - } - - /** - * Fetches and returns the vimx G3dMesh with given index - */ - async getMeshRaw(mesh: number){ - const m = await this.bfast.getLocalBfastRaw(`mesh_${mesh}`, true) - const result = await G3dMesh.createFromBfast(m) - const scene = await this.sceneRaw.get() - result.scene = scene - result.meshIndex = mesh - return result + async getChunk(chunk: number){ + const chunkBFast = await this.bfast.getLocalBfast(`chunk_${chunk}`, true) + var ranges = await chunkBFast.getRanges() + const keys = [...ranges.keys()] + var bfasts = await Promise.all(keys.map(k => chunkBFast.getBfast(k))) + var meshes = await Promise.all(bfasts.map(b => G3dMesh.createFromBfast(b))) + return meshes } - } \ No newline at end of file diff --git a/src/ts/tests/helpers.ts b/src/ts/tests/helpers.ts index 9f456369..fce03983 100644 --- a/src/ts/tests/helpers.ts +++ b/src/ts/tests/helpers.ts @@ -1,13 +1,12 @@ import * as fs from 'fs' import { BFast } from '../src/bfast' -import { AbstractG3d, G3d } from '../src/g3d' +import { G3d, VimAttributes } from '../src/g3d' +import { AbstractG3d } from '../src/abstractG3d' import { RemoteG3d } from '../src/remoteG3d' export const testVimFilePath = `${__dirname}/../../../data/Wolford_Residence.r2023.om_v4.4.0.vim` -export function getFilterTestFile(instance : number){ - return 'tests/filter_'+instance+'.txt' -} + export function loadFile(path: string) { return new Promise((resolve, reject) => { @@ -48,7 +47,7 @@ export async function loadAbstract(vimFilePath: string){ const arrayBuffer = await loadFile(vimFilePath) const bfast = new BFast((arrayBuffer as ArrayBuffer)!) const g3dBfast = await bfast.getBfast('geometry') - const remote = await AbstractG3d.createFromBfast(g3dBfast!) + const remote = await AbstractG3d.createFromBfast(g3dBfast!, VimAttributes.all) return remote } From 0b27fe0a9aea0162fb3422eec392fcbc782df938 Mon Sep 17 00:00:00 2001 From: simon Date: Thu, 5 Oct 2023 16:21:42 -0400 Subject: [PATCH 015/111] added download parameter to Load --- .../vim/Vim.Format.CodeGen/ObjectModelTypeScriptGenerator.cs | 4 ++-- src/ts/src/objectModel.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/cs/vim/Vim.Format.CodeGen/ObjectModelTypeScriptGenerator.cs b/src/cs/vim/Vim.Format.CodeGen/ObjectModelTypeScriptGenerator.cs index fb7c39b6..97d9ba74 100644 --- a/src/cs/vim/Vim.Format.CodeGen/ObjectModelTypeScriptGenerator.cs +++ b/src/cs/vim/Vim.Format.CodeGen/ObjectModelTypeScriptGenerator.cs @@ -404,8 +404,8 @@ private static void WriteVimDocument(CodeBuilder cb, Type[] entityTypes) cb.AppendLine("}"); cb.AppendLine(); - cb.AppendLine("static async createFromBfast(bfast: BFast, ignoreStrings: boolean = false): Promise {"); - cb.AppendLine("const loaded = await VimLoader.loadFromBfast(bfast, ignoreStrings)"); + cb.AppendLine("static async createFromBfast(bfast: BFast, download:boolean, ignoreStrings: boolean = false): Promise {"); + cb.AppendLine("const loaded = await VimLoader.loadFromBfast(bfast, download, ignoreStrings)"); cb.AppendLine(); cb.AppendLine("if (loaded[0] === undefined)"); cb.AppendLine(" return undefined"); diff --git a/src/ts/src/objectModel.ts b/src/ts/src/objectModel.ts index cd8cdab0..3b573542 100644 --- a/src/ts/src/objectModel.ts +++ b/src/ts/src/objectModel.ts @@ -10124,8 +10124,8 @@ export class VimDocument { this.strings = strings } - static async createFromBfast(bfast: BFast, ignoreStrings: boolean = false): Promise { - const loaded = await VimLoader.loadFromBfast(bfast, ignoreStrings) + static async createFromBfast(bfast: BFast, download:boolean, ignoreStrings: boolean = false): Promise { + const loaded = await VimLoader.loadFromBfast(bfast, download, ignoreStrings) if (loaded[0] === undefined) return undefined From 2214d55beef12ca47a77edac627b5772e5f10739 Mon Sep 17 00:00:00 2001 From: simon Date: Tue, 10 Oct 2023 10:37:53 -0400 Subject: [PATCH 016/111] Implemented proper vimx chunks --- .../Vim.G3dNext.Attributes/Attributes.g.cs | 68 +++++++++++++++++++ src/cs/g3d/Vim.G3dNext.Attributes/G3dMesh.cs | 3 + src/cs/g3d/Vim.G3dNext.Attributes/G3dScene.cs | 2 +- .../Vim.G3dNext.Attributes/SceneAttributes.cs | 4 ++ .../MeshesToScene.cs | 8 ++- .../VimxConverter.cs | 19 +++++- src/cs/vim/Vim.Format.Vimx/Vimx.cs | 4 +- src/cs/vim/Vim.Vimx.Test/VimxActions.cs | 4 +- 8 files changed, 102 insertions(+), 10 deletions(-) diff --git a/src/cs/g3d/Vim.G3dNext.Attributes/Attributes.g.cs b/src/cs/g3d/Vim.G3dNext.Attributes/Attributes.g.cs index 8bb2af61..f5f066bb 100644 --- a/src/cs/g3d/Vim.G3dNext.Attributes/Attributes.g.cs +++ b/src/cs/g3d/Vim.G3dNext.Attributes/Attributes.g.cs @@ -1315,6 +1315,51 @@ public void Write(Stream stream) } } + public partial class SceneMeshChunkIndicesAttribute : IAttribute + { + public const string AttributeName = "g3d:mesh:chunkindex:0:int32:1"; + + public string Name + => AttributeName; + + public int Count => TypedData?.Length ?? 0; + + public void AddTo(BFastNext bfast) + { + if(TypedData != null) + { + bfast.SetArray(Name, TypedData); + } + } + + public void ReadBFast(BFastNext bfast) + { + TypedData = bfast.GetArray("g3d:mesh:chunkindex:0:int32:1"); + } + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Data; + + public Type IndexInto { get; } + = null; + + public System.Int32[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + public partial class SceneMeshInstanceCountsAttribute : IAttribute { public const string AttributeName = "g3d:mesh:instancecount:0:int32:1"; @@ -2638,6 +2683,12 @@ public System.Int32[] MeshChunks set => Attributes.MeshChunks.TypedData = value; } + public System.Int32[] MeshChunkIndices + { + get => Attributes.MeshChunkIndices.TypedData; + set => Attributes.MeshChunkIndices.TypedData = value; + } + public System.Int32[] MeshInstanceCounts { get => Attributes.MeshInstanceCounts.TypedData; @@ -2703,6 +2754,7 @@ public void ReadAttributes(BFastNext bfast) [Vim.G3dNext.Attributes.SceneInstanceMinsAttribute.AttributeName] = new Vim.G3dNext.Attributes.SceneInstanceMinsAttribute(), [Vim.G3dNext.Attributes.SceneInstanceMaxsAttribute.AttributeName] = new Vim.G3dNext.Attributes.SceneInstanceMaxsAttribute(), [Vim.G3dNext.Attributes.SceneMeshChunksAttribute.AttributeName] = new Vim.G3dNext.Attributes.SceneMeshChunksAttribute(), + [Vim.G3dNext.Attributes.SceneMeshChunkIndicesAttribute.AttributeName] = new Vim.G3dNext.Attributes.SceneMeshChunkIndicesAttribute(), [Vim.G3dNext.Attributes.SceneMeshInstanceCountsAttribute.AttributeName] = new Vim.G3dNext.Attributes.SceneMeshInstanceCountsAttribute(), [Vim.G3dNext.Attributes.SceneMeshIndexCountsAttribute.AttributeName] = new Vim.G3dNext.Attributes.SceneMeshIndexCountsAttribute(), [Vim.G3dNext.Attributes.SceneMeshVertexCountsAttribute.AttributeName] = new Vim.G3dNext.Attributes.SceneMeshVertexCountsAttribute(), @@ -2772,6 +2824,12 @@ public Vim.G3dNext.Attributes.SceneMeshChunksAttribute MeshChunks set => Map[Vim.G3dNext.Attributes.SceneMeshChunksAttribute.AttributeName] = value as IAttribute; } + public Vim.G3dNext.Attributes.SceneMeshChunkIndicesAttribute MeshChunkIndices + { + get => Map.TryGetValue(Vim.G3dNext.Attributes.SceneMeshChunkIndicesAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.SceneMeshChunkIndicesAttribute : default; + set => Map[Vim.G3dNext.Attributes.SceneMeshChunkIndicesAttribute.AttributeName] = value as IAttribute; + } + public Vim.G3dNext.Attributes.SceneMeshInstanceCountsAttribute MeshInstanceCounts { get => Map.TryGetValue(Vim.G3dNext.Attributes.SceneMeshInstanceCountsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.SceneMeshInstanceCountsAttribute : default; @@ -2847,6 +2905,10 @@ public IAttribute GetAttribute(Type attributeType) return MeshChunks; + if (attributeType == typeof(Vim.G3dNext.Attributes.SceneMeshChunkIndicesAttribute)) + return MeshChunkIndices; + + if (attributeType == typeof(Vim.G3dNext.Attributes.SceneMeshInstanceCountsAttribute)) return MeshInstanceCounts; @@ -2935,6 +2997,12 @@ public IAttribute MergeAttribute(string attributeName, IReadOnlyList().ToArray().MergeDataAttributes(); } + case Vim.G3dNext.Attributes.SceneMeshChunkIndicesAttribute.AttributeName: + { + // Data Attribute + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + } + case Vim.G3dNext.Attributes.SceneMeshInstanceCountsAttribute.AttributeName: { // Data Attribute diff --git a/src/cs/g3d/Vim.G3dNext.Attributes/G3dMesh.cs b/src/cs/g3d/Vim.G3dNext.Attributes/G3dMesh.cs index b55553fc..17c47424 100644 --- a/src/cs/g3d/Vim.G3dNext.Attributes/G3dMesh.cs +++ b/src/cs/g3d/Vim.G3dNext.Attributes/G3dMesh.cs @@ -8,6 +8,9 @@ public partial class G3dMesh // Field doesn't get written but is useful in builing a Vimx. public int[] InstanceNodes; public int Chunk; + public int ChunkIndex; + + public long GetSize() => Attributes.GetSize(); void ISetup.Setup() { diff --git a/src/cs/g3d/Vim.G3dNext.Attributes/G3dScene.cs b/src/cs/g3d/Vim.G3dNext.Attributes/G3dScene.cs index 1f0612e5..108ffeba 100644 --- a/src/cs/g3d/Vim.G3dNext.Attributes/G3dScene.cs +++ b/src/cs/g3d/Vim.G3dNext.Attributes/G3dScene.cs @@ -2,7 +2,7 @@ { public partial class G3dScene { - //public int GetChunksCount() => ChunksCount[0]; + public int GetChunksCount() => ChunkCount[0]; void ISetup.Setup() { // empty diff --git a/src/cs/g3d/Vim.G3dNext.Attributes/SceneAttributes.cs b/src/cs/g3d/Vim.G3dNext.Attributes/SceneAttributes.cs index c745c128..c2841bb3 100644 --- a/src/cs/g3d/Vim.G3dNext.Attributes/SceneAttributes.cs +++ b/src/cs/g3d/Vim.G3dNext.Attributes/SceneAttributes.cs @@ -13,6 +13,7 @@ namespace Vim.G3dNext.Attributes typeof(SceneInstanceMinsAttribute), typeof(SceneInstanceMaxsAttribute), typeof(SceneMeshChunksAttribute), + typeof(SceneMeshChunkIndicesAttribute), typeof(SceneMeshInstanceCountsAttribute), typeof(SceneMeshIndexCountsAttribute), typeof(SceneMeshVertexCountsAttribute), @@ -54,6 +55,9 @@ public partial class SceneInstanceMaxsAttribute { } [AttributeDescriptor("Scene", "g3d:mesh:chunk:0:int32:1", AttributeType.Data)] public partial class SceneMeshChunksAttribute { } + [AttributeDescriptor("Scene", "g3d:mesh:chunkindex:0:int32:1", AttributeType.Data)] + public partial class SceneMeshChunkIndicesAttribute { } + [AttributeDescriptor("Scene", "g3d:mesh:instancecount:0:int32:1", AttributeType.Data)] public partial class SceneMeshInstanceCountsAttribute { } diff --git a/src/cs/vim/Vim.Format.Vimx.Conversion/MeshesToScene.cs b/src/cs/vim/Vim.Format.Vimx.Conversion/MeshesToScene.cs index c80f8460..ab435bd1 100644 --- a/src/cs/vim/Vim.Format.Vimx.Conversion/MeshesToScene.cs +++ b/src/cs/vim/Vim.Format.Vimx.Conversion/MeshesToScene.cs @@ -13,7 +13,7 @@ public static class MeshesToScene public static G3dScene CreateScene(G3dVim g3d, DocumentModel bim, VimxChunk[] chunks, G3dMesh[] meshes) { var scene = new G3dScene(); - //scene.ChunksCount = new int[1] { chunks.Length }; + scene.ChunkCount = new int[1] { chunks.Length }; var nodeElements = bim.NodeElementIndex.ToArray(); var nodeElementIds = nodeElements @@ -29,7 +29,8 @@ public static G3dScene CreateScene(G3dVim g3d, DocumentModel bim, VimxChunk[] ch scene.InstanceFlags = scene.InstanceNodes.Select(i => g3d.InstanceFlags[i]).ToArray(); // meshes - //scene.MeshChunk = new int[meshes.Length]; + scene.MeshChunks = new int[meshes.Length]; + scene.MeshChunkIndices = new int[meshes.Length]; scene.MeshInstanceCounts = new int[meshes.Length]; scene.MeshIndexCounts = new int[meshes.Length]; scene.MeshVertexCounts = new int[meshes.Length]; @@ -39,7 +40,8 @@ public static G3dScene CreateScene(G3dVim g3d, DocumentModel bim, VimxChunk[] ch for (var i = 0; i < meshes.Length; i++) { var mesh = meshes[i]; - //scene.MeshChunk[i] = mesh.Chunk; + scene.MeshChunks[i] = mesh.Chunk; + scene.MeshChunkIndices[i] = mesh.ChunkIndex; scene.MeshInstanceCounts[i] = mesh.GetInstanceCount(); scene.MeshIndexCounts[i] = mesh.GetIndexCount(); scene.MeshVertexCounts[i] = mesh.GetVertexCount(); diff --git a/src/cs/vim/Vim.Format.Vimx.Conversion/VimxConverter.cs b/src/cs/vim/Vim.Format.Vimx.Conversion/VimxConverter.cs index a1e77ba4..e1525a06 100644 --- a/src/cs/vim/Vim.Format.Vimx.Conversion/VimxConverter.cs +++ b/src/cs/vim/Vim.Format.Vimx.Conversion/VimxConverter.cs @@ -39,14 +39,29 @@ public static Vimx FromVim(G3dVim g3d, DocumentModel bim) public static VimxChunk[] SplitChunks(this IEnumerable meshes) { + //2MB once compressed -> 0.5MB + const int ChunkSize = 2000000; + var chunks = new List(); var chunk = new VimxChunk(); + var chunkSize = 0L; foreach (var mesh in meshes) { + chunkSize += mesh.GetSize(); + if (chunkSize > ChunkSize && chunk.Meshes.Count > 0) + { + chunks.Add(chunk); + chunk = new VimxChunk(); + chunkSize = 0; + } + mesh.Chunk = chunks.Count; + mesh.ChunkIndex = chunk.Meshes.Count(); chunk.Meshes.Add(mesh); - mesh.Chunk = 0; } - chunks.Add(chunk); + if(chunk.Meshes.Count > 0) + { + chunks.Add(chunk); + } return chunks.ToArray(); } diff --git a/src/cs/vim/Vim.Format.Vimx/Vimx.cs b/src/cs/vim/Vim.Format.Vimx/Vimx.cs index 55b2dff4..fe02bd4b 100644 --- a/src/cs/vim/Vim.Format.Vimx/Vimx.cs +++ b/src/cs/vim/Vim.Format.Vimx/Vimx.cs @@ -54,12 +54,12 @@ public Vimx(BFastNext bfast) bfast.GetBFast(BufferNames.Materials, BufferCompression.Materials) ); - /* + Chunks = Enumerable.Range(0, Scene.GetChunksCount()) .Select(c => bfast.GetBFast(BufferNames.Chunk(c), BufferCompression.Chunks)) .Select(b => new VimxChunk(b)) .ToArray(); - */ + } public static Vimx FromPath(string path) diff --git a/src/cs/vim/Vim.Vimx.Test/VimxActions.cs b/src/cs/vim/Vim.Vimx.Test/VimxActions.cs index c85ea6b0..5c0ea74d 100644 --- a/src/cs/vim/Vim.Vimx.Test/VimxActions.cs +++ b/src/cs/vim/Vim.Vimx.Test/VimxActions.cs @@ -13,8 +13,8 @@ public static class VimxActions [Test, Explicit] public static void ConvertVimToVimx() { - var input = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); - //var input = Path.Join(VimFormatRepoPaths.DataDir, input); + //var input = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); + var input = Path.Join(VimFormatRepoPaths.DataDir, whiteleys); var name = Path.GetFileNameWithoutExtension(input); var output = Path.Combine(VimFormatRepoPaths.OutDir, name + ".vimx"); From aeb59269bb9b20cda146f45740ebf700bc73300e Mon Sep 17 00:00:00 2001 From: simon Date: Tue, 10 Oct 2023 10:39:57 -0400 Subject: [PATCH 017/111] Implemented chunks support for viewer. --- src/ts/dist/g3dScene.d.ts | 6 +- src/ts/dist/g3dScene.js | 9 +- src/ts/dist/objectModel.d.ts | 2 +- src/ts/dist/objectModel.js | 160 +++++++++++++++++++++++------------ src/ts/dist/remoteVimx.d.ts | 3 + src/ts/dist/remoteVimx.js | 19 +++++ src/ts/dist/vimHelpers.js | 8 +- src/ts/dist/vimLoader.d.ts | 2 +- src/ts/dist/vimLoader.js | 10 ++- src/ts/package.json | 2 +- src/ts/src/g3dScene.ts | 6 ++ src/ts/src/remoteVimx.ts | 21 +++++ src/ts/src/vimHelpers.ts | 8 +- src/ts/src/vimLoader.ts | 11 ++- 14 files changed, 192 insertions(+), 75 deletions(-) diff --git a/src/ts/dist/g3dScene.d.ts b/src/ts/dist/g3dScene.d.ts index 92e7ee4e..49fe9555 100644 --- a/src/ts/dist/g3dScene.d.ts +++ b/src/ts/dist/g3dScene.d.ts @@ -19,6 +19,7 @@ export declare class SceneAttributes { static instanceMins: string; static instanceMaxs: string; static meshChunk: string; + static meshChunkIndices: string; static meshInstanceCounts: string; static meshIndexCounts: string; static meshVertexCounts: string; @@ -33,7 +34,7 @@ export declare class SceneAttributes { */ export declare class G3dScene { rawG3d: AbstractG3d; - chunksCount: number; + chunkCount: number; instanceMeshes: Int32Array; instanceTransforms: Int32Array; instanceNodes: Int32Array; @@ -43,6 +44,7 @@ export declare class G3dScene { instanceMins: Float32Array; instanceMaxs: Float32Array; meshChunks: Int32Array; + meshChunkIndices: Int32Array; meshInstanceCounts: Int32Array; meshIndexCounts: Int32Array; meshVertexCounts: Int32Array; @@ -50,7 +52,7 @@ export declare class G3dScene { meshOpaqueVertexCounts: Int32Array; private nodeToInstance; private meshSceneInstances; - constructor(rawG3d: AbstractG3d, chunksCount: Int32Array, instanceMeshes: Int32Array, instanceTransform: Int32Array, instanceNodes: Int32Array, instanceGroups: Int32Array, instanceTags: BigInt64Array, instanceFlags: Uint16Array, instanceMins: Float32Array, instanceMaxs: Float32Array, meshChunks: Int32Array, meshInstanceCounts: Int32Array, meshIndexCounts: Int32Array, meshVertexCounts: Int32Array, meshOpaqueIndexCounts: Int32Array, meshOpaqueVertexCounts: Int32Array); + constructor(rawG3d: AbstractG3d, chunkCount: Int32Array, instanceMeshes: Int32Array, instanceTransform: Int32Array, instanceNodes: Int32Array, instanceGroups: Int32Array, instanceTags: BigInt64Array, instanceFlags: Uint16Array, instanceMins: Float32Array, instanceMaxs: Float32Array, meshChunks: Int32Array, meshChunkIndices: Int32Array, meshInstanceCounts: Int32Array, meshIndexCounts: Int32Array, meshVertexCounts: Int32Array, meshOpaqueIndexCounts: Int32Array, meshOpaqueVertexCounts: Int32Array); private createMap; static createFromAbstract(g3d: AbstractG3d): G3dScene; static createFromPath(path: string): Promise; diff --git a/src/ts/dist/g3dScene.js b/src/ts/dist/g3dScene.js index e95938ae..e66b0e35 100644 --- a/src/ts/dist/g3dScene.js +++ b/src/ts/dist/g3dScene.js @@ -23,6 +23,7 @@ SceneAttributes.instanceFlags = 'g3d:instance:tag:0:uint16:1'; SceneAttributes.instanceMins = 'g3d:instance:min:0:float32:3'; SceneAttributes.instanceMaxs = 'g3d:instance:max:0:float32:3'; SceneAttributes.meshChunk = 'g3d:mesh:chunk:0:int32:1'; +SceneAttributes.meshChunkIndices = 'g3d:mesh:chunkindex:0:int32:1'; SceneAttributes.meshInstanceCounts = 'g3d:mesh:instancecount:0:int32:1'; SceneAttributes.meshIndexCounts = 'g3d:mesh:indexcount:0:int32:1'; SceneAttributes.meshVertexCounts = 'g3d:mesh:vertexcount:0:int32:1'; @@ -39,6 +40,7 @@ SceneAttributes.all = [ SceneAttributes.instanceMins, SceneAttributes.instanceMaxs, SceneAttributes.meshChunk, + SceneAttributes.meshChunkIndices, SceneAttributes.meshInstanceCounts, SceneAttributes.meshIndexCounts, SceneAttributes.meshVertexCounts, @@ -51,9 +53,9 @@ SceneAttributes.all = [ * Allows to preallocate geometry to render G3dMeshes. */ class G3dScene { - constructor(rawG3d, chunksCount, instanceMeshes, instanceTransform, instanceNodes, instanceGroups, instanceTags, instanceFlags, instanceMins, instanceMaxs, meshChunks, meshInstanceCounts, meshIndexCounts, meshVertexCounts, meshOpaqueIndexCounts, meshOpaqueVertexCounts) { + constructor(rawG3d, chunkCount, instanceMeshes, instanceTransform, instanceNodes, instanceGroups, instanceTags, instanceFlags, instanceMins, instanceMaxs, meshChunks, meshChunkIndices, meshInstanceCounts, meshIndexCounts, meshVertexCounts, meshOpaqueIndexCounts, meshOpaqueVertexCounts) { this.rawG3d = rawG3d; - this.chunksCount = chunksCount[0]; + this.chunkCount = chunkCount[0]; this.instanceMeshes = instanceMeshes; this.instanceTransforms = instanceTransform; this.instanceNodes = instanceNodes; @@ -63,6 +65,7 @@ class G3dScene { this.instanceMins = instanceMins; this.instanceMaxs = instanceMaxs; this.meshChunks = meshChunks; + this.meshChunkIndices = meshChunkIndices; this.meshInstanceCounts = meshInstanceCounts; this.meshIndexCounts = meshIndexCounts; this.meshVertexCounts = meshVertexCounts; @@ -92,7 +95,7 @@ class G3dScene { function getArray(attribute) { return g3d.findAttribute(attribute)?.data; } - return new G3dScene(g3d, getArray(SceneAttributes.instanceMesh), getArray(SceneAttributes.instanceMesh), getArray(SceneAttributes.instanceTransform), getArray(SceneAttributes.instanceNodes), getArray(SceneAttributes.instanceGroups), getArray(SceneAttributes.instanceTags), getArray(SceneAttributes.instanceFlags), getArray(SceneAttributes.instanceMins), getArray(SceneAttributes.instanceMaxs), getArray(SceneAttributes.meshChunk), getArray(SceneAttributes.meshInstanceCounts), getArray(SceneAttributes.meshIndexCounts), getArray(SceneAttributes.meshVertexCounts), getArray(SceneAttributes.meshOpaqueIndexCount), getArray(SceneAttributes.meshOpaqueVertexCount)); + return new G3dScene(g3d, getArray(SceneAttributes.chunkCount), getArray(SceneAttributes.instanceMesh), getArray(SceneAttributes.instanceTransform), getArray(SceneAttributes.instanceNodes), getArray(SceneAttributes.instanceGroups), getArray(SceneAttributes.instanceTags), getArray(SceneAttributes.instanceFlags), getArray(SceneAttributes.instanceMins), getArray(SceneAttributes.instanceMaxs), getArray(SceneAttributes.meshChunk), getArray(SceneAttributes.meshChunkIndices), getArray(SceneAttributes.meshInstanceCounts), getArray(SceneAttributes.meshIndexCounts), getArray(SceneAttributes.meshVertexCounts), getArray(SceneAttributes.meshOpaqueIndexCount), getArray(SceneAttributes.meshOpaqueVertexCount)); } static async createFromPath(path) { const f = await fetch(path); diff --git a/src/ts/dist/objectModel.d.ts b/src/ts/dist/objectModel.d.ts index 73c72add..29ffa83b 100644 --- a/src/ts/dist/objectModel.d.ts +++ b/src/ts/dist/objectModel.d.ts @@ -3352,5 +3352,5 @@ export declare class VimDocument { entities: BFast; strings: string[] | undefined; private constructor(); - static createFromBfast(bfast: BFast, ignoreStrings?: boolean): Promise; + static createFromBfast(bfast: BFast, download: boolean, ignoreStrings?: boolean): Promise; } diff --git a/src/ts/dist/objectModel.js b/src/ts/dist/objectModel.js index 8f1cbbe4..c691d974 100644 --- a/src/ts/dist/objectModel.js +++ b/src/ts/dist/objectModel.js @@ -39,7 +39,8 @@ class AssetTable { (async () => { bufferName = (await localTable.getStringArray("string:BufferName")); })(), ]); let asset = []; - for (let i = 0; i < bufferName.length; i++) { + const rowCount = await this.getCount(); + for (let i = 0; i < rowCount; i++) { asset.push({ index: i, bufferName: bufferName ? bufferName[i] : undefined @@ -95,7 +96,8 @@ class DisplayUnitTable { (async () => { label = (await localTable.getStringArray("string:Label")); })(), ]); let displayUnit = []; - for (let i = 0; i < spec.length; i++) { + const rowCount = await this.getCount(); + for (let i = 0; i < rowCount; i++) { displayUnit.push({ index: i, spec: spec ? spec[i] : undefined, @@ -184,7 +186,8 @@ class ParameterDescriptorTable { (async () => { displayUnitIndex = (await localTable.getNumberArray("index:Vim.DisplayUnit:DisplayUnit")); })(), ]); let parameterDescriptor = []; - for (let i = 0; i < name.length; i++) { + const rowCount = await this.getCount(); + for (let i = 0; i < rowCount; i++) { parameterDescriptor.push({ index: i, name: name ? name[i] : undefined, @@ -304,7 +307,8 @@ class ParameterTable { (async () => { elementIndex = (await localTable.getNumberArray("index:Vim.Element:Element")); })(), ]); let parameter = []; - for (let i = 0; i < value.length; i++) { + const rowCount = await this.getCount(); + for (let i = 0; i < rowCount; i++) { parameter.push({ index: i, value: value ? value[i] : undefined, @@ -440,7 +444,8 @@ class ElementTable { (async () => { roomIndex = (await localTable.getNumberArray("index:Vim.Room:Room")); })(), ]); let element = []; - for (let i = 0; i < id.length; i++) { + const rowCount = await this.getCount(); + for (let i = 0; i < rowCount; i++) { element.push({ index: i, id: id ? id[i] : undefined, @@ -722,7 +727,8 @@ class WorksetTable { (async () => { bimDocumentIndex = (await localTable.getNumberArray("index:Vim.BimDocument:BimDocument")); })(), ]); let workset = []; - for (let i = 0; i < id.length; i++) { + const rowCount = await this.getCount(); + for (let i = 0; i < rowCount; i++) { workset.push({ index: i, id: id ? id[i] : undefined, @@ -841,7 +847,8 @@ class AssemblyInstanceTable { (async () => { elementIndex = (await localTable.getNumberArray("index:Vim.Element:Element")); })(), ]); let assemblyInstance = []; - for (let i = 0; i < assemblyTypeName.length; i++) { + const rowCount = await this.getCount(); + for (let i = 0; i < rowCount; i++) { assemblyInstance.push({ index: i, assemblyTypeName: assemblyTypeName ? assemblyTypeName[i] : undefined, @@ -939,7 +946,8 @@ class GroupTable { (async () => { elementIndex = (await localTable.getNumberArray("index:Vim.Element:Element")); })(), ]); let group = []; - for (let i = 0; i < groupType.length; i++) { + const rowCount = await this.getCount(); + for (let i = 0; i < rowCount; i++) { group.push({ index: i, groupType: groupType ? groupType[i] : undefined, @@ -1028,7 +1036,8 @@ class DesignOptionTable { (async () => { elementIndex = (await localTable.getNumberArray("index:Vim.Element:Element")); })(), ]); let designOption = []; - for (let i = 0; i < isPrimary.length; i++) { + const rowCount = await this.getCount(); + for (let i = 0; i < rowCount; i++) { designOption.push({ index: i, isPrimary: isPrimary ? isPrimary[i] : undefined, @@ -1099,7 +1108,8 @@ class LevelTable { (async () => { elementIndex = (await localTable.getNumberArray("index:Vim.Element:Element")); })(), ]); let level = []; - for (let i = 0; i < elevation.length; i++) { + const rowCount = await this.getCount(); + for (let i = 0; i < rowCount; i++) { level.push({ index: i, elevation: elevation ? elevation[i] : undefined, @@ -1178,7 +1188,8 @@ class PhaseTable { (async () => { elementIndex = (await localTable.getNumberArray("index:Vim.Element:Element")); })(), ]); let phase = []; - for (let i = 0; i < elementIndex.length; i++) { + const rowCount = await this.getCount(); + for (let i = 0; i < rowCount; i++) { phase.push({ index: i, elementIndex: elementIndex ? elementIndex[i] : undefined @@ -1260,7 +1271,8 @@ class RoomTable { (async () => { elementIndex = (await localTable.getNumberArray("index:Vim.Element:Element")); })(), ]); let room = []; - for (let i = 0; i < baseOffset.length; i++) { + const rowCount = await this.getCount(); + for (let i = 0; i < rowCount; i++) { room.push({ index: i, baseOffset: baseOffset ? baseOffset[i] : undefined, @@ -1474,7 +1486,8 @@ class BimDocumentTable { (async () => { elementIndex = (await localTable.getNumberArray("index:Vim.Element:Element")); })(), ]); let bimDocument = []; - for (let i = 0; i < title.length; i++) { + const rowCount = await this.getCount(); + for (let i = 0; i < rowCount; i++) { bimDocument.push({ index: i, title: title ? title[i] : undefined, @@ -1773,7 +1786,8 @@ class DisplayUnitInBimDocumentTable { (async () => { bimDocumentIndex = (await localTable.getNumberArray("index:Vim.BimDocument:BimDocument")); })(), ]); let displayUnitInBimDocument = []; - for (let i = 0; i < displayUnitIndex.length; i++) { + const rowCount = await this.getCount(); + for (let i = 0; i < rowCount; i++) { displayUnitInBimDocument.push({ index: i, displayUnitIndex: displayUnitIndex ? displayUnitIndex[i] : undefined, @@ -1851,7 +1865,8 @@ class PhaseOrderInBimDocumentTable { (async () => { bimDocumentIndex = (await localTable.getNumberArray("index:Vim.BimDocument:BimDocument")); })(), ]); let phaseOrderInBimDocument = []; - for (let i = 0; i < orderIndex.length; i++) { + const rowCount = await this.getCount(); + for (let i = 0; i < rowCount; i++) { phaseOrderInBimDocument.push({ index: i, orderIndex: orderIndex ? orderIndex[i] : undefined, @@ -1954,7 +1969,8 @@ class CategoryTable { (async () => { materialIndex = (await localTable.getNumberArray("index:Vim.Material:Material")); })(), ]); let category = []; - for (let i = 0; i < name.length; i++) { + const rowCount = await this.getCount(); + for (let i = 0; i < rowCount; i++) { category.push({ index: i, name: name ? name[i] : undefined, @@ -2090,7 +2106,8 @@ class FamilyTable { (async () => { elementIndex = (await localTable.getNumberArray("index:Vim.Element:Element")); })(), ]); let family = []; - for (let i = 0; i < structuralMaterialType.length; i++) { + const rowCount = await this.getCount(); + for (let i = 0; i < rowCount; i++) { family.push({ index: i, structuralMaterialType: structuralMaterialType ? structuralMaterialType[i] : undefined, @@ -2199,7 +2216,8 @@ class FamilyTypeTable { (async () => { elementIndex = (await localTable.getNumberArray("index:Vim.Element:Element")); })(), ]); let familyType = []; - for (let i = 0; i < isSystemFamilyType.length; i++) { + const rowCount = await this.getCount(); + for (let i = 0; i < rowCount; i++) { familyType.push({ index: i, isSystemFamilyType: isSystemFamilyType ? isSystemFamilyType[i] : undefined, @@ -2373,7 +2391,8 @@ class FamilyInstanceTable { (async () => { elementIndex = (await localTable.getNumberArray("index:Vim.Element:Element")); })(), ]); let familyInstance = []; - for (let i = 0; i < facingFlipped.length; i++) { + const rowCount = await this.getCount(); + for (let i = 0; i < rowCount; i++) { familyInstance.push({ index: i, facingFlipped: facingFlipped ? facingFlipped[i] : undefined, @@ -2723,7 +2742,8 @@ class ViewTable { (async () => { elementIndex = (await localTable.getNumberArray("index:Vim.Element:Element")); })(), ]); let view = []; - for (let i = 0; i < title.length; i++) { + const rowCount = await this.getCount(); + for (let i = 0; i < rowCount; i++) { view.push({ index: i, title: title ? title[i] : undefined, @@ -2973,7 +2993,8 @@ class ElementInViewTable { (async () => { elementIndex = (await localTable.getNumberArray("index:Vim.Element:Element")); })(), ]); let elementInView = []; - for (let i = 0; i < viewIndex.length; i++) { + const rowCount = await this.getCount(); + for (let i = 0; i < rowCount; i++) { elementInView.push({ index: i, viewIndex: viewIndex ? viewIndex[i] : undefined, @@ -3048,7 +3069,8 @@ class ShapeInViewTable { (async () => { viewIndex = (await localTable.getNumberArray("index:Vim.View:View")); })(), ]); let shapeInView = []; - for (let i = 0; i < shapeIndex.length; i++) { + const rowCount = await this.getCount(); + for (let i = 0; i < rowCount; i++) { shapeInView.push({ index: i, shapeIndex: shapeIndex ? shapeIndex[i] : undefined, @@ -3123,7 +3145,8 @@ class AssetInViewTable { (async () => { viewIndex = (await localTable.getNumberArray("index:Vim.View:View")); })(), ]); let assetInView = []; - for (let i = 0; i < assetIndex.length; i++) { + const rowCount = await this.getCount(); + for (let i = 0; i < rowCount; i++) { assetInView.push({ index: i, assetIndex: assetIndex ? assetIndex[i] : undefined, @@ -3198,7 +3221,8 @@ class AssetInViewSheetTable { (async () => { viewSheetIndex = (await localTable.getNumberArray("index:Vim.ViewSheet:ViewSheet")); })(), ]); let assetInViewSheet = []; - for (let i = 0; i < assetIndex.length; i++) { + const rowCount = await this.getCount(); + for (let i = 0; i < rowCount; i++) { assetInViewSheet.push({ index: i, assetIndex: assetIndex ? assetIndex[i] : undefined, @@ -3291,7 +3315,8 @@ class LevelInViewTable { (async () => { viewIndex = (await localTable.getNumberArray("index:Vim.View:View")); })(), ]); let levelInView = []; - for (let i = 0; i < extents_Min_X.length; i++) { + const rowCount = await this.getCount(); + for (let i = 0; i < rowCount; i++) { levelInView.push({ index: i, extents_Min_X: extents_Min_X ? extents_Min_X[i] : undefined, @@ -3428,7 +3453,8 @@ class CameraTable { (async () => { upOffset = (await localTable.getNumberArray("double:UpOffset")); })(), ]); let camera = []; - for (let i = 0; i < id.length; i++) { + const rowCount = await this.getCount(); + for (let i = 0; i < rowCount; i++) { camera.push({ index: i, id: id ? id[i] : undefined, @@ -3592,7 +3618,8 @@ class MaterialTable { (async () => { elementIndex = (await localTable.getNumberArray("index:Vim.Element:Element")); })(), ]); let material = []; - for (let i = 0; i < name.length; i++) { + const rowCount = await this.getCount(); + for (let i = 0; i < rowCount; i++) { material.push({ index: i, name: name ? name[i] : undefined, @@ -3809,7 +3836,8 @@ class MaterialInElementTable { (async () => { elementIndex = (await localTable.getNumberArray("index:Vim.Element:Element")); })(), ]); let materialInElement = []; - for (let i = 0; i < area.length; i++) { + const rowCount = await this.getCount(); + for (let i = 0; i < rowCount; i++) { materialInElement.push({ index: i, area: area ? area[i] : undefined, @@ -3914,7 +3942,8 @@ class CompoundStructureLayerTable { (async () => { compoundStructureIndex = (await localTable.getNumberArray("index:Vim.CompoundStructure:CompoundStructure")); })(), ]); let compoundStructureLayer = []; - for (let i = 0; i < orderIndex.length; i++) { + const rowCount = await this.getCount(); + for (let i = 0; i < rowCount; i++) { compoundStructureLayer.push({ index: i, orderIndex: orderIndex ? orderIndex[i] : undefined, @@ -4010,7 +4039,8 @@ class CompoundStructureTable { (async () => { structuralLayerIndex = (await localTable.getNumberArray("index:Vim.CompoundStructureLayer:StructuralLayer")); })(), ]); let compoundStructure = []; - for (let i = 0; i < width.length; i++) { + const rowCount = await this.getCount(); + for (let i = 0; i < rowCount; i++) { compoundStructure.push({ index: i, width: width ? width[i] : undefined, @@ -4075,7 +4105,8 @@ class NodeTable { (async () => { elementIndex = (await localTable.getNumberArray("index:Vim.Element:Element")); })(), ]); let node = []; - for (let i = 0; i < elementIndex.length; i++) { + const rowCount = await this.getCount(); + for (let i = 0; i < rowCount; i++) { node.push({ index: i, elementIndex: elementIndex ? elementIndex[i] : undefined @@ -4153,7 +4184,8 @@ class GeometryTable { (async () => { faceCount = (await localTable.getNumberArray("int:FaceCount")); })(), ]); let geometry = []; - for (let i = 0; i < box_Min_X.length; i++) { + const rowCount = await this.getCount(); + for (let i = 0; i < rowCount; i++) { geometry.push({ index: i, box_Min_X: box_Min_X ? box_Min_X[i] : undefined, @@ -4253,7 +4285,8 @@ class ShapeTable { (async () => { elementIndex = (await localTable.getNumberArray("index:Vim.Element:Element")); })(), ]); let shape = []; - for (let i = 0; i < elementIndex.length; i++) { + const rowCount = await this.getCount(); + for (let i = 0; i < rowCount; i++) { shape.push({ index: i, elementIndex: elementIndex ? elementIndex[i] : undefined @@ -4311,7 +4344,8 @@ class ShapeCollectionTable { (async () => { elementIndex = (await localTable.getNumberArray("index:Vim.Element:Element")); })(), ]); let shapeCollection = []; - for (let i = 0; i < elementIndex.length; i++) { + const rowCount = await this.getCount(); + for (let i = 0; i < rowCount; i++) { shapeCollection.push({ index: i, elementIndex: elementIndex ? elementIndex[i] : undefined @@ -4372,7 +4406,8 @@ class ShapeInShapeCollectionTable { (async () => { shapeCollectionIndex = (await localTable.getNumberArray("index:Vim.ShapeCollection:ShapeCollection")); })(), ]); let shapeInShapeCollection = []; - for (let i = 0; i < shapeIndex.length; i++) { + const rowCount = await this.getCount(); + for (let i = 0; i < rowCount; i++) { shapeInShapeCollection.push({ index: i, shapeIndex: shapeIndex ? shapeIndex[i] : undefined, @@ -4450,7 +4485,8 @@ class SystemTable { (async () => { elementIndex = (await localTable.getNumberArray("index:Vim.Element:Element")); })(), ]); let system = []; - for (let i = 0; i < systemType.length; i++) { + const rowCount = await this.getCount(); + for (let i = 0; i < rowCount; i++) { system.push({ index: i, systemType: systemType ? systemType[i] : undefined, @@ -4535,7 +4571,8 @@ class ElementInSystemTable { (async () => { elementIndex = (await localTable.getNumberArray("index:Vim.Element:Element")); })(), ]); let elementInSystem = []; - for (let i = 0; i < roles.length; i++) { + const rowCount = await this.getCount(); + for (let i = 0; i < rowCount; i++) { elementInSystem.push({ index: i, roles: roles ? roles[i] : undefined, @@ -4623,7 +4660,8 @@ class WarningTable { (async () => { bimDocumentIndex = (await localTable.getNumberArray("index:Vim.BimDocument:BimDocument")); })(), ]); let warning = []; - for (let i = 0; i < guid.length; i++) { + const rowCount = await this.getCount(); + for (let i = 0; i < rowCount; i++) { warning.push({ index: i, guid: guid ? guid[i] : undefined, @@ -4705,7 +4743,8 @@ class ElementInWarningTable { (async () => { elementIndex = (await localTable.getNumberArray("index:Vim.Element:Element")); })(), ]); let elementInWarning = []; - for (let i = 0; i < warningIndex.length; i++) { + const rowCount = await this.getCount(); + for (let i = 0; i < rowCount; i++) { elementInWarning.push({ index: i, warningIndex: warningIndex ? warningIndex[i] : undefined, @@ -4798,7 +4837,8 @@ class BasePointTable { (async () => { elementIndex = (await localTable.getNumberArray("index:Vim.Element:Element")); })(), ]); let basePoint = []; - for (let i = 0; i < isSurveyPoint.length; i++) { + const rowCount = await this.getCount(); + for (let i = 0; i < rowCount; i++) { basePoint.push({ index: i, isSurveyPoint: isSurveyPoint ? isSurveyPoint[i] : undefined, @@ -4917,7 +4957,8 @@ class PhaseFilterTable { (async () => { elementIndex = (await localTable.getNumberArray("index:Vim.Element:Element")); })(), ]); let phaseFilter = []; - for (let i = 0; i < _new.length; i++) { + const rowCount = await this.getCount(); + for (let i = 0; i < rowCount; i++) { phaseFilter.push({ index: i, _new: _new ? _new[i] : undefined, @@ -5045,7 +5086,8 @@ class GridTable { (async () => { elementIndex = (await localTable.getNumberArray("index:Vim.Element:Element")); })(), ]); let grid = []; - for (let i = 0; i < startPoint_X.length; i++) { + const rowCount = await this.getCount(); + for (let i = 0; i < rowCount; i++) { grid.push({ index: i, startPoint_X: startPoint_X ? startPoint_X[i] : undefined, @@ -5223,7 +5265,8 @@ class AreaTable { (async () => { elementIndex = (await localTable.getNumberArray("index:Vim.Element:Element")); })(), ]); let area = []; - for (let i = 0; i < value.length; i++) { + const rowCount = await this.getCount(); + for (let i = 0; i < rowCount; i++) { area.push({ index: i, value: value ? value[i] : undefined, @@ -5326,7 +5369,8 @@ class AreaSchemeTable { (async () => { elementIndex = (await localTable.getNumberArray("index:Vim.Element:Element")); })(), ]); let areaScheme = []; - for (let i = 0; i < isGrossBuildingArea.length; i++) { + const rowCount = await this.getCount(); + for (let i = 0; i < rowCount; i++) { areaScheme.push({ index: i, isGrossBuildingArea: isGrossBuildingArea ? isGrossBuildingArea[i] : undefined, @@ -5391,7 +5435,8 @@ class ScheduleTable { (async () => { elementIndex = (await localTable.getNumberArray("index:Vim.Element:Element")); })(), ]); let schedule = []; - for (let i = 0; i < elementIndex.length; i++) { + const rowCount = await this.getCount(); + for (let i = 0; i < rowCount; i++) { schedule.push({ index: i, elementIndex: elementIndex ? elementIndex[i] : undefined @@ -5455,7 +5500,8 @@ class ScheduleColumnTable { (async () => { scheduleIndex = (await localTable.getNumberArray("index:Vim.Schedule:Schedule")); })(), ]); let scheduleColumn = []; - for (let i = 0; i < name.length; i++) { + const rowCount = await this.getCount(); + for (let i = 0; i < rowCount; i++) { scheduleColumn.push({ index: i, name: name ? name[i] : undefined, @@ -5533,7 +5579,8 @@ class ScheduleCellTable { (async () => { scheduleColumnIndex = (await localTable.getNumberArray("index:Vim.ScheduleColumn:ScheduleColumn")); })(), ]); let scheduleCell = []; - for (let i = 0; i < value.length; i++) { + const rowCount = await this.getCount(); + for (let i = 0; i < rowCount; i++) { scheduleCell.push({ index: i, value: value ? value[i] : undefined, @@ -5605,7 +5652,8 @@ class ViewSheetSetTable { (async () => { elementIndex = (await localTable.getNumberArray("index:Vim.Element:Element")); })(), ]); let viewSheetSet = []; - for (let i = 0; i < elementIndex.length; i++) { + const rowCount = await this.getCount(); + for (let i = 0; i < rowCount; i++) { viewSheetSet.push({ index: i, elementIndex: elementIndex ? elementIndex[i] : undefined @@ -5666,7 +5714,8 @@ class ViewSheetTable { (async () => { elementIndex = (await localTable.getNumberArray("index:Vim.Element:Element")); })(), ]); let viewSheet = []; - for (let i = 0; i < familyTypeIndex.length; i++) { + const rowCount = await this.getCount(); + for (let i = 0; i < rowCount; i++) { viewSheet.push({ index: i, familyTypeIndex: familyTypeIndex ? familyTypeIndex[i] : undefined, @@ -5741,7 +5790,8 @@ class ViewSheetInViewSheetSetTable { (async () => { viewSheetSetIndex = (await localTable.getNumberArray("index:Vim.ViewSheetSet:ViewSheetSet")); })(), ]); let viewSheetInViewSheetSet = []; - for (let i = 0; i < viewSheetIndex.length; i++) { + const rowCount = await this.getCount(); + for (let i = 0; i < rowCount; i++) { viewSheetInViewSheetSet.push({ index: i, viewSheetIndex: viewSheetIndex ? viewSheetIndex[i] : undefined, @@ -5816,7 +5866,8 @@ class ViewInViewSheetSetTable { (async () => { viewSheetSetIndex = (await localTable.getNumberArray("index:Vim.ViewSheetSet:ViewSheetSet")); })(), ]); let viewInViewSheetSet = []; - for (let i = 0; i < viewIndex.length; i++) { + const rowCount = await this.getCount(); + for (let i = 0; i < rowCount; i++) { viewInViewSheetSet.push({ index: i, viewIndex: viewIndex ? viewIndex[i] : undefined, @@ -5891,7 +5942,8 @@ class ViewInViewSheetTable { (async () => { viewSheetIndex = (await localTable.getNumberArray("index:Vim.ViewSheet:ViewSheet")); })(), ]); let viewInViewSheet = []; - for (let i = 0; i < viewIndex.length; i++) { + const rowCount = await this.getCount(); + for (let i = 0; i < rowCount; i++) { viewInViewSheet.push({ index: i, viewIndex: viewIndex ? viewIndex[i] : undefined, @@ -5933,8 +5985,8 @@ class VimDocument { this.entities = entities; this.strings = strings; } - static async createFromBfast(bfast, ignoreStrings = false) { - const loaded = await vimLoader_1.VimLoader.loadFromBfast(bfast, ignoreStrings); + static async createFromBfast(bfast, download, ignoreStrings = false) { + const loaded = await vimLoader_1.VimLoader.loadFromBfast(bfast, download, ignoreStrings); if (loaded[0] === undefined) return undefined; let doc = new VimDocument(loaded[0], loaded[1]); diff --git a/src/ts/dist/remoteVimx.d.ts b/src/ts/dist/remoteVimx.d.ts index 47b3169f..c4d445ee 100644 --- a/src/ts/dist/remoteVimx.d.ts +++ b/src/ts/dist/remoteVimx.d.ts @@ -6,6 +6,7 @@ import { RemoteValue } from "./remoteValue"; export declare class RemoteVimx { bfast: BFast; scene: RemoteValue; + chunkCache: Map>; constructor(bfast: BFast); static fromPath(path: string): Promise; /** @@ -29,4 +30,6 @@ export declare class RemoteVimx { * Fetches and returns the vimx G3dMesh with given index */ getChunk(chunk: number): Promise; + private requestChunk; + getMesh(mesh: number): Promise; } diff --git a/src/ts/dist/remoteVimx.js b/src/ts/dist/remoteVimx.js index 2509600b..13921803 100644 --- a/src/ts/dist/remoteVimx.js +++ b/src/ts/dist/remoteVimx.js @@ -9,6 +9,7 @@ const remoteBuffer_1 = require("./remoteBuffer"); const remoteValue_1 = require("./remoteValue"); class RemoteVimx { constructor(bfast) { + this.chunkCache = new Map(); this.bfast = bfast; this.scene = new remoteValue_1.RemoteValue(() => this.requestScene()); } @@ -50,12 +51,30 @@ class RemoteVimx { * Fetches and returns the vimx G3dMesh with given index */ async getChunk(chunk) { + var cached = this.chunkCache.get(chunk); + if (cached !== undefined) { + return cached.get(); + } + var value = new remoteValue_1.RemoteValue(() => this.requestChunk(chunk)); + this.chunkCache.set(chunk, value); + return value.get(); + } + async requestChunk(chunk) { const chunkBFast = await this.bfast.getLocalBfast(`chunk_${chunk}`, true); var ranges = await chunkBFast.getRanges(); const keys = [...ranges.keys()]; var bfasts = await Promise.all(keys.map(k => chunkBFast.getBfast(k))); var meshes = await Promise.all(bfasts.map(b => g3dMesh_1.G3dMesh.createFromBfast(b))); + const scene = await this.scene.get(); + meshes.forEach(m => m.scene = scene); return meshes; } + async getMesh(mesh) { + var scene = await this.scene.get(); + var chunk = scene.meshChunks[mesh]; + var meshes = await this.getChunk(chunk); + var index = scene.meshChunkIndices[mesh]; + return meshes[index]; + } } exports.RemoteVimx = RemoteVimx; diff --git a/src/ts/dist/vimHelpers.js b/src/ts/dist/vimHelpers.js index 1352ffbe..e4ec7e59 100644 --- a/src/ts/dist/vimHelpers.js +++ b/src/ts/dist/vimHelpers.js @@ -43,6 +43,10 @@ async function getElementsParameters(document, elements) { ]); if (!parameterElements) return undefined; + if (!parameterValues) + return undefined; + if (!getParameterDescriptorIndices) + return undefined; const getParameterDisplayValue = (index) => { const value = parameterValues[index]; const split = value.indexOf('|'); @@ -62,10 +66,10 @@ async function getElementsParameters(document, elements) { const descriptor = getParameterDescriptorIndices[parameter]; const value = getParameterDisplayValue(parameter); const name = Number.isInteger(descriptor) - ? parameterDescriptorNames[descriptor] + ? parameterDescriptorNames?.[descriptor] : undefined; const group = Number.isInteger(descriptor) - ? parameterDescriptorGroups[descriptor] + ? parameterDescriptorGroups?.[descriptor] : undefined; return { name, value, group, isInstance }; }); diff --git a/src/ts/dist/vimLoader.d.ts b/src/ts/dist/vimLoader.d.ts index eb75cb85..dee08101 100644 --- a/src/ts/dist/vimLoader.d.ts +++ b/src/ts/dist/vimLoader.d.ts @@ -3,7 +3,7 @@ */ import { BFast } from "./bfast"; export declare class VimLoader { - static loadFromBfast(bfast: BFast, ignoreStrings: boolean): Promise<[BFast | undefined, string[] | undefined]>; + static loadFromBfast(bfast: BFast, download: boolean, ignoreStrings: boolean): Promise<[BFast | undefined, string[] | undefined]>; private static requestStrings; private static requestEntities; } diff --git a/src/ts/dist/vimLoader.js b/src/ts/dist/vimLoader.js index 32bfc33b..42e79e2d 100644 --- a/src/ts/dist/vimLoader.js +++ b/src/ts/dist/vimLoader.js @@ -5,9 +5,9 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.VimLoader = void 0; class VimLoader { - static async loadFromBfast(bfast, ignoreStrings) { + static async loadFromBfast(bfast, download, ignoreStrings) { const [entity, strings] = await Promise.all([ - VimLoader.requestEntities(bfast), + VimLoader.requestEntities(bfast, download), ignoreStrings ? Promise.resolve(undefined) : VimLoader.requestStrings(bfast) ]); return [entity, strings]; @@ -21,8 +21,10 @@ class VimLoader { const strings = new TextDecoder('utf-8').decode(buffer).split('\0'); return strings; } - static async requestEntities(bfast) { - const entities = await bfast.getBfast('entities'); + static async requestEntities(bfast, download) { + const entities = download + ? await bfast.getLocalBfast('entities') + : await bfast.getBfast('entities'); if (!entities) { console.error('Could not get String Data from VIM file. Bim features will be disabled.'); } diff --git a/src/ts/package.json b/src/ts/package.json index 75fe171f..b0bfe339 100644 --- a/src/ts/package.json +++ b/src/ts/package.json @@ -1,6 +1,6 @@ { "name": "vim-format", - "version": "1.0.6-dev.201", + "version": "1.0.6-dev.209", "description": "The VIM format is a modern and efficient open 3D data interchange format designed for BIM and manufacturing data optimized for efficient loading and rendering on low-power devices.", "directories": { "test": "tests" diff --git a/src/ts/src/g3dScene.ts b/src/ts/src/g3dScene.ts index b50a86a7..8ed3c1a6 100644 --- a/src/ts/src/g3dScene.ts +++ b/src/ts/src/g3dScene.ts @@ -25,6 +25,7 @@ export class SceneAttributes { static meshChunk = 'g3d:mesh:chunk:0:int32:1' + static meshChunkIndices = 'g3d:mesh:chunkindex:0:int32:1'; static meshInstanceCounts = 'g3d:mesh:instancecount:0:int32:1' static meshIndexCounts = 'g3d:mesh:indexcount:0:int32:1' static meshVertexCounts = 'g3d:mesh:vertexcount:0:int32:1' @@ -44,6 +45,7 @@ export class SceneAttributes { SceneAttributes.instanceMaxs, SceneAttributes.meshChunk, + SceneAttributes.meshChunkIndices, SceneAttributes.meshInstanceCounts, SceneAttributes.meshIndexCounts, SceneAttributes.meshVertexCounts, @@ -72,6 +74,7 @@ export class G3dScene { instanceMaxs: Float32Array meshChunks : Int32Array + meshChunkIndices : Int32Array meshInstanceCounts: Int32Array meshIndexCounts: Int32Array meshVertexCounts: Int32Array @@ -96,6 +99,7 @@ export class G3dScene { instanceMaxs: Float32Array, meshChunks: Int32Array, + meshChunkIndices : Int32Array, meshInstanceCounts: Int32Array, meshIndexCounts : Int32Array, meshVertexCounts: Int32Array, @@ -117,6 +121,7 @@ export class G3dScene { this.instanceMaxs = instanceMaxs this.meshChunks = meshChunks + this.meshChunkIndices = meshChunkIndices this.meshInstanceCounts = meshInstanceCounts this.meshIndexCounts = meshIndexCounts this.meshVertexCounts = meshVertexCounts @@ -166,6 +171,7 @@ export class G3dScene { getArray(SceneAttributes.instanceMaxs), getArray(SceneAttributes.meshChunk), + getArray(SceneAttributes.meshChunkIndices), getArray(SceneAttributes.meshInstanceCounts), getArray(SceneAttributes.meshIndexCounts), getArray(SceneAttributes.meshVertexCounts), diff --git a/src/ts/src/remoteVimx.ts b/src/ts/src/remoteVimx.ts index b2b39933..cad867bb 100644 --- a/src/ts/src/remoteVimx.ts +++ b/src/ts/src/remoteVimx.ts @@ -8,6 +8,7 @@ import { RemoteValue } from "./remoteValue"; export class RemoteVimx{ bfast : BFast scene : RemoteValue + chunkCache = new Map>() constructor(bfast : BFast){ this.bfast = bfast @@ -58,11 +59,31 @@ export class RemoteVimx{ * Fetches and returns the vimx G3dMesh with given index */ async getChunk(chunk: number){ + var cached = this.chunkCache.get(chunk) + if(cached !== undefined){ + return cached.get() + } + var value = new RemoteValue(() => this.requestChunk(chunk)) + this.chunkCache.set(chunk, value) + return value.get() + } + + private async requestChunk(chunk : number){ const chunkBFast = await this.bfast.getLocalBfast(`chunk_${chunk}`, true) var ranges = await chunkBFast.getRanges() const keys = [...ranges.keys()] var bfasts = await Promise.all(keys.map(k => chunkBFast.getBfast(k))) var meshes = await Promise.all(bfasts.map(b => G3dMesh.createFromBfast(b))) + const scene = await this.scene.get() + meshes.forEach(m => m.scene = scene) return meshes } + + async getMesh(mesh: number){ + var scene = await this.scene.get() + var chunk = scene.meshChunks[mesh] + var meshes = await this.getChunk(chunk) + var index = scene.meshChunkIndices[mesh] + return meshes[index] + } } \ No newline at end of file diff --git a/src/ts/src/vimHelpers.ts b/src/ts/src/vimHelpers.ts index dd007881..2af207a7 100644 --- a/src/ts/src/vimHelpers.ts +++ b/src/ts/src/vimHelpers.ts @@ -58,7 +58,9 @@ export type ElementParameter = { document.parameterDescriptor.getAllName(), document.parameterDescriptor.getAllGroup() ]) - if (!parameterElements) return undefined + if(!parameterElements) return undefined + if(!parameterValues) return undefined + if(!getParameterDescriptorIndices) return undefined const getParameterDisplayValue = (index: number) => { const value = parameterValues[index] @@ -81,11 +83,11 @@ export type ElementParameter = { const value = getParameterDisplayValue(parameter) const name = Number.isInteger(descriptor) - ? parameterDescriptorNames[descriptor] + ? parameterDescriptorNames?.[descriptor] : undefined const group = Number.isInteger(descriptor) - ? parameterDescriptorGroups[descriptor] + ? parameterDescriptorGroups?.[descriptor] : undefined return {name, value, group, isInstance} as ElementParameter diff --git a/src/ts/src/vimLoader.ts b/src/ts/src/vimLoader.ts index 331be64a..97e28523 100644 --- a/src/ts/src/vimLoader.ts +++ b/src/ts/src/vimLoader.ts @@ -5,11 +5,11 @@ import { BFast } from "./bfast" export class VimLoader { - static async loadFromBfast(bfast: BFast, ignoreStrings: boolean): Promise<[BFast | undefined, string[] | undefined]> { + static async loadFromBfast(bfast: BFast, download: boolean, ignoreStrings: boolean, ): Promise<[BFast | undefined, string[] | undefined]> { const [entity, strings] = await Promise.all([ - VimLoader.requestEntities(bfast), + VimLoader.requestEntities(bfast, download), ignoreStrings ? Promise.resolve(undefined) : VimLoader.requestStrings(bfast) ]) @@ -26,8 +26,11 @@ export class VimLoader { return strings } - private static async requestEntities (bfast: BFast) { - const entities = await bfast.getBfast('entities') + private static async requestEntities (bfast: BFast, download :boolean) { + const entities = download + ? await bfast.getLocalBfast('entities') + : await bfast.getBfast('entities') + if (!entities) { console.error('Could not get String Data from VIM file. Bim features will be disabled.') } From ea501b4e020ed13c822a70042f06bf816dcee4ff Mon Sep 17 00:00:00 2001 From: simon Date: Tue, 10 Oct 2023 11:37:01 -0400 Subject: [PATCH 018/111] fixed case when no instance flags --- src/cs/vim/Vim.Format.Vimx.Conversion/MeshesToScene.cs | 6 +++++- src/cs/vim/Vim.Format.Vimx.Conversion/VimToMeshes.cs | 2 -- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/cs/vim/Vim.Format.Vimx.Conversion/MeshesToScene.cs b/src/cs/vim/Vim.Format.Vimx.Conversion/MeshesToScene.cs index ab435bd1..864ad8c1 100644 --- a/src/cs/vim/Vim.Format.Vimx.Conversion/MeshesToScene.cs +++ b/src/cs/vim/Vim.Format.Vimx.Conversion/MeshesToScene.cs @@ -26,7 +26,11 @@ public static G3dScene CreateScene(G3dVim g3d, DocumentModel bim, VimxChunk[] ch scene.InstanceGroups = scene.InstanceNodes.Select(n => nodeElements[n]).ToArray(); scene.InstanceTags = scene.InstanceNodes.Select(n => nodeElementIds[n]).ToArray(); (scene.InstanceMins, scene.InstanceMaxs) = ComputeBoundingBoxes(meshes, scene.InstanceMeshes, scene.InstanceTransforms); - scene.InstanceFlags = scene.InstanceNodes.Select(i => g3d.InstanceFlags[i]).ToArray(); + + if (g3d.InstanceFlags != null) + { + scene.InstanceFlags = scene.InstanceNodes.Select(i => g3d.InstanceFlags[i]).ToArray(); + } // meshes scene.MeshChunks = new int[meshes.Length]; diff --git a/src/cs/vim/Vim.Format.Vimx.Conversion/VimToMeshes.cs b/src/cs/vim/Vim.Format.Vimx.Conversion/VimToMeshes.cs index add9efe7..ffd07d62 100644 --- a/src/cs/vim/Vim.Format.Vimx.Conversion/VimToMeshes.cs +++ b/src/cs/vim/Vim.Format.Vimx.Conversion/VimToMeshes.cs @@ -50,7 +50,6 @@ private static G3dMesh GetMesh(this G3dVim g3d, int mesh, List instances) } var instanceNodes = new int[instances.Count]; var instanceTransforms = new Matrix4x4[instances.Count]; - var instanceFlags = new ushort[instances.Count]; var submeshIndexOffsets = new List(); var submeshVertexOffsets = new List(); @@ -64,7 +63,6 @@ private static G3dMesh GetMesh(this G3dVim g3d, int mesh, List instances) var instance = instances[i]; instanceNodes[i] = instances[i]; instanceTransforms[i] = g3d.InstanceTransforms[instance]; - instanceFlags[i] = g3d.InstanceFlags[instance]; } var opaqueCount = AppendSubmeshes( From 12ed372f10f269ccc538f1dfdec6946fd16df090 Mon Sep 17 00:00:00 2001 From: simon Date: Tue, 31 Oct 2023 15:55:18 -0400 Subject: [PATCH 019/111] ignore type files --- src/ts/.gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ts/.gitignore b/src/ts/.gitignore index 40b878db..460b930c 100644 --- a/src/ts/.gitignore +++ b/src/ts/.gitignore @@ -1 +1,2 @@ -node_modules/ \ No newline at end of file +node_modules/ +*.d.ts \ No newline at end of file From 0be6e282ee8a78f8bb17a816bd246040c87c5e8e Mon Sep 17 00:00:00 2001 From: simon Date: Tue, 31 Oct 2023 15:55:54 -0400 Subject: [PATCH 020/111] various changes --- src/ts/dist/bfast.d.ts | 2 +- src/ts/dist/bfast.js | 11 ++++++++--- src/ts/dist/remoteValue.d.ts | 1 + src/ts/dist/remoteValue.js | 3 +++ src/ts/dist/remoteVimx.d.ts | 3 ++- src/ts/dist/remoteVimx.js | 18 ++++++++++++++++-- src/ts/dist/types/bfast.d.ts | 5 ++--- src/ts/dist/types/g3dScene.d.ts | 14 ++++++++++---- src/ts/dist/types/index.d.ts | 1 + src/ts/dist/types/objectModel.d.ts | 2 +- src/ts/dist/types/remoteVimx.d.ts | 25 +++++++++---------------- src/ts/dist/types/vimHeader.d.ts | 1 + src/ts/dist/types/vimLoader.d.ts | 2 +- src/ts/dist/vimHeader.d.ts | 1 + src/ts/dist/vimHeader.js | 1 + src/ts/package.json | 2 +- src/ts/src/bfast.ts | 15 +++++++++++---- src/ts/src/remoteValue.ts | 4 ++++ src/ts/src/remoteVimx.ts | 28 ++++++++++++++++++---------- src/ts/src/vimHeader.ts | 2 ++ 20 files changed, 94 insertions(+), 47 deletions(-) diff --git a/src/ts/dist/bfast.d.ts b/src/ts/dist/bfast.d.ts index fe93201f..4b26ae03 100644 --- a/src/ts/dist/bfast.d.ts +++ b/src/ts/dist/bfast.d.ts @@ -42,7 +42,7 @@ export declare class BFast { private _header; private _ranges; private _children; - constructor(source: RemoteBuffer | ArrayBuffer, offset?: number, name?: string); + constructor(source: RemoteBuffer | ArrayBuffer | string, offset?: number, name?: string); /** * Aborts all downloads from the underlying RemoteBuffer */ diff --git a/src/ts/dist/bfast.js b/src/ts/dist/bfast.js index 4d6797e4..8c0ad054 100644 --- a/src/ts/dist/bfast.js +++ b/src/ts/dist/bfast.js @@ -176,10 +176,12 @@ exports.BFastHeader = BFastHeader; * Remote mode can transition to buffer mode if server doesnt support partial http request */ class BFast { - constructor(source, offset = 0, name = '') { - this.source = source; + constructor(source, offset = 0, name) { + this.source = typeof source === 'string' + ? new remoteBuffer_1.RemoteBuffer(source) + : source; this.offset = offset; - this.name = name; + this.name = name ?? (typeof source === 'string' ? source : ''); this._header = new remoteValue_1.RemoteValue(() => this.requestHeader(), name + '.header'); this._children = new Map(); this._ranges = new remoteValue_1.RemoteValue(() => this.requestRanges(), name + '.ranges'); @@ -191,6 +193,9 @@ class BFast { if (this.source instanceof remoteBuffer_1.RemoteBuffer) { this.source.abort(); } + this._header.abort(); + this._ranges.abort(); + this._children.forEach(c => c.abort()); } /** * @returns Bfast Header diff --git a/src/ts/dist/remoteValue.d.ts b/src/ts/dist/remoteValue.d.ts index 9aaed21a..c1f318ba 100644 --- a/src/ts/dist/remoteValue.d.ts +++ b/src/ts/dist/remoteValue.d.ts @@ -10,6 +10,7 @@ export declare class RemoteValue { private _value; private _request; constructor(getter: () => Promise, label?: string); + abort(): void; /** * Returns a value from cache or queue up existing request or start a new requests */ diff --git a/src/ts/dist/remoteValue.js b/src/ts/dist/remoteValue.js index 51139cf4..e28c42ad 100644 --- a/src/ts/dist/remoteValue.js +++ b/src/ts/dist/remoteValue.js @@ -12,6 +12,9 @@ class RemoteValue { this._getter = getter; this.label = label ?? ''; } + abort() { + this._request = undefined; + } /** * Returns a value from cache or queue up existing request or start a new requests */ diff --git a/src/ts/dist/remoteVimx.d.ts b/src/ts/dist/remoteVimx.d.ts index c4d445ee..d45625f9 100644 --- a/src/ts/dist/remoteVimx.d.ts +++ b/src/ts/dist/remoteVimx.d.ts @@ -8,7 +8,7 @@ export declare class RemoteVimx { scene: RemoteValue; chunkCache: Map>; constructor(bfast: BFast); - static fromPath(path: string): Promise; + static fromPath(path: string): RemoteVimx; /** * Aborts all downloads from the underlying BFAST. */ @@ -18,6 +18,7 @@ export declare class RemoteVimx { */ download(): Promise; private requestScene; + getHeader(): Promise; /** * Fetches and returns the vimx G3dScene */ diff --git a/src/ts/dist/remoteVimx.js b/src/ts/dist/remoteVimx.js index 13921803..968f18f0 100644 --- a/src/ts/dist/remoteVimx.js +++ b/src/ts/dist/remoteVimx.js @@ -7,13 +7,14 @@ const g3dMesh_1 = require("./g3dMesh"); const g3dScene_1 = require("./g3dScene"); const remoteBuffer_1 = require("./remoteBuffer"); const remoteValue_1 = require("./remoteValue"); +const vimHeader_1 = require("./vimHeader"); class RemoteVimx { constructor(bfast) { this.chunkCache = new Map(); this.bfast = bfast; this.scene = new remoteValue_1.RemoteValue(() => this.requestScene()); } - static async fromPath(path) { + static fromPath(path) { const buffer = new remoteBuffer_1.RemoteBuffer(path); const bfast = new bfast_1.BFast(buffer); return new RemoteVimx(bfast); @@ -23,6 +24,8 @@ class RemoteVimx { */ abort() { this.bfast.abort(); + this.scene.abort(); + this.chunkCache.forEach(c => c.abort()); } /** * Downloads underlying bfast making all subsequent request local. @@ -34,6 +37,9 @@ class RemoteVimx { const index = await this.bfast.getLocalBfast('scene', true); return g3dScene_1.G3dScene.createFromBfast(index); } + async getHeader() { + return (0, vimHeader_1.requestHeader)(this.bfast); + } /** * Fetches and returns the vimx G3dScene */ @@ -72,9 +78,17 @@ class RemoteVimx { async getMesh(mesh) { var scene = await this.scene.get(); var chunk = scene.meshChunks[mesh]; + if (chunk === undefined) + return undefined; var meshes = await this.getChunk(chunk); + if (meshes === undefined) + return undefined; var index = scene.meshChunkIndices[mesh]; - return meshes[index]; + var result = meshes[index]; + if (result === undefined) + return undefined; + result.meshIndex = mesh; + return result; } } exports.RemoteVimx = RemoteVimx; diff --git a/src/ts/dist/types/bfast.d.ts b/src/ts/dist/types/bfast.d.ts index a75624bf..4b26ae03 100644 --- a/src/ts/dist/types/bfast.d.ts +++ b/src/ts/dist/types/bfast.d.ts @@ -42,7 +42,7 @@ export declare class BFast { private _header; private _ranges; private _children; - constructor(source: RemoteBuffer | ArrayBuffer, offset?: number, name?: string); + constructor(source: RemoteBuffer | ArrayBuffer | string, offset?: number, name?: string); /** * Aborts all downloads from the underlying RemoteBuffer */ @@ -61,8 +61,7 @@ export declare class BFast { * @param name buffer name */ getBfast(name: string): Promise; - getLocalBfast(name: string, unzip?: boolean): Promise; - getLocalBfastRaw(name: string, unzip?: boolean): Promise; + getLocalBfast(name: string, inflate?: boolean): Promise; /** * Returns the raw buffer associated with a name * This value is not cached. diff --git a/src/ts/dist/types/g3dScene.d.ts b/src/ts/dist/types/g3dScene.d.ts index b501fb8a..49fe9555 100644 --- a/src/ts/dist/types/g3dScene.d.ts +++ b/src/ts/dist/types/g3dScene.d.ts @@ -9,14 +9,17 @@ export declare type FilterMode = undefined | 'mesh' | 'instance' | 'group' | 'ta * See https://github.com/vimaec/vim#vim-geometry-attributes */ export declare class SceneAttributes { - static instanceFiles: string; - static instanceIndices: string; + static chunkCount: string; + static instanceMesh: string; + static instanceTransform: string; static instanceNodes: string; static instanceGroups: string; static instanceTags: string; static instanceFlags: string; static instanceMins: string; static instanceMaxs: string; + static meshChunk: string; + static meshChunkIndices: string; static meshInstanceCounts: string; static meshIndexCounts: string; static meshVertexCounts: string; @@ -31,14 +34,17 @@ export declare class SceneAttributes { */ export declare class G3dScene { rawG3d: AbstractG3d; + chunkCount: number; instanceMeshes: Int32Array; - instanceIndices: Int32Array; + instanceTransforms: Int32Array; instanceNodes: Int32Array; instanceGroups: Int32Array; instanceTags: BigInt64Array; instanceFlags: Uint16Array; instanceMins: Float32Array; instanceMaxs: Float32Array; + meshChunks: Int32Array; + meshChunkIndices: Int32Array; meshInstanceCounts: Int32Array; meshIndexCounts: Int32Array; meshVertexCounts: Int32Array; @@ -46,7 +52,7 @@ export declare class G3dScene { meshOpaqueVertexCounts: Int32Array; private nodeToInstance; private meshSceneInstances; - constructor(rawG3d: AbstractG3d, instanceFiles: Int32Array, instanceIndices: Int32Array, instanceNodes: Int32Array, instanceGroups: Int32Array, instanceTags: BigInt64Array, instanceFlags: Uint16Array, instanceMins: Float32Array, instanceMaxs: Float32Array, meshInstanceCounts: Int32Array, meshIndexCounts: Int32Array, meshVertexCounts: Int32Array, meshOpaqueIndexCounts: Int32Array, meshOpaqueVertexCounts: Int32Array); + constructor(rawG3d: AbstractG3d, chunkCount: Int32Array, instanceMeshes: Int32Array, instanceTransform: Int32Array, instanceNodes: Int32Array, instanceGroups: Int32Array, instanceTags: BigInt64Array, instanceFlags: Uint16Array, instanceMins: Float32Array, instanceMaxs: Float32Array, meshChunks: Int32Array, meshChunkIndices: Int32Array, meshInstanceCounts: Int32Array, meshIndexCounts: Int32Array, meshVertexCounts: Int32Array, meshOpaqueIndexCounts: Int32Array, meshOpaqueVertexCounts: Int32Array); private createMap; static createFromAbstract(g3d: AbstractG3d): G3dScene; static createFromPath(path: string): Promise; diff --git a/src/ts/dist/types/index.d.ts b/src/ts/dist/types/index.d.ts index 8b034a7e..e3775c32 100644 --- a/src/ts/dist/types/index.d.ts +++ b/src/ts/dist/types/index.d.ts @@ -1,4 +1,5 @@ export * from './bfast'; +export * from './abstractG3d'; export * from './g3d'; export * from './remoteVimx'; export * from './g3dMaterials'; diff --git a/src/ts/dist/types/objectModel.d.ts b/src/ts/dist/types/objectModel.d.ts index 73c72add..29ffa83b 100644 --- a/src/ts/dist/types/objectModel.d.ts +++ b/src/ts/dist/types/objectModel.d.ts @@ -3352,5 +3352,5 @@ export declare class VimDocument { entities: BFast; strings: string[] | undefined; private constructor(); - static createFromBfast(bfast: BFast, ignoreStrings?: boolean): Promise; + static createFromBfast(bfast: BFast, download: boolean, ignoreStrings?: boolean): Promise; } diff --git a/src/ts/dist/types/remoteVimx.d.ts b/src/ts/dist/types/remoteVimx.d.ts index a5c02aee..d45625f9 100644 --- a/src/ts/dist/types/remoteVimx.d.ts +++ b/src/ts/dist/types/remoteVimx.d.ts @@ -6,9 +6,9 @@ import { RemoteValue } from "./remoteValue"; export declare class RemoteVimx { bfast: BFast; scene: RemoteValue; - sceneRaw: RemoteValue; + chunkCache: Map>; constructor(bfast: BFast); - static fromPath(path: string): Promise; + static fromPath(path: string): RemoteVimx; /** * Aborts all downloads from the underlying BFAST. */ @@ -17,13 +17,12 @@ export declare class RemoteVimx { * Downloads underlying bfast making all subsequent request local. */ download(): Promise; + private requestScene; + getHeader(): Promise; /** - * Fetches and returns the vimx G3dMeshIndex - */ - private requestIndex; - private requestIndexRaw; - getIndex(): Promise; - getIndexRaw(): Promise; + * Fetches and returns the vimx G3dScene + */ + getScene(): Promise; /** * Fetches and returns the vimx G3dMaterials */ @@ -31,13 +30,7 @@ export declare class RemoteVimx { /** * Fetches and returns the vimx G3dMesh with given index */ + getChunk(chunk: number): Promise; + private requestChunk; getMesh(mesh: number): Promise; - /** - * Fetches and returns the vimx G3dMaterials - */ - getMaterialsRaw(): Promise; - /** - * Fetches and returns the vimx G3dMesh with given index - */ - getMeshRaw(mesh: number): Promise; } diff --git a/src/ts/dist/types/vimHeader.d.ts b/src/ts/dist/types/vimHeader.d.ts index e5a3e87f..8477ca2f 100644 --- a/src/ts/dist/types/vimHeader.d.ts +++ b/src/ts/dist/types/vimHeader.d.ts @@ -4,6 +4,7 @@ import { BFast } from "./bfast"; * See https://github.com/vimaec/vim#header-buffer */ export declare type VimHeader = { + isVimx: boolean; vim: string | undefined; id: string | undefined; revision: string | undefined; diff --git a/src/ts/dist/types/vimLoader.d.ts b/src/ts/dist/types/vimLoader.d.ts index eb75cb85..dee08101 100644 --- a/src/ts/dist/types/vimLoader.d.ts +++ b/src/ts/dist/types/vimLoader.d.ts @@ -3,7 +3,7 @@ */ import { BFast } from "./bfast"; export declare class VimLoader { - static loadFromBfast(bfast: BFast, ignoreStrings: boolean): Promise<[BFast | undefined, string[] | undefined]>; + static loadFromBfast(bfast: BFast, download: boolean, ignoreStrings: boolean): Promise<[BFast | undefined, string[] | undefined]>; private static requestStrings; private static requestEntities; } diff --git a/src/ts/dist/vimHeader.d.ts b/src/ts/dist/vimHeader.d.ts index e5a3e87f..8b6664e6 100644 --- a/src/ts/dist/vimHeader.d.ts +++ b/src/ts/dist/vimHeader.d.ts @@ -5,6 +5,7 @@ import { BFast } from "./bfast"; */ export declare type VimHeader = { vim: string | undefined; + vimx: string | undefined; id: string | undefined; revision: string | undefined; generator: string | undefined; diff --git a/src/ts/dist/vimHeader.js b/src/ts/dist/vimHeader.js index a98612f1..efed36c6 100644 --- a/src/ts/dist/vimHeader.js +++ b/src/ts/dist/vimHeader.js @@ -7,6 +7,7 @@ async function requestHeader(bfast) { const map = new Map(pairs.map((p) => p.split('=')).map((p) => [p[0], p[1]])); return { vim: map.get('vim'), + vimx: map.get('vimx'), id: map.get('id'), revision: map.get('revision'), generator: map.get('generator'), diff --git a/src/ts/package.json b/src/ts/package.json index b0bfe339..15328dcb 100644 --- a/src/ts/package.json +++ b/src/ts/package.json @@ -1,6 +1,6 @@ { "name": "vim-format", - "version": "1.0.6-dev.209", + "version": "1.0.6-dev.220", "description": "The VIM format is a modern and efficient open 3D data interchange format designed for BIM and manufacturing data optimized for efficient loading and rendering on low-power devices.", "directories": { "test": "tests" diff --git a/src/ts/src/bfast.ts b/src/ts/src/bfast.ts index 7b78ab65..ff8d5d3b 100644 --- a/src/ts/src/bfast.ts +++ b/src/ts/src/bfast.ts @@ -206,13 +206,16 @@ export function parseName(name: string): [number, NumericArrayConstructor]{ private _children: Map> constructor ( - source: RemoteBuffer | ArrayBuffer, + source: RemoteBuffer | ArrayBuffer | string, offset: number = 0, - name: string = '' + name?: string ) { - this.source = source + this.source = typeof source === 'string' + ? new RemoteBuffer(source) + : source + this.offset = offset - this.name = name + this.name = name ?? (typeof source === 'string' ? source : '') this._header = new RemoteValue(() => this.requestHeader(), name + '.header') this._children = new Map>() @@ -226,6 +229,10 @@ export function parseName(name: string): [number, NumericArrayConstructor]{ if(this.source instanceof RemoteBuffer){ this.source.abort() } + + this._header.abort() + this._ranges.abort() + this._children.forEach(c => c.abort()) } /** diff --git a/src/ts/src/remoteValue.ts b/src/ts/src/remoteValue.ts index 71548c32..3e81bb4f 100644 --- a/src/ts/src/remoteValue.ts +++ b/src/ts/src/remoteValue.ts @@ -16,6 +16,10 @@ export class RemoteValue { this.label = label ?? '' } + abort(){ + this._request = undefined + } + /** * Returns a value from cache or queue up existing request or start a new requests */ diff --git a/src/ts/src/remoteVimx.ts b/src/ts/src/remoteVimx.ts index cad867bb..d7ddc92a 100644 --- a/src/ts/src/remoteVimx.ts +++ b/src/ts/src/remoteVimx.ts @@ -2,30 +2,26 @@ import { BFast } from "./bfast"; import { G3dMaterial as G3dMaterials } from "./g3dMaterials"; import { G3dMesh } from "./g3dMesh"; import { G3dScene } from "./g3dScene"; -import { RemoteBuffer } from "./remoteBuffer"; import { RemoteValue } from "./remoteValue"; +import { requestHeader } from "./vimHeader"; export class RemoteVimx{ bfast : BFast scene : RemoteValue chunkCache = new Map>() - constructor(bfast : BFast){ - this.bfast = bfast + constructor(source : BFast | ArrayBuffer | string){ + this.bfast = source instanceof BFast ? source : new BFast(source) this.scene = new RemoteValue(() => this.requestScene()) } - static async fromPath(path: string){ - const buffer = new RemoteBuffer(path) - const bfast = new BFast(buffer) - return new RemoteVimx(bfast) - } - /** * Aborts all downloads from the underlying BFAST. */ abort(){ this.bfast.abort() + this.scene.abort() + this.chunkCache.forEach(c => c.abort()) } /** @@ -40,6 +36,10 @@ export class RemoteVimx{ return G3dScene.createFromBfast(index) } + async getHeader(){ + return requestHeader(this.bfast) + } + /** * Fetches and returns the vimx G3dScene */ @@ -82,8 +82,16 @@ export class RemoteVimx{ async getMesh(mesh: number){ var scene = await this.scene.get() var chunk = scene.meshChunks[mesh] + if(chunk === undefined) return undefined + var meshes = await this.getChunk(chunk) + if(meshes === undefined) return undefined + var index = scene.meshChunkIndices[mesh] - return meshes[index] + var result = meshes[index] + if(result === undefined) return undefined + + result.meshIndex = mesh + return result } } \ No newline at end of file diff --git a/src/ts/src/vimHeader.ts b/src/ts/src/vimHeader.ts index 4216854e..435e7a59 100644 --- a/src/ts/src/vimHeader.ts +++ b/src/ts/src/vimHeader.ts @@ -6,6 +6,7 @@ import { BFast } from "./bfast" */ export type VimHeader = { vim: string | undefined + vimx: string | undefined id: string | undefined revision: string | undefined generator: string | undefined @@ -19,6 +20,7 @@ export async function requestHeader (bfast: BFast): Promise { const map = new Map(pairs.map((p) => p.split('=')).map((p) => [p[0], p[1]])) return { vim: map.get('vim'), + vimx: map.get('vimx'), id: map.get('id'), revision: map.get('revision'), generator: map.get('generator'), From ecc61a46114c531c28eb9dabc3402874726908d6 Mon Sep 17 00:00:00 2001 From: simon Date: Thu, 30 Nov 2023 15:40:20 -0500 Subject: [PATCH 021/111] dist files for ts --- src/ts/dist/remoteVimx.d.ts | 3 +-- src/ts/dist/remoteVimx.js | 10 ++-------- src/ts/dist/types/remoteValue.d.ts | 1 + src/ts/dist/types/remoteVimx.d.ts | 3 +-- src/ts/dist/types/vimHeader.d.ts | 2 +- src/ts/package.json | 2 +- 6 files changed, 7 insertions(+), 14 deletions(-) diff --git a/src/ts/dist/remoteVimx.d.ts b/src/ts/dist/remoteVimx.d.ts index d45625f9..7bdf3878 100644 --- a/src/ts/dist/remoteVimx.d.ts +++ b/src/ts/dist/remoteVimx.d.ts @@ -7,8 +7,7 @@ export declare class RemoteVimx { bfast: BFast; scene: RemoteValue; chunkCache: Map>; - constructor(bfast: BFast); - static fromPath(path: string): RemoteVimx; + constructor(source: BFast | ArrayBuffer | string); /** * Aborts all downloads from the underlying BFAST. */ diff --git a/src/ts/dist/remoteVimx.js b/src/ts/dist/remoteVimx.js index 968f18f0..d3385abe 100644 --- a/src/ts/dist/remoteVimx.js +++ b/src/ts/dist/remoteVimx.js @@ -5,20 +5,14 @@ const bfast_1 = require("./bfast"); const g3dMaterials_1 = require("./g3dMaterials"); const g3dMesh_1 = require("./g3dMesh"); const g3dScene_1 = require("./g3dScene"); -const remoteBuffer_1 = require("./remoteBuffer"); const remoteValue_1 = require("./remoteValue"); const vimHeader_1 = require("./vimHeader"); class RemoteVimx { - constructor(bfast) { + constructor(source) { this.chunkCache = new Map(); - this.bfast = bfast; + this.bfast = source instanceof bfast_1.BFast ? source : new bfast_1.BFast(source); this.scene = new remoteValue_1.RemoteValue(() => this.requestScene()); } - static fromPath(path) { - const buffer = new remoteBuffer_1.RemoteBuffer(path); - const bfast = new bfast_1.BFast(buffer); - return new RemoteVimx(bfast); - } /** * Aborts all downloads from the underlying BFAST. */ diff --git a/src/ts/dist/types/remoteValue.d.ts b/src/ts/dist/types/remoteValue.d.ts index 9aaed21a..c1f318ba 100644 --- a/src/ts/dist/types/remoteValue.d.ts +++ b/src/ts/dist/types/remoteValue.d.ts @@ -10,6 +10,7 @@ export declare class RemoteValue { private _value; private _request; constructor(getter: () => Promise, label?: string); + abort(): void; /** * Returns a value from cache or queue up existing request or start a new requests */ diff --git a/src/ts/dist/types/remoteVimx.d.ts b/src/ts/dist/types/remoteVimx.d.ts index d45625f9..7bdf3878 100644 --- a/src/ts/dist/types/remoteVimx.d.ts +++ b/src/ts/dist/types/remoteVimx.d.ts @@ -7,8 +7,7 @@ export declare class RemoteVimx { bfast: BFast; scene: RemoteValue; chunkCache: Map>; - constructor(bfast: BFast); - static fromPath(path: string): RemoteVimx; + constructor(source: BFast | ArrayBuffer | string); /** * Aborts all downloads from the underlying BFAST. */ diff --git a/src/ts/dist/types/vimHeader.d.ts b/src/ts/dist/types/vimHeader.d.ts index 8477ca2f..8b6664e6 100644 --- a/src/ts/dist/types/vimHeader.d.ts +++ b/src/ts/dist/types/vimHeader.d.ts @@ -4,8 +4,8 @@ import { BFast } from "./bfast"; * See https://github.com/vimaec/vim#header-buffer */ export declare type VimHeader = { - isVimx: boolean; vim: string | undefined; + vimx: string | undefined; id: string | undefined; revision: string | undefined; generator: string | undefined; diff --git a/src/ts/package.json b/src/ts/package.json index 15328dcb..b727f2dd 100644 --- a/src/ts/package.json +++ b/src/ts/package.json @@ -1,6 +1,6 @@ { "name": "vim-format", - "version": "1.0.6-dev.220", + "version": "1.0.6-dev.221", "description": "The VIM format is a modern and efficient open 3D data interchange format designed for BIM and manufacturing data optimized for efficient loading and rendering on low-power devices.", "directories": { "test": "tests" From 02e1d98c10a582568ed4f425e279b17a336d9513 Mon Sep 17 00:00:00 2001 From: simon Date: Thu, 30 Nov 2023 15:41:46 -0500 Subject: [PATCH 022/111] Added getEnumerable and setEnumerable to bfastnext --- src/cs/bfast/Vim.BFast.Next/BFastNext.cs | 26 +++ src/cs/bfast/Vim.BFast.Next/BFastNextNode.cs | 109 ++++++++++++- src/cs/bfast/Vim.BFast.Next/IBFastNextNode.cs | 7 +- src/cs/bfast/Vim.BFast/UnsafeHelpers.cs | 32 +++- .../Vim.BFastNext.Tests/BFastNextTests.cs | 151 ++++++++++++++++++ .../vim/Vim.Format.Core/SerializableHeader.cs | 6 + src/cs/vim/Vim.Format.Vimx/Vimx.cs | 10 +- src/cs/vim/Vim.Format.Vimx/VimxHeader.cs | 28 ++-- src/cs/vim/Vim.Vimx.Test/VimxActions.cs | 8 +- 9 files changed, 346 insertions(+), 31 deletions(-) diff --git a/src/cs/bfast/Vim.BFast.Next/BFastNext.cs b/src/cs/bfast/Vim.BFast.Next/BFastNext.cs index e7678e57..dfaf2666 100644 --- a/src/cs/bfast/Vim.BFast.Next/BFastNext.cs +++ b/src/cs/bfast/Vim.BFast.Next/BFastNext.cs @@ -3,6 +3,7 @@ using System.IO; using System.IO.Compression; using System.Linq; +using System.Xml.Linq; using Vim.BFast; namespace Vim.BFastNextNS @@ -54,6 +55,9 @@ private byte[] Deflate(BFastNext bfast) } } + public void SetEnumerable(string name, Func> enumerable) where T : unmanaged + => _children[name] = new BFastEnumerableNode(enumerable); + public void SetArray(string name, T[] array) where T : unmanaged => _children[name] = BFastNextNode.FromArray(array); @@ -95,6 +99,12 @@ private BFastNext InflateNode(IBFastNextNode node) } } + public IEnumerable GetEnumerable(string name) where T : unmanaged + { + if (!_children.ContainsKey(name)) return null; + return _children[name].AsEnumerable(); + } + public T[] GetArray(string name) where T : unmanaged { if (!_children.ContainsKey(name)) return null; @@ -138,6 +148,17 @@ T[] IBFastNextNode.AsArray() } } + public IEnumerable AsEnumerable() where T : unmanaged + { + using (var stream = new MemoryStream()) + { + Write(stream); + var end = stream.Position; + stream.Seek(0, SeekOrigin.Begin); + return stream.ReadArrayBytes((int)end); + } + } + private static IEnumerable<(string name, BFastNextNode value)> GetBFastNodes(Stream stream) { var offset = stream.Position; @@ -189,6 +210,11 @@ public static T ReadBFast(this string path, Func process) return process(bfast); } } + + public static IEnumerable ToNamedBuffers(this BFastNext bfast) + { + return bfast.Entries.Select(name => bfast.GetArray(name).ToNamedBuffer(name)); + } } } diff --git a/src/cs/bfast/Vim.BFast.Next/BFastNextNode.cs b/src/cs/bfast/Vim.BFast.Next/BFastNextNode.cs index b9776167..b6195620 100644 --- a/src/cs/bfast/Vim.BFast.Next/BFastNextNode.cs +++ b/src/cs/bfast/Vim.BFast.Next/BFastNextNode.cs @@ -1,19 +1,113 @@ using System; +using System.Collections.Generic; using System.IO; +using System.Linq; +using System.Runtime.InteropServices.ComTypes; using Vim.BFast; namespace Vim.BFastNextNS { + + public class BFastEnumerableNode : IBFastNextNode where TNode: unmanaged + { + private Func> _source; + public BFastEnumerableNode(Func> source) + { + _source = source; + } + + private BFastNextNode AsMemNode() + => BFastNextNode.FromArray(_source().ToArray()); + + public T[] AsArray() where T : unmanaged + => AsMemNode().AsArray(); + + public BFastNext AsBFast() => AsMemNode().AsBFast(); + public IEnumerable AsEnumerable() where T : unmanaged + { + var stream = new MemoryStream(); + var array = new T[1000000]; + var chunks = Chunkify(_source(), 1000000); + while (chunks.MoveNext()) + { + (var chunk, var chunkSize) = chunks.Current; + stream.Seek(0, SeekOrigin.Begin); + stream.Write(chunk, chunkSize); + var count = ReadArray(stream, array); + + if (count > 0) + { + for( var i = 0; i < count; i++) + { + yield return array[i]; + } + } + } + } + + static IEnumerator<(T[], int)> Chunkify(IEnumerable source, int chunkSize) + { + var chunk = new T[chunkSize]; + var index = 0; + + foreach (var item in source) + { + chunk[index++] = item; + + if (index == chunkSize) + { + yield return (chunk, index); + index = 0; + } + } + + if (index > 0) + { + yield return (chunk, index); + } + } + + // Function is extracted because unsafe code cannot appear in generator + private unsafe int ReadArray(MemoryStream stream, T[] array) where T : unmanaged + { + var length = (int)stream.Position; + if (length < sizeof(T)) + { + return 0; + } + + var count = length / sizeof(T); + stream.Seek(0, SeekOrigin.Begin); + stream.ReadArray(array, count); + return count; + } + + public unsafe long GetSize() => _source().Count() * sizeof(TNode); + public void Write(Stream stream) + { + //TODO: Use bigger chunks + var array = new TNode[1]; + foreach(var value in _source()) + { + array[0] = value; + stream.Write(array); + } + } + } + + + public class BFastNextNode : IBFastNextNode { private readonly Stream _stream; private readonly BFastRange _range; - - public static BFastNextNode FromArray(T[] array) where T: unmanaged + private Action _cleanUp; + + public static BFastNextNode FromArray(T[] array) where T : unmanaged { /* Is a memory leak created if a MemoryStream in .NET is not closed? - ------------------------------------------------------------------ + -----------------------------------------]------------------------- You won't leak anything - at least in the current implementation. Calling Dispose won't clean up the memory used by MemoryStream any faster. It will stop your stream from being viable for Read/Write calls after the call, which may or may not be useful to you. If you're absolutely sure that you never want to move from a MemoryStream to another kind of stream, it's not going to do you any harm to not call Dispose. However, it's generally good practice partly because if you ever do change to use a different Stream, you don't want to get bitten by a hard-to-find bug because you chose the easy way out early on. (On the other hand, there's the YAGNI argument...) @@ -25,7 +119,8 @@ You won't leak anything - at least in the current implementation. return new BFastNextNode(stream, stream.FullRange()); } - public BFastNextNode(Stream stream, BFastRange range) + + public BFastNextNode(Stream stream, BFastRange range, Action cleanup = null) { _stream = stream; _range = range; @@ -51,6 +146,10 @@ public T[] AsArray() where T : unmanaged return _stream.ReadArrayBytes((int)_range.Count); } + public IEnumerable AsEnumerable() where T : unmanaged + => AsArray(); + + public long GetSize() { return _range.Count; @@ -73,5 +172,7 @@ private static void CopyStream(Stream input, Stream output, int bytes) bytes -= read; } } + + } } diff --git a/src/cs/bfast/Vim.BFast.Next/IBFastNextNode.cs b/src/cs/bfast/Vim.BFast.Next/IBFastNextNode.cs index a46a9eec..9f730d92 100644 --- a/src/cs/bfast/Vim.BFast.Next/IBFastNextNode.cs +++ b/src/cs/bfast/Vim.BFast.Next/IBFastNextNode.cs @@ -1,4 +1,7 @@ -using System.IO; +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; namespace Vim.BFastNextNS { @@ -14,6 +17,8 @@ public interface IWritable public interface IBFastNextNode : IWritable { T[] AsArray() where T : unmanaged; + IEnumerable AsEnumerable() where T : unmanaged; + BFastNext AsBFast(); } } diff --git a/src/cs/bfast/Vim.BFast/UnsafeHelpers.cs b/src/cs/bfast/Vim.BFast/UnsafeHelpers.cs index b5435fa1..8d849f5a 100644 --- a/src/cs/bfast/Vim.BFast/UnsafeHelpers.cs +++ b/src/cs/bfast/Vim.BFast/UnsafeHelpers.cs @@ -73,6 +73,15 @@ public static unsafe T[] ReadArray(this Stream stream, int count) where T : u return r; } + public static unsafe void ReadArray(this Stream stream, T[] array, int count) where T : unmanaged + { + fixed (T* pDest = array) + { + var pBytes = (byte*)pDest; + stream.ReadBytesBuffered(pBytes, (long)count * sizeof(T)); + } + } + /// /// Equivalent to ReadArray to use when you know the byte count instead of element count. @@ -82,6 +91,7 @@ public static unsafe T[] ReadArrayBytes(this Stream stream, int byteLength) w return ReadArray(stream, byteLength / sizeof(T)); } + /* public static unsafe T[] ConvertByteArrayToTypeArray(byte[] byteArray) where T : unmanaged { if (byteArray.Length % sizeof(T) != 0) @@ -89,16 +99,16 @@ public static unsafe T[] ConvertByteArrayToTypeArray(byte[] byteArray) where throw new ArgumentException("Byte array length is not a multiple of the size of the target type."); } - int elementCount = byteArray.Length / sizeof(T); - T[] resultArray = new T[elementCount]; + var elementCount = byteArray.Length / sizeof(T); + var resultArray = new T[elementCount]; fixed (byte* bytePtr = byteArray) { byte* currentBytePtr = bytePtr; fixed (T* resultPtr = resultArray) { - T* currentResultPtr = resultPtr; - for (int i = 0; i < elementCount; i++) + var currentResultPtr = resultPtr; + for (var i = 0; i < elementCount; i++) { *currentResultPtr = *((T*)currentBytePtr); currentBytePtr += sizeof(T); @@ -110,6 +120,7 @@ public static unsafe T[] ConvertByteArrayToTypeArray(byte[] byteArray) where return resultArray; } + */ /// /// A wrapper for stream.Seek(numBytes, SeekOrigin.Current) to avoid allocating memory for unrecognized buffers. /// @@ -138,7 +149,7 @@ public static unsafe void WriteValue(this Stream stream, T x) where T : unman var p = &x; stream.WriteBytesBuffered((byte*)p, sizeof(T)); } - + /// /// Helper for writing arrays of unmanaged types @@ -150,5 +161,16 @@ public static unsafe void Write(this Stream stream, T[] xs) where T : unmanag stream.WriteBytesBuffered((byte*)p, xs.LongLength * sizeof(T)); } } + + /// + /// Helper for writing arrays of unmanaged types + /// + public static unsafe void Write(this Stream stream, T[] xs, long count) where T : unmanaged + { + fixed (T* p = xs) + { + stream.WriteBytesBuffered((byte*)p, count * sizeof(T)); + } + } } } diff --git a/src/cs/bfast/Vim.BFastNext.Tests/BFastNextTests.cs b/src/cs/bfast/Vim.BFastNext.Tests/BFastNextTests.cs index 14199ffa..71270dcc 100644 --- a/src/cs/bfast/Vim.BFastNext.Tests/BFastNextTests.cs +++ b/src/cs/bfast/Vim.BFastNext.Tests/BFastNextTests.cs @@ -1,4 +1,5 @@ using NUnit.Framework; +using System; using Vim.Util; using Vim.Util.Tests; @@ -65,6 +66,106 @@ public void EmptyBFast_Writes_Header() } } + [Test] + public void SetEnumerable_Adds_Entry() + { + var bfast = new BFastNext(); + bfast.SetEnumerable("A", () => new int[3] { 0, 1, 2 }); + Assert.That(bfast.Entries.Count(), Is.EqualTo(1)); + } + + + [Test] + public void SetEnumerable_Then_GetArray() + { + var bfast = new BFastNext(); + bfast.SetEnumerable("A", () => new int[3] { 0, 1, 2 }); + var result = bfast.GetArray("A"); + + Assert.That(result, Is.EqualTo(new int[3] { 0, 1, 2 })); + } + + [Test] + public void SetEnumerable_Then_GetArray_Bytes() + { + var bfast = new BFastNext(); + bfast.SetEnumerable("A", () => new int[3] { 0, 1, 2 }); + var result = bfast.GetArray("A"); + + var bytes = (new int[3] { 0, 1, 2 }).SelectMany(i => BitConverter.GetBytes(i)); + Assert.That(result, Is.EqualTo(bytes)); + } + + + [Test] + public void SetEnumerable_Then_GetEnumerable_Bytes() + { + var bfast = new BFastNext(); + bfast.SetEnumerable("A", () => new int[3] { 0, 1, 2 }); + var result = bfast.GetEnumerable("A"); + + var bytes = (new int[3] { 0, 1, 2 }).SelectMany(i => BitConverter.GetBytes(i)); + Assert.That(result, Is.EqualTo(bytes)); + } + + [Test] + public void SetEnumerable_Then_GetEnumerable_Float() + { + var bfast = new BFastNext(); + bfast.SetEnumerable("A", () => new int[3] { 0, 1, 2 }); + var result = bfast.GetEnumerable("A"); + + var floats = (new int[3] { 0, 1, 2 }).Select(i => BitConverter.Int32BitsToSingle(i)); + Assert.That(result, Is.EqualTo(floats)); + } + + [Test] + public void SetEnumerable_Then_GetArray_Float() + { + var bfast = new BFastNext(); + bfast.SetEnumerable("A", () => new int[3] { 0, 1, 2 }); + var result = bfast.GetArray("A"); + + var floats = (new int[3] { 0, 1, 2 }).Select(i => BitConverter.Int32BitsToSingle(i)); + Assert.That(result, Is.EqualTo(floats)); + } + + + [Test] + public void SetEnumerable_Then_GetEnumerable() + { + var bfast = new BFastNext(); + bfast.SetEnumerable("A", () => new int[3] { 0, 1, 2 }); + var result = bfast.GetEnumerable("A").ToArray(); + Assert.That(result, Is.EqualTo(new int[3] { 0, 1, 2 })); + } + + [Test] + public void SetEnumerable_Then_GetBFast() + { + var bfast = new BFastNext(); + bfast.SetEnumerable("A", () => new int[3] { 0, 1, 2 }); + var result = bfast.GetBFast("A"); + Assert.That(result, Is.Null); + } + + IEnumerable GetLots() + { + return Enumerable.Range(0, int.MaxValue).Concat(Enumerable.Range(0, 10)); + } + + + [Test, Explicit] + public void SetEnumerable_Then_GetEnumerable_Lots() + { + var bfast = new BFastNext(); + bfast.SetEnumerable("A", GetLots); + + var result = bfast.GetEnumerable("A"); + Assert.That(result, Is.EqualTo(GetLots())); + } + + [Test] public void SetArray_Adds_Entry() { @@ -106,6 +207,38 @@ public void SetArray_Then_GetArray_Float() Assert.That(result, Is.EqualTo(floats)); } + [Test] + public void SetArray_Then_GetEnumerable() + { + var bfast = new BFastNext(); + bfast.SetArray("A", new int[3] { 0, 1, 2 }); + var result = bfast.GetEnumerable("A"); + + Assert.That(result, Is.EqualTo(new int[3] { 0, 1, 2 })); + } + + [Test] + public void SetArray_Then_GetEnumerable_Bytes() + { + var bfast = new BFastNext(); + bfast.SetArray("A", new int[3] { 0, 1, 2 }); + var result = bfast.GetEnumerable("A"); + + var bytes = (new int[3] { 0, 1, 2 }).SelectMany(i => BitConverter.GetBytes(i)); + Assert.That(result, Is.EqualTo(bytes)); + } + + [Test] + public void SetArray_Then_GetEnumerable_Float() + { + var bfast = new BFastNext(); + bfast.SetArray("A", new int[3] { 0, 1, 2 }); + var result = bfast.GetEnumerable("A"); + + var floats = (new int[3] { 0, 1, 2 }).Select(i => BitConverter.Int32BitsToSingle(i)); + Assert.That(result, Is.EqualTo(floats)); + } + [Test] public void SetArray_Then_GetBFast_Returns_Null() { @@ -303,6 +436,24 @@ public void Write_Then_Read_Array() } } + [Test] + public void Write_Then_Read_Enumerable() + { + var bfast = new BFastNext(); + + bfast.SetEnumerable("A", () => new int[3] { 0, 1, 2 }); + bfast.Write(Path); + + using (var stream = File.OpenRead(Path)) + { + var other = new BFastNext(stream); + var array = other.GetArray("A"); + var enumerable = other.GetEnumerable("A"); + Assert.That(array, Is.EqualTo(new int[3] { 0, 1, 2 })); + Assert.That(enumerable, Is.EqualTo(new int[3] { 0, 1, 2 })); + } + } + [Test] public void Write_Then_Read_SimpleBFast() { diff --git a/src/cs/vim/Vim.Format.Core/SerializableHeader.cs b/src/cs/vim/Vim.Format.Core/SerializableHeader.cs index 531f46c2..c2739ad5 100644 --- a/src/cs/vim/Vim.Format.Core/SerializableHeader.cs +++ b/src/cs/vim/Vim.Format.Core/SerializableHeader.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Globalization; using System.Linq; +using System.Text; using Vim.BFast; using Vim.Util; @@ -94,6 +95,11 @@ public SerializableHeader(string generator, SerializableVersion schema, string v AddOptionalValues(values ?? new Dictionary(), versionString)) { } + public static SerializableHeader FromBytes(byte[] input) + { + return Parse(Encoding.UTF8.GetString(input)); + } + /// /// Parses the input. Throws exceptions if the input does not define a correctly formatted header. /// diff --git a/src/cs/vim/Vim.Format.Vimx/Vimx.cs b/src/cs/vim/Vim.Format.Vimx/Vimx.cs index fe02bd4b..a12c180a 100644 --- a/src/cs/vim/Vim.Format.Vimx/Vimx.cs +++ b/src/cs/vim/Vim.Format.Vimx/Vimx.cs @@ -27,13 +27,13 @@ public static class BufferCompression public class Vimx { - public readonly VimxHeader Header; + public readonly SerializableHeader Header; public readonly MetaHeader Meta; public readonly G3dScene Scene; public readonly G3dMaterials Materials; public readonly VimxChunk[] Chunks; - public Vimx(VimxHeader header, MetaHeader meta, G3dScene scene, G3dMaterials materials, VimxChunk[] chunks) + public Vimx(SerializableHeader header, MetaHeader meta, G3dScene scene, G3dMaterials materials, VimxChunk[] chunks) { Meta = meta; Header = header; @@ -44,7 +44,7 @@ public Vimx(VimxHeader header, MetaHeader meta, G3dScene scene, G3dMaterials mat public Vimx(BFastNext bfast) { - Header = new VimxHeader(bfast.GetArray(BufferNames.Header)); + Header = VimxHeader.FromBytes(bfast.GetArray(BufferNames.Header)); Scene = new G3dScene( bfast.GetBFast(BufferNames.Scene, BufferCompression.Scene) @@ -53,13 +53,11 @@ public Vimx(BFastNext bfast) Materials = new G3dMaterials( bfast.GetBFast(BufferNames.Materials, BufferCompression.Materials) ); - Chunks = Enumerable.Range(0, Scene.GetChunksCount()) .Select(c => bfast.GetBFast(BufferNames.Chunk(c), BufferCompression.Chunks)) .Select(b => new VimxChunk(b)) .ToArray(); - } public static Vimx FromPath(string path) @@ -69,7 +67,7 @@ public BFastNext ToBFast() { var bfast = new BFastNext(); bfast.SetArray(BufferNames.Meta, MetaHeader.Default.ToBytes()); - bfast.SetArray(BufferNames.Header, Header.ToBytes()); + bfast.SetArray(BufferNames.Header, Header.ToVimxBytes()); bfast.SetBFast(BufferNames.Scene, Scene.ToBFast(), BufferCompression.Scene); bfast.SetBFast(BufferNames.Materials, Materials.ToBFast(), BufferCompression.Materials); bfast.SetBFast(BufferNames.Chunk, Chunks.Select(c => c.ToBFast()), BufferCompression.Chunks); diff --git a/src/cs/vim/Vim.Format.Vimx/VimxHeader.cs b/src/cs/vim/Vim.Format.Vimx/VimxHeader.cs index c723688b..0ccb2dea 100644 --- a/src/cs/vim/Vim.Format.Vimx/VimxHeader.cs +++ b/src/cs/vim/Vim.Format.Vimx/VimxHeader.cs @@ -1,34 +1,34 @@ -using System.Collections.Generic; -using System.Text; +using System.Text; using Vim.Util; namespace Vim.Format.VimxNS { - public class VimxHeader : SerializableHeader + public static class VimxHeader { - new protected const string FormatVersionField = "vimx"; - public VimxHeader(string generator, SerializableVersion schema, string versionString, IReadOnlyDictionary values = null) : base(generator, schema, versionString, values) + static SerializableVersion CurrentVersion = SerializableVersion.Parse("0.1.0"); + public static SerializableHeader FromString(string header) { + return SerializableHeader.Parse(header.Replace("vim", "vimx")); } - - public VimxHeader(SerializableHeader header) : this(header.Generator, header.Schema, header.FileFormatVersion.ToString()) + public static SerializableHeader FromBytes(byte[] header) { + return FromString(Encoding.UTF8.GetString(header)); } - public VimxHeader(string header) : this(Parse(header)) + public static string ToVimxString(this SerializableHeader header) { + return header.ToString().Replace("vim", "vimx"); } - public VimxHeader(byte[] bytes) : this(Encoding.UTF8.GetString(bytes)) + public static byte[] ToVimxBytes(this SerializableHeader header) { + return header.ToVimxString().ToBytesUtf8(); } - public static VimxHeader CreateDefault() + public static SerializableHeader CreateDefault() { - return new VimxHeader( - "Vim.Vimx.Converter", - CurrentVimFormatVersion, - CurrentVimFormatVersion.ToString() + return new SerializableHeader( + "Vim.Vimx.Converter", new SerializableVersion(), CurrentVersion.ToString() ); } } diff --git a/src/cs/vim/Vim.Vimx.Test/VimxActions.cs b/src/cs/vim/Vim.Vimx.Test/VimxActions.cs index 5c0ea74d..b00a6336 100644 --- a/src/cs/vim/Vim.Vimx.Test/VimxActions.cs +++ b/src/cs/vim/Vim.Vimx.Test/VimxActions.cs @@ -9,17 +9,23 @@ public static class VimxActions { const string whiteleys = "_WHITELEYS-VIM-MAIN_detached.v1.2.42.vim"; + const string residence = "residence.vim"; [Test, Explicit] public static void ConvertVimToVimx() { //var input = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); - var input = Path.Join(VimFormatRepoPaths.DataDir, whiteleys); + var input = Path.Join(VimFormatRepoPaths.DataDir, residence); var name = Path.GetFileNameWithoutExtension(input); var output = Path.Combine(VimFormatRepoPaths.OutDir, name + ".vimx"); var vimx = VimxConverter.FromVimPath(input); + + Console.WriteLine(vimx.Chunks.SelectMany(c => c.Meshes).Sum(m => m.Indices.Length)); + Console.WriteLine(vimx.Chunks.SelectMany(c => c.Meshes).Sum(m => m.Positions.Length)); + + Console.WriteLine(vimx.Header); vimx.ToBFast().Write(output); } } From b65d6ac1ad49546a3376fc368bfb779aadbac3d6 Mon Sep 17 00:00:00 2001 From: simon Date: Thu, 30 Nov 2023 16:23:21 -0500 Subject: [PATCH 023/111] BigG3dWriter implementation using bfastNext --- src/cs/vim/Vim.Format.Core/BigG3dWriter2.cs | 83 +++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 src/cs/vim/Vim.Format.Core/BigG3dWriter2.cs diff --git a/src/cs/vim/Vim.Format.Core/BigG3dWriter2.cs b/src/cs/vim/Vim.Format.Core/BigG3dWriter2.cs new file mode 100644 index 00000000..2beaa36b --- /dev/null +++ b/src/cs/vim/Vim.Format.Core/BigG3dWriter2.cs @@ -0,0 +1,83 @@ +using System.Collections.Generic; +using System.Linq; +using Vim.G3d; +using Vim.BFast; +using Vim.BFastNextNS; +using System.IO; +using static Vim.Format.DocumentBuilder; +using Vim.Math3d; + +namespace Vim.Format +{ + /// + /// This is a helper class for writing the really big G3Ds needed in a VIM + /// + public class BigG3dWriter2 : IBFastComponent + { + BFastNext bfast; + + public BigG3dWriter2(List meshes, List instances, List shapes, List materials, G3dHeader? header = null, bool useColors = false) + { + var totalSubmeshCount = meshes.Select(s => s.SubmeshesIndexOffset.Count).Sum(); + + // Compute the Vertex offsets and index offsets + var meshVertexOffsets = new int[meshes.Count]; + var meshIndexOffsets = new int[meshes.Count]; + var submeshIndexOffsets = new int[totalSubmeshCount]; + var meshSubmeshOffset = new int[meshes.Count]; + + var n = meshes.Count; + + for (var i = 1; i < n; ++i) + { + meshVertexOffsets[i] = meshVertexOffsets[i - 1] + meshes[i - 1].Vertices.Count; + meshIndexOffsets[i] = meshIndexOffsets[i - 1] + meshes[i - 1].Indices.Count; + meshSubmeshOffset[i] = meshSubmeshOffset[i - 1] + meshes[i - 1].SubmeshesIndexOffset.Count; + } + + var subIndex = 0; + var previousIndexCount = 0; + foreach (var geo in meshes) + { + foreach (var sub in geo.SubmeshesIndexOffset) + { + submeshIndexOffsets[subIndex++] = sub + previousIndexCount; + } + previousIndexCount += geo.Indices.Count; + } + + // Compute the shape vertex offsets + var numShapes = shapes.Count; + var shapeVertexOffsets = new int[numShapes]; + for (var i = 1; i < numShapes; ++i) + { + shapeVertexOffsets[i] = shapeVertexOffsets[i - 1] + shapes[i - 1].Vertices.Count; + } + + bfast = new BFastNext(); + bfast.SetArray("Meta", G3dHeader.Default.ToBytes()); + + bfast.SetEnumerable(CommonAttributes.Position, () => meshes.SelectMany(m => m.Vertices)); + bfast.SetEnumerable(CommonAttributes.Index, () => meshes.SelectMany(m => m.Indices)); + bfast.SetEnumerable(CommonAttributes.MeshSubmeshOffset, () => meshSubmeshOffset); + bfast.SetEnumerable(CommonAttributes.SubmeshIndexOffset, () => submeshIndexOffsets); + bfast.SetEnumerable(CommonAttributes.SubmeshMaterial, () => meshes.SelectMany(s => s.SubmeshMaterials)); + bfast.SetEnumerable(CommonAttributes.InstanceFlags, () => instances.Select(i => (ushort)i.InstanceFlags)); + bfast.SetEnumerable(CommonAttributes.InstanceParent, () => instances.Select(i => i.ParentIndex)); + bfast.SetEnumerable(CommonAttributes.InstanceMesh, () => instances.Select(i => i.MeshIndex)); + bfast.SetEnumerable(CommonAttributes.InstanceTransform, () => instances.Select(i => i.Transform)); + bfast.SetEnumerable(CommonAttributes.ShapeVertex, () => shapes.SelectMany(s => s.Vertices)); + bfast.SetEnumerable(CommonAttributes.ShapeVertexOffset, () => shapeVertexOffsets); + bfast.SetEnumerable(CommonAttributes.ShapeColor, () => shapes.Select(s => s.Color)); + bfast.SetEnumerable(CommonAttributes.ShapeWidth, () => shapes.Select(s => s.Width)); + bfast.SetEnumerable(CommonAttributes.MaterialColor, () => materials.Select(i => i.Color)); + bfast.SetEnumerable(CommonAttributes.MaterialGlossiness, () => materials.Select(i => i.Glossiness)); + bfast.SetEnumerable(CommonAttributes.MaterialSmoothness, () => materials.Select(i => i.Smoothness)); + } + + public long GetSize() + => bfast.GetSize(); + + public void Write(Stream stream) => bfast.Write(stream); + } +} From ebf307bfb6e79289290a3359cafd5042dc2f3f61 Mon Sep 17 00:00:00 2001 From: simon Date: Fri, 1 Dec 2023 15:15:13 -0500 Subject: [PATCH 024/111] changed to a power of 2 --- src/cs/bfast/Vim.BFast.Next/BFastNextNode.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cs/bfast/Vim.BFast.Next/BFastNextNode.cs b/src/cs/bfast/Vim.BFast.Next/BFastNextNode.cs index b6195620..9ab92b1b 100644 --- a/src/cs/bfast/Vim.BFast.Next/BFastNextNode.cs +++ b/src/cs/bfast/Vim.BFast.Next/BFastNextNode.cs @@ -26,8 +26,8 @@ public T[] AsArray() where T : unmanaged public IEnumerable AsEnumerable() where T : unmanaged { var stream = new MemoryStream(); - var array = new T[1000000]; - var chunks = Chunkify(_source(), 1000000); + var array = new T[1048576]; + var chunks = Chunkify(_source(), 1048576); while (chunks.MoveNext()) { (var chunk, var chunkSize) = chunks.Current; From fdd7a7066f6ecb42c923d87c2b7e252d47a83375 Mon Sep 17 00:00:00 2001 From: simon Date: Fri, 1 Dec 2023 15:17:16 -0500 Subject: [PATCH 025/111] moved features from serializer to vimScene using bfastnext. --- src/cs/bfast/Vim.BFast/BFastBufferReader.cs | 2 +- .../Vim.Format.Core/SerializableDocument.cs | 43 +++++++++++++++++++ src/cs/vim/Vim.Format.Core/Serializer.cs | 34 ++------------- .../Vim.Format.Core/Vim.Format.Core.csproj | 3 ++ .../vim/Vim.Format/SceneBuilder/VimScene.cs | 27 ++++++++++-- 5 files changed, 75 insertions(+), 34 deletions(-) diff --git a/src/cs/bfast/Vim.BFast/BFastBufferReader.cs b/src/cs/bfast/Vim.BFast/BFastBufferReader.cs index ccdcaa7f..1d06d32e 100644 --- a/src/cs/bfast/Vim.BFast/BFastBufferReader.cs +++ b/src/cs/bfast/Vim.BFast/BFastBufferReader.cs @@ -60,7 +60,7 @@ public Stream Seek() public NamedBuffer GetBuffer(bool inflate = false) where T : unmanaged { - this.Seek(); + Seek(); if (!inflate) { return _stream.ReadArray((int)Size).ToNamedBuffer(Name); diff --git a/src/cs/vim/Vim.Format.Core/SerializableDocument.cs b/src/cs/vim/Vim.Format.Core/SerializableDocument.cs index 6b834739..00458de1 100644 --- a/src/cs/vim/Vim.Format.Core/SerializableDocument.cs +++ b/src/cs/vim/Vim.Format.Core/SerializableDocument.cs @@ -1,7 +1,10 @@ using System; using System.Collections.Generic; +using System.IO; using System.Linq; using Vim.BFast; +using Vim.BFastNextNS; +using Vim.G3d; namespace Vim.Format { @@ -88,5 +91,45 @@ public class SerializableDocument /// The originating file name (if provided) /// public string FileName; + + + public void Write(string path) + { + using (var stream = new FileStream(path, FileMode.OpenOrCreate)) + { + Write(stream); + } + } + + public void Write(Stream stream) + { + var bfast = new BFastNext(); + //bfast.SetArray(BufferNames.Header, Header.ToBytes()); + + var assets = new BFastNext(); + foreach (var asset in Assets) + { + assets.SetArray(asset.Name, asset.ToArray()); + } + bfast.SetBFast(BufferNames.Assets, assets); + + var entities = new BFastNext(); + foreach (var entity in EntityTables) + { + var b = new BFastNext(); + foreach (var buffer in entity.ToBuffers()) + { + b.SetArray(buffer.Name, buffer.ToBytes()); + } + entities.SetBFast(entity.Name, b); + + } + bfast.SetBFast(BufferNames.Entities, entities); + + bfast.SetArray(BufferNames.Strings, StringTable.PackStrings()); + + bfast.SetArray(BufferNames.Geometry, Geometry.WriteToBytes()); + bfast.Write(stream); + } } } diff --git a/src/cs/vim/Vim.Format.Core/Serializer.cs b/src/cs/vim/Vim.Format.Core/Serializer.cs index 08d50e88..e3c6337f 100644 --- a/src/cs/vim/Vim.Format.Core/Serializer.cs +++ b/src/cs/vim/Vim.Format.Core/Serializer.cs @@ -7,6 +7,7 @@ using System.Text.RegularExpressions; using Vim.G3d; using Vim.Util; +using Vim.BFastNextNS; namespace Vim.Format { @@ -191,17 +192,8 @@ public static void Serialize( CreateBFastBuilder(header, assets, stringTable, entityTables, geometry).Write(stream); } - public static void Serialize(this SerializableDocument doc, Stream stream) - => doc.ToBFastBuilder().Write(stream); - - public static void Serialize(this SerializableDocument document, string filePath) - { - using (var stream = File.OpenWrite(filePath)) - document.Serialize(stream); - } - public static SerializableHeader ToSerializableHeader(this byte[] bytes) - => SerializableHeader.Parse(Encoding.UTF8.GetString(bytes)); + => SerializableHeader.FromBytes(bytes); /// /// Returns true if the SerializableHeader in the stream is successfully parsed. @@ -212,7 +204,8 @@ public static bool TryParseSerializableHeader(this Stream stream, out Serializab { try { - header = stream.ReadBFastBuffer(BufferNames.Header)?.Array.ToSerializableHeader(); + var bytes = stream.ReadBFastBuffer(BufferNames.Header)?.Array; + header = bytes != null ? SerializableHeader.FromBytes(bytes) : null; } catch { @@ -222,25 +215,6 @@ public static bool TryParseSerializableHeader(this Stream stream, out Serializab } } - /// - /// Returns true if the SerializableHeader in the given VIM file is successfully parsed. - /// - public static bool TryParseSerializableHeader(this FileInfo fileInfo, out SerializableHeader header) - { - using (var fs = fileInfo.OpenRead()) - { - return fs.TryParseSerializableHeader(out header); - } - } - - /// - /// Returns the VIM file's header schema version. Returns null if the header schema is not found. - /// - public static string GetSchemaVersion(this FileInfo fileInfo) - => fileInfo.TryParseSerializableHeader(out var header) - ? header.Schema?.ToString() - : null; - public static void ReadBuffer(this SerializableDocument doc, BFastBufferReader bufferReader) { var (name, numBytes) = bufferReader; diff --git a/src/cs/vim/Vim.Format.Core/Vim.Format.Core.csproj b/src/cs/vim/Vim.Format.Core/Vim.Format.Core.csproj index d845180e..25c15e16 100644 --- a/src/cs/vim/Vim.Format.Core/Vim.Format.Core.csproj +++ b/src/cs/vim/Vim.Format.Core/Vim.Format.Core.csproj @@ -7,7 +7,10 @@ + + + diff --git a/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs b/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs index 48fb2f24..4d9d0709 100644 --- a/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs +++ b/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading.Tasks; @@ -10,8 +9,8 @@ using Vim.G3d; using Vim.LinqArray; using Vim.Math3d; - using IVimSceneProgress = System.IProgress<(string, double)>; +using Vim.BFastNextNS; namespace Vim { @@ -22,6 +21,28 @@ namespace Vim /// public class VimScene : IScene { + /// + /// Returns the VIM file's header schema version. Returns null if the header schema is not found. + /// + public static string GetSchemaVersion(string path) + => GetHeader(path)?.Schema?.ToString(); + + public static SerializableHeader GetHeader(string path) + { + using (var file = new FileStream(path, FileMode.OpenOrCreate)) + { + return GetHeader(file); + } + } + + public static SerializableHeader GetHeader(Stream stream) + { + var bfast = new BFastNext(stream); + var bytes = bfast.GetArray(BufferNames.Header); + if (bytes == null) return null; + return SerializableHeader.FromBytes(bytes); + } + public static VimScene LoadVim(string f, LoadOptions loadOptions, IVimSceneProgress progress = null, bool inParallel = false, int vimIndex = 0) => new VimScene(Serializer.Deserialize(f, loadOptions), progress, inParallel, vimIndex); @@ -223,7 +244,7 @@ public static IArray CreateVimSceneNodes(VimScene scene, G3D g3d, } public void Save(string filePath) - => _SerializableDocument.Serialize(filePath); + => _SerializableDocument.Write(filePath); public string FileName => _SerializableDocument.FileName; From c587f5c5b4ab662be1d19c16cdc5e241399008a3 Mon Sep 17 00:00:00 2001 From: simon Date: Fri, 1 Dec 2023 15:50:16 -0500 Subject: [PATCH 026/111] removed header methods --- src/cs/vim/Vim.Format.Core/Serializer.cs | 25 +----------------------- 1 file changed, 1 insertion(+), 24 deletions(-) diff --git a/src/cs/vim/Vim.Format.Core/Serializer.cs b/src/cs/vim/Vim.Format.Core/Serializer.cs index e3c6337f..3c764dde 100644 --- a/src/cs/vim/Vim.Format.Core/Serializer.cs +++ b/src/cs/vim/Vim.Format.Core/Serializer.cs @@ -192,29 +192,6 @@ public static void Serialize( CreateBFastBuilder(header, assets, stringTable, entityTables, geometry).Write(stream); } - public static SerializableHeader ToSerializableHeader(this byte[] bytes) - => SerializableHeader.FromBytes(bytes); - - /// - /// Returns true if the SerializableHeader in the stream is successfully parsed. - /// - public static bool TryParseSerializableHeader(this Stream stream, out SerializableHeader header) - { - using (new SeekContext(stream)) - { - try - { - var bytes = stream.ReadBFastBuffer(BufferNames.Header)?.Array; - header = bytes != null ? SerializableHeader.FromBytes(bytes) : null; - } - catch - { - header = null; - } - return header != null; - } - } - public static void ReadBuffer(this SerializableDocument doc, BFastBufferReader bufferReader) { var (name, numBytes) = bufferReader; @@ -224,7 +201,7 @@ public static void ReadBuffer(this SerializableDocument doc, BFastBufferReader b { case BufferNames.Header: { - doc.Header = stream.ReadArray((int)numBytes).ToSerializableHeader(); + doc.Header = SerializableHeader.FromBytes(stream.ReadArray((int)numBytes)); break; } From 0acfd5a552c3c2c77b4d81bd38994b5b0c037a01 Mon Sep 17 00:00:00 2001 From: simon Date: Tue, 5 Dec 2023 12:46:58 -0500 Subject: [PATCH 027/111] Added instance transforms to scene Less bfast more bfast next --- .../Vim.G3dNext.Attributes/Attributes.g.cs | 68 +++++++++++ src/cs/g3d/Vim.G3dNext.Attributes/G3dScene.cs | 1 + .../Vim.G3dNext.Attributes/SceneAttributes.cs | 4 + src/cs/vim/Vim.Format.Core/DocumentBuilder.cs | 27 ++++- .../Vim.Format.Core/SerializableDocument.cs | 57 +++++++-- src/cs/vim/Vim.Format.Core/Serializer.cs | 113 ++++++++++++++---- src/cs/vim/Vim.Format.Core/VimSchema.cs | 7 +- src/cs/vim/Vim.Format.Tests/FormatTests.cs | 8 +- src/cs/vim/Vim.Format.Vimx/Vimx.cs | 19 ++- src/cs/vim/Vim.Format.Vimx/VimxHeader.cs | 2 +- .../vim/Vim.Format/SceneBuilder/VimScene.cs | 15 ++- .../SceneBuilder/VimSceneHelpers.cs | 2 +- src/cs/vim/Vim.Vimx.Test/VimxActions.cs | 4 +- src/cs/vim/Vim.Vimx.Test/VimxTests.cs | 16 ++- 14 files changed, 287 insertions(+), 56 deletions(-) diff --git a/src/cs/g3d/Vim.G3dNext.Attributes/Attributes.g.cs b/src/cs/g3d/Vim.G3dNext.Attributes/Attributes.g.cs index f5f066bb..3f909574 100644 --- a/src/cs/g3d/Vim.G3dNext.Attributes/Attributes.g.cs +++ b/src/cs/g3d/Vim.G3dNext.Attributes/Attributes.g.cs @@ -1000,6 +1000,51 @@ public void Write(Stream stream) } } + public partial class SceneInstanceTransformDataAttribute : IAttribute + { + public const string AttributeName = "g3d:instance:transform:0:float32:16"; + + public string Name + => AttributeName; + + public int Count => TypedData?.Length ?? 0; + + public void AddTo(BFastNext bfast) + { + if(TypedData != null) + { + bfast.SetArray(Name, TypedData); + } + } + + public void ReadBFast(BFastNext bfast) + { + TypedData = bfast.GetArray("g3d:instance:transform:0:float32:16"); + } + + public IAttributeDescriptor AttributeDescriptor { get; } + = new AttributeDescriptor(AttributeName); + + public AttributeType AttributeType { get; } + = AttributeType.Data; + + public Type IndexInto { get; } + = null; + + public Vim.Math3d.Matrix4x4[] TypedData { get; set; } + = Array.Empty(); + + public Array Data + => TypedData; + + public void Write(Stream stream) + { + if (TypedData == null || TypedData.Length == 0) + return; + stream.Write(TypedData); + } + } + public partial class SceneInstanceNodesAttribute : IAttribute { public const string AttributeName = "g3d:instance:node:0:int32:1"; @@ -2641,6 +2686,12 @@ public System.Int32[] InstanceTransforms set => Attributes.InstanceTransforms.TypedData = value; } + public Vim.Math3d.Matrix4x4[] InstanceTransformData + { + get => Attributes.InstanceTransformData.TypedData; + set => Attributes.InstanceTransformData.TypedData = value; + } + public System.Int32[] InstanceNodes { get => Attributes.InstanceNodes.TypedData; @@ -2747,6 +2798,7 @@ public void ReadAttributes(BFastNext bfast) [Vim.G3dNext.Attributes.SceneChunkCountAttribute.AttributeName] = new Vim.G3dNext.Attributes.SceneChunkCountAttribute(), [Vim.G3dNext.Attributes.SceneInstanceMeshesAttribute.AttributeName] = new Vim.G3dNext.Attributes.SceneInstanceMeshesAttribute(), [Vim.G3dNext.Attributes.SceneInstanceTransformsAttribute.AttributeName] = new Vim.G3dNext.Attributes.SceneInstanceTransformsAttribute(), + [Vim.G3dNext.Attributes.SceneInstanceTransformDataAttribute.AttributeName] = new Vim.G3dNext.Attributes.SceneInstanceTransformDataAttribute(), [Vim.G3dNext.Attributes.SceneInstanceNodesAttribute.AttributeName] = new Vim.G3dNext.Attributes.SceneInstanceNodesAttribute(), [Vim.G3dNext.Attributes.SceneInstanceGroupsAttribute.AttributeName] = new Vim.G3dNext.Attributes.SceneInstanceGroupsAttribute(), [Vim.G3dNext.Attributes.SceneInstanceTagsAttribute.AttributeName] = new Vim.G3dNext.Attributes.SceneInstanceTagsAttribute(), @@ -2782,6 +2834,12 @@ public Vim.G3dNext.Attributes.SceneInstanceTransformsAttribute InstanceTransform set => Map[Vim.G3dNext.Attributes.SceneInstanceTransformsAttribute.AttributeName] = value as IAttribute; } + public Vim.G3dNext.Attributes.SceneInstanceTransformDataAttribute InstanceTransformData + { + get => Map.TryGetValue(Vim.G3dNext.Attributes.SceneInstanceTransformDataAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.SceneInstanceTransformDataAttribute : default; + set => Map[Vim.G3dNext.Attributes.SceneInstanceTransformDataAttribute.AttributeName] = value as IAttribute; + } + public Vim.G3dNext.Attributes.SceneInstanceNodesAttribute InstanceNodes { get => Map.TryGetValue(Vim.G3dNext.Attributes.SceneInstanceNodesAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.SceneInstanceNodesAttribute : default; @@ -2877,6 +2935,10 @@ public IAttribute GetAttribute(Type attributeType) return InstanceTransforms; + if (attributeType == typeof(Vim.G3dNext.Attributes.SceneInstanceTransformDataAttribute)) + return InstanceTransformData; + + if (attributeType == typeof(Vim.G3dNext.Attributes.SceneInstanceNodesAttribute)) return InstanceNodes; @@ -2955,6 +3017,12 @@ public IAttribute MergeAttribute(string attributeName, IReadOnlyList().ToArray().MergeDataAttributes(); } + case Vim.G3dNext.Attributes.SceneInstanceTransformDataAttribute.AttributeName: + { + // Data Attribute + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + } + case Vim.G3dNext.Attributes.SceneInstanceNodesAttribute.AttributeName: { // Data Attribute diff --git a/src/cs/g3d/Vim.G3dNext.Attributes/G3dScene.cs b/src/cs/g3d/Vim.G3dNext.Attributes/G3dScene.cs index 108ffeba..65e693dd 100644 --- a/src/cs/g3d/Vim.G3dNext.Attributes/G3dScene.cs +++ b/src/cs/g3d/Vim.G3dNext.Attributes/G3dScene.cs @@ -3,6 +3,7 @@ public partial class G3dScene { public int GetChunksCount() => ChunkCount[0]; + public int GetInstanceCount() => InstanceMeshes.Length; void ISetup.Setup() { // empty diff --git a/src/cs/g3d/Vim.G3dNext.Attributes/SceneAttributes.cs b/src/cs/g3d/Vim.G3dNext.Attributes/SceneAttributes.cs index c2841bb3..88fcb2c7 100644 --- a/src/cs/g3d/Vim.G3dNext.Attributes/SceneAttributes.cs +++ b/src/cs/g3d/Vim.G3dNext.Attributes/SceneAttributes.cs @@ -6,6 +6,7 @@ namespace Vim.G3dNext.Attributes typeof(SceneChunkCountAttribute), typeof(SceneInstanceMeshesAttribute), typeof(SceneInstanceTransformsAttribute), + typeof(SceneInstanceTransformDataAttribute), typeof(SceneInstanceNodesAttribute), typeof(SceneInstanceGroupsAttribute), typeof(SceneInstanceTagsAttribute), @@ -34,6 +35,9 @@ public partial class SceneInstanceMeshesAttribute { } [AttributeDescriptor("Scene", "g3d:instance:transform:0:int32:1", AttributeType.Data)] public partial class SceneInstanceTransformsAttribute { } + [AttributeDescriptor("Scene", "g3d:instance:transform:0:float32:16", AttributeType.Data, ArrayType = typeof(Matrix4x4))] + public partial class SceneInstanceTransformDataAttribute { } + [AttributeDescriptor("Scene", "g3d:instance:node:0:int32:1", AttributeType.Data)] public partial class SceneInstanceNodesAttribute { } diff --git a/src/cs/vim/Vim.Format.Core/DocumentBuilder.cs b/src/cs/vim/Vim.Format.Core/DocumentBuilder.cs index 04c2372b..08407a89 100644 --- a/src/cs/vim/Vim.Format.Core/DocumentBuilder.cs +++ b/src/cs/vim/Vim.Format.Core/DocumentBuilder.cs @@ -6,6 +6,8 @@ using Vim.BFast; using System.IO; using Vim.Util; +using Vim.BFastNextNS; +using System.Runtime.InteropServices.ComTypes; namespace Vim.Format { @@ -180,12 +182,15 @@ public List ComputeEntityTables(IReadOnlyDictionary kv.Value.ToNamedBuffer(kv.Key)) as IEnumerable; Debug.Assert(assets != null, "Asset conversion to IEnumerable failed."); @@ -194,7 +199,21 @@ public void Write(Stream stream) var entityTables = ComputeEntityTables(stringLookupInfo.StringLookup); var stringTable = stringLookupInfo.StringTable; - Serializer.Serialize(stream, Header, assets, stringTable, entityTables, new BigG3dWriter(Meshes, Instances, Shapes, Materials, null, UseColors)); + var doc = new SerializableDocument() + { + Header = Header, + Assets = assets.ToArray(), + StringTable = stringTable.ToArray(), + EntityTables = entityTables + }; + var bfast = doc.ToBFast(); + + var g3d = new BigG3dWriter2(Meshes, Instances, Shapes, Materials, null, UseColors); + bfast.SetBFast(BufferNames.Geometry, g3d.bfast); + + return bfast; } + + } } diff --git a/src/cs/vim/Vim.Format.Core/SerializableDocument.cs b/src/cs/vim/Vim.Format.Core/SerializableDocument.cs index 00458de1..a1cb5798 100644 --- a/src/cs/vim/Vim.Format.Core/SerializableDocument.cs +++ b/src/cs/vim/Vim.Format.Core/SerializableDocument.cs @@ -2,6 +2,8 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Runtime.InteropServices.ComTypes; +using System.Text; using Vim.BFast; using Vim.BFastNextNS; using Vim.G3d; @@ -40,6 +42,11 @@ public IEnumerable ColumnNames => IndexColumns.Select(c => c.Name) .Concat(StringColumns.Select(c => c.Name)) .Concat(DataColumns.Select(c => c.Name)); + + public static SerializableEntityTable FromBfast(string name, BFastNext bfast) + { + return null; + } } /// @@ -91,17 +98,7 @@ public class SerializableDocument /// The originating file name (if provided) /// public string FileName; - - - public void Write(string path) - { - using (var stream = new FileStream(path, FileMode.OpenOrCreate)) - { - Write(stream); - } - } - - public void Write(Stream stream) + public BFastNext ToBFast() { var bfast = new BFastNext(); //bfast.SetArray(BufferNames.Header, Header.ToBytes()); @@ -129,7 +126,43 @@ public void Write(Stream stream) bfast.SetArray(BufferNames.Strings, StringTable.PackStrings()); bfast.SetArray(BufferNames.Geometry, Geometry.WriteToBytes()); - bfast.Write(stream); + return bfast; } + + public static SerializableDocument FromPath(string path, LoadOptions options = null) + { + using (var file = new FileStream(path, FileMode.OpenOrCreate)) + { + var bfast = new BFastNext(file); + var doc = FromBFast(bfast); + doc.FileName = path; + return doc; + } + } + + public static SerializableDocument FromBFast(BFastNext bfast, LoadOptions options = null) + { + var doc = new SerializableDocument(); + doc.Options = options ?? new LoadOptions(); + doc.Header = SerializableHeader.FromBytes(bfast.GetArray(BufferNames.Header)); + if (!doc.Options.SkipAssets) + { + var asset = bfast.GetBFast(BufferNames.Assets); + doc.Assets = asset.ToNamedBuffers().ToArray(); + } + var strs = bfast.GetArray(BufferNames.Strings); + doc.StringTable = Encoding.UTF8.GetString(strs).Split('\0'); + + if (!doc.Options.SkipGeometry) + { + var geo = bfast.GetArray(BufferNames.Geometry); + doc.Geometry = G3D.Read(geo); + } + + var entities = bfast.GetBFast(BufferNames.Entities); + doc.EntityTables = Serializer.EnumerateEntityTables2(entities, doc.Options.SchemaOnly).ToList(); + return doc; + } + } } diff --git a/src/cs/vim/Vim.Format.Core/Serializer.cs b/src/cs/vim/Vim.Format.Core/Serializer.cs index 3c764dde..ca626201 100644 --- a/src/cs/vim/Vim.Format.Core/Serializer.cs +++ b/src/cs/vim/Vim.Format.Core/Serializer.cs @@ -8,6 +8,7 @@ using Vim.G3d; using Vim.Util; using Vim.BFastNextNS; +using System.Drawing; namespace Vim.Format { @@ -109,13 +110,81 @@ public static SerializableEntityTable ReadEntityTable( et.DataColumns.Add(colBr.ReadEntityTableColumn(schemaOnly)); break; } - // For flexibility, we ignore the columns which do not contain a recognized prefix. + // For flexibility, we ignore the columns which do not contain a recognized prefix. } } return et; } + /// + /// Returns a SerializableEntityTable based on the given buffer reader. + /// + + public static SerializableEntityTable ReadEntityTable2( + BFastNext bfast, + bool schemaOnly + ) + { + var et = new SerializableEntityTable(); + foreach(var entry in bfast.Entries) + { + var typePrefix = entry.GetTypePrefix(); + + switch (typePrefix) + { + case VimConstants.IndexColumnNameTypePrefix: + { + //TODO: replace named buffer with arrays + var col = schemaOnly ? new int[0] : bfast.GetArray(entry); + et.IndexColumns.Add(col.ToNamedBuffer(entry)); + break; + } + case VimConstants.StringColumnNameTypePrefix: + { + var col = schemaOnly ? new int[0] : bfast.GetArray(entry); + et.StringColumns.Add(col.ToNamedBuffer(entry)); + break; + } + case VimConstants.IntColumnNameTypePrefix: + { + var col = schemaOnly ? new int[0] : bfast.GetArray(entry); + et.DataColumns.Add(col.ToNamedBuffer(entry)); + break; + } + case VimConstants.LongColumnNameTypePrefix: + { + var col = schemaOnly ? new long[0] : bfast.GetArray(entry); + et.DataColumns.Add(col.ToNamedBuffer(entry)); + break; + } + case VimConstants.DoubleColumnNameTypePrefix: + { + var col = schemaOnly ? new double[0] : bfast.GetArray(entry); + et.DataColumns.Add(col.ToNamedBuffer(entry)); + break; + } + case VimConstants.FloatColumnNameTypePrefix: + { + var col = schemaOnly ? new float[0] : bfast.GetArray(entry); + et.DataColumns.Add(col.ToNamedBuffer(entry)); + break; + } + case VimConstants.ByteColumnNameTypePrefix: + { + var col = schemaOnly ? new byte[0] : bfast.GetArray(entry); + et.DataColumns.Add(col.ToNamedBuffer(entry)); + break; + } + // For flexibility, we ignore the columns which do not contain a recognized prefix. + } + } + + return et; + } + + + /// /// Enumerates the SerializableEntityTables contained in the given entities buffer. /// @@ -129,6 +198,23 @@ public static IEnumerable EnumerateEntityTables( } } + /// + /// Enumerates the SerializableEntityTables contained in the given entities buffer. + /// + public static IEnumerable EnumerateEntityTables2( + BFastNext bfast, + bool schemaOnly) + { + + foreach (var entry in bfast.Entries) + { + var b = bfast.GetBFast(entry); + var table = ReadEntityTable2(b, schemaOnly); + table.Name = entry; + yield return table; + } + } + /// /// Enumerates the SerializableEntityTables contained in the given VIM file. /// @@ -192,7 +278,9 @@ public static void Serialize( CreateBFastBuilder(header, assets, stringTable, entityTables, geometry).Write(stream); } - public static void ReadBuffer(this SerializableDocument doc, BFastBufferReader bufferReader) + + + public static void ReadBuffer(this SerializableDocument doc, BFastBufferReader bufferReader) { var (name, numBytes) = bufferReader; var stream = bufferReader.Seek(); @@ -247,26 +335,5 @@ public static string[] ReadStrings(Stream stream, long numBytes) return joinedStringTable.Split('\0'); } - public static SerializableDocument Deserialize(Stream stream, LoadOptions loadOptions = null) - { - var doc = new SerializableDocument { Options = loadOptions }; - - foreach (var buffer in stream.GetBFastBufferReaders()) - { - doc.ReadBuffer(buffer); - } - - return doc; - } - - public static SerializableDocument Deserialize(string filePath, LoadOptions loadOptions = null) - { - using (var stream = File.OpenRead(filePath)) - { - var doc = Deserialize(stream, loadOptions); - doc.SetFileName(filePath); - return doc; - } - } } } diff --git a/src/cs/vim/Vim.Format.Core/VimSchema.cs b/src/cs/vim/Vim.Format.Core/VimSchema.cs index 7790a17b..70b9e025 100644 --- a/src/cs/vim/Vim.Format.Core/VimSchema.cs +++ b/src/cs/vim/Vim.Format.Core/VimSchema.cs @@ -45,9 +45,12 @@ public EntityTableSchema AddEntityTableSchema(string entityTableName) } public static VimSchema Create(string filePath) - => Create(Serializer.Deserialize(filePath).ToDocument()); + => Create(SerializableDocument.FromPath(filePath, new LoadOptions() { SchemaOnly=true}) ); - public static VimSchema Create(Document doc) + public static VimSchema Create(SerializableDocument doc) + => Create(doc.ToDocument()); + + private static VimSchema Create(Document doc) { var vimSchema = new VimSchema(doc.Header); foreach (var entityTable in doc.EntityTables.Values.ToEnumerable()) diff --git a/src/cs/vim/Vim.Format.Tests/FormatTests.cs b/src/cs/vim/Vim.Format.Tests/FormatTests.cs index eb7cb0ed..990b3d08 100644 --- a/src/cs/vim/Vim.Format.Tests/FormatTests.cs +++ b/src/cs/vim/Vim.Format.Tests/FormatTests.cs @@ -131,8 +131,8 @@ public static void AssertIsSupersetOf(EntityTable et1, EntityTable et2) /// public static void AssertIsSuperSetOf(Document d1, Document d2, bool skipGeometryAndNodes = true) { - var schema1 = VimSchema.Create(d1); - var schema2 = VimSchema.Create(d2); + var schema1 = VimSchema.Create(d1._Document); + var schema2 = VimSchema.Create(d2._Document); Assert.IsTrue(VimSchema.IsSuperSetOf(schema1, schema2)); var etKeys1 = d1.EntityTables.Keys; @@ -154,8 +154,8 @@ public static void AssertIsSuperSetOf(Document d1, Document d2, bool skipGeometr public static void AssertEquals(Document d1, Document d2, bool skipGeometryAndNodes = false) { - var schema1 = VimSchema.Create(d1); - var schema2 = VimSchema.Create(d2); + var schema1 = VimSchema.Create(d1._Document); + var schema2 = VimSchema.Create(d2._Document); Assert.IsTrue(VimSchema.IsSame(schema1, schema2)); var entityTables1 = d1.EntityTables.Keys.ToEnumerable().OrderBy(n => n).ToArray(); diff --git a/src/cs/vim/Vim.Format.Vimx/Vimx.cs b/src/cs/vim/Vim.Format.Vimx/Vimx.cs index a12c180a..b622144d 100644 --- a/src/cs/vim/Vim.Format.Vimx/Vimx.cs +++ b/src/cs/vim/Vim.Format.Vimx/Vimx.cs @@ -1,4 +1,5 @@ -using System.Linq; +using System.Collections.Generic; +using System.Linq; using Vim.BFastNextNS; using Vim.G3dNext; using Vim.G3dNext.Attributes; @@ -32,6 +33,7 @@ public class Vimx public readonly G3dScene Scene; public readonly G3dMaterials Materials; public readonly VimxChunk[] Chunks; + public IEnumerable Meshes => Chunks.SelectMany(c => c.Meshes); public Vimx(SerializableHeader header, MetaHeader meta, G3dScene scene, G3dMaterials materials, VimxChunk[] chunks) { @@ -53,7 +55,7 @@ public Vimx(BFastNext bfast) Materials = new G3dMaterials( bfast.GetBFast(BufferNames.Materials, BufferCompression.Materials) ); - + Chunks = Enumerable.Range(0, Scene.GetChunksCount()) .Select(c => bfast.GetBFast(BufferNames.Chunk(c), BufferCompression.Chunks)) .Select(b => new VimxChunk(b)) @@ -65,6 +67,7 @@ public static Vimx FromPath(string path) public BFastNext ToBFast() { + AddTransformsToScene(); var bfast = new BFastNext(); bfast.SetArray(BufferNames.Meta, MetaHeader.Default.ToBytes()); bfast.SetArray(BufferNames.Header, Header.ToVimxBytes()); @@ -74,6 +77,18 @@ public BFastNext ToBFast() return bfast; } + private void AddTransformsToScene() + { + Scene.InstanceTransformData = new Math3d.Matrix4x4[Scene.GetInstanceCount()]; + for (var i = 0; i < Scene.GetInstanceCount(); i++) + { + var mesh = Scene.InstanceMeshes[i]; + var chunk = Scene.MeshChunks[mesh]; + var chunIndex = Scene.MeshChunkIndices[mesh]; + var transform = Scene.InstanceTransforms[i]; + Scene.InstanceTransformData[i] = Chunks[chunk].Meshes[chunIndex].InstanceTransforms[transform]; + } + } } } diff --git a/src/cs/vim/Vim.Format.Vimx/VimxHeader.cs b/src/cs/vim/Vim.Format.Vimx/VimxHeader.cs index 0ccb2dea..3ce69b58 100644 --- a/src/cs/vim/Vim.Format.Vimx/VimxHeader.cs +++ b/src/cs/vim/Vim.Format.Vimx/VimxHeader.cs @@ -8,7 +8,7 @@ public static class VimxHeader static SerializableVersion CurrentVersion = SerializableVersion.Parse("0.1.0"); public static SerializableHeader FromString(string header) { - return SerializableHeader.Parse(header.Replace("vim", "vimx")); + return SerializableHeader.Parse(header.Replace("vimx", "vim")); } public static SerializableHeader FromBytes(byte[] header) { diff --git a/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs b/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs index 4d9d0709..bd324ab1 100644 --- a/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs +++ b/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs @@ -25,7 +25,7 @@ public class VimScene : IScene /// Returns the VIM file's header schema version. Returns null if the header schema is not found. /// public static string GetSchemaVersion(string path) - => GetHeader(path)?.Schema?.ToString(); + => string.IsNullOrEmpty(path) ? null : GetHeader(path)?.Schema?.ToString(); public static SerializableHeader GetHeader(string path) { @@ -44,13 +44,20 @@ public static SerializableHeader GetHeader(Stream stream) } public static VimScene LoadVim(string f, LoadOptions loadOptions, IVimSceneProgress progress = null, bool inParallel = false, int vimIndex = 0) - => new VimScene(Serializer.Deserialize(f, loadOptions), progress, inParallel, vimIndex); + => new VimScene(SerializableDocument.FromPath(f, loadOptions), progress, inParallel, vimIndex); public static VimScene LoadVim(string f, IVimSceneProgress progress = null, bool skipGeometry = false, bool skipAssets = false, bool skipNodes = false, bool inParallel = false) => LoadVim(f, new LoadOptions { SkipGeometry = skipGeometry, SkipAssets = skipAssets}, progress, inParallel); public static VimScene LoadVim(Stream stream, LoadOptions loadOptions, IVimSceneProgress progress = null, bool inParallel = false) - => new VimScene(Serializer.Deserialize(stream, loadOptions), progress, inParallel); + => new VimScene(SerializableDocument.FromBFast(new BFastNext(stream), loadOptions), progress, inParallel); + + public static VimScene LoadVim2(Stream stream, LoadOptions loadOptions = null, IVimSceneProgress progress = null, bool inParallel = false) + { + var bfast = new BFastNext(stream); + var doc = SerializableDocument.FromBFast(bfast, loadOptions); + return new VimScene(doc, progress, inParallel); + } public static VimScene LoadVim(Stream stream, IVimSceneProgress progress = null, bool skipGeometry = false, bool skipAssets = false, bool skipNodes = false, bool inParallel = false) => LoadVim(stream, new LoadOptions { SkipGeometry = skipGeometry, SkipAssets = skipAssets}, progress, inParallel); @@ -244,7 +251,7 @@ public static IArray CreateVimSceneNodes(VimScene scene, G3D g3d, } public void Save(string filePath) - => _SerializableDocument.Write(filePath); + => _SerializableDocument.ToBFast().Write(filePath); public string FileName => _SerializableDocument.FileName; diff --git a/src/cs/vim/Vim.Format/SceneBuilder/VimSceneHelpers.cs b/src/cs/vim/Vim.Format/SceneBuilder/VimSceneHelpers.cs index 3c6e5ceb..025a2c6c 100644 --- a/src/cs/vim/Vim.Format/SceneBuilder/VimSceneHelpers.cs +++ b/src/cs/vim/Vim.Format/SceneBuilder/VimSceneHelpers.cs @@ -173,6 +173,6 @@ public static ElementInfo GetElementInfo(this VimScene vim, Element element) => vim.DocumentModel.GetElementInfo(element); public static VimSchema GetVimSchema(this VimScene vim) - => VimSchema.Create(vim.Document); + => VimSchema.Create(vim._SerializableDocument); } } diff --git a/src/cs/vim/Vim.Vimx.Test/VimxActions.cs b/src/cs/vim/Vim.Vimx.Test/VimxActions.cs index b00a6336..c64dde6e 100644 --- a/src/cs/vim/Vim.Vimx.Test/VimxActions.cs +++ b/src/cs/vim/Vim.Vimx.Test/VimxActions.cs @@ -14,8 +14,8 @@ public static class VimxActions [Test, Explicit] public static void ConvertVimToVimx() { - //var input = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); - var input = Path.Join(VimFormatRepoPaths.DataDir, residence); + var input = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); + //var input = Path.Join(VimFormatRepoPaths.DataDir, residence); var name = Path.GetFileNameWithoutExtension(input); var output = Path.Combine(VimFormatRepoPaths.OutDir, name + ".vimx"); diff --git a/src/cs/vim/Vim.Vimx.Test/VimxTests.cs b/src/cs/vim/Vim.Vimx.Test/VimxTests.cs index aa5515f0..14690f36 100644 --- a/src/cs/vim/Vim.Vimx.Test/VimxTests.cs +++ b/src/cs/vim/Vim.Vimx.Test/VimxTests.cs @@ -5,6 +5,7 @@ using Vim.Math3d; using Vim.Format.VimxNS.Conversion; using Vim.Util.Tests; +using Vim.BFastNextNS; namespace Vim.Format.VimxNS.Tests { @@ -25,10 +26,23 @@ public static void Can_Convert_And_Read_Vimx() Assert.AreEqual(vimx.Scene.InstanceMeshes, result.Scene.InstanceMeshes); Assert.AreEqual(vimx.Materials.MaterialColors, result.Materials.MaterialColors); Assert.AreEqual(vimx.Chunks.Length, result.Chunks.Length); + } + } + + [TestFixture] + internal class VimTests + { + [Test] + public static void Write_BFastNext_VsOld() + { + using (var stream = new FileStream(VimFormatRepoPaths.GetLatestWolfordResidenceVim(), FileMode.OpenOrCreate)) + { + + } } - } + } } From fec4ff8c135bc46b1bd6b253fdf6a703f655185e Mon Sep 17 00:00:00 2001 From: simon Date: Tue, 5 Dec 2023 16:20:52 -0500 Subject: [PATCH 028/111] Removed all references to BFast except in g3d. --- .../Vim.BFast.Next/BFastEnumerableNode.cs | 94 ++++ src/cs/bfast/Vim.BFast.Next/BFastIO.cs | 469 ++++++++++++++++++ src/cs/bfast/Vim.BFast.Next/BFastNext.cs | 2 - src/cs/bfast/Vim.BFast.Next/BFastNextNode.cs | 96 ---- .../bfast/Vim.BFast.Next/BufferExtensions.cs | 89 ++++ src/cs/bfast/Vim.BFast.Next/Buffers.cs | 77 +++ src/cs/bfast/Vim.BFast.Next/UnsafeHelpers.cs | 175 +++++++ src/cs/bfast/Vim.BFast/BFast.cs | 1 + .../Vim.G3dNext.Attributes/Attributes.g.cs | 1 - src/cs/g3d/Vim.G3dNext.Attributes/G3dVim.cs | 1 - .../g3d/Vim.G3dNext/IAttributeCollection.cs | 1 - src/cs/vim/Vim.Format.Core/AssetInfo.cs | 2 +- src/cs/vim/Vim.Format.Core/BigG3dWriter.cs | 210 -------- src/cs/vim/Vim.Format.Core/BigG3dWriter2.cs | 83 ---- .../ColumnExtensions.Buffer.cs | 2 +- src/cs/vim/Vim.Format.Core/Document.cs | 4 +- src/cs/vim/Vim.Format.Core/DocumentBuilder.cs | 95 ++-- .../DocumentBuilderExtensions.cs | 2 +- .../vim/Vim.Format.Core/DocumentExtensions.cs | 2 +- src/cs/vim/Vim.Format.Core/EntityTable.cs | 2 +- .../vim/Vim.Format.Core/EntityTableBuilder.cs | 2 +- src/cs/vim/Vim.Format.Core/G3dBuilder.cs | 116 +++++ .../Vim.Format.Core/Geometry/Validation.cs | 2 +- .../Vim.Format.Core/SerializableDocument.cs | 129 ++++- .../vim/Vim.Format.Core/SerializableHeader.cs | 2 +- src/cs/vim/Vim.Format.Core/Serializer.cs | 318 +----------- src/cs/vim/Vim.Format.Core/Validation.cs | 2 +- src/cs/vim/Vim.Format.Tests/FormatTests.cs | 2 +- .../MeshesToScene.cs | 2 +- .../Vim.Format.Vimx.Conversion/VimToMeshes.cs | 2 +- .../VimxConverter.cs | 2 +- .../vim/Vim.Format/SceneBuilder/Validation.cs | 8 +- src/cs/vim/Vim.Vimx.Test/VimG3dTests.cs | 2 +- src/cs/vim/Vim.Vimx.Test/VimxTests.cs | 2 - 34 files changed, 1210 insertions(+), 789 deletions(-) create mode 100644 src/cs/bfast/Vim.BFast.Next/BFastEnumerableNode.cs create mode 100644 src/cs/bfast/Vim.BFast.Next/BFastIO.cs create mode 100644 src/cs/bfast/Vim.BFast.Next/BufferExtensions.cs create mode 100644 src/cs/bfast/Vim.BFast.Next/Buffers.cs create mode 100644 src/cs/bfast/Vim.BFast.Next/UnsafeHelpers.cs delete mode 100644 src/cs/vim/Vim.Format.Core/BigG3dWriter.cs delete mode 100644 src/cs/vim/Vim.Format.Core/BigG3dWriter2.cs create mode 100644 src/cs/vim/Vim.Format.Core/G3dBuilder.cs diff --git a/src/cs/bfast/Vim.BFast.Next/BFastEnumerableNode.cs b/src/cs/bfast/Vim.BFast.Next/BFastEnumerableNode.cs new file mode 100644 index 00000000..5c68cd1f --- /dev/null +++ b/src/cs/bfast/Vim.BFast.Next/BFastEnumerableNode.cs @@ -0,0 +1,94 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; + +namespace Vim.BFastNextNS +{ + public class BFastEnumerableNode : IBFastNextNode where TNode : unmanaged + { + private Func> _source; + public BFastEnumerableNode(Func> source) + { + _source = source; + } + + private BFastNextNode AsMemNode() + => BFastNextNode.FromArray(_source().ToArray()); + + public T[] AsArray() where T : unmanaged + => AsMemNode().AsArray(); + + public BFastNext AsBFast() => AsMemNode().AsBFast(); + public IEnumerable AsEnumerable() where T : unmanaged + { + var stream = new MemoryStream(); + var array = new T[1048576]; + var chunks = Chunkify(_source(), 1048576); + while (chunks.MoveNext()) + { + (var chunk, var chunkSize) = chunks.Current; + stream.Seek(0, SeekOrigin.Begin); + stream.Write(chunk, chunkSize); + var count = ReadArray(stream, array); + + if (count > 0) + { + for( var i = 0; i < count; i++) + { + yield return array[i]; + } + } + } + } + + static IEnumerator<(T[], int)> Chunkify(IEnumerable source, int chunkSize) + { + var chunk = new T[chunkSize]; + var index = 0; + + foreach (var item in source) + { + chunk[index++] = item; + + if (index == chunkSize) + { + yield return (chunk, index); + index = 0; + } + } + + if (index > 0) + { + yield return (chunk, index); + } + } + + // Function is extracted because unsafe code cannot appear in generator + private unsafe int ReadArray(MemoryStream stream, T[] array) where T : unmanaged + { + var length = (int)stream.Position; + if (length < sizeof(T)) + { + return 0; + } + + var count = length / sizeof(T); + stream.Seek(0, SeekOrigin.Begin); + stream.ReadArray(array, count); + return count; + } + + public unsafe long GetSize() => _source().Count() * sizeof(TNode); + public void Write(Stream stream) + { + //TODO: Use bigger chunks + var array = new TNode[1]; + foreach(var value in _source()) + { + array[0] = value; + stream.Write(array); + } + } + } +} diff --git a/src/cs/bfast/Vim.BFast.Next/BFastIO.cs b/src/cs/bfast/Vim.BFast.Next/BFastIO.cs new file mode 100644 index 00000000..d92e0f9d --- /dev/null +++ b/src/cs/bfast/Vim.BFast.Next/BFastIO.cs @@ -0,0 +1,469 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; + +namespace Vim.BFastNextNS +{ + public static class BFastIO + { + /// + /// Callback function allows clients to control writing the data to the output stream + /// + public delegate long BFastWriterFn(Stream writingStream, int bufferIdx, string bufferName, long bytesToWrite); + + /// + /// Enables a user to write a BFAST from an array of names, sizes, and a custom writing function. + /// The function will receive a BinaryWriter, the index of the buffer, and is expected to return the number of bytes written. + /// Simplifies the process of creating custom BinaryWriters, or writing extremely large arrays if necessary. + /// + public static void WriteBFast(this Stream stream, string[] bufferNames, long[] bufferSizes, BFastWriterFn onBuffer) + { + if (bufferSizes.Any(sz => sz < 0)) + throw new Exception("All buffer sizes must be zero or greater than zero"); + + if (bufferNames.Length != bufferSizes.Length) + throw new Exception($"The number of buffer names {bufferNames.Length} is not equal to the number of buffer sizes {bufferSizes}"); + + var header = CreateBFastHeader(bufferSizes, bufferNames); + stream.WriteBFast(header, bufferNames, bufferSizes, onBuffer); + } + + public static long NumBytes(this IBuffer buffer) + => (long)buffer.NumElements() * buffer.ElementSize; + + /// + /// Enables a user to write a BFAST from an array of names, sizes, and a custom writing function. + /// This is useful when the header is already computed. + /// + public static void WriteBFast(this Stream stream, BFastHeader header, string[] bufferNames, long[] bufferSizes, BFastWriterFn onBuffer) + { + stream.WriteBFastHeader(header); + CheckAlignment(stream); + stream.WriteBFastBody(header, bufferNames, bufferSizes, onBuffer); + } + + /// + /// Must be called after "WriteBFastHeader" + /// Enables a user to write the contents of a BFAST from an array of names, sizes, and a custom writing function. + /// The function will receive a BinaryWriter, the index of the buffer, and is expected to return the number of bytes written. + /// Simplifies the process of creating custom BinaryWriters, or writing extremely large arrays if necessary. + /// + public static void WriteBFastBody(this Stream stream, BFastHeader header, string[] bufferNames, long[] bufferSizes, BFastWriterFn onBuffer) + { + CheckAlignment(stream); + + if (bufferSizes.Any(sz => sz < 0)) + throw new Exception("All buffer sizes must be zero or greater than zero"); + + if (bufferNames.Length != bufferSizes.Length) + throw new Exception($"The number of buffer names {bufferNames.Length} is not equal to the number of buffer sizes {bufferSizes}"); + + // Then passes the binary writer for each buffer: checking that the correct amount of data was written. + for (var i = 0; i < bufferNames.Length; ++i) + { + CheckAlignment(stream); + var nBytes = bufferSizes[i]; + var pos = stream.CanSeek ? stream.Position : 0; + var nWrittenBytes = onBuffer(stream, i, bufferNames[i], nBytes); + if (stream.CanSeek) + { + if (stream.Position - pos != nWrittenBytes) + throw new NotImplementedException($"Buffer:{bufferNames[i]}. Stream movement {stream.Position - pos} does not reflect number of bytes claimed to be written {nWrittenBytes}"); + } + + if (nBytes != nWrittenBytes) + throw new Exception($"Number of bytes written {nWrittenBytes} not equal to expected bytes{nBytes}"); + var padding = ComputePadding(nBytes); + for (var j = 0; j < padding; ++j) + stream.WriteByte(0); + CheckAlignment(stream); + } + } + + + /// + /// Writes the BFAST header and name buffer to stream using the provided BinaryWriter. The BinaryWriter will be properly aligned by padding zeros + /// + public static BinaryWriter WriteBFastHeader(this Stream stream, BFastHeader header) + { + if (header.Ranges.Length != header.Names.Length + 1) + throw new Exception($"The number of ranges {header.Ranges.Length} must be equal to one more than the number of names {header.Names.Length}"); + var bw = new BinaryWriter(stream); + bw.Write(header.Preamble.Magic); + bw.Write(header.Preamble.DataStart); + bw.Write(header.Preamble.DataEnd); + bw.Write(header.Preamble.NumArrays); + foreach (var r in header.Ranges) + { + bw.Write(r.Begin); + bw.Write(r.End); + } + WriteZeroBytes(bw, ComputePadding(header.Ranges)); + + CheckAlignment(stream); + var nameBuffer = PackStrings(header.Names); + bw.Write(nameBuffer); + WriteZeroBytes(bw, ComputePadding(nameBuffer.LongLength)); + + CheckAlignment(stream); + return bw; + } + + + /// + /// Writes n zero bytes. + /// + public static void WriteZeroBytes(this BinaryWriter bw, long n) + { + for (var i = 0L; i < n; ++i) + bw.Write((byte)0); + } + + + /// + /// Creates a BFAST structure, without any actual data buffers, from a list of sizes of buffers (not counting the name buffer). + /// Used as an intermediate step to create a BFAST. + /// + public static BFastHeader CreateBFastHeader(this long[] bufferSizes, string[] bufferNames) + { + if (bufferNames.Length != bufferSizes.Length) + throw new Exception($"The number of buffer sizes {bufferSizes.Length} is not equal to the number of buffer names {bufferNames.Length}"); + + var header = new BFastHeader + { + Names = bufferNames + }; + header.Preamble.Magic = Constants.Magic; + header.Preamble.NumArrays = bufferSizes.Length + 1; + + // Allocate the data for the ranges + header.Ranges = new BFastRange[header.Preamble.NumArrays]; + header.Preamble.DataStart = ComputeNextAlignment(header.Preamble.RangesEnd); + + var nameBufferLength = PackStrings(bufferNames).LongLength; + var sizes = (new[] { nameBufferLength }).Concat(bufferSizes).ToArray(); + + // Compute the offsets for the data buffers + var curIndex = header.Preamble.DataStart; + var i = 0; + foreach (var size in sizes) + { + curIndex = ComputeNextAlignment(curIndex); + Debug.Assert(IsAligned(curIndex)); + + header.Ranges[i].Begin = curIndex; + curIndex += size; + + header.Ranges[i].End = curIndex; + i++; + } + + // Finish with the header + // Each buffer we contain is padded to ensure the next one + // starts on alignment, so we pad our DataEnd to reflect this reality + header.Preamble.DataEnd = ComputeNextAlignment(curIndex); + + // Check that everything adds up + return header.Validate(); + } + + /// + /// Reads the preamble, the ranges, and the names of the rest of the buffers. + /// + public static BFastHeader ReadBFastHeader(this Stream stream) + { + var r = new BFastHeader(); + var br = new BinaryReader(stream); + + if (stream.Length - stream.Position < sizeof(long) * 4) + throw new Exception("Stream too short"); + + r.Preamble = new BFastPreamble + { + Magic = br.ReadInt64(), + DataStart = br.ReadInt64(), + DataEnd = br.ReadInt64(), + NumArrays = br.ReadInt64(), + }.Validate(); + + r.Ranges = stream.ReadArray((int)r.Preamble.NumArrays); + + var padding = ComputePadding(r.Ranges); + br.ReadBytes((int)padding); + CheckAlignment(br.BaseStream); + + var nameBytes = br.ReadBytes((int)r.Ranges[0].Count); + r.Names = nameBytes.UnpackStrings(); + + padding = ComputePadding(r.Ranges[0].End); + br.ReadBytes((int)padding); + CheckAlignment(br.BaseStream); + + return r.Validate(); + } + + /// + /// Computes the padding requires after the array of BFastRanges are written out. + /// + /// + /// + public static long ComputePadding(BFastRange[] ranges) + => ComputePadding(BFastPreamble.Size + ranges.Length * BFastRange.Size); + + /// + /// Given a position in the stream, computes how much padding is required to bring the value to an aligned point. + /// + public static long ComputePadding(long n) + => ComputeNextAlignment(n) - n; + + /// + /// Given a position in the stream, tells us where the the next aligned position will be, if it the current position is not aligned. + /// + public static long ComputeNextAlignment(long n) + => IsAligned(n) ? n : n + Constants.ALIGNMENT - (n % Constants.ALIGNMENT); + + + /// + /// Checks that the stream (if seekable) is well aligned + /// + public static void CheckAlignment(Stream stream) + { + if (!stream.CanSeek) + return; + // TODO: Check with CD: Should we bail out here? This means that any + // alignment checks for a currently-writing stream are effectively ignored. + if (stream.Position == stream.Length) + return; + if (!IsAligned(stream.Position)) + throw new Exception($"Stream position {stream.Position} is not well aligned"); + } + + /// + /// Given a position in the stream, tells us whether the position is aligned. + /// + public static bool IsAligned(long n) + => n % Constants.ALIGNMENT == 0; + + + /// + /// Checks that the header values are sensible, and throws an exception otherwise. + /// + public static BFastHeader Validate(this BFastHeader header) + { + var preamble = header.Preamble.Validate(); + var ranges = header.Ranges; + var names = header.Names; + + if (preamble.RangesEnd > preamble.DataStart) + throw new Exception($"Computed arrays ranges end must be less than the start of data {preamble.DataStart}"); + + if (ranges == null) + throw new Exception("Ranges must not be null"); + + var min = preamble.DataStart; + var max = preamble.DataEnd; + + for (var i = 0; i < ranges.Length; ++i) + { + var begin = ranges[i].Begin; + if (!IsAligned(begin)) + throw new Exception($"The beginning of the range is not well aligned {begin}"); + var end = ranges[i].End; + if (begin < min || begin > max) + throw new Exception($"Array offset begin {begin} is not in valid span of {min} to {max}"); + if (i > 0) + { + if (begin < ranges[i - 1].End) + throw new Exception($"Array offset begin {begin} is overlapping with previous array {ranges[i - 1].End}"); + } + + if (end < begin || end > max) + throw new Exception($"Array offset end {end} is not in valid span of {begin} to {max}"); + } + + if (names.Length < ranges.Length - 1) + throw new Exception($"Number of buffer names {names.Length} is not one less than the number of ranges {ranges.Length}"); + + return header; + } + + /// + /// Checks that the header values are sensible, and throws an exception otherwise. + /// + public static BFastPreamble Validate(this BFastPreamble preamble) + { + if (preamble.Magic != Constants.SameEndian && preamble.Magic != Constants.SwappedEndian) + throw new Exception($"Invalid magic number {preamble.Magic}"); + + if (preamble.DataStart < BFastPreamble.Size) + throw new Exception($"Data start {preamble.DataStart} cannot be before the file header size {BFastPreamble.Size}"); + + if (preamble.DataStart > preamble.DataEnd) + throw new Exception($"Data start {preamble.DataStart} cannot be after the data end {preamble.DataEnd}"); + + if (!IsAligned(preamble.DataEnd)) + throw new Exception($"Data end {preamble.DataEnd} should be aligned"); + + if (preamble.NumArrays < 0) + throw new Exception($"Number of arrays {preamble.NumArrays} is not a positive number"); + + if (preamble.NumArrays > preamble.DataEnd) + throw new Exception($"Number of arrays {preamble.NumArrays} can't be more than the total size"); + + if (preamble.RangesEnd > preamble.DataStart) + throw new Exception($"End of range {preamble.RangesEnd} can't be after data-start {preamble.DataStart}"); + + return preamble; + } + + /// + /// Converts a byte[] array encoding a collection of strings separate by NULL into an array of string + /// + public static string[] UnpackStrings(this byte[] bytes) + { + var r = new List(); + if (bytes.Length == 0) + return r.ToArray(); + var prev = 0; + for (var i = 0; i < bytes.Length; ++i) + { + if (bytes[i] == 0) + { + r.Add(Encoding.UTF8.GetString(bytes, prev, i - prev)); + prev = i + 1; + } + } + if (prev < bytes.Length) + r.Add(Encoding.UTF8.GetString(bytes, prev, bytes.Length - prev)); + return r.ToArray(); + } + + /// + /// Converts a collection of strings, into a null-separated byte[] array + /// + public static byte[] PackStrings(IEnumerable strings) + { + var r = new List(); + foreach (var name in strings) + { + var bytes = Encoding.UTF8.GetBytes(name); + r.AddRange(bytes); + r.Add(0); + } + return r.ToArray(); + } + + public static BFastRange FullRange(this Stream stream) + => new BFastRange() + { + Begin = 0, + End = stream.Length + }; + + public static BFastRange OffsetBy(this BFastRange range, long offset) + => new BFastRange() + { + Begin = range.Begin + offset, + End = range.End + offset + }; + } + + /// + /// Constants. + /// + public static class Constants + { + public const long Magic = 0xBFA5; + + // https://en.wikipedia.org/wiki/Endianness + public const long SameEndian = Magic; + public const long SwappedEndian = 0xA5BFL << 48; + + /// + /// Data arrays are aligned to 64 bytes, so that they can be cast directly to AVX-512 registers. + /// This is useful for efficiently working with floating point data. + /// + public const long ALIGNMENT = 64; + } + + + /// + /// This contains the BFAST data loaded or written from disk. + /// + public class BFastHeader + { + public BFastPreamble Preamble = new BFastPreamble(); + public BFastRange[] Ranges; + public string[] Names; + + public override bool Equals(object o) + => o is BFastHeader other && Equals(other); + + public bool Equals(BFastHeader other) + => Preamble.Equals(other.Preamble) && + Ranges.Length == other.Ranges.Length && + Ranges.Zip(other.Ranges, (x, y) => x.Equals(y)).All(x => x) && + Names.Zip(other.Names, (x, y) => x.Equals(y)).All(x => x); + } + + /// + /// This tells us where a particular array begins and ends in relation to the beginning of a file. + /// * Begin must be less than or equal to End. + /// * Begin must be greater than or equal to DataStart + /// * End must be less than or equal to DataEnd + /// + [StructLayout(LayoutKind.Explicit, Pack = 8, Size = 16)] + public struct BFastRange + { + [FieldOffset(0)] public long Begin; + [FieldOffset(8)] public long End; + + public long Count => End - Begin; + public static long Size = 16; + + public override bool Equals(object x) + => x is BFastRange other && Equals(other); + + public bool Equals(BFastRange other) + => Begin == other.Begin && End == other.End; + } + + /// + /// The header contains a magic number, the begin and end indices of data, and the number of arrays. + /// + [StructLayout(LayoutKind.Explicit, Pack = 8, Size = 32)] + public struct BFastPreamble + { + [FieldOffset(0)] public long Magic; // Either Constants.SameEndian or Constants.SwappedEndian depending on endianess of writer compared to reader. + [FieldOffset(8)] public long DataStart; // <= file size and >= ArrayRangesEnd and >= FileHeader.ByteCount + [FieldOffset(16)] public long DataEnd; // >= DataStart and <= file size + [FieldOffset(24)] public long NumArrays; // number of arrays + + /// + /// This is where the array ranges are finished. + /// Must be less than or equal to DataStart. + /// Must be greater than or equal to FileHeader.ByteCount + /// + public long RangesEnd => Size + NumArrays * 16; + + /// + /// The size of the FileHeader structure + /// + public static long Size = 32; + + /// + /// Returns true if the producer of the BFast file has the same endianness as the current library + /// + public bool SameEndian => Magic == Constants.SameEndian; + + public override bool Equals(object x) + => x is BFastPreamble other && Equals(other); + + public bool Equals(BFastPreamble other) + => Magic == other.Magic && DataStart == other.DataStart && DataEnd == other.DataEnd && NumArrays == other.NumArrays; + }; +} diff --git a/src/cs/bfast/Vim.BFast.Next/BFastNext.cs b/src/cs/bfast/Vim.BFast.Next/BFastNext.cs index dfaf2666..413362cd 100644 --- a/src/cs/bfast/Vim.BFast.Next/BFastNext.cs +++ b/src/cs/bfast/Vim.BFast.Next/BFastNext.cs @@ -3,8 +3,6 @@ using System.IO; using System.IO.Compression; using System.Linq; -using System.Xml.Linq; -using Vim.BFast; namespace Vim.BFastNextNS { diff --git a/src/cs/bfast/Vim.BFast.Next/BFastNextNode.cs b/src/cs/bfast/Vim.BFast.Next/BFastNextNode.cs index 9ab92b1b..293a87f0 100644 --- a/src/cs/bfast/Vim.BFast.Next/BFastNextNode.cs +++ b/src/cs/bfast/Vim.BFast.Next/BFastNextNode.cs @@ -1,107 +1,13 @@ using System; using System.Collections.Generic; using System.IO; -using System.Linq; -using System.Runtime.InteropServices.ComTypes; -using Vim.BFast; namespace Vim.BFastNextNS { - - public class BFastEnumerableNode : IBFastNextNode where TNode: unmanaged - { - private Func> _source; - public BFastEnumerableNode(Func> source) - { - _source = source; - } - - private BFastNextNode AsMemNode() - => BFastNextNode.FromArray(_source().ToArray()); - - public T[] AsArray() where T : unmanaged - => AsMemNode().AsArray(); - - public BFastNext AsBFast() => AsMemNode().AsBFast(); - public IEnumerable AsEnumerable() where T : unmanaged - { - var stream = new MemoryStream(); - var array = new T[1048576]; - var chunks = Chunkify(_source(), 1048576); - while (chunks.MoveNext()) - { - (var chunk, var chunkSize) = chunks.Current; - stream.Seek(0, SeekOrigin.Begin); - stream.Write(chunk, chunkSize); - var count = ReadArray(stream, array); - - if (count > 0) - { - for( var i = 0; i < count; i++) - { - yield return array[i]; - } - } - } - } - - static IEnumerator<(T[], int)> Chunkify(IEnumerable source, int chunkSize) - { - var chunk = new T[chunkSize]; - var index = 0; - - foreach (var item in source) - { - chunk[index++] = item; - - if (index == chunkSize) - { - yield return (chunk, index); - index = 0; - } - } - - if (index > 0) - { - yield return (chunk, index); - } - } - - // Function is extracted because unsafe code cannot appear in generator - private unsafe int ReadArray(MemoryStream stream, T[] array) where T : unmanaged - { - var length = (int)stream.Position; - if (length < sizeof(T)) - { - return 0; - } - - var count = length / sizeof(T); - stream.Seek(0, SeekOrigin.Begin); - stream.ReadArray(array, count); - return count; - } - - public unsafe long GetSize() => _source().Count() * sizeof(TNode); - public void Write(Stream stream) - { - //TODO: Use bigger chunks - var array = new TNode[1]; - foreach(var value in _source()) - { - array[0] = value; - stream.Write(array); - } - } - } - - - public class BFastNextNode : IBFastNextNode { private readonly Stream _stream; private readonly BFastRange _range; - private Action _cleanUp; public static BFastNextNode FromArray(T[] array) where T : unmanaged { @@ -172,7 +78,5 @@ private static void CopyStream(Stream input, Stream output, int bytes) bytes -= read; } } - - } } diff --git a/src/cs/bfast/Vim.BFast.Next/BufferExtensions.cs b/src/cs/bfast/Vim.BFast.Next/BufferExtensions.cs new file mode 100644 index 00000000..eb0bb91f --- /dev/null +++ b/src/cs/bfast/Vim.BFast.Next/BufferExtensions.cs @@ -0,0 +1,89 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; + +namespace Vim.BFastNextNS +{ + /// + /// Helper functions for working with buffers + /// + public static class BufferExtensions + { + public static Buffer ToBuffer(this T[] xs) where T : unmanaged + => new Buffer(xs); + + public static NamedBuffer ToNamedBuffer(this T[] xs, string name = "") where T : unmanaged + => new NamedBuffer(xs, name); + + public static NamedBuffer ToNamedBuffer(this IBuffer buffer, string name = "") + => new NamedBuffer(buffer, name); + + public static NamedBuffer ToNamedBuffer(this IBuffer xs, string name = "") where T : unmanaged + => new NamedBuffer(xs.GetTypedData(), name); + + public static IEnumerable ToNamedBuffers(this IEnumerable buffers, IEnumerable names = null) + => names == null ? buffers.Select(b => b.ToNamedBuffer("")) : buffers.Zip(names, ToNamedBuffer); + + public static IDictionary ToDictionary(this IEnumerable buffers) + => buffers.ToDictionary(b => b.Name, b => b); + + public static IEnumerable ToNamedBuffers(this IDictionary d) + => d.Select(kv => kv.Value.ToNamedBuffer(kv.Key)); + + public static IEnumerable ToNamedBuffers(this IDictionary d) + => d.Select(kv => kv.Value.ToNamedBuffer(kv.Key)); + + public static Array CopyBytes(this IBuffer src, Array dst, int srcOffset = 0, int destOffset = 0) + { + Buffer.BlockCopy(src.Data, srcOffset, dst, destOffset, (int)src.NumBytes()); + return dst; + } + + public static byte[] ToBytes(this IBuffer src, byte[] dest = null) + => src.ToArray(dest); + + public static byte[] ToBytes(this T[] xs, byte[] dest = null) where T : unmanaged + => xs.RecastArray(dest); + + public static byte[] ToBytes(this T x) where T : unmanaged + => ToBytes(new[] { x }); + + /// + /// Accepts an array of the given type, or creates one if necessary, copy the buffer data into it + /// + public static unsafe T[] ToArray(this IBuffer buffer, T[] dest = null) where T : unmanaged + => (T[])buffer.CopyBytes(dest ?? new T[buffer.NumBytes() / sizeof(T)]); + + /// + /// Returns the array in the buffer, if it is of the correct type, or creates a new array of the create type and copies + /// bytes into it, as necessary. + /// + public static unsafe T[] AsArray(this IBuffer buffer) where T : unmanaged + => buffer.Data is T[] r ? r : buffer.ToArray(); + + /// + /// Copies an array of unmanaged types into another array of unmanaged types + /// + public static unsafe U[] RecastArray(this T[] src, U[] r = null) where T : unmanaged where U : unmanaged + => src.ToBuffer().ToArray(r); + + public static int NumElements(this IBuffer buffer) + => buffer.Data.Length; + + public static long NumBytes(this IBuffer buffer) + => (long)buffer.NumElements() * buffer.ElementSize; + + public static Buffer ReadBufferFromNumberOfBytes(this Stream stream, long numBytes) where T : unmanaged + => stream.ReadArrayFromNumberOfBytes(numBytes).ToBuffer(); + + public static Buffer ReadBuffer(this Stream stream, int numElements) where T : unmanaged + => stream.ReadArray(numElements).ToBuffer(); + + public static Buffer ReadBuffer(this Stream stream, int numBytes) + => stream.ReadBuffer(numBytes); + + public static void Write(this Stream stream, IBuffer buffer) + => buffer.Write(stream); + } +} diff --git a/src/cs/bfast/Vim.BFast.Next/Buffers.cs b/src/cs/bfast/Vim.BFast.Next/Buffers.cs new file mode 100644 index 00000000..8a2949e5 --- /dev/null +++ b/src/cs/bfast/Vim.BFast.Next/Buffers.cs @@ -0,0 +1,77 @@ +using System; +using System.IO; + +namespace Vim.BFastNextNS +{ + /// + /// Provides an interface to an object that manages a potentially large array of elements all of the same unmanaged type. + /// + public interface IBuffer + { + Array Data { get; } + int ElementSize { get; } + void Write(Stream stream); + } + + /// + /// A version of the IBuffer interface when the element types are known + /// + public interface IBuffer : IBuffer + { + T[] GetTypedData(); + } + + /// + /// Represents a buffer associated with a string name. + /// + public interface INamedBuffer : IBuffer + { + string Name { get; } + } + + /// + /// A version of the INamedBuffer interface when the element types are known + /// + public interface INamedBuffer : INamedBuffer, IBuffer + { + } + + /// + /// A concrete implementation of IBuffer + /// + public unsafe class Buffer : IBuffer where T : unmanaged + { + public Buffer(T[] data) => Data = data; + public int ElementSize => sizeof(T); + public Array Data { get; } + public T[] GetTypedData() => Data as T[]; + public void Write(Stream stream) => stream.Write(GetTypedData()); + } + + /// + /// A concrete implementation of INamedBuffer + /// + public class NamedBuffer : INamedBuffer + { + public NamedBuffer(IBuffer buffer, string name) => (Buffer, Name) = (buffer, name); + public IBuffer Buffer { get; } + public string Name { get; } + public int ElementSize => Buffer.ElementSize; + public Array Data => Buffer.Data; + public void Write(Stream stream) => Buffer.Write(stream); + } + + /// + /// A concrete implementation of INamedBuffer with a specific type. + /// + public class NamedBuffer : INamedBuffer where T : unmanaged + { + public NamedBuffer(T[] data, string name) => (Array, Name) = (data, name); + public string Name { get; } + public unsafe int ElementSize => sizeof(T); + public readonly T[] Array; + public Array Data => Array; + public T[] GetTypedData() => Array; + public void Write(Stream stream) => stream.Write(Array); + } +} diff --git a/src/cs/bfast/Vim.BFast.Next/UnsafeHelpers.cs b/src/cs/bfast/Vim.BFast.Next/UnsafeHelpers.cs new file mode 100644 index 00000000..96b0bec1 --- /dev/null +++ b/src/cs/bfast/Vim.BFast.Next/UnsafeHelpers.cs @@ -0,0 +1,175 @@ +using System; +using System.IO; + +namespace Vim.BFastNextNS +{ + /// + /// This class would benefit from being in a generic utilities class, however, having it here allows BFAST to be a standalone without dependencies. + /// + public static class UnsafeHelpers + { + /// + /// Helper for reading arbitrary unmanaged types from a Stream. + /// + public static unsafe void ReadBytesBuffered(this Stream stream, byte* dest, long count, int bufferSize = 4096) + { + var buffer = new byte[bufferSize]; + int bytesRead; + fixed (byte* pBuffer = buffer) + { + while ((bytesRead = stream.Read(buffer, 0, (int)Math.Min(buffer.Length, count))) > 0) + { + if (dest != null) + Buffer.MemoryCopy(pBuffer, dest, count, bytesRead); + count -= bytesRead; + dest += bytesRead; + } + } + } + + /// + /// Helper for writing arbitrary large numbers of bytes + /// + public static unsafe void WriteBytesBuffered(this Stream stream, byte* src, long count, int bufferSize = 4096) + { + var buffer = new byte[bufferSize]; + fixed (byte* pBuffer = buffer) + { + while (count > 0) + { + var toWrite = (int)Math.Min(count, buffer.Length); + Buffer.MemoryCopy(src, pBuffer, buffer.Length, toWrite); + stream.Write(buffer, 0, toWrite); + count -= toWrite; + src += toWrite; + } + } + } + + /// + /// Helper for reading arbitrary unmanaged types from a Stream. + /// + public static unsafe void Read(this Stream stream, T* dest) where T : unmanaged + => stream.ReadBytesBuffered((byte*)dest, sizeof(T)); + + /// + /// Helper for reading arrays of arbitrary unmanaged types from a Stream, that might be over 2GB of size. + /// That said, in C#, you can never load more int.MaxValue numbers of items. + /// NOTE: Arrays are still limited to 2gb in size unless gcAllowVeryLargeObjects is set to true + /// in the runtime environment. + /// https://docs.microsoft.com/en-us/dotnet/api/system.array?redirectedfrom=MSDN&view=netframework-4.7.2#remarks + /// Alternatively, we could convert to .Net Core + /// + public static unsafe T[] ReadArray(this Stream stream, int count) where T : unmanaged + { + var r = new T[count]; + fixed (T* pDest = r) + { + + var pBytes = (byte*)pDest; + stream.ReadBytesBuffered(pBytes, (long)count * sizeof(T)); + } + return r; + } + + public static unsafe void ReadArray(this Stream stream, T[] array, int count) where T : unmanaged + { + fixed (T* pDest = array) + { + var pBytes = (byte*)pDest; + stream.ReadBytesBuffered(pBytes, (long)count * sizeof(T)); + } + } + + + /// + /// Equivalent to ReadArray to use when you know the byte count instead of element count. + /// + public static unsafe T[] ReadArrayBytes(this Stream stream, int byteLength) where T : unmanaged + { + return ReadArray(stream, byteLength / sizeof(T)); + } + + /* + public static unsafe T[] ConvertByteArrayToTypeArray(byte[] byteArray) where T : unmanaged + { + if (byteArray.Length % sizeof(T) != 0) + { + throw new ArgumentException("Byte array length is not a multiple of the size of the target type."); + } + + var elementCount = byteArray.Length / sizeof(T); + var resultArray = new T[elementCount]; + + fixed (byte* bytePtr = byteArray) + { + byte* currentBytePtr = bytePtr; + fixed (T* resultPtr = resultArray) + { + var currentResultPtr = resultPtr; + for (var i = 0; i < elementCount; i++) + { + *currentResultPtr = *((T*)currentBytePtr); + currentBytePtr += sizeof(T); + currentResultPtr++; + } + } + } + + return resultArray; + } + + */ + /// + /// A wrapper for stream.Seek(numBytes, SeekOrigin.Current) to avoid allocating memory for unrecognized buffers. + /// + public static void SkipBytes(this Stream stream, long numBytes) + => stream.Seek(numBytes, SeekOrigin.Current); + + /// + /// Helper for reading arrays of arbitrary unmanaged types from a Stream, that might be over 2GB of size. + /// That said, in C#, you can never load more int.MaxValue numbers of items. + /// + public static unsafe T[] ReadArrayFromNumberOfBytes(this Stream stream, long numBytes) where T : unmanaged + { + var count = numBytes / sizeof(T); + if (numBytes % sizeof(T) != 0) + throw new Exception($"The number of bytes {numBytes} is not divisible by the size of the type {sizeof(T)}"); + if (count >= int.MaxValue) + throw new Exception($"{count} exceeds the maximum number of items that can be read into an array {int.MaxValue}"); + return stream.ReadArray((int)count); + } + + /// + /// Helper for writing arbitrary unmanaged types + /// + public static unsafe void WriteValue(this Stream stream, T x) where T : unmanaged + { + var p = &x; + stream.WriteBytesBuffered((byte*)p, sizeof(T)); + } + + + /// + /// Helper for writing arrays of unmanaged types + /// + public static unsafe void Write(this Stream stream, T[] xs) where T : unmanaged + { + fixed (T* p = xs) + { + stream.WriteBytesBuffered((byte*)p, xs.LongLength * sizeof(T)); + } + } + + /// + /// Helper for writing arrays of unmanaged types + /// + public static unsafe void Write(this Stream stream, T[] xs, long count) where T : unmanaged + { + fixed (T* p = xs) + { + stream.WriteBytesBuffered((byte*)p, count * sizeof(T)); + } + } + } +} diff --git a/src/cs/bfast/Vim.BFast/BFast.cs b/src/cs/bfast/Vim.BFast/BFast.cs index e3a26b91..cbbb6eea 100644 --- a/src/cs/bfast/Vim.BFast/BFast.cs +++ b/src/cs/bfast/Vim.BFast/BFast.cs @@ -55,6 +55,7 @@ public static long ComputePadding(long n) public static long ComputePadding(BFastRange[] ranges) => ComputePadding(BFastPreamble.Size + ranges.Length * BFastRange.Size); + /// /// Given a position in the stream, tells us whether the position is aligned. /// diff --git a/src/cs/g3d/Vim.G3dNext.Attributes/Attributes.g.cs b/src/cs/g3d/Vim.G3dNext.Attributes/Attributes.g.cs index 3f909574..cdff39ea 100644 --- a/src/cs/g3d/Vim.G3dNext.Attributes/Attributes.g.cs +++ b/src/cs/g3d/Vim.G3dNext.Attributes/Attributes.g.cs @@ -4,7 +4,6 @@ using System.IO; using System.Collections.Generic; using System.Linq; -using Vim.BFast; using Vim.BFastNextNS; namespace Vim.G3dNext.Attributes diff --git a/src/cs/g3d/Vim.G3dNext.Attributes/G3dVim.cs b/src/cs/g3d/Vim.G3dNext.Attributes/G3dVim.cs index dbd84962..e803a976 100644 --- a/src/cs/g3d/Vim.G3dNext.Attributes/G3dVim.cs +++ b/src/cs/g3d/Vim.G3dNext.Attributes/G3dVim.cs @@ -1,5 +1,4 @@ using System; -using Vim.BFast; using Vim.BFastNextNS; namespace Vim.G3dNext.Attributes diff --git a/src/cs/g3d/Vim.G3dNext/IAttributeCollection.cs b/src/cs/g3d/Vim.G3dNext/IAttributeCollection.cs index c1785aae..60e9483e 100644 --- a/src/cs/g3d/Vim.G3dNext/IAttributeCollection.cs +++ b/src/cs/g3d/Vim.G3dNext/IAttributeCollection.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using Vim.BFast; using Vim.BFastNextNS; namespace Vim.G3dNext diff --git a/src/cs/vim/Vim.Format.Core/AssetInfo.cs b/src/cs/vim/Vim.Format.Core/AssetInfo.cs index 303c5d27..e2c021c0 100644 --- a/src/cs/vim/Vim.Format.Core/AssetInfo.cs +++ b/src/cs/vim/Vim.Format.Core/AssetInfo.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; using System.IO; -using Vim.BFast; +using Vim.BFastNextNS; using Vim.Util; using Vim.LinqArray; diff --git a/src/cs/vim/Vim.Format.Core/BigG3dWriter.cs b/src/cs/vim/Vim.Format.Core/BigG3dWriter.cs deleted file mode 100644 index e70ac297..00000000 --- a/src/cs/vim/Vim.Format.Core/BigG3dWriter.cs +++ /dev/null @@ -1,210 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Vim.G3d; -using Vim.BFast; -using System.IO; -using static Vim.Format.DocumentBuilder; - -namespace Vim.Format -{ - /// - /// This is a helper class for writing the really big G3Ds needed in a VIM - /// - public class BigG3dWriter : IBFastComponent - { - public INamedBuffer Meta { get; } - public string[] Names { get; } - public long[] Sizes { get; } - public BFastHeader Header { get; } - public List Meshes { get; } - public List Instances { get; } - public List Shapes { get; } - public List Materials { get; } - - // Computed fields - public int[] MeshVertexOffsets { get; } - public int[] MeshIndexOffsets { get; } - public int[] MeshSubmeshOffset { get; } - public int[] SubmeshIndexOffsets { get; } - public int[] ShapeVertexOffsets { get; } - - public BigG3dWriter(List meshes, List instances, List shapes, List materials, G3dHeader? header = null, bool useColors = false) - { - Meshes = meshes; - Instances = instances; - Shapes = shapes; - Materials = materials; - var totalSubmeshCount = meshes.Select(s => s.SubmeshesIndexOffset.Count).Sum(); - - // Compute the Vertex offsets and index offsets - MeshVertexOffsets = new int[meshes.Count]; - MeshIndexOffsets = new int[meshes.Count]; - SubmeshIndexOffsets = new int[totalSubmeshCount]; - MeshSubmeshOffset = new int[meshes.Count]; - - var n = meshes.Count; - - for (var i = 1; i < n; ++i) - { - MeshVertexOffsets[i] = MeshVertexOffsets[i - 1] + meshes[i - 1].Vertices.Count; - MeshIndexOffsets[i] = MeshIndexOffsets[i - 1] + meshes[i - 1].Indices.Count; - MeshSubmeshOffset[i] = MeshSubmeshOffset[i - 1] + meshes[i - 1].SubmeshesIndexOffset.Count; - } - - var subIndex =0; - var previousIndexCount = 0; - foreach(var geo in meshes) - { - foreach(var sub in geo.SubmeshesIndexOffset) - { - SubmeshIndexOffsets[subIndex++] = sub + previousIndexCount; - } - previousIndexCount += geo.Indices.Count; - } - - var submeshCount = meshes.Select(s => s.SubmeshesIndexOffset.Count).Sum(); - - var totalVertices = n == 0 ? 0 : MeshVertexOffsets[n - 1] + meshes[n - 1].Vertices.Count; - var totalIndices = n == 0 ? 0 : MeshIndexOffsets[n - 1] + meshes[n - 1].Indices.Count; - long totalFaces = totalIndices / 3; - - // Compute the shape vertex offsets - var numShapes = shapes.Count; - ShapeVertexOffsets = new int[numShapes]; - for (var i = 1; i < numShapes; ++i) - { - ShapeVertexOffsets[i] = ShapeVertexOffsets[i - 1] + shapes[i - 1].Vertices.Count; - } - var numShapeVertices = numShapes == 0 ? 0 : ShapeVertexOffsets[numShapes - 1] + shapes[numShapes - 1].Vertices.Count; - - Meta = (header ?? G3dHeader.Default).ToBytes().ToNamedBuffer("meta"); - - (long size, string name) AttributeSizeAndName(string attributeName, long count) - => (AttributeDescriptor.Parse(attributeName).DataElementSize * count, attributeName); - - var writers = new List<(long size, string attribute)>() - { - (Meta.NumBytes(), Meta.Name), - AttributeSizeAndName(CommonAttributes.Position, totalVertices), - AttributeSizeAndName(CommonAttributes.Index, totalIndices), - - AttributeSizeAndName(CommonAttributes.MeshSubmeshOffset, meshes.Count), - AttributeSizeAndName(CommonAttributes.SubmeshIndexOffset, submeshCount), - AttributeSizeAndName(CommonAttributes.SubmeshMaterial, submeshCount), - - AttributeSizeAndName(CommonAttributes.InstanceTransform, instances.Count), - AttributeSizeAndName(CommonAttributes.InstanceParent, instances.Count), - AttributeSizeAndName(CommonAttributes.InstanceMesh, instances.Count), - AttributeSizeAndName(CommonAttributes.InstanceFlags, instances.Count), - - AttributeSizeAndName(CommonAttributes.ShapeVertex, numShapeVertices), - AttributeSizeAndName(CommonAttributes.ShapeVertexOffset, numShapes), - AttributeSizeAndName(CommonAttributes.ShapeColor, numShapes), - AttributeSizeAndName(CommonAttributes.ShapeWidth, numShapes), - - AttributeSizeAndName(CommonAttributes.MaterialColor, materials.Count), - AttributeSizeAndName(CommonAttributes.MaterialGlossiness, materials.Count), - AttributeSizeAndName(CommonAttributes.MaterialSmoothness, materials.Count), - }; - - if (useColors) - { - writers.Add(AttributeSizeAndName(CommonAttributes.VertexColor, totalVertices)); - } - - Names = writers.Select(w => w.attribute).ToArray(); - Sizes = writers.Select(w => w.size).ToArray(); - Header = BFast.BFast.CreateBFastHeader(Sizes, Names); - } - - public long GetSize() - => BFast.BFast.ComputeNextAlignment(Header.Preamble.DataEnd); - - public void Write(Stream stream) - { - // TODO: validate in debug mode that this is producing the current data model. Look at the schema! - - stream.WriteBFastHeader(Header); - stream.WriteBFastBody(Header, Names, Sizes, (_stream, index, name, size) => - { - switch (name) - { - case "meta": - _stream.Write(Meta); - break; - - // Vertices - case CommonAttributes.Position: - Meshes.ForEach(g => stream.Write(g.Vertices.ToArray())); - break; - - // Indices - case CommonAttributes.Index: - for (var i = 0; i < Meshes.Count; ++i) - { - var g = Meshes[i]; - var offset = MeshVertexOffsets[i]; - stream.Write(g.Indices.Select(idx => idx + offset).ToArray()); - } - break; - - // Meshes - case CommonAttributes.MeshSubmeshOffset: - stream.Write(MeshSubmeshOffset); - break; - - // Instances - case CommonAttributes.InstanceMesh: - stream.Write(Instances.Select(i => i.MeshIndex).ToArray()); - break; - case CommonAttributes.InstanceTransform: - stream.Write(Instances.Select(i => i.Transform).ToArray()); - break; - case CommonAttributes.InstanceParent: - stream.Write(Instances.Select(i => i.ParentIndex).ToArray()); - break; - case CommonAttributes.InstanceFlags: - stream.Write(Instances.Select(i => (ushort) i.InstanceFlags).ToArray()); - break; - - // Shapes - case CommonAttributes.ShapeVertex: - stream.Write(Shapes.SelectMany(s => s.Vertices).ToArray()); - break; - case CommonAttributes.ShapeVertexOffset: - stream.Write(ShapeVertexOffsets); - break; - case CommonAttributes.ShapeColor: - stream.Write(Shapes.Select(s => s.Color).ToArray()); - break; - case CommonAttributes.ShapeWidth: - stream.Write(Shapes.Select(s => s.Width).ToArray()); - break; - - // Materials - case CommonAttributes.MaterialColor: - stream.Write(Materials.Select(i => i.Color).ToArray()); - break; - case CommonAttributes.MaterialGlossiness: - stream.Write(Materials.Select(i => i.Glossiness).ToArray()); - break; - case CommonAttributes.MaterialSmoothness: - stream.Write(Materials.Select(i => i.Smoothness).ToArray()); - break; - - // Submeshes - case CommonAttributes.SubmeshIndexOffset: - stream.Write(SubmeshIndexOffsets); - break; - case CommonAttributes.SubmeshMaterial: - stream.Write(Meshes.SelectMany(s => s.SubmeshMaterials).ToArray()); - break; - default: - throw new Exception($"Not a recognized geometry buffer: {name}"); - } - return size; - }); - } - } -} diff --git a/src/cs/vim/Vim.Format.Core/BigG3dWriter2.cs b/src/cs/vim/Vim.Format.Core/BigG3dWriter2.cs deleted file mode 100644 index 2beaa36b..00000000 --- a/src/cs/vim/Vim.Format.Core/BigG3dWriter2.cs +++ /dev/null @@ -1,83 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using Vim.G3d; -using Vim.BFast; -using Vim.BFastNextNS; -using System.IO; -using static Vim.Format.DocumentBuilder; -using Vim.Math3d; - -namespace Vim.Format -{ - /// - /// This is a helper class for writing the really big G3Ds needed in a VIM - /// - public class BigG3dWriter2 : IBFastComponent - { - BFastNext bfast; - - public BigG3dWriter2(List meshes, List instances, List shapes, List materials, G3dHeader? header = null, bool useColors = false) - { - var totalSubmeshCount = meshes.Select(s => s.SubmeshesIndexOffset.Count).Sum(); - - // Compute the Vertex offsets and index offsets - var meshVertexOffsets = new int[meshes.Count]; - var meshIndexOffsets = new int[meshes.Count]; - var submeshIndexOffsets = new int[totalSubmeshCount]; - var meshSubmeshOffset = new int[meshes.Count]; - - var n = meshes.Count; - - for (var i = 1; i < n; ++i) - { - meshVertexOffsets[i] = meshVertexOffsets[i - 1] + meshes[i - 1].Vertices.Count; - meshIndexOffsets[i] = meshIndexOffsets[i - 1] + meshes[i - 1].Indices.Count; - meshSubmeshOffset[i] = meshSubmeshOffset[i - 1] + meshes[i - 1].SubmeshesIndexOffset.Count; - } - - var subIndex = 0; - var previousIndexCount = 0; - foreach (var geo in meshes) - { - foreach (var sub in geo.SubmeshesIndexOffset) - { - submeshIndexOffsets[subIndex++] = sub + previousIndexCount; - } - previousIndexCount += geo.Indices.Count; - } - - // Compute the shape vertex offsets - var numShapes = shapes.Count; - var shapeVertexOffsets = new int[numShapes]; - for (var i = 1; i < numShapes; ++i) - { - shapeVertexOffsets[i] = shapeVertexOffsets[i - 1] + shapes[i - 1].Vertices.Count; - } - - bfast = new BFastNext(); - bfast.SetArray("Meta", G3dHeader.Default.ToBytes()); - - bfast.SetEnumerable(CommonAttributes.Position, () => meshes.SelectMany(m => m.Vertices)); - bfast.SetEnumerable(CommonAttributes.Index, () => meshes.SelectMany(m => m.Indices)); - bfast.SetEnumerable(CommonAttributes.MeshSubmeshOffset, () => meshSubmeshOffset); - bfast.SetEnumerable(CommonAttributes.SubmeshIndexOffset, () => submeshIndexOffsets); - bfast.SetEnumerable(CommonAttributes.SubmeshMaterial, () => meshes.SelectMany(s => s.SubmeshMaterials)); - bfast.SetEnumerable(CommonAttributes.InstanceFlags, () => instances.Select(i => (ushort)i.InstanceFlags)); - bfast.SetEnumerable(CommonAttributes.InstanceParent, () => instances.Select(i => i.ParentIndex)); - bfast.SetEnumerable(CommonAttributes.InstanceMesh, () => instances.Select(i => i.MeshIndex)); - bfast.SetEnumerable(CommonAttributes.InstanceTransform, () => instances.Select(i => i.Transform)); - bfast.SetEnumerable(CommonAttributes.ShapeVertex, () => shapes.SelectMany(s => s.Vertices)); - bfast.SetEnumerable(CommonAttributes.ShapeVertexOffset, () => shapeVertexOffsets); - bfast.SetEnumerable(CommonAttributes.ShapeColor, () => shapes.Select(s => s.Color)); - bfast.SetEnumerable(CommonAttributes.ShapeWidth, () => shapes.Select(s => s.Width)); - bfast.SetEnumerable(CommonAttributes.MaterialColor, () => materials.Select(i => i.Color)); - bfast.SetEnumerable(CommonAttributes.MaterialGlossiness, () => materials.Select(i => i.Glossiness)); - bfast.SetEnumerable(CommonAttributes.MaterialSmoothness, () => materials.Select(i => i.Smoothness)); - } - - public long GetSize() - => bfast.GetSize(); - - public void Write(Stream stream) => bfast.Write(stream); - } -} diff --git a/src/cs/vim/Vim.Format.Core/ColumnExtensions.Buffer.cs b/src/cs/vim/Vim.Format.Core/ColumnExtensions.Buffer.cs index 7e1d8ac0..ff0ddcf2 100644 --- a/src/cs/vim/Vim.Format.Core/ColumnExtensions.Buffer.cs +++ b/src/cs/vim/Vim.Format.Core/ColumnExtensions.Buffer.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; -using Vim.BFast; +using Vim.BFastNextNS; using Vim.LinqArray; namespace Vim.Format diff --git a/src/cs/vim/Vim.Format.Core/Document.cs b/src/cs/vim/Vim.Format.Core/Document.cs index 476bd8e7..c16d83b6 100644 --- a/src/cs/vim/Vim.Format.Core/Document.cs +++ b/src/cs/vim/Vim.Format.Core/Document.cs @@ -1,5 +1,5 @@ using Vim.LinqArray; -using Vim.BFast; +using Vim.BFastNextNS; namespace Vim.Format { @@ -19,7 +19,7 @@ public Document(SerializableDocument document) } public string FileName => _Document.FileName; - private SerializableDocument _Document { get; } + public SerializableDocument _Document { get; } public SerializableHeader Header { get; } public ILookup EntityTables { get; } public ILookup Assets { get; } diff --git a/src/cs/vim/Vim.Format.Core/DocumentBuilder.cs b/src/cs/vim/Vim.Format.Core/DocumentBuilder.cs index 08407a89..0090a43c 100644 --- a/src/cs/vim/Vim.Format.Core/DocumentBuilder.cs +++ b/src/cs/vim/Vim.Format.Core/DocumentBuilder.cs @@ -3,11 +3,13 @@ using System.Diagnostics; using System.Linq; using Vim.Math3d; -using Vim.BFast; +using Vim.BFastNextNS; using System.IO; using Vim.Util; using Vim.BFastNextNS; using System.Runtime.InteropServices.ComTypes; +using static Vim.Format.DocumentBuilder; +using Vim.Format.Geometry; namespace Vim.Format { @@ -16,10 +18,7 @@ public partial class DocumentBuilder public readonly SerializableHeader Header; public readonly Dictionary Tables = new Dictionary(); public readonly Dictionary Assets = new Dictionary(); - public readonly List Meshes = new List(); - public readonly List Instances = new List(); - public readonly List Shapes = new List(); - public readonly List Materials = new List(); + public readonly G3dBuilder Geometry = new G3dBuilder(); public bool UseColors { get; set; } @@ -53,51 +52,64 @@ public DocumentBuilder AddAsset(string name, byte[] asset) return this; } - public DocumentBuilder AddMesh(SubdividedMesh g) + public DocumentBuilder AddMesh(SubdividedMesh mesh) { - Meshes.Add(g); + Geometry.AddMesh(mesh); return this; } - public DocumentBuilder AddMeshes(IEnumerable gb) + public DocumentBuilder AddMeshes(IEnumerable meshes) { - Meshes.AddRange(gb); + foreach (var m in meshes) + { + AddMesh(m); + } return this; } - public DocumentBuilder AddInstances(IEnumerable ib) + public DocumentBuilder AddInstances(IEnumerable instances) { - Instances.AddRange(ib); + foreach (var m in instances) + { + Geometry.AddInstance(m); + } return this; } - public DocumentBuilder AddMaterials(IEnumerable mb) + + public DocumentBuilder AddInstance(Matrix4x4 transform, int meshIndex, int parentIndex = -1) { - Materials.AddRange(mb); + var instance = new Instance() + { + Transform = transform, + MeshIndex = meshIndex, + ParentIndex = parentIndex + }; + Geometry.AddInstance(instance); return this; } - public DocumentBuilder AddShapes(IEnumerable sb) + public DocumentBuilder AddMaterials(IEnumerable materials) { - Shapes.AddRange(sb); + foreach (var material in materials) + { + Geometry.AddMaterial(material); + } + return this; + } + + public DocumentBuilder AddShapes(IEnumerable shapes) + { + foreach (var shape in shapes) + { + Geometry.AddShape(shape); + } return this; } public DocumentBuilder AddAsset(INamedBuffer b) => AddAsset(b.Name, b.ToBytes()); - public DocumentBuilder AddInstance(Matrix4x4 transform, int meshIndex, int parentIndex = -1) - { - Instances.Add( - new Instance() - { - Transform = transform, - MeshIndex = meshIndex, - ParentIndex = parentIndex - } - ); - return this; - } public class StringLookupInfo { @@ -136,17 +148,17 @@ public List ComputeEntityTables(IReadOnlyDictionary ComputeEntityTables(IReadOnlyDictionary g.Vertices.Count)); - tb.AddDataColumn("int:FaceCount", Meshes.Select(g => g.Indices.Count / 3)); + tb.AddDataColumn("int:VertexCount", Geometry.GetVertexCounts()); + tb.AddDataColumn("int:FaceCount", Geometry.GetFaceCounts()); } // TODO: add bounding box information to the nodes @@ -208,12 +220,9 @@ public BFastNext ToBFast() }; var bfast = doc.ToBFast(); - var g3d = new BigG3dWriter2(Meshes, Instances, Shapes, Materials, null, UseColors); - bfast.SetBFast(BufferNames.Geometry, g3d.bfast); + bfast.SetBFast(BufferNames.Geometry, Geometry.ToBFast()); return bfast; } - - } } diff --git a/src/cs/vim/Vim.Format.Core/DocumentBuilderExtensions.cs b/src/cs/vim/Vim.Format.Core/DocumentBuilderExtensions.cs index 81e1c2d8..10e6adf7 100644 --- a/src/cs/vim/Vim.Format.Core/DocumentBuilderExtensions.cs +++ b/src/cs/vim/Vim.Format.Core/DocumentBuilderExtensions.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; using System.Linq; -using Vim.BFast; +using Vim.BFastNextNS; using Vim.Format.Geometry; using Vim.G3d; using Vim.LinqArray; diff --git a/src/cs/vim/Vim.Format.Core/DocumentExtensions.cs b/src/cs/vim/Vim.Format.Core/DocumentExtensions.cs index 52e2c5e2..7e1f4f40 100644 --- a/src/cs/vim/Vim.Format.Core/DocumentExtensions.cs +++ b/src/cs/vim/Vim.Format.Core/DocumentExtensions.cs @@ -1,7 +1,7 @@ using System; using System.Text.RegularExpressions; using Vim.LinqArray; -using Vim.BFast; +using Vim.BFastNextNS; namespace Vim.Format { diff --git a/src/cs/vim/Vim.Format.Core/EntityTable.cs b/src/cs/vim/Vim.Format.Core/EntityTable.cs index a9e0b050..9804b79b 100644 --- a/src/cs/vim/Vim.Format.Core/EntityTable.cs +++ b/src/cs/vim/Vim.Format.Core/EntityTable.cs @@ -1,6 +1,6 @@ using System; using System.Diagnostics; -using Vim.BFast; +using Vim.BFastNextNS; using Vim.LinqArray; namespace Vim.Format diff --git a/src/cs/vim/Vim.Format.Core/EntityTableBuilder.cs b/src/cs/vim/Vim.Format.Core/EntityTableBuilder.cs index bd1da0fd..6ade56ae 100644 --- a/src/cs/vim/Vim.Format.Core/EntityTableBuilder.cs +++ b/src/cs/vim/Vim.Format.Core/EntityTableBuilder.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; -using Vim.BFast; +using Vim.BFastNextNS; namespace Vim.Format { diff --git a/src/cs/vim/Vim.Format.Core/G3dBuilder.cs b/src/cs/vim/Vim.Format.Core/G3dBuilder.cs new file mode 100644 index 00000000..2dc19230 --- /dev/null +++ b/src/cs/vim/Vim.Format.Core/G3dBuilder.cs @@ -0,0 +1,116 @@ +using System.Collections.Generic; +using System.Linq; +using Vim.G3d; +using Vim.BFastNextNS; +using static Vim.Format.DocumentBuilder; +using Vim.Math3d; + +namespace Vim.Format +{ + public class G3dBuilder + { + private readonly List _meshes = new List(); + private readonly List _instances = new List(); + private readonly List _shapes = new List(); + private readonly List _materials = new List(); + + public void AddMesh(SubdividedMesh mesh) + { + _meshes.Add(mesh); + } + + public void AddInstance(Instance instance) + { + _instances.Add(instance); + } + + public void AddShape(Shape shape) + { + _shapes.Add(shape); + } + + public void AddMaterial(Material material) + { + _materials.Add(material); + } + public int MeshCount => _meshes.Count; + + public SubdividedMesh GetMesh(int index) => _meshes[index]; + public AABox GetBox(int meshIndex) + { + return AABox.Create(_meshes[meshIndex].Vertices); + } + + public int[] GetVertexCounts() + { + return _meshes.Select(m => m.Vertices.Count).ToArray(); + } + + public int[] GetFaceCounts() + { + return _meshes.Select(m => m.Indices.Count / 3).ToArray(); + } + + + public BFastNext ToBFast() + { + var bfast = new BFastNext(); + var totalSubmeshCount = _meshes.Select(s => s.SubmeshesIndexOffset.Count).Sum(); + + // Compute the Vertex offsets and index offsets + var meshVertexOffsets = new int[_meshes.Count]; + var meshIndexOffsets = new int[_meshes.Count]; + var submeshIndexOffsets = new int[totalSubmeshCount]; + var meshSubmeshOffset = new int[_meshes.Count]; + + var n = _meshes.Count; + + for (var i = 1; i < n; ++i) + { + meshVertexOffsets[i] = meshVertexOffsets[i - 1] + _meshes[i - 1].Vertices.Count; + meshIndexOffsets[i] = meshIndexOffsets[i - 1] + _meshes[i - 1].Indices.Count; + meshSubmeshOffset[i] = meshSubmeshOffset[i - 1] + _meshes[i - 1].SubmeshesIndexOffset.Count; + } + + var subIndex = 0; + var previousIndexCount = 0; + foreach (var geo in _meshes) + { + foreach (var sub in geo.SubmeshesIndexOffset) + { + submeshIndexOffsets[subIndex++] = sub + previousIndexCount; + } + previousIndexCount += geo.Indices.Count; + } + + // Compute the shape vertex offsets + var numShapes = _shapes.Count; + var shapeVertexOffsets = new int[numShapes]; + for (var i = 1; i < numShapes; ++i) + { + shapeVertexOffsets[i] = shapeVertexOffsets[i - 1] + _shapes[i - 1].Vertices.Count; + } + + bfast = new BFastNext(); + bfast.SetArray("Meta", G3dHeader.Default.ToBytes()); + + bfast.SetEnumerable(CommonAttributes.Position, () => _meshes.SelectMany(m => m.Vertices)); + bfast.SetEnumerable(CommonAttributes.Index, () => _meshes.SelectMany(m => m.Indices)); + bfast.SetEnumerable(CommonAttributes.MeshSubmeshOffset, () => meshSubmeshOffset); + bfast.SetEnumerable(CommonAttributes.SubmeshIndexOffset, () => submeshIndexOffsets); + bfast.SetEnumerable(CommonAttributes.SubmeshMaterial, () => _meshes.SelectMany(s => s.SubmeshMaterials)); + bfast.SetEnumerable(CommonAttributes.InstanceFlags, () => _instances.Select(i => (ushort)i.InstanceFlags)); + bfast.SetEnumerable(CommonAttributes.InstanceParent, () => _instances.Select(i => i.ParentIndex)); + bfast.SetEnumerable(CommonAttributes.InstanceMesh, () => _instances.Select(i => i.MeshIndex)); + bfast.SetEnumerable(CommonAttributes.InstanceTransform, () => _instances.Select(i => i.Transform)); + bfast.SetEnumerable(CommonAttributes.ShapeVertex, () => _shapes.SelectMany(s => s.Vertices)); + bfast.SetEnumerable(CommonAttributes.ShapeVertexOffset, () => shapeVertexOffsets); + bfast.SetEnumerable(CommonAttributes.ShapeColor, () => _shapes.Select(s => s.Color)); + bfast.SetEnumerable(CommonAttributes.ShapeWidth, () => _shapes.Select(s => s.Width)); + bfast.SetEnumerable(CommonAttributes.MaterialColor, () => _materials.Select(i => i.Color)); + bfast.SetEnumerable(CommonAttributes.MaterialGlossiness, () => _materials.Select(i => i.Glossiness)); + bfast.SetEnumerable(CommonAttributes.MaterialSmoothness, () => _materials.Select(i => i.Smoothness)); + return bfast; + } + } +} diff --git a/src/cs/vim/Vim.Format.Core/Geometry/Validation.cs b/src/cs/vim/Vim.Format.Core/Geometry/Validation.cs index 5ccca143..8904c954 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/Validation.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/Validation.cs @@ -1,6 +1,6 @@ using System; using System.Collections.Generic; -using Vim.BFast; +using Vim.BFastNextNS; using Vim.G3d; using Vim.LinqArray; diff --git a/src/cs/vim/Vim.Format.Core/SerializableDocument.cs b/src/cs/vim/Vim.Format.Core/SerializableDocument.cs index a1cb5798..f30e1af6 100644 --- a/src/cs/vim/Vim.Format.Core/SerializableDocument.cs +++ b/src/cs/vim/Vim.Format.Core/SerializableDocument.cs @@ -2,9 +2,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using System.Runtime.InteropServices.ComTypes; using System.Text; -using Vim.BFast; using Vim.BFastNextNS; using Vim.G3d; @@ -43,10 +41,25 @@ public IEnumerable ColumnNames .Concat(StringColumns.Select(c => c.Name)) .Concat(DataColumns.Select(c => c.Name)); + public IEnumerable AllColumns + => IndexColumns + .Concat(StringColumns) + .Concat(DataColumns); + public static SerializableEntityTable FromBfast(string name, BFastNext bfast) { return null; } + + public BFastNext ToBFast() + { + var bfast = new BFastNext(); + foreach (var col in AllColumns) + { + bfast.SetArray(col.Name, col.AsArray()); + } + return bfast; + } } /// @@ -113,18 +126,10 @@ public BFastNext ToBFast() var entities = new BFastNext(); foreach (var entity in EntityTables) { - var b = new BFastNext(); - foreach (var buffer in entity.ToBuffers()) - { - b.SetArray(buffer.Name, buffer.ToBytes()); - } - entities.SetBFast(entity.Name, b); - + entities.SetBFast(entity.Name, entity.ToBFast()); } bfast.SetBFast(BufferNames.Entities, entities); - - bfast.SetArray(BufferNames.Strings, StringTable.PackStrings()); - + bfast.SetArray(BufferNames.Strings, PackStrings(StringTable)); bfast.SetArray(BufferNames.Geometry, Geometry.WriteToBytes()); return bfast; } @@ -160,9 +165,107 @@ public static SerializableDocument FromBFast(BFastNext bfast, LoadOptions option } var entities = bfast.GetBFast(BufferNames.Entities); - doc.EntityTables = Serializer.EnumerateEntityTables2(entities, doc.Options.SchemaOnly).ToList(); + doc.EntityTables = GetEntityTables(entities, doc.Options.SchemaOnly).ToList(); return doc; } + /// + /// Enumerates the SerializableEntityTables contained in the given entities buffer. + /// + private static IEnumerable GetEntityTables( + BFastNext bfast, + bool schemaOnly) + { + + foreach (var entry in bfast.Entries) + { + var b = bfast.GetBFast(entry); + var table = ReadEntityTable2(b, schemaOnly); + table.Name = entry; + yield return table; + } + } + + + /// + /// Returns a SerializableEntityTable based on the given buffer reader. + /// + public static SerializableEntityTable ReadEntityTable2( + BFastNext bfast, + bool schemaOnly + ) + { + var et = new SerializableEntityTable(); + foreach (var entry in bfast.Entries) + { + var typePrefix = entry.GetTypePrefix(); + + switch (typePrefix) + { + case VimConstants.IndexColumnNameTypePrefix: + { + //TODO: replace named buffer with arrays + var col = schemaOnly ? new int[0] : bfast.GetArray(entry); + et.IndexColumns.Add(col.ToNamedBuffer(entry)); + break; + } + case VimConstants.StringColumnNameTypePrefix: + { + var col = schemaOnly ? new int[0] : bfast.GetArray(entry); + et.StringColumns.Add(col.ToNamedBuffer(entry)); + break; + } + case VimConstants.IntColumnNameTypePrefix: + { + var col = schemaOnly ? new int[0] : bfast.GetArray(entry); + et.DataColumns.Add(col.ToNamedBuffer(entry)); + break; + } + case VimConstants.LongColumnNameTypePrefix: + { + var col = schemaOnly ? new long[0] : bfast.GetArray(entry); + et.DataColumns.Add(col.ToNamedBuffer(entry)); + break; + } + case VimConstants.DoubleColumnNameTypePrefix: + { + var col = schemaOnly ? new double[0] : bfast.GetArray(entry); + et.DataColumns.Add(col.ToNamedBuffer(entry)); + break; + } + case VimConstants.FloatColumnNameTypePrefix: + { + var col = schemaOnly ? new float[0] : bfast.GetArray(entry); + et.DataColumns.Add(col.ToNamedBuffer(entry)); + break; + } + case VimConstants.ByteColumnNameTypePrefix: + { + var col = schemaOnly ? new byte[0] : bfast.GetArray(entry); + et.DataColumns.Add(col.ToNamedBuffer(entry)); + break; + } + // For flexibility, we ignore the columns which do not contain a recognized prefix. + } + } + + return et; + } + + /// + /// Converts a collection of strings, into a null-separated byte[] array + /// + public static byte[] PackStrings(IEnumerable strings) + { + var r = new List(); + foreach (var name in strings) + { + var bytes = Encoding.UTF8.GetBytes(name); + r.AddRange(bytes); + r.Add(0); + } + return r.ToArray(); + } + } } diff --git a/src/cs/vim/Vim.Format.Core/SerializableHeader.cs b/src/cs/vim/Vim.Format.Core/SerializableHeader.cs index c2739ad5..4e26382b 100644 --- a/src/cs/vim/Vim.Format.Core/SerializableHeader.cs +++ b/src/cs/vim/Vim.Format.Core/SerializableHeader.cs @@ -3,7 +3,7 @@ using System.Globalization; using System.Linq; using System.Text; -using Vim.BFast; +using Vim.BFastNextNS; using Vim.Util; namespace Vim.Format diff --git a/src/cs/vim/Vim.Format.Core/Serializer.cs b/src/cs/vim/Vim.Format.Core/Serializer.cs index ca626201..c763d9e8 100644 --- a/src/cs/vim/Vim.Format.Core/Serializer.cs +++ b/src/cs/vim/Vim.Format.Core/Serializer.cs @@ -1,30 +1,10 @@ -using System.Collections.Generic; -using System.Linq; -using System; -using Vim.BFast; -using System.IO; -using System.Text; -using System.Text.RegularExpressions; -using Vim.G3d; -using Vim.Util; +using System.Text.RegularExpressions; using Vim.BFastNextNS; -using System.Drawing; namespace Vim.Format { public static class Serializer { - public static List ToBuffers(this SerializableEntityTable table) - { - var r = new List(); - - r.AddRange(table.DataColumns); - r.AddRange(table.IndexColumns); - r.AddRange(table.StringColumns); - - return r; - } - public static readonly Regex TypePrefixRegex = new Regex(@"(\w+:).*"); public static string GetTypePrefix(this string name) @@ -39,301 +19,5 @@ public static string GetTypePrefix(this string name) public static string GetTypePrefix(this INamedBuffer namedBuffer) => namedBuffer.Name.GetTypePrefix(); - /// - /// Returns a NamedBuffer representing to an entity table column. - /// If schemaOnly is enabled, the column is returned without any of its contained data; - /// this is useful for rapidly querying the schema of the entity table. - /// - public static NamedBuffer ReadEntityTableColumn( - this BFastBufferReader columnBufferReader, - bool schemaOnly) where T : unmanaged - { - var (name, size) = columnBufferReader; - - if (schemaOnly) - return new Buffer(Array.Empty()).ToNamedBuffer(name); - - return columnBufferReader - .Seek() - .ReadBufferFromNumberOfBytes(size) - .ToNamedBuffer(name); - } - - /// - /// Returns a SerializableEntityTable based on the given buffer reader. - /// - public static SerializableEntityTable ReadEntityTable( - this BFastBufferReader entityTableBufferReader, - bool schemaOnly) - { - var et = new SerializableEntityTable { Name = entityTableBufferReader.Name }; - - foreach (var colBr in entityTableBufferReader.Seek().GetBFastBufferReaders()) - { - var name = colBr.Name; - var typePrefix = name.GetTypePrefix(); - - switch (typePrefix) - { - case VimConstants.IndexColumnNameTypePrefix: - { - et.IndexColumns.Add(colBr.ReadEntityTableColumn(schemaOnly)); - break; - } - case VimConstants.StringColumnNameTypePrefix: - { - et.StringColumns.Add(colBr.ReadEntityTableColumn(schemaOnly)); - break; - } - case VimConstants.IntColumnNameTypePrefix: - { - et.DataColumns.Add(colBr.ReadEntityTableColumn(schemaOnly)); - break; - } - case VimConstants.LongColumnNameTypePrefix: - { - et.DataColumns.Add(colBr.ReadEntityTableColumn(schemaOnly)); - break; - } - case VimConstants.DoubleColumnNameTypePrefix: - { - et.DataColumns.Add(colBr.ReadEntityTableColumn(schemaOnly)); - break; - } - case VimConstants.FloatColumnNameTypePrefix: - { - et.DataColumns.Add(colBr.ReadEntityTableColumn(schemaOnly)); - break; - } - case VimConstants.ByteColumnNameTypePrefix: - { - et.DataColumns.Add(colBr.ReadEntityTableColumn(schemaOnly)); - break; - } - // For flexibility, we ignore the columns which do not contain a recognized prefix. - } - } - - return et; - } - - /// - /// Returns a SerializableEntityTable based on the given buffer reader. - /// - - public static SerializableEntityTable ReadEntityTable2( - BFastNext bfast, - bool schemaOnly - ) - { - var et = new SerializableEntityTable(); - foreach(var entry in bfast.Entries) - { - var typePrefix = entry.GetTypePrefix(); - - switch (typePrefix) - { - case VimConstants.IndexColumnNameTypePrefix: - { - //TODO: replace named buffer with arrays - var col = schemaOnly ? new int[0] : bfast.GetArray(entry); - et.IndexColumns.Add(col.ToNamedBuffer(entry)); - break; - } - case VimConstants.StringColumnNameTypePrefix: - { - var col = schemaOnly ? new int[0] : bfast.GetArray(entry); - et.StringColumns.Add(col.ToNamedBuffer(entry)); - break; - } - case VimConstants.IntColumnNameTypePrefix: - { - var col = schemaOnly ? new int[0] : bfast.GetArray(entry); - et.DataColumns.Add(col.ToNamedBuffer(entry)); - break; - } - case VimConstants.LongColumnNameTypePrefix: - { - var col = schemaOnly ? new long[0] : bfast.GetArray(entry); - et.DataColumns.Add(col.ToNamedBuffer(entry)); - break; - } - case VimConstants.DoubleColumnNameTypePrefix: - { - var col = schemaOnly ? new double[0] : bfast.GetArray(entry); - et.DataColumns.Add(col.ToNamedBuffer(entry)); - break; - } - case VimConstants.FloatColumnNameTypePrefix: - { - var col = schemaOnly ? new float[0] : bfast.GetArray(entry); - et.DataColumns.Add(col.ToNamedBuffer(entry)); - break; - } - case VimConstants.ByteColumnNameTypePrefix: - { - var col = schemaOnly ? new byte[0] : bfast.GetArray(entry); - et.DataColumns.Add(col.ToNamedBuffer(entry)); - break; - } - // For flexibility, we ignore the columns which do not contain a recognized prefix. - } - } - - return et; - } - - - - /// - /// Enumerates the SerializableEntityTables contained in the given entities buffer. - /// - public static IEnumerable EnumerateEntityTables( - this BFastBufferReader entitiesBufferReader, - bool schemaOnly) - { - foreach (var entityTableBufferReader in entitiesBufferReader.Seek().GetBFastBufferReaders()) - { - yield return entityTableBufferReader.ReadEntityTable(schemaOnly); - } - } - - /// - /// Enumerates the SerializableEntityTables contained in the given entities buffer. - /// - public static IEnumerable EnumerateEntityTables2( - BFastNext bfast, - bool schemaOnly) - { - - foreach (var entry in bfast.Entries) - { - var b = bfast.GetBFast(entry); - var table = ReadEntityTable2(b, schemaOnly); - table.Name = entry; - yield return table; - } - } - - /// - /// Enumerates the SerializableEntityTables contained in the given VIM file. - /// - public static IEnumerable EnumerateEntityTables(this FileInfo vimFileInfo, bool schemaOnly) - { - using (var stream = vimFileInfo.OpenRead()) - { - var entitiesBufferReader = stream.GetBFastBufferReaders(b => b.Name == BufferNames.Entities).FirstOrDefault(); - if (entitiesBufferReader == null) - yield break; - - foreach (var entityTable in entitiesBufferReader.EnumerateEntityTables(schemaOnly)) - { - yield return entityTable; - } - } - } - - public static BFastBuilder ToBFastBuilder(this IEnumerable entityTables) - { - var bldr = new BFastBuilder(); - foreach (var et in entityTables) - { - bldr.Add(et.Name, et.ToBuffers()); - } - return bldr; - } - - public static BFastBuilder ToBFastBuilder(this SerializableDocument doc) - => CreateBFastBuilder( - doc.Header, - doc.Assets, - doc.StringTable, - doc.EntityTables, - doc.Geometry.ToG3DWriter()); - - public static BFastBuilder CreateBFastBuilder( - SerializableHeader header, - IEnumerable assets, - IEnumerable stringTable, - IEnumerable entityTables, - IBFastComponent geometry) - { - var bfastBuilder = new BFastBuilder(); - //bfastBuilder.Add(BufferNames.Header, header.ToBytes()); - bfastBuilder.Add(BufferNames.Assets, assets ?? Array.Empty()); - bfastBuilder.Add(BufferNames.Entities, entityTables.ToBFastBuilder()); - bfastBuilder.Add(BufferNames.Strings, stringTable.PackStrings().ToBuffer()); - bfastBuilder.Add(BufferNames.Geometry, geometry); - return bfastBuilder; - } - - public static void Serialize( - Stream stream, - SerializableHeader header, - IEnumerable assets, - IEnumerable stringTable, - IEnumerable entityTables, - IBFastComponent geometry) - { - CreateBFastBuilder(header, assets, stringTable, entityTables, geometry).Write(stream); - } - - - - public static void ReadBuffer(this SerializableDocument doc, BFastBufferReader bufferReader) - { - var (name, numBytes) = bufferReader; - var stream = bufferReader.Seek(); - - switch (name) - { - case BufferNames.Header: - { - doc.Header = SerializableHeader.FromBytes(stream.ReadArray((int)numBytes)); - break; - } - - case BufferNames.Assets: - { - if (doc.Options?.SkipAssets == true) - break; - - doc.Assets = stream.ReadBFast().ToArray(); - break; - } - - case BufferNames.Strings: - { - doc.StringTable = ReadStrings(stream, numBytes); - break; - } - - case BufferNames.Geometry: - { - if (doc.Options?.SkipGeometry == true) - break; - - doc.Geometry = G3D.Read(stream); - break; - } - - case BufferNames.Entities: - { - doc.EntityTables = - bufferReader - .EnumerateEntityTables(doc.Options?.SchemaOnly ?? false) - .ToList(); - break; - } - } - } - - public static string[] ReadStrings(Stream stream, long numBytes) - { - var stringBytes = stream.ReadArray((int)numBytes); - var joinedStringTable = Encoding.UTF8.GetString(stringBytes); - return joinedStringTable.Split('\0'); - } - } } diff --git a/src/cs/vim/Vim.Format.Core/Validation.cs b/src/cs/vim/Vim.Format.Core/Validation.cs index bb5287ab..a4cfd48d 100644 --- a/src/cs/vim/Vim.Format.Core/Validation.cs +++ b/src/cs/vim/Vim.Format.Core/Validation.cs @@ -1,6 +1,6 @@ using System; using System.Collections.Generic; -using Vim.BFast; +using Vim.BFastNextNS; using Vim.G3d; using Vim.LinqArray; diff --git a/src/cs/vim/Vim.Format.Tests/FormatTests.cs b/src/cs/vim/Vim.Format.Tests/FormatTests.cs index 990b3d08..2faa801c 100644 --- a/src/cs/vim/Vim.Format.Tests/FormatTests.cs +++ b/src/cs/vim/Vim.Format.Tests/FormatTests.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; using System.Linq; using NUnit.Framework; -using Vim.BFast; +using Vim.BFastNextNS; using Vim.LinqArray; namespace Vim.Format.Tests diff --git a/src/cs/vim/Vim.Format.Vimx.Conversion/MeshesToScene.cs b/src/cs/vim/Vim.Format.Vimx.Conversion/MeshesToScene.cs index 864ad8c1..b51ef4e4 100644 --- a/src/cs/vim/Vim.Format.Vimx.Conversion/MeshesToScene.cs +++ b/src/cs/vim/Vim.Format.Vimx.Conversion/MeshesToScene.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; using System.Linq; -using Vim.BFast; +using Vim.BFastNextNS; using Vim.Format.ObjectModel; using Vim.G3dNext.Attributes; using Vim.LinqArray; diff --git a/src/cs/vim/Vim.Format.Vimx.Conversion/VimToMeshes.cs b/src/cs/vim/Vim.Format.Vimx.Conversion/VimToMeshes.cs index ffd07d62..69535f61 100644 --- a/src/cs/vim/Vim.Format.Vimx.Conversion/VimToMeshes.cs +++ b/src/cs/vim/Vim.Format.Vimx.Conversion/VimToMeshes.cs @@ -2,7 +2,7 @@ using System.Linq; using Vim.LinqArray; using Vim.Util; -using Vim.BFast; +using Vim.BFastNextNS; using Vim.Math3d; using Vim.G3dNext.Attributes; diff --git a/src/cs/vim/Vim.Format.Vimx.Conversion/VimxConverter.cs b/src/cs/vim/Vim.Format.Vimx.Conversion/VimxConverter.cs index e1525a06..697baa74 100644 --- a/src/cs/vim/Vim.Format.Vimx.Conversion/VimxConverter.cs +++ b/src/cs/vim/Vim.Format.Vimx.Conversion/VimxConverter.cs @@ -1,6 +1,6 @@ using System.Linq; using Vim.LinqArray; -using Vim.BFast; +using Vim.BFastNextNS; using Vim.G3dNext.Attributes; using Vim.Format.ObjectModel; using Vim.G3dNext; diff --git a/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs b/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs index 55dc2b94..661dd8a0 100644 --- a/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs +++ b/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs @@ -3,7 +3,7 @@ using System.Linq; using System.Reflection; using System.Threading.Tasks; -using Vim.BFast; +using Vim.BFastNextNS; using Vim.Format.Geometry; using Vim.Format.ObjectModel; using Vim.Util; @@ -153,12 +153,12 @@ public static void ValidateEquality(this DocumentBuilder db, VimScene vim) g.SubmeshMaterials.ToList() )).ToList(); - for (var i = 0; i < db.Meshes.Count; ++i) + for (var i = 0; i < db.Geometry.MeshCount; ++i) { - if (!db.Meshes[i].IsEquivalentTo(vimGeoBuilders[i])) + if (!db.Geometry.GetMesh(i).IsEquivalentTo(vimGeoBuilders[i])) throw new VimValidationException($"{nameof(DocumentBuilder)} mesh {i} is not equivalent to {nameof(VimScene)} mesh {i}"); - if (!db.Meshes[i].ToIMesh().GeometryEquals(vim.Meshes[i])) + if (!db.Geometry.GetMesh(i).ToIMesh().GeometryEquals(vim.Meshes[i])) throw new VimValidationException($"{nameof(DocumentBuilder)} mesh {i} geometry is not equal to {nameof(VimScene)} mesh {i}"); } diff --git a/src/cs/vim/Vim.Vimx.Test/VimG3dTests.cs b/src/cs/vim/Vim.Vimx.Test/VimG3dTests.cs index 79543c72..74485781 100644 --- a/src/cs/vim/Vim.Vimx.Test/VimG3dTests.cs +++ b/src/cs/vim/Vim.Vimx.Test/VimG3dTests.cs @@ -1,6 +1,6 @@ using NUnit.Framework; using NUnit.Framework.Internal; -using Vim.BFast; +using Vim.BFastNextNS; using Vim.G3dNext.Attributes; using Vim.Math3d; using Vim.BFastNextNS; diff --git a/src/cs/vim/Vim.Vimx.Test/VimxTests.cs b/src/cs/vim/Vim.Vimx.Test/VimxTests.cs index 14690f36..d1b79444 100644 --- a/src/cs/vim/Vim.Vimx.Test/VimxTests.cs +++ b/src/cs/vim/Vim.Vimx.Test/VimxTests.cs @@ -2,10 +2,8 @@ using NUnit.Framework.Internal; using Vim.BFast; using Vim.G3dNext.Tests; -using Vim.Math3d; using Vim.Format.VimxNS.Conversion; using Vim.Util.Tests; -using Vim.BFastNextNS; namespace Vim.Format.VimxNS.Tests { From bcb8663380c839b3cce3387af1489a9883e9b157 Mon Sep 17 00:00:00 2001 From: simon Date: Wed, 6 Dec 2023 10:05:32 -0500 Subject: [PATCH 029/111] small adjustments --- src/cs/bfast/Vim.BFast.Next/BFastIO.cs | 2 -- src/cs/bfast/Vim.BFast.Next/BFastNext.cs | 2 +- .../bfast/Vim.BFast.Next/Vim.BFastNext.csproj | 4 ---- src/cs/g3d/Vim.G3d/Vim.G3d.csproj | 1 + .../vim/Vim.Format.Core/SerializableDocument.cs | 17 ++--------------- 5 files changed, 4 insertions(+), 22 deletions(-) diff --git a/src/cs/bfast/Vim.BFast.Next/BFastIO.cs b/src/cs/bfast/Vim.BFast.Next/BFastIO.cs index d92e0f9d..3b4ff753 100644 --- a/src/cs/bfast/Vim.BFast.Next/BFastIO.cs +++ b/src/cs/bfast/Vim.BFast.Next/BFastIO.cs @@ -32,8 +32,6 @@ public static void WriteBFast(this Stream stream, string[] bufferNames, long[] b stream.WriteBFast(header, bufferNames, bufferSizes, onBuffer); } - public static long NumBytes(this IBuffer buffer) - => (long)buffer.NumElements() * buffer.ElementSize; /// /// Enables a user to write a BFAST from an array of names, sizes, and a custom writing function. diff --git a/src/cs/bfast/Vim.BFast.Next/BFastNext.cs b/src/cs/bfast/Vim.BFast.Next/BFastNext.cs index 413362cd..dac8577f 100644 --- a/src/cs/bfast/Vim.BFast.Next/BFastNext.cs +++ b/src/cs/bfast/Vim.BFast.Next/BFastNext.cs @@ -193,7 +193,7 @@ private static long GetBFastSize(IEnumerable<(string name, IWritable value)> wri var sizes = values.Select(v => v.GetSize()).ToArray(); var names = writables.Select(w => w.name).ToArray(); - var header = BFast.BFast.CreateBFastHeader(sizes, names); + var header = BFastIO.CreateBFastHeader(sizes, names); return header.Preamble.DataEnd; } } diff --git a/src/cs/bfast/Vim.BFast.Next/Vim.BFastNext.csproj b/src/cs/bfast/Vim.BFast.Next/Vim.BFastNext.csproj index 9f8c5197..7f22bfd6 100644 --- a/src/cs/bfast/Vim.BFast.Next/Vim.BFastNext.csproj +++ b/src/cs/bfast/Vim.BFast.Next/Vim.BFastNext.csproj @@ -5,8 +5,4 @@ true - - - - diff --git a/src/cs/g3d/Vim.G3d/Vim.G3d.csproj b/src/cs/g3d/Vim.G3d/Vim.G3d.csproj index 7f4cdcb4..af3e2d08 100644 --- a/src/cs/g3d/Vim.G3d/Vim.G3d.csproj +++ b/src/cs/g3d/Vim.G3d/Vim.G3d.csproj @@ -48,6 +48,7 @@ It can be easily and efficiently deserialized and rendered in different language + diff --git a/src/cs/vim/Vim.Format.Core/SerializableDocument.cs b/src/cs/vim/Vim.Format.Core/SerializableDocument.cs index f30e1af6..592450f9 100644 --- a/src/cs/vim/Vim.Format.Core/SerializableDocument.cs +++ b/src/cs/vim/Vim.Format.Core/SerializableDocument.cs @@ -129,7 +129,7 @@ public BFastNext ToBFast() entities.SetBFast(entity.Name, entity.ToBFast()); } bfast.SetBFast(BufferNames.Entities, entities); - bfast.SetArray(BufferNames.Strings, PackStrings(StringTable)); + bfast.SetArray(BufferNames.Strings, BFastIO.PackStrings(StringTable)); bfast.SetArray(BufferNames.Geometry, Geometry.WriteToBytes()); return bfast; } @@ -252,20 +252,7 @@ bool schemaOnly return et; } - /// - /// Converts a collection of strings, into a null-separated byte[] array - /// - public static byte[] PackStrings(IEnumerable strings) - { - var r = new List(); - foreach (var name in strings) - { - var bytes = Encoding.UTF8.GetBytes(name); - r.AddRange(bytes); - r.Add(0); - } - return r.ToArray(); - } + } } From 0caec826f9365ad824ad4adf585257b7e167c0a2 Mon Sep 17 00:00:00 2001 From: simon Date: Wed, 6 Dec 2023 12:57:01 -0500 Subject: [PATCH 030/111] Split Bfast into BFastNext, BFast.Core and Vim.Buffers --- src/cs/Vim.BFast.Core/BFastAlignment.cs | 49 ++ src/cs/Vim.BFast.Core/BFastConstants.cs | 20 + src/cs/Vim.BFast.Core/BFastHeader.cs | 67 +++ src/cs/Vim.BFast.Core/BFastPreamble.cs | 71 +++ src/cs/Vim.BFast.Core/BFastRange.cs | 44 ++ src/cs/Vim.BFast.Core/BFastReader.cs | 44 ++ src/cs/Vim.BFast.Core/BFastStrings.cs | 46 ++ src/cs/Vim.BFast.Core/BFastWriter.cs | 167 +++++++ src/cs/Vim.BFast.Core/Vim.BFast.Core.csproj | 8 + .../BufferExtensions.cs | 2 +- .../Vim.BFast.Next => Vim.Buffers}/Buffers.cs | 2 +- .../UnsafeHelpers.cs | 2 +- src/cs/Vim.Buffers/Vim.Buffers.csproj | 12 + src/cs/bfast/Vim.BFast.Next/BFastIO.cs | 467 ------------------ src/cs/bfast/Vim.BFast.Next/BFastNext.cs | 9 +- src/cs/bfast/Vim.BFast.Next/BFastNextNode.cs | 2 + .../Vim.G3dNext.Attributes/Attributes.g.cs | 1 + src/cs/vim/Vim.Format.Core/AssetInfo.cs | 2 +- .../ColumnExtensions.Buffer.cs | 2 +- src/cs/vim/Vim.Format.Core/Document.cs | 2 +- src/cs/vim/Vim.Format.Core/DocumentBuilder.cs | 2 +- .../DocumentBuilderExtensions.cs | 1 + .../vim/Vim.Format.Core/DocumentExtensions.cs | 2 +- src/cs/vim/Vim.Format.Core/EntityTable.cs | 2 +- .../vim/Vim.Format.Core/EntityTableBuilder.cs | 2 +- .../Vim.Format.Core/Geometry/Validation.cs | 2 +- .../Vim.Format.Core/SerializableDocument.cs | 4 +- src/cs/vim/Vim.Format.Core/Serializer.cs | 2 +- src/cs/vim/Vim.Format.Core/Validation.cs | 2 +- src/cs/vim/Vim.Format.Tests/FormatTests.cs | 2 +- .../vim/Vim.Format/SceneBuilder/Validation.cs | 2 +- src/cs/vim/Vim.Vimx.Test/VimxActions.cs | 5 +- 32 files changed, 559 insertions(+), 488 deletions(-) create mode 100644 src/cs/Vim.BFast.Core/BFastAlignment.cs create mode 100644 src/cs/Vim.BFast.Core/BFastConstants.cs create mode 100644 src/cs/Vim.BFast.Core/BFastHeader.cs create mode 100644 src/cs/Vim.BFast.Core/BFastPreamble.cs create mode 100644 src/cs/Vim.BFast.Core/BFastRange.cs create mode 100644 src/cs/Vim.BFast.Core/BFastReader.cs create mode 100644 src/cs/Vim.BFast.Core/BFastStrings.cs create mode 100644 src/cs/Vim.BFast.Core/BFastWriter.cs create mode 100644 src/cs/Vim.BFast.Core/Vim.BFast.Core.csproj rename src/cs/{bfast/Vim.BFast.Next => Vim.Buffers}/BufferExtensions.cs (99%) rename src/cs/{bfast/Vim.BFast.Next => Vim.Buffers}/Buffers.cs (98%) rename src/cs/{bfast/Vim.BFast.Next => Vim.Buffers}/UnsafeHelpers.cs (99%) create mode 100644 src/cs/Vim.Buffers/Vim.Buffers.csproj delete mode 100644 src/cs/bfast/Vim.BFast.Next/BFastIO.cs diff --git a/src/cs/Vim.BFast.Core/BFastAlignment.cs b/src/cs/Vim.BFast.Core/BFastAlignment.cs new file mode 100644 index 00000000..62dae409 --- /dev/null +++ b/src/cs/Vim.BFast.Core/BFastAlignment.cs @@ -0,0 +1,49 @@ +using System; +using System.IO; + +namespace Vim.BFastNextNS +{ + internal class BFastAlignment + { + /// + /// Computes the padding requires after the array of BFastRanges are written out. + /// + /// + /// + public static long ComputePadding(BFastRange[] ranges) + => ComputePadding(BFastPreamble.Size + ranges.Length * BFastRange.Size); + + /// + /// Given a position in the stream, computes how much padding is required to bring the value to an aligned point. + /// + public static long ComputePadding(long n) + => ComputeNext(n) - n; + + /// + /// Given a position in the stream, tells us where the the next aligned position will be, if it the current position is not aligned. + /// + public static long ComputeNext(long n) + => IsAligned(n) ? n : n + BFastConstants.ALIGNMENT - (n % BFastConstants.ALIGNMENT); + + /// + /// Checks that the stream (if seekable) is well aligned + /// + public static void Check(Stream stream) + { + if (!stream.CanSeek) + return; + // TODO: Check with CD: Should we bail out here? This means that any + // alignment checks for a currently-writing stream are effectively ignored. + if (stream.Position == stream.Length) + return; + if (!IsAligned(stream.Position)) + throw new Exception($"Stream position {stream.Position} is not well aligned"); + } + + /// + /// Given a position in the stream, tells us whether the position is aligned. + /// + public static bool IsAligned(long n) + => n % BFastConstants.ALIGNMENT == 0; + } +} diff --git a/src/cs/Vim.BFast.Core/BFastConstants.cs b/src/cs/Vim.BFast.Core/BFastConstants.cs new file mode 100644 index 00000000..cb0c880b --- /dev/null +++ b/src/cs/Vim.BFast.Core/BFastConstants.cs @@ -0,0 +1,20 @@ +namespace Vim.BFastNextNS +{ + /// + /// Constants. + /// + public static class BFastConstants + { + public const long Magic = 0xBFA5; + + // https://en.wikipedia.org/wiki/Endianness + public const long SameEndian = Magic; + public const long SwappedEndian = 0xA5BFL << 48; + + /// + /// Data arrays are aligned to 64 bytes, so that they can be cast directly to AVX-512 registers. + /// This is useful for efficiently working with floating point data. + /// + public const long ALIGNMENT = 64; + } +} diff --git a/src/cs/Vim.BFast.Core/BFastHeader.cs b/src/cs/Vim.BFast.Core/BFastHeader.cs new file mode 100644 index 00000000..2ffad12e --- /dev/null +++ b/src/cs/Vim.BFast.Core/BFastHeader.cs @@ -0,0 +1,67 @@ +using System; +using System.IO; +using System.Linq; + +namespace Vim.BFast.Core +{ + /// + /// This contains the BFAST data loaded or written from disk. + /// + public class BFastHeader + { + public BFastPreamble Preamble = new BFastPreamble(); + public BFastRange[] Ranges; + public string[] Names; + + public override bool Equals(object o) + => o is BFastHeader other && Equals(other); + + public bool Equals(BFastHeader other) + => Preamble.Equals(other.Preamble) && + Ranges.Length == other.Ranges.Length && + Ranges.Zip(other.Ranges, (x, y) => x.Equals(y)).All(x => x) && + Names.Zip(other.Names, (x, y) => x.Equals(y)).All(x => x); + + /// + /// Checks that the header values are sensible, and throws an exception otherwise. + /// + public BFastHeader Validate() + { + var preamble = Preamble.Validate(); + var ranges = Ranges; + var names = Names; + + if (preamble.RangesEnd > preamble.DataStart) + throw new Exception($"Computed arrays ranges end must be less than the start of data {preamble.DataStart}"); + + if (ranges == null) + throw new Exception("Ranges must not be null"); + + var min = preamble.DataStart; + var max = preamble.DataEnd; + + for (var i = 0; i < ranges.Length; ++i) + { + var begin = ranges[i].Begin; + if (!BFastAlignment.IsAligned(begin)) + throw new Exception($"The beginning of the range is not well aligned {begin}"); + var end = ranges[i].End; + if (begin < min || begin > max) + throw new Exception($"Array offset begin {begin} is not in valid span of {min} to {max}"); + if (i > 0) + { + if (begin < ranges[i - 1].End) + throw new Exception($"Array offset begin {begin} is overlapping with previous array {ranges[i - 1].End}"); + } + + if (end < begin || end > max) + throw new Exception($"Array offset end {end} is not in valid span of {begin} to {max}"); + } + + if (names.Length < ranges.Length - 1) + throw new Exception($"Number of buffer names {names.Length} is not one less than the number of ranges {ranges.Length}"); + + return this; + } + } +} diff --git a/src/cs/Vim.BFast.Core/BFastPreamble.cs b/src/cs/Vim.BFast.Core/BFastPreamble.cs new file mode 100644 index 00000000..30883bc6 --- /dev/null +++ b/src/cs/Vim.BFast.Core/BFastPreamble.cs @@ -0,0 +1,71 @@ +using System; +using System.Runtime.InteropServices; + +namespace Vim.BFast.Core +{ + /// + /// The header contains a magic number, the begin and end indices of data, and the number of arrays. + /// + [StructLayout(LayoutKind.Explicit, Pack = 8, Size = 32)] + public struct BFastPreamble + { + [FieldOffset(0)] public long Magic; // Either Constants.SameEndian or Constants.SwappedEndian depending on endianess of writer compared to reader. + [FieldOffset(8)] public long DataStart; // <= file size and >= ArrayRangesEnd and >= FileHeader.ByteCount + [FieldOffset(16)] public long DataEnd; // >= DataStart and <= file size + [FieldOffset(24)] public long NumArrays; // number of arrays + + /// + /// This is where the array ranges are finished. + /// Must be less than or equal to DataStart. + /// Must be greater than or equal to FileHeader.ByteCount + /// + public long RangesEnd => Size + NumArrays * 16; + + /// + /// The size of the FileHeader structure + /// + public static long Size = 32; + + /// + /// Returns true if the producer of the BFast file has the same endianness as the current library + /// + public bool SameEndian => Magic == BFastConstants.SameEndian; + + public override bool Equals(object x) + => x is BFastPreamble other && Equals(other); + + public bool Equals(BFastPreamble other) + => Magic == other.Magic && DataStart == other.DataStart && DataEnd == other.DataEnd && NumArrays == other.NumArrays; + + + /// + /// Checks that the header values are sensible, and throws an exception otherwise. + /// + public BFastPreamble Validate() + { + if (Magic != BFastConstants.SameEndian && Magic != BFastConstants.SwappedEndian) + throw new Exception($"Invalid magic number {Magic}"); + + if (DataStart < BFastPreamble.Size) + throw new Exception($"Data start {DataStart} cannot be before the file header size {BFastPreamble.Size}"); + + if (DataStart > DataEnd) + throw new Exception($"Data start {DataStart} cannot be after the data end {DataEnd}"); + + if (!BFastAlignment.IsAligned(DataEnd)) + throw new Exception($"Data end {DataEnd} should be aligned"); + + if (NumArrays < 0) + throw new Exception($"Number of arrays {NumArrays} is not a positive number"); + + if (NumArrays > DataEnd) + throw new Exception($"Number of arrays {NumArrays} can't be more than the total size"); + + if (RangesEnd > DataStart) + throw new Exception($"End of range {RangesEnd} can't be after data-start {DataStart}"); + + return this; + } + + }; +} diff --git a/src/cs/Vim.BFast.Core/BFastRange.cs b/src/cs/Vim.BFast.Core/BFastRange.cs new file mode 100644 index 00000000..324d6433 --- /dev/null +++ b/src/cs/Vim.BFast.Core/BFastRange.cs @@ -0,0 +1,44 @@ +using System.IO; +using System.Runtime.InteropServices; + +namespace Vim.BFast.Core +{ + /// + /// This tells us where a particular array begins and ends in relation to the beginning of a file. + /// * Begin must be less than or equal to End. + /// * Begin must be greater than or equal to DataStart + /// * End must be less than or equal to DataEnd + /// + [StructLayout(LayoutKind.Explicit, Pack = 8, Size = 16)] + public struct BFastRange + { + [FieldOffset(0)] public long Begin; + [FieldOffset(8)] public long End; + + public long Count => End - Begin; + public static long Size = 16; + + public override bool Equals(object x) + => x is BFastRange other && Equals(other); + + public bool Equals(BFastRange other) + => Begin == other.Begin && End == other.End; + + public BFastRange OffsetBy(long offset) + => new BFastRange() + { + Begin = Begin + offset, + End = End + offset + }; + } + + public static class BFastRangeExtensions + { + public static BFastRange FullRange(this Stream stream) + => new BFastRange() + { + Begin = 0, + End = stream.Length + }; + } +} diff --git a/src/cs/Vim.BFast.Core/BFastReader.cs b/src/cs/Vim.BFast.Core/BFastReader.cs new file mode 100644 index 00000000..1a2c95cb --- /dev/null +++ b/src/cs/Vim.BFast.Core/BFastReader.cs @@ -0,0 +1,44 @@ +using System; +using System.IO; +using Vim.Buffers; + +namespace Vim.BFast.Core +{ + public static class BFastReader + { + /// + /// Reads the preamble, the ranges, and the names of the rest of the buffers. + /// + public static BFastHeader ReadHeader(Stream stream) + { + var r = new BFastHeader(); + var br = new BinaryReader(stream); + + if (stream.Length - stream.Position < sizeof(long) * 4) + throw new Exception("Stream too short"); + + r.Preamble = new BFastPreamble + { + Magic = br.ReadInt64(), + DataStart = br.ReadInt64(), + DataEnd = br.ReadInt64(), + NumArrays = br.ReadInt64(), + }.Validate(); + + r.Ranges = stream.ReadArray((int)r.Preamble.NumArrays); + + var padding = BFastAlignment.ComputePadding(r.Ranges); + br.ReadBytes((int)padding); + BFastAlignment.Check(br.BaseStream); + + var nameBytes = br.ReadBytes((int)r.Ranges[0].Count); + r.Names = BFastStrings.Unpack(nameBytes); + + padding = BFastAlignment.ComputePadding(r.Ranges[0].End); + br.ReadBytes((int)padding); + BFastAlignment.Check(br.BaseStream); + + return r.Validate(); + } + } +} diff --git a/src/cs/Vim.BFast.Core/BFastStrings.cs b/src/cs/Vim.BFast.Core/BFastStrings.cs new file mode 100644 index 00000000..401ea12d --- /dev/null +++ b/src/cs/Vim.BFast.Core/BFastStrings.cs @@ -0,0 +1,46 @@ +using System.Collections.Generic; +using System.Text; + +namespace Vim.BFast.Core +{ + public static class BFastStrings + { + /// + /// Converts a collection of strings, into a null-separated byte[] array + /// + public static byte[] Pack(IEnumerable strings) + { + var r = new List(); + foreach (var name in strings) + { + var bytes = Encoding.UTF8.GetBytes(name); + r.AddRange(bytes); + r.Add(0); + } + return r.ToArray(); + } + + + /// + /// Converts a byte[] array encoding a collection of strings separate by NULL into an array of string + /// + public static string[] Unpack(byte[] bytes) + { + var r = new List(); + if (bytes.Length == 0) + return r.ToArray(); + var prev = 0; + for (var i = 0; i < bytes.Length; ++i) + { + if (bytes[i] == 0) + { + r.Add(Encoding.UTF8.GetString(bytes, prev, i - prev)); + prev = i + 1; + } + } + if (prev < bytes.Length) + r.Add(Encoding.UTF8.GetString(bytes, prev, bytes.Length - prev)); + return r.ToArray(); + } + } +} diff --git a/src/cs/Vim.BFast.Core/BFastWriter.cs b/src/cs/Vim.BFast.Core/BFastWriter.cs new file mode 100644 index 00000000..8337a5d0 --- /dev/null +++ b/src/cs/Vim.BFast.Core/BFastWriter.cs @@ -0,0 +1,167 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.Linq; + +namespace Vim.BFast.Core +{ + public static class BFastWriter + { + /// + /// Callback function allows clients to control writing the data to the output stream + /// + public delegate long BFastWriterFn(Stream writingStream, int bufferIdx, string bufferName, long bytesToWrite); + + /// + /// Enables a user to write a BFAST from an array of names, sizes, and a custom writing function. + /// The function will receive a BinaryWriter, the index of the buffer, and is expected to return the number of bytes written. + /// Simplifies the process of creating custom BinaryWriters, or writing extremely large arrays if necessary. + /// + public static void Write(Stream stream, string[] bufferNames, long[] bufferSizes, BFastWriterFn onBuffer) + { + if (bufferSizes.Any(sz => sz < 0)) + throw new Exception("All buffer sizes must be zero or greater than zero"); + + if (bufferNames.Length != bufferSizes.Length) + throw new Exception($"The number of buffer names {bufferNames.Length} is not equal to the number of buffer sizes {bufferSizes}"); + + var header = CreateHeader(bufferSizes, bufferNames); + Write(stream, header, bufferNames, bufferSizes, onBuffer); + } + + /// + /// Enables a user to write a BFAST from an array of names, sizes, and a custom writing function. + /// This is useful when the header is already computed. + /// + public static void Write(Stream stream, BFastHeader header, string[] bufferNames, long[] bufferSizes, BFastWriterFn onBuffer) + { + WriteHeader(stream, header); + BFastAlignment.Check(stream); + WriteBody(stream, bufferNames, bufferSizes, onBuffer); + } + + /// + /// Must be called after "WriteBFastHeader" + /// Enables a user to write the contents of a BFAST from an array of names, sizes, and a custom writing function. + /// The function will receive a BinaryWriter, the index of the buffer, and is expected to return the number of bytes written. + /// Simplifies the process of creating custom BinaryWriters, or writing extremely large arrays if necessary. + /// + public static void WriteBody(Stream stream, string[] bufferNames, long[] bufferSizes, BFastWriterFn onBuffer) + { + BFastAlignment.Check(stream); + + if (bufferSizes.Any(sz => sz < 0)) + throw new Exception("All buffer sizes must be zero or greater than zero"); + + if (bufferNames.Length != bufferSizes.Length) + throw new Exception($"The number of buffer names {bufferNames.Length} is not equal to the number of buffer sizes {bufferSizes}"); + + // Then passes the binary writer for each buffer: checking that the correct amount of data was written. + for (var i = 0; i < bufferNames.Length; ++i) + { + BFastAlignment.Check(stream); + var nBytes = bufferSizes[i]; + var pos = stream.CanSeek ? stream.Position : 0; + var nWrittenBytes = onBuffer(stream, i, bufferNames[i], nBytes); + if (stream.CanSeek) + { + if (stream.Position - pos != nWrittenBytes) + throw new NotImplementedException($"Buffer:{bufferNames[i]}. Stream movement {stream.Position - pos} does not reflect number of bytes claimed to be written {nWrittenBytes}"); + } + + if (nBytes != nWrittenBytes) + throw new Exception($"Number of bytes written {nWrittenBytes} not equal to expected bytes{nBytes}"); + var padding = BFastAlignment.ComputePadding(nBytes); + for (var j = 0; j < padding; ++j) + stream.WriteByte(0); + BFastAlignment.Check(stream); + } + } + + /// + /// Creates a BFAST structure, without any actual data buffers, from a list of sizes of buffers (not counting the name buffer). + /// Used as an intermediate step to create a BFAST. + /// + public static BFastHeader CreateHeader(long[] bufferSizes, string[] bufferNames) + { + if (bufferNames.Length != bufferSizes.Length) + throw new Exception($"The number of buffer sizes {bufferSizes.Length} is not equal to the number of buffer names {bufferNames.Length}"); + + var header = new BFastHeader + { + Names = bufferNames + }; + header.Preamble.Magic = BFastConstants.Magic; + header.Preamble.NumArrays = bufferSizes.Length + 1; + + // Allocate the data for the ranges + header.Ranges = new BFastRange[header.Preamble.NumArrays]; + header.Preamble.DataStart = BFastAlignment.ComputeNext(header.Preamble.RangesEnd); + + var nameBufferLength = BFastStrings.Pack(bufferNames).LongLength; + var sizes = (new[] { nameBufferLength }).Concat(bufferSizes).ToArray(); + + // Compute the offsets for the data buffers + var curIndex = header.Preamble.DataStart; + var i = 0; + foreach (var size in sizes) + { + curIndex = BFastAlignment.ComputeNext(curIndex); + Debug.Assert(BFastAlignment.IsAligned(curIndex)); + + header.Ranges[i].Begin = curIndex; + curIndex += size; + + header.Ranges[i].End = curIndex; + i++; + } + + // Finish with the header + // Each buffer we contain is padded to ensure the next one + // starts on alignment, so we pad our DataEnd to reflect this reality + header.Preamble.DataEnd = BFastAlignment.ComputeNext(curIndex); + + // Check that everything adds up + return header.Validate(); + } + + + /// + /// Writes the BFAST header and name buffer to stream using the provided BinaryWriter. The BinaryWriter will be properly aligned by padding zeros + /// + public static BinaryWriter WriteHeader(Stream stream, BFastHeader header) + { + if (header.Ranges.Length != header.Names.Length + 1) + throw new Exception($"The number of ranges {header.Ranges.Length} must be equal to one more than the number of names {header.Names.Length}"); + var bw = new BinaryWriter(stream); + bw.Write(header.Preamble.Magic); + bw.Write(header.Preamble.DataStart); + bw.Write(header.Preamble.DataEnd); + bw.Write(header.Preamble.NumArrays); + foreach (var r in header.Ranges) + { + bw.Write(r.Begin); + bw.Write(r.End); + } + WriteZeroBytes(bw, BFastAlignment.ComputePadding(header.Ranges)); + + BFastAlignment.Check(stream); + var nameBuffer = BFastStrings.Pack(header.Names); + bw.Write(nameBuffer); + WriteZeroBytes(bw, BFastAlignment.ComputePadding(nameBuffer.LongLength)); + + BFastAlignment.Check(stream); + return bw; + } + + /// + /// Writes n zero bytes. + /// + public static void WriteZeroBytes(BinaryWriter bw, long n) + { + for (var i = 0L; i < n; ++i) + bw.Write((byte)0); + } + + } +} diff --git a/src/cs/Vim.BFast.Core/Vim.BFast.Core.csproj b/src/cs/Vim.BFast.Core/Vim.BFast.Core.csproj new file mode 100644 index 00000000..2e68195f --- /dev/null +++ b/src/cs/Vim.BFast.Core/Vim.BFast.Core.csproj @@ -0,0 +1,8 @@ + + + + netstandard2.0 + true + + + diff --git a/src/cs/bfast/Vim.BFast.Next/BufferExtensions.cs b/src/cs/Vim.Buffers/BufferExtensions.cs similarity index 99% rename from src/cs/bfast/Vim.BFast.Next/BufferExtensions.cs rename to src/cs/Vim.Buffers/BufferExtensions.cs index eb0bb91f..5900b83d 100644 --- a/src/cs/bfast/Vim.BFast.Next/BufferExtensions.cs +++ b/src/cs/Vim.Buffers/BufferExtensions.cs @@ -3,7 +3,7 @@ using System.IO; using System.Linq; -namespace Vim.BFastNextNS +namespace Vim.Buffers { /// /// Helper functions for working with buffers diff --git a/src/cs/bfast/Vim.BFast.Next/Buffers.cs b/src/cs/Vim.Buffers/Buffers.cs similarity index 98% rename from src/cs/bfast/Vim.BFast.Next/Buffers.cs rename to src/cs/Vim.Buffers/Buffers.cs index 8a2949e5..66420de7 100644 --- a/src/cs/bfast/Vim.BFast.Next/Buffers.cs +++ b/src/cs/Vim.Buffers/Buffers.cs @@ -1,7 +1,7 @@ using System; using System.IO; -namespace Vim.BFastNextNS +namespace Vim.Buffers { /// /// Provides an interface to an object that manages a potentially large array of elements all of the same unmanaged type. diff --git a/src/cs/bfast/Vim.BFast.Next/UnsafeHelpers.cs b/src/cs/Vim.Buffers/UnsafeHelpers.cs similarity index 99% rename from src/cs/bfast/Vim.BFast.Next/UnsafeHelpers.cs rename to src/cs/Vim.Buffers/UnsafeHelpers.cs index 96b0bec1..df3db198 100644 --- a/src/cs/bfast/Vim.BFast.Next/UnsafeHelpers.cs +++ b/src/cs/Vim.Buffers/UnsafeHelpers.cs @@ -1,7 +1,7 @@ using System; using System.IO; -namespace Vim.BFastNextNS +namespace Vim.Buffers { /// /// This class would benefit from being in a generic utilities class, however, having it here allows BFAST to be a standalone without dependencies. diff --git a/src/cs/Vim.Buffers/Vim.Buffers.csproj b/src/cs/Vim.Buffers/Vim.Buffers.csproj new file mode 100644 index 00000000..2cfdb964 --- /dev/null +++ b/src/cs/Vim.Buffers/Vim.Buffers.csproj @@ -0,0 +1,12 @@ + + + + netstandard2.0 + true + + + + + + + diff --git a/src/cs/bfast/Vim.BFast.Next/BFastIO.cs b/src/cs/bfast/Vim.BFast.Next/BFastIO.cs deleted file mode 100644 index 3b4ff753..00000000 --- a/src/cs/bfast/Vim.BFast.Next/BFastIO.cs +++ /dev/null @@ -1,467 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Runtime.InteropServices; -using System.Text; - -namespace Vim.BFastNextNS -{ - public static class BFastIO - { - /// - /// Callback function allows clients to control writing the data to the output stream - /// - public delegate long BFastWriterFn(Stream writingStream, int bufferIdx, string bufferName, long bytesToWrite); - - /// - /// Enables a user to write a BFAST from an array of names, sizes, and a custom writing function. - /// The function will receive a BinaryWriter, the index of the buffer, and is expected to return the number of bytes written. - /// Simplifies the process of creating custom BinaryWriters, or writing extremely large arrays if necessary. - /// - public static void WriteBFast(this Stream stream, string[] bufferNames, long[] bufferSizes, BFastWriterFn onBuffer) - { - if (bufferSizes.Any(sz => sz < 0)) - throw new Exception("All buffer sizes must be zero or greater than zero"); - - if (bufferNames.Length != bufferSizes.Length) - throw new Exception($"The number of buffer names {bufferNames.Length} is not equal to the number of buffer sizes {bufferSizes}"); - - var header = CreateBFastHeader(bufferSizes, bufferNames); - stream.WriteBFast(header, bufferNames, bufferSizes, onBuffer); - } - - - /// - /// Enables a user to write a BFAST from an array of names, sizes, and a custom writing function. - /// This is useful when the header is already computed. - /// - public static void WriteBFast(this Stream stream, BFastHeader header, string[] bufferNames, long[] bufferSizes, BFastWriterFn onBuffer) - { - stream.WriteBFastHeader(header); - CheckAlignment(stream); - stream.WriteBFastBody(header, bufferNames, bufferSizes, onBuffer); - } - - /// - /// Must be called after "WriteBFastHeader" - /// Enables a user to write the contents of a BFAST from an array of names, sizes, and a custom writing function. - /// The function will receive a BinaryWriter, the index of the buffer, and is expected to return the number of bytes written. - /// Simplifies the process of creating custom BinaryWriters, or writing extremely large arrays if necessary. - /// - public static void WriteBFastBody(this Stream stream, BFastHeader header, string[] bufferNames, long[] bufferSizes, BFastWriterFn onBuffer) - { - CheckAlignment(stream); - - if (bufferSizes.Any(sz => sz < 0)) - throw new Exception("All buffer sizes must be zero or greater than zero"); - - if (bufferNames.Length != bufferSizes.Length) - throw new Exception($"The number of buffer names {bufferNames.Length} is not equal to the number of buffer sizes {bufferSizes}"); - - // Then passes the binary writer for each buffer: checking that the correct amount of data was written. - for (var i = 0; i < bufferNames.Length; ++i) - { - CheckAlignment(stream); - var nBytes = bufferSizes[i]; - var pos = stream.CanSeek ? stream.Position : 0; - var nWrittenBytes = onBuffer(stream, i, bufferNames[i], nBytes); - if (stream.CanSeek) - { - if (stream.Position - pos != nWrittenBytes) - throw new NotImplementedException($"Buffer:{bufferNames[i]}. Stream movement {stream.Position - pos} does not reflect number of bytes claimed to be written {nWrittenBytes}"); - } - - if (nBytes != nWrittenBytes) - throw new Exception($"Number of bytes written {nWrittenBytes} not equal to expected bytes{nBytes}"); - var padding = ComputePadding(nBytes); - for (var j = 0; j < padding; ++j) - stream.WriteByte(0); - CheckAlignment(stream); - } - } - - - /// - /// Writes the BFAST header and name buffer to stream using the provided BinaryWriter. The BinaryWriter will be properly aligned by padding zeros - /// - public static BinaryWriter WriteBFastHeader(this Stream stream, BFastHeader header) - { - if (header.Ranges.Length != header.Names.Length + 1) - throw new Exception($"The number of ranges {header.Ranges.Length} must be equal to one more than the number of names {header.Names.Length}"); - var bw = new BinaryWriter(stream); - bw.Write(header.Preamble.Magic); - bw.Write(header.Preamble.DataStart); - bw.Write(header.Preamble.DataEnd); - bw.Write(header.Preamble.NumArrays); - foreach (var r in header.Ranges) - { - bw.Write(r.Begin); - bw.Write(r.End); - } - WriteZeroBytes(bw, ComputePadding(header.Ranges)); - - CheckAlignment(stream); - var nameBuffer = PackStrings(header.Names); - bw.Write(nameBuffer); - WriteZeroBytes(bw, ComputePadding(nameBuffer.LongLength)); - - CheckAlignment(stream); - return bw; - } - - - /// - /// Writes n zero bytes. - /// - public static void WriteZeroBytes(this BinaryWriter bw, long n) - { - for (var i = 0L; i < n; ++i) - bw.Write((byte)0); - } - - - /// - /// Creates a BFAST structure, without any actual data buffers, from a list of sizes of buffers (not counting the name buffer). - /// Used as an intermediate step to create a BFAST. - /// - public static BFastHeader CreateBFastHeader(this long[] bufferSizes, string[] bufferNames) - { - if (bufferNames.Length != bufferSizes.Length) - throw new Exception($"The number of buffer sizes {bufferSizes.Length} is not equal to the number of buffer names {bufferNames.Length}"); - - var header = new BFastHeader - { - Names = bufferNames - }; - header.Preamble.Magic = Constants.Magic; - header.Preamble.NumArrays = bufferSizes.Length + 1; - - // Allocate the data for the ranges - header.Ranges = new BFastRange[header.Preamble.NumArrays]; - header.Preamble.DataStart = ComputeNextAlignment(header.Preamble.RangesEnd); - - var nameBufferLength = PackStrings(bufferNames).LongLength; - var sizes = (new[] { nameBufferLength }).Concat(bufferSizes).ToArray(); - - // Compute the offsets for the data buffers - var curIndex = header.Preamble.DataStart; - var i = 0; - foreach (var size in sizes) - { - curIndex = ComputeNextAlignment(curIndex); - Debug.Assert(IsAligned(curIndex)); - - header.Ranges[i].Begin = curIndex; - curIndex += size; - - header.Ranges[i].End = curIndex; - i++; - } - - // Finish with the header - // Each buffer we contain is padded to ensure the next one - // starts on alignment, so we pad our DataEnd to reflect this reality - header.Preamble.DataEnd = ComputeNextAlignment(curIndex); - - // Check that everything adds up - return header.Validate(); - } - - /// - /// Reads the preamble, the ranges, and the names of the rest of the buffers. - /// - public static BFastHeader ReadBFastHeader(this Stream stream) - { - var r = new BFastHeader(); - var br = new BinaryReader(stream); - - if (stream.Length - stream.Position < sizeof(long) * 4) - throw new Exception("Stream too short"); - - r.Preamble = new BFastPreamble - { - Magic = br.ReadInt64(), - DataStart = br.ReadInt64(), - DataEnd = br.ReadInt64(), - NumArrays = br.ReadInt64(), - }.Validate(); - - r.Ranges = stream.ReadArray((int)r.Preamble.NumArrays); - - var padding = ComputePadding(r.Ranges); - br.ReadBytes((int)padding); - CheckAlignment(br.BaseStream); - - var nameBytes = br.ReadBytes((int)r.Ranges[0].Count); - r.Names = nameBytes.UnpackStrings(); - - padding = ComputePadding(r.Ranges[0].End); - br.ReadBytes((int)padding); - CheckAlignment(br.BaseStream); - - return r.Validate(); - } - - /// - /// Computes the padding requires after the array of BFastRanges are written out. - /// - /// - /// - public static long ComputePadding(BFastRange[] ranges) - => ComputePadding(BFastPreamble.Size + ranges.Length * BFastRange.Size); - - /// - /// Given a position in the stream, computes how much padding is required to bring the value to an aligned point. - /// - public static long ComputePadding(long n) - => ComputeNextAlignment(n) - n; - - /// - /// Given a position in the stream, tells us where the the next aligned position will be, if it the current position is not aligned. - /// - public static long ComputeNextAlignment(long n) - => IsAligned(n) ? n : n + Constants.ALIGNMENT - (n % Constants.ALIGNMENT); - - - /// - /// Checks that the stream (if seekable) is well aligned - /// - public static void CheckAlignment(Stream stream) - { - if (!stream.CanSeek) - return; - // TODO: Check with CD: Should we bail out here? This means that any - // alignment checks for a currently-writing stream are effectively ignored. - if (stream.Position == stream.Length) - return; - if (!IsAligned(stream.Position)) - throw new Exception($"Stream position {stream.Position} is not well aligned"); - } - - /// - /// Given a position in the stream, tells us whether the position is aligned. - /// - public static bool IsAligned(long n) - => n % Constants.ALIGNMENT == 0; - - - /// - /// Checks that the header values are sensible, and throws an exception otherwise. - /// - public static BFastHeader Validate(this BFastHeader header) - { - var preamble = header.Preamble.Validate(); - var ranges = header.Ranges; - var names = header.Names; - - if (preamble.RangesEnd > preamble.DataStart) - throw new Exception($"Computed arrays ranges end must be less than the start of data {preamble.DataStart}"); - - if (ranges == null) - throw new Exception("Ranges must not be null"); - - var min = preamble.DataStart; - var max = preamble.DataEnd; - - for (var i = 0; i < ranges.Length; ++i) - { - var begin = ranges[i].Begin; - if (!IsAligned(begin)) - throw new Exception($"The beginning of the range is not well aligned {begin}"); - var end = ranges[i].End; - if (begin < min || begin > max) - throw new Exception($"Array offset begin {begin} is not in valid span of {min} to {max}"); - if (i > 0) - { - if (begin < ranges[i - 1].End) - throw new Exception($"Array offset begin {begin} is overlapping with previous array {ranges[i - 1].End}"); - } - - if (end < begin || end > max) - throw new Exception($"Array offset end {end} is not in valid span of {begin} to {max}"); - } - - if (names.Length < ranges.Length - 1) - throw new Exception($"Number of buffer names {names.Length} is not one less than the number of ranges {ranges.Length}"); - - return header; - } - - /// - /// Checks that the header values are sensible, and throws an exception otherwise. - /// - public static BFastPreamble Validate(this BFastPreamble preamble) - { - if (preamble.Magic != Constants.SameEndian && preamble.Magic != Constants.SwappedEndian) - throw new Exception($"Invalid magic number {preamble.Magic}"); - - if (preamble.DataStart < BFastPreamble.Size) - throw new Exception($"Data start {preamble.DataStart} cannot be before the file header size {BFastPreamble.Size}"); - - if (preamble.DataStart > preamble.DataEnd) - throw new Exception($"Data start {preamble.DataStart} cannot be after the data end {preamble.DataEnd}"); - - if (!IsAligned(preamble.DataEnd)) - throw new Exception($"Data end {preamble.DataEnd} should be aligned"); - - if (preamble.NumArrays < 0) - throw new Exception($"Number of arrays {preamble.NumArrays} is not a positive number"); - - if (preamble.NumArrays > preamble.DataEnd) - throw new Exception($"Number of arrays {preamble.NumArrays} can't be more than the total size"); - - if (preamble.RangesEnd > preamble.DataStart) - throw new Exception($"End of range {preamble.RangesEnd} can't be after data-start {preamble.DataStart}"); - - return preamble; - } - - /// - /// Converts a byte[] array encoding a collection of strings separate by NULL into an array of string - /// - public static string[] UnpackStrings(this byte[] bytes) - { - var r = new List(); - if (bytes.Length == 0) - return r.ToArray(); - var prev = 0; - for (var i = 0; i < bytes.Length; ++i) - { - if (bytes[i] == 0) - { - r.Add(Encoding.UTF8.GetString(bytes, prev, i - prev)); - prev = i + 1; - } - } - if (prev < bytes.Length) - r.Add(Encoding.UTF8.GetString(bytes, prev, bytes.Length - prev)); - return r.ToArray(); - } - - /// - /// Converts a collection of strings, into a null-separated byte[] array - /// - public static byte[] PackStrings(IEnumerable strings) - { - var r = new List(); - foreach (var name in strings) - { - var bytes = Encoding.UTF8.GetBytes(name); - r.AddRange(bytes); - r.Add(0); - } - return r.ToArray(); - } - - public static BFastRange FullRange(this Stream stream) - => new BFastRange() - { - Begin = 0, - End = stream.Length - }; - - public static BFastRange OffsetBy(this BFastRange range, long offset) - => new BFastRange() - { - Begin = range.Begin + offset, - End = range.End + offset - }; - } - - /// - /// Constants. - /// - public static class Constants - { - public const long Magic = 0xBFA5; - - // https://en.wikipedia.org/wiki/Endianness - public const long SameEndian = Magic; - public const long SwappedEndian = 0xA5BFL << 48; - - /// - /// Data arrays are aligned to 64 bytes, so that they can be cast directly to AVX-512 registers. - /// This is useful for efficiently working with floating point data. - /// - public const long ALIGNMENT = 64; - } - - - /// - /// This contains the BFAST data loaded or written from disk. - /// - public class BFastHeader - { - public BFastPreamble Preamble = new BFastPreamble(); - public BFastRange[] Ranges; - public string[] Names; - - public override bool Equals(object o) - => o is BFastHeader other && Equals(other); - - public bool Equals(BFastHeader other) - => Preamble.Equals(other.Preamble) && - Ranges.Length == other.Ranges.Length && - Ranges.Zip(other.Ranges, (x, y) => x.Equals(y)).All(x => x) && - Names.Zip(other.Names, (x, y) => x.Equals(y)).All(x => x); - } - - /// - /// This tells us where a particular array begins and ends in relation to the beginning of a file. - /// * Begin must be less than or equal to End. - /// * Begin must be greater than or equal to DataStart - /// * End must be less than or equal to DataEnd - /// - [StructLayout(LayoutKind.Explicit, Pack = 8, Size = 16)] - public struct BFastRange - { - [FieldOffset(0)] public long Begin; - [FieldOffset(8)] public long End; - - public long Count => End - Begin; - public static long Size = 16; - - public override bool Equals(object x) - => x is BFastRange other && Equals(other); - - public bool Equals(BFastRange other) - => Begin == other.Begin && End == other.End; - } - - /// - /// The header contains a magic number, the begin and end indices of data, and the number of arrays. - /// - [StructLayout(LayoutKind.Explicit, Pack = 8, Size = 32)] - public struct BFastPreamble - { - [FieldOffset(0)] public long Magic; // Either Constants.SameEndian or Constants.SwappedEndian depending on endianess of writer compared to reader. - [FieldOffset(8)] public long DataStart; // <= file size and >= ArrayRangesEnd and >= FileHeader.ByteCount - [FieldOffset(16)] public long DataEnd; // >= DataStart and <= file size - [FieldOffset(24)] public long NumArrays; // number of arrays - - /// - /// This is where the array ranges are finished. - /// Must be less than or equal to DataStart. - /// Must be greater than or equal to FileHeader.ByteCount - /// - public long RangesEnd => Size + NumArrays * 16; - - /// - /// The size of the FileHeader structure - /// - public static long Size = 32; - - /// - /// Returns true if the producer of the BFast file has the same endianness as the current library - /// - public bool SameEndian => Magic == Constants.SameEndian; - - public override bool Equals(object x) - => x is BFastPreamble other && Equals(other); - - public bool Equals(BFastPreamble other) - => Magic == other.Magic && DataStart == other.DataStart && DataEnd == other.DataEnd && NumArrays == other.NumArrays; - }; -} diff --git a/src/cs/bfast/Vim.BFast.Next/BFastNext.cs b/src/cs/bfast/Vim.BFast.Next/BFastNext.cs index dac8577f..dad466e0 100644 --- a/src/cs/bfast/Vim.BFast.Next/BFastNext.cs +++ b/src/cs/bfast/Vim.BFast.Next/BFastNext.cs @@ -3,6 +3,9 @@ using System.IO; using System.IO.Compression; using System.Linq; +using Vim.Buffers; +using Vim.BFast.Core; + namespace Vim.BFastNextNS { @@ -160,7 +163,7 @@ public IEnumerable AsEnumerable() where T : unmanaged private static IEnumerable<(string name, BFastNextNode value)> GetBFastNodes(Stream stream) { var offset = stream.Position; - var header = stream.ReadBFastHeader(); + var header = BFastReader.ReadHeader(stream); for (var i = 1; i < header.Preamble.NumArrays; i++) { var node = new BFastNextNode( @@ -184,7 +187,7 @@ long onBuffer(Stream writingStream, int bufferIdx, string bufferName, long bytes return bytesToWrite; } - stream.WriteBFast(names, sizes, onBuffer); + BFastWriter.Write(stream, names, sizes, onBuffer); } private static long GetBFastSize(IEnumerable<(string name, IWritable value)> writables) @@ -193,7 +196,7 @@ private static long GetBFastSize(IEnumerable<(string name, IWritable value)> wri var sizes = values.Select(v => v.GetSize()).ToArray(); var names = writables.Select(w => w.name).ToArray(); - var header = BFastIO.CreateBFastHeader(sizes, names); + var header = BFastWriter.CreateHeader(sizes, names); return header.Preamble.DataEnd; } } diff --git a/src/cs/bfast/Vim.BFast.Next/BFastNextNode.cs b/src/cs/bfast/Vim.BFast.Next/BFastNextNode.cs index 293a87f0..b7600a1f 100644 --- a/src/cs/bfast/Vim.BFast.Next/BFastNextNode.cs +++ b/src/cs/bfast/Vim.BFast.Next/BFastNextNode.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; using System.IO; +using Vim.BFast.Core; +using Vim.Buffers; namespace Vim.BFastNextNS { diff --git a/src/cs/g3d/Vim.G3dNext.Attributes/Attributes.g.cs b/src/cs/g3d/Vim.G3dNext.Attributes/Attributes.g.cs index cdff39ea..ffb1484b 100644 --- a/src/cs/g3d/Vim.G3dNext.Attributes/Attributes.g.cs +++ b/src/cs/g3d/Vim.G3dNext.Attributes/Attributes.g.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Linq; using Vim.BFastNextNS; +using Vim.Buffers; namespace Vim.G3dNext.Attributes { diff --git a/src/cs/vim/Vim.Format.Core/AssetInfo.cs b/src/cs/vim/Vim.Format.Core/AssetInfo.cs index e2c021c0..503c2827 100644 --- a/src/cs/vim/Vim.Format.Core/AssetInfo.cs +++ b/src/cs/vim/Vim.Format.Core/AssetInfo.cs @@ -1,9 +1,9 @@ using System; using System.Collections.Generic; using System.IO; -using Vim.BFastNextNS; using Vim.Util; using Vim.LinqArray; +using Vim.Buffers; namespace Vim.Format { diff --git a/src/cs/vim/Vim.Format.Core/ColumnExtensions.Buffer.cs b/src/cs/vim/Vim.Format.Core/ColumnExtensions.Buffer.cs index ff0ddcf2..55b6a3b2 100644 --- a/src/cs/vim/Vim.Format.Core/ColumnExtensions.Buffer.cs +++ b/src/cs/vim/Vim.Format.Core/ColumnExtensions.Buffer.cs @@ -2,8 +2,8 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; -using Vim.BFastNextNS; using Vim.LinqArray; +using Vim.Buffers; namespace Vim.Format { diff --git a/src/cs/vim/Vim.Format.Core/Document.cs b/src/cs/vim/Vim.Format.Core/Document.cs index c16d83b6..91f93419 100644 --- a/src/cs/vim/Vim.Format.Core/Document.cs +++ b/src/cs/vim/Vim.Format.Core/Document.cs @@ -1,5 +1,5 @@ using Vim.LinqArray; -using Vim.BFastNextNS; +using Vim.Buffers; namespace Vim.Format { diff --git a/src/cs/vim/Vim.Format.Core/DocumentBuilder.cs b/src/cs/vim/Vim.Format.Core/DocumentBuilder.cs index 0090a43c..c5838b21 100644 --- a/src/cs/vim/Vim.Format.Core/DocumentBuilder.cs +++ b/src/cs/vim/Vim.Format.Core/DocumentBuilder.cs @@ -6,7 +6,7 @@ using Vim.BFastNextNS; using System.IO; using Vim.Util; -using Vim.BFastNextNS; +using Vim.Buffers; using System.Runtime.InteropServices.ComTypes; using static Vim.Format.DocumentBuilder; using Vim.Format.Geometry; diff --git a/src/cs/vim/Vim.Format.Core/DocumentBuilderExtensions.cs b/src/cs/vim/Vim.Format.Core/DocumentBuilderExtensions.cs index 10e6adf7..a5bd6f8d 100644 --- a/src/cs/vim/Vim.Format.Core/DocumentBuilderExtensions.cs +++ b/src/cs/vim/Vim.Format.Core/DocumentBuilderExtensions.cs @@ -5,6 +5,7 @@ using Vim.G3d; using Vim.LinqArray; using static Vim.Format.DocumentBuilder; +using Vim.Buffers; namespace Vim.Format { diff --git a/src/cs/vim/Vim.Format.Core/DocumentExtensions.cs b/src/cs/vim/Vim.Format.Core/DocumentExtensions.cs index 7e1f4f40..03ef5c57 100644 --- a/src/cs/vim/Vim.Format.Core/DocumentExtensions.cs +++ b/src/cs/vim/Vim.Format.Core/DocumentExtensions.cs @@ -1,7 +1,7 @@ using System; using System.Text.RegularExpressions; using Vim.LinqArray; -using Vim.BFastNextNS; +using Vim.Buffers; namespace Vim.Format { diff --git a/src/cs/vim/Vim.Format.Core/EntityTable.cs b/src/cs/vim/Vim.Format.Core/EntityTable.cs index 9804b79b..d209fc69 100644 --- a/src/cs/vim/Vim.Format.Core/EntityTable.cs +++ b/src/cs/vim/Vim.Format.Core/EntityTable.cs @@ -1,6 +1,6 @@ using System; using System.Diagnostics; -using Vim.BFastNextNS; +using Vim.Buffers; using Vim.LinqArray; namespace Vim.Format diff --git a/src/cs/vim/Vim.Format.Core/EntityTableBuilder.cs b/src/cs/vim/Vim.Format.Core/EntityTableBuilder.cs index 6ade56ae..20aea3b0 100644 --- a/src/cs/vim/Vim.Format.Core/EntityTableBuilder.cs +++ b/src/cs/vim/Vim.Format.Core/EntityTableBuilder.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; -using Vim.BFastNextNS; +using Vim.Buffers; namespace Vim.Format { diff --git a/src/cs/vim/Vim.Format.Core/Geometry/Validation.cs b/src/cs/vim/Vim.Format.Core/Geometry/Validation.cs index 8904c954..cd2625de 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/Validation.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/Validation.cs @@ -1,8 +1,8 @@ using System; using System.Collections.Generic; -using Vim.BFastNextNS; using Vim.G3d; using Vim.LinqArray; +using Vim.Buffers; namespace Vim.Format.Geometry { diff --git a/src/cs/vim/Vim.Format.Core/SerializableDocument.cs b/src/cs/vim/Vim.Format.Core/SerializableDocument.cs index 592450f9..88866a7c 100644 --- a/src/cs/vim/Vim.Format.Core/SerializableDocument.cs +++ b/src/cs/vim/Vim.Format.Core/SerializableDocument.cs @@ -5,6 +5,8 @@ using System.Text; using Vim.BFastNextNS; using Vim.G3d; +using Vim.Buffers; +using Vim.BFast.Core; namespace Vim.Format { @@ -129,7 +131,7 @@ public BFastNext ToBFast() entities.SetBFast(entity.Name, entity.ToBFast()); } bfast.SetBFast(BufferNames.Entities, entities); - bfast.SetArray(BufferNames.Strings, BFastIO.PackStrings(StringTable)); + bfast.SetArray(BufferNames.Strings, BFastStrings.Pack(StringTable)); bfast.SetArray(BufferNames.Geometry, Geometry.WriteToBytes()); return bfast; } diff --git a/src/cs/vim/Vim.Format.Core/Serializer.cs b/src/cs/vim/Vim.Format.Core/Serializer.cs index c763d9e8..864e902e 100644 --- a/src/cs/vim/Vim.Format.Core/Serializer.cs +++ b/src/cs/vim/Vim.Format.Core/Serializer.cs @@ -1,5 +1,5 @@ using System.Text.RegularExpressions; -using Vim.BFastNextNS; +using Vim.Buffers; namespace Vim.Format { diff --git a/src/cs/vim/Vim.Format.Core/Validation.cs b/src/cs/vim/Vim.Format.Core/Validation.cs index a4cfd48d..110ee6e9 100644 --- a/src/cs/vim/Vim.Format.Core/Validation.cs +++ b/src/cs/vim/Vim.Format.Core/Validation.cs @@ -1,6 +1,6 @@ using System; using System.Collections.Generic; -using Vim.BFastNextNS; +using Vim.Buffers; using Vim.G3d; using Vim.LinqArray; diff --git a/src/cs/vim/Vim.Format.Tests/FormatTests.cs b/src/cs/vim/Vim.Format.Tests/FormatTests.cs index 2faa801c..50a1ee38 100644 --- a/src/cs/vim/Vim.Format.Tests/FormatTests.cs +++ b/src/cs/vim/Vim.Format.Tests/FormatTests.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; using System.Linq; using NUnit.Framework; -using Vim.BFastNextNS; +using Vim.Buffers; using Vim.LinqArray; namespace Vim.Format.Tests diff --git a/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs b/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs index 661dd8a0..b1ae8aaf 100644 --- a/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs +++ b/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs @@ -3,7 +3,7 @@ using System.Linq; using System.Reflection; using System.Threading.Tasks; -using Vim.BFastNextNS; +using Vim.Buffers; using Vim.Format.Geometry; using Vim.Format.ObjectModel; using Vim.Util; diff --git a/src/cs/vim/Vim.Vimx.Test/VimxActions.cs b/src/cs/vim/Vim.Vimx.Test/VimxActions.cs index c64dde6e..11d130bb 100644 --- a/src/cs/vim/Vim.Vimx.Test/VimxActions.cs +++ b/src/cs/vim/Vim.Vimx.Test/VimxActions.cs @@ -14,8 +14,9 @@ public static class VimxActions [Test, Explicit] public static void ConvertVimToVimx() { - var input = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); - //var input = Path.Join(VimFormatRepoPaths.DataDir, residence); + // var input = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); + // var input = Path.Join(VimFormatRepoPaths.DataDir, residence); + var input = Path.Join(VimFormatRepoPaths.DataDir, "nbk.vim"); var name = Path.GetFileNameWithoutExtension(input); var output = Path.Combine(VimFormatRepoPaths.OutDir, name + ".vimx"); From 5d5128e5ecd9eac26d4a924fa2b1a2aa8f0b4a77 Mon Sep 17 00:00:00 2001 From: simon Date: Wed, 6 Dec 2023 12:58:39 -0500 Subject: [PATCH 031/111] missing file --- src/cs/Vim.Buffers/Vim.Buffers.csproj | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/cs/Vim.Buffers/Vim.Buffers.csproj b/src/cs/Vim.Buffers/Vim.Buffers.csproj index 2cfdb964..2e68195f 100644 --- a/src/cs/Vim.Buffers/Vim.Buffers.csproj +++ b/src/cs/Vim.Buffers/Vim.Buffers.csproj @@ -5,8 +5,4 @@ true - - - - From 630645a5b8467971b2b8be06e46354969c4ba6c0 Mon Sep 17 00:00:00 2001 From: simon Date: Thu, 7 Dec 2023 11:12:01 -0500 Subject: [PATCH 032/111] removed bfast --- src/cs/Vim.BFast.Core/BFastAlignment.cs | 2 +- src/cs/Vim.BFast.Core/BFastConstants.cs | 2 +- src/cs/Vim.BFast.Core/Vim.BFast.Core.csproj | 4 + .../Vim.BFast.Next/BFastEnumerableNode.cs | 1 + src/cs/bfast/Vim.BFast.Next/BFastNext.cs | 2 + .../bfast/Vim.BFast.Next/Vim.BFastNext.csproj | 5 + .../bfast/Vim.BFast.Tests/BFastTestProgram.cs | 198 -------- .../Vim.BFast.Tests/Vim.BFast.Tests.csproj | 18 - src/cs/bfast/Vim.BFast/BFast.cs | 478 ------------------ src/cs/bfast/Vim.BFast/BFastBufferReader.cs | 209 -------- src/cs/bfast/Vim.BFast/BFastBuilder.cs | 97 ---- src/cs/bfast/Vim.BFast/BFastStructs.cs | 113 ----- src/cs/bfast/Vim.BFast/BufferExtensions.cs | 89 ---- src/cs/bfast/Vim.BFast/Buffers.cs | 77 --- src/cs/bfast/Vim.BFast/SeekContext.cs | 41 -- src/cs/bfast/Vim.BFast/UnsafeHelpers.cs | 176 ------- src/cs/bfast/Vim.BFast/Vim.BFast.csproj | 37 -- src/cs/bfast/Vim.BFast/readme.md | 76 --- src/cs/bfast/Vim.BFast/spec.txt | 100 ---- src/cs/g3d/Vim.G3d.Tests/G3dTestUtils.cs | 2 +- src/cs/g3d/Vim.G3d.Tests/G3dTests.cs | 10 +- src/cs/g3d/Vim.G3d/G3dSerialization.cs | 108 +--- src/cs/g3d/Vim.G3d/G3dWriter.cs | 47 -- src/cs/g3d/Vim.G3d/GeometryAttribute.cs | 21 +- src/cs/g3d/Vim.G3d/Header.cs | 12 + src/cs/g3d/Vim.G3d/Vim.G3d.csproj | 1 + .../Vim.G3dNext.Attributes.csproj | 2 +- src/cs/g3d/Vim.G3dNext/Vim.G3dNext.csproj | 1 - src/cs/vim-format.sln | 28 +- .../Vim.Format.Core/SerializableDocument.cs | 2 +- .../Vim.Format.Core/Vim.Format.Core.csproj | 2 +- .../Vim.Format.Tests/Vim.Format.Tests.csproj | 1 - src/cs/vim/Vim.Format/Vim.Format.csproj | 3 +- src/cs/vim/Vim.Vimx.Test/VimxTests.cs | 1 - 34 files changed, 96 insertions(+), 1870 deletions(-) delete mode 100644 src/cs/bfast/Vim.BFast.Tests/BFastTestProgram.cs delete mode 100644 src/cs/bfast/Vim.BFast.Tests/Vim.BFast.Tests.csproj delete mode 100644 src/cs/bfast/Vim.BFast/BFast.cs delete mode 100644 src/cs/bfast/Vim.BFast/BFastBufferReader.cs delete mode 100644 src/cs/bfast/Vim.BFast/BFastBuilder.cs delete mode 100644 src/cs/bfast/Vim.BFast/BFastStructs.cs delete mode 100644 src/cs/bfast/Vim.BFast/BufferExtensions.cs delete mode 100644 src/cs/bfast/Vim.BFast/Buffers.cs delete mode 100644 src/cs/bfast/Vim.BFast/SeekContext.cs delete mode 100644 src/cs/bfast/Vim.BFast/UnsafeHelpers.cs delete mode 100644 src/cs/bfast/Vim.BFast/Vim.BFast.csproj delete mode 100644 src/cs/bfast/Vim.BFast/readme.md delete mode 100644 src/cs/bfast/Vim.BFast/spec.txt delete mode 100644 src/cs/g3d/Vim.G3d/G3dWriter.cs diff --git a/src/cs/Vim.BFast.Core/BFastAlignment.cs b/src/cs/Vim.BFast.Core/BFastAlignment.cs index 62dae409..7149e9b1 100644 --- a/src/cs/Vim.BFast.Core/BFastAlignment.cs +++ b/src/cs/Vim.BFast.Core/BFastAlignment.cs @@ -1,7 +1,7 @@ using System; using System.IO; -namespace Vim.BFastNextNS +namespace Vim.BFast.Core { internal class BFastAlignment { diff --git a/src/cs/Vim.BFast.Core/BFastConstants.cs b/src/cs/Vim.BFast.Core/BFastConstants.cs index cb0c880b..431ab07f 100644 --- a/src/cs/Vim.BFast.Core/BFastConstants.cs +++ b/src/cs/Vim.BFast.Core/BFastConstants.cs @@ -1,4 +1,4 @@ -namespace Vim.BFastNextNS +namespace Vim.BFast.Core { /// /// Constants. diff --git a/src/cs/Vim.BFast.Core/Vim.BFast.Core.csproj b/src/cs/Vim.BFast.Core/Vim.BFast.Core.csproj index 2e68195f..aaab3980 100644 --- a/src/cs/Vim.BFast.Core/Vim.BFast.Core.csproj +++ b/src/cs/Vim.BFast.Core/Vim.BFast.Core.csproj @@ -5,4 +5,8 @@ true + + + + diff --git a/src/cs/bfast/Vim.BFast.Next/BFastEnumerableNode.cs b/src/cs/bfast/Vim.BFast.Next/BFastEnumerableNode.cs index 5c68cd1f..d8eefd11 100644 --- a/src/cs/bfast/Vim.BFast.Next/BFastEnumerableNode.cs +++ b/src/cs/bfast/Vim.BFast.Next/BFastEnumerableNode.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using Vim.Buffers; namespace Vim.BFastNextNS { diff --git a/src/cs/bfast/Vim.BFast.Next/BFastNext.cs b/src/cs/bfast/Vim.BFast.Next/BFastNext.cs index dad466e0..557c9f9f 100644 --- a/src/cs/bfast/Vim.BFast.Next/BFastNext.cs +++ b/src/cs/bfast/Vim.BFast.Next/BFastNext.cs @@ -133,6 +133,8 @@ public void Write(string path) } } + public byte[] AsBytes() => (this as IBFastNextNode).AsArray(); + BFastNext IBFastNextNode.AsBFast() { return this; diff --git a/src/cs/bfast/Vim.BFast.Next/Vim.BFastNext.csproj b/src/cs/bfast/Vim.BFast.Next/Vim.BFastNext.csproj index 7f22bfd6..c85f9e9a 100644 --- a/src/cs/bfast/Vim.BFast.Next/Vim.BFastNext.csproj +++ b/src/cs/bfast/Vim.BFast.Next/Vim.BFastNext.csproj @@ -5,4 +5,9 @@ true + + + + + diff --git a/src/cs/bfast/Vim.BFast.Tests/BFastTestProgram.cs b/src/cs/bfast/Vim.BFast.Tests/BFastTestProgram.cs deleted file mode 100644 index f4b3cab8..00000000 --- a/src/cs/bfast/Vim.BFast.Tests/BFastTestProgram.cs +++ /dev/null @@ -1,198 +0,0 @@ -/* - BFAST - Binary Format for Array Streaming and Transmission - Copyright 2019, VIMaec LLC - Copyright 2018, Ara 3D, Inc. - Usage licensed under terms of MIT License - https://github.com/vimaec/bfast -*/ - -using NUnit.Framework; -using System; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Numerics; - -namespace Vim.BFast.Tests -{ - public static class BFastTests - { - public static int Mb = 1000 * 1000; - public static int Gb = 1000 * Mb; - - static byte[] ByteArray(int numBytes) => - Enumerable.Range(0, numBytes).Select(i => (byte)i).ToArray(); - - static readonly byte[] Array1MB - = ByteArray(Mb); - - static readonly double[] Array1GB - = Enumerable.Range(0, Gb / 8).Select(i => (double)i).ToArray(); - - public static (string, byte[])[] ZeroBuffers - = Enumerable.Empty<(string, byte[])>().ToArray(); - - public static (string, byte[])[] Ten1MBBuffers - = Enumerable.Range(0, 10).Select(i => (i.ToString(), Array1MB)).ToArray(); - - public static (string, double[])[] One1GBBuffer - => Enumerable.Range(0, 1).Select(i => (i.ToString(), Array1GB)).ToArray(); - - public static void TestBFastBytes(byte[] bytes) - { - Console.WriteLine($"Size of buffer = {bytes.Length}"); - Console.WriteLine($"First 8 bytes = {string.Join(", ", bytes.Take(8))}"); - } - - public class DisposableTimer : IDisposable - { - Stopwatch Stopwatch = Stopwatch.StartNew(); - - public void Dispose() - => Console.WriteLine($"Elapsed = {Stopwatch.ElapsedMilliseconds / 1000}s {Stopwatch.ElapsedMilliseconds % 1000}ms"); - } - - public static DisposableTimer CreateTimer(string message = null) - { - Console.WriteLine($"Starting timer {message ?? string.Empty}"); - return new DisposableTimer(); - } - - [Test] - public static void TestStringPacking() - { - var noStrings = new string[0]; - var oneStrings = new[] { "" }; - var twoStrings = new[] { "", "ab" }; - var threeStrings = new[] { "a", "b", "" }; - var noPacked = BFast.PackStrings(noStrings); - var onePacked = BFast.PackStrings(oneStrings); - var twoPacked = BFast.PackStrings(twoStrings); - var threePacked = BFast.PackStrings(threeStrings); - Assert.AreEqual(0, noPacked.Length); - Assert.AreEqual(1, onePacked.Length); - Assert.AreEqual(4, twoPacked.Length); - Assert.AreEqual(5, threePacked.Length); - Assert.AreEqual(noStrings, BFast.UnpackStrings(noPacked)); - Assert.AreEqual(oneStrings, BFast.UnpackStrings(onePacked)); - Assert.AreEqual(twoStrings, BFast.UnpackStrings(twoPacked)); - Assert.AreEqual(threeStrings, BFast.UnpackStrings(threePacked)); - } - - [Test] - public static void BasicTests() - { - using (CreateTimer("ZeroBuffers")) - { - var bytes = BFast.WriteBFastToBytes(ZeroBuffers); - TestBFastBytes(bytes); - var tmp = BFast.ReadBFast(bytes).ToArray(); - Assert.AreEqual(0, tmp.Length); - } - using (CreateTimer("Ten1MBBuffers")) - { - var bytes = BFast.WriteBFastToBytes(Ten1MBBuffers); - TestBFastBytes(bytes); - var tmp = BFast.ReadBFast(bytes).ToArray(); - Assert.AreEqual(10, tmp.Length); - Assert.AreEqual(tmp.Select(x => x.Name).ToArray(), Enumerable.Range(0, 10).Select(x => x.ToString()).ToArray()); - Assert.AreEqual(tmp.Select(x => (int)x.NumBytes()).ToArray(), Enumerable.Repeat(Mb, 10).ToArray()); - - for (var i = 0; i < 10; ++i) - Assert.AreEqual(Ten1MBBuffers[i].Item2, tmp[i].ToBytes(), $"Buffer {i} are different"); - } - using (CreateTimer("OneGBBuffer")) - { - //Enumerable.Range(0, Gb).Select(i => (double)i).ToArray() - var bytes = BFast.WriteBFastToBytes(One1GBBuffer); - TestBFastBytes(bytes); - var tmp = BFast.ReadBFast(bytes).ToArray(); - Assert.AreEqual(1, tmp.Length); - Assert.AreEqual(tmp.Select(x => x.Name).ToArray(), new[] { "0" }); - Assert.AreEqual(tmp.Select(x => x.NumBytes()).ToArray(), Enumerable.Repeat((long)Gb, 1).ToArray()); - } - } - - public static BFastBuilder BFastWithSubs(int numBuffers, int numLevels, Func numBytes) - => Enumerable.Range(0, numBuffers).Aggregate(new BFastBuilder(), - (bld, i) => bld.Add(i.ToString(), - numLevels > 0 - ? BFastWithSubs(numBuffers, numLevels - 1, numBytes) - : BFastRoot(numBuffers, numBytes)) - ); - - public static BFastBuilder BFastRoot(int numBuffers, Func numBytes) - => Enumerable.Range(0, numBuffers).Aggregate(new BFastBuilder(), (bld, i) => bld.Add(i.ToString(), ByteArray(numBytes()).ToBuffer())); - - public static void ValidateBFast(byte[] buffer, BFastBuilder srcBuilder) - { - var bfast = BFast.ReadBFast(buffer).ToArray(); - - var names = srcBuilder.BufferNames().ToArray(); - var sizes = srcBuilder.BufferSizes().ToArray(); - var numBuffers = names.Count(); - // We should have the same number of buffers - AssertEquals(bfast.Length, numBuffers); - for (var i = 0; i < numBuffers; i++) - { - // Of equal size - AssertEquals(bfast[i].Name, names[i]); - AssertEquals(bfast[i].Data.Length, sizes[i]); - // And they might be sub-buffers - if (srcBuilder.Children[i].Item2 is BFastBuilder childBuilder) - ValidateBFast(bfast[i].ToBytes(), childBuilder); - } - } - - [Test] - public static void TestNestedBFast() - { - var random = new Random(1234567); - // Create a nested BFast structure 3 layers deep with randomly-sized buffers between 1 & 256 bytes size - var builder = BFastWithSubs(3, 3, () => random.Next(1, 256)); - // Create a buffer to recieve this structure; - var buffer = new byte[builder.GetSize()]; - var stream = new MemoryStream(buffer, true); - builder.Write(stream); - - // Now, lets try and deserialize these buffers: - ValidateBFast(buffer, builder); - } - - public static void AssertEquals(T x, T y) - { - if (!x.Equals(y)) - throw new Exception($"Expected value {x} but instead got {y}"); - } - - /// - /// This test cannot be run from the test runner, because the App.Config option - /// has to be enabled from within the host program. - /// - public static void ReallyBigTest() - { - var xs = new Vector3[500 * 1000 * 1000]; - for (var i = 0; i < xs.Length; ++i) - xs[i] = new Vector3(i, i, i); - var filePath = Path.Combine(Path.GetTempPath(), "really_big_test.bfast"); - using (var stream = File.OpenWrite(filePath)) - stream.WriteBFast(new[] { ("buffer", xs) }); - - var name = ""; - Vector3[] ys; - using (var stream = File.OpenRead(filePath)) - { - var buffers = BFast.ReadBFast(stream).ToArray(); - if (buffers.Length != 1) - throw new Exception($"Expected exactly one buffer, not {buffers.Length}"); - (name, ys) = (buffers[0].Name, buffers[1].AsArray()); - } - if (name != "buffer") - throw new Exception($"Expected name of buffer to be buffer not {name}"); - AssertEquals(xs.Length, ys.Length); - AssertEquals(xs[0], ys[0]); - AssertEquals(xs[1], ys[1]); - AssertEquals(xs[xs.Length - 1], ys[ys.Length - 1]); - } - } -} diff --git a/src/cs/bfast/Vim.BFast.Tests/Vim.BFast.Tests.csproj b/src/cs/bfast/Vim.BFast.Tests/Vim.BFast.Tests.csproj deleted file mode 100644 index 81eae773..00000000 --- a/src/cs/bfast/Vim.BFast.Tests/Vim.BFast.Tests.csproj +++ /dev/null @@ -1,18 +0,0 @@ - - - - net6.0 - false - - - - - - - - - - - - - diff --git a/src/cs/bfast/Vim.BFast/BFast.cs b/src/cs/bfast/Vim.BFast/BFast.cs deleted file mode 100644 index cbbb6eea..00000000 --- a/src/cs/bfast/Vim.BFast/BFast.cs +++ /dev/null @@ -1,478 +0,0 @@ -/* - BFAST - Binary Format for Array Streaming and Transmission - Copyright 2019, VIMaec LLC - Copyright 2018, Ara 3D, Inc. - Usage licensed under terms of MIT License - https://github.com/vimaec/bfast - - The BFAST format is a simple, generic, and efficient representation of - buffers (arrays of binary data) with optional names. - - It can be used in place of a zip when compression is not required, or when a simple protocol - is required for transmitting data to/from disk, between processes, or over a network. -*/ - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Text; - -namespace Vim.BFast -{ - /// - /// Callback function allows clients to control writing the data to the output stream - /// - public delegate long BFastWriterFn(Stream writingStream, int bufferIdx, string bufferName, long bytesToWrite); - - /// - /// Wraps an array of byte buffers encoding a BFast structure and provides validation and safe access to the memory. - /// The BFAST file/data format is structured as follows: - /// * File header - Fixed size file descriptor - /// * Ranges - An array of pairs of offsets that point to the begin and end of each data arrays - /// * Array data - All of the array data is contained in this section. - /// - public static class BFast - { - /// - /// Given a position in the stream, tells us where the the next aligned position will be, if it the current position is not aligned. - /// - public static long ComputeNextAlignment(long n) - => IsAligned(n) ? n : n + Constants.ALIGNMENT - (n % Constants.ALIGNMENT); - - /// - /// Given a position in the stream, computes how much padding is required to bring the value to an aligned point. - /// - public static long ComputePadding(long n) - => ComputeNextAlignment(n) - n; - - /// - /// Computes the padding requires after the array of BFastRanges are written out. - /// - /// - /// - public static long ComputePadding(BFastRange[] ranges) - => ComputePadding(BFastPreamble.Size + ranges.Length * BFastRange.Size); - - - /// - /// Given a position in the stream, tells us whether the position is aligned. - /// - public static bool IsAligned(long n) - => n % Constants.ALIGNMENT == 0; - - /// - /// Writes n zero bytes. - /// - public static void WriteZeroBytes(this BinaryWriter bw, long n) - { - for (var i = 0L; i < n; ++i) - bw.Write((byte)0); - } - - /// - /// Checks that the stream (if seekable) is well aligned - /// - public static void CheckAlignment(Stream stream) - { - if (!stream.CanSeek) - return; - // TODO: Check with CD: Should we bail out here? This means that any - // alignment checks for a currently-writing stream are effectively ignored. - if (stream.Position == stream.Length) - return; - if (!IsAligned(stream.Position)) - throw new Exception($"Stream position {stream.Position} is not well aligned"); - } - - /// - /// Converts a collection of strings, into a null-separated byte[] array - /// - public static byte[] PackStrings(this IEnumerable strings) - { - var r = new List(); - foreach (var name in strings) - { - var bytes = Encoding.UTF8.GetBytes(name); - r.AddRange(bytes); - r.Add(0); - } - return r.ToArray(); - } - - /// - /// Converts a byte[] array encoding a collection of strings separate by NULL into an array of string - /// - public static string[] UnpackStrings(this byte[] bytes) - { - var r = new List(); - if (bytes.Length == 0) - return r.ToArray(); - var prev = 0; - for (var i = 0; i < bytes.Length; ++i) - { - if (bytes[i] == 0) - { - r.Add(Encoding.UTF8.GetString(bytes, prev, i - prev)); - prev = i + 1; - } - } - if (prev < bytes.Length) - r.Add(Encoding.UTF8.GetString(bytes, prev, bytes.Length - prev)); - return r.ToArray(); - } - - /// - /// Creates a BFAST structure, without any actual data buffers, from a list of sizes of buffers (not counting the name buffer). - /// Used as an intermediate step to create a BFAST. - /// - public static BFastHeader CreateBFastHeader(this long[] bufferSizes, string[] bufferNames) - { - if (bufferNames.Length != bufferSizes.Length) - throw new Exception($"The number of buffer sizes {bufferSizes.Length} is not equal to the number of buffer names {bufferNames.Length}"); - - var header = new BFastHeader - { - Names = bufferNames - }; - header.Preamble.Magic = Constants.Magic; - header.Preamble.NumArrays = bufferSizes.Length + 1; - - // Allocate the data for the ranges - header.Ranges = new BFastRange[header.Preamble.NumArrays]; - header.Preamble.DataStart = ComputeNextAlignment(header.Preamble.RangesEnd); - - var nameBufferLength = PackStrings(bufferNames).LongLength; - var sizes = (new[] { nameBufferLength }).Concat(bufferSizes).ToArray(); - - // Compute the offsets for the data buffers - var curIndex = header.Preamble.DataStart; - var i = 0; - foreach (var size in sizes) - { - curIndex = ComputeNextAlignment(curIndex); - Debug.Assert(IsAligned(curIndex)); - - header.Ranges[i].Begin = curIndex; - curIndex += size; - - header.Ranges[i].End = curIndex; - i++; - } - - // Finish with the header - // Each buffer we contain is padded to ensure the next one - // starts on alignment, so we pad our DataEnd to reflect this reality - header.Preamble.DataEnd = ComputeNextAlignment(curIndex); - - // Check that everything adds up - return header.Validate(); - } - - /// - /// Checks that the header values are sensible, and throws an exception otherwise. - /// - public static BFastPreamble Validate(this BFastPreamble preamble) - { - if (preamble.Magic != Constants.SameEndian && preamble.Magic != Constants.SwappedEndian) - throw new Exception($"Invalid magic number {preamble.Magic}"); - - if (preamble.DataStart < BFastPreamble.Size) - throw new Exception($"Data start {preamble.DataStart} cannot be before the file header size {BFastPreamble.Size}"); - - if (preamble.DataStart > preamble.DataEnd) - throw new Exception($"Data start {preamble.DataStart} cannot be after the data end {preamble.DataEnd}"); - - if (!IsAligned(preamble.DataEnd)) - throw new Exception($"Data end {preamble.DataEnd} should be aligned"); - - if (preamble.NumArrays < 0) - throw new Exception($"Number of arrays {preamble.NumArrays} is not a positive number"); - - if (preamble.NumArrays > preamble.DataEnd) - throw new Exception($"Number of arrays {preamble.NumArrays} can't be more than the total size"); - - if (preamble.RangesEnd > preamble.DataStart) - throw new Exception($"End of range {preamble.RangesEnd} can't be after data-start {preamble.DataStart}"); - - return preamble; - } - - /// - /// Checks that the header values are sensible, and throws an exception otherwise. - /// - public static BFastHeader Validate(this BFastHeader header) - { - var preamble = header.Preamble.Validate(); - var ranges = header.Ranges; - var names = header.Names; - - if (preamble.RangesEnd > preamble.DataStart) - throw new Exception($"Computed arrays ranges end must be less than the start of data {preamble.DataStart}"); - - if (ranges == null) - throw new Exception("Ranges must not be null"); - - var min = preamble.DataStart; - var max = preamble.DataEnd; - - for (var i = 0; i < ranges.Length; ++i) - { - var begin = ranges[i].Begin; - if (!IsAligned(begin)) - throw new Exception($"The beginning of the range is not well aligned {begin}"); - var end = ranges[i].End; - if (begin < min || begin > max) - throw new Exception($"Array offset begin {begin} is not in valid span of {min} to {max}"); - if (i > 0) - { - if (begin < ranges[i - 1].End) - throw new Exception($"Array offset begin {begin} is overlapping with previous array {ranges[i - 1].End}"); - } - - if (end < begin || end > max) - throw new Exception($"Array offset end {end} is not in valid span of {begin} to {max}"); - } - - if (names.Length < ranges.Length - 1) - throw new Exception($"Number of buffer names {names.Length} is not one less than the number of ranges {ranges.Length}"); - - return header; - } - - /// - /// Reads a BFAST from a file as a collection of named buffers. - /// - public static INamedBuffer[] Read(string filePath) - { - using (var stream = File.OpenRead(filePath)) - return Read(stream); - } - - /// - /// Reads a BFAST from a stream as a collection of named buffers. - /// - public static INamedBuffer[] Read(Stream stream) - => stream.ReadBFast().ToArray(); - - /// - /// Reads a BFAST buffer from a stream as a collection of named buffers. - /// This call limits the buffers to 2GB. - /// - public static IEnumerable ReadBFast(this Stream stream) - { - if (!stream.CanSeek) - { - throw new InvalidOperationException("Cannot read read non seekable stream. Consider using ReadBFastNoSeek."); - } - foreach (var br in stream.GetBFastBufferReaders()) - { - yield return br.GetBuffer(); - } - } - - /// - /// Reads a BFAST from a stream as a collection of named buffers. - /// This call limits the buffers to 2GB. - /// - public static unsafe IEnumerable> ReadBFast(this Stream stream) where T : unmanaged - => stream.ReadBFast>((s, bufferName, bufferLength) - => s.ReadArray((int)(bufferLength / sizeof(T))).ToNamedBuffer(bufferName)) - .Select(item => item.Item2); - - /// - /// Reads a BFAST from a byte array as a collection of named buffers. - /// This call limits the buffers to 2GB. - /// - public static INamedBuffer[] ReadBFast(this byte[] bytes) - { - using (var stream = new MemoryStream(bytes)) - return ReadBFast(stream).ToArray(); - } - - /// - /// Reads a BFAST buffer from a stream as a collection of named buffers. - /// This implementation does seek into the stream. - /// Supports non-seekable stream such as web stream. - /// - public static void ReadBFastNoSeek(this Stream stream, Func onBuffer) - { - var header = stream.ReadBFastHeader(); - BFast.CheckAlignment(stream); - - // position after ReadBFastHeader - var position = header.Ranges[1].Begin; - - // Range 0 is Buffer Names is already read so skip to i=1. - for (var i = 1; i < header.Ranges.Length; i++) - { - // Skip padding. - var skip = header.Ranges[i].Begin - position; - stream.SkipBytes(skip); - - if (!onBuffer(stream, header.Names[i - 1], header.Ranges[i].Count)) - { - break; - } - position = header.Ranges[i].End; - } - } - - /// - /// Writes the BFAST header and name buffer to stream using the provided BinaryWriter. The BinaryWriter will be properly aligned by padding zeros - /// - public static BinaryWriter WriteBFastHeader(this Stream stream, BFastHeader header) - { - if (header.Ranges.Length != header.Names.Length + 1) - throw new Exception($"The number of ranges {header.Ranges.Length} must be equal to one more than the number of names {header.Names.Length}"); - var bw = new BinaryWriter(stream); - bw.Write(header.Preamble.Magic); - bw.Write(header.Preamble.DataStart); - bw.Write(header.Preamble.DataEnd); - bw.Write(header.Preamble.NumArrays); - foreach (var r in header.Ranges) - { - bw.Write(r.Begin); - bw.Write(r.End); - } - WriteZeroBytes(bw, ComputePadding(header.Ranges)); - - CheckAlignment(stream); - var nameBuffer = PackStrings(header.Names); - bw.Write(nameBuffer); - WriteZeroBytes(bw, ComputePadding(nameBuffer.LongLength)); - - CheckAlignment(stream); - return bw; - } - - /// - /// Enables a user to write a BFAST from an array of names, sizes, and a custom writing function. - /// The function will receive a BinaryWriter, the index of the buffer, and is expected to return the number of bytes written. - /// Simplifies the process of creating custom BinaryWriters, or writing extremely large arrays if necessary. - /// - public static void WriteBFast(this Stream stream, string[] bufferNames, long[] bufferSizes, BFastWriterFn onBuffer) - { - if (bufferSizes.Any(sz => sz < 0)) - throw new Exception("All buffer sizes must be zero or greater than zero"); - - if (bufferNames.Length != bufferSizes.Length) - throw new Exception($"The number of buffer names {bufferNames.Length} is not equal to the number of buffer sizes {bufferSizes}"); - - var header = CreateBFastHeader(bufferSizes, bufferNames); - stream.WriteBFast(header, bufferNames, bufferSizes, onBuffer); - } - - /// - /// Enables a user to write a BFAST from an array of names, sizes, and a custom writing function. - /// This is useful when the header is already computed. - /// - public static void WriteBFast(this Stream stream, BFastHeader header, string[] bufferNames, long[] bufferSizes, BFastWriterFn onBuffer) - { - stream.WriteBFastHeader(header); - CheckAlignment(stream); - stream.WriteBFastBody(header, bufferNames, bufferSizes, onBuffer); - } - - /// - /// Must be called after "WriteBFastHeader" - /// Enables a user to write the contents of a BFAST from an array of names, sizes, and a custom writing function. - /// The function will receive a BinaryWriter, the index of the buffer, and is expected to return the number of bytes written. - /// Simplifies the process of creating custom BinaryWriters, or writing extremely large arrays if necessary. - /// - public static void WriteBFastBody(this Stream stream, BFastHeader header, string[] bufferNames, long[] bufferSizes, BFastWriterFn onBuffer) - { - CheckAlignment(stream); - - if (bufferSizes.Any(sz => sz < 0)) - throw new Exception("All buffer sizes must be zero or greater than zero"); - - if (bufferNames.Length != bufferSizes.Length) - throw new Exception($"The number of buffer names {bufferNames.Length} is not equal to the number of buffer sizes {bufferSizes}"); - - // Then passes the binary writer for each buffer: checking that the correct amount of data was written. - for (var i = 0; i < bufferNames.Length; ++i) - { - CheckAlignment(stream); - var nBytes = bufferSizes[i]; - var pos = stream.CanSeek ? stream.Position : 0; - var nWrittenBytes = onBuffer(stream, i, bufferNames[i], nBytes); - if (stream.CanSeek) - { - if (stream.Position - pos != nWrittenBytes) - throw new NotImplementedException($"Buffer:{bufferNames[i]}. Stream movement {stream.Position - pos} does not reflect number of bytes claimed to be written {nWrittenBytes}"); - } - - if (nBytes != nWrittenBytes) - throw new Exception($"Number of bytes written {nWrittenBytes} not equal to expected bytes{nBytes}"); - var padding = ComputePadding(nBytes); - for (var j = 0; j < padding; ++j) - stream.WriteByte(0); - CheckAlignment(stream); - } - } - - public static unsafe long ByteSize(this T[] self) where T : unmanaged - => self.LongLength * sizeof(T); - - public static unsafe void WriteBFast(this Stream stream, IEnumerable<(string, T[])> buffers) where T : unmanaged - { - var xs = buffers.ToArray(); - BFastWriterFn writerFn = (writer, index, name, size) => - { - var initPosition = writer.Position; - writer.Write(xs[index].Item2); - return writer.Position - initPosition; - }; - - stream.WriteBFast( - xs.Select(b => b.Item1), - xs.Select(b => b.Item2.ByteSize()), - writerFn); - } - - public static void WriteBFast(this Stream stream, IEnumerable bufferNames, IEnumerable bufferSizes, BFastWriterFn onBuffer) - => WriteBFast(stream, bufferNames.ToArray(), bufferSizes.ToArray(), onBuffer); - - public static byte[] WriteBFastToBytes(IEnumerable bufferNames, IEnumerable bufferSizes, BFastWriterFn onBuffer) - { - // NOTE: we can't call "WriteBFast(Stream ...)" directly because it disposes the stream before we can convert it to an array - using (var stream = new MemoryStream()) - { - WriteBFast(stream, bufferNames.ToArray(), bufferSizes.ToArray(), onBuffer); - return stream.ToArray(); - } - } - - public static void WriteBFastToFile(string filePath, IEnumerable bufferNames, IEnumerable bufferSizes, BFastWriterFn onBuffer) - => File.OpenWrite(filePath).WriteBFast(bufferNames, bufferSizes, onBuffer); - - public static unsafe byte[] WriteBFastToBytes(this (string Name, T[] Data)[] buffers) where T : unmanaged - => WriteBFastToBytes( - buffers.Select(b => b.Name), - buffers.Select(b => b.Data.LongLength * sizeof(T)), - (writer, index, name, size) => - { - var initPosition = writer.Position; - writer.Write(buffers[index].Data); - return writer.Position - initPosition; - }); - - public static BFastBuilder ToBFastBuilder(this IEnumerable buffers) - => new BFastBuilder().Add(buffers); - - public static BFastRange OffsetBy(this BFastRange range, long offset) - => new BFastRange() { - Begin = range.Begin + offset, - End = range.End + offset - }; - - public static BFastRange FullRange(this Stream stream) - => new BFastRange() - { - Begin = 0, - End = stream.Length - }; - } -} diff --git a/src/cs/bfast/Vim.BFast/BFastBufferReader.cs b/src/cs/bfast/Vim.BFast/BFastBufferReader.cs deleted file mode 100644 index 1d06d32e..00000000 --- a/src/cs/bfast/Vim.BFast/BFastBufferReader.cs +++ /dev/null @@ -1,209 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.IO.Compression; -using System.Linq; - -namespace Vim.BFast -{ - /// - /// Represents a BFAST buffer whose stream can be read after calling Seek(). - /// - public class BFastBufferReader - { - /// - /// The seekable stream from which the buffer can be read. - /// - private readonly Stream _stream; - - /// - /// The start position of the buffer in the stream. - /// - private readonly long _startPosition; - - /// - /// The size in bytes of the buffer. - /// - public readonly long Size; - - /// - /// The buffer name. - /// - public readonly string Name; - - /// - /// Deconstruct operator - /// - public void Deconstruct(out string name, out long size) - => (name, size) = (Name, Size); - - /// - /// Constructor. - /// - public BFastBufferReader(Stream stream, string name, long startPosition, long size) - { - _stream = stream; - _startPosition = startPosition; - Size = size; - Name = name; - } - - /// - /// Seeks to the start of the BFAST buffer and returns the stream. - /// - public Stream Seek() - { - _stream.Seek(_startPosition, SeekOrigin.Begin); - BFast.CheckAlignment(_stream); - return _stream; - } - - public NamedBuffer GetBuffer(bool inflate = false) where T : unmanaged - { - Seek(); - if (!inflate) - { - return _stream.ReadArray((int)Size).ToNamedBuffer(Name); - } - using(var deflated = new DeflateStream(_stream, CompressionMode.Decompress)){ - return _stream.ReadArray((int)Size).ToNamedBuffer(Name); - } - } - - public NamedBuffer GetBuffer(bool inflate = false) - { - return GetBuffer(inflate); - } - - } - - public static class BFastBufferReaderExtensions - { - - /// - /// Reads the preamble, the ranges, and the names of the rest of the buffers. - /// - public static BFastHeader ReadBFastHeader(this Stream stream) - { - var r = new BFastHeader(); - var br = new BinaryReader(stream); - - if (stream.Length - stream.Position < sizeof(long) * 4) - throw new Exception("Stream too short"); - - r.Preamble = new BFastPreamble - { - Magic = br.ReadInt64(), - DataStart = br.ReadInt64(), - DataEnd = br.ReadInt64(), - NumArrays = br.ReadInt64(), - }.Validate(); - - r.Ranges = stream.ReadArray((int)r.Preamble.NumArrays); - - var padding = BFast.ComputePadding(r.Ranges); - br.ReadBytes((int)padding); - BFast.CheckAlignment(br.BaseStream); - - var nameBytes = br.ReadBytes((int)r.Ranges[0].Count); - r.Names = nameBytes.UnpackStrings(); - - padding = BFast.ComputePadding(r.Ranges[0].End); - br.ReadBytes((int)padding); - BFast.CheckAlignment(br.BaseStream); - - return r.Validate(); - } - - /// - /// Returns a list of BFAST buffer readers in the stream. - /// Assumes the stream's current position designates a BFAST header. - /// - public static IReadOnlyList GetBFastBufferReaders( - this Stream stream, - Func filterFn = null) - { - var result = new List(); - - using (var seekContext = new SeekContext(stream)) - { - // Read the header - var header = stream.ReadBFastHeader(); - BFast.CheckAlignment(stream); - - // Create a BFastBufferReader for each range. - for (var i = 1; i < header.Ranges.Length; ++i) - { - var range = header.Ranges[i]; - var name = header.Names[i - 1]; - - var startSeekPosition = seekContext.OriginalSeekPosition + range.Begin; - var size = range.End - range.Begin; - - var bfastBufferReader = new BFastBufferReader(seekContext.Stream, name, startSeekPosition, size); - - if (filterFn?.Invoke(bfastBufferReader) ?? true) - { - result.Add(bfastBufferReader); - } - } - } - - return result; - } - - /// - /// Returns a BFAST buffer reader corresponding to the given buffer name. - /// Returns null if the given buffer name was not found or if the buffer name is null or empty. - /// - public static BFastBufferReader GetBFastBufferReader(this Stream stream, string bufferName) - => string.IsNullOrEmpty(bufferName) - ? null - : stream.GetBFastBufferReaders(br => br.Name == bufferName).FirstOrDefault(); - - - public static NamedBuffer GetBFastBuffer(this Stream stream, string bufferName, bool inflate = false) - { - - var buffer = stream.GetBFastBufferReader(bufferName).GetBuffer(); - return buffer; - - // if (!inflate) return buffer; - // var bytes = buffer.GetTypedData(); - // using(var inflate = new DeflateStream(stream, CompressionMode.Decompress)); - } - - public static void SeekToBFastBuffer(this Stream stream, string bufferName) - => stream.GetBFastBufferReader(bufferName).Seek(); - - - /// - /// Reads a BFAST stream and returns a list of labeled results. - /// - public static List<(string Label, T Result)> ReadBFast( - this Stream stream, - Func onBuffer) - { - var result = new List<(string, T)>(); - - foreach (var br in stream.GetBFastBufferReaders()) - { - var name = br.Name; - var s = br.Seek(); - result.Add((name, onBuffer(s, name, br.Size))); - } - - return result; - } - - /// - /// Returns a named buffer corresponding to the given bufferName. Returns null if no buffer name is found. - /// This call limits the buffers to 2GB. - /// - public static NamedBuffer ReadBFastBuffer(this Stream stream, string bufferName) where T : unmanaged - { - var br = stream.GetBFastBufferReader(bufferName); - return br?.GetBuffer(); - } - } -} diff --git a/src/cs/bfast/Vim.BFast/BFastBuilder.cs b/src/cs/bfast/Vim.BFast/BFastBuilder.cs deleted file mode 100644 index 0cac6a5c..00000000 --- a/src/cs/bfast/Vim.BFast/BFastBuilder.cs +++ /dev/null @@ -1,97 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; - -namespace Vim.BFast -{ - /// - /// Anything that can be added to a BFAST must have a size and write to a stream. - /// - public interface IBFastComponent - { - long GetSize(); - void Write(Stream stream); - } - - /// - /// A wrapper around a buffer so that it can be used as a BFAST component - /// - public class BufferAsBFastComponent : IBFastComponent - { - public BufferAsBFastComponent(IBuffer buffer) - => Buffer = buffer; - public IBuffer Buffer { get; } - public void Write(Stream stream) => stream.Write(Buffer); - public long GetSize() => Buffer.NumBytes(); - } - - /// - /// Used to build BFASTs incrementally that contain named buffers and/or other BFASTs. - /// - public class BFastBuilder : IBFastComponent - { - public BFastHeader Header { get; private set; } - public long GetSize() => GetOrComputeHeader().Preamble.DataEnd; - - public List<(string, IBFastComponent)> Children { get; } = new List<(string, IBFastComponent)>(); - - public void Write(Stream stream) - => stream.WriteBFast(GetOrComputeHeader(), - BufferNames().ToArray(), - BufferSizes().ToArray(), - OnBuffer); - - public void Write(string filePath) - { - using (var stream = File.OpenWrite(filePath)) - Write(stream); - } - - public long OnBuffer(Stream stream, int index, string name, long size) - { - var (bufferName, x) = Children[index]; - Debug.Assert(name == bufferName); - Debug.Assert(size != GetSize()); - Debug.Assert(size == x.GetSize()); - x.Write(stream); - return size; - } - - public BFastHeader GetOrComputeHeader() - => Header ?? (Header = BFast.CreateBFastHeader( - BufferSizes().ToArray(), BufferNames().ToArray())); - - private BFastBuilder _add(string name, IBFastComponent component) - { - Header = null; - Children.Add((name, component)); - return this; - } - - public BFastBuilder Add(string name, IBFastComponent component) - => _add(name, component); - - public BFastBuilder Add(string name, IBuffer buffer) - => _add(name, new BufferAsBFastComponent(buffer)); - - public BFastBuilder Add(Func getName, IEnumerable buffers) - => Add(buffers.Select((b, i) => b.ToNamedBuffer(getName(i)))); - - public BFastBuilder Add(INamedBuffer buffer) - => Add(buffer.Name, buffer); - - public BFastBuilder Add(IEnumerable buffers) - => buffers.Aggregate(this, (x, y) => x.Add(y)); - - public BFastBuilder Add(string name, IEnumerable buffers) - => Add(name, new BFastBuilder().Add(buffers)); - - public IEnumerable BufferNames() - => Children.Select(x => x.Item1); - - public IEnumerable BufferSizes() - => Children.Select(x => x.Item2.GetSize()); - } -} diff --git a/src/cs/bfast/Vim.BFast/BFastStructs.cs b/src/cs/bfast/Vim.BFast/BFastStructs.cs deleted file mode 100644 index 46cb0dde..00000000 --- a/src/cs/bfast/Vim.BFast/BFastStructs.cs +++ /dev/null @@ -1,113 +0,0 @@ -/* - BFAST - Binary Format for Array Streaming and Transmission - Copyright 2019, VIMaec LLC - Copyright 2018, Ara 3D, Inc. - Usage licensed under terms of MIT License - https://github.com/vimaec/bfast - - The BFAST format is a simple, generic, and efficient representation of - buffers (arrays of binary data) with optional names. - - It can be used in place of a zip when compression is not required, or when a simple protocol - is required for transmitting data to/from disk, between processes, or over a network. -*/ - -using System.Linq; -using System.Runtime.InteropServices; - -namespace Vim.BFast -{ - /// - /// This contains the BFAST data loaded or written from disk. - /// - public class BFastHeader - { - public BFastPreamble Preamble = new BFastPreamble(); - public BFastRange[] Ranges; - public string[] Names; - - public override bool Equals(object o) - => o is BFastHeader other && Equals(other); - - public bool Equals(BFastHeader other) - => Preamble.Equals(other.Preamble) && - Ranges.Length == other.Ranges.Length && - Ranges.Zip(other.Ranges, (x, y) => x.Equals(y)).All(x => x) && - Names.Zip(other.Names, (x, y) => x.Equals(y)).All(x => x); - } - - /// - /// Constants. - /// - public static class Constants - { - public const long Magic = 0xBFA5; - - // https://en.wikipedia.org/wiki/Endianness - public const long SameEndian = Magic; - public const long SwappedEndian = 0xA5BFL << 48; - - /// - /// Data arrays are aligned to 64 bytes, so that they can be cast directly to AVX-512 registers. - /// This is useful for efficiently working with floating point data. - /// - public const long ALIGNMENT = 64; - } - - /// - /// This tells us where a particular array begins and ends in relation to the beginning of a file. - /// * Begin must be less than or equal to End. - /// * Begin must be greater than or equal to DataStart - /// * End must be less than or equal to DataEnd - /// - [StructLayout(LayoutKind.Explicit, Pack = 8, Size = 16)] - public struct BFastRange - { - [FieldOffset(0)] public long Begin; - [FieldOffset(8)] public long End; - - public long Count => End - Begin; - public static long Size = 16; - - public override bool Equals(object x) - => x is BFastRange other && Equals(other); - - public bool Equals(BFastRange other) - => Begin == other.Begin && End == other.End; - } - - /// - /// The header contains a magic number, the begin and end indices of data, and the number of arrays. - /// - [StructLayout(LayoutKind.Explicit, Pack = 8, Size = 32)] - public struct BFastPreamble - { - [FieldOffset(0)] public long Magic; // Either Constants.SameEndian or Constants.SwappedEndian depending on endianess of writer compared to reader. - [FieldOffset(8)] public long DataStart; // <= file size and >= ArrayRangesEnd and >= FileHeader.ByteCount - [FieldOffset(16)] public long DataEnd; // >= DataStart and <= file size - [FieldOffset(24)] public long NumArrays; // number of arrays - - /// - /// This is where the array ranges are finished. - /// Must be less than or equal to DataStart. - /// Must be greater than or equal to FileHeader.ByteCount - /// - public long RangesEnd => Size + NumArrays * 16; - - /// - /// The size of the FileHeader structure - /// - public static long Size = 32; - - /// - /// Returns true if the producer of the BFast file has the same endianness as the current library - /// - public bool SameEndian => Magic == Constants.SameEndian; - - public override bool Equals(object x) - => x is BFastPreamble other && Equals(other); - - public bool Equals(BFastPreamble other) - => Magic == other.Magic && DataStart == other.DataStart && DataEnd == other.DataEnd && NumArrays == other.NumArrays; - }; -} diff --git a/src/cs/bfast/Vim.BFast/BufferExtensions.cs b/src/cs/bfast/Vim.BFast/BufferExtensions.cs deleted file mode 100644 index d07b8eb5..00000000 --- a/src/cs/bfast/Vim.BFast/BufferExtensions.cs +++ /dev/null @@ -1,89 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; - -namespace Vim.BFast -{ - /// - /// Helper functions for working with buffers - /// - public static class BufferExtensions - { - public static Buffer ToBuffer(this T[] xs) where T : unmanaged - => new Buffer(xs); - - public static NamedBuffer ToNamedBuffer(this T[] xs, string name = "") where T : unmanaged - => new NamedBuffer(xs, name); - - public static NamedBuffer ToNamedBuffer(this IBuffer buffer, string name = "") - => new NamedBuffer(buffer, name); - - public static NamedBuffer ToNamedBuffer(this IBuffer xs, string name = "") where T : unmanaged - => new NamedBuffer(xs.GetTypedData(), name); - - public static IEnumerable ToNamedBuffers(this IEnumerable buffers, IEnumerable names = null) - => names == null ? buffers.Select(b => b.ToNamedBuffer("")) : buffers.Zip(names, ToNamedBuffer); - - public static IDictionary ToDictionary(this IEnumerable buffers) - => buffers.ToDictionary(b => b.Name, b => b); - - public static IEnumerable ToNamedBuffers(this IDictionary d) - => d.Select(kv => kv.Value.ToNamedBuffer(kv.Key)); - - public static IEnumerable ToNamedBuffers(this IDictionary d) - => d.Select(kv => kv.Value.ToNamedBuffer(kv.Key)); - - public static Array CopyBytes(this IBuffer src, Array dst, int srcOffset = 0, int destOffset = 0) - { - Buffer.BlockCopy(src.Data, srcOffset, dst, destOffset, (int)src.NumBytes()); - return dst; - } - - public static byte[] ToBytes(this IBuffer src, byte[] dest = null) - => src.ToArray(dest); - - public static byte[] ToBytes(this T[] xs, byte[] dest = null) where T : unmanaged - => xs.RecastArray(dest); - - public static byte[] ToBytes(this T x) where T : unmanaged - => ToBytes(new[] { x }); - - /// - /// Accepts an array of the given type, or creates one if necessary, copy the buffer data into it - /// - public static unsafe T[] ToArray(this IBuffer buffer, T[] dest = null) where T : unmanaged - => (T[])buffer.CopyBytes(dest ?? new T[buffer.NumBytes() / sizeof(T)]); - - /// - /// Returns the array in the buffer, if it is of the correct type, or creates a new array of the create type and copies - /// bytes into it, as necessary. - /// - public static unsafe T[] AsArray(this IBuffer buffer) where T : unmanaged - => buffer.Data is T[] r ? r : buffer.ToArray(); - - /// - /// Copies an array of unmanaged types into another array of unmanaged types - /// - public static unsafe U[] RecastArray(this T[] src, U[] r = null) where T : unmanaged where U : unmanaged - => src.ToBuffer().ToArray(r); - - public static int NumElements(this IBuffer buffer) - => buffer.Data.Length; - - public static long NumBytes(this IBuffer buffer) - => (long)buffer.NumElements() * buffer.ElementSize; - - public static Buffer ReadBufferFromNumberOfBytes(this Stream stream, long numBytes) where T : unmanaged - => stream.ReadArrayFromNumberOfBytes(numBytes).ToBuffer(); - - public static Buffer ReadBuffer(this Stream stream, int numElements) where T : unmanaged - => stream.ReadArray(numElements).ToBuffer(); - - public static Buffer ReadBuffer(this Stream stream, int numBytes) - => stream.ReadBuffer(numBytes); - - public static void Write(this Stream stream, IBuffer buffer) - => buffer.Write(stream); - } -} diff --git a/src/cs/bfast/Vim.BFast/Buffers.cs b/src/cs/bfast/Vim.BFast/Buffers.cs deleted file mode 100644 index 8039f273..00000000 --- a/src/cs/bfast/Vim.BFast/Buffers.cs +++ /dev/null @@ -1,77 +0,0 @@ -using System; -using System.IO; - -namespace Vim.BFast -{ - /// - /// Provides an interface to an object that manages a potentially large array of elements all of the same unmanaged type. - /// - public interface IBuffer - { - Array Data { get; } - int ElementSize { get; } - void Write(Stream stream); - } - - /// - /// A version of the IBuffer interface when the element types are known - /// - public interface IBuffer : IBuffer - { - T[] GetTypedData(); - } - - /// - /// Represents a buffer associated with a string name. - /// - public interface INamedBuffer : IBuffer - { - string Name { get; } - } - - /// - /// A version of the INamedBuffer interface when the element types are known - /// - public interface INamedBuffer : INamedBuffer, IBuffer - { - } - - /// - /// A concrete implementation of IBuffer - /// - public unsafe class Buffer : IBuffer where T : unmanaged - { - public Buffer(T[] data) => Data = data; - public int ElementSize => sizeof(T); - public Array Data { get; } - public T[] GetTypedData() => Data as T[]; - public void Write(Stream stream) => stream.Write(GetTypedData()); - } - - /// - /// A concrete implementation of INamedBuffer - /// - public class NamedBuffer : INamedBuffer - { - public NamedBuffer(IBuffer buffer, string name) => (Buffer, Name) = (buffer, name); - public IBuffer Buffer { get; } - public string Name { get; } - public int ElementSize => Buffer.ElementSize; - public Array Data => Buffer.Data; - public void Write(Stream stream) => Buffer.Write(stream); - } - - /// - /// A concrete implementation of INamedBuffer with a specific type. - /// - public class NamedBuffer : INamedBuffer where T : unmanaged - { - public NamedBuffer(T[] data, string name) => (Array, Name) = (data, name); - public string Name { get; } - public unsafe int ElementSize => sizeof(T); - public readonly T[] Array; - public Array Data => Array; - public T[] GetTypedData() => Array; - public void Write(Stream stream) => stream.Write(Array); - } -} diff --git a/src/cs/bfast/Vim.BFast/SeekContext.cs b/src/cs/bfast/Vim.BFast/SeekContext.cs deleted file mode 100644 index eea7102e..00000000 --- a/src/cs/bfast/Vim.BFast/SeekContext.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System; -using System.IO; - -namespace Vim.BFast -{ - /// - /// Manages a Stream's seek pointer within a given `using` scope. - /// When the stream context is disposed, the seek position is reset - /// to the original position when the object was created. - /// - public sealed class SeekContext : IDisposable - { - /// - /// The seekable stream. - /// - public readonly Stream Stream; - - /// - /// The original stream seek position when the object was created. - /// - public readonly long OriginalSeekPosition; - - /// - /// Constructor. - /// - public SeekContext(Stream stream) - { - if (!stream.CanSeek) - throw new ArgumentException("Stream must be seekable."); - - Stream = stream; - OriginalSeekPosition = stream.Position; - } - - /// - /// Disposer. - /// - public void Dispose() - => Stream.Seek(OriginalSeekPosition, SeekOrigin.Begin); - } -} diff --git a/src/cs/bfast/Vim.BFast/UnsafeHelpers.cs b/src/cs/bfast/Vim.BFast/UnsafeHelpers.cs deleted file mode 100644 index 8d849f5a..00000000 --- a/src/cs/bfast/Vim.BFast/UnsafeHelpers.cs +++ /dev/null @@ -1,176 +0,0 @@ -using System; -using System.Drawing; -using System.IO; - -namespace Vim.BFast -{ - /// - /// This class would benefit from being in a generic utilities class, however, having it here allows BFAST to be a standalone without dependencies. - /// - public static class UnsafeHelpers - { - /// - /// Helper for reading arbitrary unmanaged types from a Stream. - /// - public static unsafe void ReadBytesBuffered(this Stream stream, byte* dest, long count, int bufferSize = 4096) - { - var buffer = new byte[bufferSize]; - int bytesRead; - fixed (byte* pBuffer = buffer) - { - while ((bytesRead = stream.Read(buffer, 0, (int)Math.Min(buffer.Length, count))) > 0) - { - if (dest != null) - Buffer.MemoryCopy(pBuffer, dest, count, bytesRead); - count -= bytesRead; - dest += bytesRead; - } - } - } - - /// - /// Helper for writing arbitrary large numbers of bytes - /// - public static unsafe void WriteBytesBuffered(this Stream stream, byte* src, long count, int bufferSize = 4096) - { - var buffer = new byte[bufferSize]; - fixed (byte* pBuffer = buffer) - { - while (count > 0) - { - var toWrite = (int)Math.Min(count, buffer.Length); - Buffer.MemoryCopy(src, pBuffer, buffer.Length, toWrite); - stream.Write(buffer, 0, toWrite); - count -= toWrite; - src += toWrite; - } - } - } - - /// - /// Helper for reading arbitrary unmanaged types from a Stream. - /// - public static unsafe void Read(this Stream stream, T* dest) where T : unmanaged - => stream.ReadBytesBuffered((byte*)dest, sizeof(T)); - - /// - /// Helper for reading arrays of arbitrary unmanaged types from a Stream, that might be over 2GB of size. - /// That said, in C#, you can never load more int.MaxValue numbers of items. - /// NOTE: Arrays are still limited to 2gb in size unless gcAllowVeryLargeObjects is set to true - /// in the runtime environment. - /// https://docs.microsoft.com/en-us/dotnet/api/system.array?redirectedfrom=MSDN&view=netframework-4.7.2#remarks - /// Alternatively, we could convert to .Net Core - /// - public static unsafe T[] ReadArray(this Stream stream, int count) where T : unmanaged - { - var r = new T[count]; - fixed (T* pDest = r) - { - - var pBytes = (byte*)pDest; - stream.ReadBytesBuffered(pBytes, (long)count * sizeof(T)); - } - return r; - } - - public static unsafe void ReadArray(this Stream stream, T[] array, int count) where T : unmanaged - { - fixed (T* pDest = array) - { - var pBytes = (byte*)pDest; - stream.ReadBytesBuffered(pBytes, (long)count * sizeof(T)); - } - } - - - /// - /// Equivalent to ReadArray to use when you know the byte count instead of element count. - /// - public static unsafe T[] ReadArrayBytes(this Stream stream, int byteLength) where T : unmanaged - { - return ReadArray(stream, byteLength / sizeof(T)); - } - - /* - public static unsafe T[] ConvertByteArrayToTypeArray(byte[] byteArray) where T : unmanaged - { - if (byteArray.Length % sizeof(T) != 0) - { - throw new ArgumentException("Byte array length is not a multiple of the size of the target type."); - } - - var elementCount = byteArray.Length / sizeof(T); - var resultArray = new T[elementCount]; - - fixed (byte* bytePtr = byteArray) - { - byte* currentBytePtr = bytePtr; - fixed (T* resultPtr = resultArray) - { - var currentResultPtr = resultPtr; - for (var i = 0; i < elementCount; i++) - { - *currentResultPtr = *((T*)currentBytePtr); - currentBytePtr += sizeof(T); - currentResultPtr++; - } - } - } - - return resultArray; - } - - */ - /// - /// A wrapper for stream.Seek(numBytes, SeekOrigin.Current) to avoid allocating memory for unrecognized buffers. - /// - public static void SkipBytes(this Stream stream, long numBytes) - => stream.Seek(numBytes, SeekOrigin.Current); - - /// - /// Helper for reading arrays of arbitrary unmanaged types from a Stream, that might be over 2GB of size. - /// That said, in C#, you can never load more int.MaxValue numbers of items. - /// - public static unsafe T[] ReadArrayFromNumberOfBytes(this Stream stream, long numBytes) where T : unmanaged - { - var count = numBytes / sizeof(T); - if (numBytes % sizeof(T) != 0) - throw new Exception($"The number of bytes {numBytes} is not divisible by the size of the type {sizeof(T)}"); - if (count >= int.MaxValue) - throw new Exception($"{count} exceeds the maximum number of items that can be read into an array {int.MaxValue}"); - return stream.ReadArray((int)count); - } - - /// - /// Helper for writing arbitrary unmanaged types - /// - public static unsafe void WriteValue(this Stream stream, T x) where T : unmanaged - { - var p = &x; - stream.WriteBytesBuffered((byte*)p, sizeof(T)); - } - - - /// - /// Helper for writing arrays of unmanaged types - /// - public static unsafe void Write(this Stream stream, T[] xs) where T : unmanaged - { - fixed (T* p = xs) - { - stream.WriteBytesBuffered((byte*)p, xs.LongLength * sizeof(T)); - } - } - - /// - /// Helper for writing arrays of unmanaged types - /// - public static unsafe void Write(this Stream stream, T[] xs, long count) where T : unmanaged - { - fixed (T* p = xs) - { - stream.WriteBytesBuffered((byte*)p, count * sizeof(T)); - } - } - } -} diff --git a/src/cs/bfast/Vim.BFast/Vim.BFast.csproj b/src/cs/bfast/Vim.BFast/Vim.BFast.csproj deleted file mode 100644 index 1e855d5b..00000000 --- a/src/cs/bfast/Vim.BFast/Vim.BFast.csproj +++ /dev/null @@ -1,37 +0,0 @@ - - - - netstandard2.0 - Vim.BFast - https://github.com/vimaec/bfast - https://github.com/vimaec/bfast - GitHub - true - license.txt - BFAST is a library for converting collections of named binary buffers to a single byte array for efficient cross-platform serialization and deserialization. - 1.5.0.0 - 1.5.0.0 - 1.5.0 - true - true - true - true - snupkg - - - - - - - - true - - - - - True - - - - - diff --git a/src/cs/bfast/Vim.BFast/readme.md b/src/cs/bfast/Vim.BFast/readme.md deleted file mode 100644 index 4525dbd1..00000000 --- a/src/cs/bfast/Vim.BFast/readme.md +++ /dev/null @@ -1,76 +0,0 @@ -# BFAST - -[](https://www.nuget.org/packages/Vim.Bfast) - -BFAST stands for the **B**inary **F**ormat for **A**rray **S**erialization and **T**ransmission. - -## Summary - -BFAST is an extremely efficent and simple alternative to ProtoBuf and FlatBuffers, whe data that follows the form -of a collection of name/value pairs where names are strings, and values are arrays of bytes. - -* Unlike JSON, XML, and YAML: BFAST is binary -* Unlike ProtoBuf and FlatBuffers: BFAST does not require a schema -* Unlike TAR: BFAST is simple and easy to implement -* Unlike ZIP: BFAST is not concerned with compression - -## Details - -BFAST is a data format for simple and efficient serialization and deserialization of -collections of named data buffers in a generic and cross-platform manner. -A BFAST data buffer is a named arrays of binary data (bytes) that is aligned on 64 byte boundaries. - -You would use tshe BFAST structure if you have a binary data to serialize that is mostly in the form of -long arrays. For example a set of files that you want to bundle together without wanting to bring in -the overhead of a compression library or re-implementing TAR. We use BFAST to encode mesh data and as -containers for other data. - -BFAST is intended to be a high-performance implementation that is fast enough to use as a purely -in-memory low-level data format, for representing arbitrary data such as meshes, point-clouds, image data, -collections of files, etc. and to scale to data that must be processed out of core. One of the design goals was to assure -that the format could be easily and efficiently decoded using JavaScript on most modern web-browsers -with very little code. - -BFAST is maintained by [VIMaec LLC](https://www.vimaec.com) and is licensed under the terms of -the MIT License. - -## Features - -* Very small implementation overhead -* Easy to implement efficient and conformant encoders and decoders in different languages -* Fast random access to any point in the data format with a minimum of disk accesses -* Format and endianess easily identified through a magic number at the front of the file -* Data arrays are 64 byte aligned to facilitate casting to SIMD data types (eg. AVX-512) -* Array offsets are encoded using 64-bit integers to supports large data sets -* Positions of data buffers are encoded in the beginning of the file -* Quick and easy to validate that a block is a valid BFAST encoding of data - -## Rationale - -Encoding containers of binary data is a deceptively simple problem that is easy to solve -in ways that have are not as efficient of generic as possible, or dependent on a particular platform. -We proposing a standardized solution to the problem in the form of a specification and sample -implementation that can allow software to easily encode low level binary data in a manner -that is both efficient and cross-platform. - -## Related Libraries - -The following is a partial list of commonly used binary data serialization formats: - -* [Protcol Buffers](https://developers.google.com/protocol-buffers/) -* [FlatBuffers](https://github.com/google/flatbuffers) -* [BINN](https://github.com/liteserver/binn/) -* [BSON](http://bsonspec.org/) -* [UBJSON](http://ubjson.org/) -* [MessagePack](https://msgpack.org/) -* [CBOR](https://cbor.io/) -* [TAR](https://www.gnu.org/software/tar/manual/html_node/Standard.html) - -For a more comprehensive list see: - -* https://en.wikipedia.org/wiki/Comparison_of_data-serialization_formats -* https://en.wikipedia.org/wiki/List_of_archive_formats - -# Specification - -See the file [spec.txt](spec.txt) for the official specification. diff --git a/src/cs/bfast/Vim.BFast/spec.txt b/src/cs/bfast/Vim.BFast/spec.txt deleted file mode 100644 index 1e432cf0..00000000 --- a/src/cs/bfast/Vim.BFast/spec.txt +++ /dev/null @@ -1,100 +0,0 @@ -BFAST Specification Proposal -June 23rd, 2020 - -Summary - -BFAST is a simple high-performance general purpose method of packing and unpacking named -arrays of binary data for serialization, deserialization, and transport in a cross-platform -and language agnostic manner. - -Introduction - -Of the myriad standardized formats for binary representation of structured data most -are very general and support nested data and schemas. - -One of the most common use case for structured binary data are collections of key/value -pairs where each key is a string and the value is an array of bytes. -An example of this are archive file formats like TAR and ZIP. Many 3D and image formats -data also follow this format. - -When data conforms to this kind of schema, then most binary formats (e.g CBOR, FlatBuffers, -ProtoBuf, Capnproto, etc.) introduce more overhead than is required, in terms of -memory, performance, and code. - -Often developers encountering this scenario will write an ad-hoc serialization/deserialization -protocol, which can lead to some problems: - - * Endianness may or may not be considered - * When memory mapping the structure, O(1) random access to buffers might not possible - * Programs written by other developers cannot easily deduce the layout of the format - * Alignment of the buffers might not be suitable for fast processing of the data arrays - * Testing and validation of the protocol might not be suitably robust - -The BFAST format is intended to provide a simple open standard that developers can use instead of -rolling their own. We have used in production code in a multitude of scenarios on a wide range of -devices and languages, and found it to be quite satsifactory in terms of efficiency and simplicity. - -Like TAR, BFAST is explicitly not a compression format, and can be easily compressed using -any compression algorithm. It is appropriate for use as an archive format, or as a container -format for other more complex file formats that provide additional semantic requirements -on the usage and naming of specific buffers. - -Features - - * The file format can be quickly detected reading the first 8 bytes - * Endianness of the writer can be detected from first 8 bytes, and compensated for by a reader - * Buffers names are stored in the first buffer, and can be quickly retrieved - * Each data-buffer is aligned on 64 bytes (for easy SIMD register alignment) - * Buffer begin/end positions are stored in the beginning of the file for fast seeking to data - * Buffer names can be arbitrarily long sequences of Utf-8 characters - * Buffers can be over 2GB in length - -Header Layout - - Preamble (bytes 0..32) - int64_t Magic; - int64_t DataStart; // The beginning position of the first data buffer, 64 byte aligned - int64_t DataEnd; // The end position of the last data buffer - int64_t Count; // Number of all buffers, including name buffer. There should always be at least 1 buffer. - - Ranges (bytes 32..32 + NumArray*16) - int64_t Begin; - int64_t End; - -Requirements - - * The first eight bytes are 0xBFA5 - * The file can be encoded as big-endian or little-endian - * If the endianness of the reader is different then the writer, the eight bytes will apprea as 0xA5BF << 48; - * Each DataBuffer starts on a 64 byte aligned buffer - * Buffer names are stored as null terminated Utf8 strings in the first buffer - * There are always exactly n-1 buffer names, where n is the number of buffers - * Buffer names can be empty (0 length strings) - * Multiple buffers can have the same name - * There is no padding between each range structure - * There is no padding between the header and the range - * The range struct is 16 bytes long - * The header struct is 32 bytes - * A data buffer could be empty, in which case, the begin and end is the same - * If a data buffer is empty, the the next data buffer will point to the data buffer beginning - * The DataStart can be computed by align(64, sizeof(Header) + sizeof(Range) * Header.NumArrays) - * Header.DataStart is equivalent to Range[0].Begin - * Header.DataEnd is equivalent to Range[N-1].End - -Related Information - - * [Zip]https://en.wikipedia.org/wiki/Zip_(file_format) - * [Protcol Buffers](https://developers.google.com/protocol-buffers/) - * [FlatBuffers](https://github.com/google/flatbuffers) - * [BINN](https://github.com/liteserver/binn/) - * [BSON](http://bsonspec.org/) - * [UBJSON](http://ubjson.org/) - * [MessagePack](https://msgpack.org/) - * [CBOR](https://cbor.io/) - * [TAR](https://www.gnu.org/software/tar/manual/html_node/Standard.html) - -For a more comprehensive list see: - - * [Comparison of Data Serialization Formats](https://en.wikipedia.org/wiki/Comparison_of_data-serialization_formats) - * [List of Archive Formats](https://en.wikipedia.org/wiki/List_of_archive_formats) - diff --git a/src/cs/g3d/Vim.G3d.Tests/G3dTestUtils.cs b/src/cs/g3d/Vim.G3d.Tests/G3dTestUtils.cs index 0a28e014..00c435f2 100644 --- a/src/cs/g3d/Vim.G3d.Tests/G3dTestUtils.cs +++ b/src/cs/g3d/Vim.G3d.Tests/G3dTestUtils.cs @@ -101,7 +101,7 @@ public static G3D CompareTiming(string fileName, string outputFolder) var g3d = m.ToG3D(); AssertSame(m, g3d); var outputFile = Path.Combine(outputFolder, Path.GetFileName(fileName) + ".g3d"); - g3d.Write(outputFile); + g3d.ToBFast().Write(outputFile); var r = TimeLoadingFile(outputFile, G3D.Read); //OutputG3DStats(g3d); AssertSame(g3d, r); diff --git a/src/cs/g3d/Vim.G3d.Tests/G3dTests.cs b/src/cs/g3d/Vim.G3d.Tests/G3dTests.cs index 363a020d..0493bc02 100644 --- a/src/cs/g3d/Vim.G3d.Tests/G3dTests.cs +++ b/src/cs/g3d/Vim.G3d.Tests/G3dTests.cs @@ -10,7 +10,7 @@ namespace Vim.G3d.Tests { - [TestFixture, Ignore("Ignored until the new version is ready")] + [TestFixture] public static class G3dTests { public class FileLoadData @@ -128,7 +128,7 @@ public static void OpenAndConvertAssimpFiles() f.G3DFile = new FileInfo(outputFilePath); f.MSecToSaveG3d = Util.GetMSecElapsed(() => - f.G3d.Write(outputFilePath)); + f.G3d.ToBFast().Write(outputFilePath)); } catch (Exception e) { @@ -215,7 +215,7 @@ public static void TriangleTest() .Add(materialIndices.ToIArray().ToFaceMaterialAttribute()) .ToG3D(); - var bytes = g3d.WriteToBytes(); + var bytes = g3d.ToBFast().AsBytes(); var g = G3D.Read(bytes); Assert.IsNotNull(g); @@ -253,7 +253,7 @@ public static void QuadAndCopyTest() .Add(materialIndices.ToIArray().ToFaceMaterialAttribute()) .ToG3D(); - var bytes = g3d.WriteToBytes(); + var bytes = g3d.ToBFast().AsBytes(); var g = G3D.Read(bytes); Assert.IsNotNull(g); @@ -335,7 +335,7 @@ public static void BigFileTest() var g3d = bldr.ToG3D(); Assert.AreEqual(nVerts, g3d.NumVertices); var tempFile = Path.Combine(Path.GetTempPath(), "bigfile.g3d"); - g3d.Write(tempFile); + g3d.ToBFast().Write(tempFile); var tmp = G3D.Read(tempFile); ValidateSameG3D(g3d, tmp); } diff --git a/src/cs/g3d/Vim.G3d/G3dSerialization.cs b/src/cs/g3d/Vim.G3d/G3dSerialization.cs index ba7e59a7..f62b54a4 100644 --- a/src/cs/g3d/Vim.G3d/G3dSerialization.cs +++ b/src/cs/g3d/Vim.G3d/G3dSerialization.cs @@ -1,7 +1,9 @@ using System; using System.IO; -using System.Linq; -using Vim.BFast; +using Vim.BFastNextNS; +using Vim.Buffers; +using Vim.LinqArray; +using System.Collections.Generic; namespace Vim.G3d { @@ -17,107 +19,47 @@ public static void WriteAttribute(Stream stream, GeometryAttribute attribute, st stream.Write(buffer); } - public static G3dWriter ToG3DWriter(this IGeometryAttributes self, G3dHeader? header = null) - => new G3dWriter(self, header); - - public static void Write(this IGeometryAttributes self, Stream stream, G3dHeader? header = null) - => self.ToG3DWriter(header).Write(stream); - - public static void Write(this IGeometryAttributes self, string filePath, G3dHeader? header = null) + public static BFastNext ToBFast(this IGeometryAttributes self, G3dHeader? header = null) { - using (var stream = File.OpenWrite(filePath)) - self.Write(stream, header); - } - - public static byte[] WriteToBytes(this IGeometryAttributes self) - { - using (var memoryStream = new MemoryStream()) + var bfast = new BFastNext(); + bfast.SetArray("meta", (header ?? G3dHeader.Default).ToBytes()); + foreach(var attribute in self.Attributes.ToEnumerable()) { - self.Write(memoryStream); - return memoryStream.ToArray(); + attribute.AddTo(bfast); } + return bfast; } - public static bool TryReadHeader(Stream stream, long size, out G3dHeader outHeader) + public static G3D ReadG3d(this Stream stream, Func renameFunc = null) { - var buffer = stream.ReadArray((int)size); + var bfast = new BFastNext(stream); - if (buffer[0] == G3dHeader.MagicA && buffer[1] == G3dHeader.MagicB) - { - outHeader = G3dHeader.FromBytes(buffer); - return true; - } - else + var header = G3dHeader.FromBytesOrDefault(bfast.GetArray("meta")); + var attributes = new List(); + foreach (var name in bfast.Entries) { - outHeader = default; - return false; + if (name == "meta") continue; + var attribute = GetAttribute(name); + var a = attribute.Read(bfast); + attributes.Add(a); } - } - public static bool TryReadGeometryAttribute(Stream stream, string name, long size, out GeometryAttribute geometryAttribute) + return new G3D(attributes, header); + } + public static GeometryAttribute GetAttribute(string name) { - geometryAttribute = null; - - bool ReadFailure() - { - // Update the seek head to consume the stream and return false. - stream.Seek((int)size, SeekOrigin.Current); - return false; - } - if (!AttributeDescriptor.TryParse(name, out var attributeDescriptor)) { - // Skip unknown attribute descriptors. - return ReadFailure(); + return null; } - - // Populate a default attribute with the parsed attribute descriptor. - GeometryAttribute defaultAttribute; try { - defaultAttribute = attributeDescriptor.ToDefaultAttribute(0); + return attributeDescriptor.ToDefaultAttribute(0); } catch { - // Eat the exception and return. - return ReadFailure(); + return null; } - - // Success; consume the stream. - geometryAttribute = defaultAttribute.Read(stream, size); - return true; - } - - public static G3D ReadG3d(this Stream stream, Func renameFunc = null) - { - var header = G3dHeader.Default; - - GeometryAttribute ReadG3dSegment(Stream s2, string name, long size) - { - name = renameFunc?.Invoke(name) ?? name; - - // Check for the G3dHeader - if (name == "meta" && size == 8) - { - if (TryReadHeader(s2, size, out var outHeader)) - { - // Assign to the header variable in the closure. - header = outHeader; - } - - return null; - } - else - { - return TryReadGeometryAttribute(s2, name, size, out var geometryAttribute) - ? geometryAttribute - : null; - } - - } - - var results = stream.ReadBFast(ReadG3dSegment).Select(r => r.Item2); - return new G3D(results.Where(x => x != null), header); } } } diff --git a/src/cs/g3d/Vim.G3d/G3dWriter.cs b/src/cs/g3d/Vim.G3d/G3dWriter.cs deleted file mode 100644 index 0d3a9ca8..00000000 --- a/src/cs/g3d/Vim.G3d/G3dWriter.cs +++ /dev/null @@ -1,47 +0,0 @@ -using System.IO; -using System.Linq; -using Vim.BFast; -using Vim.LinqArray; - -namespace Vim.G3d -{ - public static partial class G3DExtension - { - /// - /// This is a helper class for writing G3Ds - /// - public class G3dWriter : IBFastComponent - { - public INamedBuffer Meta { get; } - public string[] Names { get; } - public long[] Sizes { get; } - BFastHeader Header { get; } - IGeometryAttributes Attributes { get; } - - public G3dWriter(IGeometryAttributes g, G3dHeader? header = null) - { - Attributes = g; - Meta = (header ?? G3dHeader.Default).ToBytes().ToNamedBuffer("meta"); - Names = new[] { Meta.Name }.Concat(g.Attributes.ToEnumerable().Select(attr => attr.Name)).ToArray(); - Sizes = new[] { Meta.NumBytes() }.Concat(g.Attributes.ToEnumerable().Select(attr => attr.GetByteSize())).ToArray(); - Header = BFast.BFast.CreateBFastHeader(Sizes, Names); - } - - public long GetSize() - => Header.Preamble.DataEnd; - - public void Write(Stream stream) - { - stream.WriteBFastHeader(Header); - stream.WriteBFastBody(Header, Names, Sizes, (_stream, index, name, size) => - { - if (index == 0) - _stream.Write(Meta); - else - WriteAttribute(_stream, Attributes.Attributes[index - 1], name, size); - return size; - }); - } - } - } -} diff --git a/src/cs/g3d/Vim.G3d/GeometryAttribute.cs b/src/cs/g3d/Vim.G3d/GeometryAttribute.cs index 221a576e..f6f8fcfa 100644 --- a/src/cs/g3d/Vim.G3d/GeometryAttribute.cs +++ b/src/cs/g3d/Vim.G3d/GeometryAttribute.cs @@ -2,9 +2,10 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using Vim.BFast; +using Vim.Buffers; using Vim.LinqArray; using Vim.Math3d; +using Vim.BFastNextNS; namespace Vim.G3d { @@ -85,6 +86,13 @@ public GeometryAttribute AsType() where T : unmanaged /// public abstract GeometryAttribute Read(Stream stream, long byteCount); + /// + /// Loads the correct typed data from a BFastNext. + /// + public abstract GeometryAttribute Read(BFastNext bfast); + + public abstract void AddTo(BFastNext bfast); + /// /// Creates a new GeometryAttribute with the same data, but with a different index. Useful when constructing attributes /// @@ -220,6 +228,17 @@ public override GeometryAttribute Read(Stream stream, long byteCount) return new GeometryAttribute(data.ToIArray(), Descriptor); } + public override GeometryAttribute Read(BFastNext bfast) + { + var array = bfast.GetArray(Name); + return new GeometryAttribute(array.ToIArray(), Descriptor); + } + + public override void AddTo(BFastNext bfast) + { + bfast.SetArray(Name, Data.ToArray()); + } + public override GeometryAttribute SetIndex(int index) => index == Descriptor.Index ? this : new GeometryAttribute(Data, Descriptor.SetIndex(index)); } diff --git a/src/cs/g3d/Vim.G3d/Header.cs b/src/cs/g3d/Vim.G3d/Header.cs index c37140ce..60d4bb09 100644 --- a/src/cs/g3d/Vim.G3d/Header.cs +++ b/src/cs/g3d/Vim.G3d/Header.cs @@ -40,6 +40,18 @@ public static G3dHeader FromBytes(byte[] bytes) } .Validate(); + public static G3dHeader FromBytesOrDefault(byte[] bytes) + { + try + { + return FromBytes(bytes).Validate(); + } + catch (Exception) + { + return Default; + } + } + public static G3dHeader Default = new G3dHeader { diff --git a/src/cs/g3d/Vim.G3d/Vim.G3d.csproj b/src/cs/g3d/Vim.G3d/Vim.G3d.csproj index af3e2d08..0161fc81 100644 --- a/src/cs/g3d/Vim.G3d/Vim.G3d.csproj +++ b/src/cs/g3d/Vim.G3d/Vim.G3d.csproj @@ -52,6 +52,7 @@ It can be easily and efficiently deserialized and rendered in different language + diff --git a/src/cs/g3d/Vim.G3dNext.Attributes/Vim.G3dNext.Attributes.csproj b/src/cs/g3d/Vim.G3dNext.Attributes/Vim.G3dNext.Attributes.csproj index b842cea6..aabeb9f0 100644 --- a/src/cs/g3d/Vim.G3dNext.Attributes/Vim.G3dNext.Attributes.csproj +++ b/src/cs/g3d/Vim.G3dNext.Attributes/Vim.G3dNext.Attributes.csproj @@ -8,8 +8,8 @@ - + diff --git a/src/cs/g3d/Vim.G3dNext/Vim.G3dNext.csproj b/src/cs/g3d/Vim.G3dNext/Vim.G3dNext.csproj index 426db2f3..b09cb5e4 100644 --- a/src/cs/g3d/Vim.G3dNext/Vim.G3dNext.csproj +++ b/src/cs/g3d/Vim.G3dNext/Vim.G3dNext.csproj @@ -10,7 +10,6 @@ - diff --git a/src/cs/vim-format.sln b/src/cs/vim-format.sln index 9d839dae..3838d0db 100644 --- a/src/cs/vim-format.sln +++ b/src/cs/vim-format.sln @@ -5,10 +5,6 @@ VisualStudioVersion = 17.0.31903.59 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "bfast", "bfast", "{F3260C54-834F-4C74-A3B7-EAB622AFA492}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vim.BFast", "bfast\Vim.BFast\Vim.BFast.csproj", "{1059A7DE-95FA-4F54-85E3-84049E1872D5}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vim.BFast.Tests", "bfast\Vim.BFast.Tests\Vim.BFast.Tests.csproj", "{000ED0CF-EC9C-488C-BE85-14B95FFDF104}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "linqarray", "linqarray", "{CF54EDFD-51AB-4B0D-B084-2DF42918BA51}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vim.LinqArray", "linqarray\Vim.LinqArray\Vim.LinqArray.csproj", "{07CA1F46-21DA-4C22-A8CB-52D526D51C94}" @@ -63,20 +59,16 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vim.BFastNext.Tests", "bfas EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vim.Format.Vimx.Conversion", "vim\Vim.Format.Vimx.Conversion\Vim.Format.Vimx.Conversion.csproj", "{4C4F9826-0DEF-4A39-BFC8-A834522694A0}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Vim.BFast.Core", "Vim.BFast.Core\Vim.BFast.Core.csproj", "{7056183C-4DFE-4070-A714-A2AD9F47FA33}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Vim.Buffers", "Vim.Buffers\Vim.Buffers.csproj", "{BDB05F66-E90A-4DAE-A839-3281EE1338CC}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {1059A7DE-95FA-4F54-85E3-84049E1872D5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {1059A7DE-95FA-4F54-85E3-84049E1872D5}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1059A7DE-95FA-4F54-85E3-84049E1872D5}.Release|Any CPU.ActiveCfg = Release|Any CPU - {1059A7DE-95FA-4F54-85E3-84049E1872D5}.Release|Any CPU.Build.0 = Release|Any CPU - {000ED0CF-EC9C-488C-BE85-14B95FFDF104}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {000ED0CF-EC9C-488C-BE85-14B95FFDF104}.Debug|Any CPU.Build.0 = Debug|Any CPU - {000ED0CF-EC9C-488C-BE85-14B95FFDF104}.Release|Any CPU.ActiveCfg = Release|Any CPU - {000ED0CF-EC9C-488C-BE85-14B95FFDF104}.Release|Any CPU.Build.0 = Release|Any CPU {07CA1F46-21DA-4C22-A8CB-52D526D51C94}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {07CA1F46-21DA-4C22-A8CB-52D526D51C94}.Debug|Any CPU.Build.0 = Debug|Any CPU {07CA1F46-21DA-4C22-A8CB-52D526D51C94}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -165,13 +157,19 @@ Global {4C4F9826-0DEF-4A39-BFC8-A834522694A0}.Debug|Any CPU.Build.0 = Debug|Any CPU {4C4F9826-0DEF-4A39-BFC8-A834522694A0}.Release|Any CPU.ActiveCfg = Release|Any CPU {4C4F9826-0DEF-4A39-BFC8-A834522694A0}.Release|Any CPU.Build.0 = Release|Any CPU + {7056183C-4DFE-4070-A714-A2AD9F47FA33}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7056183C-4DFE-4070-A714-A2AD9F47FA33}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7056183C-4DFE-4070-A714-A2AD9F47FA33}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7056183C-4DFE-4070-A714-A2AD9F47FA33}.Release|Any CPU.Build.0 = Release|Any CPU + {BDB05F66-E90A-4DAE-A839-3281EE1338CC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BDB05F66-E90A-4DAE-A839-3281EE1338CC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BDB05F66-E90A-4DAE-A839-3281EE1338CC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BDB05F66-E90A-4DAE-A839-3281EE1338CC}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution - {1059A7DE-95FA-4F54-85E3-84049E1872D5} = {F3260C54-834F-4C74-A3B7-EAB622AFA492} - {000ED0CF-EC9C-488C-BE85-14B95FFDF104} = {F3260C54-834F-4C74-A3B7-EAB622AFA492} {07CA1F46-21DA-4C22-A8CB-52D526D51C94} = {CF54EDFD-51AB-4B0D-B084-2DF42918BA51} {461788B0-072C-485F-82C0-F83CCC86F95D} = {CF54EDFD-51AB-4B0D-B084-2DF42918BA51} {1086F24E-32C8-4261-9B06-A364EEE71DEF} = {9BD3CC85-97FD-4093-AA11-58FE405B0F65} @@ -194,6 +192,8 @@ Global {408884EA-3CE5-4A34-97F6-1F2D64A0E745} = {F3260C54-834F-4C74-A3B7-EAB622AFA492} {FD149D64-5905-4F7D-97A8-9F7DA18A257D} = {F3260C54-834F-4C74-A3B7-EAB622AFA492} {4C4F9826-0DEF-4A39-BFC8-A834522694A0} = {D639C635-01D1-48C4-89B5-1FD70F1AFEE9} + {7056183C-4DFE-4070-A714-A2AD9F47FA33} = {F3260C54-834F-4C74-A3B7-EAB622AFA492} + {BDB05F66-E90A-4DAE-A839-3281EE1338CC} = {F3260C54-834F-4C74-A3B7-EAB622AFA492} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {7D1BF641-26E8-4809-B638-029241C51BE2} diff --git a/src/cs/vim/Vim.Format.Core/SerializableDocument.cs b/src/cs/vim/Vim.Format.Core/SerializableDocument.cs index 88866a7c..bdda40b2 100644 --- a/src/cs/vim/Vim.Format.Core/SerializableDocument.cs +++ b/src/cs/vim/Vim.Format.Core/SerializableDocument.cs @@ -132,7 +132,7 @@ public BFastNext ToBFast() } bfast.SetBFast(BufferNames.Entities, entities); bfast.SetArray(BufferNames.Strings, BFastStrings.Pack(StringTable)); - bfast.SetArray(BufferNames.Geometry, Geometry.WriteToBytes()); + bfast.SetBFast(BufferNames.Geometry, Geometry.ToBFast()); return bfast; } diff --git a/src/cs/vim/Vim.Format.Core/Vim.Format.Core.csproj b/src/cs/vim/Vim.Format.Core/Vim.Format.Core.csproj index 25c15e16..544fe3cb 100644 --- a/src/cs/vim/Vim.Format.Core/Vim.Format.Core.csproj +++ b/src/cs/vim/Vim.Format.Core/Vim.Format.Core.csproj @@ -8,13 +8,13 @@ - + diff --git a/src/cs/vim/Vim.Format.Tests/Vim.Format.Tests.csproj b/src/cs/vim/Vim.Format.Tests/Vim.Format.Tests.csproj index fa09e756..46855ff9 100644 --- a/src/cs/vim/Vim.Format.Tests/Vim.Format.Tests.csproj +++ b/src/cs/vim/Vim.Format.Tests/Vim.Format.Tests.csproj @@ -16,7 +16,6 @@ - diff --git a/src/cs/vim/Vim.Format/Vim.Format.csproj b/src/cs/vim/Vim.Format/Vim.Format.csproj index ca5691f7..5d73fc41 100644 --- a/src/cs/vim/Vim.Format/Vim.Format.csproj +++ b/src/cs/vim/Vim.Format/Vim.Format.csproj @@ -18,7 +18,6 @@ - @@ -39,7 +38,7 @@ - + diff --git a/src/cs/vim/Vim.Vimx.Test/VimxTests.cs b/src/cs/vim/Vim.Vimx.Test/VimxTests.cs index d1b79444..d7e6899d 100644 --- a/src/cs/vim/Vim.Vimx.Test/VimxTests.cs +++ b/src/cs/vim/Vim.Vimx.Test/VimxTests.cs @@ -1,6 +1,5 @@ using NUnit.Framework; using NUnit.Framework.Internal; -using Vim.BFast; using Vim.G3dNext.Tests; using Vim.Format.VimxNS.Conversion; using Vim.Util.Tests; From 1a731578350132d7acaf67a1fb5b9a2d973316e5 Mon Sep 17 00:00:00 2001 From: simon Date: Fri, 8 Dec 2023 13:40:51 -0500 Subject: [PATCH 033/111] g3d based on bfast projects cleanup --- .../{BFastNext.cs => BFast/BFast.cs} | 50 ++--- .../{ => BFast}/BFastEnumerableNode.cs | 11 +- .../{BFastNextNode.cs => BFast/BFastNode.cs} | 20 +- .../IBFastNode.cs} | 8 +- .../Buffers/BufferExtensions.cs | 89 ++++++++ .../bfast/Vim.BFast.Next/Buffers/Buffers.cs | 77 +++++++ .../Vim.BFast.Next/Buffers/UnsafeHelpers.cs | 178 +++++++++++++++ .../Vim.BFast.Next/Core/BFastAlignment.cs | 49 ++++ .../Vim.BFast.Next/Core/BFastConstants.cs | 20 ++ .../bfast/Vim.BFast.Next/Core/BFastHeader.cs | 67 ++++++ .../Vim.BFast.Next/Core/BFastPreamble.cs | 71 ++++++ .../bfast/Vim.BFast.Next/Core/BFastRange.cs | 44 ++++ .../bfast/Vim.BFast.Next/Core/BFastReader.cs | 43 ++++ .../bfast/Vim.BFast.Next/Core/BFastStrings.cs | 46 ++++ .../bfast/Vim.BFast.Next/Core/BFastWriter.cs | 167 ++++++++++++++ ...{Vim.BFastNext.csproj => Vim.BFast.csproj} | 5 - .../{BFastNextTests.cs => BFastTests.cs} | 146 ++++++------ ...xt.Tests.csproj => Vim.BFast.Tests.csproj} | 4 +- src/cs/g3d/Vim.G3d.Tests/G3dTests.cs | 8 +- src/cs/g3d/Vim.G3d/G3D.cs | 40 +++- src/cs/g3d/Vim.G3d/G3dSerialization.cs | 38 +--- src/cs/g3d/Vim.G3d/GeometryAttribute.cs | 11 +- src/cs/g3d/Vim.G3d/Vim.G3d.csproj | 3 +- .../Vim.G3dNext.Attributes/Attributes.g.cs | 210 +++++++++--------- .../Vim.G3dNext.Attributes/G3dMaterials.cs | 14 +- src/cs/g3d/Vim.G3dNext.Attributes/G3dVim.cs | 2 +- .../Vim.G3dNext.Attributes.csproj | 1 - .../G3dAttributeCollectionGenerator.cs | 15 +- src/cs/g3d/Vim.G3dNext/IAttribute.cs | 6 +- .../g3d/Vim.G3dNext/IAttributeCollection.cs | 6 +- src/cs/g3d/Vim.G3dNext/Vim.G3dNext.csproj | 2 +- src/cs/vim-format.sln | 18 +- src/cs/vim/Vim.Format.Core/AssetInfo.cs | 2 +- .../ColumnExtensions.Buffer.cs | 2 +- src/cs/vim/Vim.Format.Core/Document.cs | 2 +- src/cs/vim/Vim.Format.Core/DocumentBuilder.cs | 8 +- .../DocumentBuilderExtensions.cs | 4 +- .../vim/Vim.Format.Core/DocumentExtensions.cs | 2 +- src/cs/vim/Vim.Format.Core/EntityTable.cs | 3 +- .../vim/Vim.Format.Core/EntityTableBuilder.cs | 2 +- src/cs/vim/Vim.Format.Core/G3dBuilder.cs | 8 +- .../Vim.Format.Core/Geometry/Serialization.cs | 2 +- .../Vim.Format.Core/Geometry/Validation.cs | 2 +- .../Vim.Format.Core/SerializableDocument.cs | 29 ++- .../vim/Vim.Format.Core/SerializableHeader.cs | 2 +- src/cs/vim/Vim.Format.Core/Serializer.cs | 2 +- src/cs/vim/Vim.Format.Core/Validation.cs | 2 +- .../Vim.Format.Core/Vim.Format.Core.csproj | 3 +- src/cs/vim/Vim.Format.Tests/FormatTests.cs | 2 +- .../Geometry/GeometryTests.cs | 4 +- .../MeshesToScene.cs | 2 +- .../Vim.Format.Vimx.Conversion/VimToMeshes.cs | 2 +- .../VimxConverter.cs | 5 +- .../Vim.Format.Vimx/Vim.Format.Vimx.csproj | 2 +- src/cs/vim/Vim.Format.Vimx/Vimx.cs | 8 +- src/cs/vim/Vim.Format.Vimx/VimxChunk.cs | 8 +- .../vim/Vim.Format/SceneBuilder/Validation.cs | 2 +- .../vim/Vim.Format/SceneBuilder/VimScene.cs | 8 +- .../Vim.Vimx.Test/Vim.Format.Vimx.Test.csproj | 2 +- src/cs/vim/Vim.Vimx.Test/VimG3dTests.cs | 10 +- src/cs/vim/Vim.Vimx.Test/VimxActions.cs | 7 +- 61 files changed, 1216 insertions(+), 390 deletions(-) rename src/cs/bfast/Vim.BFast.Next/{BFastNext.cs => BFast/BFast.cs} (82%) rename src/cs/bfast/Vim.BFast.Next/{ => BFast}/BFastEnumerableNode.cs (89%) rename src/cs/bfast/Vim.BFast.Next/{BFastNextNode.cs => BFast/BFastNode.cs} (84%) rename src/cs/bfast/Vim.BFast.Next/{IBFastNextNode.cs => BFast/IBFastNode.cs} (79%) create mode 100644 src/cs/bfast/Vim.BFast.Next/Buffers/BufferExtensions.cs create mode 100644 src/cs/bfast/Vim.BFast.Next/Buffers/Buffers.cs create mode 100644 src/cs/bfast/Vim.BFast.Next/Buffers/UnsafeHelpers.cs create mode 100644 src/cs/bfast/Vim.BFast.Next/Core/BFastAlignment.cs create mode 100644 src/cs/bfast/Vim.BFast.Next/Core/BFastConstants.cs create mode 100644 src/cs/bfast/Vim.BFast.Next/Core/BFastHeader.cs create mode 100644 src/cs/bfast/Vim.BFast.Next/Core/BFastPreamble.cs create mode 100644 src/cs/bfast/Vim.BFast.Next/Core/BFastRange.cs create mode 100644 src/cs/bfast/Vim.BFast.Next/Core/BFastReader.cs create mode 100644 src/cs/bfast/Vim.BFast.Next/Core/BFastStrings.cs create mode 100644 src/cs/bfast/Vim.BFast.Next/Core/BFastWriter.cs rename src/cs/bfast/Vim.BFast.Next/{Vim.BFastNext.csproj => Vim.BFast.csproj} (51%) rename src/cs/bfast/Vim.BFastNext.Tests/{BFastNextTests.cs => BFastTests.cs} (82%) rename src/cs/bfast/Vim.BFastNext.Tests/{Vim.BFastNext.Tests.csproj => Vim.BFast.Tests.csproj} (87%) diff --git a/src/cs/bfast/Vim.BFast.Next/BFastNext.cs b/src/cs/bfast/Vim.BFast.Next/BFast/BFast.cs similarity index 82% rename from src/cs/bfast/Vim.BFast.Next/BFastNext.cs rename to src/cs/bfast/Vim.BFast.Next/BFast/BFast.cs index 557c9f9f..8288a951 100644 --- a/src/cs/bfast/Vim.BFast.Next/BFastNext.cs +++ b/src/cs/bfast/Vim.BFast.Next/BFast/BFast.cs @@ -3,26 +3,24 @@ using System.IO; using System.IO.Compression; using System.Linq; -using Vim.Buffers; -using Vim.BFast.Core; +using Vim.BFastNS.Core; - -namespace Vim.BFastNextNS +namespace Vim.BFastNS { - public class BFastNext : IBFastNextNode + public class BFast : IBFastNode { - private readonly Dictionary _children = new Dictionary(); + private readonly Dictionary _children = new Dictionary(); public IEnumerable Entries => _children.Keys; private IEnumerable<(string, IWritable)> Writables => _children.Select(kvp => (kvp.Key, kvp.Value as IWritable)); - public BFastNext() { } - public BFastNext(Stream stream) + public BFast() { } + public BFast(Stream stream) { var node = GetBFastNodes(stream); - _children = node.ToDictionary(c => c.name, c => c.value as IBFastNextNode); + _children = node.ToDictionary(c => c.name, c => c.value as IBFastNode); } - public void SetBFast(Func getName, IEnumerable others, bool deflate = false) + public void SetBFast(Func getName, IEnumerable others, bool deflate = false) { var i = 0; foreach (var b in others) @@ -31,7 +29,7 @@ public void SetBFast(Func getName, IEnumerable others, b } } - public void SetBFast(string name, BFastNext bfast, bool deflate = false) + public void SetBFast(string name, BFast bfast, bool deflate = false) { if (deflate == false) { @@ -44,7 +42,7 @@ public void SetBFast(string name, BFastNext bfast, bool deflate = false) } } - private byte[] Deflate(BFastNext bfast) + private byte[] Deflate(BFast bfast) { using (var output = new MemoryStream()) { @@ -60,7 +58,7 @@ public void SetEnumerable(string name, Func> enumerable) where => _children[name] = new BFastEnumerableNode(enumerable); public void SetArray(string name, T[] array) where T : unmanaged - => _children[name] = BFastNextNode.FromArray(array); + => _children[name] = BFastNode.FromArray(array); public void SetArrays(Func getName, IEnumerable arrays) where T : unmanaged { @@ -71,12 +69,12 @@ public void SetArrays(Func getName, IEnumerable arrays) whe } } - public void SetNode(string name, BFastNextNode node) + public void SetNode(string name, BFastNode node) { _children[name] = node; } - public BFastNext GetBFast(string name, bool inflate = false) + public BFast GetBFast(string name, bool inflate = false) { var node = GetNode(name); if (node == null) return null; @@ -84,7 +82,7 @@ public BFastNext GetBFast(string name, bool inflate = false) return InflateNode(node); } - private BFastNext InflateNode(IBFastNextNode node) + private BFast InflateNode(IBFastNode node) { var output = new MemoryStream(); using (var input = new MemoryStream()) @@ -95,7 +93,7 @@ private BFastNext InflateNode(IBFastNextNode node) { compress.CopyTo(output); output.Seek(0, SeekOrigin.Begin); - return new BFastNext(output); + return new BFast(output); } } } @@ -112,7 +110,7 @@ public T[] GetArray(string name) where T : unmanaged return _children[name].AsArray(); } - public IBFastNextNode GetNode(string name) + public IBFastNode GetNode(string name) => _children.TryGetValue(name, out var value) ? value : null; public void Remove(string name) @@ -133,14 +131,14 @@ public void Write(string path) } } - public byte[] AsBytes() => (this as IBFastNextNode).AsArray(); + public byte[] AsBytes() => (this as IBFastNode).AsArray(); - BFastNext IBFastNextNode.AsBFast() + BFast IBFastNode.AsBFast() { return this; } - T[] IBFastNextNode.AsArray() + T[] IBFastNode.AsArray() { using (var stream = new MemoryStream()) { @@ -162,13 +160,13 @@ public IEnumerable AsEnumerable() where T : unmanaged } } - private static IEnumerable<(string name, BFastNextNode value)> GetBFastNodes(Stream stream) + private static IEnumerable<(string name, BFastNode value)> GetBFastNodes(Stream stream) { var offset = stream.Position; var header = BFastReader.ReadHeader(stream); for (var i = 1; i < header.Preamble.NumArrays; i++) { - var node = new BFastNextNode( + var node = new BFastNode( stream, header.Ranges[i].OffsetBy(offset) ); @@ -205,16 +203,16 @@ private static long GetBFastSize(IEnumerable<(string name, IWritable value)> wri public static class BFastNextExtensions { - public static T ReadBFast(this string path, Func process) + public static T ReadBFast(this string path, Func process) { using (var file = new FileStream(path, FileMode.Open)) { - var bfast = new BFastNext(file); + var bfast = new BFast(file); return process(bfast); } } - public static IEnumerable ToNamedBuffers(this BFastNext bfast) + public static IEnumerable ToNamedBuffers(this BFast bfast) { return bfast.Entries.Select(name => bfast.GetArray(name).ToNamedBuffer(name)); } diff --git a/src/cs/bfast/Vim.BFast.Next/BFastEnumerableNode.cs b/src/cs/bfast/Vim.BFast.Next/BFast/BFastEnumerableNode.cs similarity index 89% rename from src/cs/bfast/Vim.BFast.Next/BFastEnumerableNode.cs rename to src/cs/bfast/Vim.BFast.Next/BFast/BFastEnumerableNode.cs index d8eefd11..ff7162dd 100644 --- a/src/cs/bfast/Vim.BFast.Next/BFastEnumerableNode.cs +++ b/src/cs/bfast/Vim.BFast.Next/BFast/BFastEnumerableNode.cs @@ -2,11 +2,10 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using Vim.Buffers; -namespace Vim.BFastNextNS +namespace Vim.BFastNS { - public class BFastEnumerableNode : IBFastNextNode where TNode : unmanaged + public class BFastEnumerableNode : IBFastNode where TNode : unmanaged { private Func> _source; public BFastEnumerableNode(Func> source) @@ -14,13 +13,13 @@ public BFastEnumerableNode(Func> source) _source = source; } - private BFastNextNode AsMemNode() - => BFastNextNode.FromArray(_source().ToArray()); + private BFastNode AsMemNode() + => BFastNode.FromArray(_source().ToArray()); public T[] AsArray() where T : unmanaged => AsMemNode().AsArray(); - public BFastNext AsBFast() => AsMemNode().AsBFast(); + public BFast AsBFast() => AsMemNode().AsBFast(); public IEnumerable AsEnumerable() where T : unmanaged { var stream = new MemoryStream(); diff --git a/src/cs/bfast/Vim.BFast.Next/BFastNextNode.cs b/src/cs/bfast/Vim.BFast.Next/BFast/BFastNode.cs similarity index 84% rename from src/cs/bfast/Vim.BFast.Next/BFastNextNode.cs rename to src/cs/bfast/Vim.BFast.Next/BFast/BFastNode.cs index b7600a1f..19d1d747 100644 --- a/src/cs/bfast/Vim.BFast.Next/BFastNextNode.cs +++ b/src/cs/bfast/Vim.BFast.Next/BFast/BFastNode.cs @@ -1,17 +1,17 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.IO; -using Vim.BFast.Core; -using Vim.Buffers; +using Vim.BFastNS.Core; -namespace Vim.BFastNextNS +namespace Vim.BFastNS { - public class BFastNextNode : IBFastNextNode + public class BFastNode : IBFastNode { private readonly Stream _stream; private readonly BFastRange _range; - public static BFastNextNode FromArray(T[] array) where T : unmanaged + public static BFastNode FromArray(T[] array) where T : unmanaged { /* Is a memory leak created if a MemoryStream in .NET is not closed? @@ -24,22 +24,22 @@ You won't leak anything - at least in the current implementation. */ var stream = new MemoryStream(); stream.Write(array); - return new BFastNextNode(stream, stream.FullRange()); + return new BFastNode(stream, stream.FullRange()); } - public BFastNextNode(Stream stream, BFastRange range, Action cleanup = null) + public BFastNode(Stream stream, BFastRange range, Action cleanup = null) { _stream = stream; _range = range; } - public BFastNext AsBFast() + public BFast AsBFast() { _stream.Seek(_range.Begin, SeekOrigin.Begin); try { - return new BFastNext(_stream); + return new BFast(_stream); } catch (Exception ex) { @@ -51,7 +51,7 @@ public BFastNext AsBFast() public T[] AsArray() where T : unmanaged { _stream.Seek(_range.Begin, SeekOrigin.Begin); - return _stream.ReadArrayBytes((int)_range.Count); + return _stream.ReadArrayBytes(_range.Count); } public IEnumerable AsEnumerable() where T : unmanaged diff --git a/src/cs/bfast/Vim.BFast.Next/IBFastNextNode.cs b/src/cs/bfast/Vim.BFast.Next/BFast/IBFastNode.cs similarity index 79% rename from src/cs/bfast/Vim.BFast.Next/IBFastNextNode.cs rename to src/cs/bfast/Vim.BFast.Next/BFast/IBFastNode.cs index 9f730d92..c5412f79 100644 --- a/src/cs/bfast/Vim.BFast.Next/IBFastNextNode.cs +++ b/src/cs/bfast/Vim.BFast.Next/BFast/IBFastNode.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using System.IO; -namespace Vim.BFastNextNS +namespace Vim.BFastNS { /// /// Anything that can be added to a BFAST must have a size and write to a stream. @@ -14,11 +14,11 @@ public interface IWritable void Write(Stream stream); } - public interface IBFastNextNode : IWritable + public interface IBFastNode : IWritable { T[] AsArray() where T : unmanaged; IEnumerable AsEnumerable() where T : unmanaged; - - BFastNext AsBFast(); + + BFast AsBFast(); } } diff --git a/src/cs/bfast/Vim.BFast.Next/Buffers/BufferExtensions.cs b/src/cs/bfast/Vim.BFast.Next/Buffers/BufferExtensions.cs new file mode 100644 index 00000000..673530c2 --- /dev/null +++ b/src/cs/bfast/Vim.BFast.Next/Buffers/BufferExtensions.cs @@ -0,0 +1,89 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; + +namespace Vim.BFastNS +{ + /// + /// Helper functions for working with buffers + /// + public static class BufferExtensions + { + public static Buffer ToBuffer(this T[] xs) where T : unmanaged + => new Buffer(xs); + + public static NamedBuffer ToNamedBuffer(this T[] xs, string name = "") where T : unmanaged + => new NamedBuffer(xs, name); + + public static NamedBuffer ToNamedBuffer(this IBuffer buffer, string name = "") + => new NamedBuffer(buffer, name); + + public static NamedBuffer ToNamedBuffer(this IBuffer xs, string name = "") where T : unmanaged + => new NamedBuffer(xs.GetTypedData(), name); + + public static IEnumerable ToNamedBuffers(this IEnumerable buffers, IEnumerable names = null) + => names == null ? buffers.Select(b => b.ToNamedBuffer("")) : buffers.Zip(names, ToNamedBuffer); + + public static IDictionary ToDictionary(this IEnumerable buffers) + => buffers.ToDictionary(b => b.Name, b => b); + + public static IEnumerable ToNamedBuffers(this IDictionary d) + => d.Select(kv => kv.Value.ToNamedBuffer(kv.Key)); + + public static IEnumerable ToNamedBuffers(this IDictionary d) + => d.Select(kv => kv.Value.ToNamedBuffer(kv.Key)); + + public static Array CopyBytes(this IBuffer src, Array dst, int srcOffset = 0, int destOffset = 0) + { + Buffer.BlockCopy(src.Data, srcOffset, dst, destOffset, (int)src.NumBytes()); + return dst; + } + + public static byte[] ToBytes(this IBuffer src, byte[] dest = null) + => src.ToArray(dest); + + public static byte[] ToBytes(this T[] xs, byte[] dest = null) where T : unmanaged + => xs.RecastArray(dest); + + public static byte[] ToBytes(this T x) where T : unmanaged + => ToBytes(new[] { x }); + + /// + /// Accepts an array of the given type, or creates one if necessary, copy the buffer data into it + /// + public static unsafe T[] ToArray(this IBuffer buffer, T[] dest = null) where T : unmanaged + => (T[])buffer.CopyBytes(dest ?? new T[buffer.NumBytes() / sizeof(T)]); + + /// + /// Returns the array in the buffer, if it is of the correct type, or creates a new array of the create type and copies + /// bytes into it, as necessary. + /// + public static unsafe T[] AsArray(this IBuffer buffer) where T : unmanaged + => buffer.Data is T[] r ? r : buffer.ToArray(); + + /// + /// Copies an array of unmanaged types into another array of unmanaged types + /// + public static unsafe U[] RecastArray(this T[] src, U[] r = null) where T : unmanaged where U : unmanaged + => src.ToBuffer().ToArray(r); + + public static int NumElements(this IBuffer buffer) + => buffer.Data.Length; + + public static long NumBytes(this IBuffer buffer) + => (long)buffer.NumElements() * buffer.ElementSize; + + public static Buffer ReadBufferFromNumberOfBytes(this Stream stream, long numBytes) where T : unmanaged + => stream.ReadArrayFromNumberOfBytes(numBytes).ToBuffer(); + + public static Buffer ReadBuffer(this Stream stream, int numElements) where T : unmanaged + => stream.ReadArray(numElements).ToBuffer(); + + public static Buffer ReadBuffer(this Stream stream, int numBytes) + => stream.ReadBuffer(numBytes); + + public static void Write(this Stream stream, IBuffer buffer) + => buffer.Write(stream); + } +} diff --git a/src/cs/bfast/Vim.BFast.Next/Buffers/Buffers.cs b/src/cs/bfast/Vim.BFast.Next/Buffers/Buffers.cs new file mode 100644 index 00000000..8dd9c266 --- /dev/null +++ b/src/cs/bfast/Vim.BFast.Next/Buffers/Buffers.cs @@ -0,0 +1,77 @@ +using System; +using System.IO; + +namespace Vim.BFastNS +{ + /// + /// Provides an interface to an object that manages a potentially large array of elements all of the same unmanaged type. + /// + public interface IBuffer + { + Array Data { get; } + int ElementSize { get; } + void Write(Stream stream); + } + + /// + /// A version of the IBuffer interface when the element types are known + /// + public interface IBuffer : IBuffer + { + T[] GetTypedData(); + } + + /// + /// Represents a buffer associated with a string name. + /// + public interface INamedBuffer : IBuffer + { + string Name { get; } + } + + /// + /// A version of the INamedBuffer interface when the element types are known + /// + public interface INamedBuffer : INamedBuffer, IBuffer + { + } + + /// + /// A concrete implementation of IBuffer + /// + public unsafe class Buffer : IBuffer where T : unmanaged + { + public Buffer(T[] data) => Data = data; + public int ElementSize => sizeof(T); + public Array Data { get; } + public T[] GetTypedData() => Data as T[]; + public void Write(Stream stream) => stream.Write(GetTypedData()); + } + + /// + /// A concrete implementation of INamedBuffer + /// + public class NamedBuffer : INamedBuffer + { + public NamedBuffer(IBuffer buffer, string name) => (Buffer, Name) = (buffer, name); + public IBuffer Buffer { get; } + public string Name { get; } + public int ElementSize => Buffer.ElementSize; + public Array Data => Buffer.Data; + public void Write(Stream stream) => Buffer.Write(stream); + } + + /// + /// A concrete implementation of INamedBuffer with a specific type. + /// + public class NamedBuffer : INamedBuffer where T : unmanaged + { + public NamedBuffer(T[] data, string name) => (Array, Name) = (data, name); + public string Name { get; } + public unsafe int ElementSize => sizeof(T); + public readonly T[] Array; + public Array Data => Array; + public T[] GetTypedData() => Array; + public void Write(Stream stream) => stream.Write(Array); + } +} diff --git a/src/cs/bfast/Vim.BFast.Next/Buffers/UnsafeHelpers.cs b/src/cs/bfast/Vim.BFast.Next/Buffers/UnsafeHelpers.cs new file mode 100644 index 00000000..8c0428cd --- /dev/null +++ b/src/cs/bfast/Vim.BFast.Next/Buffers/UnsafeHelpers.cs @@ -0,0 +1,178 @@ +using System; +using System.Diagnostics; +using System.IO; + +namespace Vim.BFastNS +{ + /// + /// This class would benefit from being in a generic utilities class, however, having it here allows BFAST to be a standalone without dependencies. + /// + public static class UnsafeHelpers + { + /// + /// Helper for reading arbitrary unmanaged types from a Stream. + /// + public static unsafe void ReadBytesBuffered(this Stream stream, byte* dest, long count, int bufferSize = 4096) + { + var buffer = new byte[bufferSize]; + int bytesRead; + fixed (byte* pBuffer = buffer) + { + while ((bytesRead = stream.Read(buffer, 0, (int)Math.Min(buffer.Length, count))) > 0) + { + if (dest != null) + Buffer.MemoryCopy(pBuffer, dest, count, bytesRead); + count -= bytesRead; + dest += bytesRead; + } + } + } + + /// + /// Helper for writing arbitrary large numbers of bytes + /// + public static unsafe void WriteBytesBuffered(this Stream stream, byte* src, long count, int bufferSize = 4096) + { + var buffer = new byte[bufferSize]; + fixed (byte* pBuffer = buffer) + { + while (count > 0) + { + var toWrite = (int)Math.Min(count, buffer.Length); + Buffer.MemoryCopy(src, pBuffer, buffer.Length, toWrite); + stream.Write(buffer, 0, toWrite); + count -= toWrite; + src += toWrite; + } + } + } + + /// + /// Helper for reading arbitrary unmanaged types from a Stream. + /// + public static unsafe void Read(this Stream stream, T* dest) where T : unmanaged + => stream.ReadBytesBuffered((byte*)dest, sizeof(T)); + + /// + /// Helper for reading arrays of arbitrary unmanaged types from a Stream, that might be over 2GB of size. + /// That said, in C#, you can never load more int.MaxValue numbers of items. + /// NOTE: Arrays are still limited to 2gb in size unless gcAllowVeryLargeObjects is set to true + /// in the runtime environment. + /// https://docs.microsoft.com/en-us/dotnet/api/system.array?redirectedfrom=MSDN&view=netframework-4.7.2#remarks + /// Alternatively, we could convert to .Net Core + /// + public static unsafe T[] ReadArray(this Stream stream, int count) where T : unmanaged + { + var r = new T[count]; + fixed (T* pDest = r) + { + + var pBytes = (byte*)pDest; + stream.ReadBytesBuffered(pBytes, (long)count * sizeof(T)); + } + return r; + } + + public static unsafe void ReadArray(this Stream stream, T[] array, int count) where T : unmanaged + { + fixed (T* pDest = array) + { + var pBytes = (byte*)pDest; + stream.ReadBytesBuffered(pBytes, (long)count * sizeof(T)); + } + } + + + /// + /// Equivalent to ReadArray to use when you know the byte count instead of element count. + /// + public static unsafe T[] ReadArrayBytes(this Stream stream, long byteLength) where T : unmanaged + { + var count = byteLength / sizeof(T); + Debug.Assert(count <= int.MaxValue); + return ReadArray(stream, (int)count); + } + + /* + public static unsafe T[] ConvertByteArrayToTypeArray(byte[] byteArray) where T : unmanaged + { + if (byteArray.Length % sizeof(T) != 0) + { + throw new ArgumentException("Byte array length is not a multiple of the size of the target type."); + } + + var elementCount = byteArray.Length / sizeof(T); + var resultArray = new T[elementCount]; + + fixed (byte* bytePtr = byteArray) + { + byte* currentBytePtr = bytePtr; + fixed (T* resultPtr = resultArray) + { + var currentResultPtr = resultPtr; + for (var i = 0; i < elementCount; i++) + { + *currentResultPtr = *((T*)currentBytePtr); + currentBytePtr += sizeof(T); + currentResultPtr++; + } + } + } + + return resultArray; + } + + */ + /// + /// A wrapper for stream.Seek(numBytes, SeekOrigin.Current) to avoid allocating memory for unrecognized buffers. + /// + public static void SkipBytes(this Stream stream, long numBytes) + => stream.Seek(numBytes, SeekOrigin.Current); + + /// + /// Helper for reading arrays of arbitrary unmanaged types from a Stream, that might be over 2GB of size. + /// That said, in C#, you can never load more int.MaxValue numbers of items. + /// + public static unsafe T[] ReadArrayFromNumberOfBytes(this Stream stream, long numBytes) where T : unmanaged + { + var count = numBytes / sizeof(T); + if (numBytes % sizeof(T) != 0) + throw new Exception($"The number of bytes {numBytes} is not divisible by the size of the type {sizeof(T)}"); + if (count >= int.MaxValue) + throw new Exception($"{count} exceeds the maximum number of items that can be read into an array {int.MaxValue}"); + return stream.ReadArray((int)count); + } + + /// + /// Helper for writing arbitrary unmanaged types + /// + public static unsafe void WriteValue(this Stream stream, T x) where T : unmanaged + { + var p = &x; + stream.WriteBytesBuffered((byte*)p, sizeof(T)); + } + + + /// + /// Helper for writing arrays of unmanaged types + /// + public static unsafe void Write(this Stream stream, T[] xs) where T : unmanaged + { + fixed (T* p = xs) + { + stream.WriteBytesBuffered((byte*)p, xs.LongLength * sizeof(T)); + } + } + + /// + /// Helper for writing arrays of unmanaged types + /// + public static unsafe void Write(this Stream stream, T[] xs, long count) where T : unmanaged + { + fixed (T* p = xs) + { + stream.WriteBytesBuffered((byte*)p, count * sizeof(T)); + } + } + } +} diff --git a/src/cs/bfast/Vim.BFast.Next/Core/BFastAlignment.cs b/src/cs/bfast/Vim.BFast.Next/Core/BFastAlignment.cs new file mode 100644 index 00000000..c70555e9 --- /dev/null +++ b/src/cs/bfast/Vim.BFast.Next/Core/BFastAlignment.cs @@ -0,0 +1,49 @@ +using System; +using System.IO; + +namespace Vim.BFastNS.Core +{ + internal class BFastAlignment + { + /// + /// Computes the padding requires after the array of BFastRanges are written out. + /// + /// + /// + public static long ComputePadding(BFastRange[] ranges) + => ComputePadding(BFastPreamble.Size + ranges.Length * BFastRange.Size); + + /// + /// Given a position in the stream, computes how much padding is required to bring the value to an aligned point. + /// + public static long ComputePadding(long n) + => ComputeNext(n) - n; + + /// + /// Given a position in the stream, tells us where the the next aligned position will be, if it the current position is not aligned. + /// + public static long ComputeNext(long n) + => IsAligned(n) ? n : n + BFastConstants.ALIGNMENT - (n % BFastConstants.ALIGNMENT); + + /// + /// Checks that the stream (if seekable) is well aligned + /// + public static void Check(Stream stream) + { + if (!stream.CanSeek) + return; + // TODO: Check with CD: Should we bail out here? This means that any + // alignment checks for a currently-writing stream are effectively ignored. + if (stream.Position == stream.Length) + return; + if (!IsAligned(stream.Position)) + throw new Exception($"Stream position {stream.Position} is not well aligned"); + } + + /// + /// Given a position in the stream, tells us whether the position is aligned. + /// + public static bool IsAligned(long n) + => n % BFastConstants.ALIGNMENT == 0; + } +} diff --git a/src/cs/bfast/Vim.BFast.Next/Core/BFastConstants.cs b/src/cs/bfast/Vim.BFast.Next/Core/BFastConstants.cs new file mode 100644 index 00000000..4b0524c5 --- /dev/null +++ b/src/cs/bfast/Vim.BFast.Next/Core/BFastConstants.cs @@ -0,0 +1,20 @@ +namespace Vim.BFastNS.Core +{ + /// + /// Constants. + /// + public static class BFastConstants + { + public const long Magic = 0xBFA5; + + // https://en.wikipedia.org/wiki/Endianness + public const long SameEndian = Magic; + public const long SwappedEndian = 0xA5BFL << 48; + + /// + /// Data arrays are aligned to 64 bytes, so that they can be cast directly to AVX-512 registers. + /// This is useful for efficiently working with floating point data. + /// + public const long ALIGNMENT = 64; + } +} diff --git a/src/cs/bfast/Vim.BFast.Next/Core/BFastHeader.cs b/src/cs/bfast/Vim.BFast.Next/Core/BFastHeader.cs new file mode 100644 index 00000000..06cac970 --- /dev/null +++ b/src/cs/bfast/Vim.BFast.Next/Core/BFastHeader.cs @@ -0,0 +1,67 @@ +using System; +using System.IO; +using System.Linq; + +namespace Vim.BFastNS.Core +{ + /// + /// This contains the BFAST data loaded or written from disk. + /// + public class BFastHeader + { + public BFastPreamble Preamble = new BFastPreamble(); + public BFastRange[] Ranges; + public string[] Names; + + public override bool Equals(object o) + => o is BFastHeader other && Equals(other); + + public bool Equals(BFastHeader other) + => Preamble.Equals(other.Preamble) && + Ranges.Length == other.Ranges.Length && + Ranges.Zip(other.Ranges, (x, y) => x.Equals(y)).All(x => x) && + Names.Zip(other.Names, (x, y) => x.Equals(y)).All(x => x); + + /// + /// Checks that the header values are sensible, and throws an exception otherwise. + /// + public BFastHeader Validate() + { + var preamble = Preamble.Validate(); + var ranges = Ranges; + var names = Names; + + if (preamble.RangesEnd > preamble.DataStart) + throw new Exception($"Computed arrays ranges end must be less than the start of data {preamble.DataStart}"); + + if (ranges == null) + throw new Exception("Ranges must not be null"); + + var min = preamble.DataStart; + var max = preamble.DataEnd; + + for (var i = 0; i < ranges.Length; ++i) + { + var begin = ranges[i].Begin; + if (!BFastAlignment.IsAligned(begin)) + throw new Exception($"The beginning of the range is not well aligned {begin}"); + var end = ranges[i].End; + if (begin < min || begin > max) + throw new Exception($"Array offset begin {begin} is not in valid span of {min} to {max}"); + if (i > 0) + { + if (begin < ranges[i - 1].End) + throw new Exception($"Array offset begin {begin} is overlapping with previous array {ranges[i - 1].End}"); + } + + if (end < begin || end > max) + throw new Exception($"Array offset end {end} is not in valid span of {begin} to {max}"); + } + + if (names.Length < ranges.Length - 1) + throw new Exception($"Number of buffer names {names.Length} is not one less than the number of ranges {ranges.Length}"); + + return this; + } + } +} diff --git a/src/cs/bfast/Vim.BFast.Next/Core/BFastPreamble.cs b/src/cs/bfast/Vim.BFast.Next/Core/BFastPreamble.cs new file mode 100644 index 00000000..28c78a30 --- /dev/null +++ b/src/cs/bfast/Vim.BFast.Next/Core/BFastPreamble.cs @@ -0,0 +1,71 @@ +using System; +using System.Runtime.InteropServices; + +namespace Vim.BFastNS.Core +{ + /// + /// The header contains a magic number, the begin and end indices of data, and the number of arrays. + /// + [StructLayout(LayoutKind.Explicit, Pack = 8, Size = 32)] + public struct BFastPreamble + { + [FieldOffset(0)] public long Magic; // Either Constants.SameEndian or Constants.SwappedEndian depending on endianess of writer compared to reader. + [FieldOffset(8)] public long DataStart; // <= file size and >= ArrayRangesEnd and >= FileHeader.ByteCount + [FieldOffset(16)] public long DataEnd; // >= DataStart and <= file size + [FieldOffset(24)] public long NumArrays; // number of arrays + + /// + /// This is where the array ranges are finished. + /// Must be less than or equal to DataStart. + /// Must be greater than or equal to FileHeader.ByteCount + /// + public long RangesEnd => Size + NumArrays * 16; + + /// + /// The size of the FileHeader structure + /// + public static long Size = 32; + + /// + /// Returns true if the producer of the BFast file has the same endianness as the current library + /// + public bool SameEndian => Magic == BFastConstants.SameEndian; + + public override bool Equals(object x) + => x is BFastPreamble other && Equals(other); + + public bool Equals(BFastPreamble other) + => Magic == other.Magic && DataStart == other.DataStart && DataEnd == other.DataEnd && NumArrays == other.NumArrays; + + + /// + /// Checks that the header values are sensible, and throws an exception otherwise. + /// + public BFastPreamble Validate() + { + if (Magic != BFastConstants.SameEndian && Magic != BFastConstants.SwappedEndian) + throw new Exception($"Invalid magic number {Magic}"); + + if (DataStart < BFastPreamble.Size) + throw new Exception($"Data start {DataStart} cannot be before the file header size {BFastPreamble.Size}"); + + if (DataStart > DataEnd) + throw new Exception($"Data start {DataStart} cannot be after the data end {DataEnd}"); + + if (!BFastAlignment.IsAligned(DataEnd)) + throw new Exception($"Data end {DataEnd} should be aligned"); + + if (NumArrays < 0) + throw new Exception($"Number of arrays {NumArrays} is not a positive number"); + + if (NumArrays > DataEnd) + throw new Exception($"Number of arrays {NumArrays} can't be more than the total size"); + + if (RangesEnd > DataStart) + throw new Exception($"End of range {RangesEnd} can't be after data-start {DataStart}"); + + return this; + } + + }; +} diff --git a/src/cs/bfast/Vim.BFast.Next/Core/BFastRange.cs b/src/cs/bfast/Vim.BFast.Next/Core/BFastRange.cs new file mode 100644 index 00000000..52cbe0e8 --- /dev/null +++ b/src/cs/bfast/Vim.BFast.Next/Core/BFastRange.cs @@ -0,0 +1,44 @@ +using System.IO; +using System.Runtime.InteropServices; + +namespace Vim.BFastNS.Core +{ + /// + /// This tells us where a particular array begins and ends in relation to the beginning of a file. + /// * Begin must be less than or equal to End. + /// * Begin must be greater than or equal to DataStart + /// * End must be less than or equal to DataEnd + /// + [StructLayout(LayoutKind.Explicit, Pack = 8, Size = 16)] + public struct BFastRange + { + [FieldOffset(0)] public long Begin; + [FieldOffset(8)] public long End; + + public long Count => End - Begin; + public static long Size = 16; + + public override bool Equals(object x) + => x is BFastRange other && Equals(other); + + public bool Equals(BFastRange other) + => Begin == other.Begin && End == other.End; + + public BFastRange OffsetBy(long offset) + => new BFastRange() + { + Begin = Begin + offset, + End = End + offset + }; + } + + public static class BFastRangeExtensions + { + public static BFastRange FullRange(this Stream stream) + => new BFastRange() + { + Begin = 0, + End = stream.Length + }; + } +} diff --git a/src/cs/bfast/Vim.BFast.Next/Core/BFastReader.cs b/src/cs/bfast/Vim.BFast.Next/Core/BFastReader.cs new file mode 100644 index 00000000..d22bf3f0 --- /dev/null +++ b/src/cs/bfast/Vim.BFast.Next/Core/BFastReader.cs @@ -0,0 +1,43 @@ +using System; +using System.IO; + +namespace Vim.BFastNS.Core +{ + public static class BFastReader + { + /// + /// Reads the preamble, the ranges, and the names of the rest of the buffers. + /// + public static BFastHeader ReadHeader(Stream stream) + { + var r = new BFastHeader(); + var br = new BinaryReader(stream); + + if (stream.Length - stream.Position < sizeof(long) * 4) + throw new Exception("Stream too short"); + + r.Preamble = new BFastPreamble + { + Magic = br.ReadInt64(), + DataStart = br.ReadInt64(), + DataEnd = br.ReadInt64(), + NumArrays = br.ReadInt64(), + }.Validate(); + + r.Ranges = stream.ReadArray((int)r.Preamble.NumArrays); + + var padding = BFastAlignment.ComputePadding(r.Ranges); + br.ReadBytes((int)padding); + BFastAlignment.Check(br.BaseStream); + + var nameBytes = br.ReadBytes((int)r.Ranges[0].Count); + r.Names = BFastStrings.Unpack(nameBytes); + + padding = BFastAlignment.ComputePadding(r.Ranges[0].End); + br.ReadBytes((int)padding); + BFastAlignment.Check(br.BaseStream); + + return r.Validate(); + } + } +} diff --git a/src/cs/bfast/Vim.BFast.Next/Core/BFastStrings.cs b/src/cs/bfast/Vim.BFast.Next/Core/BFastStrings.cs new file mode 100644 index 00000000..a8988584 --- /dev/null +++ b/src/cs/bfast/Vim.BFast.Next/Core/BFastStrings.cs @@ -0,0 +1,46 @@ +using System.Collections.Generic; +using System.Text; + +namespace Vim.BFastNS.Core +{ + public static class BFastStrings + { + /// + /// Converts a collection of strings, into a null-separated byte[] array + /// + public static byte[] Pack(IEnumerable strings) + { + var r = new List(); + foreach (var name in strings) + { + var bytes = Encoding.UTF8.GetBytes(name); + r.AddRange(bytes); + r.Add(0); + } + return r.ToArray(); + } + + + /// + /// Converts a byte[] array encoding a collection of strings separate by NULL into an array of string + /// + public static string[] Unpack(byte[] bytes) + { + var r = new List(); + if (bytes.Length == 0) + return r.ToArray(); + var prev = 0; + for (var i = 0; i < bytes.Length; ++i) + { + if (bytes[i] == 0) + { + r.Add(Encoding.UTF8.GetString(bytes, prev, i - prev)); + prev = i + 1; + } + } + if (prev < bytes.Length) + r.Add(Encoding.UTF8.GetString(bytes, prev, bytes.Length - prev)); + return r.ToArray(); + } + } +} diff --git a/src/cs/bfast/Vim.BFast.Next/Core/BFastWriter.cs b/src/cs/bfast/Vim.BFast.Next/Core/BFastWriter.cs new file mode 100644 index 00000000..5596070d --- /dev/null +++ b/src/cs/bfast/Vim.BFast.Next/Core/BFastWriter.cs @@ -0,0 +1,167 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.Linq; + +namespace Vim.BFastNS.Core +{ + public static class BFastWriter + { + /// + /// Callback function allows clients to control writing the data to the output stream + /// + public delegate long BFastWriterFn(Stream writingStream, int bufferIdx, string bufferName, long bytesToWrite); + + /// + /// Enables a user to write a BFAST from an array of names, sizes, and a custom writing function. + /// The function will receive a BinaryWriter, the index of the buffer, and is expected to return the number of bytes written. + /// Simplifies the process of creating custom BinaryWriters, or writing extremely large arrays if necessary. + /// + public static void Write(Stream stream, string[] bufferNames, long[] bufferSizes, BFastWriterFn onBuffer) + { + if (bufferSizes.Any(sz => sz < 0)) + throw new Exception("All buffer sizes must be zero or greater than zero"); + + if (bufferNames.Length != bufferSizes.Length) + throw new Exception($"The number of buffer names {bufferNames.Length} is not equal to the number of buffer sizes {bufferSizes}"); + + var header = CreateHeader(bufferSizes, bufferNames); + Write(stream, header, bufferNames, bufferSizes, onBuffer); + } + + /// + /// Enables a user to write a BFAST from an array of names, sizes, and a custom writing function. + /// This is useful when the header is already computed. + /// + public static void Write(Stream stream, BFastHeader header, string[] bufferNames, long[] bufferSizes, BFastWriterFn onBuffer) + { + WriteHeader(stream, header); + BFastAlignment.Check(stream); + WriteBody(stream, bufferNames, bufferSizes, onBuffer); + } + + /// + /// Must be called after "WriteBFastHeader" + /// Enables a user to write the contents of a BFAST from an array of names, sizes, and a custom writing function. + /// The function will receive a BinaryWriter, the index of the buffer, and is expected to return the number of bytes written. + /// Simplifies the process of creating custom BinaryWriters, or writing extremely large arrays if necessary. + /// + public static void WriteBody(Stream stream, string[] bufferNames, long[] bufferSizes, BFastWriterFn onBuffer) + { + BFastAlignment.Check(stream); + + if (bufferSizes.Any(sz => sz < 0)) + throw new Exception("All buffer sizes must be zero or greater than zero"); + + if (bufferNames.Length != bufferSizes.Length) + throw new Exception($"The number of buffer names {bufferNames.Length} is not equal to the number of buffer sizes {bufferSizes}"); + + // Then passes the binary writer for each buffer: checking that the correct amount of data was written. + for (var i = 0; i < bufferNames.Length; ++i) + { + BFastAlignment.Check(stream); + var nBytes = bufferSizes[i]; + var pos = stream.CanSeek ? stream.Position : 0; + var nWrittenBytes = onBuffer(stream, i, bufferNames[i], nBytes); + if (stream.CanSeek) + { + if (stream.Position - pos != nWrittenBytes) + throw new NotImplementedException($"Buffer:{bufferNames[i]}. Stream movement {stream.Position - pos} does not reflect number of bytes claimed to be written {nWrittenBytes}"); + } + + if (nBytes != nWrittenBytes) + throw new Exception($"Number of bytes written {nWrittenBytes} not equal to expected bytes{nBytes}"); + var padding = BFastAlignment.ComputePadding(nBytes); + for (var j = 0; j < padding; ++j) + stream.WriteByte(0); + BFastAlignment.Check(stream); + } + } + + /// + /// Creates a BFAST structure, without any actual data buffers, from a list of sizes of buffers (not counting the name buffer). + /// Used as an intermediate step to create a BFAST. + /// + public static BFastHeader CreateHeader(long[] bufferSizes, string[] bufferNames) + { + if (bufferNames.Length != bufferSizes.Length) + throw new Exception($"The number of buffer sizes {bufferSizes.Length} is not equal to the number of buffer names {bufferNames.Length}"); + + var header = new BFastHeader + { + Names = bufferNames + }; + header.Preamble.Magic = BFastConstants.Magic; + header.Preamble.NumArrays = bufferSizes.Length + 1; + + // Allocate the data for the ranges + header.Ranges = new BFastRange[header.Preamble.NumArrays]; + header.Preamble.DataStart = BFastAlignment.ComputeNext(header.Preamble.RangesEnd); + + var nameBufferLength = BFastStrings.Pack(bufferNames).LongLength; + var sizes = (new[] { nameBufferLength }).Concat(bufferSizes).ToArray(); + + // Compute the offsets for the data buffers + var curIndex = header.Preamble.DataStart; + var i = 0; + foreach (var size in sizes) + { + curIndex = BFastAlignment.ComputeNext(curIndex); + Debug.Assert(BFastAlignment.IsAligned(curIndex)); + + header.Ranges[i].Begin = curIndex; + curIndex += size; + + header.Ranges[i].End = curIndex; + i++; + } + + // Finish with the header + // Each buffer we contain is padded to ensure the next one + // starts on alignment, so we pad our DataEnd to reflect this reality + header.Preamble.DataEnd = BFastAlignment.ComputeNext(curIndex); + + // Check that everything adds up + return header.Validate(); + } + + + /// + /// Writes the BFAST header and name buffer to stream using the provided BinaryWriter. The BinaryWriter will be properly aligned by padding zeros + /// + public static BinaryWriter WriteHeader(Stream stream, BFastHeader header) + { + if (header.Ranges.Length != header.Names.Length + 1) + throw new Exception($"The number of ranges {header.Ranges.Length} must be equal to one more than the number of names {header.Names.Length}"); + var bw = new BinaryWriter(stream); + bw.Write(header.Preamble.Magic); + bw.Write(header.Preamble.DataStart); + bw.Write(header.Preamble.DataEnd); + bw.Write(header.Preamble.NumArrays); + foreach (var r in header.Ranges) + { + bw.Write(r.Begin); + bw.Write(r.End); + } + WriteZeroBytes(bw, BFastAlignment.ComputePadding(header.Ranges)); + + BFastAlignment.Check(stream); + var nameBuffer = BFastStrings.Pack(header.Names); + bw.Write(nameBuffer); + WriteZeroBytes(bw, BFastAlignment.ComputePadding(nameBuffer.LongLength)); + + BFastAlignment.Check(stream); + return bw; + } + + /// + /// Writes n zero bytes. + /// + public static void WriteZeroBytes(BinaryWriter bw, long n) + { + for (var i = 0L; i < n; ++i) + bw.Write((byte)0); + } + + } +} diff --git a/src/cs/bfast/Vim.BFast.Next/Vim.BFastNext.csproj b/src/cs/bfast/Vim.BFast.Next/Vim.BFast.csproj similarity index 51% rename from src/cs/bfast/Vim.BFast.Next/Vim.BFastNext.csproj rename to src/cs/bfast/Vim.BFast.Next/Vim.BFast.csproj index c85f9e9a..7f22bfd6 100644 --- a/src/cs/bfast/Vim.BFast.Next/Vim.BFastNext.csproj +++ b/src/cs/bfast/Vim.BFast.Next/Vim.BFast.csproj @@ -5,9 +5,4 @@ true - - - - - diff --git a/src/cs/bfast/Vim.BFastNext.Tests/BFastNextTests.cs b/src/cs/bfast/Vim.BFastNext.Tests/BFastTests.cs similarity index 82% rename from src/cs/bfast/Vim.BFastNext.Tests/BFastNextTests.cs rename to src/cs/bfast/Vim.BFastNext.Tests/BFastTests.cs index 71270dcc..fd579383 100644 --- a/src/cs/bfast/Vim.BFastNext.Tests/BFastNextTests.cs +++ b/src/cs/bfast/Vim.BFastNext.Tests/BFastTests.cs @@ -3,9 +3,9 @@ using Vim.Util; using Vim.Util.Tests; -namespace Vim.BFastNextNS.Tests +namespace Vim.BFastNS.Tests { - public class BFastNextTests + public class BFastTests { public static string RootFolder = System.IO.Path.Combine(VimFormatRepoPaths.ProjDir, "..", ".."); public static string Path = System.IO.Path.Combine(RootFolder, "out/input.bfast"); @@ -22,46 +22,46 @@ public void Setup() [Test] public void EmptyBFast_Has_No_Entries() { - var bfast = new BFastNext(); + var bfast = new BFast(); Assert.That(bfast.Entries.Count(), Is.EqualTo(0)); } [Test] public void EmptyBFast_GetArray_Returns_Null() { - var bfast = new BFastNext(); + var bfast = new BFast(); Assert.IsNull(bfast.GetArray("missing")); } [Test] public void EmptyBFast_GetBfast_Returns_Null() { - var bfast = new BFastNext(); + var bfast = new BFast(); Assert.IsNull(bfast.GetBFast("missing")); } [Test] public void EmptyBFast_Remove_Does_Nothing() { - var bfast = new BFastNext(); + var bfast = new BFast(); bfast.Remove("missing"); } [Test] public void EmptyBFast_GetSize_Return_64() { - var bfast = new BFastNext(); + var bfast = new BFast(); Assert.That(bfast.GetSize(), Is.EqualTo(64)); } [Test] public void EmptyBFast_Writes_Header() { - var bfast = new BFastNext(); + var bfast = new BFast(); bfast.Write(Path); using (var stream = File.OpenRead(Path)) { - var bfast2 = new BFastNext(stream); + var bfast2 = new BFast(stream); Assert.That(bfast2.GetSize(), Is.EqualTo(64)); } } @@ -69,7 +69,7 @@ public void EmptyBFast_Writes_Header() [Test] public void SetEnumerable_Adds_Entry() { - var bfast = new BFastNext(); + var bfast = new BFast(); bfast.SetEnumerable("A", () => new int[3] { 0, 1, 2 }); Assert.That(bfast.Entries.Count(), Is.EqualTo(1)); } @@ -78,7 +78,7 @@ public void SetEnumerable_Adds_Entry() [Test] public void SetEnumerable_Then_GetArray() { - var bfast = new BFastNext(); + var bfast = new BFast(); bfast.SetEnumerable("A", () => new int[3] { 0, 1, 2 }); var result = bfast.GetArray("A"); @@ -88,7 +88,7 @@ public void SetEnumerable_Then_GetArray() [Test] public void SetEnumerable_Then_GetArray_Bytes() { - var bfast = new BFastNext(); + var bfast = new BFast(); bfast.SetEnumerable("A", () => new int[3] { 0, 1, 2 }); var result = bfast.GetArray("A"); @@ -100,7 +100,7 @@ public void SetEnumerable_Then_GetArray_Bytes() [Test] public void SetEnumerable_Then_GetEnumerable_Bytes() { - var bfast = new BFastNext(); + var bfast = new BFast(); bfast.SetEnumerable("A", () => new int[3] { 0, 1, 2 }); var result = bfast.GetEnumerable("A"); @@ -111,7 +111,7 @@ public void SetEnumerable_Then_GetEnumerable_Bytes() [Test] public void SetEnumerable_Then_GetEnumerable_Float() { - var bfast = new BFastNext(); + var bfast = new BFast(); bfast.SetEnumerable("A", () => new int[3] { 0, 1, 2 }); var result = bfast.GetEnumerable("A"); @@ -122,7 +122,7 @@ public void SetEnumerable_Then_GetEnumerable_Float() [Test] public void SetEnumerable_Then_GetArray_Float() { - var bfast = new BFastNext(); + var bfast = new BFast(); bfast.SetEnumerable("A", () => new int[3] { 0, 1, 2 }); var result = bfast.GetArray("A"); @@ -134,7 +134,7 @@ public void SetEnumerable_Then_GetArray_Float() [Test] public void SetEnumerable_Then_GetEnumerable() { - var bfast = new BFastNext(); + var bfast = new BFast(); bfast.SetEnumerable("A", () => new int[3] { 0, 1, 2 }); var result = bfast.GetEnumerable("A").ToArray(); Assert.That(result, Is.EqualTo(new int[3] { 0, 1, 2 })); @@ -143,7 +143,7 @@ public void SetEnumerable_Then_GetEnumerable() [Test] public void SetEnumerable_Then_GetBFast() { - var bfast = new BFastNext(); + var bfast = new BFast(); bfast.SetEnumerable("A", () => new int[3] { 0, 1, 2 }); var result = bfast.GetBFast("A"); Assert.That(result, Is.Null); @@ -158,7 +158,7 @@ IEnumerable GetLots() [Test, Explicit] public void SetEnumerable_Then_GetEnumerable_Lots() { - var bfast = new BFastNext(); + var bfast = new BFast(); bfast.SetEnumerable("A", GetLots); var result = bfast.GetEnumerable("A"); @@ -169,7 +169,7 @@ public void SetEnumerable_Then_GetEnumerable_Lots() [Test] public void SetArray_Adds_Entry() { - var bfast = new BFastNext(); + var bfast = new BFast(); bfast.SetArray("A", new int[3] { 0, 1, 2 }); Assert.That(bfast.Entries.Count(), Is.EqualTo(1)); @@ -178,7 +178,7 @@ public void SetArray_Adds_Entry() [Test] public void SetArray_Then_GetArray() { - var bfast = new BFastNext(); + var bfast = new BFast(); bfast.SetArray("A", new int[3] { 0, 1, 2 }); var result = bfast.GetArray("A"); @@ -188,7 +188,7 @@ public void SetArray_Then_GetArray() [Test] public void SetArray_Then_GetArray_Bytes() { - var bfast = new BFastNext(); + var bfast = new BFast(); bfast.SetArray("A", new int[3] { 0, 1, 2 }); var result = bfast.GetArray("A"); @@ -199,7 +199,7 @@ public void SetArray_Then_GetArray_Bytes() [Test] public void SetArray_Then_GetArray_Float() { - var bfast = new BFastNext(); + var bfast = new BFast(); bfast.SetArray("A", new int[3] { 0, 1, 2 }); var result = bfast.GetArray("A"); @@ -210,7 +210,7 @@ public void SetArray_Then_GetArray_Float() [Test] public void SetArray_Then_GetEnumerable() { - var bfast = new BFastNext(); + var bfast = new BFast(); bfast.SetArray("A", new int[3] { 0, 1, 2 }); var result = bfast.GetEnumerable("A"); @@ -220,7 +220,7 @@ public void SetArray_Then_GetEnumerable() [Test] public void SetArray_Then_GetEnumerable_Bytes() { - var bfast = new BFastNext(); + var bfast = new BFast(); bfast.SetArray("A", new int[3] { 0, 1, 2 }); var result = bfast.GetEnumerable("A"); @@ -231,7 +231,7 @@ public void SetArray_Then_GetEnumerable_Bytes() [Test] public void SetArray_Then_GetEnumerable_Float() { - var bfast = new BFastNext(); + var bfast = new BFast(); bfast.SetArray("A", new int[3] { 0, 1, 2 }); var result = bfast.GetEnumerable("A"); @@ -242,7 +242,7 @@ public void SetArray_Then_GetEnumerable_Float() [Test] public void SetArray_Then_GetBFast_Returns_Null() { - var bfast = new BFastNext(); + var bfast = new BFast(); bfast.SetArray("A", new int[3] { 0, 1, 2 }); var result = bfast.GetBFast("A"); @@ -252,7 +252,7 @@ public void SetArray_Then_GetBFast_Returns_Null() [Test] public void SetArray_Then_SetArray_Replaces() { - var bfast = new BFastNext(); + var bfast = new BFast(); bfast.SetArray("A", new int[3] { 0, 1, 2 }); bfast.SetArray("A", new float[3] { 0.1f, 0.2f, 0.3f }); var result = bfast.GetArray("A"); @@ -263,10 +263,10 @@ public void SetArray_Then_SetArray_Replaces() [Test] public void SetArray_Then_SetBFast_Replaces() { - var bfast = new BFastNext(); + var bfast = new BFast(); bfast.SetArray("A", new int[3] { 0, 1, 2 }); - bfast.SetBFast("A", new BFastNext()); + bfast.SetBFast("A", new BFast()); var result = bfast.GetArray("A"); Assert.That(result.Length > 3); } @@ -274,8 +274,8 @@ public void SetArray_Then_SetBFast_Replaces() [Test] public void SetBFast_Adds_Entry() { - var bfast = new BFastNext(); - bfast.SetBFast("A", new BFastNext()); + var bfast = new BFast(); + bfast.SetBFast("A", new BFast()); Assert.That(bfast.Entries.Count(), Is.EqualTo(1)); } @@ -283,8 +283,8 @@ public void SetBFast_Adds_Entry() [Test] public void SetBFast_Then_GetBFast_Returns_Same() { - var bfast = new BFastNext(); - var b = new BFastNext(); + var bfast = new BFast(); + var b = new BFast(); bfast.SetBFast("A", b); var result = bfast.GetBFast("A"); @@ -294,8 +294,8 @@ public void SetBFast_Then_GetBFast_Returns_Same() [Test] public void Inflate_NonDeflated_Throws() { - var bfast = new BFastNext(); - var b = new BFastNext(); + var bfast = new BFast(); + var b = new BFast(); bfast.SetBFast("A", b); Assert.That(() => bfast.GetBFast("A", inflate: true), Throws.Exception); } @@ -303,8 +303,8 @@ public void Inflate_NonDeflated_Throws() [Test] public void Deflate_Inflate_Works() { - var bfast = new BFastNext(); - var b = new BFastNext(); + var bfast = new BFast(); + var b = new BFast(); b.SetArray("B", new int[3] { 0, 1, 2 }); bfast.SetBFast("A", b, deflate : true); @@ -317,9 +317,9 @@ public void Deflate_Inflate_Works() [Test] public void SetBFast_Then_SetBFast_Replaces() { - var bfast = new BFastNext(); - var a = new BFastNext(); - var b = new BFastNext(); + var bfast = new BFast(); + var a = new BFast(); + var b = new BFast(); bfast.SetBFast("A", a); bfast.SetBFast("A", b); var result = bfast.GetBFast("A"); @@ -330,8 +330,8 @@ public void SetBFast_Then_SetBFast_Replaces() [Test] public void SetBFast_Then_SetArray_Replaces() { - var bfast = new BFastNext(); - bfast.SetBFast("A", new BFastNext()); + var bfast = new BFast(); + bfast.SetBFast("A", new BFast()); bfast.SetArray("A", new int[3] { 0, 1, 2 }); var result = bfast.GetBFast("A"); Assert.IsNull(result); @@ -340,7 +340,7 @@ public void SetBFast_Then_SetArray_Replaces() [Test] public void Remove_Missing_DoesNothing() { - var bfast = new BFastNext(); + var bfast = new BFast(); bfast.Remove("A"); Assert.That(bfast.Entries.Count() == 0); } @@ -348,7 +348,7 @@ public void Remove_Missing_DoesNothing() [Test] public void Remove_Array() { - var bfast = new BFastNext(); + var bfast = new BFast(); bfast.SetArray("A", new int[3] { 0, 1, 2 }); bfast.Remove("A"); Assert.IsNull(bfast.GetArray("A")); @@ -358,8 +358,8 @@ public void Remove_Array() [Test] public void Remove_BFast() { - var bfast = new BFastNext(); - bfast.SetBFast("A", new BFastNext()); + var bfast = new BFast(); + bfast.SetBFast("A", new BFast()); bfast.Remove("A"); Assert.IsNull(bfast.GetBFast("A")); Assert.That(bfast.Entries.Count() == 0); @@ -368,15 +368,15 @@ public void Remove_BFast() [Test] public void Removed_BFast_Not_Written() { - var bfast = new BFastNext(); - bfast.SetBFast("A", new BFastNext()); + var bfast = new BFast(); + bfast.SetBFast("A", new BFast()); bfast.Remove("A"); bfast.Write(Path); using (var stream = File.OpenRead(Path)) { - var other = new BFastNext(stream); + var other = new BFast(stream); Assert.IsNull(other.GetBFast("A")); Assert.That(other.Entries.Count() == 0); } @@ -385,14 +385,14 @@ public void Removed_BFast_Not_Written() [Test] public void Removed_Array_Not_Written() { - var bfast = new BFastNext(); + var bfast = new BFast(); bfast.SetArray("A", new int[3] { 0, 1, 2 }); bfast.Remove("A"); bfast.Write(Path); using (var stream = File.OpenRead(Path)) { - var other = new BFastNext(stream); + var other = new BFast(stream); Assert.IsNull(other.GetArray("A")); Assert.That(other.Entries.Count() == 0); } @@ -403,7 +403,7 @@ public void Removed_InChild_Not_Written() { using (var residence = File.OpenRead(ResidencePath)) { - var input = new BFastNext(residence); + var input = new BFast(residence); var geometry = input.GetBFast("geometry"); geometry.Remove("g3d:vertex:position:0:float32:3"); input.SetBFast("geometry", geometry); @@ -412,7 +412,7 @@ public void Removed_InChild_Not_Written() using (var stream = File.OpenRead(Path)) { - var bfast = new BFastNext(stream); + var bfast = new BFast(stream); var geometry = bfast.GetBFast("geometry"); Assert.That(bfast.Entries.Count() == 5); Assert.That(geometry.Entries.Count() == 16); @@ -423,14 +423,14 @@ public void Removed_InChild_Not_Written() [Test] public void Write_Then_Read_Array() { - var bfast = new BFastNext(); + var bfast = new BFast(); bfast.SetArray("A", new int[3] { 0, 1, 2 }); bfast.Write(Path); using (var stream = File.OpenRead(Path)) { - var other = new BFastNext(stream); + var other = new BFast(stream); var result = other.GetArray("A"); Assert.That(result, Is.EqualTo(new int[3] { 0, 1, 2 })); } @@ -439,14 +439,14 @@ public void Write_Then_Read_Array() [Test] public void Write_Then_Read_Enumerable() { - var bfast = new BFastNext(); + var bfast = new BFast(); bfast.SetEnumerable("A", () => new int[3] { 0, 1, 2 }); bfast.Write(Path); using (var stream = File.OpenRead(Path)) { - var other = new BFastNext(stream); + var other = new BFast(stream); var array = other.GetArray("A"); var enumerable = other.GetEnumerable("A"); Assert.That(array, Is.EqualTo(new int[3] { 0, 1, 2 })); @@ -457,8 +457,8 @@ public void Write_Then_Read_Enumerable() [Test] public void Write_Then_Read_SimpleBFast() { - var bfast = new BFastNext(); - var child = new BFastNext(); + var bfast = new BFast(); + var child = new BFast(); bfast.SetBFast("child", child); child.SetArray("A", new int[3] { 0, 1, 2 }); @@ -466,7 +466,7 @@ public void Write_Then_Read_SimpleBFast() using (var stream = File.OpenRead(Path)) { - var other = new BFastNext(stream); + var other = new BFast(stream); var child2 = other.GetBFast("child"); var result = child2.GetArray("A"); @@ -479,9 +479,9 @@ public void Write_Then_Read_SimpleBFast() [Test] public void Write_Then_Read_NestedBFast() { - var bfast = new BFastNext(); - var child = new BFastNext(); - var grandChild = new BFastNext(); + var bfast = new BFast(); + var child = new BFast(); + var grandChild = new BFast(); bfast.SetBFast("child", child); child.SetBFast("grandChild", grandChild); @@ -489,7 +489,7 @@ public void Write_Then_Read_NestedBFast() using (var stream = File.OpenRead(Path)) { - var other = new BFastNext(stream); + var other = new BFast(stream); var child2 = other.GetBFast("child"); var grandChild2 = child2.GetBFast("grandChild"); @@ -502,9 +502,9 @@ public void Write_Then_Read_NestedBFast() [Test] public void Write_Then_Read_NestedBFast_WithArray() { - var bfast = new BFastNext(); - var child = new BFastNext(); - var grandChild = new BFastNext(); + var bfast = new BFast(); + var child = new BFast(); + var grandChild = new BFast(); bfast.SetBFast("child", child); child.SetBFast("grandChild", grandChild); @@ -514,7 +514,7 @@ public void Write_Then_Read_NestedBFast_WithArray() bfast.Write(Path); using (var stream = File.OpenRead(Path)) { - var other = new BFastNext(stream); + var other = new BFast(stream); var child2 = other.GetBFast("child"); var grandChild2 = child2.GetBFast("grandChild"); var result = grandChild2.GetArray("A"); @@ -529,7 +529,7 @@ public void Write_Then_Read_NestedBFast_WithArray() [Test] public void Write_Then_Read_Mixed_Sources() { - var basic = new BFastNext(); + var basic = new BFast(); basic.SetArray("ints", new int[1] { 1 }); basic.SetArray("floats", new float[1] { 2.0f }); basic.Write(Path); @@ -538,9 +538,9 @@ public void Write_Then_Read_Mixed_Sources() { using (var residence = File.OpenRead(ResidencePath)) { - var input = new BFastNext(stream); - var inputResidence = new BFastNext(residence); - var output = new BFastNext(); + var input = new BFast(stream); + var inputResidence = new BFast(residence); + var output = new BFast(); output.SetBFast("input", input); output.SetBFast("residence", inputResidence); @@ -550,7 +550,7 @@ public void Write_Then_Read_Mixed_Sources() using (var stream = File.OpenRead(OutputPath)) { - var bfast = new BFastNext(stream); + var bfast = new BFast(stream); var input = bfast.GetBFast("input"); var residence = bfast.GetBFast("residence"); var geometry = residence.GetBFast("geometry"); diff --git a/src/cs/bfast/Vim.BFastNext.Tests/Vim.BFastNext.Tests.csproj b/src/cs/bfast/Vim.BFastNext.Tests/Vim.BFast.Tests.csproj similarity index 87% rename from src/cs/bfast/Vim.BFastNext.Tests/Vim.BFastNext.Tests.csproj rename to src/cs/bfast/Vim.BFastNext.Tests/Vim.BFast.Tests.csproj index 91f1af4e..43889a65 100644 --- a/src/cs/bfast/Vim.BFastNext.Tests/Vim.BFastNext.Tests.csproj +++ b/src/cs/bfast/Vim.BFastNext.Tests/Vim.BFast.Tests.csproj @@ -1,4 +1,4 @@ - + net6.0 @@ -19,7 +19,7 @@ - + diff --git a/src/cs/g3d/Vim.G3d.Tests/G3dTests.cs b/src/cs/g3d/Vim.G3d.Tests/G3dTests.cs index 0493bc02..4704ae32 100644 --- a/src/cs/g3d/Vim.G3d.Tests/G3dTests.cs +++ b/src/cs/g3d/Vim.G3d.Tests/G3dTests.cs @@ -215,8 +215,8 @@ public static void TriangleTest() .Add(materialIndices.ToIArray().ToFaceMaterialAttribute()) .ToG3D(); - var bytes = g3d.ToBFast().AsBytes(); - var g = G3D.Read(bytes); + var bfast = g3d.ToBFast(); + var g = G3D.Read(bfast); Assert.IsNotNull(g); @@ -253,8 +253,8 @@ public static void QuadAndCopyTest() .Add(materialIndices.ToIArray().ToFaceMaterialAttribute()) .ToG3D(); - var bytes = g3d.ToBFast().AsBytes(); - var g = G3D.Read(bytes); + var bfast = g3d.ToBFast(); + var g = G3D.Read(bfast); Assert.IsNotNull(g); diff --git a/src/cs/g3d/Vim.G3d/G3D.cs b/src/cs/g3d/Vim.G3d/G3D.cs index 4017134e..085c988e 100644 --- a/src/cs/g3d/Vim.G3d/G3D.cs +++ b/src/cs/g3d/Vim.G3d/G3D.cs @@ -11,6 +11,7 @@ Usage licensed under terms of MIT License using System.Linq; using Vim.LinqArray; using Vim.Math3d; +using Vim.BFastNS; namespace Vim.G3d { @@ -292,22 +293,49 @@ public Vector3 ComputeFaceNormal(int nFace) public static G3D Read(string filePath) { using (var stream = File.OpenRead(filePath)) - return stream.ReadG3d(); + { + var bfast = new BFastNS.BFast(stream); + return Read(bfast); + } } - public static G3D Read(Stream stream) - => stream.ReadG3d(); - public static G3D Read(byte[] bytes) + public static G3D Read(BFastNS.BFast bfast) { - using (var stream = new MemoryStream(bytes)) - return stream.ReadG3d(); + var header = G3dHeader.FromBytesOrDefault(bfast.GetArray("meta")); + var attributes = new List(); + foreach (var name in bfast.Entries) + { + if (name == "meta") continue; + var attribute = GetEmptyAttribute(name); + var a = attribute.Read(bfast); + attributes.Add(a); + } + + return new G3D(attributes, header); } + private static GeometryAttribute GetEmptyAttribute(string name) + { + if (!AttributeDescriptor.TryParse(name, out var attributeDescriptor)) + { + return null; + } + try + { + return attributeDescriptor.ToDefaultAttribute(0); + } + catch + { + return null; + } + } + public static G3D Create(params GeometryAttribute[] attributes) => new G3D(attributes); public static G3D Create(G3dHeader header, params GeometryAttribute[] attributes) => new G3D(attributes, header); + } } diff --git a/src/cs/g3d/Vim.G3d/G3dSerialization.cs b/src/cs/g3d/Vim.G3d/G3dSerialization.cs index f62b54a4..6369dcb2 100644 --- a/src/cs/g3d/Vim.G3d/G3dSerialization.cs +++ b/src/cs/g3d/Vim.G3d/G3dSerialization.cs @@ -1,7 +1,6 @@ using System; using System.IO; -using Vim.BFastNextNS; -using Vim.Buffers; +using Vim.BFastNS; using Vim.LinqArray; using System.Collections.Generic; @@ -19,9 +18,9 @@ public static void WriteAttribute(Stream stream, GeometryAttribute attribute, st stream.Write(buffer); } - public static BFastNext ToBFast(this IGeometryAttributes self, G3dHeader? header = null) + public static BFastNS.BFast ToBFast(this IGeometryAttributes self, G3dHeader? header = null) { - var bfast = new BFastNext(); + var bfast = new BFastNS.BFast(); bfast.SetArray("meta", (header ?? G3dHeader.Default).ToBytes()); foreach(var attribute in self.Attributes.ToEnumerable()) { @@ -30,36 +29,7 @@ public static BFastNext ToBFast(this IGeometryAttributes self, G3dHeader? header return bfast; } - public static G3D ReadG3d(this Stream stream, Func renameFunc = null) - { - var bfast = new BFastNext(stream); - - var header = G3dHeader.FromBytesOrDefault(bfast.GetArray("meta")); - var attributes = new List(); - foreach (var name in bfast.Entries) - { - if (name == "meta") continue; - var attribute = GetAttribute(name); - var a = attribute.Read(bfast); - attributes.Add(a); - } - return new G3D(attributes, header); - } - public static GeometryAttribute GetAttribute(string name) - { - if (!AttributeDescriptor.TryParse(name, out var attributeDescriptor)) - { - return null; - } - try - { - return attributeDescriptor.ToDefaultAttribute(0); - } - catch - { - return null; - } - } + } } diff --git a/src/cs/g3d/Vim.G3d/GeometryAttribute.cs b/src/cs/g3d/Vim.G3d/GeometryAttribute.cs index f6f8fcfa..6f916076 100644 --- a/src/cs/g3d/Vim.G3d/GeometryAttribute.cs +++ b/src/cs/g3d/Vim.G3d/GeometryAttribute.cs @@ -2,10 +2,9 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using Vim.Buffers; using Vim.LinqArray; using Vim.Math3d; -using Vim.BFastNextNS; +using Vim.BFastNS; namespace Vim.G3d { @@ -89,9 +88,9 @@ public GeometryAttribute AsType() where T : unmanaged /// /// Loads the correct typed data from a BFastNext. /// - public abstract GeometryAttribute Read(BFastNext bfast); + public abstract GeometryAttribute Read(BFastNS.BFast bfast); - public abstract void AddTo(BFastNext bfast); + public abstract void AddTo(BFastNS.BFast bfast); /// /// Creates a new GeometryAttribute with the same data, but with a different index. Useful when constructing attributes @@ -228,13 +227,13 @@ public override GeometryAttribute Read(Stream stream, long byteCount) return new GeometryAttribute(data.ToIArray(), Descriptor); } - public override GeometryAttribute Read(BFastNext bfast) + public override GeometryAttribute Read(BFastNS.BFast bfast) { var array = bfast.GetArray(Name); return new GeometryAttribute(array.ToIArray(), Descriptor); } - public override void AddTo(BFastNext bfast) + public override void AddTo(BFastNS.BFast bfast) { bfast.SetArray(Name, Data.ToArray()); } diff --git a/src/cs/g3d/Vim.G3d/Vim.G3d.csproj b/src/cs/g3d/Vim.G3d/Vim.G3d.csproj index 0161fc81..dce2f4f2 100644 --- a/src/cs/g3d/Vim.G3d/Vim.G3d.csproj +++ b/src/cs/g3d/Vim.G3d/Vim.G3d.csproj @@ -48,8 +48,7 @@ It can be easily and efficiently deserialized and rendered in different language - - + diff --git a/src/cs/g3d/Vim.G3dNext.Attributes/Attributes.g.cs b/src/cs/g3d/Vim.G3dNext.Attributes/Attributes.g.cs index ffb1484b..524d6a47 100644 --- a/src/cs/g3d/Vim.G3dNext.Attributes/Attributes.g.cs +++ b/src/cs/g3d/Vim.G3dNext.Attributes/Attributes.g.cs @@ -4,8 +4,7 @@ using System.IO; using System.Collections.Generic; using System.Linq; -using Vim.BFastNextNS; -using Vim.Buffers; +using Vim.BFastNS; namespace Vim.G3dNext.Attributes { @@ -19,7 +18,7 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext bfast) + public void AddTo(BFast bfast) { if(TypedData != null) { @@ -27,7 +26,7 @@ public void AddTo(BFastNext bfast) } } - public void ReadBFast(BFastNext bfast) + public void ReadBFast(BFast bfast) { TypedData = bfast.GetArray("g3d:vertex:position:0:float32:3"); } @@ -64,7 +63,7 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext bfast) + public void AddTo(BFast bfast) { if(TypedData != null) { @@ -72,7 +71,7 @@ public void AddTo(BFastNext bfast) } } - public void ReadBFast(BFastNext bfast) + public void ReadBFast(BFast bfast) { TypedData = bfast.GetArray("g3d:corner:index:0:int32:1"); } @@ -109,7 +108,7 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext bfast) + public void AddTo(BFast bfast) { if(TypedData != null) { @@ -117,7 +116,7 @@ public void AddTo(BFastNext bfast) } } - public void ReadBFast(BFastNext bfast) + public void ReadBFast(BFast bfast) { TypedData = bfast.GetArray("g3d:instance:transform:0:float32:16"); } @@ -154,7 +153,7 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext bfast) + public void AddTo(BFast bfast) { if(TypedData != null) { @@ -162,7 +161,7 @@ public void AddTo(BFastNext bfast) } } - public void ReadBFast(BFastNext bfast) + public void ReadBFast(BFast bfast) { TypedData = bfast.GetArray("g3d:instance:parent:0:int32:1"); } @@ -199,7 +198,7 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext bfast) + public void AddTo(BFast bfast) { if(TypedData != null) { @@ -207,7 +206,7 @@ public void AddTo(BFastNext bfast) } } - public void ReadBFast(BFastNext bfast) + public void ReadBFast(BFast bfast) { TypedData = bfast.GetArray("g3d:instance:flags:0:uint16:1"); } @@ -244,7 +243,7 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext bfast) + public void AddTo(BFast bfast) { if(TypedData != null) { @@ -252,7 +251,7 @@ public void AddTo(BFastNext bfast) } } - public void ReadBFast(BFastNext bfast) + public void ReadBFast(BFast bfast) { TypedData = bfast.GetArray("g3d:instance:mesh:0:int32:1"); } @@ -289,7 +288,7 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext bfast) + public void AddTo(BFast bfast) { if(TypedData != null) { @@ -297,7 +296,7 @@ public void AddTo(BFastNext bfast) } } - public void ReadBFast(BFastNext bfast) + public void ReadBFast(BFast bfast) { TypedData = bfast.GetArray("g3d:mesh:submeshoffset:0:int32:1"); } @@ -334,7 +333,7 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext bfast) + public void AddTo(BFast bfast) { if(TypedData != null) { @@ -342,7 +341,7 @@ public void AddTo(BFastNext bfast) } } - public void ReadBFast(BFastNext bfast) + public void ReadBFast(BFast bfast) { TypedData = bfast.GetArray("g3d:submesh:indexoffset:0:int32:1"); } @@ -379,7 +378,7 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext bfast) + public void AddTo(BFast bfast) { if(TypedData != null) { @@ -387,7 +386,7 @@ public void AddTo(BFastNext bfast) } } - public void ReadBFast(BFastNext bfast) + public void ReadBFast(BFast bfast) { TypedData = bfast.GetArray("g3d:submesh:material:0:int32:1"); } @@ -424,7 +423,7 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext bfast) + public void AddTo(BFast bfast) { if(TypedData != null) { @@ -432,7 +431,7 @@ public void AddTo(BFastNext bfast) } } - public void ReadBFast(BFastNext bfast) + public void ReadBFast(BFast bfast) { TypedData = bfast.GetArray("g3d:material:color:0:float32:4"); } @@ -469,7 +468,7 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext bfast) + public void AddTo(BFast bfast) { if(TypedData != null) { @@ -477,7 +476,7 @@ public void AddTo(BFastNext bfast) } } - public void ReadBFast(BFastNext bfast) + public void ReadBFast(BFast bfast) { TypedData = bfast.GetArray("g3d:material:glossiness:0:float32:1"); } @@ -514,7 +513,7 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext bfast) + public void AddTo(BFast bfast) { if(TypedData != null) { @@ -522,7 +521,7 @@ public void AddTo(BFastNext bfast) } } - public void ReadBFast(BFastNext bfast) + public void ReadBFast(BFast bfast) { TypedData = bfast.GetArray("g3d:material:smoothness:0:float32:1"); } @@ -559,7 +558,7 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext bfast) + public void AddTo(BFast bfast) { if(TypedData != null) { @@ -567,7 +566,7 @@ public void AddTo(BFastNext bfast) } } - public void ReadBFast(BFastNext bfast) + public void ReadBFast(BFast bfast) { TypedData = bfast.GetArray("g3d:shapevertex:position:0:float32:3"); } @@ -604,7 +603,7 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext bfast) + public void AddTo(BFast bfast) { if(TypedData != null) { @@ -612,7 +611,7 @@ public void AddTo(BFastNext bfast) } } - public void ReadBFast(BFastNext bfast) + public void ReadBFast(BFast bfast) { TypedData = bfast.GetArray("g3d:shape:vertexoffset:0:int32:1"); } @@ -649,7 +648,7 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext bfast) + public void AddTo(BFast bfast) { if(TypedData != null) { @@ -657,7 +656,7 @@ public void AddTo(BFastNext bfast) } } - public void ReadBFast(BFastNext bfast) + public void ReadBFast(BFast bfast) { TypedData = bfast.GetArray("g3d:shape:color:0:float32:4"); } @@ -694,7 +693,7 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext bfast) + public void AddTo(BFast bfast) { if(TypedData != null) { @@ -702,7 +701,7 @@ public void AddTo(BFastNext bfast) } } - public void ReadBFast(BFastNext bfast) + public void ReadBFast(BFast bfast) { TypedData = bfast.GetArray("g3d:shape:width:0:float32:1"); } @@ -739,7 +738,7 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext bfast) + public void AddTo(BFast bfast) { if(TypedData != null) { @@ -747,7 +746,7 @@ public void AddTo(BFastNext bfast) } } - public void ReadBFast(BFastNext bfast) + public void ReadBFast(BFast bfast) { TypedData = bfast.GetArray("g3d:material:color:0:float32:4"); } @@ -784,7 +783,7 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext bfast) + public void AddTo(BFast bfast) { if(TypedData != null) { @@ -792,7 +791,7 @@ public void AddTo(BFastNext bfast) } } - public void ReadBFast(BFastNext bfast) + public void ReadBFast(BFast bfast) { TypedData = bfast.GetArray("g3d:material:glossiness:0:float32:1"); } @@ -829,7 +828,7 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext bfast) + public void AddTo(BFast bfast) { if(TypedData != null) { @@ -837,7 +836,7 @@ public void AddTo(BFastNext bfast) } } - public void ReadBFast(BFastNext bfast) + public void ReadBFast(BFast bfast) { TypedData = bfast.GetArray("g3d:material:smoothness:0:float32:1"); } @@ -874,7 +873,7 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext bfast) + public void AddTo(BFast bfast) { if(TypedData != null) { @@ -882,7 +881,7 @@ public void AddTo(BFastNext bfast) } } - public void ReadBFast(BFastNext bfast) + public void ReadBFast(BFast bfast) { TypedData = bfast.GetArray("g3d:chunk:count:0:int32:1"); } @@ -919,7 +918,7 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext bfast) + public void AddTo(BFast bfast) { if(TypedData != null) { @@ -927,7 +926,7 @@ public void AddTo(BFastNext bfast) } } - public void ReadBFast(BFastNext bfast) + public void ReadBFast(BFast bfast) { TypedData = bfast.GetArray("g3d:instance:mesh:0:int32:1"); } @@ -964,7 +963,7 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext bfast) + public void AddTo(BFast bfast) { if(TypedData != null) { @@ -972,7 +971,7 @@ public void AddTo(BFastNext bfast) } } - public void ReadBFast(BFastNext bfast) + public void ReadBFast(BFast bfast) { TypedData = bfast.GetArray("g3d:instance:transform:0:int32:1"); } @@ -1009,7 +1008,7 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext bfast) + public void AddTo(BFast bfast) { if(TypedData != null) { @@ -1017,7 +1016,7 @@ public void AddTo(BFastNext bfast) } } - public void ReadBFast(BFastNext bfast) + public void ReadBFast(BFast bfast) { TypedData = bfast.GetArray("g3d:instance:transform:0:float32:16"); } @@ -1054,7 +1053,7 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext bfast) + public void AddTo(BFast bfast) { if(TypedData != null) { @@ -1062,7 +1061,7 @@ public void AddTo(BFastNext bfast) } } - public void ReadBFast(BFastNext bfast) + public void ReadBFast(BFast bfast) { TypedData = bfast.GetArray("g3d:instance:node:0:int32:1"); } @@ -1099,7 +1098,7 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext bfast) + public void AddTo(BFast bfast) { if(TypedData != null) { @@ -1107,7 +1106,7 @@ public void AddTo(BFastNext bfast) } } - public void ReadBFast(BFastNext bfast) + public void ReadBFast(BFast bfast) { TypedData = bfast.GetArray("g3d:instance:group:0:int32:1"); } @@ -1144,7 +1143,7 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext bfast) + public void AddTo(BFast bfast) { if(TypedData != null) { @@ -1152,7 +1151,7 @@ public void AddTo(BFastNext bfast) } } - public void ReadBFast(BFastNext bfast) + public void ReadBFast(BFast bfast) { TypedData = bfast.GetArray("g3d:instance:tag:0:int64:1"); } @@ -1189,7 +1188,7 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext bfast) + public void AddTo(BFast bfast) { if(TypedData != null) { @@ -1197,7 +1196,7 @@ public void AddTo(BFastNext bfast) } } - public void ReadBFast(BFastNext bfast) + public void ReadBFast(BFast bfast) { TypedData = bfast.GetArray("g3d:instance:flags:0:uint16:1"); } @@ -1234,7 +1233,7 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext bfast) + public void AddTo(BFast bfast) { if(TypedData != null) { @@ -1242,7 +1241,7 @@ public void AddTo(BFastNext bfast) } } - public void ReadBFast(BFastNext bfast) + public void ReadBFast(BFast bfast) { TypedData = bfast.GetArray("g3d:instance:min:0:float32:3"); } @@ -1279,7 +1278,7 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext bfast) + public void AddTo(BFast bfast) { if(TypedData != null) { @@ -1287,7 +1286,7 @@ public void AddTo(BFastNext bfast) } } - public void ReadBFast(BFastNext bfast) + public void ReadBFast(BFast bfast) { TypedData = bfast.GetArray("g3d:instance:max:0:float32:3"); } @@ -1324,7 +1323,7 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext bfast) + public void AddTo(BFast bfast) { if(TypedData != null) { @@ -1332,7 +1331,7 @@ public void AddTo(BFastNext bfast) } } - public void ReadBFast(BFastNext bfast) + public void ReadBFast(BFast bfast) { TypedData = bfast.GetArray("g3d:mesh:chunk:0:int32:1"); } @@ -1369,7 +1368,7 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext bfast) + public void AddTo(BFast bfast) { if(TypedData != null) { @@ -1377,7 +1376,7 @@ public void AddTo(BFastNext bfast) } } - public void ReadBFast(BFastNext bfast) + public void ReadBFast(BFast bfast) { TypedData = bfast.GetArray("g3d:mesh:chunkindex:0:int32:1"); } @@ -1414,7 +1413,7 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext bfast) + public void AddTo(BFast bfast) { if(TypedData != null) { @@ -1422,7 +1421,7 @@ public void AddTo(BFastNext bfast) } } - public void ReadBFast(BFastNext bfast) + public void ReadBFast(BFast bfast) { TypedData = bfast.GetArray("g3d:mesh:instancecount:0:int32:1"); } @@ -1459,7 +1458,7 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext bfast) + public void AddTo(BFast bfast) { if(TypedData != null) { @@ -1467,7 +1466,7 @@ public void AddTo(BFastNext bfast) } } - public void ReadBFast(BFastNext bfast) + public void ReadBFast(BFast bfast) { TypedData = bfast.GetArray("g3d:mesh:vertexcount:0:int32:1"); } @@ -1504,7 +1503,7 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext bfast) + public void AddTo(BFast bfast) { if(TypedData != null) { @@ -1512,7 +1511,7 @@ public void AddTo(BFastNext bfast) } } - public void ReadBFast(BFastNext bfast) + public void ReadBFast(BFast bfast) { TypedData = bfast.GetArray("g3d:mesh:indexcount:0:int32:1"); } @@ -1549,7 +1548,7 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext bfast) + public void AddTo(BFast bfast) { if(TypedData != null) { @@ -1557,7 +1556,7 @@ public void AddTo(BFastNext bfast) } } - public void ReadBFast(BFastNext bfast) + public void ReadBFast(BFast bfast) { TypedData = bfast.GetArray("g3d:mesh:opaquevertexcount:0:int32:1"); } @@ -1594,7 +1593,7 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext bfast) + public void AddTo(BFast bfast) { if(TypedData != null) { @@ -1602,7 +1601,7 @@ public void AddTo(BFastNext bfast) } } - public void ReadBFast(BFastNext bfast) + public void ReadBFast(BFast bfast) { TypedData = bfast.GetArray("g3d:mesh:opaqueindexcount:0:int32:1"); } @@ -1639,7 +1638,7 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext bfast) + public void AddTo(BFast bfast) { if(TypedData != null) { @@ -1647,7 +1646,7 @@ public void AddTo(BFastNext bfast) } } - public void ReadBFast(BFastNext bfast) + public void ReadBFast(BFast bfast) { TypedData = bfast.GetArray("g3d:instance:transform:0:float32:16"); } @@ -1684,7 +1683,7 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext bfast) + public void AddTo(BFast bfast) { if(TypedData != null) { @@ -1692,7 +1691,7 @@ public void AddTo(BFastNext bfast) } } - public void ReadBFast(BFastNext bfast) + public void ReadBFast(BFast bfast) { TypedData = bfast.GetArray("g3d:mesh:opaquesubmeshcount:0:int32:1"); } @@ -1729,7 +1728,7 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext bfast) + public void AddTo(BFast bfast) { if(TypedData != null) { @@ -1737,7 +1736,7 @@ public void AddTo(BFastNext bfast) } } - public void ReadBFast(BFastNext bfast) + public void ReadBFast(BFast bfast) { TypedData = bfast.GetArray("g3d:submesh:indexoffset:0:int32:1"); } @@ -1774,7 +1773,7 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext bfast) + public void AddTo(BFast bfast) { if(TypedData != null) { @@ -1782,7 +1781,7 @@ public void AddTo(BFastNext bfast) } } - public void ReadBFast(BFastNext bfast) + public void ReadBFast(BFast bfast) { TypedData = bfast.GetArray("g3d:submesh:vertexoffset:0:int32:1"); } @@ -1819,7 +1818,7 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext bfast) + public void AddTo(BFast bfast) { if(TypedData != null) { @@ -1827,7 +1826,7 @@ public void AddTo(BFastNext bfast) } } - public void ReadBFast(BFastNext bfast) + public void ReadBFast(BFast bfast) { TypedData = bfast.GetArray("g3d:submesh:material:0:int32:1"); } @@ -1864,7 +1863,7 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext bfast) + public void AddTo(BFast bfast) { if(TypedData != null) { @@ -1872,7 +1871,7 @@ public void AddTo(BFastNext bfast) } } - public void ReadBFast(BFastNext bfast) + public void ReadBFast(BFast bfast) { TypedData = bfast.GetArray("g3d:vertex:position:0:float32:3"); } @@ -1909,7 +1908,7 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext bfast) + public void AddTo(BFast bfast) { if(TypedData != null) { @@ -1917,7 +1916,7 @@ public void AddTo(BFastNext bfast) } } - public void ReadBFast(BFastNext bfast) + public void ReadBFast(BFast bfast) { TypedData = bfast.GetArray("g3d:corner:index:0:int32:1"); } @@ -1955,7 +1954,7 @@ public G3dVim() : this(new VimAttributeCollection()) // empty } - public G3dVim(BFastNext bfast) : this(new VimAttributeCollection(bfast)) + public G3dVim(BFast bfast) : this(new VimAttributeCollection(bfast)) { // empty } @@ -1968,7 +1967,7 @@ public G3dVim(VimAttributeCollection attributes) (this as ISetup).Setup(); } - public BFastNext ToBFast() + public BFast ToBFast() => Attributes.ToBFast(); @@ -2077,12 +2076,12 @@ public VimAttributeCollection() // empty } - public VimAttributeCollection(BFastNext bfast) + public VimAttributeCollection(BFast bfast) { this.ReadAttributes(bfast); } - public void ReadAttributes(BFastNext bfast) + public void ReadAttributes(BFast bfast) { foreach (var attribute in Map.Values) { @@ -2090,6 +2089,9 @@ public void ReadAttributes(BFastNext bfast) } } + + + public IDictionary Map { get; } = new Dictionary { @@ -2501,7 +2503,7 @@ public G3dMaterials() : this(new MaterialsAttributeCollection()) // empty } - public G3dMaterials(BFastNext bfast) : this(new MaterialsAttributeCollection(bfast)) + public G3dMaterials(BFast bfast) : this(new MaterialsAttributeCollection(bfast)) { // empty } @@ -2514,7 +2516,7 @@ public G3dMaterials(MaterialsAttributeCollection attributes) (this as ISetup).Setup(); } - public BFastNext ToBFast() + public BFast ToBFast() => Attributes.ToBFast(); @@ -2545,12 +2547,12 @@ public MaterialsAttributeCollection() // empty } - public MaterialsAttributeCollection(BFastNext bfast) + public MaterialsAttributeCollection(BFast bfast) { this.ReadAttributes(bfast); } - public void ReadAttributes(BFastNext bfast) + public void ReadAttributes(BFast bfast) { foreach (var attribute in Map.Values) { @@ -2651,7 +2653,7 @@ public G3dScene() : this(new SceneAttributeCollection()) // empty } - public G3dScene(BFastNext bfast) : this(new SceneAttributeCollection(bfast)) + public G3dScene(BFast bfast) : this(new SceneAttributeCollection(bfast)) { // empty } @@ -2664,7 +2666,7 @@ public G3dScene(SceneAttributeCollection attributes) (this as ISetup).Setup(); } - public BFastNext ToBFast() + public BFast ToBFast() => Attributes.ToBFast(); @@ -2779,12 +2781,12 @@ public SceneAttributeCollection() // empty } - public SceneAttributeCollection(BFastNext bfast) + public SceneAttributeCollection(BFast bfast) { this.ReadAttributes(bfast); } - public void ReadAttributes(BFastNext bfast) + public void ReadAttributes(BFast bfast) { foreach (var attribute in Map.Values) { @@ -3123,7 +3125,7 @@ public G3dMesh() : this(new MeshAttributeCollection()) // empty } - public G3dMesh(BFastNext bfast) : this(new MeshAttributeCollection(bfast)) + public G3dMesh(BFast bfast) : this(new MeshAttributeCollection(bfast)) { // empty } @@ -3136,7 +3138,7 @@ public G3dMesh(MeshAttributeCollection attributes) (this as ISetup).Setup(); } - public BFastNext ToBFast() + public BFast ToBFast() => Attributes.ToBFast(); @@ -3191,12 +3193,12 @@ public MeshAttributeCollection() // empty } - public MeshAttributeCollection(BFastNext bfast) + public MeshAttributeCollection(BFast bfast) { this.ReadAttributes(bfast); } - public void ReadAttributes(BFastNext bfast) + public void ReadAttributes(BFast bfast) { foreach (var attribute in Map.Values) { diff --git a/src/cs/g3d/Vim.G3dNext.Attributes/G3dMaterials.cs b/src/cs/g3d/Vim.G3dNext.Attributes/G3dMaterials.cs index 249879cd..4e9ef39a 100644 --- a/src/cs/g3d/Vim.G3dNext.Attributes/G3dMaterials.cs +++ b/src/cs/g3d/Vim.G3dNext.Attributes/G3dMaterials.cs @@ -1,4 +1,6 @@ -namespace Vim.G3dNext.Attributes +using System.Runtime.ConstrainedExecution; + +namespace Vim.G3dNext.Attributes { public partial class G3dMaterials { @@ -6,5 +8,13 @@ void ISetup.Setup() { // empty } + + public G3dMaterials ReadFromVim(G3dVim vim) + { + MaterialColors = vim.MaterialColors; + MaterialGlossiness = vim.MaterialGlossiness; + MaterialSmoothness = vim.MaterialSmoothness; + return this; + } } -} \ No newline at end of file +} diff --git a/src/cs/g3d/Vim.G3dNext.Attributes/G3dVim.cs b/src/cs/g3d/Vim.G3dNext.Attributes/G3dVim.cs index e803a976..693de592 100644 --- a/src/cs/g3d/Vim.G3dNext.Attributes/G3dVim.cs +++ b/src/cs/g3d/Vim.G3dNext.Attributes/G3dVim.cs @@ -1,5 +1,5 @@ using System; -using Vim.BFastNextNS; +using Vim.BFastNS; namespace Vim.G3dNext.Attributes { diff --git a/src/cs/g3d/Vim.G3dNext.Attributes/Vim.G3dNext.Attributes.csproj b/src/cs/g3d/Vim.G3dNext.Attributes/Vim.G3dNext.Attributes.csproj index aabeb9f0..0efd3be5 100644 --- a/src/cs/g3d/Vim.G3dNext.Attributes/Vim.G3dNext.Attributes.csproj +++ b/src/cs/g3d/Vim.G3dNext.Attributes/Vim.G3dNext.Attributes.csproj @@ -9,7 +9,6 @@ - diff --git a/src/cs/g3d/Vim.G3dNext.CodeGen/G3dAttributeCollectionGenerator.cs b/src/cs/g3d/Vim.G3dNext.CodeGen/G3dAttributeCollectionGenerator.cs index 492e0e52..c75c6562 100644 --- a/src/cs/g3d/Vim.G3dNext.CodeGen/G3dAttributeCollectionGenerator.cs +++ b/src/cs/g3d/Vim.G3dNext.CodeGen/G3dAttributeCollectionGenerator.cs @@ -21,8 +21,7 @@ public static void WriteDocument(string filePath) cb.AppendLine("using System.IO;"); cb.AppendLine("using System.Collections.Generic;"); cb.AppendLine("using System.Linq;"); - cb.AppendLine("using Vim.BFast;"); - cb.AppendLine("using Vim.BFastNextNS;"); + cb.AppendLine("using Vim.BFastNS;"); cb.AppendLine(); cb.AppendLine("namespace Vim.G3dNext.Attributes"); cb.AppendLine("{"); @@ -93,7 +92,7 @@ public string Name public int Count => TypedData?.Length ?? 0; - public void AddTo(BFastNext bfast) + public void AddTo(BFast bfast) {{ if(TypedData != null) {{ @@ -101,7 +100,7 @@ public void AddTo(BFastNext bfast) }} }} - public void ReadBFast(BFastNext bfast) + public void ReadBFast(BFast bfast) {{ TypedData = bfast.GetArray<{typedDataType}>(""{attributeName}""); }} @@ -160,7 +159,7 @@ public partial class {g3dName} : ISetup // empty }} - public {g3dName}(BFastNext bfast) : this(new {className}(bfast)) + public {g3dName}(BFast bfast) : this(new {className}(bfast)) {{ // empty }} @@ -173,7 +172,7 @@ public partial class {g3dName} : ISetup (this as ISetup).Setup(); }} - public BFastNext ToBFast() + public BFast ToBFast() => Attributes.ToBFast(); { @@ -201,12 +200,12 @@ public partial class {className} : IAttributeCollection // empty }} - public {className}(BFastNext bfast) + public {className}(BFast bfast) {{ this.ReadAttributes(bfast); }} - public void ReadAttributes(BFastNext bfast) + public void ReadAttributes(BFast bfast) {{ foreach (var attribute in Map.Values) {{ diff --git a/src/cs/g3d/Vim.G3dNext/IAttribute.cs b/src/cs/g3d/Vim.G3dNext/IAttribute.cs index ec5554ff..9c180620 100644 --- a/src/cs/g3d/Vim.G3dNext/IAttribute.cs +++ b/src/cs/g3d/Vim.G3dNext/IAttribute.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using Vim.BFastNextNS; +using Vim.BFastNS; namespace Vim.G3dNext { @@ -14,8 +14,8 @@ public interface IAttribute Type IndexInto { get; } Array Data { get; } void Write(Stream stream); - void AddTo(BFastNext bfast); - void ReadBFast(BFastNext bfast); + void AddTo(BFastNS.BFast bfast); + void ReadBFast(BFastNS.BFast bfast); } public interface IAttribute : IAttribute diff --git a/src/cs/g3d/Vim.G3dNext/IAttributeCollection.cs b/src/cs/g3d/Vim.G3dNext/IAttributeCollection.cs index 60e9483e..e2efe32e 100644 --- a/src/cs/g3d/Vim.G3dNext/IAttributeCollection.cs +++ b/src/cs/g3d/Vim.G3dNext/IAttributeCollection.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; -using Vim.BFastNextNS; +using Vim.BFastNS; namespace Vim.G3dNext { @@ -58,13 +58,13 @@ public static long GetSize(this IAttributeCollection attributeCollection) => attributeCollection.Map.Values .Sum(a => a.GetSizeInBytes()); - public static BFastNext ToBFast(this IAttributeCollection attributeCollection) + public static BFastNS.BFast ToBFast(this IAttributeCollection attributeCollection) { var attributes = attributeCollection.Map.Values .OrderBy(n => n.Name) .ToArray(); // Order the attributes by name for consistency - var bfast = new BFastNext(); + var bfast = new BFastNS.BFast(); foreach (var a in attributes) { a.AddTo(bfast); diff --git a/src/cs/g3d/Vim.G3dNext/Vim.G3dNext.csproj b/src/cs/g3d/Vim.G3dNext/Vim.G3dNext.csproj index b09cb5e4..512e8bba 100644 --- a/src/cs/g3d/Vim.G3dNext/Vim.G3dNext.csproj +++ b/src/cs/g3d/Vim.G3dNext/Vim.G3dNext.csproj @@ -9,7 +9,7 @@ - + diff --git a/src/cs/vim-format.sln b/src/cs/vim-format.sln index 3838d0db..e63cfde9 100644 --- a/src/cs/vim-format.sln +++ b/src/cs/vim-format.sln @@ -53,16 +53,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vim.Format.Vimx", "vim\Vim. EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vim.Format.Vimx.Test", "vim\Vim.Vimx.Test\Vim.Format.Vimx.Test.csproj", "{BBF94CBD-CD39-49F5-979A-5C9E52C29330}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vim.BFastNext", "bfast\Vim.BFast.Next\Vim.BFastNext.csproj", "{408884EA-3CE5-4A34-97F6-1F2D64A0E745}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vim.BFast", "bfast\Vim.BFast.Next\Vim.BFast.csproj", "{408884EA-3CE5-4A34-97F6-1F2D64A0E745}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vim.BFastNext.Tests", "bfast\Vim.BFastNext.Tests\Vim.BFastNext.Tests.csproj", "{FD149D64-5905-4F7D-97A8-9F7DA18A257D}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vim.BFast.Tests", "bfast\Vim.BFastNext.Tests\Vim.BFast.Tests.csproj", "{FD149D64-5905-4F7D-97A8-9F7DA18A257D}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vim.Format.Vimx.Conversion", "vim\Vim.Format.Vimx.Conversion\Vim.Format.Vimx.Conversion.csproj", "{4C4F9826-0DEF-4A39-BFC8-A834522694A0}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Vim.BFast.Core", "Vim.BFast.Core\Vim.BFast.Core.csproj", "{7056183C-4DFE-4070-A714-A2AD9F47FA33}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Vim.Buffers", "Vim.Buffers\Vim.Buffers.csproj", "{BDB05F66-E90A-4DAE-A839-3281EE1338CC}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -157,14 +153,6 @@ Global {4C4F9826-0DEF-4A39-BFC8-A834522694A0}.Debug|Any CPU.Build.0 = Debug|Any CPU {4C4F9826-0DEF-4A39-BFC8-A834522694A0}.Release|Any CPU.ActiveCfg = Release|Any CPU {4C4F9826-0DEF-4A39-BFC8-A834522694A0}.Release|Any CPU.Build.0 = Release|Any CPU - {7056183C-4DFE-4070-A714-A2AD9F47FA33}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7056183C-4DFE-4070-A714-A2AD9F47FA33}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7056183C-4DFE-4070-A714-A2AD9F47FA33}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7056183C-4DFE-4070-A714-A2AD9F47FA33}.Release|Any CPU.Build.0 = Release|Any CPU - {BDB05F66-E90A-4DAE-A839-3281EE1338CC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {BDB05F66-E90A-4DAE-A839-3281EE1338CC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BDB05F66-E90A-4DAE-A839-3281EE1338CC}.Release|Any CPU.ActiveCfg = Release|Any CPU - {BDB05F66-E90A-4DAE-A839-3281EE1338CC}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -192,8 +180,6 @@ Global {408884EA-3CE5-4A34-97F6-1F2D64A0E745} = {F3260C54-834F-4C74-A3B7-EAB622AFA492} {FD149D64-5905-4F7D-97A8-9F7DA18A257D} = {F3260C54-834F-4C74-A3B7-EAB622AFA492} {4C4F9826-0DEF-4A39-BFC8-A834522694A0} = {D639C635-01D1-48C4-89B5-1FD70F1AFEE9} - {7056183C-4DFE-4070-A714-A2AD9F47FA33} = {F3260C54-834F-4C74-A3B7-EAB622AFA492} - {BDB05F66-E90A-4DAE-A839-3281EE1338CC} = {F3260C54-834F-4C74-A3B7-EAB622AFA492} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {7D1BF641-26E8-4809-B638-029241C51BE2} diff --git a/src/cs/vim/Vim.Format.Core/AssetInfo.cs b/src/cs/vim/Vim.Format.Core/AssetInfo.cs index 503c2827..7d07297a 100644 --- a/src/cs/vim/Vim.Format.Core/AssetInfo.cs +++ b/src/cs/vim/Vim.Format.Core/AssetInfo.cs @@ -3,7 +3,7 @@ using System.IO; using Vim.Util; using Vim.LinqArray; -using Vim.Buffers; +using Vim.BFastNS; namespace Vim.Format { diff --git a/src/cs/vim/Vim.Format.Core/ColumnExtensions.Buffer.cs b/src/cs/vim/Vim.Format.Core/ColumnExtensions.Buffer.cs index 55b6a3b2..34c7fc20 100644 --- a/src/cs/vim/Vim.Format.Core/ColumnExtensions.Buffer.cs +++ b/src/cs/vim/Vim.Format.Core/ColumnExtensions.Buffer.cs @@ -3,7 +3,7 @@ using System.Diagnostics; using System.Linq; using Vim.LinqArray; -using Vim.Buffers; +using Vim.BFastNS; namespace Vim.Format { diff --git a/src/cs/vim/Vim.Format.Core/Document.cs b/src/cs/vim/Vim.Format.Core/Document.cs index 91f93419..cf70001a 100644 --- a/src/cs/vim/Vim.Format.Core/Document.cs +++ b/src/cs/vim/Vim.Format.Core/Document.cs @@ -1,5 +1,5 @@ using Vim.LinqArray; -using Vim.Buffers; +using Vim.BFastNS; namespace Vim.Format { diff --git a/src/cs/vim/Vim.Format.Core/DocumentBuilder.cs b/src/cs/vim/Vim.Format.Core/DocumentBuilder.cs index c5838b21..50e31e2f 100644 --- a/src/cs/vim/Vim.Format.Core/DocumentBuilder.cs +++ b/src/cs/vim/Vim.Format.Core/DocumentBuilder.cs @@ -3,13 +3,9 @@ using System.Diagnostics; using System.Linq; using Vim.Math3d; -using Vim.BFastNextNS; +using Vim.BFastNS; using System.IO; using Vim.Util; -using Vim.Buffers; -using System.Runtime.InteropServices.ComTypes; -using static Vim.Format.DocumentBuilder; -using Vim.Format.Geometry; namespace Vim.Format { @@ -202,7 +198,7 @@ public void Write(Stream stream) ToBFast().Write(stream); } - public BFastNext ToBFast() + public BFastNS.BFast ToBFast() { var assets = Assets.Select(kv => kv.Value.ToNamedBuffer(kv.Key)) as IEnumerable; Debug.Assert(assets != null, "Asset conversion to IEnumerable failed."); diff --git a/src/cs/vim/Vim.Format.Core/DocumentBuilderExtensions.cs b/src/cs/vim/Vim.Format.Core/DocumentBuilderExtensions.cs index a5bd6f8d..1a374667 100644 --- a/src/cs/vim/Vim.Format.Core/DocumentBuilderExtensions.cs +++ b/src/cs/vim/Vim.Format.Core/DocumentBuilderExtensions.cs @@ -1,11 +1,11 @@ using System.Collections.Generic; using System.Linq; -using Vim.BFastNextNS; +using Vim.BFastNS; using Vim.Format.Geometry; using Vim.G3d; using Vim.LinqArray; using static Vim.Format.DocumentBuilder; -using Vim.Buffers; +using Vim.BFastNS; namespace Vim.Format { diff --git a/src/cs/vim/Vim.Format.Core/DocumentExtensions.cs b/src/cs/vim/Vim.Format.Core/DocumentExtensions.cs index 03ef5c57..23a53fbe 100644 --- a/src/cs/vim/Vim.Format.Core/DocumentExtensions.cs +++ b/src/cs/vim/Vim.Format.Core/DocumentExtensions.cs @@ -1,7 +1,7 @@ using System; using System.Text.RegularExpressions; using Vim.LinqArray; -using Vim.Buffers; +using Vim.BFastNS; namespace Vim.Format { diff --git a/src/cs/vim/Vim.Format.Core/EntityTable.cs b/src/cs/vim/Vim.Format.Core/EntityTable.cs index d209fc69..86b73e01 100644 --- a/src/cs/vim/Vim.Format.Core/EntityTable.cs +++ b/src/cs/vim/Vim.Format.Core/EntityTable.cs @@ -1,7 +1,6 @@ using System; -using System.Diagnostics; -using Vim.Buffers; using Vim.LinqArray; +using Vim.BFastNS; namespace Vim.Format { diff --git a/src/cs/vim/Vim.Format.Core/EntityTableBuilder.cs b/src/cs/vim/Vim.Format.Core/EntityTableBuilder.cs index 20aea3b0..d5b60dd7 100644 --- a/src/cs/vim/Vim.Format.Core/EntityTableBuilder.cs +++ b/src/cs/vim/Vim.Format.Core/EntityTableBuilder.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; -using Vim.Buffers; +using Vim.BFastNS; namespace Vim.Format { diff --git a/src/cs/vim/Vim.Format.Core/G3dBuilder.cs b/src/cs/vim/Vim.Format.Core/G3dBuilder.cs index 2dc19230..4b8ef3fb 100644 --- a/src/cs/vim/Vim.Format.Core/G3dBuilder.cs +++ b/src/cs/vim/Vim.Format.Core/G3dBuilder.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; using System.Linq; using Vim.G3d; -using Vim.BFastNextNS; +using Vim.BFastNS; using static Vim.Format.DocumentBuilder; using Vim.Math3d; @@ -52,9 +52,9 @@ public int[] GetFaceCounts() } - public BFastNext ToBFast() + public BFastNS.BFast ToBFast() { - var bfast = new BFastNext(); + var bfast = new BFastNS.BFast(); var totalSubmeshCount = _meshes.Select(s => s.SubmeshesIndexOffset.Count).Sum(); // Compute the Vertex offsets and index offsets @@ -91,7 +91,7 @@ public BFastNext ToBFast() shapeVertexOffsets[i] = shapeVertexOffsets[i - 1] + _shapes[i - 1].Vertices.Count; } - bfast = new BFastNext(); + bfast = new BFastNS.BFast(); bfast.SetArray("Meta", G3dHeader.Default.ToBytes()); bfast.SetEnumerable(CommonAttributes.Position, () => _meshes.SelectMany(m => m.Vertices)); diff --git a/src/cs/vim/Vim.Format.Core/Geometry/Serialization.cs b/src/cs/vim/Vim.Format.Core/Geometry/Serialization.cs index 8a7f15a0..7619d097 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/Serialization.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/Serialization.cs @@ -11,7 +11,7 @@ public static G3D ToG3d(this IMesh mesh) => mesh is G3D r ? r : mesh.Attributes.ToG3d(); public static void WriteG3d(this IMesh mesh, string filePath) - => mesh.ToG3d().Write(filePath); + => mesh.ToG3d().ToBFast().Write(filePath); public static void WriteObj(this IMesh mesh, string filePath) => mesh.ToG3d().WriteObj(filePath); diff --git a/src/cs/vim/Vim.Format.Core/Geometry/Validation.cs b/src/cs/vim/Vim.Format.Core/Geometry/Validation.cs index cd2625de..e984f61a 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/Validation.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/Validation.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using Vim.G3d; using Vim.LinqArray; -using Vim.Buffers; +using Vim.BFastNS; namespace Vim.Format.Geometry { diff --git a/src/cs/vim/Vim.Format.Core/SerializableDocument.cs b/src/cs/vim/Vim.Format.Core/SerializableDocument.cs index bdda40b2..cfb34ed0 100644 --- a/src/cs/vim/Vim.Format.Core/SerializableDocument.cs +++ b/src/cs/vim/Vim.Format.Core/SerializableDocument.cs @@ -3,10 +3,9 @@ using System.IO; using System.Linq; using System.Text; -using Vim.BFastNextNS; +using Vim.BFastNS; +using Vim.BFastNS.Core; using Vim.G3d; -using Vim.Buffers; -using Vim.BFast.Core; namespace Vim.Format { @@ -48,14 +47,14 @@ public IEnumerable AllColumns .Concat(StringColumns) .Concat(DataColumns); - public static SerializableEntityTable FromBfast(string name, BFastNext bfast) + public static SerializableEntityTable FromBfast(string name, BFastNS.BFast bfast) { return null; } - public BFastNext ToBFast() + public BFastNS.BFast ToBFast() { - var bfast = new BFastNext(); + var bfast = new BFastNS.BFast(); foreach (var col in AllColumns) { bfast.SetArray(col.Name, col.AsArray()); @@ -113,19 +112,19 @@ public class SerializableDocument /// The originating file name (if provided) /// public string FileName; - public BFastNext ToBFast() + public BFastNS.BFast ToBFast() { - var bfast = new BFastNext(); + var bfast = new BFastNS.BFast(); //bfast.SetArray(BufferNames.Header, Header.ToBytes()); - var assets = new BFastNext(); + var assets = new BFastNS.BFast(); foreach (var asset in Assets) { assets.SetArray(asset.Name, asset.ToArray()); } bfast.SetBFast(BufferNames.Assets, assets); - var entities = new BFastNext(); + var entities = new BFastNS.BFast(); foreach (var entity in EntityTables) { entities.SetBFast(entity.Name, entity.ToBFast()); @@ -140,14 +139,14 @@ public static SerializableDocument FromPath(string path, LoadOptions options = n { using (var file = new FileStream(path, FileMode.OpenOrCreate)) { - var bfast = new BFastNext(file); + var bfast = new BFastNS.BFast(file); var doc = FromBFast(bfast); doc.FileName = path; return doc; } } - public static SerializableDocument FromBFast(BFastNext bfast, LoadOptions options = null) + public static SerializableDocument FromBFast(BFastNS.BFast bfast, LoadOptions options = null) { var doc = new SerializableDocument(); doc.Options = options ?? new LoadOptions(); @@ -162,7 +161,7 @@ public static SerializableDocument FromBFast(BFastNext bfast, LoadOptions option if (!doc.Options.SkipGeometry) { - var geo = bfast.GetArray(BufferNames.Geometry); + var geo = bfast.GetBFast(BufferNames.Geometry); doc.Geometry = G3D.Read(geo); } @@ -175,7 +174,7 @@ public static SerializableDocument FromBFast(BFastNext bfast, LoadOptions option /// Enumerates the SerializableEntityTables contained in the given entities buffer. /// private static IEnumerable GetEntityTables( - BFastNext bfast, + BFastNS.BFast bfast, bool schemaOnly) { @@ -193,7 +192,7 @@ private static IEnumerable GetEntityTables( /// Returns a SerializableEntityTable based on the given buffer reader. /// public static SerializableEntityTable ReadEntityTable2( - BFastNext bfast, + BFastNS.BFast bfast, bool schemaOnly ) { diff --git a/src/cs/vim/Vim.Format.Core/SerializableHeader.cs b/src/cs/vim/Vim.Format.Core/SerializableHeader.cs index 4e26382b..c3e6a57d 100644 --- a/src/cs/vim/Vim.Format.Core/SerializableHeader.cs +++ b/src/cs/vim/Vim.Format.Core/SerializableHeader.cs @@ -3,7 +3,7 @@ using System.Globalization; using System.Linq; using System.Text; -using Vim.BFastNextNS; +using Vim.BFastNS; using Vim.Util; namespace Vim.Format diff --git a/src/cs/vim/Vim.Format.Core/Serializer.cs b/src/cs/vim/Vim.Format.Core/Serializer.cs index 864e902e..a63dd565 100644 --- a/src/cs/vim/Vim.Format.Core/Serializer.cs +++ b/src/cs/vim/Vim.Format.Core/Serializer.cs @@ -1,5 +1,5 @@ using System.Text.RegularExpressions; -using Vim.Buffers; +using Vim.BFastNS; namespace Vim.Format { diff --git a/src/cs/vim/Vim.Format.Core/Validation.cs b/src/cs/vim/Vim.Format.Core/Validation.cs index 110ee6e9..a16f9bc4 100644 --- a/src/cs/vim/Vim.Format.Core/Validation.cs +++ b/src/cs/vim/Vim.Format.Core/Validation.cs @@ -1,6 +1,6 @@ using System; using System.Collections.Generic; -using Vim.Buffers; +using Vim.BFastNS; using Vim.G3d; using Vim.LinqArray; diff --git a/src/cs/vim/Vim.Format.Core/Vim.Format.Core.csproj b/src/cs/vim/Vim.Format.Core/Vim.Format.Core.csproj index 544fe3cb..2ab91d8a 100644 --- a/src/cs/vim/Vim.Format.Core/Vim.Format.Core.csproj +++ b/src/cs/vim/Vim.Format.Core/Vim.Format.Core.csproj @@ -7,14 +7,13 @@ - + - diff --git a/src/cs/vim/Vim.Format.Tests/FormatTests.cs b/src/cs/vim/Vim.Format.Tests/FormatTests.cs index 50a1ee38..1cc20934 100644 --- a/src/cs/vim/Vim.Format.Tests/FormatTests.cs +++ b/src/cs/vim/Vim.Format.Tests/FormatTests.cs @@ -1,8 +1,8 @@ using System.Collections.Generic; using System.Linq; using NUnit.Framework; -using Vim.Buffers; using Vim.LinqArray; +using Vim.BFastNS; namespace Vim.Format.Tests { diff --git a/src/cs/vim/Vim.Format.Tests/Geometry/GeometryTests.cs b/src/cs/vim/Vim.Format.Tests/Geometry/GeometryTests.cs index 6cf7f142..62cdac6f 100644 --- a/src/cs/vim/Vim.Format.Tests/Geometry/GeometryTests.cs +++ b/src/cs/vim/Vim.Format.Tests/Geometry/GeometryTests.cs @@ -298,8 +298,8 @@ public static void TriangleSerializationTest() .Add(submeshMaterials.ToIArray().ToSubmeshMaterialAttribute()) .ToG3D(); - var bfastBytes = g3d.WriteToBytes(); - var readG3d = G3D.Read(bfastBytes); + var bfast = g3d.ToBFast(); + var readG3d = G3D.Read(bfast); Assert.IsNotNull(readG3d); var mesh = readG3d.ToIMesh(); diff --git a/src/cs/vim/Vim.Format.Vimx.Conversion/MeshesToScene.cs b/src/cs/vim/Vim.Format.Vimx.Conversion/MeshesToScene.cs index b51ef4e4..db4fb722 100644 --- a/src/cs/vim/Vim.Format.Vimx.Conversion/MeshesToScene.cs +++ b/src/cs/vim/Vim.Format.Vimx.Conversion/MeshesToScene.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; using System.Linq; -using Vim.BFastNextNS; +using Vim.BFastNS; using Vim.Format.ObjectModel; using Vim.G3dNext.Attributes; using Vim.LinqArray; diff --git a/src/cs/vim/Vim.Format.Vimx.Conversion/VimToMeshes.cs b/src/cs/vim/Vim.Format.Vimx.Conversion/VimToMeshes.cs index 69535f61..2f771080 100644 --- a/src/cs/vim/Vim.Format.Vimx.Conversion/VimToMeshes.cs +++ b/src/cs/vim/Vim.Format.Vimx.Conversion/VimToMeshes.cs @@ -2,7 +2,7 @@ using System.Linq; using Vim.LinqArray; using Vim.Util; -using Vim.BFastNextNS; +using Vim.BFastNS; using Vim.Math3d; using Vim.G3dNext.Attributes; diff --git a/src/cs/vim/Vim.Format.Vimx.Conversion/VimxConverter.cs b/src/cs/vim/Vim.Format.Vimx.Conversion/VimxConverter.cs index 697baa74..5e97e25b 100644 --- a/src/cs/vim/Vim.Format.Vimx.Conversion/VimxConverter.cs +++ b/src/cs/vim/Vim.Format.Vimx.Conversion/VimxConverter.cs @@ -1,6 +1,6 @@ using System.Linq; using Vim.LinqArray; -using Vim.BFastNextNS; +using Vim.BFastNS; using Vim.G3dNext.Attributes; using Vim.Format.ObjectModel; using Vim.G3dNext; @@ -30,8 +30,7 @@ public static Vimx FromVim(G3dVim g3d, DocumentModel bim) var chunks = meshes.SplitChunks(); var scene = MeshesToScene.CreateScene(g3d, bim, chunks, meshes); - - var materials = new G3dMaterials(g3d.ToBFast()); + var materials = new G3dMaterials().ReadFromVim(g3d); var header = VimxHeader.CreateDefault(); return new Vimx(header, MetaHeader.Default, scene, materials, chunks); diff --git a/src/cs/vim/Vim.Format.Vimx/Vim.Format.Vimx.csproj b/src/cs/vim/Vim.Format.Vimx/Vim.Format.Vimx.csproj index 7b01d77a..06f4f992 100644 --- a/src/cs/vim/Vim.Format.Vimx/Vim.Format.Vimx.csproj +++ b/src/cs/vim/Vim.Format.Vimx/Vim.Format.Vimx.csproj @@ -9,7 +9,7 @@ - + diff --git a/src/cs/vim/Vim.Format.Vimx/Vimx.cs b/src/cs/vim/Vim.Format.Vimx/Vimx.cs index b622144d..a5155c01 100644 --- a/src/cs/vim/Vim.Format.Vimx/Vimx.cs +++ b/src/cs/vim/Vim.Format.Vimx/Vimx.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; using System.Linq; -using Vim.BFastNextNS; +using Vim.BFastNS; using Vim.G3dNext; using Vim.G3dNext.Attributes; @@ -44,7 +44,7 @@ public Vimx(SerializableHeader header, MetaHeader meta, G3dScene scene, G3dMater Chunks = chunks; } - public Vimx(BFastNext bfast) + public Vimx(BFastNS.BFast bfast) { Header = VimxHeader.FromBytes(bfast.GetArray(BufferNames.Header)); @@ -65,10 +65,10 @@ public Vimx(BFastNext bfast) public static Vimx FromPath(string path) => path.ReadBFast((b) => new Vimx(b)); - public BFastNext ToBFast() + public BFastNS.BFast ToBFast() { AddTransformsToScene(); - var bfast = new BFastNext(); + var bfast = new BFast(); bfast.SetArray(BufferNames.Meta, MetaHeader.Default.ToBytes()); bfast.SetArray(BufferNames.Header, Header.ToVimxBytes()); bfast.SetBFast(BufferNames.Scene, Scene.ToBFast(), BufferCompression.Scene); diff --git a/src/cs/vim/Vim.Format.Vimx/VimxChunk.cs b/src/cs/vim/Vim.Format.Vimx/VimxChunk.cs index f769a791..ffcc73bf 100644 --- a/src/cs/vim/Vim.Format.Vimx/VimxChunk.cs +++ b/src/cs/vim/Vim.Format.Vimx/VimxChunk.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; using System.Linq; -using Vim.BFastNextNS; +using Vim.BFastNS; using Vim.G3dNext.Attributes; namespace Vim.Format.VimxNS @@ -12,16 +12,16 @@ public class VimxChunk public VimxChunk() { } public VimxChunk(List meshes) { Meshes = meshes; } - public VimxChunk(BFastNext bfast) + public VimxChunk(BFastNS.BFast bfast) { Meshes = bfast.Entries .Select(e => new G3dMesh(bfast.GetBFast(e))) .ToList(); } - public BFastNext ToBFast() + public BFastNS.BFast ToBFast() { - var chunk = new BFastNext(); + var chunk = new BFastNS.BFast(); chunk.SetBFast( BufferNames.Mesh, Meshes.Select(m => m.ToBFast()) diff --git a/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs b/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs index b1ae8aaf..adcdcc9b 100644 --- a/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs +++ b/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs @@ -3,7 +3,7 @@ using System.Linq; using System.Reflection; using System.Threading.Tasks; -using Vim.Buffers; +using Vim.BFastNS; using Vim.Format.Geometry; using Vim.Format.ObjectModel; using Vim.Util; diff --git a/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs b/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs index bd324ab1..13001b75 100644 --- a/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs +++ b/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs @@ -10,7 +10,7 @@ using Vim.LinqArray; using Vim.Math3d; using IVimSceneProgress = System.IProgress<(string, double)>; -using Vim.BFastNextNS; +using Vim.BFastNS; namespace Vim { @@ -37,7 +37,7 @@ public static SerializableHeader GetHeader(string path) public static SerializableHeader GetHeader(Stream stream) { - var bfast = new BFastNext(stream); + var bfast = new BFastNS.BFast(stream); var bytes = bfast.GetArray(BufferNames.Header); if (bytes == null) return null; return SerializableHeader.FromBytes(bytes); @@ -50,11 +50,11 @@ public static VimScene LoadVim(string f, IVimSceneProgress progress = null, bool => LoadVim(f, new LoadOptions { SkipGeometry = skipGeometry, SkipAssets = skipAssets}, progress, inParallel); public static VimScene LoadVim(Stream stream, LoadOptions loadOptions, IVimSceneProgress progress = null, bool inParallel = false) - => new VimScene(SerializableDocument.FromBFast(new BFastNext(stream), loadOptions), progress, inParallel); + => new VimScene(SerializableDocument.FromBFast(new BFastNS.BFast(stream), loadOptions), progress, inParallel); public static VimScene LoadVim2(Stream stream, LoadOptions loadOptions = null, IVimSceneProgress progress = null, bool inParallel = false) { - var bfast = new BFastNext(stream); + var bfast = new BFastNS.BFast(stream); var doc = SerializableDocument.FromBFast(bfast, loadOptions); return new VimScene(doc, progress, inParallel); } diff --git a/src/cs/vim/Vim.Vimx.Test/Vim.Format.Vimx.Test.csproj b/src/cs/vim/Vim.Vimx.Test/Vim.Format.Vimx.Test.csproj index 7f74954c..008a1701 100644 --- a/src/cs/vim/Vim.Vimx.Test/Vim.Format.Vimx.Test.csproj +++ b/src/cs/vim/Vim.Vimx.Test/Vim.Format.Vimx.Test.csproj @@ -17,7 +17,7 @@ - + diff --git a/src/cs/vim/Vim.Vimx.Test/VimG3dTests.cs b/src/cs/vim/Vim.Vimx.Test/VimG3dTests.cs index 74485781..51e4b2b0 100644 --- a/src/cs/vim/Vim.Vimx.Test/VimG3dTests.cs +++ b/src/cs/vim/Vim.Vimx.Test/VimG3dTests.cs @@ -1,9 +1,9 @@ using NUnit.Framework; using NUnit.Framework.Internal; -using Vim.BFastNextNS; +using Vim.BFastNS; using Vim.G3dNext.Attributes; using Vim.Math3d; -using Vim.BFastNextNS; +using Vim.BFastNS; namespace Vim.G3dNext.Tests { @@ -43,7 +43,7 @@ public static void Can_Read_Write_Triangle() var memoryStream = new MemoryStream(); g3d1.ToBFast().Write(memoryStream); memoryStream.Seek(0, SeekOrigin.Begin); - var bfast = new BFastNext(memoryStream); + var bfast = new BFastNS.BFast(memoryStream); var g3d2 = new VimAttributeCollection(bfast); Assert.IsNotNull(g3d2); @@ -76,7 +76,7 @@ public static void Can_Ignore_Extra_Attributes() var g3d = G3dVim.FromVim(TestUtils.ResidencePath); g3d.ToBFast().Write(memoryStream); memoryStream.Seek(0, SeekOrigin.Begin); - var bfast = new BFastNext(memoryStream); + var bfast = new BFastNS.BFast(memoryStream); var g3dMats = new G3dMaterials(bfast); Assert.IsNotNull(g3dMats); @@ -115,7 +115,7 @@ public static void Can_Merge_two_g3d() var g3dFilePath = Path.Combine(testDir!, "merged.g3d"); mergedG3d.ToBFast().Write(memoryStream); memoryStream.Seek(0, SeekOrigin.Begin); - var bfast = new BFastNext(memoryStream); + var bfast = new BFastNS.BFast(memoryStream); var g3dResult = new VimAttributeCollection(bfast); diff --git a/src/cs/vim/Vim.Vimx.Test/VimxActions.cs b/src/cs/vim/Vim.Vimx.Test/VimxActions.cs index 11d130bb..fd5c27f6 100644 --- a/src/cs/vim/Vim.Vimx.Test/VimxActions.cs +++ b/src/cs/vim/Vim.Vimx.Test/VimxActions.cs @@ -22,12 +22,11 @@ public static void ConvertVimToVimx() var output = Path.Combine(VimFormatRepoPaths.OutDir, name + ".vimx"); var vimx = VimxConverter.FromVimPath(input); + Console.WriteLine(vimx.Materials.MaterialSmoothness); - Console.WriteLine(vimx.Chunks.SelectMany(c => c.Meshes).Sum(m => m.Indices.Length)); - Console.WriteLine(vimx.Chunks.SelectMany(c => c.Meshes).Sum(m => m.Positions.Length)); - - Console.WriteLine(vimx.Header); vimx.ToBFast().Write(output); + var v = Vimx.FromPath(output); + Console.WriteLine(v.Scene.InstanceTransformData.Length); } } } From 7fb8a552d7ed579e447d6a8d56a2a655d50f4373 Mon Sep 17 00:00:00 2001 From: simon Date: Fri, 8 Dec 2023 14:20:17 -0500 Subject: [PATCH 034/111] removed unlinked files after projects cleanup --- src/cs/Vim.BFast.Core/BFastAlignment.cs | 49 ----- src/cs/Vim.BFast.Core/BFastConstants.cs | 20 -- src/cs/Vim.BFast.Core/BFastHeader.cs | 67 ------- src/cs/Vim.BFast.Core/BFastPreamble.cs | 71 ------- src/cs/Vim.BFast.Core/BFastRange.cs | 44 ----- src/cs/Vim.BFast.Core/BFastReader.cs | 44 ----- src/cs/Vim.BFast.Core/BFastStrings.cs | 46 ----- src/cs/Vim.BFast.Core/BFastWriter.cs | 167 ----------------- src/cs/Vim.BFast.Core/Vim.BFast.Core.csproj | 12 -- src/cs/Vim.Buffers/BufferExtensions.cs | 89 --------- src/cs/Vim.Buffers/Buffers.cs | 77 -------- src/cs/Vim.Buffers/UnsafeHelpers.cs | 175 ------------------ src/cs/Vim.Buffers/Vim.Buffers.csproj | 8 - .../BFastTests.cs | 0 .../Vim.BFast.Tests.csproj | 2 +- .../BFast/BFast.cs | 0 .../BFast/BFastEnumerableNode.cs | 0 .../BFast/BFastNode.cs | 0 .../BFast/IBFastNode.cs | 0 .../Buffers/BufferExtensions.cs | 0 .../Buffers/Buffers.cs | 0 .../Buffers/UnsafeHelpers.cs | 0 .../Core/BFastAlignment.cs | 0 .../Core/BFastConstants.cs | 0 .../Core/BFastHeader.cs | 0 .../Core/BFastPreamble.cs | 0 .../Core/BFastRange.cs | 0 .../Core/BFastReader.cs | 0 .../Core/BFastStrings.cs | 0 .../Core/BFastWriter.cs | 0 .../Vim.BFast.csproj | 0 src/cs/g3d/Vim.G3d/Vim.G3d.csproj | 2 +- .../Vim.G3dNext.Attributes/Attributes.g.cs | 3 - .../Vim.G3dNext.Attributes.csproj | 1 + src/cs/g3d/Vim.G3dNext/Vim.G3dNext.csproj | 2 +- src/cs/vim-format.sln | 4 +- .../Vim.Format.Core/Vim.Format.Core.csproj | 2 +- .../Vim.Format.Vimx/Vim.Format.Vimx.csproj | 2 +- .../Vim.Vimx.Test/Vim.Format.Vimx.Test.csproj | 2 +- src/cs/vim/Vim.Vimx.Test/VimxActions.cs | 4 +- 40 files changed, 11 insertions(+), 882 deletions(-) delete mode 100644 src/cs/Vim.BFast.Core/BFastAlignment.cs delete mode 100644 src/cs/Vim.BFast.Core/BFastConstants.cs delete mode 100644 src/cs/Vim.BFast.Core/BFastHeader.cs delete mode 100644 src/cs/Vim.BFast.Core/BFastPreamble.cs delete mode 100644 src/cs/Vim.BFast.Core/BFastRange.cs delete mode 100644 src/cs/Vim.BFast.Core/BFastReader.cs delete mode 100644 src/cs/Vim.BFast.Core/BFastStrings.cs delete mode 100644 src/cs/Vim.BFast.Core/BFastWriter.cs delete mode 100644 src/cs/Vim.BFast.Core/Vim.BFast.Core.csproj delete mode 100644 src/cs/Vim.Buffers/BufferExtensions.cs delete mode 100644 src/cs/Vim.Buffers/Buffers.cs delete mode 100644 src/cs/Vim.Buffers/UnsafeHelpers.cs delete mode 100644 src/cs/Vim.Buffers/Vim.Buffers.csproj rename src/cs/bfast/{Vim.BFastNext.Tests => Vim.BFast.Tests}/BFastTests.cs (100%) rename src/cs/bfast/{Vim.BFastNext.Tests => Vim.BFast.Tests}/Vim.BFast.Tests.csproj (91%) rename src/cs/bfast/{Vim.BFast.Next => Vim.BFast}/BFast/BFast.cs (100%) rename src/cs/bfast/{Vim.BFast.Next => Vim.BFast}/BFast/BFastEnumerableNode.cs (100%) rename src/cs/bfast/{Vim.BFast.Next => Vim.BFast}/BFast/BFastNode.cs (100%) rename src/cs/bfast/{Vim.BFast.Next => Vim.BFast}/BFast/IBFastNode.cs (100%) rename src/cs/bfast/{Vim.BFast.Next => Vim.BFast}/Buffers/BufferExtensions.cs (100%) rename src/cs/bfast/{Vim.BFast.Next => Vim.BFast}/Buffers/Buffers.cs (100%) rename src/cs/bfast/{Vim.BFast.Next => Vim.BFast}/Buffers/UnsafeHelpers.cs (100%) rename src/cs/bfast/{Vim.BFast.Next => Vim.BFast}/Core/BFastAlignment.cs (100%) rename src/cs/bfast/{Vim.BFast.Next => Vim.BFast}/Core/BFastConstants.cs (100%) rename src/cs/bfast/{Vim.BFast.Next => Vim.BFast}/Core/BFastHeader.cs (100%) rename src/cs/bfast/{Vim.BFast.Next => Vim.BFast}/Core/BFastPreamble.cs (100%) rename src/cs/bfast/{Vim.BFast.Next => Vim.BFast}/Core/BFastRange.cs (100%) rename src/cs/bfast/{Vim.BFast.Next => Vim.BFast}/Core/BFastReader.cs (100%) rename src/cs/bfast/{Vim.BFast.Next => Vim.BFast}/Core/BFastStrings.cs (100%) rename src/cs/bfast/{Vim.BFast.Next => Vim.BFast}/Core/BFastWriter.cs (100%) rename src/cs/bfast/{Vim.BFast.Next => Vim.BFast}/Vim.BFast.csproj (100%) diff --git a/src/cs/Vim.BFast.Core/BFastAlignment.cs b/src/cs/Vim.BFast.Core/BFastAlignment.cs deleted file mode 100644 index 7149e9b1..00000000 --- a/src/cs/Vim.BFast.Core/BFastAlignment.cs +++ /dev/null @@ -1,49 +0,0 @@ -using System; -using System.IO; - -namespace Vim.BFast.Core -{ - internal class BFastAlignment - { - /// - /// Computes the padding requires after the array of BFastRanges are written out. - /// - /// - /// - public static long ComputePadding(BFastRange[] ranges) - => ComputePadding(BFastPreamble.Size + ranges.Length * BFastRange.Size); - - /// - /// Given a position in the stream, computes how much padding is required to bring the value to an aligned point. - /// - public static long ComputePadding(long n) - => ComputeNext(n) - n; - - /// - /// Given a position in the stream, tells us where the the next aligned position will be, if it the current position is not aligned. - /// - public static long ComputeNext(long n) - => IsAligned(n) ? n : n + BFastConstants.ALIGNMENT - (n % BFastConstants.ALIGNMENT); - - /// - /// Checks that the stream (if seekable) is well aligned - /// - public static void Check(Stream stream) - { - if (!stream.CanSeek) - return; - // TODO: Check with CD: Should we bail out here? This means that any - // alignment checks for a currently-writing stream are effectively ignored. - if (stream.Position == stream.Length) - return; - if (!IsAligned(stream.Position)) - throw new Exception($"Stream position {stream.Position} is not well aligned"); - } - - /// - /// Given a position in the stream, tells us whether the position is aligned. - /// - public static bool IsAligned(long n) - => n % BFastConstants.ALIGNMENT == 0; - } -} diff --git a/src/cs/Vim.BFast.Core/BFastConstants.cs b/src/cs/Vim.BFast.Core/BFastConstants.cs deleted file mode 100644 index 431ab07f..00000000 --- a/src/cs/Vim.BFast.Core/BFastConstants.cs +++ /dev/null @@ -1,20 +0,0 @@ -namespace Vim.BFast.Core -{ - /// - /// Constants. - /// - public static class BFastConstants - { - public const long Magic = 0xBFA5; - - // https://en.wikipedia.org/wiki/Endianness - public const long SameEndian = Magic; - public const long SwappedEndian = 0xA5BFL << 48; - - /// - /// Data arrays are aligned to 64 bytes, so that they can be cast directly to AVX-512 registers. - /// This is useful for efficiently working with floating point data. - /// - public const long ALIGNMENT = 64; - } -} diff --git a/src/cs/Vim.BFast.Core/BFastHeader.cs b/src/cs/Vim.BFast.Core/BFastHeader.cs deleted file mode 100644 index 2ffad12e..00000000 --- a/src/cs/Vim.BFast.Core/BFastHeader.cs +++ /dev/null @@ -1,67 +0,0 @@ -using System; -using System.IO; -using System.Linq; - -namespace Vim.BFast.Core -{ - /// - /// This contains the BFAST data loaded or written from disk. - /// - public class BFastHeader - { - public BFastPreamble Preamble = new BFastPreamble(); - public BFastRange[] Ranges; - public string[] Names; - - public override bool Equals(object o) - => o is BFastHeader other && Equals(other); - - public bool Equals(BFastHeader other) - => Preamble.Equals(other.Preamble) && - Ranges.Length == other.Ranges.Length && - Ranges.Zip(other.Ranges, (x, y) => x.Equals(y)).All(x => x) && - Names.Zip(other.Names, (x, y) => x.Equals(y)).All(x => x); - - /// - /// Checks that the header values are sensible, and throws an exception otherwise. - /// - public BFastHeader Validate() - { - var preamble = Preamble.Validate(); - var ranges = Ranges; - var names = Names; - - if (preamble.RangesEnd > preamble.DataStart) - throw new Exception($"Computed arrays ranges end must be less than the start of data {preamble.DataStart}"); - - if (ranges == null) - throw new Exception("Ranges must not be null"); - - var min = preamble.DataStart; - var max = preamble.DataEnd; - - for (var i = 0; i < ranges.Length; ++i) - { - var begin = ranges[i].Begin; - if (!BFastAlignment.IsAligned(begin)) - throw new Exception($"The beginning of the range is not well aligned {begin}"); - var end = ranges[i].End; - if (begin < min || begin > max) - throw new Exception($"Array offset begin {begin} is not in valid span of {min} to {max}"); - if (i > 0) - { - if (begin < ranges[i - 1].End) - throw new Exception($"Array offset begin {begin} is overlapping with previous array {ranges[i - 1].End}"); - } - - if (end < begin || end > max) - throw new Exception($"Array offset end {end} is not in valid span of {begin} to {max}"); - } - - if (names.Length < ranges.Length - 1) - throw new Exception($"Number of buffer names {names.Length} is not one less than the number of ranges {ranges.Length}"); - - return this; - } - } -} diff --git a/src/cs/Vim.BFast.Core/BFastPreamble.cs b/src/cs/Vim.BFast.Core/BFastPreamble.cs deleted file mode 100644 index 30883bc6..00000000 --- a/src/cs/Vim.BFast.Core/BFastPreamble.cs +++ /dev/null @@ -1,71 +0,0 @@ -using System; -using System.Runtime.InteropServices; - -namespace Vim.BFast.Core -{ - /// - /// The header contains a magic number, the begin and end indices of data, and the number of arrays. - /// - [StructLayout(LayoutKind.Explicit, Pack = 8, Size = 32)] - public struct BFastPreamble - { - [FieldOffset(0)] public long Magic; // Either Constants.SameEndian or Constants.SwappedEndian depending on endianess of writer compared to reader. - [FieldOffset(8)] public long DataStart; // <= file size and >= ArrayRangesEnd and >= FileHeader.ByteCount - [FieldOffset(16)] public long DataEnd; // >= DataStart and <= file size - [FieldOffset(24)] public long NumArrays; // number of arrays - - /// - /// This is where the array ranges are finished. - /// Must be less than or equal to DataStart. - /// Must be greater than or equal to FileHeader.ByteCount - /// - public long RangesEnd => Size + NumArrays * 16; - - /// - /// The size of the FileHeader structure - /// - public static long Size = 32; - - /// - /// Returns true if the producer of the BFast file has the same endianness as the current library - /// - public bool SameEndian => Magic == BFastConstants.SameEndian; - - public override bool Equals(object x) - => x is BFastPreamble other && Equals(other); - - public bool Equals(BFastPreamble other) - => Magic == other.Magic && DataStart == other.DataStart && DataEnd == other.DataEnd && NumArrays == other.NumArrays; - - - /// - /// Checks that the header values are sensible, and throws an exception otherwise. - /// - public BFastPreamble Validate() - { - if (Magic != BFastConstants.SameEndian && Magic != BFastConstants.SwappedEndian) - throw new Exception($"Invalid magic number {Magic}"); - - if (DataStart < BFastPreamble.Size) - throw new Exception($"Data start {DataStart} cannot be before the file header size {BFastPreamble.Size}"); - - if (DataStart > DataEnd) - throw new Exception($"Data start {DataStart} cannot be after the data end {DataEnd}"); - - if (!BFastAlignment.IsAligned(DataEnd)) - throw new Exception($"Data end {DataEnd} should be aligned"); - - if (NumArrays < 0) - throw new Exception($"Number of arrays {NumArrays} is not a positive number"); - - if (NumArrays > DataEnd) - throw new Exception($"Number of arrays {NumArrays} can't be more than the total size"); - - if (RangesEnd > DataStart) - throw new Exception($"End of range {RangesEnd} can't be after data-start {DataStart}"); - - return this; - } - - }; -} diff --git a/src/cs/Vim.BFast.Core/BFastRange.cs b/src/cs/Vim.BFast.Core/BFastRange.cs deleted file mode 100644 index 324d6433..00000000 --- a/src/cs/Vim.BFast.Core/BFastRange.cs +++ /dev/null @@ -1,44 +0,0 @@ -using System.IO; -using System.Runtime.InteropServices; - -namespace Vim.BFast.Core -{ - /// - /// This tells us where a particular array begins and ends in relation to the beginning of a file. - /// * Begin must be less than or equal to End. - /// * Begin must be greater than or equal to DataStart - /// * End must be less than or equal to DataEnd - /// - [StructLayout(LayoutKind.Explicit, Pack = 8, Size = 16)] - public struct BFastRange - { - [FieldOffset(0)] public long Begin; - [FieldOffset(8)] public long End; - - public long Count => End - Begin; - public static long Size = 16; - - public override bool Equals(object x) - => x is BFastRange other && Equals(other); - - public bool Equals(BFastRange other) - => Begin == other.Begin && End == other.End; - - public BFastRange OffsetBy(long offset) - => new BFastRange() - { - Begin = Begin + offset, - End = End + offset - }; - } - - public static class BFastRangeExtensions - { - public static BFastRange FullRange(this Stream stream) - => new BFastRange() - { - Begin = 0, - End = stream.Length - }; - } -} diff --git a/src/cs/Vim.BFast.Core/BFastReader.cs b/src/cs/Vim.BFast.Core/BFastReader.cs deleted file mode 100644 index 1a2c95cb..00000000 --- a/src/cs/Vim.BFast.Core/BFastReader.cs +++ /dev/null @@ -1,44 +0,0 @@ -using System; -using System.IO; -using Vim.Buffers; - -namespace Vim.BFast.Core -{ - public static class BFastReader - { - /// - /// Reads the preamble, the ranges, and the names of the rest of the buffers. - /// - public static BFastHeader ReadHeader(Stream stream) - { - var r = new BFastHeader(); - var br = new BinaryReader(stream); - - if (stream.Length - stream.Position < sizeof(long) * 4) - throw new Exception("Stream too short"); - - r.Preamble = new BFastPreamble - { - Magic = br.ReadInt64(), - DataStart = br.ReadInt64(), - DataEnd = br.ReadInt64(), - NumArrays = br.ReadInt64(), - }.Validate(); - - r.Ranges = stream.ReadArray((int)r.Preamble.NumArrays); - - var padding = BFastAlignment.ComputePadding(r.Ranges); - br.ReadBytes((int)padding); - BFastAlignment.Check(br.BaseStream); - - var nameBytes = br.ReadBytes((int)r.Ranges[0].Count); - r.Names = BFastStrings.Unpack(nameBytes); - - padding = BFastAlignment.ComputePadding(r.Ranges[0].End); - br.ReadBytes((int)padding); - BFastAlignment.Check(br.BaseStream); - - return r.Validate(); - } - } -} diff --git a/src/cs/Vim.BFast.Core/BFastStrings.cs b/src/cs/Vim.BFast.Core/BFastStrings.cs deleted file mode 100644 index 401ea12d..00000000 --- a/src/cs/Vim.BFast.Core/BFastStrings.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System.Collections.Generic; -using System.Text; - -namespace Vim.BFast.Core -{ - public static class BFastStrings - { - /// - /// Converts a collection of strings, into a null-separated byte[] array - /// - public static byte[] Pack(IEnumerable strings) - { - var r = new List(); - foreach (var name in strings) - { - var bytes = Encoding.UTF8.GetBytes(name); - r.AddRange(bytes); - r.Add(0); - } - return r.ToArray(); - } - - - /// - /// Converts a byte[] array encoding a collection of strings separate by NULL into an array of string - /// - public static string[] Unpack(byte[] bytes) - { - var r = new List(); - if (bytes.Length == 0) - return r.ToArray(); - var prev = 0; - for (var i = 0; i < bytes.Length; ++i) - { - if (bytes[i] == 0) - { - r.Add(Encoding.UTF8.GetString(bytes, prev, i - prev)); - prev = i + 1; - } - } - if (prev < bytes.Length) - r.Add(Encoding.UTF8.GetString(bytes, prev, bytes.Length - prev)); - return r.ToArray(); - } - } -} diff --git a/src/cs/Vim.BFast.Core/BFastWriter.cs b/src/cs/Vim.BFast.Core/BFastWriter.cs deleted file mode 100644 index 8337a5d0..00000000 --- a/src/cs/Vim.BFast.Core/BFastWriter.cs +++ /dev/null @@ -1,167 +0,0 @@ -using System; -using System.Diagnostics; -using System.IO; -using System.Linq; - -namespace Vim.BFast.Core -{ - public static class BFastWriter - { - /// - /// Callback function allows clients to control writing the data to the output stream - /// - public delegate long BFastWriterFn(Stream writingStream, int bufferIdx, string bufferName, long bytesToWrite); - - /// - /// Enables a user to write a BFAST from an array of names, sizes, and a custom writing function. - /// The function will receive a BinaryWriter, the index of the buffer, and is expected to return the number of bytes written. - /// Simplifies the process of creating custom BinaryWriters, or writing extremely large arrays if necessary. - /// - public static void Write(Stream stream, string[] bufferNames, long[] bufferSizes, BFastWriterFn onBuffer) - { - if (bufferSizes.Any(sz => sz < 0)) - throw new Exception("All buffer sizes must be zero or greater than zero"); - - if (bufferNames.Length != bufferSizes.Length) - throw new Exception($"The number of buffer names {bufferNames.Length} is not equal to the number of buffer sizes {bufferSizes}"); - - var header = CreateHeader(bufferSizes, bufferNames); - Write(stream, header, bufferNames, bufferSizes, onBuffer); - } - - /// - /// Enables a user to write a BFAST from an array of names, sizes, and a custom writing function. - /// This is useful when the header is already computed. - /// - public static void Write(Stream stream, BFastHeader header, string[] bufferNames, long[] bufferSizes, BFastWriterFn onBuffer) - { - WriteHeader(stream, header); - BFastAlignment.Check(stream); - WriteBody(stream, bufferNames, bufferSizes, onBuffer); - } - - /// - /// Must be called after "WriteBFastHeader" - /// Enables a user to write the contents of a BFAST from an array of names, sizes, and a custom writing function. - /// The function will receive a BinaryWriter, the index of the buffer, and is expected to return the number of bytes written. - /// Simplifies the process of creating custom BinaryWriters, or writing extremely large arrays if necessary. - /// - public static void WriteBody(Stream stream, string[] bufferNames, long[] bufferSizes, BFastWriterFn onBuffer) - { - BFastAlignment.Check(stream); - - if (bufferSizes.Any(sz => sz < 0)) - throw new Exception("All buffer sizes must be zero or greater than zero"); - - if (bufferNames.Length != bufferSizes.Length) - throw new Exception($"The number of buffer names {bufferNames.Length} is not equal to the number of buffer sizes {bufferSizes}"); - - // Then passes the binary writer for each buffer: checking that the correct amount of data was written. - for (var i = 0; i < bufferNames.Length; ++i) - { - BFastAlignment.Check(stream); - var nBytes = bufferSizes[i]; - var pos = stream.CanSeek ? stream.Position : 0; - var nWrittenBytes = onBuffer(stream, i, bufferNames[i], nBytes); - if (stream.CanSeek) - { - if (stream.Position - pos != nWrittenBytes) - throw new NotImplementedException($"Buffer:{bufferNames[i]}. Stream movement {stream.Position - pos} does not reflect number of bytes claimed to be written {nWrittenBytes}"); - } - - if (nBytes != nWrittenBytes) - throw new Exception($"Number of bytes written {nWrittenBytes} not equal to expected bytes{nBytes}"); - var padding = BFastAlignment.ComputePadding(nBytes); - for (var j = 0; j < padding; ++j) - stream.WriteByte(0); - BFastAlignment.Check(stream); - } - } - - /// - /// Creates a BFAST structure, without any actual data buffers, from a list of sizes of buffers (not counting the name buffer). - /// Used as an intermediate step to create a BFAST. - /// - public static BFastHeader CreateHeader(long[] bufferSizes, string[] bufferNames) - { - if (bufferNames.Length != bufferSizes.Length) - throw new Exception($"The number of buffer sizes {bufferSizes.Length} is not equal to the number of buffer names {bufferNames.Length}"); - - var header = new BFastHeader - { - Names = bufferNames - }; - header.Preamble.Magic = BFastConstants.Magic; - header.Preamble.NumArrays = bufferSizes.Length + 1; - - // Allocate the data for the ranges - header.Ranges = new BFastRange[header.Preamble.NumArrays]; - header.Preamble.DataStart = BFastAlignment.ComputeNext(header.Preamble.RangesEnd); - - var nameBufferLength = BFastStrings.Pack(bufferNames).LongLength; - var sizes = (new[] { nameBufferLength }).Concat(bufferSizes).ToArray(); - - // Compute the offsets for the data buffers - var curIndex = header.Preamble.DataStart; - var i = 0; - foreach (var size in sizes) - { - curIndex = BFastAlignment.ComputeNext(curIndex); - Debug.Assert(BFastAlignment.IsAligned(curIndex)); - - header.Ranges[i].Begin = curIndex; - curIndex += size; - - header.Ranges[i].End = curIndex; - i++; - } - - // Finish with the header - // Each buffer we contain is padded to ensure the next one - // starts on alignment, so we pad our DataEnd to reflect this reality - header.Preamble.DataEnd = BFastAlignment.ComputeNext(curIndex); - - // Check that everything adds up - return header.Validate(); - } - - - /// - /// Writes the BFAST header and name buffer to stream using the provided BinaryWriter. The BinaryWriter will be properly aligned by padding zeros - /// - public static BinaryWriter WriteHeader(Stream stream, BFastHeader header) - { - if (header.Ranges.Length != header.Names.Length + 1) - throw new Exception($"The number of ranges {header.Ranges.Length} must be equal to one more than the number of names {header.Names.Length}"); - var bw = new BinaryWriter(stream); - bw.Write(header.Preamble.Magic); - bw.Write(header.Preamble.DataStart); - bw.Write(header.Preamble.DataEnd); - bw.Write(header.Preamble.NumArrays); - foreach (var r in header.Ranges) - { - bw.Write(r.Begin); - bw.Write(r.End); - } - WriteZeroBytes(bw, BFastAlignment.ComputePadding(header.Ranges)); - - BFastAlignment.Check(stream); - var nameBuffer = BFastStrings.Pack(header.Names); - bw.Write(nameBuffer); - WriteZeroBytes(bw, BFastAlignment.ComputePadding(nameBuffer.LongLength)); - - BFastAlignment.Check(stream); - return bw; - } - - /// - /// Writes n zero bytes. - /// - public static void WriteZeroBytes(BinaryWriter bw, long n) - { - for (var i = 0L; i < n; ++i) - bw.Write((byte)0); - } - - } -} diff --git a/src/cs/Vim.BFast.Core/Vim.BFast.Core.csproj b/src/cs/Vim.BFast.Core/Vim.BFast.Core.csproj deleted file mode 100644 index aaab3980..00000000 --- a/src/cs/Vim.BFast.Core/Vim.BFast.Core.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - - netstandard2.0 - true - - - - - - - diff --git a/src/cs/Vim.Buffers/BufferExtensions.cs b/src/cs/Vim.Buffers/BufferExtensions.cs deleted file mode 100644 index 5900b83d..00000000 --- a/src/cs/Vim.Buffers/BufferExtensions.cs +++ /dev/null @@ -1,89 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; - -namespace Vim.Buffers -{ - /// - /// Helper functions for working with buffers - /// - public static class BufferExtensions - { - public static Buffer ToBuffer(this T[] xs) where T : unmanaged - => new Buffer(xs); - - public static NamedBuffer ToNamedBuffer(this T[] xs, string name = "") where T : unmanaged - => new NamedBuffer(xs, name); - - public static NamedBuffer ToNamedBuffer(this IBuffer buffer, string name = "") - => new NamedBuffer(buffer, name); - - public static NamedBuffer ToNamedBuffer(this IBuffer xs, string name = "") where T : unmanaged - => new NamedBuffer(xs.GetTypedData(), name); - - public static IEnumerable ToNamedBuffers(this IEnumerable buffers, IEnumerable names = null) - => names == null ? buffers.Select(b => b.ToNamedBuffer("")) : buffers.Zip(names, ToNamedBuffer); - - public static IDictionary ToDictionary(this IEnumerable buffers) - => buffers.ToDictionary(b => b.Name, b => b); - - public static IEnumerable ToNamedBuffers(this IDictionary d) - => d.Select(kv => kv.Value.ToNamedBuffer(kv.Key)); - - public static IEnumerable ToNamedBuffers(this IDictionary d) - => d.Select(kv => kv.Value.ToNamedBuffer(kv.Key)); - - public static Array CopyBytes(this IBuffer src, Array dst, int srcOffset = 0, int destOffset = 0) - { - Buffer.BlockCopy(src.Data, srcOffset, dst, destOffset, (int)src.NumBytes()); - return dst; - } - - public static byte[] ToBytes(this IBuffer src, byte[] dest = null) - => src.ToArray(dest); - - public static byte[] ToBytes(this T[] xs, byte[] dest = null) where T : unmanaged - => xs.RecastArray(dest); - - public static byte[] ToBytes(this T x) where T : unmanaged - => ToBytes(new[] { x }); - - /// - /// Accepts an array of the given type, or creates one if necessary, copy the buffer data into it - /// - public static unsafe T[] ToArray(this IBuffer buffer, T[] dest = null) where T : unmanaged - => (T[])buffer.CopyBytes(dest ?? new T[buffer.NumBytes() / sizeof(T)]); - - /// - /// Returns the array in the buffer, if it is of the correct type, or creates a new array of the create type and copies - /// bytes into it, as necessary. - /// - public static unsafe T[] AsArray(this IBuffer buffer) where T : unmanaged - => buffer.Data is T[] r ? r : buffer.ToArray(); - - /// - /// Copies an array of unmanaged types into another array of unmanaged types - /// - public static unsafe U[] RecastArray(this T[] src, U[] r = null) where T : unmanaged where U : unmanaged - => src.ToBuffer().ToArray(r); - - public static int NumElements(this IBuffer buffer) - => buffer.Data.Length; - - public static long NumBytes(this IBuffer buffer) - => (long)buffer.NumElements() * buffer.ElementSize; - - public static Buffer ReadBufferFromNumberOfBytes(this Stream stream, long numBytes) where T : unmanaged - => stream.ReadArrayFromNumberOfBytes(numBytes).ToBuffer(); - - public static Buffer ReadBuffer(this Stream stream, int numElements) where T : unmanaged - => stream.ReadArray(numElements).ToBuffer(); - - public static Buffer ReadBuffer(this Stream stream, int numBytes) - => stream.ReadBuffer(numBytes); - - public static void Write(this Stream stream, IBuffer buffer) - => buffer.Write(stream); - } -} diff --git a/src/cs/Vim.Buffers/Buffers.cs b/src/cs/Vim.Buffers/Buffers.cs deleted file mode 100644 index 66420de7..00000000 --- a/src/cs/Vim.Buffers/Buffers.cs +++ /dev/null @@ -1,77 +0,0 @@ -using System; -using System.IO; - -namespace Vim.Buffers -{ - /// - /// Provides an interface to an object that manages a potentially large array of elements all of the same unmanaged type. - /// - public interface IBuffer - { - Array Data { get; } - int ElementSize { get; } - void Write(Stream stream); - } - - /// - /// A version of the IBuffer interface when the element types are known - /// - public interface IBuffer : IBuffer - { - T[] GetTypedData(); - } - - /// - /// Represents a buffer associated with a string name. - /// - public interface INamedBuffer : IBuffer - { - string Name { get; } - } - - /// - /// A version of the INamedBuffer interface when the element types are known - /// - public interface INamedBuffer : INamedBuffer, IBuffer - { - } - - /// - /// A concrete implementation of IBuffer - /// - public unsafe class Buffer : IBuffer where T : unmanaged - { - public Buffer(T[] data) => Data = data; - public int ElementSize => sizeof(T); - public Array Data { get; } - public T[] GetTypedData() => Data as T[]; - public void Write(Stream stream) => stream.Write(GetTypedData()); - } - - /// - /// A concrete implementation of INamedBuffer - /// - public class NamedBuffer : INamedBuffer - { - public NamedBuffer(IBuffer buffer, string name) => (Buffer, Name) = (buffer, name); - public IBuffer Buffer { get; } - public string Name { get; } - public int ElementSize => Buffer.ElementSize; - public Array Data => Buffer.Data; - public void Write(Stream stream) => Buffer.Write(stream); - } - - /// - /// A concrete implementation of INamedBuffer with a specific type. - /// - public class NamedBuffer : INamedBuffer where T : unmanaged - { - public NamedBuffer(T[] data, string name) => (Array, Name) = (data, name); - public string Name { get; } - public unsafe int ElementSize => sizeof(T); - public readonly T[] Array; - public Array Data => Array; - public T[] GetTypedData() => Array; - public void Write(Stream stream) => stream.Write(Array); - } -} diff --git a/src/cs/Vim.Buffers/UnsafeHelpers.cs b/src/cs/Vim.Buffers/UnsafeHelpers.cs deleted file mode 100644 index df3db198..00000000 --- a/src/cs/Vim.Buffers/UnsafeHelpers.cs +++ /dev/null @@ -1,175 +0,0 @@ -using System; -using System.IO; - -namespace Vim.Buffers -{ - /// - /// This class would benefit from being in a generic utilities class, however, having it here allows BFAST to be a standalone without dependencies. - /// - public static class UnsafeHelpers - { - /// - /// Helper for reading arbitrary unmanaged types from a Stream. - /// - public static unsafe void ReadBytesBuffered(this Stream stream, byte* dest, long count, int bufferSize = 4096) - { - var buffer = new byte[bufferSize]; - int bytesRead; - fixed (byte* pBuffer = buffer) - { - while ((bytesRead = stream.Read(buffer, 0, (int)Math.Min(buffer.Length, count))) > 0) - { - if (dest != null) - Buffer.MemoryCopy(pBuffer, dest, count, bytesRead); - count -= bytesRead; - dest += bytesRead; - } - } - } - - /// - /// Helper for writing arbitrary large numbers of bytes - /// - public static unsafe void WriteBytesBuffered(this Stream stream, byte* src, long count, int bufferSize = 4096) - { - var buffer = new byte[bufferSize]; - fixed (byte* pBuffer = buffer) - { - while (count > 0) - { - var toWrite = (int)Math.Min(count, buffer.Length); - Buffer.MemoryCopy(src, pBuffer, buffer.Length, toWrite); - stream.Write(buffer, 0, toWrite); - count -= toWrite; - src += toWrite; - } - } - } - - /// - /// Helper for reading arbitrary unmanaged types from a Stream. - /// - public static unsafe void Read(this Stream stream, T* dest) where T : unmanaged - => stream.ReadBytesBuffered((byte*)dest, sizeof(T)); - - /// - /// Helper for reading arrays of arbitrary unmanaged types from a Stream, that might be over 2GB of size. - /// That said, in C#, you can never load more int.MaxValue numbers of items. - /// NOTE: Arrays are still limited to 2gb in size unless gcAllowVeryLargeObjects is set to true - /// in the runtime environment. - /// https://docs.microsoft.com/en-us/dotnet/api/system.array?redirectedfrom=MSDN&view=netframework-4.7.2#remarks - /// Alternatively, we could convert to .Net Core - /// - public static unsafe T[] ReadArray(this Stream stream, int count) where T : unmanaged - { - var r = new T[count]; - fixed (T* pDest = r) - { - - var pBytes = (byte*)pDest; - stream.ReadBytesBuffered(pBytes, (long)count * sizeof(T)); - } - return r; - } - - public static unsafe void ReadArray(this Stream stream, T[] array, int count) where T : unmanaged - { - fixed (T* pDest = array) - { - var pBytes = (byte*)pDest; - stream.ReadBytesBuffered(pBytes, (long)count * sizeof(T)); - } - } - - - /// - /// Equivalent to ReadArray to use when you know the byte count instead of element count. - /// - public static unsafe T[] ReadArrayBytes(this Stream stream, int byteLength) where T : unmanaged - { - return ReadArray(stream, byteLength / sizeof(T)); - } - - /* - public static unsafe T[] ConvertByteArrayToTypeArray(byte[] byteArray) where T : unmanaged - { - if (byteArray.Length % sizeof(T) != 0) - { - throw new ArgumentException("Byte array length is not a multiple of the size of the target type."); - } - - var elementCount = byteArray.Length / sizeof(T); - var resultArray = new T[elementCount]; - - fixed (byte* bytePtr = byteArray) - { - byte* currentBytePtr = bytePtr; - fixed (T* resultPtr = resultArray) - { - var currentResultPtr = resultPtr; - for (var i = 0; i < elementCount; i++) - { - *currentResultPtr = *((T*)currentBytePtr); - currentBytePtr += sizeof(T); - currentResultPtr++; - } - } - } - - return resultArray; - } - - */ - /// - /// A wrapper for stream.Seek(numBytes, SeekOrigin.Current) to avoid allocating memory for unrecognized buffers. - /// - public static void SkipBytes(this Stream stream, long numBytes) - => stream.Seek(numBytes, SeekOrigin.Current); - - /// - /// Helper for reading arrays of arbitrary unmanaged types from a Stream, that might be over 2GB of size. - /// That said, in C#, you can never load more int.MaxValue numbers of items. - /// - public static unsafe T[] ReadArrayFromNumberOfBytes(this Stream stream, long numBytes) where T : unmanaged - { - var count = numBytes / sizeof(T); - if (numBytes % sizeof(T) != 0) - throw new Exception($"The number of bytes {numBytes} is not divisible by the size of the type {sizeof(T)}"); - if (count >= int.MaxValue) - throw new Exception($"{count} exceeds the maximum number of items that can be read into an array {int.MaxValue}"); - return stream.ReadArray((int)count); - } - - /// - /// Helper for writing arbitrary unmanaged types - /// - public static unsafe void WriteValue(this Stream stream, T x) where T : unmanaged - { - var p = &x; - stream.WriteBytesBuffered((byte*)p, sizeof(T)); - } - - - /// - /// Helper for writing arrays of unmanaged types - /// - public static unsafe void Write(this Stream stream, T[] xs) where T : unmanaged - { - fixed (T* p = xs) - { - stream.WriteBytesBuffered((byte*)p, xs.LongLength * sizeof(T)); - } - } - - /// - /// Helper for writing arrays of unmanaged types - /// - public static unsafe void Write(this Stream stream, T[] xs, long count) where T : unmanaged - { - fixed (T* p = xs) - { - stream.WriteBytesBuffered((byte*)p, count * sizeof(T)); - } - } - } -} diff --git a/src/cs/Vim.Buffers/Vim.Buffers.csproj b/src/cs/Vim.Buffers/Vim.Buffers.csproj deleted file mode 100644 index 2e68195f..00000000 --- a/src/cs/Vim.Buffers/Vim.Buffers.csproj +++ /dev/null @@ -1,8 +0,0 @@ - - - - netstandard2.0 - true - - - diff --git a/src/cs/bfast/Vim.BFastNext.Tests/BFastTests.cs b/src/cs/bfast/Vim.BFast.Tests/BFastTests.cs similarity index 100% rename from src/cs/bfast/Vim.BFastNext.Tests/BFastTests.cs rename to src/cs/bfast/Vim.BFast.Tests/BFastTests.cs diff --git a/src/cs/bfast/Vim.BFastNext.Tests/Vim.BFast.Tests.csproj b/src/cs/bfast/Vim.BFast.Tests/Vim.BFast.Tests.csproj similarity index 91% rename from src/cs/bfast/Vim.BFastNext.Tests/Vim.BFast.Tests.csproj rename to src/cs/bfast/Vim.BFast.Tests/Vim.BFast.Tests.csproj index 43889a65..2179c1db 100644 --- a/src/cs/bfast/Vim.BFastNext.Tests/Vim.BFast.Tests.csproj +++ b/src/cs/bfast/Vim.BFast.Tests/Vim.BFast.Tests.csproj @@ -19,7 +19,7 @@ - + diff --git a/src/cs/bfast/Vim.BFast.Next/BFast/BFast.cs b/src/cs/bfast/Vim.BFast/BFast/BFast.cs similarity index 100% rename from src/cs/bfast/Vim.BFast.Next/BFast/BFast.cs rename to src/cs/bfast/Vim.BFast/BFast/BFast.cs diff --git a/src/cs/bfast/Vim.BFast.Next/BFast/BFastEnumerableNode.cs b/src/cs/bfast/Vim.BFast/BFast/BFastEnumerableNode.cs similarity index 100% rename from src/cs/bfast/Vim.BFast.Next/BFast/BFastEnumerableNode.cs rename to src/cs/bfast/Vim.BFast/BFast/BFastEnumerableNode.cs diff --git a/src/cs/bfast/Vim.BFast.Next/BFast/BFastNode.cs b/src/cs/bfast/Vim.BFast/BFast/BFastNode.cs similarity index 100% rename from src/cs/bfast/Vim.BFast.Next/BFast/BFastNode.cs rename to src/cs/bfast/Vim.BFast/BFast/BFastNode.cs diff --git a/src/cs/bfast/Vim.BFast.Next/BFast/IBFastNode.cs b/src/cs/bfast/Vim.BFast/BFast/IBFastNode.cs similarity index 100% rename from src/cs/bfast/Vim.BFast.Next/BFast/IBFastNode.cs rename to src/cs/bfast/Vim.BFast/BFast/IBFastNode.cs diff --git a/src/cs/bfast/Vim.BFast.Next/Buffers/BufferExtensions.cs b/src/cs/bfast/Vim.BFast/Buffers/BufferExtensions.cs similarity index 100% rename from src/cs/bfast/Vim.BFast.Next/Buffers/BufferExtensions.cs rename to src/cs/bfast/Vim.BFast/Buffers/BufferExtensions.cs diff --git a/src/cs/bfast/Vim.BFast.Next/Buffers/Buffers.cs b/src/cs/bfast/Vim.BFast/Buffers/Buffers.cs similarity index 100% rename from src/cs/bfast/Vim.BFast.Next/Buffers/Buffers.cs rename to src/cs/bfast/Vim.BFast/Buffers/Buffers.cs diff --git a/src/cs/bfast/Vim.BFast.Next/Buffers/UnsafeHelpers.cs b/src/cs/bfast/Vim.BFast/Buffers/UnsafeHelpers.cs similarity index 100% rename from src/cs/bfast/Vim.BFast.Next/Buffers/UnsafeHelpers.cs rename to src/cs/bfast/Vim.BFast/Buffers/UnsafeHelpers.cs diff --git a/src/cs/bfast/Vim.BFast.Next/Core/BFastAlignment.cs b/src/cs/bfast/Vim.BFast/Core/BFastAlignment.cs similarity index 100% rename from src/cs/bfast/Vim.BFast.Next/Core/BFastAlignment.cs rename to src/cs/bfast/Vim.BFast/Core/BFastAlignment.cs diff --git a/src/cs/bfast/Vim.BFast.Next/Core/BFastConstants.cs b/src/cs/bfast/Vim.BFast/Core/BFastConstants.cs similarity index 100% rename from src/cs/bfast/Vim.BFast.Next/Core/BFastConstants.cs rename to src/cs/bfast/Vim.BFast/Core/BFastConstants.cs diff --git a/src/cs/bfast/Vim.BFast.Next/Core/BFastHeader.cs b/src/cs/bfast/Vim.BFast/Core/BFastHeader.cs similarity index 100% rename from src/cs/bfast/Vim.BFast.Next/Core/BFastHeader.cs rename to src/cs/bfast/Vim.BFast/Core/BFastHeader.cs diff --git a/src/cs/bfast/Vim.BFast.Next/Core/BFastPreamble.cs b/src/cs/bfast/Vim.BFast/Core/BFastPreamble.cs similarity index 100% rename from src/cs/bfast/Vim.BFast.Next/Core/BFastPreamble.cs rename to src/cs/bfast/Vim.BFast/Core/BFastPreamble.cs diff --git a/src/cs/bfast/Vim.BFast.Next/Core/BFastRange.cs b/src/cs/bfast/Vim.BFast/Core/BFastRange.cs similarity index 100% rename from src/cs/bfast/Vim.BFast.Next/Core/BFastRange.cs rename to src/cs/bfast/Vim.BFast/Core/BFastRange.cs diff --git a/src/cs/bfast/Vim.BFast.Next/Core/BFastReader.cs b/src/cs/bfast/Vim.BFast/Core/BFastReader.cs similarity index 100% rename from src/cs/bfast/Vim.BFast.Next/Core/BFastReader.cs rename to src/cs/bfast/Vim.BFast/Core/BFastReader.cs diff --git a/src/cs/bfast/Vim.BFast.Next/Core/BFastStrings.cs b/src/cs/bfast/Vim.BFast/Core/BFastStrings.cs similarity index 100% rename from src/cs/bfast/Vim.BFast.Next/Core/BFastStrings.cs rename to src/cs/bfast/Vim.BFast/Core/BFastStrings.cs diff --git a/src/cs/bfast/Vim.BFast.Next/Core/BFastWriter.cs b/src/cs/bfast/Vim.BFast/Core/BFastWriter.cs similarity index 100% rename from src/cs/bfast/Vim.BFast.Next/Core/BFastWriter.cs rename to src/cs/bfast/Vim.BFast/Core/BFastWriter.cs diff --git a/src/cs/bfast/Vim.BFast.Next/Vim.BFast.csproj b/src/cs/bfast/Vim.BFast/Vim.BFast.csproj similarity index 100% rename from src/cs/bfast/Vim.BFast.Next/Vim.BFast.csproj rename to src/cs/bfast/Vim.BFast/Vim.BFast.csproj diff --git a/src/cs/g3d/Vim.G3d/Vim.G3d.csproj b/src/cs/g3d/Vim.G3d/Vim.G3d.csproj index dce2f4f2..ead77bb8 100644 --- a/src/cs/g3d/Vim.G3d/Vim.G3d.csproj +++ b/src/cs/g3d/Vim.G3d/Vim.G3d.csproj @@ -48,7 +48,7 @@ It can be easily and efficiently deserialized and rendered in different language - + diff --git a/src/cs/g3d/Vim.G3dNext.Attributes/Attributes.g.cs b/src/cs/g3d/Vim.G3dNext.Attributes/Attributes.g.cs index 524d6a47..5822acfe 100644 --- a/src/cs/g3d/Vim.G3dNext.Attributes/Attributes.g.cs +++ b/src/cs/g3d/Vim.G3dNext.Attributes/Attributes.g.cs @@ -2089,9 +2089,6 @@ public void ReadAttributes(BFast bfast) } } - - - public IDictionary Map { get; } = new Dictionary { diff --git a/src/cs/g3d/Vim.G3dNext.Attributes/Vim.G3dNext.Attributes.csproj b/src/cs/g3d/Vim.G3dNext.Attributes/Vim.G3dNext.Attributes.csproj index 0efd3be5..b842cea6 100644 --- a/src/cs/g3d/Vim.G3dNext.Attributes/Vim.G3dNext.Attributes.csproj +++ b/src/cs/g3d/Vim.G3dNext.Attributes/Vim.G3dNext.Attributes.csproj @@ -8,6 +8,7 @@ + diff --git a/src/cs/g3d/Vim.G3dNext/Vim.G3dNext.csproj b/src/cs/g3d/Vim.G3dNext/Vim.G3dNext.csproj index 512e8bba..b312cc13 100644 --- a/src/cs/g3d/Vim.G3dNext/Vim.G3dNext.csproj +++ b/src/cs/g3d/Vim.G3dNext/Vim.G3dNext.csproj @@ -9,7 +9,7 @@ - + diff --git a/src/cs/vim-format.sln b/src/cs/vim-format.sln index e63cfde9..5676f7be 100644 --- a/src/cs/vim-format.sln +++ b/src/cs/vim-format.sln @@ -53,9 +53,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vim.Format.Vimx", "vim\Vim. EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vim.Format.Vimx.Test", "vim\Vim.Vimx.Test\Vim.Format.Vimx.Test.csproj", "{BBF94CBD-CD39-49F5-979A-5C9E52C29330}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vim.BFast", "bfast\Vim.BFast.Next\Vim.BFast.csproj", "{408884EA-3CE5-4A34-97F6-1F2D64A0E745}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vim.BFast", "bfast\Vim.BFast\Vim.BFast.csproj", "{408884EA-3CE5-4A34-97F6-1F2D64A0E745}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vim.BFast.Tests", "bfast\Vim.BFastNext.Tests\Vim.BFast.Tests.csproj", "{FD149D64-5905-4F7D-97A8-9F7DA18A257D}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vim.BFast.Tests", "bfast\Vim.BFast.Tests\Vim.BFast.Tests.csproj", "{FD149D64-5905-4F7D-97A8-9F7DA18A257D}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vim.Format.Vimx.Conversion", "vim\Vim.Format.Vimx.Conversion\Vim.Format.Vimx.Conversion.csproj", "{4C4F9826-0DEF-4A39-BFC8-A834522694A0}" EndProject diff --git a/src/cs/vim/Vim.Format.Core/Vim.Format.Core.csproj b/src/cs/vim/Vim.Format.Core/Vim.Format.Core.csproj index 2ab91d8a..a7b621ed 100644 --- a/src/cs/vim/Vim.Format.Core/Vim.Format.Core.csproj +++ b/src/cs/vim/Vim.Format.Core/Vim.Format.Core.csproj @@ -7,7 +7,7 @@ - + diff --git a/src/cs/vim/Vim.Format.Vimx/Vim.Format.Vimx.csproj b/src/cs/vim/Vim.Format.Vimx/Vim.Format.Vimx.csproj index 06f4f992..fcb35ccc 100644 --- a/src/cs/vim/Vim.Format.Vimx/Vim.Format.Vimx.csproj +++ b/src/cs/vim/Vim.Format.Vimx/Vim.Format.Vimx.csproj @@ -9,7 +9,7 @@ - + diff --git a/src/cs/vim/Vim.Vimx.Test/Vim.Format.Vimx.Test.csproj b/src/cs/vim/Vim.Vimx.Test/Vim.Format.Vimx.Test.csproj index 008a1701..ff2ffb1c 100644 --- a/src/cs/vim/Vim.Vimx.Test/Vim.Format.Vimx.Test.csproj +++ b/src/cs/vim/Vim.Vimx.Test/Vim.Format.Vimx.Test.csproj @@ -17,7 +17,7 @@ - + diff --git a/src/cs/vim/Vim.Vimx.Test/VimxActions.cs b/src/cs/vim/Vim.Vimx.Test/VimxActions.cs index fd5c27f6..cede562f 100644 --- a/src/cs/vim/Vim.Vimx.Test/VimxActions.cs +++ b/src/cs/vim/Vim.Vimx.Test/VimxActions.cs @@ -15,8 +15,8 @@ public static class VimxActions public static void ConvertVimToVimx() { // var input = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); - // var input = Path.Join(VimFormatRepoPaths.DataDir, residence); - var input = Path.Join(VimFormatRepoPaths.DataDir, "nbk.vim"); + var input = Path.Join(VimFormatRepoPaths.DataDir, residence); + //var input = Path.Join(VimFormatRepoPaths.DataDir, "nbk.vim"); var name = Path.GetFileNameWithoutExtension(input); var output = Path.Combine(VimFormatRepoPaths.OutDir, name + ".vimx"); From 220c3102cfc45270d21602edf00d42997dbe7073 Mon Sep 17 00:00:00 2001 From: simon Date: Mon, 11 Dec 2023 15:42:36 -0500 Subject: [PATCH 035/111] removed serializer file. Removed bfastns prefix --- src/cs/g3d/Vim.G3d/G3D.cs | 4 +- src/cs/g3d/Vim.G3d/G3dSerialization.cs | 4 +- src/cs/g3d/Vim.G3d/GeometryAttribute.cs | 8 +- src/cs/g3d/Vim.G3dNext/IAttribute.cs | 4 +- .../g3d/Vim.G3dNext/IAttributeCollection.cs | 4 +- .../ColumnExtensions.Buffer.cs | 11 ++- src/cs/vim/Vim.Format.Core/DocumentBuilder.cs | 2 +- src/cs/vim/Vim.Format.Core/G3dBuilder.cs | 6 +- .../Vim.Format.Core/SerializableDocument.cs | 79 +++---------------- .../SerializableEntityTable.cs | 69 ++++++++++++++++ src/cs/vim/Vim.Format.Core/Serializer.cs | 23 ------ src/cs/vim/Vim.Format.Vimx/Vimx.cs | 4 +- src/cs/vim/Vim.Format.Vimx/VimxChunk.cs | 6 +- .../vim/Vim.Format/SceneBuilder/VimScene.cs | 6 +- src/cs/vim/Vim.Vimx.Test/VimG3dTests.cs | 6 +- 15 files changed, 113 insertions(+), 123 deletions(-) create mode 100644 src/cs/vim/Vim.Format.Core/SerializableEntityTable.cs delete mode 100644 src/cs/vim/Vim.Format.Core/Serializer.cs diff --git a/src/cs/g3d/Vim.G3d/G3D.cs b/src/cs/g3d/Vim.G3d/G3D.cs index 085c988e..ac63b84d 100644 --- a/src/cs/g3d/Vim.G3d/G3D.cs +++ b/src/cs/g3d/Vim.G3d/G3D.cs @@ -294,13 +294,13 @@ public static G3D Read(string filePath) { using (var stream = File.OpenRead(filePath)) { - var bfast = new BFastNS.BFast(stream); + var bfast = new BFast(stream); return Read(bfast); } } - public static G3D Read(BFastNS.BFast bfast) + public static G3D Read(BFast bfast) { var header = G3dHeader.FromBytesOrDefault(bfast.GetArray("meta")); var attributes = new List(); diff --git a/src/cs/g3d/Vim.G3d/G3dSerialization.cs b/src/cs/g3d/Vim.G3d/G3dSerialization.cs index 6369dcb2..a8cadb6e 100644 --- a/src/cs/g3d/Vim.G3d/G3dSerialization.cs +++ b/src/cs/g3d/Vim.G3d/G3dSerialization.cs @@ -18,9 +18,9 @@ public static void WriteAttribute(Stream stream, GeometryAttribute attribute, st stream.Write(buffer); } - public static BFastNS.BFast ToBFast(this IGeometryAttributes self, G3dHeader? header = null) + public static BFast ToBFast(this IGeometryAttributes self, G3dHeader? header = null) { - var bfast = new BFastNS.BFast(); + var bfast = new BFast(); bfast.SetArray("meta", (header ?? G3dHeader.Default).ToBytes()); foreach(var attribute in self.Attributes.ToEnumerable()) { diff --git a/src/cs/g3d/Vim.G3d/GeometryAttribute.cs b/src/cs/g3d/Vim.G3d/GeometryAttribute.cs index 6f916076..dc0ce989 100644 --- a/src/cs/g3d/Vim.G3d/GeometryAttribute.cs +++ b/src/cs/g3d/Vim.G3d/GeometryAttribute.cs @@ -88,9 +88,9 @@ public GeometryAttribute AsType() where T : unmanaged /// /// Loads the correct typed data from a BFastNext. /// - public abstract GeometryAttribute Read(BFastNS.BFast bfast); + public abstract GeometryAttribute Read(BFast bfast); - public abstract void AddTo(BFastNS.BFast bfast); + public abstract void AddTo(BFast bfast); /// /// Creates a new GeometryAttribute with the same data, but with a different index. Useful when constructing attributes @@ -227,13 +227,13 @@ public override GeometryAttribute Read(Stream stream, long byteCount) return new GeometryAttribute(data.ToIArray(), Descriptor); } - public override GeometryAttribute Read(BFastNS.BFast bfast) + public override GeometryAttribute Read(BFast bfast) { var array = bfast.GetArray(Name); return new GeometryAttribute(array.ToIArray(), Descriptor); } - public override void AddTo(BFastNS.BFast bfast) + public override void AddTo(BFast bfast) { bfast.SetArray(Name, Data.ToArray()); } diff --git a/src/cs/g3d/Vim.G3dNext/IAttribute.cs b/src/cs/g3d/Vim.G3dNext/IAttribute.cs index 9c180620..a2d280ef 100644 --- a/src/cs/g3d/Vim.G3dNext/IAttribute.cs +++ b/src/cs/g3d/Vim.G3dNext/IAttribute.cs @@ -14,8 +14,8 @@ public interface IAttribute Type IndexInto { get; } Array Data { get; } void Write(Stream stream); - void AddTo(BFastNS.BFast bfast); - void ReadBFast(BFastNS.BFast bfast); + void AddTo(BFast bfast); + void ReadBFast(BFast bfast); } public interface IAttribute : IAttribute diff --git a/src/cs/g3d/Vim.G3dNext/IAttributeCollection.cs b/src/cs/g3d/Vim.G3dNext/IAttributeCollection.cs index e2efe32e..2cf120dc 100644 --- a/src/cs/g3d/Vim.G3dNext/IAttributeCollection.cs +++ b/src/cs/g3d/Vim.G3dNext/IAttributeCollection.cs @@ -58,13 +58,13 @@ public static long GetSize(this IAttributeCollection attributeCollection) => attributeCollection.Map.Values .Sum(a => a.GetSizeInBytes()); - public static BFastNS.BFast ToBFast(this IAttributeCollection attributeCollection) + public static BFast ToBFast(this IAttributeCollection attributeCollection) { var attributes = attributeCollection.Map.Values .OrderBy(n => n.Name) .ToArray(); // Order the attributes by name for consistency - var bfast = new BFastNS.BFast(); + var bfast = new BFast(); foreach (var a in attributes) { a.AddTo(bfast); diff --git a/src/cs/vim/Vim.Format.Core/ColumnExtensions.Buffer.cs b/src/cs/vim/Vim.Format.Core/ColumnExtensions.Buffer.cs index 34c7fc20..ecd6f52a 100644 --- a/src/cs/vim/Vim.Format.Core/ColumnExtensions.Buffer.cs +++ b/src/cs/vim/Vim.Format.Core/ColumnExtensions.Buffer.cs @@ -35,11 +35,11 @@ public static SerializableEntityTable ValidateColumnRowsAreAligned(this Serializ public static string ValidateCanConcatBuffers(this INamedBuffer thisBuffer, INamedBuffer otherBuffer) { - var thisPrefix = thisBuffer.GetTypePrefix(); + var thisPrefix = SerializableEntityTable.GetTypeFromName(thisBuffer.Name); if (string.IsNullOrEmpty(thisPrefix)) throw new Exception("NamedBuffer prefix not found"); - var otherPrefix = otherBuffer.GetTypePrefix(); + var otherPrefix = SerializableEntityTable.GetTypeFromName(otherBuffer.Name); if (string.IsNullOrEmpty(otherPrefix)) throw new Exception("NamedBuffer prefix not found"); @@ -77,7 +77,10 @@ public static object GetDataColumnValue(this IBuffer dataColumn, string typePref } public static object GetDataColumnValue(this INamedBuffer dataColumn, int rowIndex) - => dataColumn.GetDataColumnValue(dataColumn.GetTypePrefix(), rowIndex); + { + var prefix = SerializableEntityTable.GetTypeFromName(dataColumn.Name); + return dataColumn.GetDataColumnValue(prefix, rowIndex); + } public static IBuffer CreateDefaultDataColumnBuffer(int length, string typePrefix) { @@ -119,7 +122,7 @@ public static IBuffer CopyDataColumn(this IBuffer dataColumn, string typePrefix, public static INamedBuffer CopyDataColumn(this INamedBuffer dataColumn, List remapping = null) { - var typePrefix = dataColumn.GetTypePrefix(); + var typePrefix = SerializableEntityTable.GetTypeFromName(dataColumn.Name); return new NamedBuffer(dataColumn.CopyDataColumn(typePrefix, remapping), dataColumn.Name); } diff --git a/src/cs/vim/Vim.Format.Core/DocumentBuilder.cs b/src/cs/vim/Vim.Format.Core/DocumentBuilder.cs index 50e31e2f..371c41e9 100644 --- a/src/cs/vim/Vim.Format.Core/DocumentBuilder.cs +++ b/src/cs/vim/Vim.Format.Core/DocumentBuilder.cs @@ -198,7 +198,7 @@ public void Write(Stream stream) ToBFast().Write(stream); } - public BFastNS.BFast ToBFast() + public BFast ToBFast() { var assets = Assets.Select(kv => kv.Value.ToNamedBuffer(kv.Key)) as IEnumerable; Debug.Assert(assets != null, "Asset conversion to IEnumerable failed."); diff --git a/src/cs/vim/Vim.Format.Core/G3dBuilder.cs b/src/cs/vim/Vim.Format.Core/G3dBuilder.cs index 4b8ef3fb..5f946865 100644 --- a/src/cs/vim/Vim.Format.Core/G3dBuilder.cs +++ b/src/cs/vim/Vim.Format.Core/G3dBuilder.cs @@ -52,9 +52,9 @@ public int[] GetFaceCounts() } - public BFastNS.BFast ToBFast() + public BFast ToBFast() { - var bfast = new BFastNS.BFast(); + var bfast = new BFast(); var totalSubmeshCount = _meshes.Select(s => s.SubmeshesIndexOffset.Count).Sum(); // Compute the Vertex offsets and index offsets @@ -91,7 +91,7 @@ public BFastNS.BFast ToBFast() shapeVertexOffsets[i] = shapeVertexOffsets[i - 1] + _shapes[i - 1].Vertices.Count; } - bfast = new BFastNS.BFast(); + bfast = new BFast(); bfast.SetArray("Meta", G3dHeader.Default.ToBytes()); bfast.SetEnumerable(CommonAttributes.Position, () => _meshes.SelectMany(m => m.Vertices)); diff --git a/src/cs/vim/Vim.Format.Core/SerializableDocument.cs b/src/cs/vim/Vim.Format.Core/SerializableDocument.cs index cfb34ed0..a57ae7e9 100644 --- a/src/cs/vim/Vim.Format.Core/SerializableDocument.cs +++ b/src/cs/vim/Vim.Format.Core/SerializableDocument.cs @@ -9,60 +9,6 @@ namespace Vim.Format { - /// - /// Tracks all of the data for a particular entity type in a conceptual table. - /// A column maybe a relation to another entity table (IndexColumn) - /// a data value stored as a double (DataColumn) or else - /// it is string data, stored as an index into the global lookup table (StringColumn). - /// - public class SerializableEntityTable - { - /// - /// Name of - /// - public string Name; - - /// - /// Relation to another entity table. For example surface to element. - /// - public List> IndexColumns = new List>(); - - /// - /// Data encoded as strings in the global string table - /// - public List> StringColumns = new List>(); - - /// - /// Numeric data encoded as byte, int, float, or doubles - /// - public List DataColumns = new List(); - - public IEnumerable ColumnNames - => IndexColumns.Select(c => c.Name) - .Concat(StringColumns.Select(c => c.Name)) - .Concat(DataColumns.Select(c => c.Name)); - - public IEnumerable AllColumns - => IndexColumns - .Concat(StringColumns) - .Concat(DataColumns); - - public static SerializableEntityTable FromBfast(string name, BFastNS.BFast bfast) - { - return null; - } - - public BFastNS.BFast ToBFast() - { - var bfast = new BFastNS.BFast(); - foreach (var col in AllColumns) - { - bfast.SetArray(col.Name, col.AsArray()); - } - return bfast; - } - } - /// /// Controls what parts of the VIM file are loaded /// @@ -112,19 +58,18 @@ public class SerializableDocument /// The originating file name (if provided) /// public string FileName; - public BFastNS.BFast ToBFast() + public BFast ToBFast() { - var bfast = new BFastNS.BFast(); - //bfast.SetArray(BufferNames.Header, Header.ToBytes()); + var bfast = new BFast(); - var assets = new BFastNS.BFast(); + var assets = new BFast(); foreach (var asset in Assets) { assets.SetArray(asset.Name, asset.ToArray()); } bfast.SetBFast(BufferNames.Assets, assets); - - var entities = new BFastNS.BFast(); + + var entities = new BFast(); foreach (var entity in EntityTables) { entities.SetBFast(entity.Name, entity.ToBFast()); @@ -139,14 +84,14 @@ public static SerializableDocument FromPath(string path, LoadOptions options = n { using (var file = new FileStream(path, FileMode.OpenOrCreate)) { - var bfast = new BFastNS.BFast(file); + var bfast = new BFast(file); var doc = FromBFast(bfast); doc.FileName = path; return doc; } } - public static SerializableDocument FromBFast(BFastNS.BFast bfast, LoadOptions options = null) + public static SerializableDocument FromBFast(BFast bfast, LoadOptions options = null) { var doc = new SerializableDocument(); doc.Options = options ?? new LoadOptions(); @@ -174,7 +119,7 @@ public static SerializableDocument FromBFast(BFastNS.BFast bfast, LoadOptions op /// Enumerates the SerializableEntityTables contained in the given entities buffer. /// private static IEnumerable GetEntityTables( - BFastNS.BFast bfast, + BFast bfast, bool schemaOnly) { @@ -187,19 +132,18 @@ private static IEnumerable GetEntityTables( } } - /// /// Returns a SerializableEntityTable based on the given buffer reader. /// public static SerializableEntityTable ReadEntityTable2( - BFastNS.BFast bfast, + BFast bfast, bool schemaOnly ) { var et = new SerializableEntityTable(); foreach (var entry in bfast.Entries) { - var typePrefix = entry.GetTypePrefix(); + var typePrefix = SerializableEntityTable.GetTypeFromName(entry); switch (typePrefix) { @@ -252,8 +196,5 @@ bool schemaOnly return et; } - - - } } diff --git a/src/cs/vim/Vim.Format.Core/SerializableEntityTable.cs b/src/cs/vim/Vim.Format.Core/SerializableEntityTable.cs new file mode 100644 index 00000000..87c234c9 --- /dev/null +++ b/src/cs/vim/Vim.Format.Core/SerializableEntityTable.cs @@ -0,0 +1,69 @@ +using System.Collections.Generic; +using System.Linq; +using System.Text.RegularExpressions; +using Vim.BFastNS; + +namespace Vim.Format +{ + /// + /// Tracks all of the data for a particular entity type in a conceptual table. + /// A column maybe a relation to another entity table (IndexColumn) + /// a data value stored as a double (DataColumn) or else + /// it is string data, stored as an index into the global lookup table (StringColumn). + /// + public class SerializableEntityTable + { + /// + /// Name of + /// + public string Name; + + /// + /// Relation to another entity table. For example surface to element. + /// + public List> IndexColumns = new List>(); + + /// + /// Data encoded as strings in the global string table + /// + public List> StringColumns = new List>(); + + /// + /// Numeric data encoded as byte, int, float, or doubles + /// + public List DataColumns = new List(); + + public IEnumerable ColumnNames + => IndexColumns.Select(c => c.Name) + .Concat(StringColumns.Select(c => c.Name)) + .Concat(DataColumns.Select(c => c.Name)); + + public IEnumerable AllColumns + => IndexColumns + .Concat(StringColumns) + .Concat(DataColumns); + + public static SerializableEntityTable FromBfast(string name, BFast bfast) + { + return null; + } + + private readonly static Regex TypePrefixRegex = new Regex(@"(\w+:).*"); + + public static string GetTypeFromName(string name) + { + var match = TypePrefixRegex.Match(name); + return match.Success ? match.Groups[1].Value : ""; + } + + public BFast ToBFast() + { + var bfast = new BFast(); + foreach (var col in AllColumns) + { + bfast.SetArray(col.Name, col.AsArray()); + } + return bfast; + } + } +} diff --git a/src/cs/vim/Vim.Format.Core/Serializer.cs b/src/cs/vim/Vim.Format.Core/Serializer.cs deleted file mode 100644 index a63dd565..00000000 --- a/src/cs/vim/Vim.Format.Core/Serializer.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Text.RegularExpressions; -using Vim.BFastNS; - -namespace Vim.Format -{ - public static class Serializer - { - public static readonly Regex TypePrefixRegex = new Regex(@"(\w+:).*"); - - public static string GetTypePrefix(this string name) - { - var match = TypePrefixRegex.Match(name); - return match.Success ? match.Groups[1].Value : ""; - } - - /// - /// Returns the named buffer prefix, or null if no prefix was found. - /// - public static string GetTypePrefix(this INamedBuffer namedBuffer) - => namedBuffer.Name.GetTypePrefix(); - - } -} diff --git a/src/cs/vim/Vim.Format.Vimx/Vimx.cs b/src/cs/vim/Vim.Format.Vimx/Vimx.cs index a5155c01..12ef4f1f 100644 --- a/src/cs/vim/Vim.Format.Vimx/Vimx.cs +++ b/src/cs/vim/Vim.Format.Vimx/Vimx.cs @@ -44,7 +44,7 @@ public Vimx(SerializableHeader header, MetaHeader meta, G3dScene scene, G3dMater Chunks = chunks; } - public Vimx(BFastNS.BFast bfast) + public Vimx(BFast bfast) { Header = VimxHeader.FromBytes(bfast.GetArray(BufferNames.Header)); @@ -65,7 +65,7 @@ public Vimx(BFastNS.BFast bfast) public static Vimx FromPath(string path) => path.ReadBFast((b) => new Vimx(b)); - public BFastNS.BFast ToBFast() + public BFast ToBFast() { AddTransformsToScene(); var bfast = new BFast(); diff --git a/src/cs/vim/Vim.Format.Vimx/VimxChunk.cs b/src/cs/vim/Vim.Format.Vimx/VimxChunk.cs index ffcc73bf..5a647877 100644 --- a/src/cs/vim/Vim.Format.Vimx/VimxChunk.cs +++ b/src/cs/vim/Vim.Format.Vimx/VimxChunk.cs @@ -12,16 +12,16 @@ public class VimxChunk public VimxChunk() { } public VimxChunk(List meshes) { Meshes = meshes; } - public VimxChunk(BFastNS.BFast bfast) + public VimxChunk(BFast bfast) { Meshes = bfast.Entries .Select(e => new G3dMesh(bfast.GetBFast(e))) .ToList(); } - public BFastNS.BFast ToBFast() + public BFast ToBFast() { - var chunk = new BFastNS.BFast(); + var chunk = new BFast(); chunk.SetBFast( BufferNames.Mesh, Meshes.Select(m => m.ToBFast()) diff --git a/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs b/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs index 13001b75..4a34a9da 100644 --- a/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs +++ b/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs @@ -37,7 +37,7 @@ public static SerializableHeader GetHeader(string path) public static SerializableHeader GetHeader(Stream stream) { - var bfast = new BFastNS.BFast(stream); + var bfast = new BFast(stream); var bytes = bfast.GetArray(BufferNames.Header); if (bytes == null) return null; return SerializableHeader.FromBytes(bytes); @@ -50,11 +50,11 @@ public static VimScene LoadVim(string f, IVimSceneProgress progress = null, bool => LoadVim(f, new LoadOptions { SkipGeometry = skipGeometry, SkipAssets = skipAssets}, progress, inParallel); public static VimScene LoadVim(Stream stream, LoadOptions loadOptions, IVimSceneProgress progress = null, bool inParallel = false) - => new VimScene(SerializableDocument.FromBFast(new BFastNS.BFast(stream), loadOptions), progress, inParallel); + => new VimScene(SerializableDocument.FromBFast(new BFast(stream), loadOptions), progress, inParallel); public static VimScene LoadVim2(Stream stream, LoadOptions loadOptions = null, IVimSceneProgress progress = null, bool inParallel = false) { - var bfast = new BFastNS.BFast(stream); + var bfast = new BFast(stream); var doc = SerializableDocument.FromBFast(bfast, loadOptions); return new VimScene(doc, progress, inParallel); } diff --git a/src/cs/vim/Vim.Vimx.Test/VimG3dTests.cs b/src/cs/vim/Vim.Vimx.Test/VimG3dTests.cs index 51e4b2b0..e8ad967d 100644 --- a/src/cs/vim/Vim.Vimx.Test/VimG3dTests.cs +++ b/src/cs/vim/Vim.Vimx.Test/VimG3dTests.cs @@ -43,7 +43,7 @@ public static void Can_Read_Write_Triangle() var memoryStream = new MemoryStream(); g3d1.ToBFast().Write(memoryStream); memoryStream.Seek(0, SeekOrigin.Begin); - var bfast = new BFastNS.BFast(memoryStream); + var bfast = new BFast(memoryStream); var g3d2 = new VimAttributeCollection(bfast); Assert.IsNotNull(g3d2); @@ -76,7 +76,7 @@ public static void Can_Ignore_Extra_Attributes() var g3d = G3dVim.FromVim(TestUtils.ResidencePath); g3d.ToBFast().Write(memoryStream); memoryStream.Seek(0, SeekOrigin.Begin); - var bfast = new BFastNS.BFast(memoryStream); + var bfast = new BFast(memoryStream); var g3dMats = new G3dMaterials(bfast); Assert.IsNotNull(g3dMats); @@ -115,7 +115,7 @@ public static void Can_Merge_two_g3d() var g3dFilePath = Path.Combine(testDir!, "merged.g3d"); mergedG3d.ToBFast().Write(memoryStream); memoryStream.Seek(0, SeekOrigin.Begin); - var bfast = new BFastNS.BFast(memoryStream); + var bfast = new BFast(memoryStream); var g3dResult = new VimAttributeCollection(bfast); From ec9878af62c5093d8ccfdacf9fc609a8a0495af8 Mon Sep 17 00:00:00 2001 From: simon Date: Mon, 11 Dec 2023 16:14:35 -0500 Subject: [PATCH 036/111] added counts --- src/cs/vim/Vim.Format.Core/G3dBuilder.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/cs/vim/Vim.Format.Core/G3dBuilder.cs b/src/cs/vim/Vim.Format.Core/G3dBuilder.cs index 5f946865..6d7df92c 100644 --- a/src/cs/vim/Vim.Format.Core/G3dBuilder.cs +++ b/src/cs/vim/Vim.Format.Core/G3dBuilder.cs @@ -33,7 +33,11 @@ public void AddMaterial(Material material) { _materials.Add(material); } + + public int InstanceCount => _instances.Count; public int MeshCount => _meshes.Count; + public int MaterialCount => _materials.Count; + public int ShapeCount => _shapes.Count; public SubdividedMesh GetMesh(int index) => _meshes[index]; public AABox GetBox(int meshIndex) From 5e272230e26169ceaf371496fbdc7364e85a028d Mon Sep 17 00:00:00 2001 From: simon Date: Fri, 15 Dec 2023 14:37:40 -0500 Subject: [PATCH 037/111] Moved Transform from mesh to scene. Removed abstract g3d and cie. --- src/ts/dist/bfast.d.ts | 4 + src/ts/dist/bfast.js | 24 ++++ src/ts/dist/g3dMaterials.d.ts | 11 +- src/ts/dist/g3dMaterials.js | 33 +----- src/ts/dist/g3dMesh.d.ts | 40 ++----- src/ts/dist/g3dMesh.js | 85 +++----------- src/ts/dist/g3dScene.d.ts | 47 ++++---- src/ts/dist/g3dScene.js | 94 ++++----------- src/ts/dist/types/bfast.d.ts | 4 + src/ts/dist/types/g3dMaterials.d.ts | 11 +- src/ts/dist/types/g3dMesh.d.ts | 40 ++----- src/ts/dist/types/g3dScene.d.ts | 47 ++++---- src/ts/package.json | 2 +- src/ts/src/abstractG3d.ts | 43 ------- src/ts/src/bfast.ts | 24 ++++ src/ts/src/g3d.ts | 72 +++--------- src/ts/src/g3dAttributes.ts | 144 ----------------------- src/ts/src/g3dMaterials.ts | 55 +-------- src/ts/src/g3dMesh.ts | 142 ++++------------------- src/ts/src/g3dScene.ts | 171 ++++++++-------------------- 20 files changed, 247 insertions(+), 846 deletions(-) delete mode 100644 src/ts/src/abstractG3d.ts delete mode 100644 src/ts/src/g3dAttributes.ts diff --git a/src/ts/dist/bfast.d.ts b/src/ts/dist/bfast.d.ts index 4b26ae03..33cea1c5 100644 --- a/src/ts/dist/bfast.d.ts +++ b/src/ts/dist/bfast.d.ts @@ -73,6 +73,10 @@ export declare class BFast { * @param name buffer name */ getArray(name: string): Promise; + getInt32Array(name: string): Promise; + getFloat32Array(name: string): Promise; + getBigInt64Array(name: string): Promise; + getUint16Array(name: string): Promise; /** * Returns a single value from given buffer name * @param name buffer name diff --git a/src/ts/dist/bfast.js b/src/ts/dist/bfast.js index 8c0ad054..e88e2bb6 100644 --- a/src/ts/dist/bfast.js +++ b/src/ts/dist/bfast.js @@ -257,6 +257,30 @@ class BFast { const array = new Ctor(buffer); return array; } + async getInt32Array(name) { + const buffer = await this.getBuffer(name); + if (!buffer) + return; + return new Int32Array(buffer); + } + async getFloat32Array(name) { + const buffer = await this.getBuffer(name); + if (!buffer) + return; + return new Float32Array(buffer); + } + async getBigInt64Array(name) { + const buffer = await this.getBuffer(name); + if (!buffer) + return; + return new BigInt64Array(buffer); + } + async getUint16Array(name) { + const buffer = await this.getBuffer(name); + if (!buffer) + return; + return new Uint16Array(buffer); + } /** * Returns a single value from given buffer name * @param name buffer name diff --git a/src/ts/dist/g3dMaterials.d.ts b/src/ts/dist/g3dMaterials.d.ts index 8737e18d..e1955ff7 100644 --- a/src/ts/dist/g3dMaterials.d.ts +++ b/src/ts/dist/g3dMaterials.d.ts @@ -1,14 +1,12 @@ /** * @module vim-ts */ -import { AbstractG3d } from './abstractG3d'; import { BFast } from './bfast'; /** * See https://github.com/vimaec/vim#vim-geometry-attributes */ export declare class MaterialAttributes { static materialColors: string; - static all: string[]; } /** * G3D is a simple, efficient, generic binary format for storing and transmitting geometry. @@ -18,16 +16,11 @@ export declare class MaterialAttributes { * See https://github.com/vimaec/g3d for the g3d specification. */ export declare class G3dMaterial { - static COLOR_SIZE: number; - rawG3d: AbstractG3d; + static readonly COLOR_SIZE = 4; + static readonly DEFAULT_COLOR: Float32Array; materialColors: Float32Array; - DEFAULT_COLOR: Float32Array; constructor(materialColors: Float32Array); - static createFromAbstract(g3d: AbstractG3d): G3dMaterial; - static createFromPath(path: string): Promise; - static createFromBuffer(buffer: ArrayBuffer): Promise; static createFromBfast(bfast: BFast): Promise; - toG3d(): G3dMaterial; getMaterialCount: () => number; /** * Returns color of given material as a 4-number array (RGBA) diff --git a/src/ts/dist/g3dMaterials.js b/src/ts/dist/g3dMaterials.js index a8c71df3..cba9a150 100644 --- a/src/ts/dist/g3dMaterials.js +++ b/src/ts/dist/g3dMaterials.js @@ -4,8 +4,6 @@ */ Object.defineProperty(exports, "__esModule", { value: true }); exports.G3dMaterial = exports.MaterialAttributes = void 0; -const abstractG3d_1 = require("./abstractG3d"); -const bfast_1 = require("./bfast"); /** * See https://github.com/vimaec/vim#vim-geometry-attributes */ @@ -13,9 +11,6 @@ class MaterialAttributes { } exports.MaterialAttributes = MaterialAttributes; MaterialAttributes.materialColors = 'g3d:material:color:0:float32:4'; -MaterialAttributes.all = [ - MaterialAttributes.materialColors -]; /** * G3D is a simple, efficient, generic binary format for storing and transmitting geometry. * The G3D format is designed to be used either as a serialization format or as an in-memory data structure. @@ -25,33 +20,12 @@ MaterialAttributes.all = [ */ class G3dMaterial { constructor(materialColors) { - this.DEFAULT_COLOR = new Float32Array([1, 1, 1, 1]); this.getMaterialCount = () => this.materialColors.length / G3dMaterial.COLOR_SIZE; this.materialColors = materialColors; } - static createFromAbstract(g3d) { - const materialColors = g3d.findAttribute(MaterialAttributes.materialColors) - ?.data; - const result = new G3dMaterial(materialColors); - result.rawG3d = g3d; - return result; - } - static async createFromPath(path) { - const f = await fetch(path); - const buffer = await f.arrayBuffer(); - var g3d = this.createFromBuffer(buffer); - return g3d; - } - static async createFromBuffer(buffer) { - const bfast = new bfast_1.BFast(buffer); - return this.createFromBfast(bfast); - } static async createFromBfast(bfast) { - const g3d = await abstractG3d_1.AbstractG3d.createFromBfast(bfast, MaterialAttributes.all); - return G3dMaterial.createFromAbstract(g3d); - } - toG3d() { - return new G3dMaterial(this.materialColors); + const mats = await bfast.getFloat32Array(MaterialAttributes.materialColors); + return new G3dMaterial(mats); } /** * Returns color of given material as a 4-number array (RGBA) @@ -59,7 +33,7 @@ class G3dMaterial { */ getMaterialColor(material) { if (material < 0) - return this.DEFAULT_COLOR; + return G3dMaterial.DEFAULT_COLOR; return this.materialColors.subarray(material * G3dMaterial.COLOR_SIZE, (material + 1) * G3dMaterial.COLOR_SIZE); } getMaterialAlpha(material) { @@ -72,3 +46,4 @@ class G3dMaterial { } exports.G3dMaterial = G3dMaterial; G3dMaterial.COLOR_SIZE = 4; +G3dMaterial.DEFAULT_COLOR = new Float32Array([1, 1, 1, 1]); diff --git a/src/ts/dist/g3dMesh.d.ts b/src/ts/dist/g3dMesh.d.ts index 3f755f41..30c17da2 100644 --- a/src/ts/dist/g3dMesh.d.ts +++ b/src/ts/dist/g3dMesh.d.ts @@ -1,7 +1,6 @@ /** * @module vim-ts */ -import { AbstractG3d } from './abstractG3d'; import { BFast } from './bfast'; import { MeshSection } from './g3d'; import { G3dScene } from './g3dScene'; @@ -9,7 +8,6 @@ import { G3dScene } from './g3dScene'; * See https://github.com/vimaec/vim#vim-geometry-attributes */ export declare class MeshAttributes { - static instanceTransforms: string; static meshOpaqueSubmeshCount: string; static submeshIndexOffsets: string; static submeshVertexOffsets: string; @@ -28,38 +26,20 @@ export declare class MeshAttributes { export declare class G3dMesh { scene: G3dScene; meshIndex: number; - rawG3d: AbstractG3d; - instanceTransforms: Float32Array; - meshOpaqueSubmeshCount: number; - submeshIndexOffset: Int32Array; - submeshVertexOffset: Int32Array; - submeshMaterial: Int32Array; - positions: Float32Array; - indices: Uint32Array; - static MATRIX_SIZE: number; - static COLOR_SIZE: number; - static POSITION_SIZE: number; + readonly meshOpaqueSubmeshCount: number; + readonly submeshIndexOffset: Int32Array; + readonly submeshVertexOffset: Int32Array; + readonly submeshMaterial: Int32Array; + readonly positions: Float32Array; + readonly indices: Uint32Array; + static readonly COLOR_SIZE = 4; + static readonly POSITION_SIZE = 3; /** * Opaque white */ - DEFAULT_COLOR: Float32Array; - constructor(instanceTransforms: Float32Array, meshOpaqueSubmeshCount: number, submeshIndexOffsets: Int32Array, submeshVertexOffsets: Int32Array, submeshMaterials: Int32Array, indices: Int32Array | Uint32Array, positions: Float32Array); - static createFromAbstract(g3d: AbstractG3d): G3dMesh; - static createFromPath(path: string): Promise; - static createFromBuffer(buffer: ArrayBuffer): Promise; + static readonly DEFAULT_COLOR: Float32Array; + constructor(meshOpaqueSubmeshCount: number, submeshIndexOffsets: Int32Array, submeshVertexOffsets: Int32Array, submeshMaterials: Int32Array, indices: Int32Array | Uint32Array, positions: Float32Array); static createFromBfast(bfast: BFast): Promise; - getBimInstance(meshInstance: number): number; - getInstanceMax(meshInstance: number): Float32Array; - getInstanceMin(meshInstance: number): Float32Array; - getInstanceGroup(meshInstance: number): number; - getInstanceTag(meshInstance: number): bigint; - getInstanceHasFlag(meshInstance: number, flag: number): boolean; - getInstanceCount: () => number; - /** - * Returns an 16 number array representation of the matrix for given instance - * @param instance g3d instance index - */ - getInstanceMatrix(instance: number): Float32Array; getVertexStart(section?: MeshSection): number; getVertexEnd(section?: MeshSection): number; getVertexCount(section?: MeshSection): number; diff --git a/src/ts/dist/g3dMesh.js b/src/ts/dist/g3dMesh.js index b5be09e7..8b572ae4 100644 --- a/src/ts/dist/g3dMesh.js +++ b/src/ts/dist/g3dMesh.js @@ -4,8 +4,6 @@ */ Object.defineProperty(exports, "__esModule", { value: true }); exports.G3dMesh = exports.MeshAttributes = void 0; -const abstractG3d_1 = require("./abstractG3d"); -const bfast_1 = require("./bfast"); const g3d_1 = require("./g3d"); /** * See https://github.com/vimaec/vim#vim-geometry-attributes @@ -13,7 +11,6 @@ const g3d_1 = require("./g3d"); class MeshAttributes { } exports.MeshAttributes = MeshAttributes; -MeshAttributes.instanceTransforms = 'g3d:instance:transform:0:float32:16'; MeshAttributes.meshOpaqueSubmeshCount = 'g3d:mesh:opaquesubmeshcount:0:int32:1'; MeshAttributes.submeshIndexOffsets = 'g3d:submesh:indexoffset:0:int32:1'; MeshAttributes.submeshVertexOffsets = 'g3d:submesh:vertexoffset:0:int32:1'; @@ -21,7 +18,6 @@ MeshAttributes.submeshMaterials = 'g3d:submesh:material:0:int32:1'; MeshAttributes.positions = 'g3d:vertex:position:0:float32:3'; MeshAttributes.indices = 'g3d:corner:index:0:int32:1'; MeshAttributes.all = [ - MeshAttributes.instanceTransforms, MeshAttributes.meshOpaqueSubmeshCount, MeshAttributes.submeshIndexOffsets, MeshAttributes.submeshVertexOffsets, @@ -37,13 +33,7 @@ MeshAttributes.all = [ * See https://github.com/vimaec/g3d for the g3d specification. */ class G3dMesh { - constructor(instanceTransforms, meshOpaqueSubmeshCount, submeshIndexOffsets, submeshVertexOffsets, submeshMaterials, indices, positions) { - /** - * Opaque white - */ - this.DEFAULT_COLOR = new Float32Array([1, 1, 1, 1]); - this.getInstanceCount = () => this.instanceTransforms.length; - this.instanceTransforms = instanceTransforms; + constructor(meshOpaqueSubmeshCount, submeshIndexOffsets, submeshVertexOffsets, submeshMaterials, indices, positions) { this.meshOpaqueSubmeshCount = meshOpaqueSubmeshCount; this.submeshIndexOffset = submeshIndexOffsets; this.submeshVertexOffset = submeshVertexOffsets; @@ -51,66 +41,16 @@ class G3dMesh { this.indices = indices instanceof Uint32Array ? indices : new Uint32Array(indices.buffer); this.positions = positions; } - static createFromAbstract(g3d) { - const instanceTransforms = g3d.findAttribute(MeshAttributes.instanceTransforms)?.data; - const meshOpaqueSubmeshCountArray = g3d.findAttribute(MeshAttributes.meshOpaqueSubmeshCount)?.data; - const meshOpaqueSubmeshCount = meshOpaqueSubmeshCountArray[0]; - const submeshIndexOffsets = g3d.findAttribute(MeshAttributes.submeshIndexOffsets)?.data; - const submeshVertexOffsets = g3d.findAttribute(MeshAttributes.submeshVertexOffsets)?.data; - const submeshMaterial = g3d.findAttribute(MeshAttributes.submeshMaterials) - ?.data; - const indices = g3d.findAttribute(MeshAttributes.indices)?.data; - const positions = g3d.findAttribute(MeshAttributes.positions) - ?.data; - const result = new G3dMesh(instanceTransforms, meshOpaqueSubmeshCount, submeshIndexOffsets, submeshVertexOffsets, submeshMaterial, indices, positions); - result.rawG3d = g3d; - return result; - } - static async createFromPath(path) { - const f = await fetch(path); - const buffer = await f.arrayBuffer(); - var g3d = this.createFromBuffer(buffer); - return g3d; - } - static async createFromBuffer(buffer) { - const bfast = new bfast_1.BFast(buffer); - return this.createFromBfast(bfast); - } static async createFromBfast(bfast) { - const g3d = await abstractG3d_1.AbstractG3d.createFromBfast(bfast, MeshAttributes.all); - return G3dMesh.createFromAbstract(g3d); - } - // -----------Instances--------------- - getBimInstance(meshInstance) { - const sceneInstance = this.scene.getMeshSceneInstance(this.meshIndex, meshInstance); - return this.scene.instanceNodes[sceneInstance]; - } - getInstanceMax(meshInstance) { - const sceneInstance = this.scene.getMeshSceneInstance(this.meshIndex, meshInstance); - return this.scene.instanceMaxs.subarray(sceneInstance * 3, (sceneInstance + 1) * 3); - } - getInstanceMin(meshInstance) { - const sceneInstance = this.scene.getMeshSceneInstance(this.meshIndex, meshInstance); - return this.scene.instanceMins.subarray(sceneInstance * 3, (sceneInstance + 1) * 3); - } - getInstanceGroup(meshInstance) { - const sceneInstance = this.scene.getMeshSceneInstance(this.meshIndex, meshInstance); - return this.scene.instanceGroups[sceneInstance]; - } - getInstanceTag(meshInstance) { - const sceneInstance = this.scene.getMeshSceneInstance(this.meshIndex, meshInstance); - return this.scene.instanceTags[sceneInstance]; - } - getInstanceHasFlag(meshInstance, flag) { - const sceneInstance = this.scene.getMeshSceneInstance(this.meshIndex, meshInstance); - return (this.scene.instanceFlags[sceneInstance] & flag) > 0; - } - /** - * Returns an 16 number array representation of the matrix for given instance - * @param instance g3d instance index - */ - getInstanceMatrix(instance) { - return this.instanceTransforms.subarray(instance * G3dMesh.MATRIX_SIZE, (instance + 1) * G3dMesh.MATRIX_SIZE); + const values = await Promise.all([ + bfast.getValue(MeshAttributes.meshOpaqueSubmeshCount, 0).then(v => v), + bfast.getInt32Array(MeshAttributes.submeshIndexOffsets), + bfast.getInt32Array(MeshAttributes.submeshVertexOffsets), + bfast.getInt32Array(MeshAttributes.submeshMaterials), + bfast.getInt32Array(MeshAttributes.indices), + bfast.getFloat32Array(MeshAttributes.positions) + ]); + return new G3dMesh(...values); } // ------------- Mesh ----------------- getVertexStart(section = 'all') { @@ -184,6 +124,9 @@ class G3dMesh { } } exports.G3dMesh = G3dMesh; -G3dMesh.MATRIX_SIZE = 16; G3dMesh.COLOR_SIZE = 4; G3dMesh.POSITION_SIZE = 3; +/** + * Opaque white + */ +G3dMesh.DEFAULT_COLOR = new Float32Array([1, 1, 1, 1]); diff --git a/src/ts/dist/g3dScene.d.ts b/src/ts/dist/g3dScene.d.ts index 49fe9555..4cb2d42b 100644 --- a/src/ts/dist/g3dScene.d.ts +++ b/src/ts/dist/g3dScene.d.ts @@ -1,7 +1,6 @@ /** * @module vim-ts */ -import { AbstractG3d } from './abstractG3d'; import { BFast } from './bfast'; import { MeshSection } from './g3d'; export declare type FilterMode = undefined | 'mesh' | 'instance' | 'group' | 'tag'; @@ -9,23 +8,22 @@ export declare type FilterMode = undefined | 'mesh' | 'instance' | 'group' | 'ta * See https://github.com/vimaec/vim#vim-geometry-attributes */ export declare class SceneAttributes { - static chunkCount: string; - static instanceMesh: string; - static instanceTransform: string; - static instanceNodes: string; - static instanceGroups: string; - static instanceTags: string; - static instanceFlags: string; - static instanceMins: string; - static instanceMaxs: string; - static meshChunk: string; - static meshChunkIndices: string; - static meshInstanceCounts: string; - static meshIndexCounts: string; - static meshVertexCounts: string; - static meshOpaqueIndexCount: string; - static meshOpaqueVertexCount: string; - static all: string[]; + static readonly chunkCount = "g3d:chunk:count:0:int32:1"; + static readonly instanceMesh = "g3d:instance:mesh:0:int32:1"; + static readonly instanceMatrix = "g3d:instance:transform:0:float32:16"; + static readonly instanceNodes = "g3d:instance:node:0:int32:1"; + static readonly instanceGroups = "g3d:instance:group:0:int32:1"; + static readonly instanceTags = "g3d:instance:tag:0:int64:1"; + static readonly instanceFlags = "g3d:instance:tag:0:uint16:1"; + static readonly instanceMins = "g3d:instance:min:0:float32:3"; + static readonly instanceMaxs = "g3d:instance:max:0:float32:3"; + static readonly meshChunk = "g3d:mesh:chunk:0:int32:1"; + static readonly meshChunkIndices = "g3d:mesh:chunkindex:0:int32:1"; + static readonly meshInstanceCounts = "g3d:mesh:instancecount:0:int32:1"; + static readonly meshIndexCounts = "g3d:mesh:indexcount:0:int32:1"; + static readonly meshVertexCounts = "g3d:mesh:vertexcount:0:int32:1"; + static readonly meshOpaqueIndexCount = "g3d:mesh:opaqueindexcount:0:int32:1"; + static readonly meshOpaqueVertexCount = "g3d:mesh:opaquevertexcount:0:int32:1"; } /** * Represents the index, as in book index, of a collection of G3dMesh. @@ -33,10 +31,9 @@ export declare class SceneAttributes { * Allows to preallocate geometry to render G3dMeshes. */ export declare class G3dScene { - rawG3d: AbstractG3d; chunkCount: number; instanceMeshes: Int32Array; - instanceTransforms: Int32Array; + instanceMatrices: Float32Array; instanceNodes: Int32Array; instanceGroups: Int32Array; instanceTags: BigInt64Array; @@ -51,19 +48,13 @@ export declare class G3dScene { meshOpaqueIndexCounts: Int32Array; meshOpaqueVertexCounts: Int32Array; private nodeToInstance; - private meshSceneInstances; - constructor(rawG3d: AbstractG3d, chunkCount: Int32Array, instanceMeshes: Int32Array, instanceTransform: Int32Array, instanceNodes: Int32Array, instanceGroups: Int32Array, instanceTags: BigInt64Array, instanceFlags: Uint16Array, instanceMins: Float32Array, instanceMaxs: Float32Array, meshChunks: Int32Array, meshChunkIndices: Int32Array, meshInstanceCounts: Int32Array, meshIndexCounts: Int32Array, meshVertexCounts: Int32Array, meshOpaqueIndexCounts: Int32Array, meshOpaqueVertexCounts: Int32Array); - private createMap; - static createFromAbstract(g3d: AbstractG3d): G3dScene; - static createFromPath(path: string): Promise; + constructor(chunkCount: Int32Array, instanceMeshes: Int32Array, instanceMatrices: Float32Array, instanceNodes: Int32Array, instanceGroups: Int32Array, instanceTags: BigInt64Array, instanceFlags: Uint16Array, instanceMins: Float32Array, instanceMaxs: Float32Array, meshChunks: Int32Array, meshChunkIndices: Int32Array, meshInstanceCounts: Int32Array, meshIndexCounts: Int32Array, meshVertexCounts: Int32Array, meshOpaqueIndexCounts: Int32Array, meshOpaqueVertexCounts: Int32Array); static createFromBfast(bfast: BFast): Promise; - getMeshSceneInstance(mesh: number, meshIndex: number): number; getMeshCount(): number; getMeshIndexCount(mesh: number, section: MeshSection): number; getMeshVertexCount(mesh: number, section: MeshSection): number; getMeshInstanceCount(mesh: number): number; - getNodeMin(node: number): Float32Array; - getNodeMax(node: number): Float32Array; getInstanceMin(instance: number): Float32Array; getInstanceMax(instance: number): Float32Array; + getInstanceMatrix(instance: number): Float32Array; } diff --git a/src/ts/dist/g3dScene.js b/src/ts/dist/g3dScene.js index e66b0e35..0962d188 100644 --- a/src/ts/dist/g3dScene.js +++ b/src/ts/dist/g3dScene.js @@ -4,8 +4,6 @@ */ Object.defineProperty(exports, "__esModule", { value: true }); exports.G3dScene = exports.SceneAttributes = void 0; -const abstractG3d_1 = require("./abstractG3d"); -const bfast_1 = require("./bfast"); const g3d_1 = require("./g3d"); /** * See https://github.com/vimaec/vim#vim-geometry-attributes @@ -15,7 +13,7 @@ class SceneAttributes { exports.SceneAttributes = SceneAttributes; SceneAttributes.chunkCount = 'g3d:chunk:count:0:int32:1'; SceneAttributes.instanceMesh = 'g3d:instance:mesh:0:int32:1'; -SceneAttributes.instanceTransform = 'g3d:instance:transform:0:int32:1'; +SceneAttributes.instanceMatrix = 'g3d:instance:transform:0:float32:16'; SceneAttributes.instanceNodes = 'g3d:instance:node:0:int32:1'; SceneAttributes.instanceGroups = 'g3d:instance:group:0:int32:1'; SceneAttributes.instanceTags = 'g3d:instance:tag:0:int64:1'; @@ -29,35 +27,16 @@ SceneAttributes.meshIndexCounts = 'g3d:mesh:indexcount:0:int32:1'; SceneAttributes.meshVertexCounts = 'g3d:mesh:vertexcount:0:int32:1'; SceneAttributes.meshOpaqueIndexCount = "g3d:mesh:opaqueindexcount:0:int32:1"; SceneAttributes.meshOpaqueVertexCount = "g3d:mesh:opaquevertexcount:0:int32:1"; -SceneAttributes.all = [ - SceneAttributes.chunkCount, - SceneAttributes.instanceMesh, - SceneAttributes.instanceTransform, - SceneAttributes.instanceNodes, - SceneAttributes.instanceGroups, - SceneAttributes.instanceTags, - SceneAttributes.instanceFlags, - SceneAttributes.instanceMins, - SceneAttributes.instanceMaxs, - SceneAttributes.meshChunk, - SceneAttributes.meshChunkIndices, - SceneAttributes.meshInstanceCounts, - SceneAttributes.meshIndexCounts, - SceneAttributes.meshVertexCounts, - SceneAttributes.meshOpaqueIndexCount, - SceneAttributes.meshOpaqueVertexCount, -]; /** * Represents the index, as in book index, of a collection of G3dMesh. * Allows to find and download G3dMesh as needed. * Allows to preallocate geometry to render G3dMeshes. */ class G3dScene { - constructor(rawG3d, chunkCount, instanceMeshes, instanceTransform, instanceNodes, instanceGroups, instanceTags, instanceFlags, instanceMins, instanceMaxs, meshChunks, meshChunkIndices, meshInstanceCounts, meshIndexCounts, meshVertexCounts, meshOpaqueIndexCounts, meshOpaqueVertexCounts) { - this.rawG3d = rawG3d; + constructor(chunkCount, instanceMeshes, instanceMatrices, instanceNodes, instanceGroups, instanceTags, instanceFlags, instanceMins, instanceMaxs, meshChunks, meshChunkIndices, meshInstanceCounts, meshIndexCounts, meshVertexCounts, meshOpaqueIndexCounts, meshOpaqueVertexCounts) { this.chunkCount = chunkCount[0]; this.instanceMeshes = instanceMeshes; - this.instanceTransforms = instanceTransform; + this.instanceMatrices = instanceMatrices; this.instanceNodes = instanceNodes; this.instanceGroups = instanceGroups; this.instanceTags = instanceTags; @@ -76,39 +55,27 @@ class G3dScene { for (let i = 0; i < this.instanceNodes.length; i++) { this.nodeToInstance.set(this.instanceNodes[i], i); } - this.meshSceneInstances = this.createMap(); - } - createMap() { - // From : (mesh, scene-index) -> mesh-index - // To: (mesh, mesh-index) -> scene-index - const map = new Map(); - for (let i = 0; i < this.instanceMeshes.length; i++) { - const mesh = this.instanceMeshes[i]; - const index = this.instanceTransforms[i]; - const indices = map.get(mesh) ?? new Map(); - indices.set(index, i); - map.set(mesh, indices); - } - return map; - } - static createFromAbstract(g3d) { - function getArray(attribute) { - return g3d.findAttribute(attribute)?.data; - } - return new G3dScene(g3d, getArray(SceneAttributes.chunkCount), getArray(SceneAttributes.instanceMesh), getArray(SceneAttributes.instanceTransform), getArray(SceneAttributes.instanceNodes), getArray(SceneAttributes.instanceGroups), getArray(SceneAttributes.instanceTags), getArray(SceneAttributes.instanceFlags), getArray(SceneAttributes.instanceMins), getArray(SceneAttributes.instanceMaxs), getArray(SceneAttributes.meshChunk), getArray(SceneAttributes.meshChunkIndices), getArray(SceneAttributes.meshInstanceCounts), getArray(SceneAttributes.meshIndexCounts), getArray(SceneAttributes.meshVertexCounts), getArray(SceneAttributes.meshOpaqueIndexCount), getArray(SceneAttributes.meshOpaqueVertexCount)); - } - static async createFromPath(path) { - const f = await fetch(path); - const buffer = await f.arrayBuffer(); - const bfast = new bfast_1.BFast(buffer); - return this.createFromBfast(bfast); } static async createFromBfast(bfast) { - const g3d = await abstractG3d_1.AbstractG3d.createFromBfast(bfast, SceneAttributes.all); - return G3dScene.createFromAbstract(g3d); - } - getMeshSceneInstance(mesh, meshIndex) { - return this.meshSceneInstances.get(mesh)?.get(meshIndex); + const values = await Promise.all([ + bfast.getInt32Array(SceneAttributes.chunkCount), + bfast.getInt32Array(SceneAttributes.instanceMesh), + bfast.getFloat32Array(SceneAttributes.instanceMatrix), + bfast.getInt32Array(SceneAttributes.instanceNodes), + bfast.getInt32Array(SceneAttributes.instanceGroups), + bfast.getBigInt64Array(SceneAttributes.instanceTags), + bfast.getUint16Array(SceneAttributes.instanceFlags), + bfast.getFloat32Array(SceneAttributes.instanceMins), + bfast.getFloat32Array(SceneAttributes.instanceMaxs), + bfast.getInt32Array(SceneAttributes.meshChunk), + bfast.getInt32Array(SceneAttributes.meshChunkIndices), + bfast.getInt32Array(SceneAttributes.meshInstanceCounts), + bfast.getInt32Array(SceneAttributes.meshIndexCounts), + bfast.getInt32Array(SceneAttributes.meshVertexCounts), + bfast.getInt32Array(SceneAttributes.meshOpaqueIndexCount), + bfast.getInt32Array(SceneAttributes.meshOpaqueVertexCount), + ]); + return new G3dScene(...values); } getMeshCount() { return this.meshInstanceCounts.length; @@ -130,25 +97,14 @@ class G3dScene { getMeshInstanceCount(mesh) { return this.meshInstanceCounts[mesh]; } - getNodeMin(node) { - const instance = this.nodeToInstance.get(node); - if (!instance) { - return undefined; - } - return this.getInstanceMin(instance); - } - getNodeMax(node) { - const instance = this.nodeToInstance.get(node); - if (!instance) { - return undefined; - } - return this.getInstanceMax(instance); - } getInstanceMin(instance) { return this.instanceMins.subarray(instance * g3d_1.G3d.POSITION_SIZE); } getInstanceMax(instance) { return this.instanceMaxs.subarray(instance * g3d_1.G3d.POSITION_SIZE); } + getInstanceMatrix(instance) { + return this.instanceMatrices.subarray(instance * g3d_1.G3d.MATRIX_SIZE, (instance + 1) * g3d_1.G3d.MATRIX_SIZE); + } } exports.G3dScene = G3dScene; diff --git a/src/ts/dist/types/bfast.d.ts b/src/ts/dist/types/bfast.d.ts index 4b26ae03..33cea1c5 100644 --- a/src/ts/dist/types/bfast.d.ts +++ b/src/ts/dist/types/bfast.d.ts @@ -73,6 +73,10 @@ export declare class BFast { * @param name buffer name */ getArray(name: string): Promise; + getInt32Array(name: string): Promise; + getFloat32Array(name: string): Promise; + getBigInt64Array(name: string): Promise; + getUint16Array(name: string): Promise; /** * Returns a single value from given buffer name * @param name buffer name diff --git a/src/ts/dist/types/g3dMaterials.d.ts b/src/ts/dist/types/g3dMaterials.d.ts index 8737e18d..e1955ff7 100644 --- a/src/ts/dist/types/g3dMaterials.d.ts +++ b/src/ts/dist/types/g3dMaterials.d.ts @@ -1,14 +1,12 @@ /** * @module vim-ts */ -import { AbstractG3d } from './abstractG3d'; import { BFast } from './bfast'; /** * See https://github.com/vimaec/vim#vim-geometry-attributes */ export declare class MaterialAttributes { static materialColors: string; - static all: string[]; } /** * G3D is a simple, efficient, generic binary format for storing and transmitting geometry. @@ -18,16 +16,11 @@ export declare class MaterialAttributes { * See https://github.com/vimaec/g3d for the g3d specification. */ export declare class G3dMaterial { - static COLOR_SIZE: number; - rawG3d: AbstractG3d; + static readonly COLOR_SIZE = 4; + static readonly DEFAULT_COLOR: Float32Array; materialColors: Float32Array; - DEFAULT_COLOR: Float32Array; constructor(materialColors: Float32Array); - static createFromAbstract(g3d: AbstractG3d): G3dMaterial; - static createFromPath(path: string): Promise; - static createFromBuffer(buffer: ArrayBuffer): Promise; static createFromBfast(bfast: BFast): Promise; - toG3d(): G3dMaterial; getMaterialCount: () => number; /** * Returns color of given material as a 4-number array (RGBA) diff --git a/src/ts/dist/types/g3dMesh.d.ts b/src/ts/dist/types/g3dMesh.d.ts index 3f755f41..30c17da2 100644 --- a/src/ts/dist/types/g3dMesh.d.ts +++ b/src/ts/dist/types/g3dMesh.d.ts @@ -1,7 +1,6 @@ /** * @module vim-ts */ -import { AbstractG3d } from './abstractG3d'; import { BFast } from './bfast'; import { MeshSection } from './g3d'; import { G3dScene } from './g3dScene'; @@ -9,7 +8,6 @@ import { G3dScene } from './g3dScene'; * See https://github.com/vimaec/vim#vim-geometry-attributes */ export declare class MeshAttributes { - static instanceTransforms: string; static meshOpaqueSubmeshCount: string; static submeshIndexOffsets: string; static submeshVertexOffsets: string; @@ -28,38 +26,20 @@ export declare class MeshAttributes { export declare class G3dMesh { scene: G3dScene; meshIndex: number; - rawG3d: AbstractG3d; - instanceTransforms: Float32Array; - meshOpaqueSubmeshCount: number; - submeshIndexOffset: Int32Array; - submeshVertexOffset: Int32Array; - submeshMaterial: Int32Array; - positions: Float32Array; - indices: Uint32Array; - static MATRIX_SIZE: number; - static COLOR_SIZE: number; - static POSITION_SIZE: number; + readonly meshOpaqueSubmeshCount: number; + readonly submeshIndexOffset: Int32Array; + readonly submeshVertexOffset: Int32Array; + readonly submeshMaterial: Int32Array; + readonly positions: Float32Array; + readonly indices: Uint32Array; + static readonly COLOR_SIZE = 4; + static readonly POSITION_SIZE = 3; /** * Opaque white */ - DEFAULT_COLOR: Float32Array; - constructor(instanceTransforms: Float32Array, meshOpaqueSubmeshCount: number, submeshIndexOffsets: Int32Array, submeshVertexOffsets: Int32Array, submeshMaterials: Int32Array, indices: Int32Array | Uint32Array, positions: Float32Array); - static createFromAbstract(g3d: AbstractG3d): G3dMesh; - static createFromPath(path: string): Promise; - static createFromBuffer(buffer: ArrayBuffer): Promise; + static readonly DEFAULT_COLOR: Float32Array; + constructor(meshOpaqueSubmeshCount: number, submeshIndexOffsets: Int32Array, submeshVertexOffsets: Int32Array, submeshMaterials: Int32Array, indices: Int32Array | Uint32Array, positions: Float32Array); static createFromBfast(bfast: BFast): Promise; - getBimInstance(meshInstance: number): number; - getInstanceMax(meshInstance: number): Float32Array; - getInstanceMin(meshInstance: number): Float32Array; - getInstanceGroup(meshInstance: number): number; - getInstanceTag(meshInstance: number): bigint; - getInstanceHasFlag(meshInstance: number, flag: number): boolean; - getInstanceCount: () => number; - /** - * Returns an 16 number array representation of the matrix for given instance - * @param instance g3d instance index - */ - getInstanceMatrix(instance: number): Float32Array; getVertexStart(section?: MeshSection): number; getVertexEnd(section?: MeshSection): number; getVertexCount(section?: MeshSection): number; diff --git a/src/ts/dist/types/g3dScene.d.ts b/src/ts/dist/types/g3dScene.d.ts index 49fe9555..4cb2d42b 100644 --- a/src/ts/dist/types/g3dScene.d.ts +++ b/src/ts/dist/types/g3dScene.d.ts @@ -1,7 +1,6 @@ /** * @module vim-ts */ -import { AbstractG3d } from './abstractG3d'; import { BFast } from './bfast'; import { MeshSection } from './g3d'; export declare type FilterMode = undefined | 'mesh' | 'instance' | 'group' | 'tag'; @@ -9,23 +8,22 @@ export declare type FilterMode = undefined | 'mesh' | 'instance' | 'group' | 'ta * See https://github.com/vimaec/vim#vim-geometry-attributes */ export declare class SceneAttributes { - static chunkCount: string; - static instanceMesh: string; - static instanceTransform: string; - static instanceNodes: string; - static instanceGroups: string; - static instanceTags: string; - static instanceFlags: string; - static instanceMins: string; - static instanceMaxs: string; - static meshChunk: string; - static meshChunkIndices: string; - static meshInstanceCounts: string; - static meshIndexCounts: string; - static meshVertexCounts: string; - static meshOpaqueIndexCount: string; - static meshOpaqueVertexCount: string; - static all: string[]; + static readonly chunkCount = "g3d:chunk:count:0:int32:1"; + static readonly instanceMesh = "g3d:instance:mesh:0:int32:1"; + static readonly instanceMatrix = "g3d:instance:transform:0:float32:16"; + static readonly instanceNodes = "g3d:instance:node:0:int32:1"; + static readonly instanceGroups = "g3d:instance:group:0:int32:1"; + static readonly instanceTags = "g3d:instance:tag:0:int64:1"; + static readonly instanceFlags = "g3d:instance:tag:0:uint16:1"; + static readonly instanceMins = "g3d:instance:min:0:float32:3"; + static readonly instanceMaxs = "g3d:instance:max:0:float32:3"; + static readonly meshChunk = "g3d:mesh:chunk:0:int32:1"; + static readonly meshChunkIndices = "g3d:mesh:chunkindex:0:int32:1"; + static readonly meshInstanceCounts = "g3d:mesh:instancecount:0:int32:1"; + static readonly meshIndexCounts = "g3d:mesh:indexcount:0:int32:1"; + static readonly meshVertexCounts = "g3d:mesh:vertexcount:0:int32:1"; + static readonly meshOpaqueIndexCount = "g3d:mesh:opaqueindexcount:0:int32:1"; + static readonly meshOpaqueVertexCount = "g3d:mesh:opaquevertexcount:0:int32:1"; } /** * Represents the index, as in book index, of a collection of G3dMesh. @@ -33,10 +31,9 @@ export declare class SceneAttributes { * Allows to preallocate geometry to render G3dMeshes. */ export declare class G3dScene { - rawG3d: AbstractG3d; chunkCount: number; instanceMeshes: Int32Array; - instanceTransforms: Int32Array; + instanceMatrices: Float32Array; instanceNodes: Int32Array; instanceGroups: Int32Array; instanceTags: BigInt64Array; @@ -51,19 +48,13 @@ export declare class G3dScene { meshOpaqueIndexCounts: Int32Array; meshOpaqueVertexCounts: Int32Array; private nodeToInstance; - private meshSceneInstances; - constructor(rawG3d: AbstractG3d, chunkCount: Int32Array, instanceMeshes: Int32Array, instanceTransform: Int32Array, instanceNodes: Int32Array, instanceGroups: Int32Array, instanceTags: BigInt64Array, instanceFlags: Uint16Array, instanceMins: Float32Array, instanceMaxs: Float32Array, meshChunks: Int32Array, meshChunkIndices: Int32Array, meshInstanceCounts: Int32Array, meshIndexCounts: Int32Array, meshVertexCounts: Int32Array, meshOpaqueIndexCounts: Int32Array, meshOpaqueVertexCounts: Int32Array); - private createMap; - static createFromAbstract(g3d: AbstractG3d): G3dScene; - static createFromPath(path: string): Promise; + constructor(chunkCount: Int32Array, instanceMeshes: Int32Array, instanceMatrices: Float32Array, instanceNodes: Int32Array, instanceGroups: Int32Array, instanceTags: BigInt64Array, instanceFlags: Uint16Array, instanceMins: Float32Array, instanceMaxs: Float32Array, meshChunks: Int32Array, meshChunkIndices: Int32Array, meshInstanceCounts: Int32Array, meshIndexCounts: Int32Array, meshVertexCounts: Int32Array, meshOpaqueIndexCounts: Int32Array, meshOpaqueVertexCounts: Int32Array); static createFromBfast(bfast: BFast): Promise; - getMeshSceneInstance(mesh: number, meshIndex: number): number; getMeshCount(): number; getMeshIndexCount(mesh: number, section: MeshSection): number; getMeshVertexCount(mesh: number, section: MeshSection): number; getMeshInstanceCount(mesh: number): number; - getNodeMin(node: number): Float32Array; - getNodeMax(node: number): Float32Array; getInstanceMin(instance: number): Float32Array; getInstanceMax(instance: number): Float32Array; + getInstanceMatrix(instance: number): Float32Array; } diff --git a/src/ts/package.json b/src/ts/package.json index b727f2dd..6ddb8c21 100644 --- a/src/ts/package.json +++ b/src/ts/package.json @@ -1,6 +1,6 @@ { "name": "vim-format", - "version": "1.0.6-dev.221", + "version": "1.0.6-dev.229", "description": "The VIM format is a modern and efficient open 3D data interchange format designed for BIM and manufacturing data optimized for efficient loading and rendering on low-power devices.", "directories": { "test": "tests" diff --git a/src/ts/src/abstractG3d.ts b/src/ts/src/abstractG3d.ts deleted file mode 100644 index ec3dd895..00000000 --- a/src/ts/src/abstractG3d.ts +++ /dev/null @@ -1,43 +0,0 @@ - -import { G3dAttribute, G3dAttributeDescriptor } from './g3dAttributes' -import { BFast } from './bfast' - -/** - * G3D is a simple, efficient, generic binary format for storing and transmitting geometry. - * The G3D format is designed to be used either as a serialization format or as an in-memory data structure. - * See https://github.com/vimaec/g3d - */ -export class AbstractG3d { - meta: string - attributes: G3dAttribute[] - - constructor (meta: string, attributes: G3dAttribute[]) { - this.meta = meta - this.attributes = attributes - } - - findAttribute (descriptor: string): G3dAttribute | undefined { - const filter = G3dAttributeDescriptor.fromString(descriptor) - for (let i = 0; i < this.attributes.length; ++i) { - const attribute = this.attributes[i] - if (attribute.descriptor.matches(filter)) return attribute - } - } - - /** - * Create g3d from bfast by requesting all necessary buffers individually. - */ - static async createFromBfast (bfast: BFast, names: string[]) { - - const attributes = await Promise.all(names.map(async (a) => { - const bytes = await bfast.getBytes(a) - if(!bytes) return - const decriptor = G3dAttributeDescriptor.fromString(a) - return new G3dAttribute(decriptor, bytes) - })) - - const validAttributes = attributes.filter((a): a is G3dAttribute => a !== undefined) - const g3d = new AbstractG3d('meta', validAttributes) - return g3d - } -} diff --git a/src/ts/src/bfast.ts b/src/ts/src/bfast.ts index ff8d5d3b..092f5431 100644 --- a/src/ts/src/bfast.ts +++ b/src/ts/src/bfast.ts @@ -298,6 +298,30 @@ export function parseName(name: string): [number, NumericArrayConstructor]{ return array } + async getInt32Array(name: string): Promise { + const buffer = await this.getBuffer(name) + if(!buffer) return + return new Int32Array(buffer) + } + + async getFloat32Array(name: string): Promise { + const buffer = await this.getBuffer(name) + if(!buffer) return + return new Float32Array(buffer) + } + + async getBigInt64Array(name: string): Promise { + const buffer = await this.getBuffer(name) + if(!buffer) return + return new BigInt64Array(buffer) + } + + async getUint16Array(name: string): Promise { + const buffer = await this.getBuffer(name) + if(!buffer) return + return new Uint16Array(buffer) + } + /** * Returns a single value from given buffer name * @param name buffer name diff --git a/src/ts/src/g3d.ts b/src/ts/src/g3d.ts index 8b7dbdc1..07ed9c63 100644 --- a/src/ts/src/g3d.ts +++ b/src/ts/src/g3d.ts @@ -2,7 +2,6 @@ * @module vim-ts */ -import { AbstractG3d } from './abstractG3d' import { BFast } from './bfast' export type MeshSection = 'opaque' | 'transparent' | 'all' @@ -63,9 +62,6 @@ export class G3d { submeshVertexStart: Int32Array submeshVertexEnd: Int32Array - - rawG3d: AbstractG3d - static MATRIX_SIZE = 16 static COLOR_SIZE = 4 static POSITION_SIZE = 3 @@ -138,58 +134,6 @@ export class G3d { return {start, end} } - static createFromAbstract(g3d: AbstractG3d) { - - const instanceMeshes = g3d.findAttribute(VimAttributes.instanceMeshes) - ?.data as Int32Array - - const instanceTransforms = g3d.findAttribute( - VimAttributes.instanceTransforms - )?.data as Float32Array - - const instanceFlags = - (g3d.findAttribute(VimAttributes.instanceFlags)?.data as Uint16Array) ?? - new Uint16Array(instanceMeshes.length) - - const instanceNodes = g3d.findAttribute( - VimAttributes.instanceNodes - )?.data as Int32Array - - const meshSubmeshes = g3d.findAttribute(VimAttributes.meshSubmeshes) - ?.data as Int32Array - - const submeshIndexOffset = g3d.findAttribute( - VimAttributes.submeshIndexOffsets - )?.data as Int32Array - - const submeshMaterial = g3d.findAttribute(VimAttributes.submeshMaterials) - ?.data as Int32Array - - const indices = g3d.findAttribute(VimAttributes.indices)?.data as Int32Array - - const positions = g3d.findAttribute(VimAttributes.positions) - ?.data as Float32Array - - const materialColors = g3d.findAttribute(VimAttributes.materialColors) - ?.data as Float32Array - - const result = new G3d( - instanceMeshes, - instanceFlags, - instanceTransforms, - instanceNodes, - meshSubmeshes, - submeshIndexOffset, - submeshMaterial, - indices, - positions, - materialColors - ) - result.rawG3d = g3d - - return result - } - static async createFromPath (path: string) { const f = await fetch(path) const buffer = await f.arrayBuffer() @@ -198,8 +142,20 @@ export class G3d { } static async createFromBfast (bfast: BFast) { - const g3d = await AbstractG3d.createFromBfast(bfast, VimAttributes.all) - return G3d.createFromAbstract(g3d) + + const values = await Promise.all([ + bfast.getInt32Array(VimAttributes.instanceMeshes), + bfast.getUint16Array(VimAttributes.instanceFlags), + bfast.getFloat32Array(VimAttributes.instanceTransforms), + bfast.getInt32Array(VimAttributes.instanceNodes), + bfast.getInt32Array(VimAttributes.meshSubmeshes), + bfast.getInt32Array(VimAttributes.submeshIndexOffsets), + bfast.getInt32Array(VimAttributes.submeshMaterials), + bfast.getInt32Array(VimAttributes.indices), + bfast.getFloat32Array(VimAttributes.positions), + bfast.getFloat32Array(VimAttributes.materialColors) + ]) + return new G3d(...values) } /** diff --git a/src/ts/src/g3dAttributes.ts b/src/ts/src/g3dAttributes.ts deleted file mode 100644 index 1cb57653..00000000 --- a/src/ts/src/g3dAttributes.ts +++ /dev/null @@ -1,144 +0,0 @@ - -export class G3dAttributeDescriptor { - // original descriptor string - description: string - // Indicates the part of the geometry that this attribute is associated with - association: string - // the role of the attribute - semantic: string - // each attribute type should have it's own index ( you can have uv0, uv1, etc. ) - attributeTypeIndex: string - // the type of individual values (e.g. int32, float64) - dataType: string - // how many values associated with each element (e.g. UVs might be 2, geometry might be 3, quaternions 4, matrices 9 or 16) - dataArity: number - - constructor ( - description: string, - association: string, - semantic: string, - attributeTypeIndex: string, - dataType: string, - dataArity: string - ) { - if (!description.startsWith('g3d:')) { - throw new Error(`${description} must start with 'g3d'`) - } - - this.description = description - this.association = association - this.semantic = semantic - this.attributeTypeIndex = attributeTypeIndex - this.dataType = dataType - this.dataArity = parseInt(dataArity) - } - - static fromString (descriptor: string): G3dAttributeDescriptor { - const desc = descriptor.split(':') - - if (desc.length !== 6) { - throw new Error(`${descriptor}, must have 6 components delimited by ':'`) - } - - return new this(descriptor, desc[1], desc[2], desc[3], desc[4], desc[5]) - } - - matches (other: G3dAttributeDescriptor) { - const match = (a: string, b: string) => a === '*' || b === '*' || a === b - - return ( - match(this.association, other.association) && - match(this.semantic, other.semantic) && - match(this.attributeTypeIndex, other.attributeTypeIndex) && - match(this.dataType, other.dataType) - ) - } -} - - -export type TypedArray = - | Uint8Array - | Int16Array - | Uint16Array - | Int32Array - | Uint32Array - | Float32Array - | Uint32Array - | BigUint64Array - | BigInt64Array - | Float64Array - -export class G3dAttribute { - descriptor: G3dAttributeDescriptor - bytes: Uint8Array - data: TypedArray | undefined - - constructor (descriptor: G3dAttributeDescriptor, bytes: Uint8Array) { - this.descriptor = descriptor - this.bytes = bytes - this.data = G3dAttribute.castData(bytes, descriptor.dataType) - } - - static fromString (descriptor: string, buffer: Uint8Array): G3dAttribute { - return new this(G3dAttributeDescriptor.fromString(descriptor), buffer) - } - - // Converts a VIM attribute into a typed array from its raw data - static castData (bytes: Uint8Array, dataType: string): TypedArray | undefined { - switch (dataType) { - case 'float32': - return new Float32Array( - bytes.buffer, - bytes.byteOffset, - bytes.byteLength / 4 - ) - case 'float64': - throw new Float64Array( - bytes.buffer, - bytes.byteOffset, - bytes.byteLength / 8 - ) - case 'uint8': - case 'int8': - return bytes - case 'int16': - return new Int16Array( - bytes.buffer, - bytes.byteOffset, - bytes.byteLength / 2 - ) - case 'uint16': - return new Uint16Array( - bytes.buffer, - bytes.byteOffset, - bytes.byteLength / 2 - ) - case 'int32': - return new Int32Array( - bytes.buffer, - bytes.byteOffset, - bytes.byteLength / 4 - ) - case 'uint32': - return new Uint32Array( - bytes.buffer, - bytes.byteOffset, - bytes.byteLength / 4 - ) - case 'int64': - return new BigInt64Array( - bytes.buffer, - bytes.byteOffset, - bytes.byteLength / 8 - ) - case 'uint64': - return new BigUint64Array( - bytes.buffer, - bytes.byteOffset, - bytes.byteLength / 8 - ) - default: - console.error('Unrecognized attribute data type ' + dataType) - } - } -} diff --git a/src/ts/src/g3dMaterials.ts b/src/ts/src/g3dMaterials.ts index 3d77ebee..ebc5524f 100644 --- a/src/ts/src/g3dMaterials.ts +++ b/src/ts/src/g3dMaterials.ts @@ -2,7 +2,6 @@ * @module vim-ts */ -import { AbstractG3d } from './abstractG3d' import { BFast } from './bfast' /** @@ -10,10 +9,6 @@ import { BFast } from './bfast' */ export class MaterialAttributes { static materialColors = 'g3d:material:color:0:float32:4' - - static all = [ - MaterialAttributes.materialColors - ] } /** @@ -24,56 +19,18 @@ export class MaterialAttributes { * See https://github.com/vimaec/g3d for the g3d specification. */ export class G3dMaterial { - - static COLOR_SIZE = 4 - - rawG3d: AbstractG3d + static readonly COLOR_SIZE = 4 + static readonly DEFAULT_COLOR = new Float32Array([1, 1, 1, 1]) materialColors: Float32Array - DEFAULT_COLOR = new Float32Array([1, 1, 1, 1]) - constructor( - - materialColors: Float32Array){ + constructor(materialColors: Float32Array){ this.materialColors = materialColors } - static createFromAbstract(g3d: AbstractG3d) { - - const materialColors = g3d.findAttribute(MaterialAttributes.materialColors) - ?.data as Float32Array - - const result = new G3dMaterial( - - materialColors - ) - result.rawG3d = g3d - - return result - } - - static async createFromPath (path: string) { - const f = await fetch(path) - const buffer = await f.arrayBuffer() - var g3d = this.createFromBuffer(buffer) - - return g3d - } - - static async createFromBuffer (buffer: ArrayBuffer) { - const bfast = new BFast(buffer) - return this.createFromBfast(bfast) - } - static async createFromBfast (bfast: BFast) { - const g3d = await AbstractG3d.createFromBfast(bfast, MaterialAttributes.all) - return G3dMaterial.createFromAbstract(g3d) - } - - toG3d(){ - return new G3dMaterial( - this.materialColors - ) + const mats = await bfast.getFloat32Array(MaterialAttributes.materialColors) + return new G3dMaterial(mats) } getMaterialCount = () => this.materialColors.length / G3dMaterial.COLOR_SIZE @@ -83,7 +40,7 @@ export class G3dMaterial { * @param material g3d material index */ getMaterialColor (material: number): Float32Array { - if (material < 0) return this.DEFAULT_COLOR + if (material < 0) return G3dMaterial.DEFAULT_COLOR return this.materialColors.subarray( material * G3dMaterial.COLOR_SIZE, (material + 1) * G3dMaterial.COLOR_SIZE diff --git a/src/ts/src/g3dMesh.ts b/src/ts/src/g3dMesh.ts index 1986c0ad..1d349282 100644 --- a/src/ts/src/g3dMesh.ts +++ b/src/ts/src/g3dMesh.ts @@ -2,10 +2,8 @@ * @module vim-ts */ -import { AbstractG3d } from './abstractG3d' import { BFast } from './bfast' import { G3d, MeshSection } from './g3d' -import { G3dMaterial } from './g3dMaterials' import { G3dScene } from './g3dScene' /** @@ -13,7 +11,6 @@ import { G3dScene } from './g3dScene' */ export class MeshAttributes { - static instanceTransforms = 'g3d:instance:transform:0:float32:16' static meshOpaqueSubmeshCount = 'g3d:mesh:opaquesubmeshcount:0:int32:1' static submeshIndexOffsets = 'g3d:submesh:indexoffset:0:int32:1' static submeshVertexOffsets = 'g3d:submesh:vertexoffset:0:int32:1' @@ -22,7 +19,6 @@ export class MeshAttributes { static indices = 'g3d:corner:index:0:int32:1' static all = [ - MeshAttributes.instanceTransforms, MeshAttributes.meshOpaqueSubmeshCount, MeshAttributes.submeshIndexOffsets, MeshAttributes.submeshVertexOffsets, @@ -43,30 +39,22 @@ export class G3dMesh { scene: G3dScene meshIndex: number + readonly meshOpaqueSubmeshCount : number + readonly submeshIndexOffset: Int32Array + readonly submeshVertexOffset: Int32Array + readonly submeshMaterial: Int32Array - rawG3d: AbstractG3d + readonly positions: Float32Array + readonly indices: Uint32Array - instanceTransforms: Float32Array - - meshOpaqueSubmeshCount : number - - submeshIndexOffset: Int32Array - submeshVertexOffset: Int32Array - submeshMaterial: Int32Array - - positions: Float32Array - indices: Uint32Array - - static MATRIX_SIZE = 16 - static COLOR_SIZE = 4 - static POSITION_SIZE = 3 + static readonly COLOR_SIZE = 4 + static readonly POSITION_SIZE = 3 /** * Opaque white */ - DEFAULT_COLOR = new Float32Array([1, 1, 1, 1]) + static readonly DEFAULT_COLOR = new Float32Array([1, 1, 1, 1]) constructor( - instanceTransforms: Float32Array, meshOpaqueSubmeshCount : number, submeshIndexOffsets : Int32Array, submeshVertexOffsets : Int32Array, @@ -75,7 +63,6 @@ export class G3dMesh { positions: Float32Array, ){ - this.instanceTransforms = instanceTransforms this.meshOpaqueSubmeshCount = meshOpaqueSubmeshCount this.submeshIndexOffset = submeshIndexOffsets this.submeshVertexOffset = submeshVertexOffsets @@ -84,108 +71,17 @@ export class G3dMesh { this.positions = positions } - static createFromAbstract(g3d: AbstractG3d) { - - const instanceTransforms = g3d.findAttribute( - MeshAttributes.instanceTransforms - )?.data as Float32Array - - const meshOpaqueSubmeshCountArray = g3d.findAttribute( - MeshAttributes.meshOpaqueSubmeshCount - )?.data as Int32Array - const meshOpaqueSubmeshCount = meshOpaqueSubmeshCountArray[0] - - const submeshIndexOffsets = g3d.findAttribute( - MeshAttributes.submeshIndexOffsets - )?.data as Int32Array - - const submeshVertexOffsets = g3d.findAttribute( - MeshAttributes.submeshVertexOffsets - )?.data as Int32Array - - const submeshMaterial = g3d.findAttribute(MeshAttributes.submeshMaterials) - ?.data as Int32Array - - const indices = g3d.findAttribute(MeshAttributes.indices)?.data as Int32Array - - const positions = g3d.findAttribute(MeshAttributes.positions) - ?.data as Float32Array - - const result = new G3dMesh( - instanceTransforms, - meshOpaqueSubmeshCount, - submeshIndexOffsets, - submeshVertexOffsets, - submeshMaterial, - indices, - positions, - ) - result.rawG3d = g3d - - return result - } - - static async createFromPath (path: string) { - const f = await fetch(path) - const buffer = await f.arrayBuffer() - var g3d = this.createFromBuffer(buffer) - - return g3d - } - - static async createFromBuffer (buffer: ArrayBuffer) { - const bfast = new BFast(buffer) - return this.createFromBfast(bfast) - } - static async createFromBfast (bfast: BFast) { - const g3d = await AbstractG3d.createFromBfast(bfast, MeshAttributes.all) - return G3dMesh.createFromAbstract(g3d) - } - - // -----------Instances--------------- - - getBimInstance(meshInstance: number){ - const sceneInstance = this.scene.getMeshSceneInstance(this.meshIndex, meshInstance) - return this.scene.instanceNodes[sceneInstance] - } - - getInstanceMax(meshInstance: number){ - const sceneInstance = this.scene.getMeshSceneInstance(this.meshIndex, meshInstance) - return this.scene.instanceMaxs.subarray(sceneInstance * 3, (sceneInstance +1) * 3) - } - - getInstanceMin(meshInstance: number){ - const sceneInstance = this.scene.getMeshSceneInstance(this.meshIndex, meshInstance) - return this.scene.instanceMins.subarray(sceneInstance * 3, (sceneInstance +1) * 3) - } - - getInstanceGroup(meshInstance: number){ - const sceneInstance = this.scene.getMeshSceneInstance(this.meshIndex, meshInstance) - return this.scene.instanceGroups[sceneInstance] - } - - getInstanceTag(meshInstance: number){ - const sceneInstance = this.scene.getMeshSceneInstance(this.meshIndex, meshInstance) - return this.scene.instanceTags[sceneInstance] - } - - getInstanceHasFlag(meshInstance: number, flag: number){ - const sceneInstance = this.scene.getMeshSceneInstance(this.meshIndex, meshInstance) - return (this.scene.instanceFlags[sceneInstance] & flag) > 0 - } - - getInstanceCount = () => this.instanceTransforms.length - - /** - * Returns an 16 number array representation of the matrix for given instance - * @param instance g3d instance index - */ - getInstanceMatrix (instance: number): Float32Array { - return this.instanceTransforms.subarray( - instance * G3dMesh.MATRIX_SIZE, - (instance + 1) * G3dMesh.MATRIX_SIZE - ) + const values = await Promise.all([ + bfast.getValue(MeshAttributes.meshOpaqueSubmeshCount, 0).then(v => v as number), + bfast.getInt32Array(MeshAttributes.submeshIndexOffsets), + bfast.getInt32Array(MeshAttributes.submeshVertexOffsets), + bfast.getInt32Array(MeshAttributes.submeshMaterials), + bfast.getInt32Array(MeshAttributes.indices), + bfast.getFloat32Array(MeshAttributes.positions) + ]) + + return new G3dMesh(...values) } // ------------- Mesh ----------------- diff --git a/src/ts/src/g3dScene.ts b/src/ts/src/g3dScene.ts index 8ed3c1a6..1a959d18 100644 --- a/src/ts/src/g3dScene.ts +++ b/src/ts/src/g3dScene.ts @@ -2,7 +2,6 @@ * @module vim-ts */ -import { AbstractG3d } from './abstractG3d' import { BFast } from './bfast' import { G3d, MeshSection } from './g3d' @@ -13,46 +12,25 @@ export type FilterMode = undefined | 'mesh' | 'instance' | 'group' | 'tag' */ export class SceneAttributes { - static chunkCount = 'g3d:chunk:count:0:int32:1' - static instanceMesh = 'g3d:instance:mesh:0:int32:1' - static instanceTransform = 'g3d:instance:transform:0:int32:1' - static instanceNodes = 'g3d:instance:node:0:int32:1' - static instanceGroups = 'g3d:instance:group:0:int32:1' - static instanceTags = 'g3d:instance:tag:0:int64:1' - static instanceFlags = 'g3d:instance:tag:0:uint16:1' - static instanceMins = 'g3d:instance:min:0:float32:3' - static instanceMaxs = 'g3d:instance:max:0:float32:3' - - - static meshChunk = 'g3d:mesh:chunk:0:int32:1' - static meshChunkIndices = 'g3d:mesh:chunkindex:0:int32:1'; - static meshInstanceCounts = 'g3d:mesh:instancecount:0:int32:1' - static meshIndexCounts = 'g3d:mesh:indexcount:0:int32:1' - static meshVertexCounts = 'g3d:mesh:vertexcount:0:int32:1' - - static meshOpaqueIndexCount = "g3d:mesh:opaqueindexcount:0:int32:1" - static meshOpaqueVertexCount = "g3d:mesh:opaquevertexcount:0:int32:1" - - static all = [ - SceneAttributes.chunkCount, - SceneAttributes.instanceMesh, - SceneAttributes.instanceTransform, - SceneAttributes.instanceNodes, - SceneAttributes.instanceGroups, - SceneAttributes.instanceTags, - SceneAttributes.instanceFlags, - SceneAttributes.instanceMins, - SceneAttributes.instanceMaxs, - - SceneAttributes.meshChunk, - SceneAttributes.meshChunkIndices, - SceneAttributes.meshInstanceCounts, - SceneAttributes.meshIndexCounts, - SceneAttributes.meshVertexCounts, - - SceneAttributes.meshOpaqueIndexCount, - SceneAttributes.meshOpaqueVertexCount, - ] + static readonly chunkCount = 'g3d:chunk:count:0:int32:1' + static readonly instanceMesh = 'g3d:instance:mesh:0:int32:1' + static readonly instanceMatrix = 'g3d:instance:transform:0:float32:16' + static readonly instanceNodes = 'g3d:instance:node:0:int32:1' + static readonly instanceGroups = 'g3d:instance:group:0:int32:1' + static readonly instanceTags = 'g3d:instance:tag:0:int64:1' + static readonly instanceFlags = 'g3d:instance:tag:0:uint16:1' + static readonly instanceMins = 'g3d:instance:min:0:float32:3' + static readonly instanceMaxs = 'g3d:instance:max:0:float32:3' + + + static readonly meshChunk = 'g3d:mesh:chunk:0:int32:1' + static readonly meshChunkIndices = 'g3d:mesh:chunkindex:0:int32:1'; + static readonly meshInstanceCounts = 'g3d:mesh:instancecount:0:int32:1' + static readonly meshIndexCounts = 'g3d:mesh:indexcount:0:int32:1' + static readonly meshVertexCounts = 'g3d:mesh:vertexcount:0:int32:1' + + static readonly meshOpaqueIndexCount = "g3d:mesh:opaqueindexcount:0:int32:1" + static readonly meshOpaqueVertexCount = "g3d:mesh:opaquevertexcount:0:int32:1" } /** @@ -61,11 +39,9 @@ export class SceneAttributes { * Allows to preallocate geometry to render G3dMeshes. */ export class G3dScene { - rawG3d: AbstractG3d - chunkCount: number instanceMeshes: Int32Array - instanceTransforms: Int32Array + instanceMatrices: Float32Array instanceNodes: Int32Array instanceGroups: Int32Array instanceTags : BigInt64Array @@ -83,14 +59,11 @@ export class G3dScene { meshOpaqueVertexCounts: Int32Array private nodeToInstance : Map - private meshSceneInstances: Map> constructor( - rawG3d: AbstractG3d, - chunkCount: Int32Array, instanceMeshes: Int32Array, - instanceTransform: Int32Array, + instanceMatrices: Float32Array, instanceNodes: Int32Array, instanceGroups: Int32Array, instanceTags: BigInt64Array, @@ -107,12 +80,9 @@ export class G3dScene { meshOpaqueIndexCounts: Int32Array, meshOpaqueVertexCounts: Int32Array, ){ - - this.rawG3d = rawG3d - this.chunkCount = chunkCount[0] this.instanceMeshes = instanceMeshes - this.instanceTransforms = instanceTransform + this.instanceMatrices = instanceMatrices this.instanceNodes = instanceNodes this.instanceGroups = instanceGroups this.instanceTags = instanceTags @@ -133,67 +103,30 @@ export class G3dScene { for(let i = 0; i < this.instanceNodes.length; i ++){ this.nodeToInstance.set(this.instanceNodes[i], i) } - this.meshSceneInstances = this.createMap() - } - - private createMap(){ - // From : (mesh, scene-index) -> mesh-index - // To: (mesh, mesh-index) -> scene-index - const map = new Map>() - for(let i =0; i < this.instanceMeshes.length; i++){ - const mesh = this.instanceMeshes[i] - const index = this.instanceTransforms[i] - const indices = map.get(mesh) ?? new Map() - indices.set(index, i) - map.set(mesh, indices) - } - return map } - static createFromAbstract(g3d: AbstractG3d) { - - function getArray(attribute: string){ - return g3d.findAttribute( - attribute - )?.data as T - } - - return new G3dScene( - g3d, - getArray(SceneAttributes.chunkCount), - getArray(SceneAttributes.instanceMesh), - getArray(SceneAttributes.instanceTransform), - getArray(SceneAttributes.instanceNodes), - getArray(SceneAttributes.instanceGroups), - getArray(SceneAttributes.instanceTags), - getArray(SceneAttributes.instanceFlags), - getArray(SceneAttributes.instanceMins), - getArray(SceneAttributes.instanceMaxs), - - getArray(SceneAttributes.meshChunk), - getArray(SceneAttributes.meshChunkIndices), - getArray(SceneAttributes.meshInstanceCounts), - getArray(SceneAttributes.meshIndexCounts), - getArray(SceneAttributes.meshVertexCounts), - getArray(SceneAttributes.meshOpaqueIndexCount), - getArray(SceneAttributes.meshOpaqueVertexCount), - ) - } - - static async createFromPath (path: string) { - const f = await fetch(path) - const buffer = await f.arrayBuffer() - const bfast = new BFast(buffer) - return this.createFromBfast(bfast) - } - static async createFromBfast (bfast: BFast) { - const g3d = await AbstractG3d.createFromBfast(bfast, SceneAttributes.all) - return G3dScene.createFromAbstract(g3d) - } - getMeshSceneInstance(mesh: number, meshIndex: number){ - return this.meshSceneInstances.get(mesh)?.get(meshIndex) + const values = await Promise.all([ + bfast.getInt32Array(SceneAttributes.chunkCount), + bfast.getInt32Array(SceneAttributes.instanceMesh), + bfast.getFloat32Array(SceneAttributes.instanceMatrix), + bfast.getInt32Array(SceneAttributes.instanceNodes), + bfast.getInt32Array(SceneAttributes.instanceGroups), + bfast.getBigInt64Array(SceneAttributes.instanceTags), + bfast.getUint16Array(SceneAttributes.instanceFlags), + bfast.getFloat32Array(SceneAttributes.instanceMins), + bfast.getFloat32Array(SceneAttributes.instanceMaxs), + + bfast.getInt32Array(SceneAttributes.meshChunk), + bfast.getInt32Array(SceneAttributes.meshChunkIndices), + bfast.getInt32Array(SceneAttributes.meshInstanceCounts), + bfast.getInt32Array(SceneAttributes.meshIndexCounts), + bfast.getInt32Array(SceneAttributes.meshVertexCounts), + bfast.getInt32Array(SceneAttributes.meshOpaqueIndexCount), + bfast.getInt32Array(SceneAttributes.meshOpaqueVertexCount), + ]) + return new G3dScene(...values) } getMeshCount() { @@ -218,22 +151,6 @@ export class G3dScene { return this.meshInstanceCounts[mesh] } - getNodeMin(node: number){ - const instance = this.nodeToInstance.get(node) - if(!instance){ - return undefined - } - return this.getInstanceMin(instance) - } - - getNodeMax(node: number){ - const instance = this.nodeToInstance.get(node) - if(!instance){ - return undefined - } - return this.getInstanceMax(instance) - } - getInstanceMin(instance: number){ return this.instanceMins.subarray(instance * G3d.POSITION_SIZE) } @@ -242,4 +159,8 @@ export class G3dScene { return this.instanceMaxs.subarray(instance * G3d.POSITION_SIZE) } + getInstanceMatrix(instance: number){ + return this.instanceMatrices.subarray(instance * G3d.MATRIX_SIZE, (instance + 1)* G3d.MATRIX_SIZE) + } + } From 78d010c2087b71195aa9529c9d2950992c5aaefb Mon Sep 17 00:00:00 2001 From: simon Date: Mon, 18 Dec 2023 13:31:32 -0500 Subject: [PATCH 038/111] removed remoteg3d, removed meshInstanceCounts --- src/cs/g3d/Vim.G3d/Vim.G3d.csproj | 1 - .../Vim.G3dNext.Attributes/Attributes.g.cs | 114 ++-- .../Vim.G3dNext.Attributes/MeshAttributes.cs | 4 + .../Vim.G3dNext.Attributes/SceneAttributes.cs | 4 - .../MeshesToScene.cs | 2 - src/ts/dist/index.js | 2 - src/ts/package.json | 2 +- src/ts/src/g3dScene.ts | 11 +- src/ts/src/index.ts | 2 - src/ts/src/remoteG3d.ts | 529 ------------------ 10 files changed, 70 insertions(+), 601 deletions(-) delete mode 100644 src/ts/src/remoteG3d.ts diff --git a/src/cs/g3d/Vim.G3d/Vim.G3d.csproj b/src/cs/g3d/Vim.G3d/Vim.G3d.csproj index ead77bb8..7f4cdcb4 100644 --- a/src/cs/g3d/Vim.G3d/Vim.G3d.csproj +++ b/src/cs/g3d/Vim.G3d/Vim.G3d.csproj @@ -51,7 +51,6 @@ It can be easily and efficiently deserialized and rendered in different language - diff --git a/src/cs/g3d/Vim.G3dNext.Attributes/Attributes.g.cs b/src/cs/g3d/Vim.G3dNext.Attributes/Attributes.g.cs index 5822acfe..cae68120 100644 --- a/src/cs/g3d/Vim.G3dNext.Attributes/Attributes.g.cs +++ b/src/cs/g3d/Vim.G3dNext.Attributes/Attributes.g.cs @@ -1404,9 +1404,9 @@ public void Write(Stream stream) } } - public partial class SceneMeshInstanceCountsAttribute : IAttribute + public partial class SceneMeshVertexCountsAttribute : IAttribute { - public const string AttributeName = "g3d:mesh:instancecount:0:int32:1"; + public const string AttributeName = "g3d:mesh:vertexcount:0:int32:1"; public string Name => AttributeName; @@ -1423,7 +1423,7 @@ public void AddTo(BFast bfast) public void ReadBFast(BFast bfast) { - TypedData = bfast.GetArray("g3d:mesh:instancecount:0:int32:1"); + TypedData = bfast.GetArray("g3d:mesh:vertexcount:0:int32:1"); } public IAttributeDescriptor AttributeDescriptor { get; } @@ -1449,9 +1449,9 @@ public void Write(Stream stream) } } - public partial class SceneMeshVertexCountsAttribute : IAttribute + public partial class SceneMeshIndexCountsAttribute : IAttribute { - public const string AttributeName = "g3d:mesh:vertexcount:0:int32:1"; + public const string AttributeName = "g3d:mesh:indexcount:0:int32:1"; public string Name => AttributeName; @@ -1468,7 +1468,7 @@ public void AddTo(BFast bfast) public void ReadBFast(BFast bfast) { - TypedData = bfast.GetArray("g3d:mesh:vertexcount:0:int32:1"); + TypedData = bfast.GetArray("g3d:mesh:indexcount:0:int32:1"); } public IAttributeDescriptor AttributeDescriptor { get; } @@ -1494,9 +1494,9 @@ public void Write(Stream stream) } } - public partial class SceneMeshIndexCountsAttribute : IAttribute + public partial class SceneMeshOpaqueVertexCountsAttribute : IAttribute { - public const string AttributeName = "g3d:mesh:indexcount:0:int32:1"; + public const string AttributeName = "g3d:mesh:opaquevertexcount:0:int32:1"; public string Name => AttributeName; @@ -1513,7 +1513,7 @@ public void AddTo(BFast bfast) public void ReadBFast(BFast bfast) { - TypedData = bfast.GetArray("g3d:mesh:indexcount:0:int32:1"); + TypedData = bfast.GetArray("g3d:mesh:opaquevertexcount:0:int32:1"); } public IAttributeDescriptor AttributeDescriptor { get; } @@ -1539,9 +1539,9 @@ public void Write(Stream stream) } } - public partial class SceneMeshOpaqueVertexCountsAttribute : IAttribute + public partial class SceneMeshOpaqueIndexCountsAttribute : IAttribute { - public const string AttributeName = "g3d:mesh:opaquevertexcount:0:int32:1"; + public const string AttributeName = "g3d:mesh:opaqueindexcount:0:int32:1"; public string Name => AttributeName; @@ -1558,7 +1558,7 @@ public void AddTo(BFast bfast) public void ReadBFast(BFast bfast) { - TypedData = bfast.GetArray("g3d:mesh:opaquevertexcount:0:int32:1"); + TypedData = bfast.GetArray("g3d:mesh:opaqueindexcount:0:int32:1"); } public IAttributeDescriptor AttributeDescriptor { get; } @@ -1584,9 +1584,9 @@ public void Write(Stream stream) } } - public partial class SceneMeshOpaqueIndexCountsAttribute : IAttribute + public partial class MeshInstanceTransformsAttribute : IAttribute { - public const string AttributeName = "g3d:mesh:opaqueindexcount:0:int32:1"; + public const string AttributeName = "g3d:instance:transform:0:float32:16"; public string Name => AttributeName; @@ -1603,7 +1603,7 @@ public void AddTo(BFast bfast) public void ReadBFast(BFast bfast) { - TypedData = bfast.GetArray("g3d:mesh:opaqueindexcount:0:int32:1"); + TypedData = bfast.GetArray("g3d:instance:transform:0:float32:16"); } public IAttributeDescriptor AttributeDescriptor { get; } @@ -1615,8 +1615,8 @@ public void ReadBFast(BFast bfast) public Type IndexInto { get; } = null; - public System.Int32[] TypedData { get; set; } - = Array.Empty(); + public Vim.Math3d.Matrix4x4[] TypedData { get; set; } + = Array.Empty(); public Array Data => TypedData; @@ -1629,9 +1629,9 @@ public void Write(Stream stream) } } - public partial class MeshInstanceTransformsAttribute : IAttribute + public partial class MeshOpaqueSubmeshCountsAttribute : IAttribute { - public const string AttributeName = "g3d:instance:transform:0:float32:16"; + public const string AttributeName = "g3d:mesh:opaquesubmeshcount:0:int32:1"; public string Name => AttributeName; @@ -1648,7 +1648,7 @@ public void AddTo(BFast bfast) public void ReadBFast(BFast bfast) { - TypedData = bfast.GetArray("g3d:instance:transform:0:float32:16"); + TypedData = bfast.GetArray("g3d:mesh:opaquesubmeshcount:0:int32:1"); } public IAttributeDescriptor AttributeDescriptor { get; } @@ -1660,8 +1660,8 @@ public void ReadBFast(BFast bfast) public Type IndexInto { get; } = null; - public Vim.Math3d.Matrix4x4[] TypedData { get; set; } - = Array.Empty(); + public System.Int32[] TypedData { get; set; } + = Array.Empty(); public Array Data => TypedData; @@ -1674,9 +1674,9 @@ public void Write(Stream stream) } } - public partial class MeshOpaqueSubmeshCountsAttribute : IAttribute + public partial class MeshSubmeshOffsetAttribute : IAttribute { - public const string AttributeName = "g3d:mesh:opaquesubmeshcount:0:int32:1"; + public const string AttributeName = "g3d:mesh:submeshOffset:0:int32:1"; public string Name => AttributeName; @@ -1693,17 +1693,17 @@ public void AddTo(BFast bfast) public void ReadBFast(BFast bfast) { - TypedData = bfast.GetArray("g3d:mesh:opaquesubmeshcount:0:int32:1"); + TypedData = bfast.GetArray("g3d:mesh:submeshOffset:0:int32:1"); } public IAttributeDescriptor AttributeDescriptor { get; } = new AttributeDescriptor(AttributeName); public AttributeType AttributeType { get; } - = AttributeType.Data; + = AttributeType.Index; public Type IndexInto { get; } - = null; + = typeof(Vim.G3dNext.Attributes.MeshIndicesAttribute); public System.Int32[] TypedData { get; set; } = Array.Empty(); @@ -2739,12 +2739,6 @@ public System.Int32[] MeshChunkIndices set => Attributes.MeshChunkIndices.TypedData = value; } - public System.Int32[] MeshInstanceCounts - { - get => Attributes.MeshInstanceCounts.TypedData; - set => Attributes.MeshInstanceCounts.TypedData = value; - } - public System.Int32[] MeshIndexCounts { get => Attributes.MeshIndexCounts.TypedData; @@ -2806,7 +2800,6 @@ public void ReadAttributes(BFast bfast) [Vim.G3dNext.Attributes.SceneInstanceMaxsAttribute.AttributeName] = new Vim.G3dNext.Attributes.SceneInstanceMaxsAttribute(), [Vim.G3dNext.Attributes.SceneMeshChunksAttribute.AttributeName] = new Vim.G3dNext.Attributes.SceneMeshChunksAttribute(), [Vim.G3dNext.Attributes.SceneMeshChunkIndicesAttribute.AttributeName] = new Vim.G3dNext.Attributes.SceneMeshChunkIndicesAttribute(), - [Vim.G3dNext.Attributes.SceneMeshInstanceCountsAttribute.AttributeName] = new Vim.G3dNext.Attributes.SceneMeshInstanceCountsAttribute(), [Vim.G3dNext.Attributes.SceneMeshIndexCountsAttribute.AttributeName] = new Vim.G3dNext.Attributes.SceneMeshIndexCountsAttribute(), [Vim.G3dNext.Attributes.SceneMeshVertexCountsAttribute.AttributeName] = new Vim.G3dNext.Attributes.SceneMeshVertexCountsAttribute(), [Vim.G3dNext.Attributes.SceneMeshOpaqueIndexCountsAttribute.AttributeName] = new Vim.G3dNext.Attributes.SceneMeshOpaqueIndexCountsAttribute(), @@ -2887,12 +2880,6 @@ public Vim.G3dNext.Attributes.SceneMeshChunkIndicesAttribute MeshChunkIndices set => Map[Vim.G3dNext.Attributes.SceneMeshChunkIndicesAttribute.AttributeName] = value as IAttribute; } - public Vim.G3dNext.Attributes.SceneMeshInstanceCountsAttribute MeshInstanceCounts - { - get => Map.TryGetValue(Vim.G3dNext.Attributes.SceneMeshInstanceCountsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.SceneMeshInstanceCountsAttribute : default; - set => Map[Vim.G3dNext.Attributes.SceneMeshInstanceCountsAttribute.AttributeName] = value as IAttribute; - } - public Vim.G3dNext.Attributes.SceneMeshIndexCountsAttribute MeshIndexCounts { get => Map.TryGetValue(Vim.G3dNext.Attributes.SceneMeshIndexCountsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.SceneMeshIndexCountsAttribute : default; @@ -2970,10 +2957,6 @@ public IAttribute GetAttribute(Type attributeType) return MeshChunkIndices; - if (attributeType == typeof(Vim.G3dNext.Attributes.SceneMeshInstanceCountsAttribute)) - return MeshInstanceCounts; - - if (attributeType == typeof(Vim.G3dNext.Attributes.SceneMeshIndexCountsAttribute)) return MeshIndexCounts; @@ -3070,12 +3053,6 @@ public IAttribute MergeAttribute(string attributeName, IReadOnlyList().ToArray().MergeDataAttributes(); } - case Vim.G3dNext.Attributes.SceneMeshInstanceCountsAttribute.AttributeName: - { - // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); - } - case Vim.G3dNext.Attributes.SceneMeshIndexCountsAttribute.AttributeName: { // Data Attribute @@ -3145,6 +3122,12 @@ public Vim.Math3d.Matrix4x4[] InstanceTransforms set => Attributes.InstanceTransforms.TypedData = value; } + public System.Int32[] SubmeshOffset + { + get => Attributes.SubmeshOffset.TypedData; + set => Attributes.SubmeshOffset.TypedData = value; + } + public System.Int32[] OpaqueSubmeshCounts { get => Attributes.OpaqueSubmeshCounts.TypedData; @@ -3207,6 +3190,7 @@ public void ReadAttributes(BFast bfast) = new Dictionary { [Vim.G3dNext.Attributes.MeshInstanceTransformsAttribute.AttributeName] = new Vim.G3dNext.Attributes.MeshInstanceTransformsAttribute(), + [Vim.G3dNext.Attributes.MeshSubmeshOffsetAttribute.AttributeName] = new Vim.G3dNext.Attributes.MeshSubmeshOffsetAttribute(), [Vim.G3dNext.Attributes.MeshOpaqueSubmeshCountsAttribute.AttributeName] = new Vim.G3dNext.Attributes.MeshOpaqueSubmeshCountsAttribute(), [Vim.G3dNext.Attributes.MeshSubmeshIndexOffsetsAttribute.AttributeName] = new Vim.G3dNext.Attributes.MeshSubmeshIndexOffsetsAttribute(), [Vim.G3dNext.Attributes.MeshSubmeshVertexOffsetsAttribute.AttributeName] = new Vim.G3dNext.Attributes.MeshSubmeshVertexOffsetsAttribute(), @@ -3223,6 +3207,12 @@ public Vim.G3dNext.Attributes.MeshInstanceTransformsAttribute InstanceTransforms set => Map[Vim.G3dNext.Attributes.MeshInstanceTransformsAttribute.AttributeName] = value as IAttribute; } + public Vim.G3dNext.Attributes.MeshSubmeshOffsetAttribute SubmeshOffset + { + get => Map.TryGetValue(Vim.G3dNext.Attributes.MeshSubmeshOffsetAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshSubmeshOffsetAttribute : default; + set => Map[Vim.G3dNext.Attributes.MeshSubmeshOffsetAttribute.AttributeName] = value as IAttribute; + } + public Vim.G3dNext.Attributes.MeshOpaqueSubmeshCountsAttribute OpaqueSubmeshCounts { get => Map.TryGetValue(Vim.G3dNext.Attributes.MeshOpaqueSubmeshCountsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshOpaqueSubmeshCountsAttribute : default; @@ -3268,6 +3258,10 @@ public IAttribute GetAttribute(Type attributeType) return InstanceTransforms; + if (attributeType == typeof(Vim.G3dNext.Attributes.MeshSubmeshOffsetAttribute)) + return SubmeshOffset; + + if (attributeType == typeof(Vim.G3dNext.Attributes.MeshOpaqueSubmeshCountsAttribute)) return OpaqueSubmeshCounts; @@ -3306,6 +3300,12 @@ public IAttribute MergeAttribute(string attributeName, IReadOnlyList().ToArray().MergeDataAttributes(); } + case Vim.G3dNext.Attributes.MeshSubmeshOffsetAttribute.AttributeName: + { + // Index Attribute + return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); + } + case Vim.G3dNext.Attributes.MeshOpaqueSubmeshCountsAttribute.AttributeName: { // Data Attribute @@ -3351,6 +3351,20 @@ public void Validate() { // Ensure all the indices are either -1 or within the bounds of the attributes they are indexing into. + { + var maxIndex = GetAttribute(SubmeshOffset.IndexInto).Data.Length - 1; + for (var i = 0; i < SubmeshOffset.TypedData.Length; ++i) + { + var index = SubmeshOffset.TypedData[i]; + + if (index == -1) + continue; // no relation. + + if (index < -1 || index > maxIndex) + throw new Exception($"Index out of range in Vim.G3dNext.Attributes.MeshSubmeshOffsetAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); + } + } + { var maxIndex = GetAttribute(SubmeshIndexOffsets.IndexInto).Data.Length - 1; for (var i = 0; i < SubmeshIndexOffsets.TypedData.Length; ++i) diff --git a/src/cs/g3d/Vim.G3dNext.Attributes/MeshAttributes.cs b/src/cs/g3d/Vim.G3dNext.Attributes/MeshAttributes.cs index c0dd4a66..0e7b94a5 100644 --- a/src/cs/g3d/Vim.G3dNext.Attributes/MeshAttributes.cs +++ b/src/cs/g3d/Vim.G3dNext.Attributes/MeshAttributes.cs @@ -4,6 +4,7 @@ namespace Vim.G3dNext.Attributes { [AttributeCollection( typeof(MeshInstanceTransformsAttribute), + typeof(MeshSubmeshOffsetAttribute), typeof(MeshOpaqueSubmeshCountsAttribute), typeof(MeshSubmeshIndexOffsetsAttribute), typeof(MeshSubmeshVertexOffsetsAttribute), @@ -22,6 +23,9 @@ public partial class MeshInstanceTransformsAttribute { } [AttributeDescriptor("Mesh", "g3d:mesh:opaquesubmeshcount:0:int32:1", AttributeType.Data)] public partial class MeshOpaqueSubmeshCountsAttribute { } + [AttributeDescriptor("Mesh", "g3d:mesh:submeshOffset:0:int32:1", AttributeType.Index, IndexInto = typeof(MeshIndicesAttribute))] + public partial class MeshSubmeshOffsetAttribute { } + [AttributeDescriptor("Mesh", "g3d:submesh:indexoffset:0:int32:1", AttributeType.Index, IndexInto = typeof(MeshIndicesAttribute))] public partial class MeshSubmeshIndexOffsetsAttribute { } diff --git a/src/cs/g3d/Vim.G3dNext.Attributes/SceneAttributes.cs b/src/cs/g3d/Vim.G3dNext.Attributes/SceneAttributes.cs index 88fcb2c7..2bfb592e 100644 --- a/src/cs/g3d/Vim.G3dNext.Attributes/SceneAttributes.cs +++ b/src/cs/g3d/Vim.G3dNext.Attributes/SceneAttributes.cs @@ -15,7 +15,6 @@ namespace Vim.G3dNext.Attributes typeof(SceneInstanceMaxsAttribute), typeof(SceneMeshChunksAttribute), typeof(SceneMeshChunkIndicesAttribute), - typeof(SceneMeshInstanceCountsAttribute), typeof(SceneMeshIndexCountsAttribute), typeof(SceneMeshVertexCountsAttribute), typeof(SceneMeshOpaqueIndexCountsAttribute), @@ -62,9 +61,6 @@ public partial class SceneMeshChunksAttribute { } [AttributeDescriptor("Scene", "g3d:mesh:chunkindex:0:int32:1", AttributeType.Data)] public partial class SceneMeshChunkIndicesAttribute { } - [AttributeDescriptor("Scene", "g3d:mesh:instancecount:0:int32:1", AttributeType.Data)] - public partial class SceneMeshInstanceCountsAttribute { } - [AttributeDescriptor("Scene", "g3d:mesh:vertexcount:0:int32:1", AttributeType.Data)] public partial class SceneMeshVertexCountsAttribute { } diff --git a/src/cs/vim/Vim.Format.Vimx.Conversion/MeshesToScene.cs b/src/cs/vim/Vim.Format.Vimx.Conversion/MeshesToScene.cs index db4fb722..74627b1d 100644 --- a/src/cs/vim/Vim.Format.Vimx.Conversion/MeshesToScene.cs +++ b/src/cs/vim/Vim.Format.Vimx.Conversion/MeshesToScene.cs @@ -35,7 +35,6 @@ public static G3dScene CreateScene(G3dVim g3d, DocumentModel bim, VimxChunk[] ch // meshes scene.MeshChunks = new int[meshes.Length]; scene.MeshChunkIndices = new int[meshes.Length]; - scene.MeshInstanceCounts = new int[meshes.Length]; scene.MeshIndexCounts = new int[meshes.Length]; scene.MeshVertexCounts = new int[meshes.Length]; scene.MeshOpaqueIndexCounts = new int[meshes.Length]; @@ -46,7 +45,6 @@ public static G3dScene CreateScene(G3dVim g3d, DocumentModel bim, VimxChunk[] ch var mesh = meshes[i]; scene.MeshChunks[i] = mesh.Chunk; scene.MeshChunkIndices[i] = mesh.ChunkIndex; - scene.MeshInstanceCounts[i] = mesh.GetInstanceCount(); scene.MeshIndexCounts[i] = mesh.GetIndexCount(); scene.MeshVertexCounts[i] = mesh.GetVertexCount(); scene.MeshOpaqueIndexCounts[i] = mesh.GetIndexCount(MeshSection.Opaque); diff --git a/src/ts/dist/index.js b/src/ts/dist/index.js index a922c8ef..d1133d3a 100644 --- a/src/ts/dist/index.js +++ b/src/ts/dist/index.js @@ -29,13 +29,11 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.VimHelpers = void 0; // Links files to generate package type exports __exportStar(require("./bfast"), exports); -__exportStar(require("./abstractG3d"), exports); __exportStar(require("./g3d"), exports); __exportStar(require("./remoteVimx"), exports); __exportStar(require("./g3dMaterials"), exports); __exportStar(require("./g3dMesh"), exports); __exportStar(require("./g3dScene"), exports); -__exportStar(require("./remoteG3d"), exports); __exportStar(require("./remoteBuffer"), exports); __exportStar(require("./requestTracker"), exports); __exportStar(require("./requester"), exports); diff --git a/src/ts/package.json b/src/ts/package.json index 6ddb8c21..9863b633 100644 --- a/src/ts/package.json +++ b/src/ts/package.json @@ -1,6 +1,6 @@ { "name": "vim-format", - "version": "1.0.6-dev.229", + "version": "1.0.6-dev.230", "description": "The VIM format is a modern and efficient open 3D data interchange format designed for BIM and manufacturing data optimized for efficient loading and rendering on low-power devices.", "directories": { "test": "tests" diff --git a/src/ts/src/g3dScene.ts b/src/ts/src/g3dScene.ts index 1a959d18..903f5e59 100644 --- a/src/ts/src/g3dScene.ts +++ b/src/ts/src/g3dScene.ts @@ -25,7 +25,6 @@ export class SceneAttributes { static readonly meshChunk = 'g3d:mesh:chunk:0:int32:1' static readonly meshChunkIndices = 'g3d:mesh:chunkindex:0:int32:1'; - static readonly meshInstanceCounts = 'g3d:mesh:instancecount:0:int32:1' static readonly meshIndexCounts = 'g3d:mesh:indexcount:0:int32:1' static readonly meshVertexCounts = 'g3d:mesh:vertexcount:0:int32:1' @@ -51,7 +50,6 @@ export class G3dScene { meshChunks : Int32Array meshChunkIndices : Int32Array - meshInstanceCounts: Int32Array meshIndexCounts: Int32Array meshVertexCounts: Int32Array @@ -73,7 +71,6 @@ export class G3dScene { meshChunks: Int32Array, meshChunkIndices : Int32Array, - meshInstanceCounts: Int32Array, meshIndexCounts : Int32Array, meshVertexCounts: Int32Array, @@ -92,7 +89,6 @@ export class G3dScene { this.meshChunks = meshChunks this.meshChunkIndices = meshChunkIndices - this.meshInstanceCounts = meshInstanceCounts this.meshIndexCounts = meshIndexCounts this.meshVertexCounts = meshVertexCounts this.meshOpaqueIndexCounts = meshOpaqueIndexCounts @@ -120,7 +116,6 @@ export class G3dScene { bfast.getInt32Array(SceneAttributes.meshChunk), bfast.getInt32Array(SceneAttributes.meshChunkIndices), - bfast.getInt32Array(SceneAttributes.meshInstanceCounts), bfast.getInt32Array(SceneAttributes.meshIndexCounts), bfast.getInt32Array(SceneAttributes.meshVertexCounts), bfast.getInt32Array(SceneAttributes.meshOpaqueIndexCount), @@ -130,7 +125,7 @@ export class G3dScene { } getMeshCount() { - return this.meshInstanceCounts.length + return this.meshChunks.length } getMeshIndexCount(mesh: number, section: MeshSection){ @@ -145,10 +140,6 @@ export class G3dScene { if(section === 'all') return all; const opaque = this.meshOpaqueVertexCounts[mesh] return section === 'opaque' ? opaque : all - opaque - } - - getMeshInstanceCount(mesh:number){ - return this.meshInstanceCounts[mesh] } getInstanceMin(instance: number){ diff --git a/src/ts/src/index.ts b/src/ts/src/index.ts index 8309f425..180f23c1 100644 --- a/src/ts/src/index.ts +++ b/src/ts/src/index.ts @@ -1,12 +1,10 @@ // Links files to generate package type exports export * from './bfast' -export * from './abstractG3d' export * from './g3d' export * from './remoteVimx' export * from './g3dMaterials' export * from './g3dMesh' export * from './g3dScene' -export * from './remoteG3d' export * from './remoteBuffer' export * from './requestTracker' export * from './requester' diff --git a/src/ts/src/remoteG3d.ts b/src/ts/src/remoteG3d.ts deleted file mode 100644 index 8478d9d0..00000000 --- a/src/ts/src/remoteG3d.ts +++ /dev/null @@ -1,529 +0,0 @@ -import { BFast, typeSize } from "./bfast" -import { G3d, VimAttributes } from "./g3d" -import { G3dAttribute, G3dAttributeDescriptor, TypedArray } from "./g3dAttributes" - -class G3dRemoteAttribute { - descriptor: G3dAttributeDescriptor - bfast: BFast - - constructor (descriptor: G3dAttributeDescriptor, bfast: BFast) { - this.descriptor = descriptor - this.bfast = bfast - } - - async getAll() { - const bytes = await this.bfast.getBytes(this.descriptor.description) - if(!bytes) return - - const data = G3dAttribute.castData(bytes, this.descriptor.dataType) - return data as T - } - - async getByte(index: number){ - return await this.bfast.getValue(this.descriptor.description, index) - } - - async getNumber(index: number): Promise { - return Number(await this.bfast.getValue(this.descriptor.description, index)) - } - - async getValue(index: number){ - const value = await this.bfast.getValues(this.descriptor.description, index * this.descriptor.dataArity, this.descriptor.dataArity) - return value as T - } - - async getValues(index: number, count: number){ - const value = await this.bfast.getValues(this.descriptor.description, index*this.descriptor.dataArity , count*this.descriptor.dataArity) - return value as T - } - - async getCount(){ - const range = await this.bfast.getRange(this.descriptor.description) - const count = range.length / (this.descriptor.dataArity * typeSize(this.descriptor.dataType)) - return count - } - - static fromString(description: string, bfast: BFast){ - return new G3dRemoteAttribute(G3dAttributeDescriptor.fromString(description), bfast) - } -} - -/** - * G3D is a simple, efficient, generic binary format for storing and transmitting geometry. - * The G3D format is designed to be used either as a serialization format or as an in-memory data structure. - * See https://github.com/vimaec/g3d - */ -export class RemoteAbstractG3d { - meta: string - attributes: G3dRemoteAttribute[] - - constructor (meta: string, attributes: G3dRemoteAttribute[]) { - this.meta = meta - this.attributes = attributes - } - - findAttribute (descriptor: string): G3dRemoteAttribute | undefined { - const filter = G3dAttributeDescriptor.fromString(descriptor) - for (let i = 0; i < this.attributes.length; ++i) { - const attribute = this.attributes[i] - if (attribute.descriptor.matches(filter)) return attribute - } - } - - /** - * Create g3d from bfast by requesting all necessary buffers individually. - */ - static createFromBfast (bfast: BFast) { - const attributes = VimAttributes.all.map((a) => G3dRemoteAttribute.fromString(a, bfast)) - return new RemoteAbstractG3d('meta', attributes) - } -} - -export class RemoteG3d { - rawG3d: RemoteAbstractG3d - - // attributes - positions: G3dRemoteAttribute - indices: G3dRemoteAttribute - - instanceMeshes: G3dRemoteAttribute - instanceTransforms: G3dRemoteAttribute - instanceFlags: G3dRemoteAttribute - meshSubmeshes: G3dRemoteAttribute - submeshIndexOffsets: G3dRemoteAttribute - submeshMaterials: G3dRemoteAttribute - materialColors: G3dRemoteAttribute - - constructor (g3d: RemoteAbstractG3d) { - this.rawG3d = g3d - - this.positions = g3d.findAttribute(VimAttributes.positions) - this.indices = g3d.findAttribute(VimAttributes.indices) - - this.meshSubmeshes = g3d.findAttribute(VimAttributes.meshSubmeshes) - this.submeshIndexOffsets = g3d.findAttribute( - VimAttributes.submeshIndexOffsets - ) - this.submeshMaterials = g3d.findAttribute(VimAttributes.submeshMaterials) - this.materialColors = g3d.findAttribute(VimAttributes.materialColors) - this.instanceMeshes = g3d.findAttribute(VimAttributes.instanceMeshes) - this.instanceTransforms = g3d.findAttribute( - VimAttributes.instanceTransforms - ) - this.instanceFlags = - g3d.findAttribute(VimAttributes.instanceFlags) - } - - static createFromBfast (bfast: BFast) { - const abstract = RemoteAbstractG3d.createFromBfast(bfast) - return new RemoteG3d(abstract) - } - - // ------------- All ----------------- - getVertexCount = () => this.positions.getCount() - - // ------------- Meshes ----------------- - getMeshCount = () => this.meshSubmeshes.getCount() - - getSubmeshCount = () => this.submeshIndexOffsets.getCount() - - async getMeshIndexStart (mesh: number) { - const sub = await this.getMeshSubmeshStart(mesh) - return this.getSubmeshIndexStart(sub) - } - - async getMeshIndexEnd (mesh: number) { - const sub = await this.getMeshSubmeshEnd(mesh) - return this.getSubmeshIndexEnd(sub - 1) - } - - async getMeshIndexCount (mesh: number) { - const start = await this.getMeshIndexStart(mesh) - const end = await this.getMeshIndexEnd(mesh) - return end - start - } - - async getMeshIndices(mesh:number){ - const start = await this.getMeshIndexStart(mesh) - const end = await this.getMeshIndexEnd(mesh) - const indices = await this.indices.getValues(start, end-start) - return new Uint32Array(indices.buffer) - } - - async getMeshSubmeshEnd (mesh: number) { - const meshCount = await this.getMeshCount() - const submeshCount = await this.getSubmeshCount() - return mesh + 1 < meshCount - ? await this.meshSubmeshes.getNumber(mesh + 1) - : submeshCount - } - - async getMeshSubmeshStart (mesh: number) { - return this.meshSubmeshes.getNumber(mesh) - } - - async getMeshSubmeshCount (mesh: number) { - const end = await this.getMeshSubmeshEnd(mesh) - const start = await this.getMeshSubmeshStart(mesh) - return end - start - } - - // // ------------- Submeshes ----------------- - - async getSubmeshIndexStart (submesh: number) { - const submeshCount = await this.submeshIndexOffsets.getCount() - return submesh < submeshCount - ? this.submeshIndexOffsets.getNumber(submesh) - : await this.indices.getCount() - } - - async getSubmeshIndexEnd (submesh: number) { - const submeshCount = await this.submeshIndexOffsets.getCount() - return submesh < submeshCount - 1 - ? this.submeshIndexOffsets.getNumber(submesh + 1) - : await this.indices.getCount() - } - - async getSubmeshIndexCount (submesh: number) { - const start = await this.getSubmeshIndexStart(submesh) - const end = await this.getSubmeshIndexEnd(submesh) - return end - start - } - - async toG3d(){ - - const attributes = await Promise.all([ - this.instanceMeshes.getAll(), - this.instanceFlags.getAll(), - this.instanceTransforms.getAll(), - Promise.resolve(undefined), - this.meshSubmeshes.getAll(), - this.submeshIndexOffsets.getAll(), - this.submeshMaterials.getAll(), - this.indices.getAll(), - this.positions.getAll(), - this.materialColors.getAll(), - ]) - - return new G3d(... attributes) - } - - async slice(instance: number){ - return this.filter([instance]) - } - - async filter(instances: number[]){ - - // Instances - const instanceData = await this.filterInstances(instances) - - // Meshes - const meshes = await this.filterMesh(instanceData.meshes) - if(!meshes.hasMeshes) return instanceData.toG3d() - - instanceData.remapMeshes(meshes.map) - - const [indiceCount, submeshCount] = await meshes.getAttributeCounts(this) - - let submeshes: SubmeshData - let materials : MaterialData - const A = async ()=>{ - submeshes = await this.filterSubmeshes(meshes, submeshCount) - materials = await this.filterMaterials(submeshes.materials) - } - - let vertices : VertexData - let positions : Float32Array - const B = async() => { - vertices = await this.filterIndices(meshes, indiceCount) - positions = await this.filterPositions(vertices, meshes) - } - - await Promise.all([A(), B()]) - - submeshes.remapMaterials(materials.map) - - return new G3d( - instanceData.meshes, - instanceData.flags, - instanceData.transforms, - instanceData.nodes, - meshes.submeshes, - submeshes.indexOffsets, - submeshes.materials, - vertices.indices, - positions, - materials.colors - ) - } - - private async filterInstances(instances: number[]){ - const instanceSet = new Set(instances) - const attributes = new InstanceData(instanceSet.size) - let instance_i = 0 - const instanceCount = await this.instanceMeshes.getCount() - const promises : Promise[] = [] - for(let i=0; i < instanceCount; i ++){ - if(!instanceSet.has(i)) continue - const current = instance_i - promises.push(this.instanceFlags.getNumber(i).then(v => attributes.flags[current] = v)) - promises.push(this.instanceMeshes.getNumber(i).then(v => attributes.meshes[current] = v)) - promises.push(this.instanceTransforms.getValue(i).then(v => attributes.transforms.set(v, current *16))) - attributes.nodes[current] = i - instance_i++ - } - await Promise.all(promises) - return attributes - } - - private async filterMesh(instanceMeshes: Int32Array ){ - - const meshes = new MeshData(instanceMeshes) - if(meshes.hasMeshes){ - meshes.originalCount = await this.meshSubmeshes.getCount() - - let last = -1 - let mesh_i = 0 - for(let i=0; i < meshes.originalCount; i++){ - if(!meshes.set.has(i)) continue - - const offset = mesh_i > 0 ? meshes.submeshes[mesh_i -1] : 0 - const lastCount = last < 0 ? 0 : await this.getMeshSubmeshCount(last) - meshes.submeshes[mesh_i] = lastCount + offset - meshes.map.set(i, mesh_i) - last = i - mesh_i++ - } - } - - return meshes - } - - private async filterSubmeshes(meshes: MeshData, submeshCount: number){ - - let submesh_i =0 - let submeshOffset = 0 - const submeshes = new SubmeshData(submeshCount) - - for(let mesh=0; mesh < meshes.originalCount; mesh ++){ - if(!meshes.set.has(mesh)) continue - - const subStart = await this.getMeshSubmeshStart(mesh) - const subEnd = await this.getMeshSubmeshEnd(mesh) - - const promises : Promise[] = [] - for(let j = subStart; j < subEnd ; j++){ - const current = submesh_i - promises.push( - this.submeshIndexOffsets.getNumber(subStart) - .then(start => this.submeshIndexOffsets.getNumber(j) - .then(v=> submeshes.indexOffsets[current] = v - start + submeshOffset) - ) - ) - promises.push(this.submeshMaterials.getNumber(j).then(v => submeshes.materials[current] = v)) - - submesh_i++ - } - await Promise.all(promises) - submeshOffset += await this.getMeshIndexCount(mesh) - } - return submeshes - } - - private async filterIndices(meshes: MeshData, indicesCount: number){ - - let indices_i = 0 - let mesh_i=0 - const result = new VertexData(meshes, indicesCount) - - for(let mesh=0; mesh < meshes.originalCount; mesh ++){ - if(!meshes.set.has(mesh)) continue - - const [indexStart, indexEnd] = await Promise.all([ - this.getMeshIndexStart(mesh), - this.getMeshIndexEnd(mesh) - ]) - - const indices = await this.indices.getValues(indexStart, indexEnd - indexStart) - result.indices.set(indices, indices_i) - - let min = Number.MAX_SAFE_INTEGER - let max = Number.MIN_SAFE_INTEGER - for(let i = 0; i < indices.length ; i++){ - min = Math.min(indices[i], min) - max = Math.max(indices[i] + 1, max) - } - - for(let i = 0; i < indices.length ; i++){ - result.indices[indices_i + i] = result.indices[indices_i + i] - min + result.positionCount - } - - result.meshVertexStart[mesh_i] = min - result.meshVertexEnd[mesh_i] = max - result.positionCount += max-min - if(mesh_i > 0){ - const previous = result.vertexOffsets[mesh_i -1] - const previousLength = result.meshVertexEnd[mesh_i-1] - result.meshVertexStart[mesh_i-1] - result.vertexOffsets[mesh_i] = previous + previousLength - } - - mesh_i++ - indices_i += indices.length - } - return result - } - - private async filterPositions(indices: VertexData, meshes : MeshData){ - - const _positions = new Float32Array(indices.positionCount * G3d.POSITION_SIZE) - const promises : Promise[] = [] - - let mesh_i = 0 - for(let mesh=0; mesh < meshes.originalCount; mesh ++){ - if(!meshes.set.has(mesh)) continue - - const vertexStart = indices.meshVertexStart[mesh_i] - const vertexEnd = indices.meshVertexEnd[mesh_i] - const current = mesh_i - - promises.push( - this.positions.getValues(vertexStart, vertexEnd - vertexStart) - .then(v => _positions.set(v, indices.vertexOffsets[current] * G3d.POSITION_SIZE)) - ) - - mesh_i ++ - } - await Promise.all(promises) - return _positions - } - - private async filterMaterials(submeshMaterials : Int32Array){ - // Material Colors - const materialCount = await this.materialColors.getCount() - - let color_i =0 - const materials = new MaterialData(submeshMaterials) - const promises : Promise[] = [] - for(let i =0; i < materialCount; i ++){ - if(materials.set.has(i)){ - materials.map.set(i, color_i) - const current = color_i - promises.push( - this.materialColors.getValue(i) - .then(c => materials.colors.set(c, current * G3d.COLOR_SIZE)) - ) - color_i ++ - } - } - await Promise.all(promises) - return materials - } -} - -class InstanceData{ - meshes : Int32Array - flags: Uint16Array - transforms : Float32Array - nodes : Int32Array - - constructor(count: number){ - this.meshes = new Int32Array(count) - this.flags = new Uint16Array(count) - this.transforms = new Float32Array(count * 16) - this.nodes = new Int32Array(count) - } - - remapMeshes(map: Map){ - for(let i = 0; i < this.meshes.length; i++){ - this.meshes[i] = map.get(this.meshes[i]) ?? -1 - } - } - - toG3d(){ - return new G3d( - this.meshes, - this.flags, - this.transforms, - this.nodes, - new Int32Array(), - new Int32Array(), - new Int32Array(), - new Uint32Array(), - new Float32Array(), - new Float32Array() - ) - } -} - -class MeshData{ - hasMeshes: boolean - submeshes : Int32Array - originalCount : number - map : Map - set : Set - - constructor(instanceMeshes: Int32Array){ - this.set = new Set(instanceMeshes) - this.set.delete(-1) - this.hasMeshes = this.set.size > 0 - this.submeshes = this.hasMeshes ? new Int32Array(this.set.size) : undefined - this.map = this.hasMeshes ? new Map() : undefined - } - - async getAttributeCounts(g3d: RemoteG3d){ - let submeshCount = 0 - let indiceCount = 0 - const promises : Promise[] = [] - for(let mesh=0; mesh < this.originalCount; mesh ++){ - if(!this.set.has(mesh)) continue - promises.push(g3d.getMeshIndexCount(mesh).then(v => indiceCount += v )) - promises.push(g3d.getMeshSubmeshCount(mesh).then(v =>submeshCount += v)) - } - await Promise.all(promises) - return [indiceCount, submeshCount] - } -} - -class SubmeshData{ - indexOffsets: Int32Array - materials : Int32Array - - constructor(count: number){ - this.indexOffsets = new Int32Array(count) - this.materials = new Int32Array(count) - } - - remapMaterials(map: Map){ - for(let i=0; i < this.materials.length; i++){ - this.materials[i] = this.materials[i] < 0 ? -1 : map.get(this.materials[i]) - } - } -} - -class VertexData{ - indices: Uint32Array - positionCount : number - meshVertexStart : Int32Array - meshVertexEnd : Int32Array - vertexOffsets: Int32Array - - constructor(meshes : MeshData, indicesCount : number){ - this.positionCount = 0 - this.indices = new Uint32Array(indicesCount) - this.meshVertexStart = new Int32Array(meshes.set.size) - this.meshVertexEnd = new Int32Array(meshes.set.size) - this.vertexOffsets = new Int32Array(meshes.set.size) - } -} - -class MaterialData{ - set : Set - map : Map - colors : Float32Array - - constructor(submeshMaterials: Int32Array){ - this.set = new Set(submeshMaterials) - this.map = new Map() - this.colors = new Float32Array(this.set.size * G3d.COLOR_SIZE) - } -} From 93122f87ebbb9e2d58e112745a4c5f2a2999666e Mon Sep 17 00:00:00 2001 From: simon Date: Thu, 21 Dec 2023 15:57:47 -0500 Subject: [PATCH 039/111] Working vimx mamacos --- .../Vim.G3dNext.Attributes/Attributes.g.cs | 94 ++---------- src/cs/g3d/Vim.G3dNext.Attributes/G3dMesh.cs | 97 +++++++----- src/cs/g3d/Vim.G3dNext.Attributes/G3dVim.cs | 34 +++++ .../Vim.G3dNext.Attributes/MeshAttributes.cs | 5 +- .../Vim.G3dNext.Attributes/SceneAttributes.cs | 4 - src/cs/linqarray/Vim.LinqArray/LinqArray.cs | 11 +- .../MeshesToScene.cs | 13 +- .../Vim.Format.Vimx.Conversion/VimToMeshes.cs | 73 ++++++--- .../VimxConverter.cs | 111 +++++++++++++- .../VimxOrdering.cs | 26 ++++ src/cs/vim/Vim.Format.Vimx/Vimx.cs | 22 +-- src/cs/vim/Vim.Format.Vimx/VimxChunk.cs | 2 +- src/ts/dist/g3d.d.ts | 3 - src/ts/dist/g3d.js | 37 ++--- src/ts/dist/g3dChunk.js | 53 +++++++ src/ts/dist/g3dMesh.d.ts | 33 +---- src/ts/dist/g3dMesh.js | 93 ++++-------- src/ts/dist/g3dScene.d.ts | 5 +- src/ts/dist/g3dScene.js | 10 +- src/ts/dist/index.d.ts | 2 - src/ts/dist/remoteVimx.d.ts | 7 +- src/ts/dist/remoteVimx.js | 26 +--- src/ts/dist/types/g3d.d.ts | 3 - src/ts/dist/types/g3dMesh.d.ts | 33 +---- src/ts/dist/types/g3dScene.d.ts | 5 +- src/ts/dist/types/index.d.ts | 2 - src/ts/dist/types/remoteVimx.d.ts | 7 +- src/ts/package.json | 4 +- src/ts/src/g3dChunk.ts | 71 +++++++++ src/ts/src/g3dMesh.ts | 139 +++++------------- src/ts/src/remoteVimx.ts | 30 ++-- 31 files changed, 571 insertions(+), 484 deletions(-) create mode 100644 src/ts/dist/g3dChunk.js create mode 100644 src/ts/src/g3dChunk.ts diff --git a/src/cs/g3d/Vim.G3dNext.Attributes/Attributes.g.cs b/src/cs/g3d/Vim.G3dNext.Attributes/Attributes.g.cs index cae68120..7b680ac8 100644 --- a/src/cs/g3d/Vim.G3dNext.Attributes/Attributes.g.cs +++ b/src/cs/g3d/Vim.G3dNext.Attributes/Attributes.g.cs @@ -954,51 +954,6 @@ public void Write(Stream stream) } } - public partial class SceneInstanceTransformsAttribute : IAttribute - { - public const string AttributeName = "g3d:instance:transform:0:int32:1"; - - public string Name - => AttributeName; - - public int Count => TypedData?.Length ?? 0; - - public void AddTo(BFast bfast) - { - if(TypedData != null) - { - bfast.SetArray(Name, TypedData); - } - } - - public void ReadBFast(BFast bfast) - { - TypedData = bfast.GetArray("g3d:instance:transform:0:int32:1"); - } - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Data; - - public Type IndexInto { get; } - = null; - - public System.Int32[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - public partial class SceneInstanceTransformDataAttribute : IAttribute { public const string AttributeName = "g3d:instance:transform:0:float32:16"; @@ -2679,12 +2634,6 @@ public System.Int32[] InstanceMeshes set => Attributes.InstanceMeshes.TypedData = value; } - public System.Int32[] InstanceTransforms - { - get => Attributes.InstanceTransforms.TypedData; - set => Attributes.InstanceTransforms.TypedData = value; - } - public Vim.Math3d.Matrix4x4[] InstanceTransformData { get => Attributes.InstanceTransformData.TypedData; @@ -2790,7 +2739,6 @@ public void ReadAttributes(BFast bfast) { [Vim.G3dNext.Attributes.SceneChunkCountAttribute.AttributeName] = new Vim.G3dNext.Attributes.SceneChunkCountAttribute(), [Vim.G3dNext.Attributes.SceneInstanceMeshesAttribute.AttributeName] = new Vim.G3dNext.Attributes.SceneInstanceMeshesAttribute(), - [Vim.G3dNext.Attributes.SceneInstanceTransformsAttribute.AttributeName] = new Vim.G3dNext.Attributes.SceneInstanceTransformsAttribute(), [Vim.G3dNext.Attributes.SceneInstanceTransformDataAttribute.AttributeName] = new Vim.G3dNext.Attributes.SceneInstanceTransformDataAttribute(), [Vim.G3dNext.Attributes.SceneInstanceNodesAttribute.AttributeName] = new Vim.G3dNext.Attributes.SceneInstanceNodesAttribute(), [Vim.G3dNext.Attributes.SceneInstanceGroupsAttribute.AttributeName] = new Vim.G3dNext.Attributes.SceneInstanceGroupsAttribute(), @@ -2820,12 +2768,6 @@ public Vim.G3dNext.Attributes.SceneInstanceMeshesAttribute InstanceMeshes set => Map[Vim.G3dNext.Attributes.SceneInstanceMeshesAttribute.AttributeName] = value as IAttribute; } - public Vim.G3dNext.Attributes.SceneInstanceTransformsAttribute InstanceTransforms - { - get => Map.TryGetValue(Vim.G3dNext.Attributes.SceneInstanceTransformsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.SceneInstanceTransformsAttribute : default; - set => Map[Vim.G3dNext.Attributes.SceneInstanceTransformsAttribute.AttributeName] = value as IAttribute; - } - public Vim.G3dNext.Attributes.SceneInstanceTransformDataAttribute InstanceTransformData { get => Map.TryGetValue(Vim.G3dNext.Attributes.SceneInstanceTransformDataAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.SceneInstanceTransformDataAttribute : default; @@ -2917,10 +2859,6 @@ public IAttribute GetAttribute(Type attributeType) return InstanceMeshes; - if (attributeType == typeof(Vim.G3dNext.Attributes.SceneInstanceTransformsAttribute)) - return InstanceTransforms; - - if (attributeType == typeof(Vim.G3dNext.Attributes.SceneInstanceTransformDataAttribute)) return InstanceTransformData; @@ -2993,12 +2931,6 @@ public IAttribute MergeAttribute(string attributeName, IReadOnlyList().ToArray().MergeDataAttributes(); } - case Vim.G3dNext.Attributes.SceneInstanceTransformsAttribute.AttributeName: - { - // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); - } - case Vim.G3dNext.Attributes.SceneInstanceTransformDataAttribute.AttributeName: { // Data Attribute @@ -3122,16 +3054,16 @@ public Vim.Math3d.Matrix4x4[] InstanceTransforms set => Attributes.InstanceTransforms.TypedData = value; } - public System.Int32[] SubmeshOffset + public System.Int32[] MeshSubmeshOffset { - get => Attributes.SubmeshOffset.TypedData; - set => Attributes.SubmeshOffset.TypedData = value; + get => Attributes.MeshSubmeshOffset.TypedData; + set => Attributes.MeshSubmeshOffset.TypedData = value; } - public System.Int32[] OpaqueSubmeshCounts + public System.Int32[] MeshOpaqueSubmeshCounts { - get => Attributes.OpaqueSubmeshCounts.TypedData; - set => Attributes.OpaqueSubmeshCounts.TypedData = value; + get => Attributes.MeshOpaqueSubmeshCounts.TypedData; + set => Attributes.MeshOpaqueSubmeshCounts.TypedData = value; } public System.Int32[] SubmeshIndexOffsets @@ -3207,13 +3139,13 @@ public Vim.G3dNext.Attributes.MeshInstanceTransformsAttribute InstanceTransforms set => Map[Vim.G3dNext.Attributes.MeshInstanceTransformsAttribute.AttributeName] = value as IAttribute; } - public Vim.G3dNext.Attributes.MeshSubmeshOffsetAttribute SubmeshOffset + public Vim.G3dNext.Attributes.MeshSubmeshOffsetAttribute MeshSubmeshOffset { get => Map.TryGetValue(Vim.G3dNext.Attributes.MeshSubmeshOffsetAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshSubmeshOffsetAttribute : default; set => Map[Vim.G3dNext.Attributes.MeshSubmeshOffsetAttribute.AttributeName] = value as IAttribute; } - public Vim.G3dNext.Attributes.MeshOpaqueSubmeshCountsAttribute OpaqueSubmeshCounts + public Vim.G3dNext.Attributes.MeshOpaqueSubmeshCountsAttribute MeshOpaqueSubmeshCounts { get => Map.TryGetValue(Vim.G3dNext.Attributes.MeshOpaqueSubmeshCountsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshOpaqueSubmeshCountsAttribute : default; set => Map[Vim.G3dNext.Attributes.MeshOpaqueSubmeshCountsAttribute.AttributeName] = value as IAttribute; @@ -3259,11 +3191,11 @@ public IAttribute GetAttribute(Type attributeType) if (attributeType == typeof(Vim.G3dNext.Attributes.MeshSubmeshOffsetAttribute)) - return SubmeshOffset; + return MeshSubmeshOffset; if (attributeType == typeof(Vim.G3dNext.Attributes.MeshOpaqueSubmeshCountsAttribute)) - return OpaqueSubmeshCounts; + return MeshOpaqueSubmeshCounts; if (attributeType == typeof(Vim.G3dNext.Attributes.MeshSubmeshIndexOffsetsAttribute)) @@ -3352,10 +3284,10 @@ public void Validate() // Ensure all the indices are either -1 or within the bounds of the attributes they are indexing into. { - var maxIndex = GetAttribute(SubmeshOffset.IndexInto).Data.Length - 1; - for (var i = 0; i < SubmeshOffset.TypedData.Length; ++i) + var maxIndex = GetAttribute(MeshSubmeshOffset.IndexInto).Data.Length - 1; + for (var i = 0; i < MeshSubmeshOffset.TypedData.Length; ++i) { - var index = SubmeshOffset.TypedData[i]; + var index = MeshSubmeshOffset.TypedData[i]; if (index == -1) continue; // no relation. diff --git a/src/cs/g3d/Vim.G3dNext.Attributes/G3dMesh.cs b/src/cs/g3d/Vim.G3dNext.Attributes/G3dMesh.cs index 17c47424..1534f574 100644 --- a/src/cs/g3d/Vim.G3dNext.Attributes/G3dMesh.cs +++ b/src/cs/g3d/Vim.G3dNext.Attributes/G3dMesh.cs @@ -9,6 +9,7 @@ public partial class G3dMesh public int[] InstanceNodes; public int Chunk; public int ChunkIndex; + public int[] MeshIndices; public long GetSize() => Attributes.GetSize(); @@ -22,44 +23,70 @@ void ISetup.Setup() /// public int GetInstanceCount() => InstanceTransforms?.Length ?? 0; - /// - /// The total number of submeshes. - /// public int GetSubmeshCount() => SubmeshIndexOffsets?.Length ?? 0; + + public int getMeshCount() => MeshSubmeshOffset?.Length ?? 0; + /// /// The total number of submeshes. /// - public int GetSubmeshCount(MeshSection section) + public int GetSubmeshCount(int mesh, MeshSection section) => + GetMeshSubmeshEnd(mesh, section) - GetMeshSubmeshStart(mesh, section); + + public int GetMeshSubmeshStart(int mesh, MeshSection section) + { + if (section == MeshSection.Opaque || section == MeshSection.All) + { + return MeshSubmeshOffset[mesh]; + } + + return MeshSubmeshOffset[mesh] + MeshOpaqueSubmeshCounts[mesh]; + } + + public int GetMeshSubmeshEnd(int mesh, MeshSection section) { - var count = GetSubmeshCount(); - if (OpaqueSubmeshCounts == null) return count; - var opaque = OpaqueSubmeshCounts[0]; + if (section == MeshSection.Opaque) + { + return MeshSubmeshOffset[mesh] + MeshOpaqueSubmeshCounts[mesh]; + } + if(mesh + 1 >= MeshSubmeshOffset.Length) + { + return SubmeshIndexOffsets.Length; + } + return MeshSubmeshOffset[mesh + 1]; + } - return section == MeshSection.Opaque - ? opaque - : count - opaque; + public int GetMeshIndexStart(int mesh, MeshSection section) + { + var sub = GetMeshSubmeshStart(mesh, section); + return GetSubmeshIndexStart(sub); } - public int GetIndexStart(MeshSection section) + public int GetMeshIndexEnd(int mesh, MeshSection section) { - if (OpaqueSubmeshCounts == null) return 0; - if (section == MeshSection.Opaque) return 0; - var opaque = OpaqueSubmeshCounts[0]; - return GetSubmeshIndexStart(opaque); + var sub = GetMeshSubmeshEnd(mesh, section); + return GetSubmeshIndexEnd(sub); } - public int GetIndexEnd(MeshSection section) + public int GetMeshIndexCount(int mesh, MeshSection section) { - if (OpaqueSubmeshCounts == null) return Indices.Length; - if (section == MeshSection.Transparent) return Indices.Length; - var opaque = OpaqueSubmeshCounts[0]; - return GetSubmeshIndexEnd(opaque - 1); + return GetMeshIndexEnd(mesh, section) - GetMeshIndexStart(mesh, section); } - public int GetIndexCount(MeshSection section) + public AABox GetAABox(int mesh, Matrix4x4 matrix) { - return GetIndexEnd(section) - GetIndexStart(section); + var start = GetMeshVertexStart(mesh, MeshSection.All); + var end = GetMeshVertexEnd(mesh, MeshSection.All); + var min = Positions[start].Transform(matrix); + var max = min; + for (var v = start + 1; v < end; v++) + { + var pos = Positions[v].Transform(matrix); + min = min.Min(pos); + max = max.Max(pos); + } + return new AABox(min, max); } /// @@ -67,27 +94,21 @@ public int GetIndexCount(MeshSection section) /// public int GetIndexCount() => Indices?.Length ?? 0; - public int GetVertexStart(MeshSection section) + public int GetMeshVertexStart(int mesh, MeshSection section) { - if (OpaqueSubmeshCounts == null) return 0; - if (SubmeshVertexOffsets == null) return 0; - if (section == MeshSection.Opaque) return 0; - var opaque = OpaqueSubmeshCounts[0]; - return GetSubmeshVertexStart(opaque); + var sub = GetMeshSubmeshStart(mesh, section); + return GetSubmeshVertexStart(sub); } - public int GetVertexEnd(MeshSection section) + public int GetMeshVertexEnd(int mesh, MeshSection section) { - if (OpaqueSubmeshCounts == null) return Positions.Length; - if (SubmeshVertexOffsets == null) return Positions.Length; - if (section == MeshSection.Transparent) return Positions.Length; - var opaque = OpaqueSubmeshCounts[0]; - return GetSubmeshVertexEnd(opaque - 1); + var sub = GetMeshSubmeshEnd(mesh, section); + return GetSubmeshVertexEnd(sub); } - public int GetVertexCount(MeshSection section) + public int GetMeshVertexCount(int mesh, MeshSection section) { - return GetVertexEnd(section) - GetVertexStart(section); + return GetMeshVertexEnd(mesh, section) - GetMeshVertexStart(mesh, section); } /// @@ -102,7 +123,9 @@ public int GetSubmeshIndexStart(int submesh) public int GetSubmeshIndexEnd(int submesh) { - return submesh + 1 < GetSubmeshCount() ? SubmeshIndexOffsets[submesh + 1] : GetIndexCount(); + return submesh + 1 < GetSubmeshCount() + ? SubmeshIndexOffsets[submesh + 1] + : GetIndexCount(); } public int GetSubmeshIndexCount(int submesh) diff --git a/src/cs/g3d/Vim.G3dNext.Attributes/G3dVim.cs b/src/cs/g3d/Vim.G3dNext.Attributes/G3dVim.cs index 693de592..10bd6732 100644 --- a/src/cs/g3d/Vim.G3dNext.Attributes/G3dVim.cs +++ b/src/cs/g3d/Vim.G3dNext.Attributes/G3dVim.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using Vim.BFastNS; namespace Vim.G3dNext.Attributes @@ -7,10 +8,22 @@ public partial class G3dVim { // Computed field public int[] MeshVertexOffsets; + private List[] _meshInstances; + + public IReadOnlyList GetMeshInstances(int mesh) + { + return _meshInstances[mesh]; + } + + public int GetApproxSize(int mesh) + { + return GetMeshVertexCount(mesh) * 12 + GetMeshIndexCount(mesh) * 4; + } void ISetup.Setup() { MeshVertexOffsets = ComputeMeshVertexOffsets(); + _meshInstances = ComputeMeshInstances(); } public static G3dVim FromVim(string vimPath) @@ -33,6 +46,27 @@ private int[] ComputeMeshVertexOffsets() return result; } + private List[] ComputeMeshInstances() + { + var result = new List[GetMeshCount()]; + for (var i = 0; i < result.Length; i++) + { + result[i] = new List(); + } + + for (var i = 0; i < InstanceMeshes.Length; i++) + { + var mesh = InstanceMeshes[i]; + if (mesh >= 0) + { + result[mesh].Add(i); + } + } + + return result; + } + + public int GetTriangleCount() { return GetIndexCount() / 3; diff --git a/src/cs/g3d/Vim.G3dNext.Attributes/MeshAttributes.cs b/src/cs/g3d/Vim.G3dNext.Attributes/MeshAttributes.cs index 0e7b94a5..bc6ef10b 100644 --- a/src/cs/g3d/Vim.G3dNext.Attributes/MeshAttributes.cs +++ b/src/cs/g3d/Vim.G3dNext.Attributes/MeshAttributes.cs @@ -20,10 +20,10 @@ public partial class MeshAttributeCollection // : IAttributeCollection [AttributeDescriptor("Mesh", "g3d:instance:transform:0:float32:16", AttributeType.Data, ArrayType = typeof(Matrix4x4))] public partial class MeshInstanceTransformsAttribute { } - [AttributeDescriptor("Mesh", "g3d:mesh:opaquesubmeshcount:0:int32:1", AttributeType.Data)] + [AttributeDescriptor("g3d:mesh:opaquesubmeshcount:0:int32:1", AttributeType.Data)] public partial class MeshOpaqueSubmeshCountsAttribute { } - [AttributeDescriptor("Mesh", "g3d:mesh:submeshOffset:0:int32:1", AttributeType.Index, IndexInto = typeof(MeshIndicesAttribute))] + [AttributeDescriptor("g3d:mesh:submeshOffset:0:int32:1", AttributeType.Index, IndexInto = typeof(MeshIndicesAttribute))] public partial class MeshSubmeshOffsetAttribute { } [AttributeDescriptor("Mesh", "g3d:submesh:indexoffset:0:int32:1", AttributeType.Index, IndexInto = typeof(MeshIndicesAttribute))] @@ -45,6 +45,7 @@ public partial class MeshIndicesAttribute { } public enum MeshSection { + All, Opaque, Transparent } diff --git a/src/cs/g3d/Vim.G3dNext.Attributes/SceneAttributes.cs b/src/cs/g3d/Vim.G3dNext.Attributes/SceneAttributes.cs index 2bfb592e..3999e558 100644 --- a/src/cs/g3d/Vim.G3dNext.Attributes/SceneAttributes.cs +++ b/src/cs/g3d/Vim.G3dNext.Attributes/SceneAttributes.cs @@ -5,7 +5,6 @@ namespace Vim.G3dNext.Attributes [AttributeCollection( typeof(SceneChunkCountAttribute), typeof(SceneInstanceMeshesAttribute), - typeof(SceneInstanceTransformsAttribute), typeof(SceneInstanceTransformDataAttribute), typeof(SceneInstanceNodesAttribute), typeof(SceneInstanceGroupsAttribute), @@ -31,9 +30,6 @@ public partial class SceneChunkCountAttribute { } [AttributeDescriptor("Scene", "g3d:instance:mesh:0:int32:1", AttributeType.Data)] public partial class SceneInstanceMeshesAttribute { } - [AttributeDescriptor("Scene", "g3d:instance:transform:0:int32:1", AttributeType.Data)] - public partial class SceneInstanceTransformsAttribute { } - [AttributeDescriptor("Scene", "g3d:instance:transform:0:float32:16", AttributeType.Data, ArrayType = typeof(Matrix4x4))] public partial class SceneInstanceTransformDataAttribute { } diff --git a/src/cs/linqarray/Vim.LinqArray/LinqArray.cs b/src/cs/linqarray/Vim.LinqArray/LinqArray.cs index 92cc3b45..cf646593 100644 --- a/src/cs/linqarray/Vim.LinqArray/LinqArray.cs +++ b/src/cs/linqarray/Vim.LinqArray/LinqArray.cs @@ -651,7 +651,7 @@ public static int IndexOf(this IArray self, T item) where T : IEquatable /// Returns the index of the first element matching the given item. /// - public static int IndexOf(this IArray self, Func predicate) + public static int IndexOf(this IArray self, Func predicate) { for (var i = 0; i < self.Count; ++i) { @@ -976,7 +976,7 @@ public static IArray PrefixSums(this IArray self) public static IArray PrefixSums(this IArray self) => self.Scan(0.0, (a, b) => a + b); - public static IArray Scan(this IArray self, U init, Func scanFunc) + public static IArray Scan(this IArray self, U init, Func scanFunc) { if (self.Count == 0) return Empty(); @@ -1012,5 +1012,12 @@ public static IArray SetFirstElementWhere(this IArray self, Func(this IArray self, int index, T defaultValue) + { + if(index < 0) return defaultValue; + if(index >= self.Count) return defaultValue; + return self[index]; + } } } diff --git a/src/cs/vim/Vim.Format.Vimx.Conversion/MeshesToScene.cs b/src/cs/vim/Vim.Format.Vimx.Conversion/MeshesToScene.cs index 74627b1d..1a70dfd2 100644 --- a/src/cs/vim/Vim.Format.Vimx.Conversion/MeshesToScene.cs +++ b/src/cs/vim/Vim.Format.Vimx.Conversion/MeshesToScene.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Linq; using Vim.BFastNS; using Vim.Format.ObjectModel; @@ -10,6 +11,7 @@ namespace Vim.Format.VimxNS.Conversion { public static class MeshesToScene { + public static G3dScene CreateScene(G3dVim g3d, DocumentModel bim, VimxChunk[] chunks, G3dMesh[] meshes) { var scene = new G3dScene(); @@ -22,10 +24,11 @@ public static G3dScene CreateScene(G3dVim g3d, DocumentModel bim, VimxChunk[] ch : bim.ElementId[n] ).ToArray(); - (scene.InstanceMeshes, scene.InstanceTransforms, scene.InstanceNodes) = meshes.GetInstanceIds(); + int[] dummy; + (scene.InstanceMeshes, dummy, scene.InstanceNodes) = meshes.GetInstanceIds(); scene.InstanceGroups = scene.InstanceNodes.Select(n => nodeElements[n]).ToArray(); scene.InstanceTags = scene.InstanceNodes.Select(n => nodeElementIds[n]).ToArray(); - (scene.InstanceMins, scene.InstanceMaxs) = ComputeBoundingBoxes(meshes, scene.InstanceMeshes, scene.InstanceTransforms); + (scene.InstanceMins, scene.InstanceMaxs) = ComputeBoundingBoxes(meshes, scene.InstanceMeshes, dummy); if (g3d.InstanceFlags != null) { @@ -47,8 +50,8 @@ public static G3dScene CreateScene(G3dVim g3d, DocumentModel bim, VimxChunk[] ch scene.MeshChunkIndices[i] = mesh.ChunkIndex; scene.MeshIndexCounts[i] = mesh.GetIndexCount(); scene.MeshVertexCounts[i] = mesh.GetVertexCount(); - scene.MeshOpaqueIndexCounts[i] = mesh.GetIndexCount(MeshSection.Opaque); - scene.MeshOpaqueVertexCounts[i] = mesh.GetVertexCount(MeshSection.Opaque); + //scene.MeshOpaqueIndexCounts[i] = mesh.GetIndexCount(MeshSection.Opaque); + //scene.MeshOpaqueVertexCounts[i] = mesh.GetMeshVertexCount(MeshSection.Opaque); } return scene; } diff --git a/src/cs/vim/Vim.Format.Vimx.Conversion/VimToMeshes.cs b/src/cs/vim/Vim.Format.Vimx.Conversion/VimToMeshes.cs index 2f771080..62a7f2e8 100644 --- a/src/cs/vim/Vim.Format.Vimx.Conversion/VimToMeshes.cs +++ b/src/cs/vim/Vim.Format.Vimx.Conversion/VimToMeshes.cs @@ -5,6 +5,7 @@ using Vim.BFastNS; using Vim.Math3d; using Vim.G3dNext.Attributes; +using static Vim.Format.DocumentBuilder; namespace Vim.Format.VimxNS.Conversion { @@ -15,35 +16,70 @@ public static class VimToMeshes /// public static IEnumerable ExtractMeshes(G3dVim g3d) { - var meshInstances = g3d.GetMeshInstances(); - return Enumerable.Range(0, g3d.GetMeshCount()) - .Select(m => g3d.GetMesh(m, meshInstances[m])) + .Select(m => g3d.GetMesh(m)) .WhereNotNull(); } - private static List[] GetMeshInstances(this G3dVim g3d) + public static G3dMesh GetMesh2(G3dVim g3d, List meshes) { - var result = new List[g3d.GetMeshCount()]; - for (var i = 0; i < result.Length; i++) - { - result[i] = new List(); - } + var submeshOffsets = new List() { 0}; + var meshOpaqueCounts = new List(); + var submeshIndexOffsets = new List(); + var submeshVertexOffsets = new List(); + var submeshMaterials = new List(); + var indices = new List(); + var vertices = new List(); + - for (var i = 0; i < g3d.InstanceMeshes.Length; i++) + for(var i =0; i < meshes.Count; i ++) { - var mesh = g3d.InstanceMeshes[i]; - if (mesh >= 0) - { - result[mesh].Add(i); - } + var mesh = meshes[i]; + + var opaqueCount = AppendSubmeshes( + g3d, + mesh, + false, + submeshIndexOffsets, + submeshVertexOffsets, + submeshMaterials, + indices, + vertices + ); + + var transparentCount = AppendSubmeshes( + g3d, + mesh, + true, + submeshIndexOffsets, + submeshVertexOffsets, + submeshMaterials, + indices, + vertices + ); + meshOpaqueCounts.Add(opaqueCount); + submeshOffsets.Add(submeshOffsets[i] + opaqueCount + transparentCount); } - return result; + return new G3dMesh() + { + MeshIndices = meshes.ToArray(), + InstanceNodes = null, + InstanceTransforms = null, + MeshSubmeshOffset = submeshOffsets.ToArray(), + MeshOpaqueSubmeshCounts = meshOpaqueCounts.ToArray(), + SubmeshIndexOffsets = submeshIndexOffsets.ToArray(), + SubmeshVertexOffsets = submeshVertexOffsets.ToArray(), + SubmeshMaterials = submeshMaterials.ToArray(), + Indices = indices.ToArray(), + Positions = vertices.ToArray() + }; } - private static G3dMesh GetMesh(this G3dVim g3d, int mesh, List instances) + + private static G3dMesh GetMesh(this G3dVim g3d, int mesh) { + var instances = g3d.GetMeshInstances(mesh); if (instances.Count == 0) { return null; @@ -91,7 +127,7 @@ private static G3dMesh GetMesh(this G3dVim g3d, int mesh, List instances) { InstanceNodes = instanceNodes.ToArray(), InstanceTransforms = instanceTransforms.ToArray(), - OpaqueSubmeshCounts = new int[] { opaqueCount }, + MeshOpaqueSubmeshCounts = new int[] { opaqueCount }, SubmeshIndexOffsets = submeshIndexOffsets.ToArray(), SubmeshVertexOffsets = submeshVertexOffsets.ToArray(), SubmeshMaterials = submeshMaterials.ToArray(), @@ -100,6 +136,7 @@ private static G3dMesh GetMesh(this G3dVim g3d, int mesh, List instances) }; } + private static int AppendSubmeshes( G3dVim g3d, int mesh, diff --git a/src/cs/vim/Vim.Format.Vimx.Conversion/VimxConverter.cs b/src/cs/vim/Vim.Format.Vimx.Conversion/VimxConverter.cs index 5e97e25b..fa45c2c7 100644 --- a/src/cs/vim/Vim.Format.Vimx.Conversion/VimxConverter.cs +++ b/src/cs/vim/Vim.Format.Vimx.Conversion/VimxConverter.cs @@ -5,6 +5,7 @@ using Vim.Format.ObjectModel; using Vim.G3dNext; using System.Collections.Generic; +using Vim.Math3d; namespace Vim.Format.VimxNS.Conversion { @@ -19,9 +20,67 @@ public static Vimx FromVimPath(string vimPath) }); var g3d = G3dVim.FromVim(vimPath); - return FromVim(g3d, vim.DocumentModel); + return FromVim2(g3d, vim.DocumentModel); } + + public static Vimx FromVim2(G3dVim g3d, DocumentModel bim) + { + var meshOrder = VimxOrdering.OrderByBim2(g3d, bim).ToArray(); + var instanceNodes = meshOrder.SelectMany(m => g3d.GetMeshInstances(m)); + var instanceMeshes = meshOrder.SelectMany((m,i) => g3d.GetMeshInstances(m).Select(_ => i)).ToArray(); + var instanceTransforms = instanceNodes.Select(n => g3d.InstanceTransforms[n]).ToArray(); + var instanceFlags = g3d.InstanceFlags != null + ? instanceNodes.Select(n => g3d.InstanceFlags[n]).ToArray() + : null; + + var nodeElements = bim.NodeElementIndex.ToArray(); + var instanceGroups = instanceNodes.Select(n => nodeElements[n]).ToArray(); + + var nodeElementIds = nodeElements + .Select(n => bim.ElementId.SafeGet(n, -1)) + .ToArray(); + + var chunks = SplitChunks2(g3d, meshOrder); + + var meshes = chunks.Chunks.Select(c => VimToMeshes.GetMesh2(g3d, c)).ToArray(); + var indexCount = meshOrder.Select((m, i) => meshes[chunks.MeshChunks[i]].GetMeshIndexCount(chunks.MeshIndex[i], MeshSection.All)); + var vertexCount = meshOrder.Select((m, i) => meshes[chunks.MeshChunks[i]].GetMeshVertexCount(chunks.MeshIndex[i], MeshSection.All)); + var opaqueIndexCount = meshOrder.Select((m, i) => meshes[chunks.MeshChunks[i]].GetMeshIndexCount(chunks.MeshIndex[i], MeshSection.Opaque)); + var opaqueVertexCount = meshOrder.Select((m, i) => meshes[chunks.MeshChunks[i]].GetMeshVertexCount(chunks.MeshIndex[i], MeshSection.Opaque)); + + var boxes = instanceMeshes + .Select((m, i) => meshes[chunks.MeshChunks[m]].GetAABox(chunks.MeshIndex[m], instanceTransforms[i])) + .ToArray(); + var mins = boxes.Select(b => b.Min).ToArray(); + var maxs = boxes.Select(b => b.Max).ToArray(); + + var scene = new G3dScene() + { + ChunkCount = new[] { chunks.Chunks.Count }, + InstanceMeshes = instanceMeshes.ToArray(), + InstanceTransformData = instanceTransforms, + InstanceNodes = instanceNodes.ToArray(), + InstanceFlags = instanceFlags, + InstanceGroups = instanceGroups, + InstanceMaxs = maxs, + InstanceMins = mins, + InstanceTags = nodeElementIds, + MeshChunks = chunks.MeshChunks.ToArray(), + MeshChunkIndices = chunks.MeshIndex.ToArray(), + MeshIndexCounts = indexCount.ToArray(), + MeshVertexCounts = vertexCount.ToArray(), + MeshOpaqueIndexCounts = opaqueIndexCount.ToArray(), + MeshOpaqueVertexCounts = opaqueVertexCount.ToArray(), + }; + + var materials = new G3dMaterials().ReadFromVim(g3d); + var header = VimxHeader.CreateDefault(); + + return new Vimx(header, MetaHeader.Default, scene, materials, meshes); + } + + public static Vimx FromVim(G3dVim g3d, DocumentModel bim) { var meshes = VimToMeshes.ExtractMeshes(g3d) @@ -32,8 +91,8 @@ public static Vimx FromVim(G3dVim g3d, DocumentModel bim) var scene = MeshesToScene.CreateScene(g3d, bim, chunks, meshes); var materials = new G3dMaterials().ReadFromVim(g3d); var header = VimxHeader.CreateDefault(); - - return new Vimx(header, MetaHeader.Default, scene, materials, chunks); + + return new Vimx(header, MetaHeader.Default, scene, materials, meshes); } public static VimxChunk[] SplitChunks(this IEnumerable meshes) @@ -57,12 +116,56 @@ public static VimxChunk[] SplitChunks(this IEnumerable meshes) mesh.ChunkIndex = chunk.Meshes.Count(); chunk.Meshes.Add(mesh); } - if(chunk.Meshes.Count > 0) + if (chunk.Meshes.Count > 0) { chunks.Add(chunk); } return chunks.ToArray(); } + + public static ChunkResult SplitChunks2(G3dVim g3d, int[] meshes) + { + // 2MB once compressed -> 0.5MB + const int ChunkSize = 2000000; + + var meshChunks = new List(); + var meshIndex = new List(); + + var chunks = new List>(); + var chunk = new List(); + var chunkSize = 0L; + foreach (var mesh in meshes) + { + chunkSize += g3d.GetApproxSize(mesh); + if (chunkSize > ChunkSize && chunk.Count > 0) + { + chunks.Add(chunk); + chunk = new List(); + chunkSize = 0; + } + + meshChunks.Add(chunks.Count); + meshIndex.Add(chunk.Count); + chunk.Add(mesh); + } + if (chunk.Count > 0) + { + chunks.Add(chunk); + } + + return new ChunkResult { + MeshChunks = meshChunks, + MeshIndex = meshIndex, + Chunks = chunks + }; + } } } + +public class ChunkResult +{ + public List MeshChunks = new List(); + public List MeshIndex = new List(); + public List> Chunks = new List>(); +} diff --git a/src/cs/vim/Vim.Format.Vimx.Conversion/VimxOrdering.cs b/src/cs/vim/Vim.Format.Vimx.Conversion/VimxOrdering.cs index cf9ff791..a61ba943 100644 --- a/src/cs/vim/Vim.Format.Vimx.Conversion/VimxOrdering.cs +++ b/src/cs/vim/Vim.Format.Vimx.Conversion/VimxOrdering.cs @@ -15,6 +15,32 @@ public static IEnumerable OrderByBim(this IEnumerable meshes, ); } + public static IEnumerable OrderByBim2(G3dVim g3d, DocumentModel bim) + { + return Enumerable.Range(0, g3d.GetMeshCount()) + .Where(m => g3d.GetMeshInstances(m).Count > 0) + .OrderByDescending((m) => + GetPriority(GetMeshName2(g3d, bim, m)) + ); + } + + static string GetMeshName2(G3dVim g3d, DocumentModel bim, int mesh) + { + var node = g3d.GetMeshInstances(mesh)[0]; + + if (node < 0 || node >= bim.NodeElementIndex.Count) return ""; + var element = bim.NodeElementIndex[node]; + + if (element < 0 || element >= bim.ElementCategoryIndex.Count) return ""; + var category = bim.ElementCategoryIndex[element]; + + if (category < 0 || category >= bim.CategoryName.Count) return ""; + var name = bim.CategoryName[category]; + + return name; + } + + static string GetMeshName(this G3dMesh mesh, DocumentModel bim) { var node = mesh.InstanceNodes[0]; diff --git a/src/cs/vim/Vim.Format.Vimx/Vimx.cs b/src/cs/vim/Vim.Format.Vimx/Vimx.cs index 12ef4f1f..73f6af5f 100644 --- a/src/cs/vim/Vim.Format.Vimx/Vimx.cs +++ b/src/cs/vim/Vim.Format.Vimx/Vimx.cs @@ -12,7 +12,6 @@ public static class BufferNames public const string Meta = "meta"; public const string Scene = "scene"; public const string Materials = "materials"; - public static string Mesh(int mesh) => $"mesh_{mesh}"; public static string Chunk(int mesh) => $"chunk_{mesh}"; } @@ -32,10 +31,10 @@ public class Vimx public readonly MetaHeader Meta; public readonly G3dScene Scene; public readonly G3dMaterials Materials; - public readonly VimxChunk[] Chunks; - public IEnumerable Meshes => Chunks.SelectMany(c => c.Meshes); + //public readonly VimxChunk[] Chunks; + public readonly G3dMesh[] Chunks; - public Vimx(SerializableHeader header, MetaHeader meta, G3dScene scene, G3dMaterials materials, VimxChunk[] chunks) + public Vimx(SerializableHeader header, MetaHeader meta, G3dScene scene, G3dMaterials materials, G3dMesh[] chunks) { Meta = meta; Header = header; @@ -58,7 +57,7 @@ public Vimx(BFast bfast) Chunks = Enumerable.Range(0, Scene.GetChunksCount()) .Select(c => bfast.GetBFast(BufferNames.Chunk(c), BufferCompression.Chunks)) - .Select(b => new VimxChunk(b)) + .Select(b => new G3dMesh(b)) .ToArray(); } @@ -67,7 +66,6 @@ public static Vimx FromPath(string path) public BFast ToBFast() { - AddTransformsToScene(); var bfast = new BFast(); bfast.SetArray(BufferNames.Meta, MetaHeader.Default.ToBytes()); bfast.SetArray(BufferNames.Header, Header.ToVimxBytes()); @@ -77,18 +75,6 @@ public BFast ToBFast() return bfast; } - private void AddTransformsToScene() - { - Scene.InstanceTransformData = new Math3d.Matrix4x4[Scene.GetInstanceCount()]; - for (var i = 0; i < Scene.GetInstanceCount(); i++) - { - var mesh = Scene.InstanceMeshes[i]; - var chunk = Scene.MeshChunks[mesh]; - var chunIndex = Scene.MeshChunkIndices[mesh]; - var transform = Scene.InstanceTransforms[i]; - Scene.InstanceTransformData[i] = Chunks[chunk].Meshes[chunIndex].InstanceTransforms[transform]; - } - } } } diff --git a/src/cs/vim/Vim.Format.Vimx/VimxChunk.cs b/src/cs/vim/Vim.Format.Vimx/VimxChunk.cs index 5a647877..c90bb8dd 100644 --- a/src/cs/vim/Vim.Format.Vimx/VimxChunk.cs +++ b/src/cs/vim/Vim.Format.Vimx/VimxChunk.cs @@ -23,7 +23,7 @@ public BFast ToBFast() { var chunk = new BFast(); chunk.SetBFast( - BufferNames.Mesh, + BufferNames.Chunk, Meshes.Select(m => m.ToBFast()) ); return chunk; diff --git a/src/ts/dist/g3d.d.ts b/src/ts/dist/g3d.d.ts index bba0b4a2..f1599699 100644 --- a/src/ts/dist/g3d.d.ts +++ b/src/ts/dist/g3d.d.ts @@ -1,7 +1,6 @@ /** * @module vim-ts */ -import { AbstractG3d } from './abstractG3d'; import { BFast } from './bfast'; export declare type MeshSection = 'opaque' | 'transparent' | 'all'; /** @@ -43,7 +42,6 @@ export declare class G3d { meshOpaqueCount: Int32Array; submeshVertexStart: Int32Array; submeshVertexEnd: Int32Array; - rawG3d: AbstractG3d; static MATRIX_SIZE: number; static COLOR_SIZE: number; static POSITION_SIZE: number; @@ -53,7 +51,6 @@ export declare class G3d { DEFAULT_COLOR: Float32Array; constructor(instanceMeshes: Int32Array, instanceFlags: Uint16Array | undefined, instanceTransforms: Float32Array, instanceNodes: Int32Array | undefined, meshSubmeshes: Int32Array, submeshIndexOffsets: Int32Array, submeshMaterials: Int32Array, indices: Int32Array | Uint32Array, positions: Float32Array, materialColors: Float32Array); private computeSubmeshVertexRange; - static createFromAbstract(g3d: AbstractG3d): G3d; static createFromPath(path: string): Promise; static createFromBfast(bfast: BFast): Promise; /** diff --git a/src/ts/dist/g3d.js b/src/ts/dist/g3d.js index 1cf5cd24..9ebe38a9 100644 --- a/src/ts/dist/g3d.js +++ b/src/ts/dist/g3d.js @@ -4,7 +4,6 @@ */ Object.defineProperty(exports, "__esModule", { value: true }); exports.G3d = exports.VimAttributes = void 0; -const abstractG3d_1 = require("./abstractG3d"); const bfast_1 = require("./bfast"); /** * See https://github.com/vimaec/vim#vim-geometry-attributes @@ -101,27 +100,6 @@ class G3d { } return { start, end }; } - static createFromAbstract(g3d) { - const instanceMeshes = g3d.findAttribute(VimAttributes.instanceMeshes) - ?.data; - const instanceTransforms = g3d.findAttribute(VimAttributes.instanceTransforms)?.data; - const instanceFlags = g3d.findAttribute(VimAttributes.instanceFlags)?.data ?? - new Uint16Array(instanceMeshes.length); - const instanceNodes = g3d.findAttribute(VimAttributes.instanceNodes)?.data; - const meshSubmeshes = g3d.findAttribute(VimAttributes.meshSubmeshes) - ?.data; - const submeshIndexOffset = g3d.findAttribute(VimAttributes.submeshIndexOffsets)?.data; - const submeshMaterial = g3d.findAttribute(VimAttributes.submeshMaterials) - ?.data; - const indices = g3d.findAttribute(VimAttributes.indices)?.data; - const positions = g3d.findAttribute(VimAttributes.positions) - ?.data; - const materialColors = g3d.findAttribute(VimAttributes.materialColors) - ?.data; - const result = new G3d(instanceMeshes, instanceFlags, instanceTransforms, instanceNodes, meshSubmeshes, submeshIndexOffset, submeshMaterial, indices, positions, materialColors); - result.rawG3d = g3d; - return result; - } static async createFromPath(path) { const f = await fetch(path); const buffer = await f.arrayBuffer(); @@ -129,8 +107,19 @@ class G3d { return this.createFromBfast(bfast); } static async createFromBfast(bfast) { - const g3d = await abstractG3d_1.AbstractG3d.createFromBfast(bfast, VimAttributes.all); - return G3d.createFromAbstract(g3d); + const values = await Promise.all([ + bfast.getInt32Array(VimAttributes.instanceMeshes), + bfast.getUint16Array(VimAttributes.instanceFlags), + bfast.getFloat32Array(VimAttributes.instanceTransforms), + bfast.getInt32Array(VimAttributes.instanceNodes), + bfast.getInt32Array(VimAttributes.meshSubmeshes), + bfast.getInt32Array(VimAttributes.submeshIndexOffsets), + bfast.getInt32Array(VimAttributes.submeshMaterials), + bfast.getInt32Array(VimAttributes.indices), + bfast.getFloat32Array(VimAttributes.positions), + bfast.getFloat32Array(VimAttributes.materialColors) + ]); + return new G3d(...values); } /** * Computes the index of the first vertex of each mesh diff --git a/src/ts/dist/g3dChunk.js b/src/ts/dist/g3dChunk.js new file mode 100644 index 00000000..0630de04 --- /dev/null +++ b/src/ts/dist/g3dChunk.js @@ -0,0 +1,53 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.G3dChunk = exports.MeshAttributes = void 0; +/** + * G3D is a simple, efficient, generic binary format for storing and transmitting geometry. + * The G3D format is designed to be used either as a serialization format or as an in-memory data structure. + * A G3d with specific attributes according to the VIM format specification. + * See https://github.com/vimaec/vim#vim-geometry-attributes for the vim specification. + * See https://github.com/vimaec/g3d for the g3d specification. + */ +/** + * See https://github.com/vimaec/vim#vim-geometry-attributes + */ +class MeshAttributes { +} +exports.MeshAttributes = MeshAttributes; +MeshAttributes.meshSubmeshOffset = 'g3d:mesh:submeshOffset:0:int32:1'; +MeshAttributes.meshOpaqueSubmeshCount = 'g3d:mesh:opaquesubmeshcount:0:int32:1'; +MeshAttributes.submeshIndexOffsets = 'g3d:submesh:indexoffset:0:int32:1'; +MeshAttributes.submeshVertexOffsets = 'g3d:submesh:vertexoffset:0:int32:1'; +MeshAttributes.submeshMaterials = 'g3d:submesh:material:0:int32:1'; +MeshAttributes.positions = 'g3d:vertex:position:0:float32:3'; +MeshAttributes.indices = 'g3d:corner:index:0:int32:1'; +class G3dChunk { + constructor(meshSubmeshOffset, meshOpaqueSubmeshCount, submeshIndexOffsets, submeshVertexOffsets, submeshMaterials, indices, positions) { + this.meshSubmeshOffset = meshSubmeshOffset; + this.meshOpaqueSubmeshCount = meshOpaqueSubmeshCount; + this.submeshIndexOffset = submeshIndexOffsets; + this.submeshVertexOffset = submeshVertexOffsets; + this.submeshMaterial = submeshMaterials; + this.indices = indices instanceof Uint32Array ? indices : new Uint32Array(indices.buffer); + this.positions = positions; + } + static async createFromBfast(bfast) { + const values = await Promise.all([ + bfast.getInt32Array(MeshAttributes.meshSubmeshOffset), + bfast.getInt32Array(MeshAttributes.meshOpaqueSubmeshCount), + bfast.getInt32Array(MeshAttributes.submeshIndexOffsets), + bfast.getInt32Array(MeshAttributes.submeshVertexOffsets), + bfast.getInt32Array(MeshAttributes.submeshMaterials), + bfast.getInt32Array(MeshAttributes.indices), + bfast.getFloat32Array(MeshAttributes.positions) + ]); + return new G3dChunk(...values); + } +} +exports.G3dChunk = G3dChunk; +G3dChunk.COLOR_SIZE = 4; +G3dChunk.POSITION_SIZE = 3; +/** + * Opaque white + */ +G3dChunk.DEFAULT_COLOR = new Float32Array([1, 1, 1, 1]); diff --git a/src/ts/dist/g3dMesh.d.ts b/src/ts/dist/g3dMesh.d.ts index 30c17da2..637da62d 100644 --- a/src/ts/dist/g3dMesh.d.ts +++ b/src/ts/dist/g3dMesh.d.ts @@ -1,52 +1,33 @@ /** * @module vim-ts */ -import { BFast } from './bfast'; +import { G3dChunk } from './g3dChunk'; import { MeshSection } from './g3d'; import { G3dScene } from './g3dScene'; /** * See https://github.com/vimaec/vim#vim-geometry-attributes */ export declare class MeshAttributes { + static meshSubmeshOffset: string; static meshOpaqueSubmeshCount: string; static submeshIndexOffsets: string; static submeshVertexOffsets: string; static submeshMaterials: string; static positions: string; static indices: string; - static all: string[]; } -/** - * G3D is a simple, efficient, generic binary format for storing and transmitting geometry. - * The G3D format is designed to be used either as a serialization format or as an in-memory data structure. - * A G3d with specific attributes according to the VIM format specification. - * See https://github.com/vimaec/vim#vim-geometry-attributes for the vim specification. - * See https://github.com/vimaec/g3d for the g3d specification. - */ export declare class G3dMesh { - scene: G3dScene; - meshIndex: number; - readonly meshOpaqueSubmeshCount: number; - readonly submeshIndexOffset: Int32Array; - readonly submeshVertexOffset: Int32Array; - readonly submeshMaterial: Int32Array; - readonly positions: Float32Array; - readonly indices: Uint32Array; - static readonly COLOR_SIZE = 4; - static readonly POSITION_SIZE = 3; - /** - * Opaque white - */ - static readonly DEFAULT_COLOR: Float32Array; - constructor(meshOpaqueSubmeshCount: number, submeshIndexOffsets: Int32Array, submeshVertexOffsets: Int32Array, submeshMaterials: Int32Array, indices: Int32Array | Uint32Array, positions: Float32Array); - static createFromBfast(bfast: BFast): Promise; + readonly scene: G3dScene; + readonly chunk: G3dChunk; + readonly index: number; + constructor(scene: G3dScene, chunk: G3dChunk, index: number); getVertexStart(section?: MeshSection): number; getVertexEnd(section?: MeshSection): number; getVertexCount(section?: MeshSection): number; getIndexStart(section?: MeshSection): number; getIndexEnd(section?: MeshSection): number; getIndexCount(section?: MeshSection): number; - getHasTransparency(): boolean; + getHasTransparency(mesh: number): boolean; getSubmeshStart(section: MeshSection): number; getSubmeshEnd(section: MeshSection): number; getSubmeshCount(section: MeshSection): number; diff --git a/src/ts/dist/g3dMesh.js b/src/ts/dist/g3dMesh.js index 8b572ae4..732cd452 100644 --- a/src/ts/dist/g3dMesh.js +++ b/src/ts/dist/g3dMesh.js @@ -11,46 +11,18 @@ const g3d_1 = require("./g3d"); class MeshAttributes { } exports.MeshAttributes = MeshAttributes; +MeshAttributes.meshSubmeshOffset = 'g3d:mesh:submeshOffset:0:int32:1'; MeshAttributes.meshOpaqueSubmeshCount = 'g3d:mesh:opaquesubmeshcount:0:int32:1'; MeshAttributes.submeshIndexOffsets = 'g3d:submesh:indexoffset:0:int32:1'; MeshAttributes.submeshVertexOffsets = 'g3d:submesh:vertexoffset:0:int32:1'; MeshAttributes.submeshMaterials = 'g3d:submesh:material:0:int32:1'; MeshAttributes.positions = 'g3d:vertex:position:0:float32:3'; MeshAttributes.indices = 'g3d:corner:index:0:int32:1'; -MeshAttributes.all = [ - MeshAttributes.meshOpaqueSubmeshCount, - MeshAttributes.submeshIndexOffsets, - MeshAttributes.submeshVertexOffsets, - MeshAttributes.submeshMaterials, - MeshAttributes.positions, - MeshAttributes.indices, -]; -/** - * G3D is a simple, efficient, generic binary format for storing and transmitting geometry. - * The G3D format is designed to be used either as a serialization format or as an in-memory data structure. - * A G3d with specific attributes according to the VIM format specification. - * See https://github.com/vimaec/vim#vim-geometry-attributes for the vim specification. - * See https://github.com/vimaec/g3d for the g3d specification. - */ class G3dMesh { - constructor(meshOpaqueSubmeshCount, submeshIndexOffsets, submeshVertexOffsets, submeshMaterials, indices, positions) { - this.meshOpaqueSubmeshCount = meshOpaqueSubmeshCount; - this.submeshIndexOffset = submeshIndexOffsets; - this.submeshVertexOffset = submeshVertexOffsets; - this.submeshMaterial = submeshMaterials; - this.indices = indices instanceof Uint32Array ? indices : new Uint32Array(indices.buffer); - this.positions = positions; - } - static async createFromBfast(bfast) { - const values = await Promise.all([ - bfast.getValue(MeshAttributes.meshOpaqueSubmeshCount, 0).then(v => v), - bfast.getInt32Array(MeshAttributes.submeshIndexOffsets), - bfast.getInt32Array(MeshAttributes.submeshVertexOffsets), - bfast.getInt32Array(MeshAttributes.submeshMaterials), - bfast.getInt32Array(MeshAttributes.indices), - bfast.getFloat32Array(MeshAttributes.positions) - ]); - return new G3dMesh(...values); + constructor(scene, chunk, index) { + this.scene = scene; + this.chunk = chunk; + this.index = index; } // ------------- Mesh ----------------- getVertexStart(section = 'all') { @@ -75,58 +47,53 @@ class G3dMesh { getIndexCount(section = 'all') { return this.getIndexEnd(section) - this.getIndexStart(section); } - getHasTransparency() { - return this.meshOpaqueSubmeshCount < this.submeshIndexOffset.length; + getHasTransparency(mesh) { + return this.getSubmeshCount('transparent') > 0; } // ------------- Submeshes ----------------- getSubmeshStart(section) { - if (section === 'all') - return 0; - if (section === 'opaque') - return 0; - return this.meshOpaqueSubmeshCount; + if (section === 'all' || section === 'opaque') { + return this.chunk.meshSubmeshOffset[this.index]; + } + return this.chunk.meshSubmeshOffset[this.index] + this.chunk.meshOpaqueSubmeshCount[this.index]; } getSubmeshEnd(section) { - if (section === 'all') - return this.submeshIndexOffset.length; - if (section === 'transparent') - return this.submeshIndexOffset.length; - return this.meshOpaqueSubmeshCount; + if (section === 'opaque') { + return this.chunk.meshSubmeshOffset[this.index] + this.chunk.meshOpaqueSubmeshCount[this.index]; + } + if (this.index + 1 < this.chunk.meshSubmeshOffset.length) { + return this.chunk.meshSubmeshOffset[this.index + 1]; + } + return this.chunk.submeshIndexOffset.length; } getSubmeshCount(section) { return this.getSubmeshEnd(section) - this.getSubmeshStart(section); } getSubmeshIndexStart(submesh) { - return submesh < this.submeshIndexOffset.length - ? this.submeshIndexOffset[submesh] - : this.indices.length; + return submesh < this.chunk.submeshIndexOffset.length + ? this.chunk.submeshIndexOffset[submesh] + : this.chunk.indices.length; } getSubmeshIndexEnd(submesh) { - return submesh < this.submeshIndexOffset.length - 1 - ? this.submeshIndexOffset[submesh + 1] - : this.indices.length; + return submesh < this.chunk.submeshIndexOffset.length - 1 + ? this.chunk.submeshIndexOffset[submesh + 1] + : this.chunk.indices.length; } getSubmeshIndexCount(submesh) { return this.getSubmeshIndexEnd(submesh) - this.getSubmeshIndexStart(submesh); } getSubmeshVertexStart(submesh) { - return submesh < this.submeshIndexOffset.length - ? this.submeshVertexOffset[submesh] - : this.positions.length / g3d_1.G3d.POSITION_SIZE; + return submesh < this.chunk.submeshIndexOffset.length + ? this.chunk.submeshVertexOffset[submesh] + : this.chunk.positions.length / g3d_1.G3d.POSITION_SIZE; } getSubmeshVertexEnd(submesh) { - return submesh < this.submeshVertexOffset.length - 1 - ? this.submeshVertexOffset[submesh + 1] - : this.positions.length / g3d_1.G3d.POSITION_SIZE; + return submesh < this.chunk.submeshVertexOffset.length - 1 + ? this.chunk.submeshVertexOffset[submesh + 1] + : this.chunk.positions.length / g3d_1.G3d.POSITION_SIZE; } getSubmeshVertexCount(submesh) { return this.getSubmeshVertexEnd(submesh) - this.getSubmeshVertexStart(submesh); } } exports.G3dMesh = G3dMesh; -G3dMesh.COLOR_SIZE = 4; -G3dMesh.POSITION_SIZE = 3; -/** - * Opaque white - */ -G3dMesh.DEFAULT_COLOR = new Float32Array([1, 1, 1, 1]); diff --git a/src/ts/dist/g3dScene.d.ts b/src/ts/dist/g3dScene.d.ts index 4cb2d42b..f87ace78 100644 --- a/src/ts/dist/g3dScene.d.ts +++ b/src/ts/dist/g3dScene.d.ts @@ -19,7 +19,6 @@ export declare class SceneAttributes { static readonly instanceMaxs = "g3d:instance:max:0:float32:3"; static readonly meshChunk = "g3d:mesh:chunk:0:int32:1"; static readonly meshChunkIndices = "g3d:mesh:chunkindex:0:int32:1"; - static readonly meshInstanceCounts = "g3d:mesh:instancecount:0:int32:1"; static readonly meshIndexCounts = "g3d:mesh:indexcount:0:int32:1"; static readonly meshVertexCounts = "g3d:mesh:vertexcount:0:int32:1"; static readonly meshOpaqueIndexCount = "g3d:mesh:opaqueindexcount:0:int32:1"; @@ -42,18 +41,16 @@ export declare class G3dScene { instanceMaxs: Float32Array; meshChunks: Int32Array; meshChunkIndices: Int32Array; - meshInstanceCounts: Int32Array; meshIndexCounts: Int32Array; meshVertexCounts: Int32Array; meshOpaqueIndexCounts: Int32Array; meshOpaqueVertexCounts: Int32Array; private nodeToInstance; - constructor(chunkCount: Int32Array, instanceMeshes: Int32Array, instanceMatrices: Float32Array, instanceNodes: Int32Array, instanceGroups: Int32Array, instanceTags: BigInt64Array, instanceFlags: Uint16Array, instanceMins: Float32Array, instanceMaxs: Float32Array, meshChunks: Int32Array, meshChunkIndices: Int32Array, meshInstanceCounts: Int32Array, meshIndexCounts: Int32Array, meshVertexCounts: Int32Array, meshOpaqueIndexCounts: Int32Array, meshOpaqueVertexCounts: Int32Array); + constructor(chunkCount: Int32Array, instanceMeshes: Int32Array, instanceMatrices: Float32Array, instanceNodes: Int32Array, instanceGroups: Int32Array, instanceTags: BigInt64Array, instanceFlags: Uint16Array, instanceMins: Float32Array, instanceMaxs: Float32Array, meshChunks: Int32Array, meshChunkIndices: Int32Array, meshIndexCounts: Int32Array, meshVertexCounts: Int32Array, meshOpaqueIndexCounts: Int32Array, meshOpaqueVertexCounts: Int32Array); static createFromBfast(bfast: BFast): Promise; getMeshCount(): number; getMeshIndexCount(mesh: number, section: MeshSection): number; getMeshVertexCount(mesh: number, section: MeshSection): number; - getMeshInstanceCount(mesh: number): number; getInstanceMin(instance: number): Float32Array; getInstanceMax(instance: number): Float32Array; getInstanceMatrix(instance: number): Float32Array; diff --git a/src/ts/dist/g3dScene.js b/src/ts/dist/g3dScene.js index 0962d188..9c0f5e83 100644 --- a/src/ts/dist/g3dScene.js +++ b/src/ts/dist/g3dScene.js @@ -22,7 +22,6 @@ SceneAttributes.instanceMins = 'g3d:instance:min:0:float32:3'; SceneAttributes.instanceMaxs = 'g3d:instance:max:0:float32:3'; SceneAttributes.meshChunk = 'g3d:mesh:chunk:0:int32:1'; SceneAttributes.meshChunkIndices = 'g3d:mesh:chunkindex:0:int32:1'; -SceneAttributes.meshInstanceCounts = 'g3d:mesh:instancecount:0:int32:1'; SceneAttributes.meshIndexCounts = 'g3d:mesh:indexcount:0:int32:1'; SceneAttributes.meshVertexCounts = 'g3d:mesh:vertexcount:0:int32:1'; SceneAttributes.meshOpaqueIndexCount = "g3d:mesh:opaqueindexcount:0:int32:1"; @@ -33,7 +32,7 @@ SceneAttributes.meshOpaqueVertexCount = "g3d:mesh:opaquevertexcount:0:int32:1"; * Allows to preallocate geometry to render G3dMeshes. */ class G3dScene { - constructor(chunkCount, instanceMeshes, instanceMatrices, instanceNodes, instanceGroups, instanceTags, instanceFlags, instanceMins, instanceMaxs, meshChunks, meshChunkIndices, meshInstanceCounts, meshIndexCounts, meshVertexCounts, meshOpaqueIndexCounts, meshOpaqueVertexCounts) { + constructor(chunkCount, instanceMeshes, instanceMatrices, instanceNodes, instanceGroups, instanceTags, instanceFlags, instanceMins, instanceMaxs, meshChunks, meshChunkIndices, meshIndexCounts, meshVertexCounts, meshOpaqueIndexCounts, meshOpaqueVertexCounts) { this.chunkCount = chunkCount[0]; this.instanceMeshes = instanceMeshes; this.instanceMatrices = instanceMatrices; @@ -45,7 +44,6 @@ class G3dScene { this.instanceMaxs = instanceMaxs; this.meshChunks = meshChunks; this.meshChunkIndices = meshChunkIndices; - this.meshInstanceCounts = meshInstanceCounts; this.meshIndexCounts = meshIndexCounts; this.meshVertexCounts = meshVertexCounts; this.meshOpaqueIndexCounts = meshOpaqueIndexCounts; @@ -69,7 +67,6 @@ class G3dScene { bfast.getFloat32Array(SceneAttributes.instanceMaxs), bfast.getInt32Array(SceneAttributes.meshChunk), bfast.getInt32Array(SceneAttributes.meshChunkIndices), - bfast.getInt32Array(SceneAttributes.meshInstanceCounts), bfast.getInt32Array(SceneAttributes.meshIndexCounts), bfast.getInt32Array(SceneAttributes.meshVertexCounts), bfast.getInt32Array(SceneAttributes.meshOpaqueIndexCount), @@ -78,7 +75,7 @@ class G3dScene { return new G3dScene(...values); } getMeshCount() { - return this.meshInstanceCounts.length; + return this.meshChunks.length; } getMeshIndexCount(mesh, section) { const all = this.meshIndexCounts[mesh]; @@ -94,9 +91,6 @@ class G3dScene { const opaque = this.meshOpaqueVertexCounts[mesh]; return section === 'opaque' ? opaque : all - opaque; } - getMeshInstanceCount(mesh) { - return this.meshInstanceCounts[mesh]; - } getInstanceMin(instance) { return this.instanceMins.subarray(instance * g3d_1.G3d.POSITION_SIZE); } diff --git a/src/ts/dist/index.d.ts b/src/ts/dist/index.d.ts index e3775c32..b90db4ff 100644 --- a/src/ts/dist/index.d.ts +++ b/src/ts/dist/index.d.ts @@ -1,11 +1,9 @@ export * from './bfast'; -export * from './abstractG3d'; export * from './g3d'; export * from './remoteVimx'; export * from './g3dMaterials'; export * from './g3dMesh'; export * from './g3dScene'; -export * from './remoteG3d'; export * from './remoteBuffer'; export * from './requestTracker'; export * from './requester'; diff --git a/src/ts/dist/remoteVimx.d.ts b/src/ts/dist/remoteVimx.d.ts index 7bdf3878..9286f409 100644 --- a/src/ts/dist/remoteVimx.d.ts +++ b/src/ts/dist/remoteVimx.d.ts @@ -1,12 +1,13 @@ import { BFast } from "./bfast"; import { G3dMaterial as G3dMaterials } from "./g3dMaterials"; -import { G3dMesh } from "./g3dMesh"; +import { G3dChunk } from './g3dChunk'; import { G3dScene } from "./g3dScene"; import { RemoteValue } from "./remoteValue"; +import { G3dMesh } from "./g3dMesh"; export declare class RemoteVimx { bfast: BFast; scene: RemoteValue; - chunkCache: Map>; + chunkCache: Map>; constructor(source: BFast | ArrayBuffer | string); /** * Aborts all downloads from the underlying BFAST. @@ -29,7 +30,7 @@ export declare class RemoteVimx { /** * Fetches and returns the vimx G3dMesh with given index */ - getChunk(chunk: number): Promise; + getChunk(chunk: number): Promise; private requestChunk; getMesh(mesh: number): Promise; } diff --git a/src/ts/dist/remoteVimx.js b/src/ts/dist/remoteVimx.js index d3385abe..04e28d7c 100644 --- a/src/ts/dist/remoteVimx.js +++ b/src/ts/dist/remoteVimx.js @@ -3,10 +3,11 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.RemoteVimx = void 0; const bfast_1 = require("./bfast"); const g3dMaterials_1 = require("./g3dMaterials"); -const g3dMesh_1 = require("./g3dMesh"); +const g3dChunk_1 = require("./g3dChunk"); const g3dScene_1 = require("./g3dScene"); const remoteValue_1 = require("./remoteValue"); const vimHeader_1 = require("./vimHeader"); +const g3dMesh_1 = require("./g3dMesh"); class RemoteVimx { constructor(source) { this.chunkCache = new Map(); @@ -61,28 +62,17 @@ class RemoteVimx { } async requestChunk(chunk) { const chunkBFast = await this.bfast.getLocalBfast(`chunk_${chunk}`, true); - var ranges = await chunkBFast.getRanges(); - const keys = [...ranges.keys()]; - var bfasts = await Promise.all(keys.map(k => chunkBFast.getBfast(k))); - var meshes = await Promise.all(bfasts.map(b => g3dMesh_1.G3dMesh.createFromBfast(b))); - const scene = await this.scene.get(); - meshes.forEach(m => m.scene = scene); - return meshes; + return g3dChunk_1.G3dChunk.createFromBfast(chunkBFast); } async getMesh(mesh) { var scene = await this.scene.get(); - var chunk = scene.meshChunks[mesh]; - if (chunk === undefined) + var meshChunk = scene.meshChunks[mesh]; + if (meshChunk === undefined) return undefined; - var meshes = await this.getChunk(chunk); - if (meshes === undefined) - return undefined; - var index = scene.meshChunkIndices[mesh]; - var result = meshes[index]; - if (result === undefined) + var chunk = await this.getChunk(meshChunk); + if (chunk === undefined) return undefined; - result.meshIndex = mesh; - return result; + return new g3dMesh_1.G3dMesh(scene, chunk, scene.meshChunkIndices[mesh]); } } exports.RemoteVimx = RemoteVimx; diff --git a/src/ts/dist/types/g3d.d.ts b/src/ts/dist/types/g3d.d.ts index bba0b4a2..f1599699 100644 --- a/src/ts/dist/types/g3d.d.ts +++ b/src/ts/dist/types/g3d.d.ts @@ -1,7 +1,6 @@ /** * @module vim-ts */ -import { AbstractG3d } from './abstractG3d'; import { BFast } from './bfast'; export declare type MeshSection = 'opaque' | 'transparent' | 'all'; /** @@ -43,7 +42,6 @@ export declare class G3d { meshOpaqueCount: Int32Array; submeshVertexStart: Int32Array; submeshVertexEnd: Int32Array; - rawG3d: AbstractG3d; static MATRIX_SIZE: number; static COLOR_SIZE: number; static POSITION_SIZE: number; @@ -53,7 +51,6 @@ export declare class G3d { DEFAULT_COLOR: Float32Array; constructor(instanceMeshes: Int32Array, instanceFlags: Uint16Array | undefined, instanceTransforms: Float32Array, instanceNodes: Int32Array | undefined, meshSubmeshes: Int32Array, submeshIndexOffsets: Int32Array, submeshMaterials: Int32Array, indices: Int32Array | Uint32Array, positions: Float32Array, materialColors: Float32Array); private computeSubmeshVertexRange; - static createFromAbstract(g3d: AbstractG3d): G3d; static createFromPath(path: string): Promise; static createFromBfast(bfast: BFast): Promise; /** diff --git a/src/ts/dist/types/g3dMesh.d.ts b/src/ts/dist/types/g3dMesh.d.ts index 30c17da2..637da62d 100644 --- a/src/ts/dist/types/g3dMesh.d.ts +++ b/src/ts/dist/types/g3dMesh.d.ts @@ -1,52 +1,33 @@ /** * @module vim-ts */ -import { BFast } from './bfast'; +import { G3dChunk } from './g3dChunk'; import { MeshSection } from './g3d'; import { G3dScene } from './g3dScene'; /** * See https://github.com/vimaec/vim#vim-geometry-attributes */ export declare class MeshAttributes { + static meshSubmeshOffset: string; static meshOpaqueSubmeshCount: string; static submeshIndexOffsets: string; static submeshVertexOffsets: string; static submeshMaterials: string; static positions: string; static indices: string; - static all: string[]; } -/** - * G3D is a simple, efficient, generic binary format for storing and transmitting geometry. - * The G3D format is designed to be used either as a serialization format or as an in-memory data structure. - * A G3d with specific attributes according to the VIM format specification. - * See https://github.com/vimaec/vim#vim-geometry-attributes for the vim specification. - * See https://github.com/vimaec/g3d for the g3d specification. - */ export declare class G3dMesh { - scene: G3dScene; - meshIndex: number; - readonly meshOpaqueSubmeshCount: number; - readonly submeshIndexOffset: Int32Array; - readonly submeshVertexOffset: Int32Array; - readonly submeshMaterial: Int32Array; - readonly positions: Float32Array; - readonly indices: Uint32Array; - static readonly COLOR_SIZE = 4; - static readonly POSITION_SIZE = 3; - /** - * Opaque white - */ - static readonly DEFAULT_COLOR: Float32Array; - constructor(meshOpaqueSubmeshCount: number, submeshIndexOffsets: Int32Array, submeshVertexOffsets: Int32Array, submeshMaterials: Int32Array, indices: Int32Array | Uint32Array, positions: Float32Array); - static createFromBfast(bfast: BFast): Promise; + readonly scene: G3dScene; + readonly chunk: G3dChunk; + readonly index: number; + constructor(scene: G3dScene, chunk: G3dChunk, index: number); getVertexStart(section?: MeshSection): number; getVertexEnd(section?: MeshSection): number; getVertexCount(section?: MeshSection): number; getIndexStart(section?: MeshSection): number; getIndexEnd(section?: MeshSection): number; getIndexCount(section?: MeshSection): number; - getHasTransparency(): boolean; + getHasTransparency(mesh: number): boolean; getSubmeshStart(section: MeshSection): number; getSubmeshEnd(section: MeshSection): number; getSubmeshCount(section: MeshSection): number; diff --git a/src/ts/dist/types/g3dScene.d.ts b/src/ts/dist/types/g3dScene.d.ts index 4cb2d42b..f87ace78 100644 --- a/src/ts/dist/types/g3dScene.d.ts +++ b/src/ts/dist/types/g3dScene.d.ts @@ -19,7 +19,6 @@ export declare class SceneAttributes { static readonly instanceMaxs = "g3d:instance:max:0:float32:3"; static readonly meshChunk = "g3d:mesh:chunk:0:int32:1"; static readonly meshChunkIndices = "g3d:mesh:chunkindex:0:int32:1"; - static readonly meshInstanceCounts = "g3d:mesh:instancecount:0:int32:1"; static readonly meshIndexCounts = "g3d:mesh:indexcount:0:int32:1"; static readonly meshVertexCounts = "g3d:mesh:vertexcount:0:int32:1"; static readonly meshOpaqueIndexCount = "g3d:mesh:opaqueindexcount:0:int32:1"; @@ -42,18 +41,16 @@ export declare class G3dScene { instanceMaxs: Float32Array; meshChunks: Int32Array; meshChunkIndices: Int32Array; - meshInstanceCounts: Int32Array; meshIndexCounts: Int32Array; meshVertexCounts: Int32Array; meshOpaqueIndexCounts: Int32Array; meshOpaqueVertexCounts: Int32Array; private nodeToInstance; - constructor(chunkCount: Int32Array, instanceMeshes: Int32Array, instanceMatrices: Float32Array, instanceNodes: Int32Array, instanceGroups: Int32Array, instanceTags: BigInt64Array, instanceFlags: Uint16Array, instanceMins: Float32Array, instanceMaxs: Float32Array, meshChunks: Int32Array, meshChunkIndices: Int32Array, meshInstanceCounts: Int32Array, meshIndexCounts: Int32Array, meshVertexCounts: Int32Array, meshOpaqueIndexCounts: Int32Array, meshOpaqueVertexCounts: Int32Array); + constructor(chunkCount: Int32Array, instanceMeshes: Int32Array, instanceMatrices: Float32Array, instanceNodes: Int32Array, instanceGroups: Int32Array, instanceTags: BigInt64Array, instanceFlags: Uint16Array, instanceMins: Float32Array, instanceMaxs: Float32Array, meshChunks: Int32Array, meshChunkIndices: Int32Array, meshIndexCounts: Int32Array, meshVertexCounts: Int32Array, meshOpaqueIndexCounts: Int32Array, meshOpaqueVertexCounts: Int32Array); static createFromBfast(bfast: BFast): Promise; getMeshCount(): number; getMeshIndexCount(mesh: number, section: MeshSection): number; getMeshVertexCount(mesh: number, section: MeshSection): number; - getMeshInstanceCount(mesh: number): number; getInstanceMin(instance: number): Float32Array; getInstanceMax(instance: number): Float32Array; getInstanceMatrix(instance: number): Float32Array; diff --git a/src/ts/dist/types/index.d.ts b/src/ts/dist/types/index.d.ts index e3775c32..b90db4ff 100644 --- a/src/ts/dist/types/index.d.ts +++ b/src/ts/dist/types/index.d.ts @@ -1,11 +1,9 @@ export * from './bfast'; -export * from './abstractG3d'; export * from './g3d'; export * from './remoteVimx'; export * from './g3dMaterials'; export * from './g3dMesh'; export * from './g3dScene'; -export * from './remoteG3d'; export * from './remoteBuffer'; export * from './requestTracker'; export * from './requester'; diff --git a/src/ts/dist/types/remoteVimx.d.ts b/src/ts/dist/types/remoteVimx.d.ts index 7bdf3878..9286f409 100644 --- a/src/ts/dist/types/remoteVimx.d.ts +++ b/src/ts/dist/types/remoteVimx.d.ts @@ -1,12 +1,13 @@ import { BFast } from "./bfast"; import { G3dMaterial as G3dMaterials } from "./g3dMaterials"; -import { G3dMesh } from "./g3dMesh"; +import { G3dChunk } from './g3dChunk'; import { G3dScene } from "./g3dScene"; import { RemoteValue } from "./remoteValue"; +import { G3dMesh } from "./g3dMesh"; export declare class RemoteVimx { bfast: BFast; scene: RemoteValue; - chunkCache: Map>; + chunkCache: Map>; constructor(source: BFast | ArrayBuffer | string); /** * Aborts all downloads from the underlying BFAST. @@ -29,7 +30,7 @@ export declare class RemoteVimx { /** * Fetches and returns the vimx G3dMesh with given index */ - getChunk(chunk: number): Promise; + getChunk(chunk: number): Promise; private requestChunk; getMesh(mesh: number): Promise; } diff --git a/src/ts/package.json b/src/ts/package.json index 9863b633..0853030f 100644 --- a/src/ts/package.json +++ b/src/ts/package.json @@ -1,6 +1,6 @@ { "name": "vim-format", - "version": "1.0.6-dev.230", + "version": "1.0.6-dev.235", "description": "The VIM format is a modern and efficient open 3D data interchange format designed for BIM and manufacturing data optimized for efficient loading and rendering on low-power devices.", "directories": { "test": "tests" @@ -8,7 +8,7 @@ "scripts": { "declarations": "tsc --declaration --emitDeclarationOnly --outdir ./dist/types", "build": "tsc", - "package": "npm run build && npm run declarations && npm publish", + "package": "npm run build && npm run declarations && npm publish", "test": "jest" }, "author": "VIM ", diff --git a/src/ts/src/g3dChunk.ts b/src/ts/src/g3dChunk.ts new file mode 100644 index 00000000..9bc94bc6 --- /dev/null +++ b/src/ts/src/g3dChunk.ts @@ -0,0 +1,71 @@ +import { BFast } from './bfast'; + +/** + * G3D is a simple, efficient, generic binary format for storing and transmitting geometry. + * The G3D format is designed to be used either as a serialization format or as an in-memory data structure. + * A G3d with specific attributes according to the VIM format specification. + * See https://github.com/vimaec/vim#vim-geometry-attributes for the vim specification. + * See https://github.com/vimaec/g3d for the g3d specification. + */ + +/** + * See https://github.com/vimaec/vim#vim-geometry-attributes + */ +export class MeshAttributes { + static meshSubmeshOffset = 'g3d:mesh:submeshOffset:0:int32:1' + static meshOpaqueSubmeshCount = 'g3d:mesh:opaquesubmeshcount:0:int32:1' + static submeshIndexOffsets = 'g3d:submesh:indexoffset:0:int32:1' + static submeshVertexOffsets = 'g3d:submesh:vertexoffset:0:int32:1' + static submeshMaterials = 'g3d:submesh:material:0:int32:1' + static positions = 'g3d:vertex:position:0:float32:3' + static indices = 'g3d:corner:index:0:int32:1' +} + +export class G3dChunk { + readonly meshSubmeshOffset: Int32Array; + readonly meshOpaqueSubmeshCount: Int32Array; + readonly submeshIndexOffset: Int32Array; + readonly submeshVertexOffset: Int32Array; + readonly submeshMaterial: Int32Array; + readonly positions: Float32Array; + readonly indices: Uint32Array; + + static readonly COLOR_SIZE = 4; + static readonly POSITION_SIZE = 3; + /** + * Opaque white + */ + static readonly DEFAULT_COLOR = new Float32Array([1, 1, 1, 1]); + + constructor( + meshSubmeshOffset: Int32Array, + meshOpaqueSubmeshCount: Int32Array, + submeshIndexOffsets: Int32Array, + submeshVertexOffsets: Int32Array, + submeshMaterials: Int32Array, + indices: Int32Array | Uint32Array, + positions: Float32Array + ) { + this.meshSubmeshOffset = meshSubmeshOffset; + this.meshOpaqueSubmeshCount = meshOpaqueSubmeshCount; + this.submeshIndexOffset = submeshIndexOffsets; + this.submeshVertexOffset = submeshVertexOffsets; + this.submeshMaterial = submeshMaterials; + this.indices = indices instanceof Uint32Array ? indices : new Uint32Array(indices.buffer); + this.positions = positions; + } + + static async createFromBfast(bfast: BFast) { + const values = await Promise.all([ + bfast.getInt32Array(MeshAttributes.meshSubmeshOffset), + bfast.getInt32Array(MeshAttributes.meshOpaqueSubmeshCount), + bfast.getInt32Array(MeshAttributes.submeshIndexOffsets), + bfast.getInt32Array(MeshAttributes.submeshVertexOffsets), + bfast.getInt32Array(MeshAttributes.submeshMaterials), + bfast.getInt32Array(MeshAttributes.indices), + bfast.getFloat32Array(MeshAttributes.positions) + ]); + + return new G3dChunk(...values); + } +} diff --git a/src/ts/src/g3dMesh.ts b/src/ts/src/g3dMesh.ts index 1d349282..cc0d3b32 100644 --- a/src/ts/src/g3dMesh.ts +++ b/src/ts/src/g3dMesh.ts @@ -2,90 +2,24 @@ * @module vim-ts */ -import { BFast } from './bfast' +import { G3dChunk } from './g3dChunk' import { G3d, MeshSection } from './g3d' import { G3dScene } from './g3dScene' -/** - * See https://github.com/vimaec/vim#vim-geometry-attributes - */ -export class MeshAttributes { - - static meshOpaqueSubmeshCount = 'g3d:mesh:opaquesubmeshcount:0:int32:1' - static submeshIndexOffsets = 'g3d:submesh:indexoffset:0:int32:1' - static submeshVertexOffsets = 'g3d:submesh:vertexoffset:0:int32:1' - static submeshMaterials = 'g3d:submesh:material:0:int32:1' - static positions = 'g3d:vertex:position:0:float32:3' - static indices = 'g3d:corner:index:0:int32:1' - - static all = [ - MeshAttributes.meshOpaqueSubmeshCount, - MeshAttributes.submeshIndexOffsets, - MeshAttributes.submeshVertexOffsets, - MeshAttributes.submeshMaterials, - MeshAttributes.positions, - MeshAttributes.indices, - ] -} +export class G3dMesh +{ + readonly scene : G3dScene + readonly chunk: G3dChunk + readonly index : number -/** - * G3D is a simple, efficient, generic binary format for storing and transmitting geometry. - * The G3D format is designed to be used either as a serialization format or as an in-memory data structure. - * A G3d with specific attributes according to the VIM format specification. - * See https://github.com/vimaec/vim#vim-geometry-attributes for the vim specification. - * See https://github.com/vimaec/g3d for the g3d specification. - */ -export class G3dMesh { - - scene: G3dScene - meshIndex: number - readonly meshOpaqueSubmeshCount : number - readonly submeshIndexOffset: Int32Array - readonly submeshVertexOffset: Int32Array - readonly submeshMaterial: Int32Array - - readonly positions: Float32Array - readonly indices: Uint32Array - - static readonly COLOR_SIZE = 4 - static readonly POSITION_SIZE = 3 - /** - * Opaque white - */ - static readonly DEFAULT_COLOR = new Float32Array([1, 1, 1, 1]) - - constructor( - meshOpaqueSubmeshCount : number, - submeshIndexOffsets : Int32Array, - submeshVertexOffsets : Int32Array, - submeshMaterials : Int32Array, - indices: Int32Array | Uint32Array, - positions: Float32Array, - ){ - - this.meshOpaqueSubmeshCount = meshOpaqueSubmeshCount - this.submeshIndexOffset = submeshIndexOffsets - this.submeshVertexOffset = submeshVertexOffsets - this.submeshMaterial = submeshMaterials - this.indices = indices instanceof Uint32Array ? indices : new Uint32Array(indices.buffer) - this.positions = positions - } - - static async createFromBfast (bfast: BFast) { - const values = await Promise.all([ - bfast.getValue(MeshAttributes.meshOpaqueSubmeshCount, 0).then(v => v as number), - bfast.getInt32Array(MeshAttributes.submeshIndexOffsets), - bfast.getInt32Array(MeshAttributes.submeshVertexOffsets), - bfast.getInt32Array(MeshAttributes.submeshMaterials), - bfast.getInt32Array(MeshAttributes.indices), - bfast.getFloat32Array(MeshAttributes.positions) - ]) - - return new G3dMesh(...values) + constructor(scene : G3dScene, chunk: G3dChunk, index : number) + { + this.scene = scene + this.chunk = chunk + this.index = index } // ------------- Mesh ----------------- - getVertexStart(section: MeshSection = 'all'){ const sub = this.getSubmeshStart(section) return this.getSubmeshVertexStart(sub) @@ -114,21 +48,28 @@ export class G3dMesh { return this.getIndexEnd(section) - this.getIndexStart(section) } - getHasTransparency () { - return this.meshOpaqueSubmeshCount < this.submeshIndexOffset.length} + getHasTransparency (mesh: number) { + return this.getSubmeshCount('transparent') > 0 + } // ------------- Submeshes ----------------- getSubmeshStart(section: MeshSection){ - if(section === 'all') return 0 - if(section === 'opaque') return 0 - return this.meshOpaqueSubmeshCount + if(section === 'all' || section === 'opaque'){ + return this.chunk.meshSubmeshOffset[this.index] + } + return this.chunk.meshSubmeshOffset[this.index] + this.chunk.meshOpaqueSubmeshCount[this.index] } getSubmeshEnd(section: MeshSection){ - if(section === 'all') return this.submeshIndexOffset.length - if(section === 'transparent') return this.submeshIndexOffset.length - return this.meshOpaqueSubmeshCount + if(section === 'opaque'){ + return this.chunk.meshSubmeshOffset[this.index] + this.chunk.meshOpaqueSubmeshCount[this.index] + } + if(this.index + 1 < this.chunk.meshSubmeshOffset.length){ + return this.chunk.meshSubmeshOffset[this.index + 1] + } + + return this.chunk.submeshIndexOffset.length } getSubmeshCount(section: MeshSection){ @@ -136,15 +77,15 @@ export class G3dMesh { } getSubmeshIndexStart (submesh: number): number { - return submesh < this.submeshIndexOffset.length - ? this.submeshIndexOffset[submesh] - : this.indices.length + return submesh < this.chunk.submeshIndexOffset.length + ? this.chunk.submeshIndexOffset[submesh] + : this.chunk.indices.length } getSubmeshIndexEnd (submesh: number): number { - return submesh < this.submeshIndexOffset.length - 1 - ? this.submeshIndexOffset[submesh + 1] - : this.indices.length + return submesh < this.chunk.submeshIndexOffset.length - 1 + ? this.chunk.submeshIndexOffset[submesh + 1] + : this.chunk.indices.length } getSubmeshIndexCount (submesh: number): number { @@ -152,22 +93,18 @@ export class G3dMesh { } getSubmeshVertexStart(submesh: number){ - return submesh < this.submeshIndexOffset.length - ? this.submeshVertexOffset[submesh] - : this.positions.length / G3d.POSITION_SIZE + return submesh < this.chunk.submeshIndexOffset.length + ? this.chunk.submeshVertexOffset[submesh] + : this.chunk.positions.length / G3d.POSITION_SIZE } getSubmeshVertexEnd (submesh: number): number { - return submesh < this.submeshVertexOffset.length - 1 - ? this.submeshVertexOffset[submesh + 1] - : this.positions.length / G3d.POSITION_SIZE + return submesh < this.chunk.submeshVertexOffset.length - 1 + ? this.chunk.submeshVertexOffset[submesh + 1] + : this.chunk.positions.length / G3d.POSITION_SIZE } getSubmeshVertexCount (submesh: number): number { return this.getSubmeshVertexEnd(submesh) - this.getSubmeshVertexStart(submesh) } - - // ------------- Instances ----------------- - } - diff --git a/src/ts/src/remoteVimx.ts b/src/ts/src/remoteVimx.ts index d7ddc92a..73e6c2b1 100644 --- a/src/ts/src/remoteVimx.ts +++ b/src/ts/src/remoteVimx.ts @@ -1,14 +1,15 @@ import { BFast } from "./bfast"; import { G3dMaterial as G3dMaterials } from "./g3dMaterials"; -import { G3dMesh } from "./g3dMesh"; +import { G3dChunk } from './g3dChunk'; import { G3dScene } from "./g3dScene"; import { RemoteValue } from "./remoteValue"; import { requestHeader } from "./vimHeader"; +import { G3dMesh } from "./g3dMesh"; export class RemoteVimx{ bfast : BFast scene : RemoteValue - chunkCache = new Map>() + chunkCache = new Map>() constructor(source : BFast | ArrayBuffer | string){ this.bfast = source instanceof BFast ? source : new BFast(source) @@ -63,35 +64,24 @@ export class RemoteVimx{ if(cached !== undefined){ return cached.get() } - var value = new RemoteValue(() => this.requestChunk(chunk)) + var value = new RemoteValue(() => this.requestChunk(chunk)) this.chunkCache.set(chunk, value) return value.get() } private async requestChunk(chunk : number){ const chunkBFast = await this.bfast.getLocalBfast(`chunk_${chunk}`, true) - var ranges = await chunkBFast.getRanges() - const keys = [...ranges.keys()] - var bfasts = await Promise.all(keys.map(k => chunkBFast.getBfast(k))) - var meshes = await Promise.all(bfasts.map(b => G3dMesh.createFromBfast(b))) - const scene = await this.scene.get() - meshes.forEach(m => m.scene = scene) - return meshes + return G3dChunk.createFromBfast(chunkBFast) } async getMesh(mesh: number){ var scene = await this.scene.get() - var chunk = scene.meshChunks[mesh] - if(chunk === undefined) return undefined + var meshChunk = scene.meshChunks[mesh] + if(meshChunk === undefined) return undefined - var meshes = await this.getChunk(chunk) - if(meshes === undefined) return undefined - - var index = scene.meshChunkIndices[mesh] - var result = meshes[index] - if(result === undefined) return undefined + var chunk = await this.getChunk(meshChunk) + if(chunk === undefined) return undefined - result.meshIndex = mesh - return result + return new G3dMesh(scene, chunk, scene.meshChunkIndices[mesh]) } } \ No newline at end of file From 83adbe79b81b29ba519a1f5dd4d2b4757a24498d Mon Sep 17 00:00:00 2001 From: simon Date: Wed, 10 Jan 2024 18:25:29 -0500 Subject: [PATCH 040/111] vimx mamacos optims --- .../Vim.G3dNext.Attributes/Attributes.g.cs | 214 ++++-------- .../{G3dMesh.cs => G3dChunk.cs} | 11 +- .../Vim.G3dNext.Attributes/MeshAttributes.cs | 48 ++- src/cs/vim/Vim.Format.Core/G3dBuilder.cs | 4 +- .../Vim.Format.Vimx.Conversion/Chunking.cs | 316 ++++++++++++++++++ .../MeshesToScene.cs | 106 ------ .../{VimxOrdering.cs => Ordering.cs} | 65 ++-- .../Vim.Format.Vimx.Conversion/VimToMeshes.cs | 198 ----------- .../VimxConverter.cs | 312 ++++++++++------- src/cs/vim/Vim.Format.Vimx/Vimx.cs | 7 +- src/cs/vim/Vim.Format.Vimx/VimxChunk.cs | 6 +- src/cs/vim/Vim.Vimx.Test/VimxActions.cs | 18 +- 12 files changed, 656 insertions(+), 649 deletions(-) rename src/cs/g3d/Vim.G3dNext.Attributes/{G3dMesh.cs => G3dChunk.cs} (93%) create mode 100644 src/cs/vim/Vim.Format.Vimx.Conversion/Chunking.cs delete mode 100644 src/cs/vim/Vim.Format.Vimx.Conversion/MeshesToScene.cs rename src/cs/vim/Vim.Format.Vimx.Conversion/{VimxOrdering.cs => Ordering.cs} (51%) delete mode 100644 src/cs/vim/Vim.Format.Vimx.Conversion/VimToMeshes.cs diff --git a/src/cs/g3d/Vim.G3dNext.Attributes/Attributes.g.cs b/src/cs/g3d/Vim.G3dNext.Attributes/Attributes.g.cs index 7b680ac8..552b0153 100644 --- a/src/cs/g3d/Vim.G3dNext.Attributes/Attributes.g.cs +++ b/src/cs/g3d/Vim.G3dNext.Attributes/Attributes.g.cs @@ -1539,52 +1539,7 @@ public void Write(Stream stream) } } - public partial class MeshInstanceTransformsAttribute : IAttribute - { - public const string AttributeName = "g3d:instance:transform:0:float32:16"; - - public string Name - => AttributeName; - - public int Count => TypedData?.Length ?? 0; - - public void AddTo(BFast bfast) - { - if(TypedData != null) - { - bfast.SetArray(Name, TypedData); - } - } - - public void ReadBFast(BFast bfast) - { - TypedData = bfast.GetArray("g3d:instance:transform:0:float32:16"); - } - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Data; - - public Type IndexInto { get; } - = null; - - public Vim.Math3d.Matrix4x4[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - - public partial class MeshOpaqueSubmeshCountsAttribute : IAttribute + public partial class ChunkMeshOpaqueSubmeshCountsAttribute : IAttribute { public const string AttributeName = "g3d:mesh:opaquesubmeshcount:0:int32:1"; @@ -1629,7 +1584,7 @@ public void Write(Stream stream) } } - public partial class MeshSubmeshOffsetAttribute : IAttribute + public partial class ChunkMeshSubmeshOffsetAttribute : IAttribute { public const string AttributeName = "g3d:mesh:submeshOffset:0:int32:1"; @@ -1658,7 +1613,7 @@ public void ReadBFast(BFast bfast) = AttributeType.Index; public Type IndexInto { get; } - = typeof(Vim.G3dNext.Attributes.MeshIndicesAttribute); + = typeof(Vim.G3dNext.Attributes.ChunkIndicesAttribute); public System.Int32[] TypedData { get; set; } = Array.Empty(); @@ -1674,7 +1629,7 @@ public void Write(Stream stream) } } - public partial class MeshSubmeshIndexOffsetsAttribute : IAttribute + public partial class ChunkSubmeshIndexOffsetsAttribute : IAttribute { public const string AttributeName = "g3d:submesh:indexoffset:0:int32:1"; @@ -1703,7 +1658,7 @@ public void ReadBFast(BFast bfast) = AttributeType.Index; public Type IndexInto { get; } - = typeof(Vim.G3dNext.Attributes.MeshIndicesAttribute); + = typeof(Vim.G3dNext.Attributes.ChunkIndicesAttribute); public System.Int32[] TypedData { get; set; } = Array.Empty(); @@ -1719,7 +1674,7 @@ public void Write(Stream stream) } } - public partial class MeshSubmeshVertexOffsetsAttribute : IAttribute + public partial class ChunkSubmeshVertexOffsetsAttribute : IAttribute { public const string AttributeName = "g3d:submesh:vertexoffset:0:int32:1"; @@ -1748,7 +1703,7 @@ public void ReadBFast(BFast bfast) = AttributeType.Index; public Type IndexInto { get; } - = typeof(Vim.G3dNext.Attributes.MeshIndicesAttribute); + = typeof(Vim.G3dNext.Attributes.ChunkIndicesAttribute); public System.Int32[] TypedData { get; set; } = Array.Empty(); @@ -1764,7 +1719,7 @@ public void Write(Stream stream) } } - public partial class MeshSubmeshMaterialsAttribute : IAttribute + public partial class ChunkSubmeshMaterialsAttribute : IAttribute { public const string AttributeName = "g3d:submesh:material:0:int32:1"; @@ -1809,7 +1764,7 @@ public void Write(Stream stream) } } - public partial class MeshPositionsAttribute : IAttribute + public partial class ChunkPositionsAttribute : IAttribute { public const string AttributeName = "g3d:vertex:position:0:float32:3"; @@ -1854,7 +1809,7 @@ public void Write(Stream stream) } } - public partial class MeshIndicesAttribute : IAttribute + public partial class ChunkIndicesAttribute : IAttribute { public const string AttributeName = "g3d:corner:index:0:int32:1"; @@ -1883,7 +1838,7 @@ public void ReadBFast(BFast bfast) = AttributeType.Index; public Type IndexInto { get; } - = typeof(Vim.G3dNext.Attributes.MeshPositionsAttribute); + = typeof(Vim.G3dNext.Attributes.ChunkPositionsAttribute); public System.Int32[] TypedData { get; set; } = Array.Empty(); @@ -3022,21 +2977,21 @@ public void Validate() } // Please provide an explicit implementation in another partial class file. - public partial class G3dMesh : ISetup + public partial class G3dChunk : ISetup { - public MeshAttributeCollection Attributes; + public ChunkAttributeCollection Attributes; - public G3dMesh() : this(new MeshAttributeCollection()) + public G3dChunk() : this(new ChunkAttributeCollection()) { // empty } - public G3dMesh(BFast bfast) : this(new MeshAttributeCollection(bfast)) + public G3dChunk(BFast bfast) : this(new ChunkAttributeCollection(bfast)) { // empty } - public G3dMesh(MeshAttributeCollection attributes) + public G3dChunk(ChunkAttributeCollection attributes) { Attributes = attributes; @@ -3048,12 +3003,6 @@ public BFast ToBFast() => Attributes.ToBFast(); - public Vim.Math3d.Matrix4x4[] InstanceTransforms - { - get => Attributes.InstanceTransforms.TypedData; - set => Attributes.InstanceTransforms.TypedData = value; - } - public System.Int32[] MeshSubmeshOffset { get => Attributes.MeshSubmeshOffset.TypedData; @@ -3098,14 +3047,14 @@ public System.Int32[] Indices } - public partial class MeshAttributeCollection : IAttributeCollection + public partial class ChunkAttributeCollection : IAttributeCollection { - public MeshAttributeCollection() + public ChunkAttributeCollection() { // empty } - public MeshAttributeCollection(BFast bfast) + public ChunkAttributeCollection(BFast bfast) { this.ReadAttributes(bfast); } @@ -3121,64 +3070,57 @@ public void ReadAttributes(BFast bfast) public IDictionary Map { get; } = new Dictionary { - [Vim.G3dNext.Attributes.MeshInstanceTransformsAttribute.AttributeName] = new Vim.G3dNext.Attributes.MeshInstanceTransformsAttribute(), - [Vim.G3dNext.Attributes.MeshSubmeshOffsetAttribute.AttributeName] = new Vim.G3dNext.Attributes.MeshSubmeshOffsetAttribute(), - [Vim.G3dNext.Attributes.MeshOpaqueSubmeshCountsAttribute.AttributeName] = new Vim.G3dNext.Attributes.MeshOpaqueSubmeshCountsAttribute(), - [Vim.G3dNext.Attributes.MeshSubmeshIndexOffsetsAttribute.AttributeName] = new Vim.G3dNext.Attributes.MeshSubmeshIndexOffsetsAttribute(), - [Vim.G3dNext.Attributes.MeshSubmeshVertexOffsetsAttribute.AttributeName] = new Vim.G3dNext.Attributes.MeshSubmeshVertexOffsetsAttribute(), - [Vim.G3dNext.Attributes.MeshSubmeshMaterialsAttribute.AttributeName] = new Vim.G3dNext.Attributes.MeshSubmeshMaterialsAttribute(), - [Vim.G3dNext.Attributes.MeshPositionsAttribute.AttributeName] = new Vim.G3dNext.Attributes.MeshPositionsAttribute(), - [Vim.G3dNext.Attributes.MeshIndicesAttribute.AttributeName] = new Vim.G3dNext.Attributes.MeshIndicesAttribute(), + [Vim.G3dNext.Attributes.ChunkMeshSubmeshOffsetAttribute.AttributeName] = new Vim.G3dNext.Attributes.ChunkMeshSubmeshOffsetAttribute(), + [Vim.G3dNext.Attributes.ChunkMeshOpaqueSubmeshCountsAttribute.AttributeName] = new Vim.G3dNext.Attributes.ChunkMeshOpaqueSubmeshCountsAttribute(), + [Vim.G3dNext.Attributes.ChunkSubmeshIndexOffsetsAttribute.AttributeName] = new Vim.G3dNext.Attributes.ChunkSubmeshIndexOffsetsAttribute(), + [Vim.G3dNext.Attributes.ChunkSubmeshVertexOffsetsAttribute.AttributeName] = new Vim.G3dNext.Attributes.ChunkSubmeshVertexOffsetsAttribute(), + [Vim.G3dNext.Attributes.ChunkSubmeshMaterialsAttribute.AttributeName] = new Vim.G3dNext.Attributes.ChunkSubmeshMaterialsAttribute(), + [Vim.G3dNext.Attributes.ChunkPositionsAttribute.AttributeName] = new Vim.G3dNext.Attributes.ChunkPositionsAttribute(), + [Vim.G3dNext.Attributes.ChunkIndicesAttribute.AttributeName] = new Vim.G3dNext.Attributes.ChunkIndicesAttribute(), }; // Named Attributes. - public Vim.G3dNext.Attributes.MeshInstanceTransformsAttribute InstanceTransforms - { - get => Map.TryGetValue(Vim.G3dNext.Attributes.MeshInstanceTransformsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshInstanceTransformsAttribute : default; - set => Map[Vim.G3dNext.Attributes.MeshInstanceTransformsAttribute.AttributeName] = value as IAttribute; - } - - public Vim.G3dNext.Attributes.MeshSubmeshOffsetAttribute MeshSubmeshOffset + public Vim.G3dNext.Attributes.ChunkMeshSubmeshOffsetAttribute MeshSubmeshOffset { - get => Map.TryGetValue(Vim.G3dNext.Attributes.MeshSubmeshOffsetAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshSubmeshOffsetAttribute : default; - set => Map[Vim.G3dNext.Attributes.MeshSubmeshOffsetAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.ChunkMeshSubmeshOffsetAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.ChunkMeshSubmeshOffsetAttribute : default; + set => Map[Vim.G3dNext.Attributes.ChunkMeshSubmeshOffsetAttribute.AttributeName] = value as IAttribute; } - public Vim.G3dNext.Attributes.MeshOpaqueSubmeshCountsAttribute MeshOpaqueSubmeshCounts + public Vim.G3dNext.Attributes.ChunkMeshOpaqueSubmeshCountsAttribute MeshOpaqueSubmeshCounts { - get => Map.TryGetValue(Vim.G3dNext.Attributes.MeshOpaqueSubmeshCountsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshOpaqueSubmeshCountsAttribute : default; - set => Map[Vim.G3dNext.Attributes.MeshOpaqueSubmeshCountsAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.ChunkMeshOpaqueSubmeshCountsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.ChunkMeshOpaqueSubmeshCountsAttribute : default; + set => Map[Vim.G3dNext.Attributes.ChunkMeshOpaqueSubmeshCountsAttribute.AttributeName] = value as IAttribute; } - public Vim.G3dNext.Attributes.MeshSubmeshIndexOffsetsAttribute SubmeshIndexOffsets + public Vim.G3dNext.Attributes.ChunkSubmeshIndexOffsetsAttribute SubmeshIndexOffsets { - get => Map.TryGetValue(Vim.G3dNext.Attributes.MeshSubmeshIndexOffsetsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshSubmeshIndexOffsetsAttribute : default; - set => Map[Vim.G3dNext.Attributes.MeshSubmeshIndexOffsetsAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.ChunkSubmeshIndexOffsetsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.ChunkSubmeshIndexOffsetsAttribute : default; + set => Map[Vim.G3dNext.Attributes.ChunkSubmeshIndexOffsetsAttribute.AttributeName] = value as IAttribute; } - public Vim.G3dNext.Attributes.MeshSubmeshVertexOffsetsAttribute SubmeshVertexOffsets + public Vim.G3dNext.Attributes.ChunkSubmeshVertexOffsetsAttribute SubmeshVertexOffsets { - get => Map.TryGetValue(Vim.G3dNext.Attributes.MeshSubmeshVertexOffsetsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshSubmeshVertexOffsetsAttribute : default; - set => Map[Vim.G3dNext.Attributes.MeshSubmeshVertexOffsetsAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.ChunkSubmeshVertexOffsetsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.ChunkSubmeshVertexOffsetsAttribute : default; + set => Map[Vim.G3dNext.Attributes.ChunkSubmeshVertexOffsetsAttribute.AttributeName] = value as IAttribute; } - public Vim.G3dNext.Attributes.MeshSubmeshMaterialsAttribute SubmeshMaterials + public Vim.G3dNext.Attributes.ChunkSubmeshMaterialsAttribute SubmeshMaterials { - get => Map.TryGetValue(Vim.G3dNext.Attributes.MeshSubmeshMaterialsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshSubmeshMaterialsAttribute : default; - set => Map[Vim.G3dNext.Attributes.MeshSubmeshMaterialsAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.ChunkSubmeshMaterialsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.ChunkSubmeshMaterialsAttribute : default; + set => Map[Vim.G3dNext.Attributes.ChunkSubmeshMaterialsAttribute.AttributeName] = value as IAttribute; } - public Vim.G3dNext.Attributes.MeshPositionsAttribute Positions + public Vim.G3dNext.Attributes.ChunkPositionsAttribute Positions { - get => Map.TryGetValue(Vim.G3dNext.Attributes.MeshPositionsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshPositionsAttribute : default; - set => Map[Vim.G3dNext.Attributes.MeshPositionsAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.ChunkPositionsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.ChunkPositionsAttribute : default; + set => Map[Vim.G3dNext.Attributes.ChunkPositionsAttribute.AttributeName] = value as IAttribute; } - public Vim.G3dNext.Attributes.MeshIndicesAttribute Indices + public Vim.G3dNext.Attributes.ChunkIndicesAttribute Indices { - get => Map.TryGetValue(Vim.G3dNext.Attributes.MeshIndicesAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MeshIndicesAttribute : default; - set => Map[Vim.G3dNext.Attributes.MeshIndicesAttribute.AttributeName] = value as IAttribute; + get => Map.TryGetValue(Vim.G3dNext.Attributes.ChunkIndicesAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.ChunkIndicesAttribute : default; + set => Map[Vim.G3dNext.Attributes.ChunkIndicesAttribute.AttributeName] = value as IAttribute; } /// @@ -3186,35 +3128,31 @@ public IAttribute GetAttribute(Type attributeType) { - if (attributeType == typeof(Vim.G3dNext.Attributes.MeshInstanceTransformsAttribute)) - return InstanceTransforms; - - - if (attributeType == typeof(Vim.G3dNext.Attributes.MeshSubmeshOffsetAttribute)) + if (attributeType == typeof(Vim.G3dNext.Attributes.ChunkMeshSubmeshOffsetAttribute)) return MeshSubmeshOffset; - if (attributeType == typeof(Vim.G3dNext.Attributes.MeshOpaqueSubmeshCountsAttribute)) + if (attributeType == typeof(Vim.G3dNext.Attributes.ChunkMeshOpaqueSubmeshCountsAttribute)) return MeshOpaqueSubmeshCounts; - if (attributeType == typeof(Vim.G3dNext.Attributes.MeshSubmeshIndexOffsetsAttribute)) + if (attributeType == typeof(Vim.G3dNext.Attributes.ChunkSubmeshIndexOffsetsAttribute)) return SubmeshIndexOffsets; - if (attributeType == typeof(Vim.G3dNext.Attributes.MeshSubmeshVertexOffsetsAttribute)) + if (attributeType == typeof(Vim.G3dNext.Attributes.ChunkSubmeshVertexOffsetsAttribute)) return SubmeshVertexOffsets; - if (attributeType == typeof(Vim.G3dNext.Attributes.MeshSubmeshMaterialsAttribute)) + if (attributeType == typeof(Vim.G3dNext.Attributes.ChunkSubmeshMaterialsAttribute)) return SubmeshMaterials; - if (attributeType == typeof(Vim.G3dNext.Attributes.MeshPositionsAttribute)) + if (attributeType == typeof(Vim.G3dNext.Attributes.ChunkPositionsAttribute)) return Positions; - if (attributeType == typeof(Vim.G3dNext.Attributes.MeshIndicesAttribute)) + if (attributeType == typeof(Vim.G3dNext.Attributes.ChunkIndicesAttribute)) return Indices; throw new ArgumentException("Type {attributeType.ToString()} is not supported."); @@ -3226,52 +3164,46 @@ public IAttribute MergeAttribute(string attributeName, IReadOnlyList().ToArray().MergeDataAttributes(); - } - - case Vim.G3dNext.Attributes.MeshSubmeshOffsetAttribute.AttributeName: + case Vim.G3dNext.Attributes.ChunkMeshSubmeshOffsetAttribute.AttributeName: { // Index Attribute - return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); + return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); } - case Vim.G3dNext.Attributes.MeshOpaqueSubmeshCountsAttribute.AttributeName: + case Vim.G3dNext.Attributes.ChunkMeshOpaqueSubmeshCountsAttribute.AttributeName: { // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); } - case Vim.G3dNext.Attributes.MeshSubmeshIndexOffsetsAttribute.AttributeName: + case Vim.G3dNext.Attributes.ChunkSubmeshIndexOffsetsAttribute.AttributeName: { // Index Attribute - return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); + return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); } - case Vim.G3dNext.Attributes.MeshSubmeshVertexOffsetsAttribute.AttributeName: + case Vim.G3dNext.Attributes.ChunkSubmeshVertexOffsetsAttribute.AttributeName: { // Index Attribute - return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); + return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); } - case Vim.G3dNext.Attributes.MeshSubmeshMaterialsAttribute.AttributeName: + case Vim.G3dNext.Attributes.ChunkSubmeshMaterialsAttribute.AttributeName: { // Index Attribute - return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); + return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); } - case Vim.G3dNext.Attributes.MeshPositionsAttribute.AttributeName: + case Vim.G3dNext.Attributes.ChunkPositionsAttribute.AttributeName: { // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); + return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); } - case Vim.G3dNext.Attributes.MeshIndicesAttribute.AttributeName: + case Vim.G3dNext.Attributes.ChunkIndicesAttribute.AttributeName: { // Index Attribute - return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); + return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); } default: @@ -3293,7 +3225,7 @@ public void Validate() continue; // no relation. if (index < -1 || index > maxIndex) - throw new Exception($"Index out of range in Vim.G3dNext.Attributes.MeshSubmeshOffsetAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); + throw new Exception($"Index out of range in Vim.G3dNext.Attributes.ChunkMeshSubmeshOffsetAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); } } @@ -3307,7 +3239,7 @@ public void Validate() continue; // no relation. if (index < -1 || index > maxIndex) - throw new Exception($"Index out of range in Vim.G3dNext.Attributes.MeshSubmeshIndexOffsetsAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); + throw new Exception($"Index out of range in Vim.G3dNext.Attributes.ChunkSubmeshIndexOffsetsAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); } } @@ -3321,7 +3253,7 @@ public void Validate() continue; // no relation. if (index < -1 || index > maxIndex) - throw new Exception($"Index out of range in Vim.G3dNext.Attributes.MeshSubmeshVertexOffsetsAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); + throw new Exception($"Index out of range in Vim.G3dNext.Attributes.ChunkSubmeshVertexOffsetsAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); } } @@ -3335,7 +3267,7 @@ public void Validate() continue; // no relation. if (index < -1 || index > maxIndex) - throw new Exception($"Index out of range in Vim.G3dNext.Attributes.MeshSubmeshMaterialsAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); + throw new Exception($"Index out of range in Vim.G3dNext.Attributes.ChunkSubmeshMaterialsAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); } } @@ -3349,7 +3281,7 @@ public void Validate() continue; // no relation. if (index < -1 || index > maxIndex) - throw new Exception($"Index out of range in Vim.G3dNext.Attributes.MeshIndicesAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); + throw new Exception($"Index out of range in Vim.G3dNext.Attributes.ChunkIndicesAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); } } } diff --git a/src/cs/g3d/Vim.G3dNext.Attributes/G3dMesh.cs b/src/cs/g3d/Vim.G3dNext.Attributes/G3dChunk.cs similarity index 93% rename from src/cs/g3d/Vim.G3dNext.Attributes/G3dMesh.cs rename to src/cs/g3d/Vim.G3dNext.Attributes/G3dChunk.cs index 1534f574..698a29de 100644 --- a/src/cs/g3d/Vim.G3dNext.Attributes/G3dMesh.cs +++ b/src/cs/g3d/Vim.G3dNext.Attributes/G3dChunk.cs @@ -3,16 +3,8 @@ namespace Vim.G3dNext.Attributes { - public partial class G3dMesh + public partial class G3dChunk { - // Field doesn't get written but is useful in builing a Vimx. - public int[] InstanceNodes; - public int Chunk; - public int ChunkIndex; - public int[] MeshIndices; - - public long GetSize() => Attributes.GetSize(); - void ISetup.Setup() { // empty @@ -21,7 +13,6 @@ void ISetup.Setup() /// /// The total number of instances. /// - public int GetInstanceCount() => InstanceTransforms?.Length ?? 0; public int GetSubmeshCount() => SubmeshIndexOffsets?.Length ?? 0; diff --git a/src/cs/g3d/Vim.G3dNext.Attributes/MeshAttributes.cs b/src/cs/g3d/Vim.G3dNext.Attributes/MeshAttributes.cs index bc6ef10b..5b99ec9b 100644 --- a/src/cs/g3d/Vim.G3dNext.Attributes/MeshAttributes.cs +++ b/src/cs/g3d/Vim.G3dNext.Attributes/MeshAttributes.cs @@ -3,43 +3,39 @@ namespace Vim.G3dNext.Attributes { [AttributeCollection( - typeof(MeshInstanceTransformsAttribute), - typeof(MeshSubmeshOffsetAttribute), - typeof(MeshOpaqueSubmeshCountsAttribute), - typeof(MeshSubmeshIndexOffsetsAttribute), - typeof(MeshSubmeshVertexOffsetsAttribute), - typeof(MeshSubmeshMaterialsAttribute), - typeof(MeshPositionsAttribute), - typeof(MeshIndicesAttribute) + typeof(ChunkMeshSubmeshOffsetAttribute), + typeof(ChunkMeshOpaqueSubmeshCountsAttribute), + typeof(ChunkSubmeshIndexOffsetsAttribute), + typeof(ChunkSubmeshVertexOffsetsAttribute), + typeof(ChunkSubmeshMaterialsAttribute), + typeof(ChunkPositionsAttribute), + typeof(ChunkIndicesAttribute) )] - public partial class MeshAttributeCollection // : IAttributeCollection + public partial class ChunkAttributeCollection // : IAttributeCollection { } - [AttributeDescriptor("Mesh", "g3d:instance:transform:0:float32:16", AttributeType.Data, ArrayType = typeof(Matrix4x4))] - public partial class MeshInstanceTransformsAttribute { } + [AttributeDescriptor("Chunk", "g3d:mesh:opaquesubmeshcount:0:int32:1", AttributeType.Data)] + public partial class ChunkMeshOpaqueSubmeshCountsAttribute { } - [AttributeDescriptor("g3d:mesh:opaquesubmeshcount:0:int32:1", AttributeType.Data)] - public partial class MeshOpaqueSubmeshCountsAttribute { } + [AttributeDescriptor("Chunk", "g3d:mesh:submeshOffset:0:int32:1", AttributeType.Index, IndexInto = typeof(ChunkIndicesAttribute))] + public partial class ChunkMeshSubmeshOffsetAttribute { } - [AttributeDescriptor("g3d:mesh:submeshOffset:0:int32:1", AttributeType.Index, IndexInto = typeof(MeshIndicesAttribute))] - public partial class MeshSubmeshOffsetAttribute { } + [AttributeDescriptor("Chunk", "g3d:submesh:indexoffset:0:int32:1", AttributeType.Index, IndexInto = typeof(ChunkIndicesAttribute))] + public partial class ChunkSubmeshIndexOffsetsAttribute { } - [AttributeDescriptor("Mesh", "g3d:submesh:indexoffset:0:int32:1", AttributeType.Index, IndexInto = typeof(MeshIndicesAttribute))] - public partial class MeshSubmeshIndexOffsetsAttribute { } + [AttributeDescriptor("Chunk", "g3d:submesh:vertexoffset:0:int32:1", AttributeType.Index, IndexInto = typeof(ChunkIndicesAttribute))] + public partial class ChunkSubmeshVertexOffsetsAttribute { } - [AttributeDescriptor("Mesh", "g3d:submesh:vertexoffset:0:int32:1", AttributeType.Index, IndexInto = typeof(MeshIndicesAttribute))] - public partial class MeshSubmeshVertexOffsetsAttribute { } + [AttributeDescriptor("Chunk", "g3d:submesh:material:0:int32:1", AttributeType.Index)] + public partial class ChunkSubmeshMaterialsAttribute { } - [AttributeDescriptor("Mesh", "g3d:submesh:material:0:int32:1", AttributeType.Index)] - public partial class MeshSubmeshMaterialsAttribute { } + [AttributeDescriptor("Chunk", "g3d:vertex:position:0:float32:3", AttributeType.Data, ArrayType = typeof(Vector3))] + public partial class ChunkPositionsAttribute { } - [AttributeDescriptor("Mesh", "g3d:vertex:position:0:float32:3", AttributeType.Data, ArrayType = typeof(Vector3))] - public partial class MeshPositionsAttribute { } - - [AttributeDescriptor("Mesh", "g3d:corner:index:0:int32:1", AttributeType.Index, IndexInto = typeof(MeshPositionsAttribute))] - public partial class MeshIndicesAttribute { } + [AttributeDescriptor("Chunk", "g3d:corner:index:0:int32:1", AttributeType.Index, IndexInto = typeof(ChunkPositionsAttribute))] + public partial class ChunkIndicesAttribute { } } diff --git a/src/cs/vim/Vim.Format.Core/G3dBuilder.cs b/src/cs/vim/Vim.Format.Core/G3dBuilder.cs index 6d7df92c..db10261c 100644 --- a/src/cs/vim/Vim.Format.Core/G3dBuilder.cs +++ b/src/cs/vim/Vim.Format.Core/G3dBuilder.cs @@ -4,6 +4,7 @@ using Vim.BFastNS; using static Vim.Format.DocumentBuilder; using Vim.Math3d; +using Vim.G3dNext.Attributes; namespace Vim.Format { @@ -95,9 +96,6 @@ public BFast ToBFast() shapeVertexOffsets[i] = shapeVertexOffsets[i - 1] + _shapes[i - 1].Vertices.Count; } - bfast = new BFast(); - bfast.SetArray("Meta", G3dHeader.Default.ToBytes()); - bfast.SetEnumerable(CommonAttributes.Position, () => _meshes.SelectMany(m => m.Vertices)); bfast.SetEnumerable(CommonAttributes.Index, () => _meshes.SelectMany(m => m.Indices)); bfast.SetEnumerable(CommonAttributes.MeshSubmeshOffset, () => meshSubmeshOffset); diff --git a/src/cs/vim/Vim.Format.Vimx.Conversion/Chunking.cs b/src/cs/vim/Vim.Format.Vimx.Conversion/Chunking.cs new file mode 100644 index 00000000..f431c19b --- /dev/null +++ b/src/cs/vim/Vim.Format.Vimx.Conversion/Chunking.cs @@ -0,0 +1,316 @@ +using System.Collections.Generic; +using System.Linq; +using Vim.LinqArray; +using Vim.Math3d; +using Vim.G3dNext.Attributes; +using Vim.G3d; +using System.Xml.Serialization; +using System; + +namespace Vim.Format.VimxNS.Conversion +{ + public static class Chunking + { + + public static VimChunks CreateChunks(ChunksDescription description) + { + var chunks = new G3dChunk[description.ChunkMeshes.Count]; + for (var i = 0; i < chunks.Length; i++) + { + var meshes = description.ChunkMeshes[i]; + chunks[i] = CreateChunk2(description.g3d, meshes); + } + return new VimChunks(description, chunks); + } + + public static ChunksDescription ComputeChunks(MeshOrder ordering) + { + // 2MB once compressed -> 0.5MB + const int ChunkSize = 2000000; + + var meshChunks = new int[ordering.Meshes.Length]; + var meshIndex = new int[ordering.Meshes.Length]; + + var chunks = new List>(); + var chunk = new List(); + var chunkSize = 0L; + for (var i = 0; i < ordering.Meshes.Length; i++) + { + var mesh = ordering.Meshes[i]; + chunkSize += ordering.g3d.GetApproxSize(mesh); + if (chunkSize > ChunkSize && chunk.Count > 0) + { + chunks.Add(chunk); + chunk = new List(); + chunkSize = 0; + } + + meshChunks[i] = chunks.Count; + meshIndex[i] = chunk.Count; + chunk.Add(mesh); + } + if (chunk.Count > 0) + { + chunks.Add(chunk); + } + + return new ChunksDescription(ordering, meshChunks, meshIndex, chunks); + } + + public static G3dChunk CreateChunk(G3dVim g3d, List meshes) + { + var submeshOffsets = new List() { 0 }; + var opaqueCounts = new List(); + var submeshIndexOffsets = new List(); + var submeshVertexOffsets = new List(); + var submeshMaterials = new List(); + var indices = new List(); + var vertices = new List(); + + for (var i = 0; i < meshes.Count; i++) + { + var mesh = meshes[i]; + + var opaqueCount = AppendSubmeshes( + g3d, + mesh, + false, + submeshIndexOffsets, + submeshVertexOffsets, + submeshMaterials, + indices, + vertices + ); + + var transparentCount = AppendSubmeshes( + g3d, + mesh, + true, + submeshIndexOffsets, + submeshVertexOffsets, + submeshMaterials, + indices, + vertices + ); + opaqueCounts.Add(opaqueCount); + submeshOffsets.Add(submeshOffsets[i] + opaqueCount + transparentCount); + } + + return new G3dChunk() + { + MeshSubmeshOffset = submeshOffsets.ToArray(), + MeshOpaqueSubmeshCounts = opaqueCounts.ToArray(), + SubmeshIndexOffsets = submeshIndexOffsets.ToArray(), + SubmeshVertexOffsets = submeshVertexOffsets.ToArray(), + SubmeshMaterials = submeshMaterials.ToArray(), + Indices = indices.ToArray(), + Positions = vertices.ToArray() + }; + } + + + public class SubmeshBuffer + { + int index = 0; + public int[] IndexOffsets; + public int[] VertexOffsets; + public int[] Materials; + + public SubmeshBuffer(int count) + { + IndexOffsets = new int[count]; + VertexOffsets = new int[count]; + Materials = new int[count]; + } + + public void Add(int indexOffset, int vertexOffset, int material) + { + IndexOffsets[index] = indexOffset; + VertexOffsets[index] = vertexOffset; + Materials[index] = material; + index++; + } + } + + public class PointsBuffer + { + public int[] indices; + public List vertices; + + public int IndexCount { get; private set; } = 0; + public int VertexCount => vertices.Count; + + public PointsBuffer(int indexCount, int vertexCount) + { + indices = new int[indexCount]; + vertices = new List(vertexCount); + } + + public void AddIndex(int index) + { + indices[IndexCount++] = index; + } + + public void AddVertex(Vector3 vertex) + { + vertices.Add(vertex); + } + } + + public static G3dChunk CreateChunk2(G3dVim g3d, List meshes) + { + var meshSubmeshOffsets = new int[meshes.Count + 1]; + var meshOpaqueCounts = new int[meshes.Count]; + + var submeshCount = meshes.Sum(m => g3d.GetMeshSubmeshCount(m)); + var submeshBuffer = new SubmeshBuffer(submeshCount); + + var indexCount = meshes.Sum(m => g3d.GetMeshIndexCount(m)); + var vertexCount = meshes.Sum(m => g3d.GetMeshVertexCount(m)); + var pointsBuffer = new PointsBuffer(indexCount, vertexCount); + + for (var i = 0; i < meshes.Count; i++) + { + var mesh = meshes[i]; + + var opaqueCount = AppendSubmeshes2( + g3d, + mesh, + false, + submeshBuffer, + pointsBuffer + ); + + var transparentCount = AppendSubmeshes2( + g3d, + mesh, + true, + submeshBuffer, + pointsBuffer + ); + meshOpaqueCounts[i] = opaqueCount; + meshSubmeshOffsets[i + 1] = meshSubmeshOffsets[i] + opaqueCount + transparentCount; + } + + return new G3dChunk() + { + MeshSubmeshOffset = meshSubmeshOffsets, + MeshOpaqueSubmeshCounts = meshOpaqueCounts, + SubmeshIndexOffsets = submeshBuffer.IndexOffsets, + SubmeshVertexOffsets = submeshBuffer.VertexOffsets, + SubmeshMaterials = submeshBuffer.Materials, + Indices = pointsBuffer.indices, + Positions = pointsBuffer.vertices.ToArray() + }; + } + + private static int AppendSubmeshes( + G3dVim g3d, + int mesh, + bool transparent, + List submeshIndexOffsets, + List submeshVertexOffsets, + List submeshMaterials, + List indices, + List vertices + ) + { + var subStart = g3d.GetMeshSubmeshStart(mesh); + var subEnd = g3d.GetMeshSubmeshEnd(mesh); + var count = 0; + for (var sub = subStart; sub < subEnd; sub++) + { + var currentMat = g3d.SubmeshMaterials[sub]; + var color = currentMat > 0 ? g3d.MaterialColors[currentMat] : Vector4.One; + var accept = color.W < 1 == transparent; + + if (!accept) continue; + count++; + submeshMaterials.Add(currentMat); + submeshIndexOffsets.Add(indices.Count); + submeshVertexOffsets.Add(vertices.Count); + var (subIndices, subVertices) = g3d.GetSubmesh(sub); + indices.AddRange(subIndices.Select(i => i + vertices.Count)); + vertices.AddRange(subVertices); + } + return count; + } + + + private static int AppendSubmeshes2( + G3dVim g3d, + int mesh, + bool transparent, + SubmeshBuffer submeshBuffer, + PointsBuffer pointsBuffer + ) + { + var subStart = g3d.GetMeshSubmeshStart(mesh); + var subEnd = g3d.GetMeshSubmeshEnd(mesh); + var count = 0; + for (var sub = subStart; sub < subEnd; sub++) + { + var currentMat = g3d.SubmeshMaterials[sub]; + var color = currentMat > 0 ? g3d.MaterialColors[currentMat] : Vector4.One; + var accept = color.W < 1 == transparent; + + if (!accept) continue; + count++; + submeshBuffer.Add(pointsBuffer.IndexCount, pointsBuffer.VertexCount, currentMat); + g3d.GetSubmesh2(sub, pointsBuffer); + } + return count; + } + + + private static (List, List) GetSubmesh(this G3dVim g3d, int submesh) + { + var indices = new List(); + var vertices = new List(); + var dict = new Dictionary(); + + var start = g3d.GetSubmeshIndexStart(submesh); + var end = g3d.GetSubmeshIndexEnd(submesh); + + for (var i = start; i < end; i++) + { + var v = g3d.Indices[i]; + if (dict.ContainsKey(v)) + { + indices.Add(dict[v]); + } + else + { + indices.Add(vertices.Count); + dict.Add(v, vertices.Count); + vertices.Add(g3d.Positions[v]); + } + } + return (indices, vertices); + } + + private static void GetSubmesh2(this G3dVim g3d, int submesh, PointsBuffer points) + { + var index = points.VertexCount; + var dict = new Dictionary(); + var start = g3d.GetSubmeshIndexStart(submesh); + var end = g3d.GetSubmeshIndexEnd(submesh); + + for (var i = start; i < end; i++) + { + var v = g3d.Indices[i]; + if (dict.ContainsKey(v)) + { + points.AddIndex(dict[v]); + } + else + { + points.AddIndex(index); + points.AddVertex(g3d.Positions[v]); + dict.Add(v, index); + index++; + } + } + } + } +} diff --git a/src/cs/vim/Vim.Format.Vimx.Conversion/MeshesToScene.cs b/src/cs/vim/Vim.Format.Vimx.Conversion/MeshesToScene.cs deleted file mode 100644 index 1a70dfd2..00000000 --- a/src/cs/vim/Vim.Format.Vimx.Conversion/MeshesToScene.cs +++ /dev/null @@ -1,106 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Vim.BFastNS; -using Vim.Format.ObjectModel; -using Vim.G3dNext.Attributes; -using Vim.LinqArray; -using Vim.Math3d; - -namespace Vim.Format.VimxNS.Conversion -{ - public static class MeshesToScene - { - - public static G3dScene CreateScene(G3dVim g3d, DocumentModel bim, VimxChunk[] chunks, G3dMesh[] meshes) - { - var scene = new G3dScene(); - scene.ChunkCount = new int[1] { chunks.Length }; - - var nodeElements = bim.NodeElementIndex.ToArray(); - var nodeElementIds = nodeElements - .Select(n => n < 0 || n > bim.ElementId.Count - ? -1 - : bim.ElementId[n] - ).ToArray(); - - int[] dummy; - (scene.InstanceMeshes, dummy, scene.InstanceNodes) = meshes.GetInstanceIds(); - scene.InstanceGroups = scene.InstanceNodes.Select(n => nodeElements[n]).ToArray(); - scene.InstanceTags = scene.InstanceNodes.Select(n => nodeElementIds[n]).ToArray(); - (scene.InstanceMins, scene.InstanceMaxs) = ComputeBoundingBoxes(meshes, scene.InstanceMeshes, dummy); - - if (g3d.InstanceFlags != null) - { - scene.InstanceFlags = scene.InstanceNodes.Select(i => g3d.InstanceFlags[i]).ToArray(); - } - - // meshes - scene.MeshChunks = new int[meshes.Length]; - scene.MeshChunkIndices = new int[meshes.Length]; - scene.MeshIndexCounts = new int[meshes.Length]; - scene.MeshVertexCounts = new int[meshes.Length]; - scene.MeshOpaqueIndexCounts = new int[meshes.Length]; - scene.MeshOpaqueVertexCounts = new int[meshes.Length]; - - for (var i = 0; i < meshes.Length; i++) - { - var mesh = meshes[i]; - scene.MeshChunks[i] = mesh.Chunk; - scene.MeshChunkIndices[i] = mesh.ChunkIndex; - scene.MeshIndexCounts[i] = mesh.GetIndexCount(); - scene.MeshVertexCounts[i] = mesh.GetVertexCount(); - //scene.MeshOpaqueIndexCounts[i] = mesh.GetIndexCount(MeshSection.Opaque); - //scene.MeshOpaqueVertexCounts[i] = mesh.GetMeshVertexCount(MeshSection.Opaque); - } - return scene; - } - - private static (Vector3[] min, Vector3[] max) ComputeBoundingBoxes(G3dMesh[] meshes, int[] instanceFiles, int[] instanceIndices) - { - var instanceMins = new Vector3[instanceFiles.Length]; - var instanceMaxs = new Vector3[instanceFiles.Length]; - for (var i = 0; i < instanceFiles.Length; i++) - { - var file = instanceFiles[i]; - var index = instanceIndices[i]; - - var min = Vector3.MaxValue; - var max = Vector3.MinValue; - var mesh = meshes[file]; - var vertexCount = mesh.GetVertexCount(); - for (var j = 0; j < vertexCount; j++) - { - var pos = mesh.Positions[j]; - var matrix = mesh.InstanceTransforms[index]; - var pos2 = pos.Transform(matrix); - min = min.Min(pos2); - max = max.Max(pos2); - } - instanceMins[i] = min; - instanceMaxs[i] = max; - } - return (instanceMins, instanceMaxs); - } - - private static (int[], int[], int[]) GetInstanceIds(this G3dMesh[] meshes) - { - var instanceMeshes = new List(); - var instanceIndices = new List(); - var instanceNodes = new List(); - - // Associate intances to meshes - for (var i = 0; i < meshes.Length; i++) - { - var mesh = meshes[i]; - for (var j = 0; j < mesh.InstanceNodes.Length; j++) - { - instanceMeshes.Add(i); - instanceIndices.Add(j); - instanceNodes.Add(mesh.InstanceNodes[j]); - } - } - return (instanceMeshes.ToArray(), instanceIndices.ToArray(), instanceNodes.ToArray()); - } - } -} diff --git a/src/cs/vim/Vim.Format.Vimx.Conversion/VimxOrdering.cs b/src/cs/vim/Vim.Format.Vimx.Conversion/Ordering.cs similarity index 51% rename from src/cs/vim/Vim.Format.Vimx.Conversion/VimxOrdering.cs rename to src/cs/vim/Vim.Format.Vimx.Conversion/Ordering.cs index a61ba943..c1ef1c27 100644 --- a/src/cs/vim/Vim.Format.Vimx.Conversion/VimxOrdering.cs +++ b/src/cs/vim/Vim.Format.Vimx.Conversion/Ordering.cs @@ -1,30 +1,42 @@ -using System.Collections.Generic; -using System.Linq; +using System; using Vim.Format.ObjectModel; using Vim.G3dNext.Attributes; namespace Vim.Format.VimxNS.Conversion { - public static class VimxOrdering + public static class Ordering { - public static IEnumerable OrderByBim(this IEnumerable meshes, DocumentModel bim) + public static MeshOrder ComputeOrder(G3dVim g3d, DocumentModel bim) { - return meshes.OrderByDescending((m) => ( - GetPriority(GetMeshName(m, bim)), - m.GetAABB().MaxSide) - ); + var meshCount = g3d.GetMeshCount(); + var resultCount = 0; + for (var mesh = 0; mesh < meshCount; mesh++) + { + if (g3d.GetMeshInstances(mesh).Count > 0) resultCount++; + } + + var i = 0; + var order = new int[resultCount]; + var instanceCount = 0; + for (var mesh = 0; mesh < meshCount; mesh++) + { + var instances = g3d.GetMeshInstances(mesh); + if (instances.Count > 0) + { + instanceCount += instances.Count; + order[i++] = mesh; + } + } + Array.Sort(order, (a, b) => + { + var prioA = GetPriority(GetMeshName(g3d, bim, a)); + var prioB = GetPriority(GetMeshName(g3d, bim, b)); + return prioA - prioB; + }); + return new MeshOrder(g3d, order, instanceCount); } - public static IEnumerable OrderByBim2(G3dVim g3d, DocumentModel bim) - { - return Enumerable.Range(0, g3d.GetMeshCount()) - .Where(m => g3d.GetMeshInstances(m).Count > 0) - .OrderByDescending((m) => - GetPriority(GetMeshName2(g3d, bim, m)) - ); - } - - static string GetMeshName2(G3dVim g3d, DocumentModel bim, int mesh) + static string GetMeshName(G3dVim g3d, DocumentModel bim, int mesh) { var node = g3d.GetMeshInstances(mesh)[0]; @@ -40,23 +52,6 @@ static string GetMeshName2(G3dVim g3d, DocumentModel bim, int mesh) return name; } - - static string GetMeshName(this G3dMesh mesh, DocumentModel bim) - { - var node = mesh.InstanceNodes[0]; - - if (node < 0 || node >= bim.NodeElementIndex.Count) return ""; - var element = bim.NodeElementIndex[node]; - - if (element < 0 || element >= bim.ElementCategoryIndex.Count) return ""; - var category = bim.ElementCategoryIndex[element]; - - if (category < 0 || category >= bim.CategoryName.Count) return ""; - var name = bim.CategoryName[category]; - - return name; - } - static int GetPriority(string value) { if (string.IsNullOrWhiteSpace(value)) return 0; diff --git a/src/cs/vim/Vim.Format.Vimx.Conversion/VimToMeshes.cs b/src/cs/vim/Vim.Format.Vimx.Conversion/VimToMeshes.cs deleted file mode 100644 index 62a7f2e8..00000000 --- a/src/cs/vim/Vim.Format.Vimx.Conversion/VimToMeshes.cs +++ /dev/null @@ -1,198 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using Vim.LinqArray; -using Vim.Util; -using Vim.BFastNS; -using Vim.Math3d; -using Vim.G3dNext.Attributes; -using static Vim.Format.DocumentBuilder; - -namespace Vim.Format.VimxNS.Conversion -{ - public static class VimToMeshes - { - /// - /// Splits a g3dVim into a sequence of vimx getMesh. - /// - public static IEnumerable ExtractMeshes(G3dVim g3d) - { - return Enumerable.Range(0, g3d.GetMeshCount()) - .Select(m => g3d.GetMesh(m)) - .WhereNotNull(); - } - - public static G3dMesh GetMesh2(G3dVim g3d, List meshes) - { - var submeshOffsets = new List() { 0}; - var meshOpaqueCounts = new List(); - var submeshIndexOffsets = new List(); - var submeshVertexOffsets = new List(); - var submeshMaterials = new List(); - var indices = new List(); - var vertices = new List(); - - - for(var i =0; i < meshes.Count; i ++) - { - var mesh = meshes[i]; - - var opaqueCount = AppendSubmeshes( - g3d, - mesh, - false, - submeshIndexOffsets, - submeshVertexOffsets, - submeshMaterials, - indices, - vertices - ); - - var transparentCount = AppendSubmeshes( - g3d, - mesh, - true, - submeshIndexOffsets, - submeshVertexOffsets, - submeshMaterials, - indices, - vertices - ); - meshOpaqueCounts.Add(opaqueCount); - submeshOffsets.Add(submeshOffsets[i] + opaqueCount + transparentCount); - } - - return new G3dMesh() - { - MeshIndices = meshes.ToArray(), - InstanceNodes = null, - InstanceTransforms = null, - MeshSubmeshOffset = submeshOffsets.ToArray(), - MeshOpaqueSubmeshCounts = meshOpaqueCounts.ToArray(), - SubmeshIndexOffsets = submeshIndexOffsets.ToArray(), - SubmeshVertexOffsets = submeshVertexOffsets.ToArray(), - SubmeshMaterials = submeshMaterials.ToArray(), - Indices = indices.ToArray(), - Positions = vertices.ToArray() - }; - } - - - private static G3dMesh GetMesh(this G3dVim g3d, int mesh) - { - var instances = g3d.GetMeshInstances(mesh); - if (instances.Count == 0) - { - return null; - } - var instanceNodes = new int[instances.Count]; - var instanceTransforms = new Matrix4x4[instances.Count]; - - var submeshIndexOffsets = new List(); - var submeshVertexOffsets = new List(); - var submeshMaterials = new List(); - var indices = new List(); - var vertices = new List(); - - // instances - for (var i = 0; i < instances.Count; i++) - { - var instance = instances[i]; - instanceNodes[i] = instances[i]; - instanceTransforms[i] = g3d.InstanceTransforms[instance]; - } - - var opaqueCount = AppendSubmeshes( - g3d, - mesh, - false, - submeshIndexOffsets, - submeshVertexOffsets, - submeshMaterials, - indices, - vertices - ); - - AppendSubmeshes( - g3d, - mesh, - true, - submeshIndexOffsets, - submeshVertexOffsets, - submeshMaterials, - indices, - vertices - ); - - return new G3dMesh() - { - InstanceNodes = instanceNodes.ToArray(), - InstanceTransforms = instanceTransforms.ToArray(), - MeshOpaqueSubmeshCounts = new int[] { opaqueCount }, - SubmeshIndexOffsets = submeshIndexOffsets.ToArray(), - SubmeshVertexOffsets = submeshVertexOffsets.ToArray(), - SubmeshMaterials = submeshMaterials.ToArray(), - Indices = indices.ToArray(), - Positions = vertices.ToArray() - }; - } - - - private static int AppendSubmeshes( - G3dVim g3d, - int mesh, - bool transparent, - List submeshIndexOffsets, - List submeshVertexOffsets, - List submeshMaterials, - List indices, - List vertices - ) - { - var subStart = g3d.GetMeshSubmeshStart(mesh); - var subEnd = g3d.GetMeshSubmeshEnd(mesh); - var count = 0; - for (var sub = subStart; sub < subEnd; sub++) - { - var currentMat = g3d.SubmeshMaterials[sub]; - var color = currentMat > 0 ? g3d.MaterialColors[currentMat] : Vector4.One; - var accept = color.W < 1 == transparent; - - if (!accept) continue; - count++; - submeshMaterials.Add(currentMat); - submeshIndexOffsets.Add(indices.Count); - submeshVertexOffsets.Add(vertices.Count); - var (subIndices, subVertices) = g3d.GetSubmesh(sub); - indices.AddRange(subIndices.Select(i => i + vertices.Count)); - vertices.AddRange(subVertices); - } - return count; - } - - private static (List, List) GetSubmesh(this G3dVim g3d, int submesh) - { - var indices = new List(); - var vertices = new List(); - var dict = new Dictionary(); - - var start = g3d.GetSubmeshIndexStart(submesh); - var end = g3d.GetSubmeshIndexEnd(submesh); - - for (var i = start; i < end; i++) - { - var v = g3d.Indices[i]; - if (dict.ContainsKey(v)) - { - indices.Add(dict[v]); - } - else - { - indices.Add(vertices.Count); - dict.Add(v, vertices.Count); - vertices.Add(g3d.Positions[v]); - } - } - return (indices, vertices); - } - } -} diff --git a/src/cs/vim/Vim.Format.Vimx.Conversion/VimxConverter.cs b/src/cs/vim/Vim.Format.Vimx.Conversion/VimxConverter.cs index fa45c2c7..8b763fbe 100644 --- a/src/cs/vim/Vim.Format.Vimx.Conversion/VimxConverter.cs +++ b/src/cs/vim/Vim.Format.Vimx.Conversion/VimxConverter.cs @@ -6,6 +6,8 @@ using Vim.G3dNext; using System.Collections.Generic; using Vim.Math3d; +using System.Diagnostics; +using System; namespace Vim.Format.VimxNS.Conversion { @@ -13,159 +15,235 @@ public static class VimxConverter { public static Vimx FromVimPath(string vimPath) { + var sw = Stopwatch.StartNew(); var vim = VimScene.LoadVim(vimPath, new LoadOptions() { SkipAssets = true, SkipGeometry = true, }); + Console.WriteLine(" LoadVim " + sw.ElapsedMilliseconds); + sw.Restart(); var g3d = G3dVim.FromVim(vimPath); - return FromVim2(g3d, vim.DocumentModel); + Console.WriteLine(" G3dVim.FromVim " + sw.ElapsedMilliseconds); + + sw.Restart(); + var vimx = FromVim(g3d, vim.DocumentModel); + Console.WriteLine(" FromVim " + sw.ElapsedMilliseconds); + + return vimx; } + public static Vimx FromVim(G3dVim g3d, DocumentModel bim) + { + var sw = Stopwatch.StartNew(); + // Split input Vim into chunks. + var chunks = CreateChunks(g3d, bim); + Console.WriteLine(" CreateChunks " + sw.ElapsedMilliseconds); + + sw.Restart(); + // Compute the scene definition from chunks. + var scene = CreateScene(chunks, bim); + Console.WriteLine(" CreateScene " + sw.ElapsedMilliseconds); + + sw.Restart(); + // Materials are reused from input g3d. + var materials = new G3dMaterials().ReadFromVim(g3d); + Console.WriteLine(" G3dMaterials " + sw.ElapsedMilliseconds); + + var header = VimxHeader.CreateDefault(); - public static Vimx FromVim2(G3dVim g3d, DocumentModel bim) + return new Vimx(header, MetaHeader.Default, scene, materials, chunks.Chunks); + } + + public static VimChunks CreateChunks(G3dVim g3d, DocumentModel bim) { - var meshOrder = VimxOrdering.OrderByBim2(g3d, bim).ToArray(); - var instanceNodes = meshOrder.SelectMany(m => g3d.GetMeshInstances(m)); - var instanceMeshes = meshOrder.SelectMany((m,i) => g3d.GetMeshInstances(m).Select(_ => i)).ToArray(); - var instanceTransforms = instanceNodes.Select(n => g3d.InstanceTransforms[n]).ToArray(); - var instanceFlags = g3d.InstanceFlags != null - ? instanceNodes.Select(n => g3d.InstanceFlags[n]).ToArray() - : null; + var sw = Stopwatch.StartNew(); + // First compute a desirable presentation order. + var ordering = Ordering.ComputeOrder(g3d, bim); + Console.WriteLine(" ComputeOrder " + sw.ElapsedMilliseconds); + + sw.Restart(); + // Groups meshes up to a certain size. + var groups = Chunking.ComputeChunks(ordering); + // Append and merge geometry from g3d to create the chunks. + Console.WriteLine(" ComputeChunks " + sw.ElapsedMilliseconds); + + sw.Restart(); + var chunks = Chunking.CreateChunks(groups); + Console.WriteLine(" CreateChunks " + sw.ElapsedMilliseconds); + + return chunks; + } + public static G3dScene CreateScene(VimChunks chunks, DocumentModel bim) + { var nodeElements = bim.NodeElementIndex.ToArray(); - var instanceGroups = instanceNodes.Select(n => nodeElements[n]).ToArray(); - - var nodeElementIds = nodeElements - .Select(n => bim.ElementId.SafeGet(n, -1)) - .ToArray(); + + var instanceCount = chunks.InstanceCount; + var instanceNodes = new int[instanceCount]; + var instanceMeshes = new int[instanceCount]; + var instanceGroups = new int[instanceCount]; + var instanceTransforms = new Matrix4x4[instanceCount]; + var instanceFlags = new ushort[instanceCount]; + var instanceTags = new long[instanceCount]; + var instanceMins = new Vector3[instanceCount]; + var instanceMaxs = new Vector3[instanceCount]; + + var meshCount = chunks.MeshCount; + var indexCounts = new int[meshCount]; + var vertexCounts = new int[meshCount]; + var opaqueIndexCounts = new int[meshCount]; + var opaqueVertexCounts = new int[meshCount]; + + var sw = Stopwatch.StartNew(); + sw.Stop(); + var instance = 0; + for (var i = 0; i < meshCount; i++) + { + var meshChunk = chunks.MeshChunks[i]; + var meshIndex = chunks.MeshIndex[i]; + var instances = chunks.GetInstances(i); + var chunk = chunks.Chunks[meshChunk]; + for (var j = 0; j < instances.Count; j++) + { + var node = instances[j]; + var element = nodeElements[node]; + var transform = chunks.g3d.InstanceTransforms[node]; + + // geometry + instanceMeshes[instance] = i; + instanceTransforms[instance] = transform; + + // bounding box + sw.Start(); + var box = chunk.GetAABox(meshIndex, transform); + sw.Stop(); + instanceMins[instance] = box.Min; + instanceMaxs[instance] = box.Max; + + // bim + instanceNodes[instance] = node; + instanceGroups[instance] = element; + instanceTags[instance] = bim.ElementId.SafeGet(element, -1); + + instance++; + } - var chunks = SplitChunks2(g3d, meshOrder); + // geometry counts + indexCounts[i] = chunk.GetMeshIndexCount(meshIndex, MeshSection.All); + vertexCounts[i] = chunk.GetMeshVertexCount(meshIndex, MeshSection.All); + opaqueIndexCounts[i] = chunk.GetMeshIndexCount(meshIndex, MeshSection.Opaque); + opaqueVertexCounts[i] = chunk.GetMeshVertexCount(meshIndex, MeshSection.Opaque); ; + } - var meshes = chunks.Chunks.Select(c => VimToMeshes.GetMesh2(g3d, c)).ToArray(); - var indexCount = meshOrder.Select((m, i) => meshes[chunks.MeshChunks[i]].GetMeshIndexCount(chunks.MeshIndex[i], MeshSection.All)); - var vertexCount = meshOrder.Select((m, i) => meshes[chunks.MeshChunks[i]].GetMeshVertexCount(chunks.MeshIndex[i], MeshSection.All)); - var opaqueIndexCount = meshOrder.Select((m, i) => meshes[chunks.MeshChunks[i]].GetMeshIndexCount(chunks.MeshIndex[i], MeshSection.Opaque)); - var opaqueVertexCount = meshOrder.Select((m, i) => meshes[chunks.MeshChunks[i]].GetMeshVertexCount(chunks.MeshIndex[i], MeshSection.Opaque)); + // InstanceFlags is not always present. + if (chunks.g3d.InstanceFlags != null) + { + for(var i = 0; i < instanceNodes.Length; i++) + { + var node = instanceNodes[i]; + instanceFlags[i] = chunks.g3d.InstanceFlags[node]; + } + } - var boxes = instanceMeshes - .Select((m, i) => meshes[chunks.MeshChunks[m]].GetAABox(chunks.MeshIndex[m], instanceTransforms[i])) - .ToArray(); - var mins = boxes.Select(b => b.Min).ToArray(); - var maxs = boxes.Select(b => b.Max).ToArray(); + Console.WriteLine("AABB " + sw.ElapsedMilliseconds); var scene = new G3dScene() { - ChunkCount = new[] { chunks.Chunks.Count }, - InstanceMeshes = instanceMeshes.ToArray(), + ChunkCount = new[] { chunks.ChunkCount}, + InstanceMeshes = instanceMeshes, InstanceTransformData = instanceTransforms, - InstanceNodes = instanceNodes.ToArray(), + InstanceNodes = instanceNodes, InstanceFlags = instanceFlags, InstanceGroups = instanceGroups, - InstanceMaxs = maxs, - InstanceMins = mins, - InstanceTags = nodeElementIds, - MeshChunks = chunks.MeshChunks.ToArray(), - MeshChunkIndices = chunks.MeshIndex.ToArray(), - MeshIndexCounts = indexCount.ToArray(), - MeshVertexCounts = vertexCount.ToArray(), - MeshOpaqueIndexCounts = opaqueIndexCount.ToArray(), - MeshOpaqueVertexCounts = opaqueVertexCount.ToArray(), + InstanceMaxs = instanceMaxs, + InstanceMins = instanceMins, + InstanceTags = instanceTags, + MeshChunks = chunks.MeshChunks, + MeshChunkIndices = chunks.MeshIndex, + MeshIndexCounts = indexCounts, + MeshVertexCounts = vertexCounts, + MeshOpaqueIndexCounts = opaqueIndexCounts, + MeshOpaqueVertexCounts = opaqueVertexCounts, }; - - var materials = new G3dMaterials().ReadFromVim(g3d); - var header = VimxHeader.CreateDefault(); - - return new Vimx(header, MetaHeader.Default, scene, materials, meshes); + return scene; } + } - public static Vimx FromVim(G3dVim g3d, DocumentModel bim) - { - var meshes = VimToMeshes.ExtractMeshes(g3d) - .OrderByBim(bim) - .ToArray(); - - var chunks = meshes.SplitChunks(); - var scene = MeshesToScene.CreateScene(g3d, bim, chunks, meshes); - var materials = new G3dMaterials().ReadFromVim(g3d); - var header = VimxHeader.CreateDefault(); + /// + /// Initial step of vim->vimx conversion. + /// + public class MeshOrder + { + public readonly G3dVim g3d; + public readonly int[] Meshes; + public readonly int InstanceCount; - return new Vimx(header, MetaHeader.Default, scene, materials, meshes); + public MeshOrder(G3dVim g3d, int[] meshes, int instanceCount) + { + this.g3d = g3d; + Meshes = meshes; + InstanceCount = instanceCount; } + } - public static VimxChunk[] SplitChunks(this IEnumerable meshes) + /// + /// Describes how the meshes from the vim will be grouped in the vimx. + /// + public class ChunksDescription + { + public readonly G3dVim g3d; + public readonly int[] Meshes; + public readonly int[] MeshChunks; + public readonly int[] MeshIndex; + public readonly List> ChunkMeshes; + public readonly int InstanceCount; + + public ChunksDescription(MeshOrder ordering, int[] meshChunks, int[] meshIndex, List> chunkMeshes) { - //2MB once compressed -> 0.5MB - const int ChunkSize = 2000000; - - var chunks = new List(); - var chunk = new VimxChunk(); - var chunkSize = 0L; - foreach (var mesh in meshes) - { - chunkSize += mesh.GetSize(); - if (chunkSize > ChunkSize && chunk.Meshes.Count > 0) - { - chunks.Add(chunk); - chunk = new VimxChunk(); - chunkSize = 0; - } - mesh.Chunk = chunks.Count; - mesh.ChunkIndex = chunk.Meshes.Count(); - chunk.Meshes.Add(mesh); - } - if (chunk.Meshes.Count > 0) - { - chunks.Add(chunk); - } - - return chunks.ToArray(); + g3d = ordering.g3d; + Meshes = ordering.Meshes; + InstanceCount = ordering.InstanceCount; + MeshChunks = meshChunks; + MeshIndex = meshIndex; + ChunkMeshes = chunkMeshes; } + } - public static ChunkResult SplitChunks2(G3dVim g3d, int[] meshes) + /// + /// Resulting Chunks of the vim->vimx conversion. + /// + public class VimChunks + { + public readonly G3dVim g3d; + public readonly int[] Meshes; + public readonly int[] MeshChunks; + public readonly int[] MeshIndex; + public readonly List> ChunkMeshes; + public readonly G3dChunk[] Chunks; + public readonly int InstanceCount; + + public VimChunks(ChunksDescription description, G3dChunk[] chunks) { - // 2MB once compressed -> 0.5MB - const int ChunkSize = 2000000; + g3d = description.g3d; + Meshes = description.Meshes; + MeshChunks = description.MeshChunks; + MeshIndex = description.MeshIndex; + ChunkMeshes = description.ChunkMeshes; + InstanceCount = description.InstanceCount; + Chunks = chunks; + } - var meshChunks = new List(); - var meshIndex = new List(); + public int ChunkCount => Chunks.Length; - var chunks = new List>(); - var chunk = new List(); - var chunkSize = 0L; - foreach (var mesh in meshes) - { - chunkSize += g3d.GetApproxSize(mesh); - if (chunkSize > ChunkSize && chunk.Count > 0) - { - chunks.Add(chunk); - chunk = new List(); - chunkSize = 0; - } - - meshChunks.Add(chunks.Count); - meshIndex.Add(chunk.Count); - chunk.Add(mesh); - } - if (chunk.Count > 0) - { - chunks.Add(chunk); - } + public int MeshCount => Meshes.Length; - return new ChunkResult { - MeshChunks = meshChunks, - MeshIndex = meshIndex, - Chunks = chunks - }; + public IReadOnlyList GetInstances(int meshIndex) + { + var m = Meshes[meshIndex]; + return g3d.GetMeshInstances(m); } } } - -public class ChunkResult -{ - public List MeshChunks = new List(); - public List MeshIndex = new List(); - public List> Chunks = new List>(); -} diff --git a/src/cs/vim/Vim.Format.Vimx/Vimx.cs b/src/cs/vim/Vim.Format.Vimx/Vimx.cs index 73f6af5f..c23f6b93 100644 --- a/src/cs/vim/Vim.Format.Vimx/Vimx.cs +++ b/src/cs/vim/Vim.Format.Vimx/Vimx.cs @@ -31,10 +31,9 @@ public class Vimx public readonly MetaHeader Meta; public readonly G3dScene Scene; public readonly G3dMaterials Materials; - //public readonly VimxChunk[] Chunks; - public readonly G3dMesh[] Chunks; + public readonly G3dChunk[] Chunks; - public Vimx(SerializableHeader header, MetaHeader meta, G3dScene scene, G3dMaterials materials, G3dMesh[] chunks) + public Vimx(SerializableHeader header, MetaHeader meta, G3dScene scene, G3dMaterials materials, G3dChunk[] chunks) { Meta = meta; Header = header; @@ -57,7 +56,7 @@ public Vimx(BFast bfast) Chunks = Enumerable.Range(0, Scene.GetChunksCount()) .Select(c => bfast.GetBFast(BufferNames.Chunk(c), BufferCompression.Chunks)) - .Select(b => new G3dMesh(b)) + .Select(b => new G3dChunk(b)) .ToArray(); } diff --git a/src/cs/vim/Vim.Format.Vimx/VimxChunk.cs b/src/cs/vim/Vim.Format.Vimx/VimxChunk.cs index c90bb8dd..0b766bff 100644 --- a/src/cs/vim/Vim.Format.Vimx/VimxChunk.cs +++ b/src/cs/vim/Vim.Format.Vimx/VimxChunk.cs @@ -7,15 +7,15 @@ namespace Vim.Format.VimxNS { public class VimxChunk { - public List Meshes = new List(); + public List Meshes = new List(); public VimxChunk() { } - public VimxChunk(List meshes) { Meshes = meshes; } + public VimxChunk(List meshes) { Meshes = meshes; } public VimxChunk(BFast bfast) { Meshes = bfast.Entries - .Select(e => new G3dMesh(bfast.GetBFast(e))) + .Select(e => new G3dChunk(bfast.GetBFast(e))) .ToList(); } diff --git a/src/cs/vim/Vim.Vimx.Test/VimxActions.cs b/src/cs/vim/Vim.Vimx.Test/VimxActions.cs index cede562f..f6db6697 100644 --- a/src/cs/vim/Vim.Vimx.Test/VimxActions.cs +++ b/src/cs/vim/Vim.Vimx.Test/VimxActions.cs @@ -1,4 +1,5 @@ using NUnit.Framework; +using System.Diagnostics; using Vim.Format.VimxNS.Conversion; using Vim.Util.Tests; @@ -15,18 +16,23 @@ public static class VimxActions public static void ConvertVimToVimx() { // var input = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); - var input = Path.Join(VimFormatRepoPaths.DataDir, residence); - //var input = Path.Join(VimFormatRepoPaths.DataDir, "nbk.vim"); + //var input = Path.Join(VimFormatRepoPaths.DataDir, whiteleys); + var input = Path.Join(VimFormatRepoPaths.DataDir, "nbk.vim"); var name = Path.GetFileNameWithoutExtension(input); var output = Path.Combine(VimFormatRepoPaths.OutDir, name + ".vimx"); + var sw = Stopwatch.StartNew(); var vimx = VimxConverter.FromVimPath(input); - Console.WriteLine(vimx.Materials.MaterialSmoothness); + Console.WriteLine("FromVimPath " + sw.ElapsedMilliseconds); - vimx.ToBFast().Write(output); - var v = Vimx.FromPath(output); - Console.WriteLine(v.Scene.InstanceTransformData.Length); + sw.Restart(); + var bfast = vimx.ToBFast(); + Console.WriteLine("Write " + sw.ElapsedMilliseconds); + + sw.Restart(); + bfast.Write(output); + Console.WriteLine("Write " + sw.ElapsedMilliseconds); } } } From 01eba97ef66365d2cb1135c646cd64ac4b001096 Mon Sep 17 00:00:00 2001 From: simon Date: Thu, 11 Jan 2024 16:41:57 -0500 Subject: [PATCH 041/111] NUnit version to match with vimaec repo --- src/cs/bfast/Vim.BFast.Tests/Vim.BFast.Tests.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cs/bfast/Vim.BFast.Tests/Vim.BFast.Tests.csproj b/src/cs/bfast/Vim.BFast.Tests/Vim.BFast.Tests.csproj index 2179c1db..f5a64658 100644 --- a/src/cs/bfast/Vim.BFast.Tests/Vim.BFast.Tests.csproj +++ b/src/cs/bfast/Vim.BFast.Tests/Vim.BFast.Tests.csproj @@ -11,7 +11,7 @@ - + From 592018722a438f0159890f1c377e6061534157a4 Mon Sep 17 00:00:00 2001 From: simon Date: Fri, 12 Jan 2024 11:22:51 -0500 Subject: [PATCH 042/111] fixed nunit versions to match vimaec --- src/cs/bfast/Vim.BFast.Tests/Vim.BFast.Tests.csproj | 1 - src/cs/vim/Vim.Vimx.Test/Vim.Format.Vimx.Test.csproj | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/cs/bfast/Vim.BFast.Tests/Vim.BFast.Tests.csproj b/src/cs/bfast/Vim.BFast.Tests/Vim.BFast.Tests.csproj index f5a64658..9c4ce3ec 100644 --- a/src/cs/bfast/Vim.BFast.Tests/Vim.BFast.Tests.csproj +++ b/src/cs/bfast/Vim.BFast.Tests/Vim.BFast.Tests.csproj @@ -10,7 +10,6 @@ - diff --git a/src/cs/vim/Vim.Vimx.Test/Vim.Format.Vimx.Test.csproj b/src/cs/vim/Vim.Vimx.Test/Vim.Format.Vimx.Test.csproj index ff2ffb1c..fa59a272 100644 --- a/src/cs/vim/Vim.Vimx.Test/Vim.Format.Vimx.Test.csproj +++ b/src/cs/vim/Vim.Vimx.Test/Vim.Format.Vimx.Test.csproj @@ -10,9 +10,8 @@ - - + From 2a0f3c6c5b99fb965de08b3b85cc82aaf555effc Mon Sep 17 00:00:00 2001 From: simon Date: Fri, 12 Jan 2024 13:25:57 -0500 Subject: [PATCH 043/111] removed uneeded packages --- src/cs/bfast/Vim.BFast.Tests/Vim.BFast.Tests.csproj | 3 +-- src/cs/vim/Vim.Vimx.Test/Vim.Format.Vimx.Test.csproj | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/cs/bfast/Vim.BFast.Tests/Vim.BFast.Tests.csproj b/src/cs/bfast/Vim.BFast.Tests/Vim.BFast.Tests.csproj index 9c4ce3ec..98f7f7a7 100644 --- a/src/cs/bfast/Vim.BFast.Tests/Vim.BFast.Tests.csproj +++ b/src/cs/bfast/Vim.BFast.Tests/Vim.BFast.Tests.csproj @@ -10,10 +10,9 @@ + - - diff --git a/src/cs/vim/Vim.Vimx.Test/Vim.Format.Vimx.Test.csproj b/src/cs/vim/Vim.Vimx.Test/Vim.Format.Vimx.Test.csproj index fa59a272..b88dcd29 100644 --- a/src/cs/vim/Vim.Vimx.Test/Vim.Format.Vimx.Test.csproj +++ b/src/cs/vim/Vim.Vimx.Test/Vim.Format.Vimx.Test.csproj @@ -10,7 +10,7 @@ - + From 46d4470fc9fd4ce742ff1b0da1fe8d5807ae5f3f Mon Sep 17 00:00:00 2001 From: simon Date: Tue, 16 Jan 2024 10:59:12 -0500 Subject: [PATCH 044/111] updated test and removed old tests. --- src/ts/src/index.ts | 1 + src/ts/src/vimHelpers.ts | 2 +- src/ts/src/vimLoader.ts | 3 +- src/ts/tests/filter_0.txt | 1 - src/ts/tests/filter_1.txt | 1 - src/ts/tests/filter_4000.txt | 1 - src/ts/tests/filter_8059.txt | 1 - src/ts/tests/g3d.test.ts | 63 ---------- src/ts/tests/helpers.ts | 192 ---------------------------- src/ts/tests/objectModel.test.ts | 17 +-- src/ts/tests/remoteG3d.test.ts | 209 ------------------------------- src/ts/tests/vimHelpers.test.ts | 2 +- 12 files changed, 14 insertions(+), 479 deletions(-) delete mode 100644 src/ts/tests/filter_0.txt delete mode 100644 src/ts/tests/filter_1.txt delete mode 100644 src/ts/tests/filter_4000.txt delete mode 100644 src/ts/tests/filter_8059.txt delete mode 100644 src/ts/tests/g3d.test.ts delete mode 100644 src/ts/tests/remoteG3d.test.ts diff --git a/src/ts/src/index.ts b/src/ts/src/index.ts index 180f23c1..c4f05ee2 100644 --- a/src/ts/src/index.ts +++ b/src/ts/src/index.ts @@ -4,6 +4,7 @@ export * from './g3d' export * from './remoteVimx' export * from './g3dMaterials' export * from './g3dMesh' +export * from './g3dChunk' export * from './g3dScene' export * from './remoteBuffer' export * from './requestTracker' diff --git a/src/ts/src/vimHelpers.ts b/src/ts/src/vimHelpers.ts index 2af207a7..61c71bcf 100644 --- a/src/ts/src/vimHelpers.ts +++ b/src/ts/src/vimHelpers.ts @@ -1,7 +1,7 @@ import { VimDocument } from "./objectModel" /** - * Representation of ElementParamter entity from the entity model + * Representation of ElementParameter entity from the entity model * See https://github.com/vimaec/vim/blob/master/ObjectModel/object-model-schema.json */ export type ElementParameter = { diff --git a/src/ts/src/vimLoader.ts b/src/ts/src/vimLoader.ts index 97e28523..744bccf5 100644 --- a/src/ts/src/vimLoader.ts +++ b/src/ts/src/vimLoader.ts @@ -5,14 +5,13 @@ import { BFast } from "./bfast" export class VimLoader { - static async loadFromBfast(bfast: BFast, download: boolean, ignoreStrings: boolean, ): Promise<[BFast | undefined, string[] | undefined]> { + static async loadFromBfast(bfast: BFast, download: boolean, ignoreStrings: boolean): Promise<[BFast | undefined, string[] | undefined]> { const [entity, strings] = await Promise.all([ VimLoader.requestEntities(bfast, download), ignoreStrings ? Promise.resolve(undefined) : VimLoader.requestStrings(bfast) ]) - return [entity, strings] as [BFast, string[]] } diff --git a/src/ts/tests/filter_0.txt b/src/ts/tests/filter_0.txt deleted file mode 100644 index d38d96a2..00000000 --- a/src/ts/tests/filter_0.txt +++ /dev/null @@ -1 +0,0 @@ -{"DEFAULT_COLOR":{"0":1,"1":1,"2":1,"3":1},"instanceMeshes":{"0":-1},"instanceFlags":{"0":0},"instanceTransforms":{"0":1,"1":0,"2":0,"3":0,"4":0,"5":1,"6":0,"7":0,"8":0,"9":0,"10":1,"11":0,"12":0,"13":0,"14":0,"15":1},"instanceNodes":{"0":0},"meshSubmeshes":{},"submeshIndexOffset":{},"submeshMaterial":{},"indices":{},"positions":{},"materialColors":{},"meshVertexOffsets":{},"meshInstances":[],"meshOpaqueCount":[]} \ No newline at end of file diff --git a/src/ts/tests/filter_1.txt b/src/ts/tests/filter_1.txt deleted file mode 100644 index d9ae7665..00000000 --- a/src/ts/tests/filter_1.txt +++ /dev/null @@ -1 +0,0 @@ -{"DEFAULT_COLOR":{"0":1,"1":1,"2":1,"3":1},"instanceMeshes":{"0":0},"instanceFlags":{"0":0},"instanceTransforms":{"0":1,"1":0,"2":0,"3":0,"4":0,"5":1,"6":0,"7":0,"8":0,"9":0,"10":1,"11":0,"12":0,"13":0,"14":0,"15":1},"instanceNodes":{"0":1},"meshSubmeshes":{"0":0},"submeshIndexOffset":{"0":0,"1":42},"submeshMaterial":{"0":1,"1":0},"indices":{"0":6,"1":7,"2":8,"3":4,"4":5,"5":2,"6":10,"7":11,"8":0,"9":10,"10":1,"11":9,"12":1,"13":10,"14":0,"15":9,"16":1,"17":2,"18":9,"19":6,"20":8,"21":2,"22":3,"23":4,"24":2,"25":6,"26":9,"27":2,"28":5,"29":6,"30":55,"31":50,"32":51,"33":54,"34":55,"35":52,"36":51,"37":52,"38":55,"39":52,"40":53,"41":54,"42":12,"43":20,"44":21,"45":20,"46":12,"47":17,"48":39,"49":12,"50":21,"51":16,"52":17,"53":12,"54":24,"55":21,"56":23,"57":20,"58":17,"59":19,"60":12,"61":13,"62":16,"63":39,"64":21,"65":24,"66":37,"67":38,"68":39,"69":25,"70":39,"71":24,"72":32,"73":39,"74":25,"75":29,"76":32,"77":25,"78":35,"79":37,"80":39,"81":33,"82":35,"83":39,"84":32,"85":29,"86":31,"87":33,"88":39,"89":32,"90":29,"91":25,"92":28,"93":16,"94":13,"95":15,"96":18,"97":19,"98":17,"99":21,"100":22,"101":23,"102":26,"103":28,"104":25,"105":34,"106":35,"107":33,"108":30,"109":31,"110":29,"111":35,"112":36,"113":37,"114":28,"115":26,"116":27,"117":15,"118":13,"119":14,"120":40,"121":41,"122":43,"123":42,"124":43,"125":41,"126":43,"127":44,"128":40,"129":45,"130":46,"131":48,"132":47,"133":48,"134":46,"135":48,"136":49,"137":45,"138":58,"139":59,"140":57,"141":58,"142":57,"143":56,"144":69,"145":70,"146":61,"147":73,"148":61,"149":70,"150":70,"151":71,"152":73,"153":61,"154":73,"155":74,"156":74,"157":60,"158":61,"159":66,"160":69,"161":62,"162":61,"163":62,"164":69,"165":62,"166":65,"167":66,"168":68,"169":69,"170":66,"171":63,"172":65,"173":62,"174":72,"175":73,"176":71,"177":64,"178":65,"179":63,"180":67,"181":68,"182":66,"183":60,"184":74,"185":75,"186":83,"187":80,"188":82,"189":81,"190":82,"191":80,"192":83,"193":76,"194":78,"195":78,"196":80,"197":83,"198":80,"199":78,"200":79,"201":78,"202":76,"203":77,"204":86,"205":87,"206":85,"207":86,"208":85,"209":84,"210":90,"211":91,"212":92,"213":88,"214":89,"215":92,"216":90,"217":92,"218":89,"219":93,"220":88,"221":92,"222":96,"223":97,"224":95,"225":96,"226":95,"227":94,"228":100,"229":101,"230":99,"231":100,"232":99,"233":98,"234":104,"235":105,"236":103,"237":104,"238":103,"239":102,"240":108,"241":109,"242":107,"243":108,"244":107,"245":106,"246":112,"247":113,"248":111,"249":112,"250":111,"251":110,"252":116,"253":117,"254":115,"255":116,"256":115,"257":114,"258":120,"259":121,"260":119,"261":120,"262":119,"263":118,"264":124,"265":125,"266":123,"267":124,"268":123,"269":122,"270":128,"271":129,"272":127,"273":128,"274":127,"275":126,"276":132,"277":133,"278":131,"279":132,"280":131,"281":130,"282":136,"283":137,"284":135,"285":136,"286":135,"287":134,"288":140,"289":141,"290":139,"291":140,"292":139,"293":138,"294":144,"295":145,"296":143,"297":144,"298":143,"299":142,"300":148,"301":149,"302":147,"303":148,"304":147,"305":146,"306":155,"307":150,"308":154,"309":151,"310":152,"311":154,"312":153,"313":154,"314":152,"315":150,"316":151,"317":154,"318":158,"319":159,"320":157,"321":158,"322":157,"323":156,"324":162,"325":163,"326":161,"327":162,"328":161,"329":160,"330":166,"331":167,"332":165,"333":166,"334":165,"335":164},"positions":{"0":-41.18024826049805,"1":-27.568527221679688,"2":-2,"3":-42.21149826049805,"4":-27.568527221679688,"5":-2,"6":-42.21149826049805,"7":-27.568527221679688,"8":10.381101608276367,"9":-42.21149826049805,"10":-27.568527221679688,"11":10.65625,"12":-41.22191619873047,"13":-27.568527221679688,"14":10.65625,"15":-41.22191619873047,"16":-27.568527221679688,"17":10.381101608276367,"18":-41.22191619873047,"19":-27.568527221679688,"20":8.65625,"21":-41.19066619873047,"22":-27.568527221679688,"23":8.65625,"24":-41.19066619873047,"25":-27.568527221679688,"26":8.385416984558105,"27":-41.234859466552734,"28":-27.568527221679688,"29":8.341222763061523,"30":-41.22749328613281,"31":-27.568527221679688,"32":8.333856582641602,"33":-41.18024826049805,"34":-27.568527221679688,"35":8.381101608276367,"36":-42.21149826049805,"37":-28.172693252563477,"38":-2,"39":-41.607330322265625,"40":-28.172693252563477,"41":-2,"42":-41.18024826049805,"43":-28.172693252563477,"44":-2,"45":-41.18024826049805,"46":-28.172693252563477,"47":0.34207287430763245,"48":-41.607330322265625,"49":-28.172693252563477,"50":0.34207287430763245,"51":-41.607330322265625,"52":-28.172693252563477,"53":0.38373956084251404,"54":-41.18024826049805,"55":-28.172693252563477,"56":0.38373956084251404,"57":-41.18024826049805,"58":-28.172693252563477,"59":3.106520891189575,"60":-41.607330322265625,"61":-28.172693252563477,"62":3.106520891189575,"63":-41.607330322265625,"64":-28.172693252563477,"65":3.1481873989105225,"66":-41.18024826049805,"67":-28.172693252563477,"68":3.1481873989105225,"69":-41.18024826049805,"70":-28.172693252563477,"71":5.870968818664551,"72":-41.607330322265625,"73":-28.172693252563477,"74":5.870968818664551,"75":-41.607330322265625,"76":-28.172693252563477,"77":5.912635326385498,"78":-41.18024826049805,"79":-28.172693252563477,"80":5.912635326385498,"81":-41.18024826049805,"82":-28.172693252563477,"83":8.381101608276367,"84":-41.22749328613281,"85":-28.172693252563477,"86":8.333856582641602,"87":-41.234859466552734,"88":-28.172693252563477,"89":8.341222763061523,"90":-41.19066619873047,"91":-28.172693252563477,"92":8.385416984558105,"93":-41.19066619873047,"94":-28.172693252563477,"95":8.635416984558105,"96":-41.607330322265625,"97":-28.172693252563477,"98":8.635416984558105,"99":-41.607330322265625,"100":-28.172693252563477,"101":8.677083015441895,"102":-41.22191619873047,"103":-28.172693252563477,"104":8.677083015441895,"105":-41.22191619873047,"106":-28.172693252563477,"107":10.381101608276367,"108":-41.22191619873047,"109":-28.172693252563477,"110":10.65625,"111":-41.607330322265625,"112":-28.172693252563477,"113":10.65625,"114":-42.21149826049805,"115":-28.172693252563477,"116":10.65625,"117":-42.21149826049805,"118":-28.172693252563477,"119":10.381101608276367,"120":-42.21149826049805,"121":-27.568527221679688,"122":-2,"123":-41.18024826049805,"124":-27.568527221679688,"125":-2,"126":-41.18024826049805,"127":-28.172693252563477,"128":-2,"129":-41.607330322265625,"130":-28.172693252563477,"131":-2,"132":-42.21149826049805,"133":-28.172693252563477,"134":-2,"135":-41.22191619873047,"136":-27.568527221679688,"137":10.65625,"138":-42.21149826049805,"139":-27.568527221679688,"140":10.65625,"141":-42.21149826049805,"142":-28.172693252563477,"143":10.65625,"144":-41.607330322265625,"145":-28.172693252563477,"146":10.65625,"147":-41.22191619873047,"148":-28.172693252563477,"149":10.65625,"150":-42.21149826049805,"151":-27.568527221679688,"152":-2,"153":-42.21149826049805,"154":-28.172693252563477,"155":-2,"156":-42.21149826049805,"157":-28.172693252563477,"158":10.381101608276367,"159":-42.21149826049805,"160":-28.172693252563477,"161":10.65625,"162":-42.21149826049805,"163":-27.568527221679688,"164":10.65625,"165":-42.21149826049805,"166":-27.568527221679688,"167":10.381101608276367,"168":-41.22191619873047,"169":-27.568527221679688,"170":8.65625,"171":-41.19066619873047,"172":-27.568527221679688,"173":8.65625,"174":-41.22191619873047,"175":-28.131027221679688,"176":8.65625,"177":-41.19066619873047,"178":-28.131027221679688,"179":8.65625,"180":-41.18024826049805,"181":-28.172693252563477,"182":-2,"183":-41.18024826049805,"184":-27.568527221679688,"185":-2,"186":-41.18024826049805,"187":-27.568527221679688,"188":8.381101608276367,"189":-41.18024826049805,"190":-28.172693252563477,"191":8.381101608276367,"192":-41.18024826049805,"193":-28.172693252563477,"194":5.912635326385498,"195":-41.18024826049805,"196":-28.131027221679688,"197":5.912635326385498,"198":-41.18024826049805,"199":-28.131027221679688,"200":5.870968818664551,"201":-41.18024826049805,"202":-28.172693252563477,"203":5.870968818664551,"204":-41.18024826049805,"205":-28.172693252563477,"206":3.1481873989105225,"207":-41.18024826049805,"208":-28.131027221679688,"209":3.1481873989105225,"210":-41.18024826049805,"211":-28.131027221679688,"212":3.106520891189575,"213":-41.18024826049805,"214":-28.172693252563477,"215":3.106520891189575,"216":-41.18024826049805,"217":-28.172693252563477,"218":0.38373956084251404,"219":-41.18024826049805,"220":-28.131027221679688,"221":0.38373956084251404,"222":-41.18024826049805,"223":-28.131027221679688,"224":0.34207287430763245,"225":-41.18024826049805,"226":-28.172693252563477,"227":0.34207287430763245,"228":-41.22191619873047,"229":-27.568527221679688,"230":10.65625,"231":-41.22191619873047,"232":-28.172693252563477,"233":10.65625,"234":-41.22191619873047,"235":-28.172693252563477,"236":10.381101608276367,"237":-41.22191619873047,"238":-28.172693252563477,"239":8.677083015441895,"240":-41.22191619873047,"241":-28.131027221679688,"242":8.677083015441895,"243":-41.22191619873047,"244":-28.131027221679688,"245":8.65625,"246":-41.22191619873047,"247":-27.568527221679688,"248":8.65625,"249":-41.22191619873047,"250":-27.568527221679688,"251":10.381101608276367,"252":-41.607330322265625,"253":-28.172693252563477,"254":8.635416984558105,"255":-41.607330322265625,"256":-28.172693252563477,"257":8.677083015441895,"258":-41.607330322265625,"259":-28.131027221679688,"260":8.635416984558105,"261":-41.607330322265625,"262":-28.131027221679688,"263":8.677083015441895,"264":-41.607330322265625,"265":-28.131027221679688,"266":8.677083015441895,"267":-41.607330322265625,"268":-28.131027221679688,"269":8.635416984558105,"270":-41.19066619873047,"271":-28.131027221679688,"272":8.635416984558105,"273":-41.19066619873047,"274":-28.131027221679688,"275":8.65625,"276":-41.22191619873047,"277":-28.131027221679688,"278":8.65625,"279":-41.22191619873047,"280":-28.131027221679688,"281":8.677083015441895,"282":-41.607330322265625,"283":-28.172693252563477,"284":8.677083015441895,"285":-41.22191619873047,"286":-28.172693252563477,"287":8.677083015441895,"288":-41.607330322265625,"289":-28.131027221679688,"290":8.677083015441895,"291":-41.22191619873047,"292":-28.131027221679688,"293":8.677083015441895,"294":-41.607330322265625,"295":-28.131027221679688,"296":8.635416984558105,"297":-41.19066619873047,"298":-28.131027221679688,"299":8.635416984558105,"300":-41.607330322265625,"301":-28.172693252563477,"302":8.635416984558105,"303":-41.19066619873047,"304":-28.172693252563477,"305":8.635416984558105,"306":-41.607330322265625,"307":-28.172693252563477,"308":5.870968818664551,"309":-41.607330322265625,"310":-28.172693252563477,"311":5.912635326385498,"312":-41.607330322265625,"313":-28.131027221679688,"314":5.870968818664551,"315":-41.607330322265625,"316":-28.131027221679688,"317":5.912635326385498,"318":-41.607330322265625,"319":-28.131027221679688,"320":5.912635326385498,"321":-41.18024826049805,"322":-28.131027221679688,"323":5.912635326385498,"324":-41.607330322265625,"325":-28.131027221679688,"326":5.870968818664551,"327":-41.18024826049805,"328":-28.131027221679688,"329":5.870968818664551,"330":-41.607330322265625,"331":-28.172693252563477,"332":5.912635326385498,"333":-41.18024826049805,"334":-28.172693252563477,"335":5.912635326385498,"336":-41.607330322265625,"337":-28.131027221679688,"338":5.912635326385498,"339":-41.18024826049805,"340":-28.131027221679688,"341":5.912635326385498,"342":-41.607330322265625,"343":-28.131027221679688,"344":5.870968818664551,"345":-41.18024826049805,"346":-28.131027221679688,"347":5.870968818664551,"348":-41.607330322265625,"349":-28.172693252563477,"350":5.870968818664551,"351":-41.18024826049805,"352":-28.172693252563477,"353":5.870968818664551,"354":-41.607330322265625,"355":-28.172693252563477,"356":3.106520891189575,"357":-41.607330322265625,"358":-28.172693252563477,"359":3.1481873989105225,"360":-41.607330322265625,"361":-28.131027221679688,"362":3.106520891189575,"363":-41.607330322265625,"364":-28.131027221679688,"365":3.1481873989105225,"366":-41.607330322265625,"367":-28.131027221679688,"368":3.1481873989105225,"369":-41.18024826049805,"370":-28.131027221679688,"371":3.1481873989105225,"372":-41.607330322265625,"373":-28.131027221679688,"374":3.106520891189575,"375":-41.18024826049805,"376":-28.131027221679688,"377":3.106520891189575,"378":-41.607330322265625,"379":-28.172693252563477,"380":3.1481873989105225,"381":-41.18024826049805,"382":-28.172693252563477,"383":3.1481873989105225,"384":-41.607330322265625,"385":-28.131027221679688,"386":3.1481873989105225,"387":-41.18024826049805,"388":-28.131027221679688,"389":3.1481873989105225,"390":-41.607330322265625,"391":-28.131027221679688,"392":3.106520891189575,"393":-41.18024826049805,"394":-28.131027221679688,"395":3.106520891189575,"396":-41.607330322265625,"397":-28.172693252563477,"398":3.106520891189575,"399":-41.18024826049805,"400":-28.172693252563477,"401":3.106520891189575,"402":-41.607330322265625,"403":-28.172693252563477,"404":0.34207287430763245,"405":-41.607330322265625,"406":-28.172693252563477,"407":0.38373956084251404,"408":-41.607330322265625,"409":-28.131027221679688,"410":0.34207287430763245,"411":-41.607330322265625,"412":-28.131027221679688,"413":0.38373956084251404,"414":-41.607330322265625,"415":-28.131027221679688,"416":0.38373956084251404,"417":-41.18024826049805,"418":-28.131027221679688,"419":0.38373956084251404,"420":-41.607330322265625,"421":-28.131027221679688,"422":0.34207287430763245,"423":-41.18024826049805,"424":-28.131027221679688,"425":0.34207287430763245,"426":-41.607330322265625,"427":-28.172693252563477,"428":0.38373956084251404,"429":-41.18024826049805,"430":-28.172693252563477,"431":0.38373956084251404,"432":-41.607330322265625,"433":-28.131027221679688,"434":0.38373956084251404,"435":-41.18024826049805,"436":-28.131027221679688,"437":0.38373956084251404,"438":-41.607330322265625,"439":-28.131027221679688,"440":0.34207287430763245,"441":-41.18024826049805,"442":-28.131027221679688,"443":0.34207287430763245,"444":-41.607330322265625,"445":-28.172693252563477,"446":0.34207287430763245,"447":-41.18024826049805,"448":-28.172693252563477,"449":0.34207287430763245,"450":-41.19066619873047,"451":-28.172693252563477,"452":8.385416984558105,"453":-41.19066619873047,"454":-27.568527221679688,"455":8.385416984558105,"456":-41.19066619873047,"457":-27.568527221679688,"458":8.65625,"459":-41.19066619873047,"460":-28.131027221679688,"461":8.65625,"462":-41.19066619873047,"463":-28.131027221679688,"464":8.635416984558105,"465":-41.19066619873047,"466":-28.172693252563477,"467":8.635416984558105,"468":-41.19066619873047,"469":-27.568527221679688,"470":8.385416984558105,"471":-41.234859466552734,"472":-27.568527221679688,"473":8.341222763061523,"474":-41.19066619873047,"475":-28.172693252563477,"476":8.385416984558105,"477":-41.234859466552734,"478":-28.172693252563477,"479":8.341222763061523,"480":-41.234859466552734,"481":-27.568527221679688,"482":8.341222763061523,"483":-41.22749328613281,"484":-27.568527221679688,"485":8.333856582641602,"486":-41.234859466552734,"487":-28.172693252563477,"488":8.341222763061523,"489":-41.22749328613281,"490":-28.172693252563477,"491":8.333856582641602,"492":-41.22749328613281,"493":-27.568527221679688,"494":8.333856582641602,"495":-41.18024826049805,"496":-27.568527221679688,"497":8.381101608276367,"498":-41.22749328613281,"499":-28.172693252563477,"500":8.333856582641602,"501":-41.18024826049805,"502":-28.172693252563477,"503":8.381101608276367},"materialColors":{"0":0.9725490212440491,"1":0.9686274528503418,"2":0.9529411792755127,"3":1,"4":1,"5":1,"6":1,"7":1},"meshVertexOffsets":{"0":0},"meshInstances":[[0]],"meshOpaqueCount":[2]} \ No newline at end of file diff --git a/src/ts/tests/filter_4000.txt b/src/ts/tests/filter_4000.txt deleted file mode 100644 index 99561a0b..00000000 --- a/src/ts/tests/filter_4000.txt +++ /dev/null @@ -1 +0,0 @@ -{"DEFAULT_COLOR":{"0":1,"1":1,"2":1,"3":1},"instanceMeshes":{"0":-1},"instanceFlags":{"0":0},"instanceTransforms":{"0":1,"1":0,"2":0,"3":0,"4":0,"5":1,"6":0,"7":0,"8":0,"9":0,"10":1,"11":0,"12":0,"13":0,"14":0,"15":1},"instanceNodes":{"0":4000},"meshSubmeshes":{},"submeshIndexOffset":{},"submeshMaterial":{},"indices":{},"positions":{},"materialColors":{},"meshVertexOffsets":{},"meshInstances":[],"meshOpaqueCount":[]} \ No newline at end of file diff --git a/src/ts/tests/filter_8059.txt b/src/ts/tests/filter_8059.txt deleted file mode 100644 index af6f3c72..00000000 --- a/src/ts/tests/filter_8059.txt +++ /dev/null @@ -1 +0,0 @@ -{"DEFAULT_COLOR":{"0":1,"1":1,"2":1,"3":1},"instanceMeshes":{"0":-1},"instanceFlags":{"0":0},"instanceTransforms":{"0":1,"1":0,"2":0,"3":0,"4":0,"5":1,"6":0,"7":0,"8":0,"9":0,"10":1,"11":0,"12":0,"13":0,"14":0,"15":1},"instanceNodes":{"0":8059},"meshSubmeshes":{},"submeshIndexOffset":{},"submeshMaterial":{},"indices":{},"positions":{},"materialColors":{},"meshVertexOffsets":{},"meshInstances":[],"meshOpaqueCount":[]} \ No newline at end of file diff --git a/src/ts/tests/g3d.test.ts b/src/ts/tests/g3d.test.ts deleted file mode 100644 index 84775206..00000000 --- a/src/ts/tests/g3d.test.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { g3dAreEqual, getFilterTestFile, instanceAreEqual, loadG3d, testVimFilePath } from "./helpers" -import * as fs from 'fs'; - -describe('G3d', () =>{ - - test('g3d.append', async () =>{ - const g3d = await loadG3d(testVimFilePath) - - for(let i = 0; i < g3d.getInstanceCount(); i++ ){ - const slice = g3d.slice(i) - const merge = slice.append(slice) - instanceAreEqual(merge, 0, g3d, i) - instanceAreEqual(merge, 1, g3d, i) - } - }) - - test('g3d.equals (all)', async () =>{ - const g3d = await loadG3d(testVimFilePath) - expect(g3dAreEqual(g3d, g3d)).toBeTruthy() - }) - - test('g3d.filter (all)', async () => { - const g3d = await loadG3d(testVimFilePath) - - const instances = g3d.instanceMeshes.map((_,i) => i) - const filter = g3d.filter([...instances]) - expect(g3dAreEqual(filter, g3d)).toBeTruthy() - }) - - - - test('G3d.filter (some)', async () =>{ - const g3d = await loadG3d(testVimFilePath) - const instances = [0, 1, 4000, 8059] - for(let i=0; i < instances.length; i++){ - const instance = instances[i] - const path = getFilterTestFile(instance) - const data = await fs.promises.readFile(path) - const expected = data.toString() - - const filter = g3d.filter([instance]) - const value = JSON.stringify(filter) - - expect(value).toEqual(expected) - } - }) - - /* - // Run this to regenerate test cases. - test('G3d.toJson', async () =>{ - const g3d = await loadG3d() - const instances = [0, 1, 4000, 8059] - for(let i=0; i < instances.length; i++){ - const instance = instances[i] - const filter = g3d.filter([instance]) - const str = JSON.stringify(filter) - await fs.promises.writeFile(getFilterTestFile(instance), str); - } - }) - */ -}) - - diff --git a/src/ts/tests/helpers.ts b/src/ts/tests/helpers.ts index fce03983..2aa08654 100644 --- a/src/ts/tests/helpers.ts +++ b/src/ts/tests/helpers.ts @@ -1,13 +1,7 @@ import * as fs from 'fs' -import { BFast } from '../src/bfast' -import { G3d, VimAttributes } from '../src/g3d' -import { AbstractG3d } from '../src/abstractG3d' -import { RemoteG3d } from '../src/remoteG3d' - export const testVimFilePath = `${__dirname}/../../../data/Wolford_Residence.r2023.om_v4.4.0.vim` - export function loadFile(path: string) { return new Promise((resolve, reject) => { fs.readFile(path, (err, data) => { @@ -25,189 +19,3 @@ export function loadFile(path: string) { }) }) } - -export async function loadBoth(vimFilePath: string){ - const arrayBuffer = await loadFile(vimFilePath) - const bfast = new BFast((arrayBuffer as ArrayBuffer)!) - const g3dBfast = await bfast.getBfast('geometry') - const g3d = await G3d.createFromBfast(g3dBfast!) - const remote = RemoteG3d.createFromBfast(g3dBfast!) - return [g3d, remote] as [G3d, RemoteG3d] -} - -export async function loadRemote(vimFilePath: string){ - const arrayBuffer = await loadFile(vimFilePath) - const bfast = new BFast((arrayBuffer as ArrayBuffer)!) - const g3dBfast = await bfast.getBfast('geometry') - const remote = RemoteG3d.createFromBfast(g3dBfast!) - return remote -} - -export async function loadAbstract(vimFilePath: string){ - const arrayBuffer = await loadFile(vimFilePath) - const bfast = new BFast((arrayBuffer as ArrayBuffer)!) - const g3dBfast = await bfast.getBfast('geometry') - const remote = await AbstractG3d.createFromBfast(g3dBfast!, VimAttributes.all) - return remote -} - -export async function loadG3d(vimFilePath: string){ - const arrayBuffer = await loadFile(vimFilePath) - const bfast = new BFast((arrayBuffer as ArrayBuffer)!) - const g3dBfast = await bfast.getBfast('geometry') - return await G3d.createFromBfast(g3dBfast!) -} - -export function expectG3dAreSame(self: G3d, other: G3d){ - expect(self.instanceFlags).toEqual(other.instanceFlags) - expect(self.instanceMeshes).toEqual(other.instanceMeshes) - expect(self.instanceTransforms).toEqual(other.instanceTransforms) - expect(self.instanceNodes).toEqual(other.instanceNodes) - - expect(self.meshSubmeshes).toEqual(other.meshSubmeshes) - expect(self.submeshIndexOffset).toEqual(other.submeshIndexOffset) - - expect(self.submeshMaterial).toEqual(other.submeshMaterial) - expect(self.materialColors).toEqual(other.materialColors) - expect(self.positions).toEqual(other.positions) - expect(self.indices).toEqual(other.indices) -} - -export function g3dAreEqual(self: G3d, other: G3d){ - if (self.instanceMeshes.length !== other.instanceMeshes.length){ - console.log('instances count !=') - return false - } - for(let i =0; i < self.instanceMeshes.length; i++){ - - if(!instanceAreEqual(self, i, other, i)){ - console.log('instance != ' + i) - return false - } - } - return true -} - -export function instanceAreEqual(self: G3d, instance: number, other:G3d, otherInstance: number){ - const selfFlag = self.instanceFlags[instance] - const otherFlag = other.instanceFlags[otherInstance] - - if(selfFlag !== otherFlag){ - console.log('flags !=') - return false - } - for(let i=0; i < 16; i++){ - if(self.instanceTransforms[instance *16 + i] !== other.instanceTransforms[otherInstance *16 + i]){ - console.log('transform !=') - return false - } - } - const selfMesh = self.instanceMeshes[instance] - const otherMesh = other.instanceMeshes[otherInstance] - return meshAreEqual(self, selfMesh, other, otherMesh) -} - -export function meshAreEqual(self: G3d, mesh: number, other:G3d, otherMesh: number){ - if(mesh === -1 && otherMesh === -1){ - return true - } - if(mesh === -1 || otherMesh === -1){ - return false - } - - const selfSubStart = self.getMeshSubmeshStart(mesh) - const selfSubEnd = self.getMeshSubmeshEnd(mesh) - const selfCount = selfSubEnd - selfSubStart - - const otherSubStart = other.getMeshSubmeshStart(otherMesh) - const otherSubEnd = other.getMeshSubmeshEnd(otherMesh) - const otherCount = otherSubEnd - otherSubStart - - if(selfCount !== otherCount){ - console.log([mesh,otherMesh]) - console.log([selfCount,otherCount]) - console.log('SubCount !=') - return false - } - for(let i = 0 ; i < selfCount; i ++){ - const selfSub = selfSubStart + i - const otherSub = otherSubStart + i - if(!submeshAreEqual(self, mesh, selfSub, other, otherMesh, otherSub)){ - console.log('Sub !=') - return false - } - } - return true -} - -export function submeshAreEqual(self: G3d, mesh: number, submesh: number, other:G3d, otherMesh: number, otherSubmesh: number){ - if(!submeshMaterialIsEqual(self, submesh, other, otherSubmesh)){ - console.log('mat !=') - return false - } - if(!submeshGeometryIsEqual(self, mesh, submesh, other, otherMesh, otherSubmesh)){ - console.log('sub !=') - return false - } - return true -} - -export function submeshMaterialIsEqual(self: G3d, submesh: number, other:G3d, otherSubmesh: number){ - const selfColor = self.getSubmeshColor(submesh) - const otherColor = other.getSubmeshColor(otherSubmesh) - if(selfColor.length !== otherColor.length){ - console.log('mat length !=') - return false - } - for(let i =0 ; i < selfColor.length; i ++){ - if(selfColor[i] !== otherColor[i]){ - console.log('color !=') - console.log(selfColor) - console.log(otherColor) - return false - } - } - return true -} - -export function submeshGeometryIsEqual(self: G3d, mesh: number, submesh: number, other:G3d, otherMesh: number, otherSubmesh: number){ - const selfIndexStart = self.getSubmeshIndexStart(submesh) - const selfIndexEnd = self.getSubmeshIndexEnd(submesh) - const selfIndexCount = selfIndexEnd - selfIndexStart - - const otherIndexStart = other.getSubmeshIndexStart(otherSubmesh) - const otherIndexEnd = other.getSubmeshIndexEnd(otherSubmesh) - const otherIndexCount = otherIndexEnd - otherIndexStart - - const selfVertexStart = self.meshVertexOffsets[mesh] - const otherVertexStart = other.meshVertexOffsets[otherMesh] - - if(selfIndexCount !== otherIndexCount){ - console.log('index count !=') - return false - } - for(let i =0; i < selfIndexCount; i++){ - const selfLocalVertex = self.indices[selfIndexStart + i] - const otherLocalVertex = other.indices[otherIndexStart + i] - - if (selfLocalVertex !== otherLocalVertex){ - console.log('vertex !=') - return false - } - - const selfVertex = selfLocalVertex + selfVertexStart - const otherVertex = otherLocalVertex + otherVertexStart - for(let p=0; p<3; p++){ - - const selfPosition = self.positions[selfVertex*3 + p] - const otherPosition = other.positions[otherVertex*3 + p] - if (selfPosition !== otherPosition){ - console.log([mesh, submesh, selfLocalVertex, selfVertexStart, selfVertex, selfPosition]) - console.log([otherMesh, otherSubmesh, otherLocalVertex, otherVertexStart, otherVertex, otherPosition]) - console.log('position !=') - return false - } - } - } - return true -} diff --git a/src/ts/tests/objectModel.test.ts b/src/ts/tests/objectModel.test.ts index b040935c..0e3ba6e4 100644 --- a/src/ts/tests/objectModel.test.ts +++ b/src/ts/tests/objectModel.test.ts @@ -41,7 +41,7 @@ describe('testing VIM loading file', () => { const arrayBuffer = await testCase.loadFile() const bfast = new BFast((arrayBuffer as ArrayBuffer)!) - const doc = await VimDocument.createFromBfast(bfast) + const doc = await VimDocument.createFromBfast(bfast, false) expect(doc).not.toBe(undefined) expect(doc!.element).not.toBe(undefined); @@ -53,7 +53,7 @@ describe('testing objectModel.ts file', () => { const arrayBuffer = await testCase.loadFile() const bfast = new BFast((arrayBuffer as ArrayBuffer)!) - const doc = await VimDocument.createFromBfast(bfast) + const doc = await VimDocument.createFromBfast(bfast, false) expect(doc).not.toBe(undefined) expect(doc!.element).not.toBe(undefined) @@ -90,7 +90,7 @@ describe('testing objectModel.ts array getter', () => { const arrayBuffer = await testCase.loadFile() const bfast = new BFast((arrayBuffer as ArrayBuffer)!) - const doc = await VimDocument.createFromBfast(bfast) + const doc = await VimDocument.createFromBfast(bfast, false) const ids = await doc?.element?.getAllId() expect(doc).not.toBe(undefined) @@ -106,7 +106,7 @@ describe('testing objectModel.ts get-all getter', () => { const arrayBuffer = await testCase.loadFile() const bfast = new BFast((arrayBuffer as ArrayBuffer)!) - const doc = await VimDocument.createFromBfast(bfast) + const doc = await VimDocument.createFromBfast(bfast, false) const levels = await doc?.level?.getAll() expect(levels).not.toBe(undefined) @@ -119,8 +119,8 @@ describe('testing objectModel.ts ignoreStrings flag', () => { const arrayBuffer = await testCase.loadFile() const bfast = new BFast((arrayBuffer as ArrayBuffer)!) - const docWithStrings = await VimDocument.createFromBfast(bfast) - const docWithoutStrings = await VimDocument.createFromBfast(bfast, true) + const docWithStrings = await VimDocument.createFromBfast(bfast, false, false) + const docWithoutStrings = await VimDocument.createFromBfast(bfast, false, true) const elementWithStrings = await getElementById(docWithStrings!, 374011n) const elementWithoutStrings = await getElementById(docWithoutStrings!, 374011n) @@ -129,10 +129,13 @@ describe('testing objectModel.ts ignoreStrings flag', () => { expect(docWithoutStrings).not.toBeUndefined() expect(elementWithStrings).not.toBeUndefined() expect(elementWithoutStrings).not.toBeUndefined() + expect(elementWithStrings!.name).toBe("GWB on Mtl. Stud") - expect(elementWithoutStrings!.name).toBeUndefined() expect(elementWithStrings!.familyName).toBe("Compound Ceiling") + + expect(elementWithoutStrings!.name).toBeUndefined() expect(elementWithoutStrings!.familyName).toBeUndefined() + expect(elementWithStrings!.id).toBe(elementWithoutStrings!.id) }) }) diff --git a/src/ts/tests/remoteG3d.test.ts b/src/ts/tests/remoteG3d.test.ts deleted file mode 100644 index 601dc7e9..00000000 --- a/src/ts/tests/remoteG3d.test.ts +++ /dev/null @@ -1,209 +0,0 @@ -import { g3dAreEqual, expectG3dAreSame, loadAbstract, loadBoth, loadG3d, loadRemote, testVimFilePath } from './helpers' -import { VimAttributes } from '../src/g3d' - -describe('RemoteG3d', () => { - - test('RemoteG3d.getVertexCount', async () => { - const [g3d, remoteG3d] = await loadBoth(testVimFilePath) - - const value = await remoteG3d.getVertexCount() - const expected = g3d.getVertexCount() - - expect(value).toBe(expected) - }) - - test('RemoteG3d.getMeshCount', async () => { - const [g3d, remoteG3d] = await loadBoth(testVimFilePath) - - const value = await remoteG3d.getMeshCount() - const expected = g3d.getMeshCount() - - expect(value).toBe(expected) - }) - - test('RemoteG3d.getSubmeshCount', async () => { - const [g3d, remoteG3d] = await loadBoth(testVimFilePath) - - const value = await remoteG3d.getSubmeshCount() - const expected = g3d.getSubmeshCount() - expect(value).toBe(expected) - }) - - test('RemoteG3d.meshSubmeshes', async () => { - - const [g3d, remoteG3d] = await loadBoth(testVimFilePath) - const meshCount = g3d.getMeshCount() - - for (let m=0; m < meshCount; m++){ - const value = await remoteG3d.meshSubmeshes.getNumber(m) - const expected = g3d.meshSubmeshes[m] - expect(value).toBe(expected) - } - }) - - test('RemoteG3d.getMeshSubmeshStart', async () => { - - const [g3d, remoteG3d] = await loadBoth(testVimFilePath) - const meshCount = g3d.getMeshCount() - - for (let m=0; m < meshCount; m++){ - const value = await remoteG3d.getMeshSubmeshStart(m) - const expected = g3d.getMeshSubmeshStart(m) - expect(value).toBe(expected) - } - }) - - test('RemoteG3d.getMeshSubmeshEnd', async () => { - - const [g3d, remoteG3d] = await loadBoth(testVimFilePath) - const meshCount = g3d.getMeshCount() - - for (let m=0; m < meshCount; m++){ - const value = await remoteG3d.getMeshSubmeshEnd(m) - const expected = g3d.getMeshSubmeshEnd(m) - expect(value).toBe(expected) - } - }) - - test('RemoteG3d.getMeshIndexStart', async () => { - - const [g3d, remoteG3d] = await loadBoth(testVimFilePath) - const meshCount = g3d.getMeshCount() - - for (let m=0; m < meshCount; m++){ - const value = await remoteG3d.getMeshIndexStart(m) - const expected = g3d.getMeshIndexStart(m) - expect(value).toBe(expected) - } - }) - - test('RemoteG3d.getMeshIndexEnd', async () => { - - const [g3d, remoteG3d] = await loadBoth(testVimFilePath) - const meshCount = g3d.getMeshCount() - for (let m=0; m < meshCount; m++){ - const value = await remoteG3d.getMeshIndexEnd(m) - const expected = g3d.getMeshIndexEnd(m) - expect(value).toBe(expected) - } - }) - - test('RemoteG3d.getMeshIndexCount', async () => { - - const [g3d, remoteG3d] = await loadBoth(testVimFilePath) - const meshCount = g3d.getMeshCount() - - for(let m=0; m < meshCount; m++ ){ - const value = await remoteG3d.getMeshIndexCount(m) - const expected = g3d.getMeshIndexCount(m) - expect(value).toBe(expected) - } - }) - - test('RemoteG3d.getMeshIndices', async () => { - - const remote = await loadRemote(testVimFilePath) - const abstract = await loadAbstract(testVimFilePath) - const g3d = await loadG3d(testVimFilePath) - const meshCount = g3d.getMeshCount() - - const compareIndices = async function(mesh: number){ - const start = g3d.getMeshIndexStart(mesh) - const end = g3d.getMeshIndexEnd(mesh) - - // Compare with original values before reordering. - const value = await remote.getMeshIndices(mesh) - const attribute = abstract.findAttribute(VimAttributes.indices) - const original = new Uint32Array(attribute?.data?.buffer!) - const expected = original.slice(start, end) - - expect(value).toEqual(expected) - } - - for(let m=0; m < meshCount; m++ ){ - await compareIndices(m) - } - }) - - test('RemoteG3d.getMeshSubmeshCount', async () => { - - const [g3d, remoteG3d] = await loadBoth(testVimFilePath) - const meshCount = g3d.getMeshCount() - for(let m=0; m < meshCount; m++){ - const value = await remoteG3d.getMeshSubmeshCount(m) - const expected = await g3d.getMeshSubmeshCount(m) - expect(value).toBe(expected) - } - }) - - test('RemoteG3d.getSubmeshIndexStart', async () => { - - const remoteG3d = await loadRemote(testVimFilePath) - const abstract = await loadAbstract(testVimFilePath) - const g3d = await loadG3d(testVimFilePath) - const submeshCount = g3d.getSubmeshCount() - - for(let m=0; m < submeshCount; m++){ - const value = await remoteG3d.getSubmeshIndexStart(m) - - // Compare with original values before reordering. - const attribute = abstract.findAttribute(VimAttributes.submeshIndexOffsets) - const original = attribute?.data as Int32Array - const expected = original[m] - - expect(value).toBe(expected) - } - }) - - test('RemoteG3d.getSubmeshIndexEnd', async () => { - - const remoteG3d = await loadRemote(testVimFilePath) - const abstract = await loadAbstract(testVimFilePath) - const g3d = await loadG3d(testVimFilePath) - const submeshCount = g3d.getSubmeshCount() - - for(let m=0; m < submeshCount; m++){ - const value = await remoteG3d.getSubmeshIndexEnd(m) - - // Compare with original values before reordering. - const attribute = abstract.findAttribute(VimAttributes.submeshIndexOffsets) - const original = attribute?.data as Int32Array - const expected = m + 1 < original.length ? original[m+1] : g3d.indices.length - expect(value).toBe(expected) - } - }) - - test('RemoteG3d.getSubmeshIndexCount', async () => { - - const [g3d, remoteG3d] = await loadBoth(testVimFilePath) - const submeshCount = g3d.getSubmeshCount() - for(let m=0; m < submeshCount; m++){ - const value = await remoteG3d.getSubmeshIndexCount(-1) - const expected = g3d.getSubmeshIndexCount(-1) - expect(value).toBe(expected) - } - }) - - test('RemoteG3d.toG3d', async () =>{ - const [g3d, remote] = await loadBoth(testVimFilePath) - const value = await remote.toG3d() - expectG3dAreSame(value, g3d) - }) - - test('RemoteG3d.slice', async () =>{ - const [g3d, remote] = await loadBoth(testVimFilePath) - for(let i = 0; i < g3d.getInstanceCount(); i++ ){ - const value = await remote.slice(i) - const expected = await g3d.slice(i) - expect(g3dAreEqual(value, expected)).toBeTruthy() - } - }) - - test('RemoteG3d.filter (all)', async () =>{ - const [g3d, remote] = await loadBoth(testVimFilePath) - const instances = Array.from(g3d.instanceMeshes.map((_,i) => i)) - const expected = g3d.filter(instances) - const value = await remote.filter(instances) - expectG3dAreSame(value, expected) - }) -}) \ No newline at end of file diff --git a/src/ts/tests/vimHelpers.test.ts b/src/ts/tests/vimHelpers.test.ts index fadc1a93..e95cb4b0 100644 --- a/src/ts/tests/vimHelpers.test.ts +++ b/src/ts/tests/vimHelpers.test.ts @@ -11,7 +11,7 @@ describe('testing vimHelpers.ts getElementParameters', () => { const arrayBuffer = await loadFile(testVimFilePath) const bfast = new BFast((arrayBuffer as ArrayBuffer)!) - const doc = await VimDocument.createFromBfast(bfast) + const doc = await VimDocument.createFromBfast(bfast, false) const parameters = await VimHelpers.getElementParameters(doc!, 119) //fs.writeFileSync(testFilePath, JSON.stringify(parameters)); From 90c4bb607489f79f507f7758132ad9a9a6677a31 Mon Sep 17 00:00:00 2001 From: simon Date: Tue, 16 Jan 2024 11:24:42 -0500 Subject: [PATCH 045/111] check for file before delete --- src/cs/bfast/Vim.BFast.Tests/BFastTests.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/cs/bfast/Vim.BFast.Tests/BFastTests.cs b/src/cs/bfast/Vim.BFast.Tests/BFastTests.cs index fd579383..4c9e7ef4 100644 --- a/src/cs/bfast/Vim.BFast.Tests/BFastTests.cs +++ b/src/cs/bfast/Vim.BFast.Tests/BFastTests.cs @@ -15,8 +15,14 @@ public class BFastTests [SetUp] public void Setup() { - File.Delete(Path); - File.Delete(OutputPath); + if (File.Exists(Path)) + { + File.Delete(Path); + } + if (File.Exists(OutputPath)) + { + File.Delete(OutputPath); + } } [Test] From cf49ba0278ce55d26844c81f7a1b7efa362e5f1e Mon Sep 17 00:00:00 2001 From: simon Date: Tue, 16 Jan 2024 11:45:22 -0500 Subject: [PATCH 046/111] simplified paths using vimrepopaths --- src/cs/bfast/Vim.BFast.Tests/BFastTests.cs | 59 ++++++++++------------ 1 file changed, 28 insertions(+), 31 deletions(-) diff --git a/src/cs/bfast/Vim.BFast.Tests/BFastTests.cs b/src/cs/bfast/Vim.BFast.Tests/BFastTests.cs index 4c9e7ef4..64e2c2be 100644 --- a/src/cs/bfast/Vim.BFast.Tests/BFastTests.cs +++ b/src/cs/bfast/Vim.BFast.Tests/BFastTests.cs @@ -1,27 +1,24 @@ using NUnit.Framework; -using System; -using Vim.Util; using Vim.Util.Tests; namespace Vim.BFastNS.Tests { public class BFastTests { - public static string RootFolder = System.IO.Path.Combine(VimFormatRepoPaths.ProjDir, "..", ".."); - public static string Path = System.IO.Path.Combine(RootFolder, "out/input.bfast"); - public static string OutputPath = System.IO.Path.Combine(RootFolder, "out/output.bfast"); + public static string ResultPath = Path.Combine(VimFormatRepoPaths.OutDir, "input.bfast"); + public static string ResultPath2 =Path.Combine(VimFormatRepoPaths.OutDir, "input.bfast"); public static string ResidencePath = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); [SetUp] public void Setup() { - if (File.Exists(Path)) + if (File.Exists(ResultPath)) { - File.Delete(Path); + File.Delete(ResultPath); } - if (File.Exists(OutputPath)) + if (File.Exists(ResultPath2)) { - File.Delete(OutputPath); + File.Delete(ResultPath2); } } @@ -64,8 +61,8 @@ public void EmptyBFast_GetSize_Return_64() public void EmptyBFast_Writes_Header() { var bfast = new BFast(); - bfast.Write(Path); - using (var stream = File.OpenRead(Path)) + bfast.Write(ResultPath); + using (var stream = File.OpenRead(ResultPath)) { var bfast2 = new BFast(stream); Assert.That(bfast2.GetSize(), Is.EqualTo(64)); @@ -378,9 +375,9 @@ public void Removed_BFast_Not_Written() bfast.SetBFast("A", new BFast()); bfast.Remove("A"); - bfast.Write(Path); + bfast.Write(ResultPath); - using (var stream = File.OpenRead(Path)) + using (var stream = File.OpenRead(ResultPath)) { var other = new BFast(stream); Assert.IsNull(other.GetBFast("A")); @@ -394,9 +391,9 @@ public void Removed_Array_Not_Written() var bfast = new BFast(); bfast.SetArray("A", new int[3] { 0, 1, 2 }); bfast.Remove("A"); - bfast.Write(Path); + bfast.Write(ResultPath); - using (var stream = File.OpenRead(Path)) + using (var stream = File.OpenRead(ResultPath)) { var other = new BFast(stream); Assert.IsNull(other.GetArray("A")); @@ -413,10 +410,10 @@ public void Removed_InChild_Not_Written() var geometry = input.GetBFast("geometry"); geometry.Remove("g3d:vertex:position:0:float32:3"); input.SetBFast("geometry", geometry); - input.Write(Path); + input.Write(ResultPath); } - using (var stream = File.OpenRead(Path)) + using (var stream = File.OpenRead(ResultPath)) { var bfast = new BFast(stream); var geometry = bfast.GetBFast("geometry"); @@ -432,9 +429,9 @@ public void Write_Then_Read_Array() var bfast = new BFast(); bfast.SetArray("A", new int[3] { 0, 1, 2 }); - bfast.Write(Path); + bfast.Write(ResultPath); - using (var stream = File.OpenRead(Path)) + using (var stream = File.OpenRead(ResultPath)) { var other = new BFast(stream); var result = other.GetArray("A"); @@ -448,9 +445,9 @@ public void Write_Then_Read_Enumerable() var bfast = new BFast(); bfast.SetEnumerable("A", () => new int[3] { 0, 1, 2 }); - bfast.Write(Path); + bfast.Write(ResultPath); - using (var stream = File.OpenRead(Path)) + using (var stream = File.OpenRead(ResultPath)) { var other = new BFast(stream); var array = other.GetArray("A"); @@ -468,9 +465,9 @@ public void Write_Then_Read_SimpleBFast() bfast.SetBFast("child", child); child.SetArray("A", new int[3] { 0, 1, 2 }); - bfast.Write(Path); + bfast.Write(ResultPath); - using (var stream = File.OpenRead(Path)) + using (var stream = File.OpenRead(ResultPath)) { var other = new BFast(stream); var child2 = other.GetBFast("child"); @@ -491,9 +488,9 @@ public void Write_Then_Read_NestedBFast() bfast.SetBFast("child", child); child.SetBFast("grandChild", grandChild); - bfast.Write(Path); + bfast.Write(ResultPath); - using (var stream = File.OpenRead(Path)) + using (var stream = File.OpenRead(ResultPath)) { var other = new BFast(stream); var child2 = other.GetBFast("child"); @@ -517,8 +514,8 @@ public void Write_Then_Read_NestedBFast_WithArray() grandChild.SetArray("A", new int[3] { 0, 1, 2 }); - bfast.Write(Path); - using (var stream = File.OpenRead(Path)) + bfast.Write(ResultPath); + using (var stream = File.OpenRead(ResultPath)) { var other = new BFast(stream); var child2 = other.GetBFast("child"); @@ -538,9 +535,9 @@ public void Write_Then_Read_Mixed_Sources() var basic = new BFast(); basic.SetArray("ints", new int[1] { 1 }); basic.SetArray("floats", new float[1] { 2.0f }); - basic.Write(Path); + basic.Write(ResultPath); - using (var stream = File.OpenRead(Path)) + using (var stream = File.OpenRead(ResultPath)) { using (var residence = File.OpenRead(ResidencePath)) { @@ -550,11 +547,11 @@ public void Write_Then_Read_Mixed_Sources() output.SetBFast("input", input); output.SetBFast("residence", inputResidence); - output.Write(OutputPath); + output.Write(ResultPath2); } } - using (var stream = File.OpenRead(OutputPath)) + using (var stream = File.OpenRead(ResultPath2)) { var bfast = new BFast(stream); var input = bfast.GetBFast("input"); From d6e6dd220b33239cbff27f25632442402035362c Mon Sep 17 00:00:00 2001 From: simon Date: Tue, 16 Jan 2024 11:59:54 -0500 Subject: [PATCH 047/111] create path --- src/cs/bfast/Vim.BFast.Tests/BFastTests.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/cs/bfast/Vim.BFast.Tests/BFastTests.cs b/src/cs/bfast/Vim.BFast.Tests/BFastTests.cs index 64e2c2be..a1ec1a7f 100644 --- a/src/cs/bfast/Vim.BFast.Tests/BFastTests.cs +++ b/src/cs/bfast/Vim.BFast.Tests/BFastTests.cs @@ -6,12 +6,16 @@ namespace Vim.BFastNS.Tests public class BFastTests { public static string ResultPath = Path.Combine(VimFormatRepoPaths.OutDir, "input.bfast"); - public static string ResultPath2 =Path.Combine(VimFormatRepoPaths.OutDir, "input.bfast"); + public static string ResultPath2 = Path.Combine(VimFormatRepoPaths.OutDir, "input.bfast"); public static string ResidencePath = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); [SetUp] public void Setup() { + if (!Directory.Exists(VimFormatRepoPaths.OutDir)) + { + Directory.CreateDirectory(VimFormatRepoPaths.OutDir); + } if (File.Exists(ResultPath)) { File.Delete(ResultPath); From 0e568fb8e23c316271074d64e3917871b3d7f0ce Mon Sep 17 00:00:00 2001 From: simon Date: Tue, 16 Jan 2024 13:24:52 -0500 Subject: [PATCH 048/111] updated g3d tests --- src/cs/g3d/Vim.G3d.Tests/G3dTests.cs | 98 +++++++--------------------- 1 file changed, 24 insertions(+), 74 deletions(-) diff --git a/src/cs/g3d/Vim.G3d.Tests/G3dTests.cs b/src/cs/g3d/Vim.G3d.Tests/G3dTests.cs index 4704ae32..885a2ec2 100644 --- a/src/cs/g3d/Vim.G3d.Tests/G3dTests.cs +++ b/src/cs/g3d/Vim.G3d.Tests/G3dTests.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using Vim.BFastNS; using Vim.G3d.AssimpWrapper; using Vim.LinqArray; using Vim.Math3d; @@ -37,6 +38,23 @@ public FileLoadData(string filePath) public static string RootFolder = Path.Combine(ProjectFolder, "..", "..", "..", ".."); public static string TestInputFolder = Path.Combine(RootFolder, "data", "g3d-test-data", "models"); public static string TestOutputFolder = Path.Combine(RootFolder, "data", "g3d-test-data", "output"); + + [SetUp] + public static void Setup() + { + if (!Directory.Exists(RootFolder)) + { + Directory.CreateDirectory(RootFolder); + } + if (!Directory.Exists(TestInputFolder)) + { + Directory.CreateDirectory(TestInputFolder); + } + if (!Directory.Exists(TestOutputFolder)) + { + Directory.CreateDirectory(TestOutputFolder); + } + } public static IEnumerable GetInputFiles() => Directory.GetFiles(TestInputFolder, "*.*", SearchOption.AllDirectories); @@ -233,84 +251,16 @@ public static void TriangleTest() } [Test] - public static void QuadAndCopyTest() + public static void UnexpectedAttributes_Are_Ignored() { - // Serialize a triangle g3d as bytes and read it back. - var vertices = new[] - { - new Vector3(0, 0, 0), - new Vector3(0, 1, 0), - new Vector3(0, 1, 1), - new Vector3(1, 1, 1) - }; - - var indices = new[] { 0, 1, 2, 3 }; - var materialIndices = new[] { 5 }; - - var g3d = new G3DBuilder() - .AddVertices(vertices.ToIArray()) - .AddIndices(indices.ToIArray()) - .Add(materialIndices.ToIArray().ToFaceMaterialAttribute()) - .ToG3D(); + var unexpected = Path.Combine(TestInputFolder, "unexpected.g3d"); - var bfast = g3d.ToBFast(); - var g = G3D.Read(bfast); - - Assert.IsNotNull(g); - - Assert.AreEqual(4, g.NumCornersPerFace); - Assert.AreEqual(4, g.NumVertices); - Assert.AreEqual(4, g.NumCorners); - Assert.AreEqual(1, g.NumFaces); - Assert.AreEqual(0, g.NumMeshes); - Assert.AreEqual(0, g.NumInstances); - - Assert.AreEqual(vertices, g.Vertices.ToArray()); - Assert.AreEqual(indices, g.Indices.ToArray()); - Assert.AreEqual(materialIndices, g.FaceMaterials.ToArray()); - - var g2 = g.TriangulateQuadMesh(); - - Assert.AreEqual(3, g2.NumCornersPerFace); - Assert.AreEqual(4, g2.NumVertices); - Assert.AreEqual(6, g2.NumCorners); - Assert.AreEqual(2, g2.NumFaces); - Assert.AreEqual(0, g2.NumMeshes); - Assert.AreEqual(0, g2.NumInstances); - - Assert.AreEqual(vertices, g2.GetAttributeDataPosition().ToArray()); - Assert.AreEqual(new[] { 0, 1, 2, 0, 2, 3 }, g2.GetAttributeDataIndex().ToArray()); - Assert.AreEqual(new[] { 5, 5 }, g2.GetAttributeDataFaceMaterial().ToArray()); - - g2 = g2.CopyFaces(1, 1); - - Assert.AreEqual(3, g2.NumCornersPerFace); - Assert.AreEqual(4, g2.NumVertices); - Assert.AreEqual(3, g2.NumCorners); - Assert.AreEqual(1, g2.NumFaces); - - Assert.AreEqual(vertices, g2.GetAttributeDataPosition().ToArray()); - Assert.AreEqual(new[] { 0, 2, 3 }, g2.GetAttributeDataIndex().ToArray()); - Assert.AreEqual(new[] { 5 }, g2.GetAttributeDataFaceMaterial().ToArray()); - } - - [Test] - public static void UnexpectedAttributeTest() - { - // This test validates that unrecognized g3d attributes are simply ignored in the deserialization process. - // - // "unexpected.g3d" was generated using the following code snippet. Note that the code was temporarily modified such - // that UNKNOWN mapped to a ulong data type value (8 bits): - // - // var g3d = new G3DBuilder() - // .Add(new GeometryAttribute(new int[] { 5 }.ToIArray(), AttributeDescriptor.Parse("g3d:instance:potato:0:int32:1"))) - // .Add(new GeometryAttribute(new ulong[] { 42 }.ToIArray(), AttributeDescriptor.Parse("g3d:instance:beep:0:UNKNOWN:1"))) - // .ToG3D(); - - var g = G3D.Read(Path.Combine(TestInputFolder, "unexpected.g3d")); + var bfast = new BFast(); + bfast.SetArray("g3d:instance:potato:0:int32:1", new int[] { 5 }); + bfast.Write(unexpected); + var g = G3D.Read(unexpected); var parsedInstanceAttrs = g.Attributes.Where(ga => ga.Descriptor.Association == Association.assoc_instance).ToArray(); - Assert.AreEqual(1, parsedInstanceAttrs.Length); // NOTE: we only expect one attribute (the one with the "potato" semantic) because UNKNOWN is currently ignored as a datatype. var parsedPotatoAttr = parsedInstanceAttrs.Single(ga => ga.Descriptor.Semantic == "potato"); Assert.AreEqual(new [] { 5 }, parsedPotatoAttr.AsType().Data.ToArray()); } From 1f21f39288f5d874ce989450577fcbc8cbb82e99 Mon Sep 17 00:00:00 2001 From: simon Date: Tue, 16 Jan 2024 13:47:42 -0500 Subject: [PATCH 049/111] removed old tests --- src/cs/g3d/Vim.G3d.Tests/G3dTestUtils.cs | 68 ------------------------ src/cs/g3d/Vim.G3d.Tests/G3dTests.cs | 12 +---- 2 files changed, 1 insertion(+), 79 deletions(-) diff --git a/src/cs/g3d/Vim.G3d.Tests/G3dTestUtils.cs b/src/cs/g3d/Vim.G3d.Tests/G3dTestUtils.cs index 00c435f2..0ebb530f 100644 --- a/src/cs/g3d/Vim.G3d.Tests/G3dTestUtils.cs +++ b/src/cs/g3d/Vim.G3d.Tests/G3dTestUtils.cs @@ -65,73 +65,5 @@ public static void OutputStats(G3D g) foreach (var attr in g.Attributes.ToEnumerable()) Console.WriteLine($"{attr.Name} #items={attr.ElementCount}"); } - - public static void AssertSame(G3D g1, G3D g2) - { - Assert.AreEqual(g1.NumCornersPerFace, g2.NumCornersPerFace); - Assert.AreEqual(g1.NumFaces, g2.NumFaces); - Assert.AreEqual(g1.NumCorners, g2.NumCorners); - Assert.AreEqual(g1.NumVertices, g2.NumVertices); - Assert.AreEqual(g1.NumInstances, g2.NumInstances); - Assert.AreEqual(g1.NumMeshes, g2.NumMeshes); - Assert.AreEqual(g1.Attributes.Count, g2.Attributes.Count); - for (var i = 0; i < g1.Attributes.Count; ++i) - { - var attr1 = g1.Attributes[i]; - var attr2 = g2.Attributes[i]; - Assert.AreEqual(attr1.Name, attr2.Name); - Assert.AreEqual(attr1.GetByteSize(), attr2.GetByteSize()); - Assert.AreEqual(attr1.ElementCount, attr2.ElementCount); - } - } - - public static void AssertSame(Mesh m, G3D g) - { - Assert.AreEqual(m.FaceCount, g.NumFaces); - Assert.AreEqual(m.GetIndices(), g.Indices.ToArray()); - Assert.AreEqual(m.VertexCount, g.NumVertices); - } - - public static G3D CompareTiming(string fileName, string outputFolder) - { - using (var context = new AssimpContext()) - { - var scene = TimeLoadingFile(fileName, context.ImportFile); - var m = scene.Meshes[0]; - var g3d = m.ToG3D(); - AssertSame(m, g3d); - var outputFile = Path.Combine(outputFolder, Path.GetFileName(fileName) + ".g3d"); - g3d.ToBFast().Write(outputFile); - var r = TimeLoadingFile(outputFile, G3D.Read); - //OutputG3DStats(g3d); - AssertSame(g3d, r); - return r; - } - } - - public static string[] TestFiles = - { - @"models-nonbsd\3DS\jeep1.3ds", - @"models-nonbsd\3DS\mar_rifle.3ds", - @"models-nonbsd\dxf\rifle.dxf", - @"models-nonbsd\FBX\2013_ASCII\duck.fbx", - @"models-nonbsd\FBX\2013_ASCII\jeep1.fbx", - // Binary fails assimp import - //@"models-nonbsd\FBX\2013_BINARY\duck.fbx", - //@"models-nonbsd\FBX\2013_BINARY\jeep1.fbx", - // OBJ files were not checked in to the repo. - //@"models-nonbsd\OBJ\rifle.obj", - //@"models-nonbsd\OBJ\segment.obj", - @"models-nonbsd\PLY\ant-half.ply", - @"models\IFC\AC14-FZK-Haus.ifc", - @"models\PLY\Wuson.ply", - @"models\STL\Wuson.stl", - @"models\STL\Spider_ascii.stl", - @"models\STL\Spider_binary.stl", - @"models\glTF\CesiumMilkTruck\CesiumMilkTruck.gltf", - @"models\glTF2\2CylinderEngine-glTF-Binary\2CylinderEngine.glb", - @"models\DXF\wuson.dxf", - @"models\Collada\duck.dae", - }; } } diff --git a/src/cs/g3d/Vim.G3d.Tests/G3dTests.cs b/src/cs/g3d/Vim.G3d.Tests/G3dTests.cs index 885a2ec2..60d23fd5 100644 --- a/src/cs/g3d/Vim.G3d.Tests/G3dTests.cs +++ b/src/cs/g3d/Vim.G3d.Tests/G3dTests.cs @@ -84,16 +84,6 @@ public static void ValidateSameG3D(G3D g1, G3D g2) } } - [Test, Explicit("Use during debugging")] - public static void ReadG3DFiles() - { - foreach (var f in Directory.GetFiles(TestOutputFolder)) - { - var g3d = G3D.Read(f); - G3dTestUtils.OutputStats(g3d); - } - } - [Test] [Platform(Exclude = "Linux,Unix", Reason = "AssimpNet is failing to load its dependency on 'libdl.so'.")] public static void OpenAndConvertAssimpFiles() @@ -290,7 +280,7 @@ public static void BigFileTest() ValidateSameG3D(g3d, tmp); } - [Test] + [Test, Explicit] [Platform(Exclude = "Linux,Unix", Reason = "AssimpNet is failing to load its dependency on 'libdl.so'.")] public static void TestWriters() { From ea1b8e147171dd3d51666b00ecd638df85db3f8f Mon Sep 17 00:00:00 2001 From: simon Date: Thu, 18 Jan 2024 16:40:45 -0500 Subject: [PATCH 050/111] g3d.next refactor --- src/cs/bfast/Vim.BFast/BFast/BFast.cs | 18 +- .../Vim.G3dNext.Attributes/Attributes.g.cs | 3581 ++--------------- .../Vim.G3dNext.Attributes/G3dMaterials.cs | 4 +- .../MaterialsAttributes.cs | 23 - .../Vim.G3dNext.Attributes/MeshAttributes.cs | 47 - .../Vim.G3dNext.Attributes/SceneAttributes.cs | 71 - .../Vim.G3dNext.Attributes/VimAttributes.cs | 75 - src/cs/g3d/Vim.G3dNext.CodeGen/CodeBuilder.cs | 11 +- src/cs/g3d/Vim.G3dNext.CodeGen/Definitions.cs | 62 + .../G3dAttributeCollectionGenerator.cs | 334 +- src/cs/g3d/Vim.G3dNext.CodeGen/G3dBuffer.cs | 42 + src/cs/g3d/Vim.G3dNext.CodeGen/G3dEntity.cs | 31 + .../Vim.G3dNext.CodeGen.csproj | 9 +- src/cs/g3d/Vim.G3dNext/AttributeDescriptor.cs | 182 - .../Vim.G3dNext/AttributeDescriptorErrors.cs | 17 - src/cs/g3d/Vim.G3dNext/AttributeType.cs | 9 - src/cs/g3d/Vim.G3dNext/CodeGenAttributes.cs | 51 - src/cs/g3d/Vim.G3dNext/Constants.cs | 31 + src/cs/g3d/Vim.G3dNext/DataType.cs | 87 - src/cs/g3d/Vim.G3dNext/Entities.g.cs | 471 +++ src/cs/g3d/Vim.G3dNext/G3dChunk.cs | 169 + src/cs/g3d/Vim.G3dNext/G3dMaterials.cs | 20 + src/cs/g3d/Vim.G3dNext/G3dScene.cs | 12 + src/cs/g3d/Vim.G3dNext/G3dVim.cs | 186 + src/cs/g3d/Vim.G3dNext/IAttribute.cs | 74 - .../g3d/Vim.G3dNext/IAttributeCollection.cs | 129 - .../g3d/Vim.G3dNext/IAttributeDescriptor.cs | 88 - .../Vim.Format.Vimx.Conversion/Chunking.cs | 38 +- .../VimxConverter.cs | 38 +- src/cs/vim/Vim.Vimx.Test/TestUtils.cs | 41 +- src/cs/vim/Vim.Vimx.Test/VimG3dTests.cs | 167 +- src/cs/vim/Vim.Vimx.Test/VimxActions.cs | 4 +- 32 files changed, 1594 insertions(+), 4528 deletions(-) delete mode 100644 src/cs/g3d/Vim.G3dNext.Attributes/MaterialsAttributes.cs delete mode 100644 src/cs/g3d/Vim.G3dNext.Attributes/MeshAttributes.cs delete mode 100644 src/cs/g3d/Vim.G3dNext.Attributes/SceneAttributes.cs delete mode 100644 src/cs/g3d/Vim.G3dNext.Attributes/VimAttributes.cs create mode 100644 src/cs/g3d/Vim.G3dNext.CodeGen/Definitions.cs create mode 100644 src/cs/g3d/Vim.G3dNext.CodeGen/G3dBuffer.cs create mode 100644 src/cs/g3d/Vim.G3dNext.CodeGen/G3dEntity.cs delete mode 100644 src/cs/g3d/Vim.G3dNext/AttributeDescriptor.cs delete mode 100644 src/cs/g3d/Vim.G3dNext/AttributeDescriptorErrors.cs delete mode 100644 src/cs/g3d/Vim.G3dNext/AttributeType.cs delete mode 100644 src/cs/g3d/Vim.G3dNext/CodeGenAttributes.cs delete mode 100644 src/cs/g3d/Vim.G3dNext/DataType.cs create mode 100644 src/cs/g3d/Vim.G3dNext/Entities.g.cs create mode 100644 src/cs/g3d/Vim.G3dNext/G3dChunk.cs create mode 100644 src/cs/g3d/Vim.G3dNext/G3dMaterials.cs create mode 100644 src/cs/g3d/Vim.G3dNext/G3dScene.cs create mode 100644 src/cs/g3d/Vim.G3dNext/G3dVim.cs delete mode 100644 src/cs/g3d/Vim.G3dNext/IAttribute.cs delete mode 100644 src/cs/g3d/Vim.G3dNext/IAttributeCollection.cs delete mode 100644 src/cs/g3d/Vim.G3dNext/IAttributeDescriptor.cs diff --git a/src/cs/bfast/Vim.BFast/BFast/BFast.cs b/src/cs/bfast/Vim.BFast/BFast/BFast.cs index 8288a951..3a38c4b5 100644 --- a/src/cs/bfast/Vim.BFast/BFast/BFast.cs +++ b/src/cs/bfast/Vim.BFast/BFast/BFast.cs @@ -55,10 +55,24 @@ private byte[] Deflate(BFast bfast) } public void SetEnumerable(string name, Func> enumerable) where T : unmanaged - => _children[name] = new BFastEnumerableNode(enumerable); + { + if (enumerable == null) + { + _children.Remove(name); + return; + } + _children[name] = new BFastEnumerableNode(enumerable); + } public void SetArray(string name, T[] array) where T : unmanaged - => _children[name] = BFastNode.FromArray(array); + { + if (array == null) + { + _children.Remove(name); + return; + } + _children[name] = BFastNode.FromArray(array); + } public void SetArrays(Func getName, IEnumerable arrays) where T : unmanaged { diff --git a/src/cs/g3d/Vim.G3dNext.Attributes/Attributes.g.cs b/src/cs/g3d/Vim.G3dNext.Attributes/Attributes.g.cs index 552b0153..7062796c 100644 --- a/src/cs/g3d/Vim.G3dNext.Attributes/Attributes.g.cs +++ b/src/cs/g3d/Vim.G3dNext.Attributes/Attributes.g.cs @@ -1,3289 +1,476 @@ -// AUTO-GENERATED FILE, DO NOT MODIFY WACKO3. +// AUTO-GENERATED FILE, DO NOT MODIFY. // ReSharper disable All -using System; -using System.IO; -using System.Collections.Generic; -using System.Linq; using Vim.BFastNS; +using Vim.G3dNext; namespace Vim.G3dNext.Attributes { - - public partial class VimPositionsAttribute : IAttribute - { - public const string AttributeName = "g3d:vertex:position:0:float32:3"; - - public string Name - => AttributeName; - - public int Count => TypedData?.Length ?? 0; - - public void AddTo(BFast bfast) - { - if(TypedData != null) - { - bfast.SetArray(Name, TypedData); - } - } - - public void ReadBFast(BFast bfast) - { - TypedData = bfast.GetArray("g3d:vertex:position:0:float32:3"); - } - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Data; - - public Type IndexInto { get; } - = null; - - public Vim.Math3d.Vector3[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - - public partial class VimIndicesAttribute : IAttribute - { - public const string AttributeName = "g3d:corner:index:0:int32:1"; - - public string Name - => AttributeName; - - public int Count => TypedData?.Length ?? 0; - - public void AddTo(BFast bfast) - { - if(TypedData != null) - { - bfast.SetArray(Name, TypedData); - } - } - - public void ReadBFast(BFast bfast) - { - TypedData = bfast.GetArray("g3d:corner:index:0:int32:1"); - } - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Index; - - public Type IndexInto { get; } - = typeof(Vim.G3dNext.Attributes.VimPositionsAttribute); - - public System.Int32[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - - public partial class VimInstanceTransformsAttribute : IAttribute - { - public const string AttributeName = "g3d:instance:transform:0:float32:16"; - - public string Name - => AttributeName; - - public int Count => TypedData?.Length ?? 0; - - public void AddTo(BFast bfast) - { - if(TypedData != null) - { - bfast.SetArray(Name, TypedData); - } - } - - public void ReadBFast(BFast bfast) - { - TypedData = bfast.GetArray("g3d:instance:transform:0:float32:16"); - } - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Data; - - public Type IndexInto { get; } - = null; - - public Vim.Math3d.Matrix4x4[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - - public partial class VimInstanceParentsAttribute : IAttribute - { - public const string AttributeName = "g3d:instance:parent:0:int32:1"; - - public string Name - => AttributeName; - - public int Count => TypedData?.Length ?? 0; - - public void AddTo(BFast bfast) - { - if(TypedData != null) - { - bfast.SetArray(Name, TypedData); - } - } - - public void ReadBFast(BFast bfast) - { - TypedData = bfast.GetArray("g3d:instance:parent:0:int32:1"); - } - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Index; - - public Type IndexInto { get; } - = typeof(Vim.G3dNext.Attributes.VimInstanceTransformsAttribute); - - public System.Int32[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - - public partial class VimInstanceFlagsAttribute : IAttribute - { - public const string AttributeName = "g3d:instance:flags:0:uint16:1"; - - public string Name - => AttributeName; - - public int Count => TypedData?.Length ?? 0; - - public void AddTo(BFast bfast) - { - if(TypedData != null) - { - bfast.SetArray(Name, TypedData); - } - } - - public void ReadBFast(BFast bfast) - { - TypedData = bfast.GetArray("g3d:instance:flags:0:uint16:1"); - } - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Data; - - public Type IndexInto { get; } - = null; - - public System.UInt16[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - - public partial class VimInstanceMeshesAttribute : IAttribute - { - public const string AttributeName = "g3d:instance:mesh:0:int32:1"; - - public string Name - => AttributeName; - - public int Count => TypedData?.Length ?? 0; - - public void AddTo(BFast bfast) - { - if(TypedData != null) - { - bfast.SetArray(Name, TypedData); - } - } - - public void ReadBFast(BFast bfast) - { - TypedData = bfast.GetArray("g3d:instance:mesh:0:int32:1"); - } - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Index; - - public Type IndexInto { get; } - = typeof(Vim.G3dNext.Attributes.VimMeshSubmeshOffsetsAttribute); - - public System.Int32[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - - public partial class VimMeshSubmeshOffsetsAttribute : IAttribute - { - public const string AttributeName = "g3d:mesh:submeshoffset:0:int32:1"; - - public string Name - => AttributeName; - - public int Count => TypedData?.Length ?? 0; - - public void AddTo(BFast bfast) - { - if(TypedData != null) - { - bfast.SetArray(Name, TypedData); - } - } - - public void ReadBFast(BFast bfast) - { - TypedData = bfast.GetArray("g3d:mesh:submeshoffset:0:int32:1"); - } - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Index; - - public Type IndexInto { get; } - = typeof(Vim.G3dNext.Attributes.VimSubmeshIndexOffsetsAttribute); - - public System.Int32[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - - public partial class VimSubmeshIndexOffsetsAttribute : IAttribute - { - public const string AttributeName = "g3d:submesh:indexoffset:0:int32:1"; - - public string Name - => AttributeName; - - public int Count => TypedData?.Length ?? 0; - - public void AddTo(BFast bfast) - { - if(TypedData != null) - { - bfast.SetArray(Name, TypedData); - } - } - - public void ReadBFast(BFast bfast) - { - TypedData = bfast.GetArray("g3d:submesh:indexoffset:0:int32:1"); - } - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Index; - - public Type IndexInto { get; } - = typeof(Vim.G3dNext.Attributes.VimIndicesAttribute); - - public System.Int32[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - - public partial class VimSubmeshMaterialsAttribute : IAttribute - { - public const string AttributeName = "g3d:submesh:material:0:int32:1"; - - public string Name - => AttributeName; - - public int Count => TypedData?.Length ?? 0; - - public void AddTo(BFast bfast) - { - if(TypedData != null) - { - bfast.SetArray(Name, TypedData); - } - } - - public void ReadBFast(BFast bfast) - { - TypedData = bfast.GetArray("g3d:submesh:material:0:int32:1"); - } - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Index; - - public Type IndexInto { get; } - = typeof(Vim.G3dNext.Attributes.VimMaterialColorsAttribute); - - public System.Int32[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - - public partial class VimMaterialColorsAttribute : IAttribute - { - public const string AttributeName = "g3d:material:color:0:float32:4"; - - public string Name - => AttributeName; - - public int Count => TypedData?.Length ?? 0; - - public void AddTo(BFast bfast) - { - if(TypedData != null) - { - bfast.SetArray(Name, TypedData); - } - } - - public void ReadBFast(BFast bfast) - { - TypedData = bfast.GetArray("g3d:material:color:0:float32:4"); - } - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Data; - - public Type IndexInto { get; } - = null; - - public Vim.Math3d.Vector4[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - - public partial class VimMaterialGlossinessAttribute : IAttribute - { - public const string AttributeName = "g3d:material:glossiness:0:float32:1"; - - public string Name - => AttributeName; - - public int Count => TypedData?.Length ?? 0; - - public void AddTo(BFast bfast) - { - if(TypedData != null) - { - bfast.SetArray(Name, TypedData); - } - } - - public void ReadBFast(BFast bfast) - { - TypedData = bfast.GetArray("g3d:material:glossiness:0:float32:1"); - } - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Data; - - public Type IndexInto { get; } - = null; - - public System.Single[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - - public partial class VimMaterialSmoothnessAttribute : IAttribute - { - public const string AttributeName = "g3d:material:smoothness:0:float32:1"; - - public string Name - => AttributeName; - - public int Count => TypedData?.Length ?? 0; - - public void AddTo(BFast bfast) - { - if(TypedData != null) - { - bfast.SetArray(Name, TypedData); - } - } - - public void ReadBFast(BFast bfast) - { - TypedData = bfast.GetArray("g3d:material:smoothness:0:float32:1"); - } - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Data; - - public Type IndexInto { get; } - = null; - - public System.Single[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - - public partial class VimShapeVerticesAttribute : IAttribute - { - public const string AttributeName = "g3d:shapevertex:position:0:float32:3"; - - public string Name - => AttributeName; - - public int Count => TypedData?.Length ?? 0; - - public void AddTo(BFast bfast) - { - if(TypedData != null) - { - bfast.SetArray(Name, TypedData); - } - } - - public void ReadBFast(BFast bfast) - { - TypedData = bfast.GetArray("g3d:shapevertex:position:0:float32:3"); - } - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Data; - - public Type IndexInto { get; } - = null; - - public Vim.Math3d.Vector3[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - - public partial class VimShapeVertexOffsetsAttribute : IAttribute - { - public const string AttributeName = "g3d:shape:vertexoffset:0:int32:1"; - - public string Name - => AttributeName; - - public int Count => TypedData?.Length ?? 0; - - public void AddTo(BFast bfast) - { - if(TypedData != null) - { - bfast.SetArray(Name, TypedData); - } - } - - public void ReadBFast(BFast bfast) - { - TypedData = bfast.GetArray("g3d:shape:vertexoffset:0:int32:1"); - } - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Index; - - public Type IndexInto { get; } - = typeof(Vim.G3dNext.Attributes.VimShapeVerticesAttribute); - - public System.Int32[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - - public partial class VimShapeColorsAttribute : IAttribute - { - public const string AttributeName = "g3d:shape:color:0:float32:4"; - - public string Name - => AttributeName; - - public int Count => TypedData?.Length ?? 0; - - public void AddTo(BFast bfast) - { - if(TypedData != null) - { - bfast.SetArray(Name, TypedData); - } - } - - public void ReadBFast(BFast bfast) - { - TypedData = bfast.GetArray("g3d:shape:color:0:float32:4"); - } - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Data; - - public Type IndexInto { get; } - = null; - - public Vim.Math3d.Vector4[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - - public partial class VimShapeWidthsAttribute : IAttribute - { - public const string AttributeName = "g3d:shape:width:0:float32:1"; - - public string Name - => AttributeName; - - public int Count => TypedData?.Length ?? 0; - - public void AddTo(BFast bfast) - { - if(TypedData != null) - { - bfast.SetArray(Name, TypedData); - } - } - - public void ReadBFast(BFast bfast) - { - TypedData = bfast.GetArray("g3d:shape:width:0:float32:1"); - } - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Data; - - public Type IndexInto { get; } - = null; - - public System.Single[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - - public partial class MaterialColorsAttribute : IAttribute - { - public const string AttributeName = "g3d:material:color:0:float32:4"; - - public string Name - => AttributeName; - - public int Count => TypedData?.Length ?? 0; - - public void AddTo(BFast bfast) - { - if(TypedData != null) - { - bfast.SetArray(Name, TypedData); - } - } - - public void ReadBFast(BFast bfast) - { - TypedData = bfast.GetArray("g3d:material:color:0:float32:4"); - } - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Data; - - public Type IndexInto { get; } - = null; - - public Vim.Math3d.Vector4[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - - public partial class MaterialGlossinessAttribute : IAttribute - { - public const string AttributeName = "g3d:material:glossiness:0:float32:1"; - - public string Name - => AttributeName; - - public int Count => TypedData?.Length ?? 0; - - public void AddTo(BFast bfast) - { - if(TypedData != null) - { - bfast.SetArray(Name, TypedData); - } - } - - public void ReadBFast(BFast bfast) - { - TypedData = bfast.GetArray("g3d:material:glossiness:0:float32:1"); - } - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Data; - - public Type IndexInto { get; } - = null; - - public System.Single[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - - public partial class MaterialSmoothnessAttribute : IAttribute - { - public const string AttributeName = "g3d:material:smoothness:0:float32:1"; - - public string Name - => AttributeName; - - public int Count => TypedData?.Length ?? 0; - - public void AddTo(BFast bfast) - { - if(TypedData != null) - { - bfast.SetArray(Name, TypedData); - } - } - - public void ReadBFast(BFast bfast) - { - TypedData = bfast.GetArray("g3d:material:smoothness:0:float32:1"); - } - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Data; - - public Type IndexInto { get; } - = null; - - public System.Single[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - - public partial class SceneChunkCountAttribute : IAttribute - { - public const string AttributeName = "g3d:chunk:count:0:int32:1"; - - public string Name - => AttributeName; - - public int Count => TypedData?.Length ?? 0; - - public void AddTo(BFast bfast) - { - if(TypedData != null) - { - bfast.SetArray(Name, TypedData); - } - } - - public void ReadBFast(BFast bfast) - { - TypedData = bfast.GetArray("g3d:chunk:count:0:int32:1"); - } - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Data; - - public Type IndexInto { get; } - = null; - - public System.Int32[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - - public partial class SceneInstanceMeshesAttribute : IAttribute - { - public const string AttributeName = "g3d:instance:mesh:0:int32:1"; - - public string Name - => AttributeName; - - public int Count => TypedData?.Length ?? 0; - - public void AddTo(BFast bfast) - { - if(TypedData != null) - { - bfast.SetArray(Name, TypedData); - } - } - - public void ReadBFast(BFast bfast) - { - TypedData = bfast.GetArray("g3d:instance:mesh:0:int32:1"); - } - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Data; - - public Type IndexInto { get; } - = null; - - public System.Int32[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - - public partial class SceneInstanceTransformDataAttribute : IAttribute - { - public const string AttributeName = "g3d:instance:transform:0:float32:16"; - - public string Name - => AttributeName; - - public int Count => TypedData?.Length ?? 0; - - public void AddTo(BFast bfast) - { - if(TypedData != null) - { - bfast.SetArray(Name, TypedData); - } - } - - public void ReadBFast(BFast bfast) - { - TypedData = bfast.GetArray("g3d:instance:transform:0:float32:16"); - } - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Data; - - public Type IndexInto { get; } - = null; - - public Vim.Math3d.Matrix4x4[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - - public partial class SceneInstanceNodesAttribute : IAttribute - { - public const string AttributeName = "g3d:instance:node:0:int32:1"; - - public string Name - => AttributeName; - - public int Count => TypedData?.Length ?? 0; - - public void AddTo(BFast bfast) - { - if(TypedData != null) - { - bfast.SetArray(Name, TypedData); - } - } - - public void ReadBFast(BFast bfast) - { - TypedData = bfast.GetArray("g3d:instance:node:0:int32:1"); - } - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Data; - - public Type IndexInto { get; } - = null; - - public System.Int32[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - - public partial class SceneInstanceGroupsAttribute : IAttribute - { - public const string AttributeName = "g3d:instance:group:0:int32:1"; - - public string Name - => AttributeName; - - public int Count => TypedData?.Length ?? 0; - - public void AddTo(BFast bfast) - { - if(TypedData != null) - { - bfast.SetArray(Name, TypedData); - } - } - - public void ReadBFast(BFast bfast) - { - TypedData = bfast.GetArray("g3d:instance:group:0:int32:1"); - } - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Data; - - public Type IndexInto { get; } - = null; - - public System.Int32[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - - public partial class SceneInstanceTagsAttribute : IAttribute - { - public const string AttributeName = "g3d:instance:tag:0:int64:1"; - - public string Name - => AttributeName; - - public int Count => TypedData?.Length ?? 0; - - public void AddTo(BFast bfast) - { - if(TypedData != null) - { - bfast.SetArray(Name, TypedData); - } - } - - public void ReadBFast(BFast bfast) - { - TypedData = bfast.GetArray("g3d:instance:tag:0:int64:1"); - } - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Data; - - public Type IndexInto { get; } - = null; - - public System.Int64[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - - public partial class SceneInstanceFlagsAttribute : IAttribute - { - public const string AttributeName = "g3d:instance:flags:0:uint16:1"; - - public string Name - => AttributeName; - - public int Count => TypedData?.Length ?? 0; - - public void AddTo(BFast bfast) - { - if(TypedData != null) - { - bfast.SetArray(Name, TypedData); - } - } - - public void ReadBFast(BFast bfast) - { - TypedData = bfast.GetArray("g3d:instance:flags:0:uint16:1"); - } - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Data; - - public Type IndexInto { get; } - = null; - - public System.UInt16[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - - public partial class SceneInstanceMinsAttribute : IAttribute - { - public const string AttributeName = "g3d:instance:min:0:float32:3"; - - public string Name - => AttributeName; - - public int Count => TypedData?.Length ?? 0; - - public void AddTo(BFast bfast) - { - if(TypedData != null) - { - bfast.SetArray(Name, TypedData); - } - } - - public void ReadBFast(BFast bfast) - { - TypedData = bfast.GetArray("g3d:instance:min:0:float32:3"); - } - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Data; - - public Type IndexInto { get; } - = null; - - public Vim.Math3d.Vector3[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - - public partial class SceneInstanceMaxsAttribute : IAttribute - { - public const string AttributeName = "g3d:instance:max:0:float32:3"; - - public string Name - => AttributeName; - - public int Count => TypedData?.Length ?? 0; - - public void AddTo(BFast bfast) - { - if(TypedData != null) - { - bfast.SetArray(Name, TypedData); - } - } - - public void ReadBFast(BFast bfast) - { - TypedData = bfast.GetArray("g3d:instance:max:0:float32:3"); - } - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Data; - - public Type IndexInto { get; } - = null; - - public Vim.Math3d.Vector3[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - - public partial class SceneMeshChunksAttribute : IAttribute - { - public const string AttributeName = "g3d:mesh:chunk:0:int32:1"; - - public string Name - => AttributeName; - - public int Count => TypedData?.Length ?? 0; - - public void AddTo(BFast bfast) - { - if(TypedData != null) - { - bfast.SetArray(Name, TypedData); - } - } - - public void ReadBFast(BFast bfast) - { - TypedData = bfast.GetArray("g3d:mesh:chunk:0:int32:1"); - } - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Data; - - public Type IndexInto { get; } - = null; - - public System.Int32[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - - public partial class SceneMeshChunkIndicesAttribute : IAttribute - { - public const string AttributeName = "g3d:mesh:chunkindex:0:int32:1"; - - public string Name - => AttributeName; - - public int Count => TypedData?.Length ?? 0; - - public void AddTo(BFast bfast) - { - if(TypedData != null) - { - bfast.SetArray(Name, TypedData); - } - } - - public void ReadBFast(BFast bfast) - { - TypedData = bfast.GetArray("g3d:mesh:chunkindex:0:int32:1"); - } - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Data; - - public Type IndexInto { get; } - = null; - - public System.Int32[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - - public partial class SceneMeshVertexCountsAttribute : IAttribute - { - public const string AttributeName = "g3d:mesh:vertexcount:0:int32:1"; - - public string Name - => AttributeName; - - public int Count => TypedData?.Length ?? 0; - - public void AddTo(BFast bfast) - { - if(TypedData != null) - { - bfast.SetArray(Name, TypedData); - } - } - - public void ReadBFast(BFast bfast) - { - TypedData = bfast.GetArray("g3d:mesh:vertexcount:0:int32:1"); - } - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Data; - - public Type IndexInto { get; } - = null; - - public System.Int32[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - - public partial class SceneMeshIndexCountsAttribute : IAttribute - { - public const string AttributeName = "g3d:mesh:indexcount:0:int32:1"; - - public string Name - => AttributeName; - - public int Count => TypedData?.Length ?? 0; - - public void AddTo(BFast bfast) - { - if(TypedData != null) - { - bfast.SetArray(Name, TypedData); - } - } - - public void ReadBFast(BFast bfast) - { - TypedData = bfast.GetArray("g3d:mesh:indexcount:0:int32:1"); - } - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Data; - - public Type IndexInto { get; } - = null; - - public System.Int32[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - - public partial class SceneMeshOpaqueVertexCountsAttribute : IAttribute - { - public const string AttributeName = "g3d:mesh:opaquevertexcount:0:int32:1"; - - public string Name - => AttributeName; - - public int Count => TypedData?.Length ?? 0; - - public void AddTo(BFast bfast) - { - if(TypedData != null) - { - bfast.SetArray(Name, TypedData); - } - } - - public void ReadBFast(BFast bfast) - { - TypedData = bfast.GetArray("g3d:mesh:opaquevertexcount:0:int32:1"); - } - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Data; - - public Type IndexInto { get; } - = null; - - public System.Int32[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - - public partial class SceneMeshOpaqueIndexCountsAttribute : IAttribute - { - public const string AttributeName = "g3d:mesh:opaqueindexcount:0:int32:1"; - - public string Name - => AttributeName; - - public int Count => TypedData?.Length ?? 0; - - public void AddTo(BFast bfast) - { - if(TypedData != null) - { - bfast.SetArray(Name, TypedData); - } - } - - public void ReadBFast(BFast bfast) - { - TypedData = bfast.GetArray("g3d:mesh:opaqueindexcount:0:int32:1"); - } - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Data; - - public Type IndexInto { get; } - = null; - - public System.Int32[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - - public partial class ChunkMeshOpaqueSubmeshCountsAttribute : IAttribute - { - public const string AttributeName = "g3d:mesh:opaquesubmeshcount:0:int32:1"; - - public string Name - => AttributeName; - - public int Count => TypedData?.Length ?? 0; - - public void AddTo(BFast bfast) - { - if(TypedData != null) - { - bfast.SetArray(Name, TypedData); - } - } - - public void ReadBFast(BFast bfast) - { - TypedData = bfast.GetArray("g3d:mesh:opaquesubmeshcount:0:int32:1"); - } - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Data; - - public Type IndexInto { get; } - = null; - - public System.Int32[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - - public partial class ChunkMeshSubmeshOffsetAttribute : IAttribute - { - public const string AttributeName = "g3d:mesh:submeshOffset:0:int32:1"; - - public string Name - => AttributeName; - - public int Count => TypedData?.Length ?? 0; - - public void AddTo(BFast bfast) - { - if(TypedData != null) - { - bfast.SetArray(Name, TypedData); - } - } - - public void ReadBFast(BFast bfast) - { - TypedData = bfast.GetArray("g3d:mesh:submeshOffset:0:int32:1"); - } - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Index; - - public Type IndexInto { get; } - = typeof(Vim.G3dNext.Attributes.ChunkIndicesAttribute); - - public System.Int32[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - - public partial class ChunkSubmeshIndexOffsetsAttribute : IAttribute - { - public const string AttributeName = "g3d:submesh:indexoffset:0:int32:1"; - - public string Name - => AttributeName; - - public int Count => TypedData?.Length ?? 0; - - public void AddTo(BFast bfast) - { - if(TypedData != null) - { - bfast.SetArray(Name, TypedData); - } - } - - public void ReadBFast(BFast bfast) - { - TypedData = bfast.GetArray("g3d:submesh:indexoffset:0:int32:1"); - } - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Index; - - public Type IndexInto { get; } - = typeof(Vim.G3dNext.Attributes.ChunkIndicesAttribute); - - public System.Int32[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - - public partial class ChunkSubmeshVertexOffsetsAttribute : IAttribute - { - public const string AttributeName = "g3d:submesh:vertexoffset:0:int32:1"; - - public string Name - => AttributeName; - - public int Count => TypedData?.Length ?? 0; - - public void AddTo(BFast bfast) - { - if(TypedData != null) - { - bfast.SetArray(Name, TypedData); - } - } - - public void ReadBFast(BFast bfast) - { - TypedData = bfast.GetArray("g3d:submesh:vertexoffset:0:int32:1"); - } - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Index; - - public Type IndexInto { get; } - = typeof(Vim.G3dNext.Attributes.ChunkIndicesAttribute); - - public System.Int32[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - - public partial class ChunkSubmeshMaterialsAttribute : IAttribute - { - public const string AttributeName = "g3d:submesh:material:0:int32:1"; - - public string Name - => AttributeName; - - public int Count => TypedData?.Length ?? 0; - - public void AddTo(BFast bfast) - { - if(TypedData != null) - { - bfast.SetArray(Name, TypedData); - } - } - - public void ReadBFast(BFast bfast) - { - TypedData = bfast.GetArray("g3d:submesh:material:0:int32:1"); - } - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Index; - - public Type IndexInto { get; } - = null; - - public System.Int32[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - - public partial class ChunkPositionsAttribute : IAttribute - { - public const string AttributeName = "g3d:vertex:position:0:float32:3"; - - public string Name - => AttributeName; - - public int Count => TypedData?.Length ?? 0; - - public void AddTo(BFast bfast) - { - if(TypedData != null) - { - bfast.SetArray(Name, TypedData); - } - } - - public void ReadBFast(BFast bfast) - { - TypedData = bfast.GetArray("g3d:vertex:position:0:float32:3"); - } - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Data; - - public Type IndexInto { get; } - = null; - - public Vim.Math3d.Vector3[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - - public partial class ChunkIndicesAttribute : IAttribute - { - public const string AttributeName = "g3d:corner:index:0:int32:1"; - - public string Name - => AttributeName; - - public int Count => TypedData?.Length ?? 0; - - public void AddTo(BFast bfast) - { - if(TypedData != null) - { - bfast.SetArray(Name, TypedData); - } - } - - public void ReadBFast(BFast bfast) - { - TypedData = bfast.GetArray("g3d:corner:index:0:int32:1"); - } - - public IAttributeDescriptor AttributeDescriptor { get; } - = new AttributeDescriptor(AttributeName); - - public AttributeType AttributeType { get; } - = AttributeType.Index; - - public Type IndexInto { get; } - = typeof(Vim.G3dNext.Attributes.ChunkPositionsAttribute); - - public System.Int32[] TypedData { get; set; } - = Array.Empty(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - { - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - } - } - - // Please provide an explicit implementation in another partial class file. - public partial class G3dVim : ISetup - { - public VimAttributeCollection Attributes; - - public G3dVim() : this(new VimAttributeCollection()) - { - // empty - } - - public G3dVim(BFast bfast) : this(new VimAttributeCollection(bfast)) - { - // empty - } - - public G3dVim(VimAttributeCollection attributes) - { - Attributes = attributes; - - // Method to implement in another partial class - (this as ISetup).Setup(); - } - - public BFast ToBFast() - => Attributes.ToBFast(); - - - public Vim.Math3d.Vector3[] Positions - { - get => Attributes.Positions.TypedData; - set => Attributes.Positions.TypedData = value; - } - - public System.Int32[] Indices - { - get => Attributes.Indices.TypedData; - set => Attributes.Indices.TypedData = value; - } - - public Vim.Math3d.Matrix4x4[] InstanceTransforms - { - get => Attributes.InstanceTransforms.TypedData; - set => Attributes.InstanceTransforms.TypedData = value; - } - - public System.Int32[] InstanceParents - { - get => Attributes.InstanceParents.TypedData; - set => Attributes.InstanceParents.TypedData = value; - } - - public System.UInt16[] InstanceFlags - { - get => Attributes.InstanceFlags.TypedData; - set => Attributes.InstanceFlags.TypedData = value; - } - - public System.Int32[] InstanceMeshes - { - get => Attributes.InstanceMeshes.TypedData; - set => Attributes.InstanceMeshes.TypedData = value; - } - - public System.Int32[] MeshSubmeshOffsets - { - get => Attributes.MeshSubmeshOffsets.TypedData; - set => Attributes.MeshSubmeshOffsets.TypedData = value; - } - - public System.Int32[] SubmeshIndexOffsets - { - get => Attributes.SubmeshIndexOffsets.TypedData; - set => Attributes.SubmeshIndexOffsets.TypedData = value; - } - - public System.Int32[] SubmeshMaterials - { - get => Attributes.SubmeshMaterials.TypedData; - set => Attributes.SubmeshMaterials.TypedData = value; - } - - public Vim.Math3d.Vector4[] MaterialColors - { - get => Attributes.MaterialColors.TypedData; - set => Attributes.MaterialColors.TypedData = value; - } - - public System.Single[] MaterialGlossiness - { - get => Attributes.MaterialGlossiness.TypedData; - set => Attributes.MaterialGlossiness.TypedData = value; - } - - public System.Single[] MaterialSmoothness - { - get => Attributes.MaterialSmoothness.TypedData; - set => Attributes.MaterialSmoothness.TypedData = value; - } - - public Vim.Math3d.Vector3[] ShapeVertices - { - get => Attributes.ShapeVertices.TypedData; - set => Attributes.ShapeVertices.TypedData = value; - } - - public System.Int32[] ShapeVertexOffsets - { - get => Attributes.ShapeVertexOffsets.TypedData; - set => Attributes.ShapeVertexOffsets.TypedData = value; - } - - public Vim.Math3d.Vector4[] ShapeColors - { - get => Attributes.ShapeColors.TypedData; - set => Attributes.ShapeColors.TypedData = value; - } - - public System.Single[] ShapeWidths - { - get => Attributes.ShapeWidths.TypedData; - set => Attributes.ShapeWidths.TypedData = value; - } - } - - - public partial class VimAttributeCollection : IAttributeCollection - { - public VimAttributeCollection() - { - // empty - } - - public VimAttributeCollection(BFast bfast) - { - this.ReadAttributes(bfast); - } - - public void ReadAttributes(BFast bfast) - { - foreach (var attribute in Map.Values) - { - attribute.ReadBFast(bfast); - } - } - - public IDictionary Map { get; } - = new Dictionary - { - [Vim.G3dNext.Attributes.VimPositionsAttribute.AttributeName] = new Vim.G3dNext.Attributes.VimPositionsAttribute(), - [Vim.G3dNext.Attributes.VimIndicesAttribute.AttributeName] = new Vim.G3dNext.Attributes.VimIndicesAttribute(), - [Vim.G3dNext.Attributes.VimInstanceTransformsAttribute.AttributeName] = new Vim.G3dNext.Attributes.VimInstanceTransformsAttribute(), - [Vim.G3dNext.Attributes.VimInstanceParentsAttribute.AttributeName] = new Vim.G3dNext.Attributes.VimInstanceParentsAttribute(), - [Vim.G3dNext.Attributes.VimInstanceFlagsAttribute.AttributeName] = new Vim.G3dNext.Attributes.VimInstanceFlagsAttribute(), - [Vim.G3dNext.Attributes.VimInstanceMeshesAttribute.AttributeName] = new Vim.G3dNext.Attributes.VimInstanceMeshesAttribute(), - [Vim.G3dNext.Attributes.VimMeshSubmeshOffsetsAttribute.AttributeName] = new Vim.G3dNext.Attributes.VimMeshSubmeshOffsetsAttribute(), - [Vim.G3dNext.Attributes.VimSubmeshIndexOffsetsAttribute.AttributeName] = new Vim.G3dNext.Attributes.VimSubmeshIndexOffsetsAttribute(), - [Vim.G3dNext.Attributes.VimSubmeshMaterialsAttribute.AttributeName] = new Vim.G3dNext.Attributes.VimSubmeshMaterialsAttribute(), - [Vim.G3dNext.Attributes.VimMaterialColorsAttribute.AttributeName] = new Vim.G3dNext.Attributes.VimMaterialColorsAttribute(), - [Vim.G3dNext.Attributes.VimMaterialGlossinessAttribute.AttributeName] = new Vim.G3dNext.Attributes.VimMaterialGlossinessAttribute(), - [Vim.G3dNext.Attributes.VimMaterialSmoothnessAttribute.AttributeName] = new Vim.G3dNext.Attributes.VimMaterialSmoothnessAttribute(), - [Vim.G3dNext.Attributes.VimShapeVerticesAttribute.AttributeName] = new Vim.G3dNext.Attributes.VimShapeVerticesAttribute(), - [Vim.G3dNext.Attributes.VimShapeVertexOffsetsAttribute.AttributeName] = new Vim.G3dNext.Attributes.VimShapeVertexOffsetsAttribute(), - [Vim.G3dNext.Attributes.VimShapeColorsAttribute.AttributeName] = new Vim.G3dNext.Attributes.VimShapeColorsAttribute(), - [Vim.G3dNext.Attributes.VimShapeWidthsAttribute.AttributeName] = new Vim.G3dNext.Attributes.VimShapeWidthsAttribute(), - }; - - // Named Attributes. - - public Vim.G3dNext.Attributes.VimPositionsAttribute Positions - { - get => Map.TryGetValue(Vim.G3dNext.Attributes.VimPositionsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.VimPositionsAttribute : default; - set => Map[Vim.G3dNext.Attributes.VimPositionsAttribute.AttributeName] = value as IAttribute; - } - - public Vim.G3dNext.Attributes.VimIndicesAttribute Indices - { - get => Map.TryGetValue(Vim.G3dNext.Attributes.VimIndicesAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.VimIndicesAttribute : default; - set => Map[Vim.G3dNext.Attributes.VimIndicesAttribute.AttributeName] = value as IAttribute; - } - - public Vim.G3dNext.Attributes.VimInstanceTransformsAttribute InstanceTransforms - { - get => Map.TryGetValue(Vim.G3dNext.Attributes.VimInstanceTransformsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.VimInstanceTransformsAttribute : default; - set => Map[Vim.G3dNext.Attributes.VimInstanceTransformsAttribute.AttributeName] = value as IAttribute; - } - - public Vim.G3dNext.Attributes.VimInstanceParentsAttribute InstanceParents - { - get => Map.TryGetValue(Vim.G3dNext.Attributes.VimInstanceParentsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.VimInstanceParentsAttribute : default; - set => Map[Vim.G3dNext.Attributes.VimInstanceParentsAttribute.AttributeName] = value as IAttribute; - } - - public Vim.G3dNext.Attributes.VimInstanceFlagsAttribute InstanceFlags - { - get => Map.TryGetValue(Vim.G3dNext.Attributes.VimInstanceFlagsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.VimInstanceFlagsAttribute : default; - set => Map[Vim.G3dNext.Attributes.VimInstanceFlagsAttribute.AttributeName] = value as IAttribute; - } - - public Vim.G3dNext.Attributes.VimInstanceMeshesAttribute InstanceMeshes - { - get => Map.TryGetValue(Vim.G3dNext.Attributes.VimInstanceMeshesAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.VimInstanceMeshesAttribute : default; - set => Map[Vim.G3dNext.Attributes.VimInstanceMeshesAttribute.AttributeName] = value as IAttribute; - } - - public Vim.G3dNext.Attributes.VimMeshSubmeshOffsetsAttribute MeshSubmeshOffsets - { - get => Map.TryGetValue(Vim.G3dNext.Attributes.VimMeshSubmeshOffsetsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.VimMeshSubmeshOffsetsAttribute : default; - set => Map[Vim.G3dNext.Attributes.VimMeshSubmeshOffsetsAttribute.AttributeName] = value as IAttribute; - } - - public Vim.G3dNext.Attributes.VimSubmeshIndexOffsetsAttribute SubmeshIndexOffsets - { - get => Map.TryGetValue(Vim.G3dNext.Attributes.VimSubmeshIndexOffsetsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.VimSubmeshIndexOffsetsAttribute : default; - set => Map[Vim.G3dNext.Attributes.VimSubmeshIndexOffsetsAttribute.AttributeName] = value as IAttribute; - } - - public Vim.G3dNext.Attributes.VimSubmeshMaterialsAttribute SubmeshMaterials - { - get => Map.TryGetValue(Vim.G3dNext.Attributes.VimSubmeshMaterialsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.VimSubmeshMaterialsAttribute : default; - set => Map[Vim.G3dNext.Attributes.VimSubmeshMaterialsAttribute.AttributeName] = value as IAttribute; - } - - public Vim.G3dNext.Attributes.VimMaterialColorsAttribute MaterialColors - { - get => Map.TryGetValue(Vim.G3dNext.Attributes.VimMaterialColorsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.VimMaterialColorsAttribute : default; - set => Map[Vim.G3dNext.Attributes.VimMaterialColorsAttribute.AttributeName] = value as IAttribute; - } - - public Vim.G3dNext.Attributes.VimMaterialGlossinessAttribute MaterialGlossiness - { - get => Map.TryGetValue(Vim.G3dNext.Attributes.VimMaterialGlossinessAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.VimMaterialGlossinessAttribute : default; - set => Map[Vim.G3dNext.Attributes.VimMaterialGlossinessAttribute.AttributeName] = value as IAttribute; - } - - public Vim.G3dNext.Attributes.VimMaterialSmoothnessAttribute MaterialSmoothness - { - get => Map.TryGetValue(Vim.G3dNext.Attributes.VimMaterialSmoothnessAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.VimMaterialSmoothnessAttribute : default; - set => Map[Vim.G3dNext.Attributes.VimMaterialSmoothnessAttribute.AttributeName] = value as IAttribute; - } - - public Vim.G3dNext.Attributes.VimShapeVerticesAttribute ShapeVertices - { - get => Map.TryGetValue(Vim.G3dNext.Attributes.VimShapeVerticesAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.VimShapeVerticesAttribute : default; - set => Map[Vim.G3dNext.Attributes.VimShapeVerticesAttribute.AttributeName] = value as IAttribute; - } - - public Vim.G3dNext.Attributes.VimShapeVertexOffsetsAttribute ShapeVertexOffsets - { - get => Map.TryGetValue(Vim.G3dNext.Attributes.VimShapeVertexOffsetsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.VimShapeVertexOffsetsAttribute : default; - set => Map[Vim.G3dNext.Attributes.VimShapeVertexOffsetsAttribute.AttributeName] = value as IAttribute; - } - - public Vim.G3dNext.Attributes.VimShapeColorsAttribute ShapeColors - { - get => Map.TryGetValue(Vim.G3dNext.Attributes.VimShapeColorsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.VimShapeColorsAttribute : default; - set => Map[Vim.G3dNext.Attributes.VimShapeColorsAttribute.AttributeName] = value as IAttribute; - } - - public Vim.G3dNext.Attributes.VimShapeWidthsAttribute ShapeWidths - { - get => Map.TryGetValue(Vim.G3dNext.Attributes.VimShapeWidthsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.VimShapeWidthsAttribute : default; - set => Map[Vim.G3dNext.Attributes.VimShapeWidthsAttribute.AttributeName] = value as IAttribute; - } - - /// - public IAttribute GetAttribute(Type attributeType) - { - - - if (attributeType == typeof(Vim.G3dNext.Attributes.VimPositionsAttribute)) - return Positions; - - - if (attributeType == typeof(Vim.G3dNext.Attributes.VimIndicesAttribute)) - return Indices; - - - if (attributeType == typeof(Vim.G3dNext.Attributes.VimInstanceTransformsAttribute)) - return InstanceTransforms; - - - if (attributeType == typeof(Vim.G3dNext.Attributes.VimInstanceParentsAttribute)) - return InstanceParents; - - - if (attributeType == typeof(Vim.G3dNext.Attributes.VimInstanceFlagsAttribute)) - return InstanceFlags; - - - if (attributeType == typeof(Vim.G3dNext.Attributes.VimInstanceMeshesAttribute)) - return InstanceMeshes; - - - if (attributeType == typeof(Vim.G3dNext.Attributes.VimMeshSubmeshOffsetsAttribute)) - return MeshSubmeshOffsets; - - - if (attributeType == typeof(Vim.G3dNext.Attributes.VimSubmeshIndexOffsetsAttribute)) - return SubmeshIndexOffsets; - - - if (attributeType == typeof(Vim.G3dNext.Attributes.VimSubmeshMaterialsAttribute)) - return SubmeshMaterials; - - - if (attributeType == typeof(Vim.G3dNext.Attributes.VimMaterialColorsAttribute)) - return MaterialColors; - - - if (attributeType == typeof(Vim.G3dNext.Attributes.VimMaterialGlossinessAttribute)) - return MaterialGlossiness; - - - if (attributeType == typeof(Vim.G3dNext.Attributes.VimMaterialSmoothnessAttribute)) - return MaterialSmoothness; - - - if (attributeType == typeof(Vim.G3dNext.Attributes.VimShapeVerticesAttribute)) - return ShapeVertices; - - - if (attributeType == typeof(Vim.G3dNext.Attributes.VimShapeVertexOffsetsAttribute)) - return ShapeVertexOffsets; - - - if (attributeType == typeof(Vim.G3dNext.Attributes.VimShapeColorsAttribute)) - return ShapeColors; - - - if (attributeType == typeof(Vim.G3dNext.Attributes.VimShapeWidthsAttribute)) - return ShapeWidths; - - throw new ArgumentException("Type {attributeType.ToString()} is not supported."); - } - - public IAttribute MergeAttribute(string attributeName, IReadOnlyList otherCollections) - { - var collections = otherCollections.Prepend(this).ToArray(); - switch (attributeName) - { - - case Vim.G3dNext.Attributes.VimPositionsAttribute.AttributeName: - { - // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); - } - - case Vim.G3dNext.Attributes.VimIndicesAttribute.AttributeName: - { - // Index Attribute - return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); - } - - case Vim.G3dNext.Attributes.VimInstanceTransformsAttribute.AttributeName: - { - // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); - } - - case Vim.G3dNext.Attributes.VimInstanceParentsAttribute.AttributeName: - { - // Index Attribute - return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); - } - - case Vim.G3dNext.Attributes.VimInstanceFlagsAttribute.AttributeName: - { - // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); - } - - case Vim.G3dNext.Attributes.VimInstanceMeshesAttribute.AttributeName: - { - // Index Attribute - return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); - } - - case Vim.G3dNext.Attributes.VimMeshSubmeshOffsetsAttribute.AttributeName: - { - // Index Attribute - return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); - } - - case Vim.G3dNext.Attributes.VimSubmeshIndexOffsetsAttribute.AttributeName: - { - // Index Attribute - return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); - } - - case Vim.G3dNext.Attributes.VimSubmeshMaterialsAttribute.AttributeName: - { - // Index Attribute - return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); - } - - case Vim.G3dNext.Attributes.VimMaterialColorsAttribute.AttributeName: - { - // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); - } - - case Vim.G3dNext.Attributes.VimMaterialGlossinessAttribute.AttributeName: - { - // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); - } - - case Vim.G3dNext.Attributes.VimMaterialSmoothnessAttribute.AttributeName: - { - // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); - } - - case Vim.G3dNext.Attributes.VimShapeVerticesAttribute.AttributeName: - { - // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); - } - - case Vim.G3dNext.Attributes.VimShapeVertexOffsetsAttribute.AttributeName: - { - // Index Attribute - return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); - } - - case Vim.G3dNext.Attributes.VimShapeColorsAttribute.AttributeName: - { - // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); - } - - case Vim.G3dNext.Attributes.VimShapeWidthsAttribute.AttributeName: - { - // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); - } - - default: - throw new ArgumentException(nameof(attributeName)); - } - } - - public void Validate() - { - // Ensure all the indices are either -1 or within the bounds of the attributes they are indexing into. - - { - var maxIndex = GetAttribute(Indices.IndexInto).Data.Length - 1; - for (var i = 0; i < Indices.TypedData.Length; ++i) - { - var index = Indices.TypedData[i]; - - if (index == -1) - continue; // no relation. - - if (index < -1 || index > maxIndex) - throw new Exception($"Index out of range in Vim.G3dNext.Attributes.VimIndicesAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); - } - } - - { - var maxIndex = GetAttribute(InstanceParents.IndexInto).Data.Length - 1; - for (var i = 0; i < InstanceParents.TypedData.Length; ++i) - { - var index = InstanceParents.TypedData[i]; - - if (index == -1) - continue; // no relation. - - if (index < -1 || index > maxIndex) - throw new Exception($"Index out of range in Vim.G3dNext.Attributes.VimInstanceParentsAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); - } - } - - { - var maxIndex = GetAttribute(InstanceMeshes.IndexInto).Data.Length - 1; - for (var i = 0; i < InstanceMeshes.TypedData.Length; ++i) - { - var index = InstanceMeshes.TypedData[i]; - - if (index == -1) - continue; // no relation. - - if (index < -1 || index > maxIndex) - throw new Exception($"Index out of range in Vim.G3dNext.Attributes.VimInstanceMeshesAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); - } - } - - { - var maxIndex = GetAttribute(MeshSubmeshOffsets.IndexInto).Data.Length - 1; - for (var i = 0; i < MeshSubmeshOffsets.TypedData.Length; ++i) - { - var index = MeshSubmeshOffsets.TypedData[i]; - - if (index == -1) - continue; // no relation. - - if (index < -1 || index > maxIndex) - throw new Exception($"Index out of range in Vim.G3dNext.Attributes.VimMeshSubmeshOffsetsAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); - } - } - - { - var maxIndex = GetAttribute(SubmeshIndexOffsets.IndexInto).Data.Length - 1; - for (var i = 0; i < SubmeshIndexOffsets.TypedData.Length; ++i) - { - var index = SubmeshIndexOffsets.TypedData[i]; - - if (index == -1) - continue; // no relation. - - if (index < -1 || index > maxIndex) - throw new Exception($"Index out of range in Vim.G3dNext.Attributes.VimSubmeshIndexOffsetsAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); - } - } - - { - var maxIndex = GetAttribute(SubmeshMaterials.IndexInto).Data.Length - 1; - for (var i = 0; i < SubmeshMaterials.TypedData.Length; ++i) - { - var index = SubmeshMaterials.TypedData[i]; - - if (index == -1) - continue; // no relation. - - if (index < -1 || index > maxIndex) - throw new Exception($"Index out of range in Vim.G3dNext.Attributes.VimSubmeshMaterialsAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); - } - } - - { - var maxIndex = GetAttribute(ShapeVertexOffsets.IndexInto).Data.Length - 1; - for (var i = 0; i < ShapeVertexOffsets.TypedData.Length; ++i) - { - var index = ShapeVertexOffsets.TypedData[i]; - - if (index == -1) - continue; // no relation. - - if (index < -1 || index > maxIndex) - throw new Exception($"Index out of range in Vim.G3dNext.Attributes.VimShapeVertexOffsetsAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); - } - } - } - } - - // Please provide an explicit implementation in another partial class file. - public partial class G3dMaterials : ISetup - { - public MaterialsAttributeCollection Attributes; - - public G3dMaterials() : this(new MaterialsAttributeCollection()) - { - // empty - } - - public G3dMaterials(BFast bfast) : this(new MaterialsAttributeCollection(bfast)) - { - // empty - } - - public G3dMaterials(MaterialsAttributeCollection attributes) - { - Attributes = attributes; - - // Method to implement in another partial class - (this as ISetup).Setup(); - } - - public BFast ToBFast() - => Attributes.ToBFast(); - - - public Vim.Math3d.Vector4[] MaterialColors - { - get => Attributes.MaterialColors.TypedData; - set => Attributes.MaterialColors.TypedData = value; - } - - public System.Single[] MaterialGlossiness - { - get => Attributes.MaterialGlossiness.TypedData; - set => Attributes.MaterialGlossiness.TypedData = value; - } - - public System.Single[] MaterialSmoothness - { - get => Attributes.MaterialSmoothness.TypedData; - set => Attributes.MaterialSmoothness.TypedData = value; - } - } - - - public partial class MaterialsAttributeCollection : IAttributeCollection - { - public MaterialsAttributeCollection() - { - // empty - } - - public MaterialsAttributeCollection(BFast bfast) - { - this.ReadAttributes(bfast); - } - - public void ReadAttributes(BFast bfast) - { - foreach (var attribute in Map.Values) - { - attribute.ReadBFast(bfast); - } - } - - public IDictionary Map { get; } - = new Dictionary - { - [Vim.G3dNext.Attributes.MaterialColorsAttribute.AttributeName] = new Vim.G3dNext.Attributes.MaterialColorsAttribute(), - [Vim.G3dNext.Attributes.MaterialGlossinessAttribute.AttributeName] = new Vim.G3dNext.Attributes.MaterialGlossinessAttribute(), - [Vim.G3dNext.Attributes.MaterialSmoothnessAttribute.AttributeName] = new Vim.G3dNext.Attributes.MaterialSmoothnessAttribute(), - }; - - // Named Attributes. - - public Vim.G3dNext.Attributes.MaterialColorsAttribute MaterialColors - { - get => Map.TryGetValue(Vim.G3dNext.Attributes.MaterialColorsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MaterialColorsAttribute : default; - set => Map[Vim.G3dNext.Attributes.MaterialColorsAttribute.AttributeName] = value as IAttribute; - } - - public Vim.G3dNext.Attributes.MaterialGlossinessAttribute MaterialGlossiness - { - get => Map.TryGetValue(Vim.G3dNext.Attributes.MaterialGlossinessAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MaterialGlossinessAttribute : default; - set => Map[Vim.G3dNext.Attributes.MaterialGlossinessAttribute.AttributeName] = value as IAttribute; - } - - public Vim.G3dNext.Attributes.MaterialSmoothnessAttribute MaterialSmoothness - { - get => Map.TryGetValue(Vim.G3dNext.Attributes.MaterialSmoothnessAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.MaterialSmoothnessAttribute : default; - set => Map[Vim.G3dNext.Attributes.MaterialSmoothnessAttribute.AttributeName] = value as IAttribute; - } - - /// - public IAttribute GetAttribute(Type attributeType) - { - - - if (attributeType == typeof(Vim.G3dNext.Attributes.MaterialColorsAttribute)) - return MaterialColors; - - - if (attributeType == typeof(Vim.G3dNext.Attributes.MaterialGlossinessAttribute)) - return MaterialGlossiness; - - - if (attributeType == typeof(Vim.G3dNext.Attributes.MaterialSmoothnessAttribute)) - return MaterialSmoothness; - - throw new ArgumentException("Type {attributeType.ToString()} is not supported."); - } - - public IAttribute MergeAttribute(string attributeName, IReadOnlyList otherCollections) - { - var collections = otherCollections.Prepend(this).ToArray(); - switch (attributeName) - { - - case Vim.G3dNext.Attributes.MaterialColorsAttribute.AttributeName: - { - // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); - } - - case Vim.G3dNext.Attributes.MaterialGlossinessAttribute.AttributeName: - { - // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); - } - - case Vim.G3dNext.Attributes.MaterialSmoothnessAttribute.AttributeName: - { - // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); - } - - default: - throw new ArgumentException(nameof(attributeName)); - } - } - - public void Validate() - { - // Ensure all the indices are either -1 or within the bounds of the attributes they are indexing into. - - } - } - // Please provide an explicit implementation in another partial class file. - public partial class G3dScene : ISetup + public partial class G3dVim : ISetup { - public SceneAttributeCollection Attributes; + public System.Int32[] Indices; + public Vim.Math3d.Vector3[] Positions; + public Vim.Math3d.Matrix4x4[] InstanceTransforms; + public System.Int32[] InstanceParents; + public System.UInt16[] InstanceFlags; + public System.Int32[] InstanceMeshes; + public System.Int32[] MeshSubmeshOffsets; + public System.Int32[] SubmeshIndexOffsets; + public System.Int32[] SubmeshMaterials; + public Vim.Math3d.Vector4[] MaterialColors; + public System.Single[] MaterialGlossiness; + public System.Single[] MaterialSmoothness; + public Vim.Math3d.Vector3[] ShapeVertices; + public System.Int32[] ShapeVertexOffsets; + public Vim.Math3d.Vector4[] ShapeColors; + public System.Single[] ShapeWidths; + + public G3dVim( + System.Int32[] indices, + Vim.Math3d.Vector3[] positions, + Vim.Math3d.Matrix4x4[] instanceTransforms, + System.Int32[] instanceParents, + System.UInt16[] instanceFlags, + System.Int32[] instanceMeshes, + System.Int32[] meshSubmeshOffsets, + System.Int32[] submeshIndexOffsets, + System.Int32[] submeshMaterials, + Vim.Math3d.Vector4[] materialColors, + System.Single[] materialGlossiness, + System.Single[] materialSmoothness, + Vim.Math3d.Vector3[] shapeVertices, + System.Int32[] shapeVertexOffsets, + Vim.Math3d.Vector4[] shapeColors, + System.Single[] shapeWidths + ) + { + Indices = indices; + Positions = positions; + InstanceTransforms = instanceTransforms; + InstanceParents = instanceParents; + InstanceFlags = instanceFlags; + InstanceMeshes = instanceMeshes; + MeshSubmeshOffsets = meshSubmeshOffsets; + SubmeshIndexOffsets = submeshIndexOffsets; + SubmeshMaterials = submeshMaterials; + MaterialColors = materialColors; + MaterialGlossiness = materialGlossiness; + MaterialSmoothness = materialSmoothness; + ShapeVertices = shapeVertices; + ShapeVertexOffsets = shapeVertexOffsets; + ShapeColors = shapeColors; + ShapeWidths = shapeWidths; - public G3dScene() : this(new SceneAttributeCollection()) - { - // empty - } - - public G3dScene(BFast bfast) : this(new SceneAttributeCollection(bfast)) - { - // empty + (this as ISetup).Setup(); } - public G3dScene(SceneAttributeCollection attributes) - { - Attributes = attributes; + public G3dVim(BFast bfast) + { + Indices = bfast.GetArray("g3d:corner:index:0:int32:1"); + Positions = bfast.GetArray("g3d:vertex:position:0:float32:3"); + InstanceTransforms = bfast.GetArray("g3d:instance:transform:0:float32:16"); + InstanceParents = bfast.GetArray("g3d:instance:parent:0:int32:1"); + InstanceFlags = bfast.GetArray("g3d:instance:flags:0:uint16:1"); + InstanceMeshes = bfast.GetArray("g3d:instance:mesh:0:int32:1"); + MeshSubmeshOffsets = bfast.GetArray("g3d:mesh:submeshoffset:0:int32:1"); + SubmeshIndexOffsets = bfast.GetArray("g3d:submesh:indexoffset:0:int32:1"); + SubmeshMaterials = bfast.GetArray("g3d:submesh:material:0:int32:1"); + MaterialColors = bfast.GetArray("g3d:material:color:0:float32:4"); + MaterialGlossiness = bfast.GetArray("g3d:material:glossiness:0:float32:1"); + MaterialSmoothness = bfast.GetArray("g3d:material:smoothness:0:float32:1"); + ShapeVertices = bfast.GetArray("g3d:shapevertex:position:0:float32:3"); + ShapeVertexOffsets = bfast.GetArray("g3d:shape:vertexoffset:0:int32:1"); + ShapeColors = bfast.GetArray("g3d:shape:color:0:float32:4"); + ShapeWidths = bfast.GetArray("g3d:shape:width:0:float32:1"); - // Method to implement in another partial class (this as ISetup).Setup(); } public BFast ToBFast() - => Attributes.ToBFast(); - - - public System.Int32[] ChunkCount - { - get => Attributes.ChunkCount.TypedData; - set => Attributes.ChunkCount.TypedData = value; - } - - public System.Int32[] InstanceMeshes - { - get => Attributes.InstanceMeshes.TypedData; - set => Attributes.InstanceMeshes.TypedData = value; - } - - public Vim.Math3d.Matrix4x4[] InstanceTransformData - { - get => Attributes.InstanceTransformData.TypedData; - set => Attributes.InstanceTransformData.TypedData = value; - } - - public System.Int32[] InstanceNodes - { - get => Attributes.InstanceNodes.TypedData; - set => Attributes.InstanceNodes.TypedData = value; - } - - public System.Int32[] InstanceGroups - { - get => Attributes.InstanceGroups.TypedData; - set => Attributes.InstanceGroups.TypedData = value; - } - - public System.Int64[] InstanceTags - { - get => Attributes.InstanceTags.TypedData; - set => Attributes.InstanceTags.TypedData = value; - } - - public System.UInt16[] InstanceFlags - { - get => Attributes.InstanceFlags.TypedData; - set => Attributes.InstanceFlags.TypedData = value; - } - - public Vim.Math3d.Vector3[] InstanceMins - { - get => Attributes.InstanceMins.TypedData; - set => Attributes.InstanceMins.TypedData = value; - } - - public Vim.Math3d.Vector3[] InstanceMaxs - { - get => Attributes.InstanceMaxs.TypedData; - set => Attributes.InstanceMaxs.TypedData = value; - } - - public System.Int32[] MeshChunks - { - get => Attributes.MeshChunks.TypedData; - set => Attributes.MeshChunks.TypedData = value; - } - - public System.Int32[] MeshChunkIndices - { - get => Attributes.MeshChunkIndices.TypedData; - set => Attributes.MeshChunkIndices.TypedData = value; - } - - public System.Int32[] MeshIndexCounts { - get => Attributes.MeshIndexCounts.TypedData; - set => Attributes.MeshIndexCounts.TypedData = value; + var bfast = new BFast(); + + bfast.SetArray("g3d:corner:index:0:int32:1", Indices); + bfast.SetArray("g3d:vertex:position:0:float32:3", Positions); + bfast.SetArray("g3d:instance:transform:0:float32:16", InstanceTransforms); + bfast.SetArray("g3d:instance:parent:0:int32:1", InstanceParents); + bfast.SetArray("g3d:instance:flags:0:uint16:1", InstanceFlags); + bfast.SetArray("g3d:instance:mesh:0:int32:1", InstanceMeshes); + bfast.SetArray("g3d:mesh:submeshoffset:0:int32:1", MeshSubmeshOffsets); + bfast.SetArray("g3d:submesh:indexoffset:0:int32:1", SubmeshIndexOffsets); + bfast.SetArray("g3d:submesh:material:0:int32:1", SubmeshMaterials); + bfast.SetArray("g3d:material:color:0:float32:4", MaterialColors); + bfast.SetArray("g3d:material:glossiness:0:float32:1", MaterialGlossiness); + bfast.SetArray("g3d:material:smoothness:0:float32:1", MaterialSmoothness); + bfast.SetArray("g3d:shapevertex:position:0:float32:3", ShapeVertices); + bfast.SetArray("g3d:shape:vertexoffset:0:int32:1", ShapeVertexOffsets); + bfast.SetArray("g3d:shape:color:0:float32:4", ShapeColors); + bfast.SetArray("g3d:shape:width:0:float32:1", ShapeWidths); + + return bfast; + } + + public bool Equals(G3dVim other ) + { + return Indices.SafeEquals(other.Indices) && + Positions.SafeEquals(other.Positions) && + InstanceTransforms.SafeEquals(other.InstanceTransforms) && + InstanceParents.SafeEquals(other.InstanceParents) && + InstanceFlags.SafeEquals(other.InstanceFlags) && + InstanceMeshes.SafeEquals(other.InstanceMeshes) && + MeshSubmeshOffsets.SafeEquals(other.MeshSubmeshOffsets) && + SubmeshIndexOffsets.SafeEquals(other.SubmeshIndexOffsets) && + SubmeshMaterials.SafeEquals(other.SubmeshMaterials) && + MaterialColors.SafeEquals(other.MaterialColors) && + MaterialGlossiness.SafeEquals(other.MaterialGlossiness) && + MaterialSmoothness.SafeEquals(other.MaterialSmoothness) && + ShapeVertices.SafeEquals(other.ShapeVertices) && + ShapeVertexOffsets.SafeEquals(other.ShapeVertexOffsets) && + ShapeColors.SafeEquals(other.ShapeColors) && + ShapeWidths.SafeEquals(other.ShapeWidths); + } + + + public G3dVim Merge(G3dVim other) + { + return new G3dVim( + Indices.MergeIndices(other.Indices, Positions?.Length ?? 0), + Positions.MergeData(other.Positions), + InstanceTransforms.MergeData(other.InstanceTransforms), + InstanceParents.MergeIndices(other.InstanceParents, InstanceTransforms?.Length ?? 0), + InstanceFlags.MergeData(other.InstanceFlags), + InstanceMeshes.MergeIndices(other.InstanceMeshes, MeshSubmeshOffsets?.Length ?? 0), + MeshSubmeshOffsets.MergeIndices(other.MeshSubmeshOffsets, SubmeshIndexOffsets?.Length ?? 0), + SubmeshIndexOffsets.MergeIndices(other.SubmeshIndexOffsets, Indices?.Length ?? 0), + SubmeshMaterials.MergeIndices(other.SubmeshMaterials, MaterialColors?.Length ?? 0), + MaterialColors.MergeData(other.MaterialColors), + MaterialGlossiness.MergeData(other.MaterialGlossiness), + MaterialSmoothness.MergeData(other.MaterialSmoothness), + ShapeVertices.MergeData(other.ShapeVertices), + ShapeVertexOffsets.MergeIndices(other.ShapeVertexOffsets, ShapeVertices?.Length ?? 0), + ShapeColors.MergeData(other.ShapeColors), + ShapeWidths.MergeData(other.ShapeWidths) + ); } - public System.Int32[] MeshVertexCounts - { - get => Attributes.MeshVertexCounts.TypedData; - set => Attributes.MeshVertexCounts.TypedData = value; - } - - public System.Int32[] MeshOpaqueIndexCounts - { - get => Attributes.MeshOpaqueIndexCounts.TypedData; - set => Attributes.MeshOpaqueIndexCounts.TypedData = value; - } - - public System.Int32[] MeshOpaqueVertexCounts + public void Validate() { - get => Attributes.MeshOpaqueVertexCounts.TypedData; - set => Attributes.MeshOpaqueVertexCounts.TypedData = value; + // Ensure all the indices are either -1 or within the bounds of the attributes they are indexing into. + Indices?.ValidateIndex(Positions, "Indices"); + InstanceParents?.ValidateIndex(InstanceTransforms, "InstanceParents"); + InstanceMeshes?.ValidateIndex(MeshSubmeshOffsets, "InstanceMeshes"); + MeshSubmeshOffsets?.ValidateIndex(SubmeshIndexOffsets, "MeshSubmeshOffsets"); + SubmeshIndexOffsets?.ValidateIndex(Indices, "SubmeshIndexOffsets"); + SubmeshMaterials?.ValidateIndex(MaterialColors, "SubmeshMaterials"); + ShapeVertexOffsets?.ValidateIndex(ShapeVertices, "ShapeVertexOffsets"); } } - - public partial class SceneAttributeCollection : IAttributeCollection + // Please provide an explicit implementation in another partial class file. + public partial class G3dChunk : ISetup { - public SceneAttributeCollection() - { - // empty - } - - public SceneAttributeCollection(BFast bfast) - { - this.ReadAttributes(bfast); - } - - public void ReadAttributes(BFast bfast) - { - foreach (var attribute in Map.Values) - { - attribute.ReadBFast(bfast); - } - } - - public IDictionary Map { get; } - = new Dictionary - { - [Vim.G3dNext.Attributes.SceneChunkCountAttribute.AttributeName] = new Vim.G3dNext.Attributes.SceneChunkCountAttribute(), - [Vim.G3dNext.Attributes.SceneInstanceMeshesAttribute.AttributeName] = new Vim.G3dNext.Attributes.SceneInstanceMeshesAttribute(), - [Vim.G3dNext.Attributes.SceneInstanceTransformDataAttribute.AttributeName] = new Vim.G3dNext.Attributes.SceneInstanceTransformDataAttribute(), - [Vim.G3dNext.Attributes.SceneInstanceNodesAttribute.AttributeName] = new Vim.G3dNext.Attributes.SceneInstanceNodesAttribute(), - [Vim.G3dNext.Attributes.SceneInstanceGroupsAttribute.AttributeName] = new Vim.G3dNext.Attributes.SceneInstanceGroupsAttribute(), - [Vim.G3dNext.Attributes.SceneInstanceTagsAttribute.AttributeName] = new Vim.G3dNext.Attributes.SceneInstanceTagsAttribute(), - [Vim.G3dNext.Attributes.SceneInstanceFlagsAttribute.AttributeName] = new Vim.G3dNext.Attributes.SceneInstanceFlagsAttribute(), - [Vim.G3dNext.Attributes.SceneInstanceMinsAttribute.AttributeName] = new Vim.G3dNext.Attributes.SceneInstanceMinsAttribute(), - [Vim.G3dNext.Attributes.SceneInstanceMaxsAttribute.AttributeName] = new Vim.G3dNext.Attributes.SceneInstanceMaxsAttribute(), - [Vim.G3dNext.Attributes.SceneMeshChunksAttribute.AttributeName] = new Vim.G3dNext.Attributes.SceneMeshChunksAttribute(), - [Vim.G3dNext.Attributes.SceneMeshChunkIndicesAttribute.AttributeName] = new Vim.G3dNext.Attributes.SceneMeshChunkIndicesAttribute(), - [Vim.G3dNext.Attributes.SceneMeshIndexCountsAttribute.AttributeName] = new Vim.G3dNext.Attributes.SceneMeshIndexCountsAttribute(), - [Vim.G3dNext.Attributes.SceneMeshVertexCountsAttribute.AttributeName] = new Vim.G3dNext.Attributes.SceneMeshVertexCountsAttribute(), - [Vim.G3dNext.Attributes.SceneMeshOpaqueIndexCountsAttribute.AttributeName] = new Vim.G3dNext.Attributes.SceneMeshOpaqueIndexCountsAttribute(), - [Vim.G3dNext.Attributes.SceneMeshOpaqueVertexCountsAttribute.AttributeName] = new Vim.G3dNext.Attributes.SceneMeshOpaqueVertexCountsAttribute(), - }; - - // Named Attributes. - - public Vim.G3dNext.Attributes.SceneChunkCountAttribute ChunkCount - { - get => Map.TryGetValue(Vim.G3dNext.Attributes.SceneChunkCountAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.SceneChunkCountAttribute : default; - set => Map[Vim.G3dNext.Attributes.SceneChunkCountAttribute.AttributeName] = value as IAttribute; - } - - public Vim.G3dNext.Attributes.SceneInstanceMeshesAttribute InstanceMeshes - { - get => Map.TryGetValue(Vim.G3dNext.Attributes.SceneInstanceMeshesAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.SceneInstanceMeshesAttribute : default; - set => Map[Vim.G3dNext.Attributes.SceneInstanceMeshesAttribute.AttributeName] = value as IAttribute; - } - - public Vim.G3dNext.Attributes.SceneInstanceTransformDataAttribute InstanceTransformData - { - get => Map.TryGetValue(Vim.G3dNext.Attributes.SceneInstanceTransformDataAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.SceneInstanceTransformDataAttribute : default; - set => Map[Vim.G3dNext.Attributes.SceneInstanceTransformDataAttribute.AttributeName] = value as IAttribute; - } - - public Vim.G3dNext.Attributes.SceneInstanceNodesAttribute InstanceNodes - { - get => Map.TryGetValue(Vim.G3dNext.Attributes.SceneInstanceNodesAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.SceneInstanceNodesAttribute : default; - set => Map[Vim.G3dNext.Attributes.SceneInstanceNodesAttribute.AttributeName] = value as IAttribute; - } + public System.Int32[] MeshOpaqueSubmeshCounts; + public System.Int32[] MeshSubmeshOffset; + public System.Int32[] SubmeshIndexOffsets; + public System.Int32[] SubmeshVertexOffsets; + public System.Int32[] SubmeshMaterials; + public Vim.Math3d.Vector3[] Positions; + public System.Int32[] Indices; + + public G3dChunk( + System.Int32[] meshOpaqueSubmeshCounts, + System.Int32[] meshSubmeshOffset, + System.Int32[] submeshIndexOffsets, + System.Int32[] submeshVertexOffsets, + System.Int32[] submeshMaterials, + Vim.Math3d.Vector3[] positions, + System.Int32[] indices + ) + { + MeshOpaqueSubmeshCounts = meshOpaqueSubmeshCounts; + MeshSubmeshOffset = meshSubmeshOffset; + SubmeshIndexOffsets = submeshIndexOffsets; + SubmeshVertexOffsets = submeshVertexOffsets; + SubmeshMaterials = submeshMaterials; + Positions = positions; + Indices = indices; - public Vim.G3dNext.Attributes.SceneInstanceGroupsAttribute InstanceGroups - { - get => Map.TryGetValue(Vim.G3dNext.Attributes.SceneInstanceGroupsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.SceneInstanceGroupsAttribute : default; - set => Map[Vim.G3dNext.Attributes.SceneInstanceGroupsAttribute.AttributeName] = value as IAttribute; - } - - public Vim.G3dNext.Attributes.SceneInstanceTagsAttribute InstanceTags - { - get => Map.TryGetValue(Vim.G3dNext.Attributes.SceneInstanceTagsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.SceneInstanceTagsAttribute : default; - set => Map[Vim.G3dNext.Attributes.SceneInstanceTagsAttribute.AttributeName] = value as IAttribute; - } - - public Vim.G3dNext.Attributes.SceneInstanceFlagsAttribute InstanceFlags - { - get => Map.TryGetValue(Vim.G3dNext.Attributes.SceneInstanceFlagsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.SceneInstanceFlagsAttribute : default; - set => Map[Vim.G3dNext.Attributes.SceneInstanceFlagsAttribute.AttributeName] = value as IAttribute; - } - - public Vim.G3dNext.Attributes.SceneInstanceMinsAttribute InstanceMins - { - get => Map.TryGetValue(Vim.G3dNext.Attributes.SceneInstanceMinsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.SceneInstanceMinsAttribute : default; - set => Map[Vim.G3dNext.Attributes.SceneInstanceMinsAttribute.AttributeName] = value as IAttribute; - } - - public Vim.G3dNext.Attributes.SceneInstanceMaxsAttribute InstanceMaxs - { - get => Map.TryGetValue(Vim.G3dNext.Attributes.SceneInstanceMaxsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.SceneInstanceMaxsAttribute : default; - set => Map[Vim.G3dNext.Attributes.SceneInstanceMaxsAttribute.AttributeName] = value as IAttribute; + (this as ISetup).Setup(); } - public Vim.G3dNext.Attributes.SceneMeshChunksAttribute MeshChunks + public G3dChunk(BFast bfast) { - get => Map.TryGetValue(Vim.G3dNext.Attributes.SceneMeshChunksAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.SceneMeshChunksAttribute : default; - set => Map[Vim.G3dNext.Attributes.SceneMeshChunksAttribute.AttributeName] = value as IAttribute; - } + MeshOpaqueSubmeshCounts = bfast.GetArray("g3d:mesh:opaquesubmeshcount:0:int32:1"); + MeshSubmeshOffset = bfast.GetArray("g3d:mesh:submeshOffset:0:int32:1"); + SubmeshIndexOffsets = bfast.GetArray("g3d:submesh:indexoffset:0:int32:1"); + SubmeshVertexOffsets = bfast.GetArray("g3d:submesh:vertexoffset:0:int32:1"); + SubmeshMaterials = bfast.GetArray("g3d:submesh:material:0:int32:1"); + Positions = bfast.GetArray("g3d:vertex:position:0:float32:3"); + Indices = bfast.GetArray("g3d:corner:index:0:int32:1"); - public Vim.G3dNext.Attributes.SceneMeshChunkIndicesAttribute MeshChunkIndices - { - get => Map.TryGetValue(Vim.G3dNext.Attributes.SceneMeshChunkIndicesAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.SceneMeshChunkIndicesAttribute : default; - set => Map[Vim.G3dNext.Attributes.SceneMeshChunkIndicesAttribute.AttributeName] = value as IAttribute; + (this as ISetup).Setup(); } - public Vim.G3dNext.Attributes.SceneMeshIndexCountsAttribute MeshIndexCounts + public BFast ToBFast() { - get => Map.TryGetValue(Vim.G3dNext.Attributes.SceneMeshIndexCountsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.SceneMeshIndexCountsAttribute : default; - set => Map[Vim.G3dNext.Attributes.SceneMeshIndexCountsAttribute.AttributeName] = value as IAttribute; - } + var bfast = new BFast(); - public Vim.G3dNext.Attributes.SceneMeshVertexCountsAttribute MeshVertexCounts - { - get => Map.TryGetValue(Vim.G3dNext.Attributes.SceneMeshVertexCountsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.SceneMeshVertexCountsAttribute : default; - set => Map[Vim.G3dNext.Attributes.SceneMeshVertexCountsAttribute.AttributeName] = value as IAttribute; - } + bfast.SetArray("g3d:mesh:opaquesubmeshcount:0:int32:1", MeshOpaqueSubmeshCounts); + bfast.SetArray("g3d:mesh:submeshOffset:0:int32:1", MeshSubmeshOffset); + bfast.SetArray("g3d:submesh:indexoffset:0:int32:1", SubmeshIndexOffsets); + bfast.SetArray("g3d:submesh:vertexoffset:0:int32:1", SubmeshVertexOffsets); + bfast.SetArray("g3d:submesh:material:0:int32:1", SubmeshMaterials); + bfast.SetArray("g3d:vertex:position:0:float32:3", Positions); + bfast.SetArray("g3d:corner:index:0:int32:1", Indices); - public Vim.G3dNext.Attributes.SceneMeshOpaqueIndexCountsAttribute MeshOpaqueIndexCounts - { - get => Map.TryGetValue(Vim.G3dNext.Attributes.SceneMeshOpaqueIndexCountsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.SceneMeshOpaqueIndexCountsAttribute : default; - set => Map[Vim.G3dNext.Attributes.SceneMeshOpaqueIndexCountsAttribute.AttributeName] = value as IAttribute; + return bfast; } - public Vim.G3dNext.Attributes.SceneMeshOpaqueVertexCountsAttribute MeshOpaqueVertexCounts + public bool Equals(G3dChunk other ) { - get => Map.TryGetValue(Vim.G3dNext.Attributes.SceneMeshOpaqueVertexCountsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.SceneMeshOpaqueVertexCountsAttribute : default; - set => Map[Vim.G3dNext.Attributes.SceneMeshOpaqueVertexCountsAttribute.AttributeName] = value as IAttribute; + return MeshOpaqueSubmeshCounts.SafeEquals(other.MeshOpaqueSubmeshCounts) && + MeshSubmeshOffset.SafeEquals(other.MeshSubmeshOffset) && + SubmeshIndexOffsets.SafeEquals(other.SubmeshIndexOffsets) && + SubmeshVertexOffsets.SafeEquals(other.SubmeshVertexOffsets) && + SubmeshMaterials.SafeEquals(other.SubmeshMaterials) && + Positions.SafeEquals(other.Positions) && + Indices.SafeEquals(other.Indices); } - /// - public IAttribute GetAttribute(Type attributeType) - { - - - if (attributeType == typeof(Vim.G3dNext.Attributes.SceneChunkCountAttribute)) - return ChunkCount; - - - if (attributeType == typeof(Vim.G3dNext.Attributes.SceneInstanceMeshesAttribute)) - return InstanceMeshes; - - - if (attributeType == typeof(Vim.G3dNext.Attributes.SceneInstanceTransformDataAttribute)) - return InstanceTransformData; - - - if (attributeType == typeof(Vim.G3dNext.Attributes.SceneInstanceNodesAttribute)) - return InstanceNodes; - - if (attributeType == typeof(Vim.G3dNext.Attributes.SceneInstanceGroupsAttribute)) - return InstanceGroups; - - - if (attributeType == typeof(Vim.G3dNext.Attributes.SceneInstanceTagsAttribute)) - return InstanceTags; - - - if (attributeType == typeof(Vim.G3dNext.Attributes.SceneInstanceFlagsAttribute)) - return InstanceFlags; - - - if (attributeType == typeof(Vim.G3dNext.Attributes.SceneInstanceMinsAttribute)) - return InstanceMins; - - - if (attributeType == typeof(Vim.G3dNext.Attributes.SceneInstanceMaxsAttribute)) - return InstanceMaxs; - - - if (attributeType == typeof(Vim.G3dNext.Attributes.SceneMeshChunksAttribute)) - return MeshChunks; - - - if (attributeType == typeof(Vim.G3dNext.Attributes.SceneMeshChunkIndicesAttribute)) - return MeshChunkIndices; - - - if (attributeType == typeof(Vim.G3dNext.Attributes.SceneMeshIndexCountsAttribute)) - return MeshIndexCounts; - - - if (attributeType == typeof(Vim.G3dNext.Attributes.SceneMeshVertexCountsAttribute)) - return MeshVertexCounts; - - - if (attributeType == typeof(Vim.G3dNext.Attributes.SceneMeshOpaqueIndexCountsAttribute)) - return MeshOpaqueIndexCounts; - - - if (attributeType == typeof(Vim.G3dNext.Attributes.SceneMeshOpaqueVertexCountsAttribute)) - return MeshOpaqueVertexCounts; - - throw new ArgumentException("Type {attributeType.ToString()} is not supported."); - } - - public IAttribute MergeAttribute(string attributeName, IReadOnlyList otherCollections) + public G3dChunk Merge(G3dChunk other) { - var collections = otherCollections.Prepend(this).ToArray(); - switch (attributeName) - { - - case Vim.G3dNext.Attributes.SceneChunkCountAttribute.AttributeName: - { - // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); - } - - case Vim.G3dNext.Attributes.SceneInstanceMeshesAttribute.AttributeName: - { - // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); - } - - case Vim.G3dNext.Attributes.SceneInstanceTransformDataAttribute.AttributeName: - { - // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); - } - - case Vim.G3dNext.Attributes.SceneInstanceNodesAttribute.AttributeName: - { - // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); - } - - case Vim.G3dNext.Attributes.SceneInstanceGroupsAttribute.AttributeName: - { - // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); - } - - case Vim.G3dNext.Attributes.SceneInstanceTagsAttribute.AttributeName: - { - // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); - } - - case Vim.G3dNext.Attributes.SceneInstanceFlagsAttribute.AttributeName: - { - // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); - } - - case Vim.G3dNext.Attributes.SceneInstanceMinsAttribute.AttributeName: - { - // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); - } - - case Vim.G3dNext.Attributes.SceneInstanceMaxsAttribute.AttributeName: - { - // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); - } - - case Vim.G3dNext.Attributes.SceneMeshChunksAttribute.AttributeName: - { - // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); - } - - case Vim.G3dNext.Attributes.SceneMeshChunkIndicesAttribute.AttributeName: - { - // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); - } - - case Vim.G3dNext.Attributes.SceneMeshIndexCountsAttribute.AttributeName: - { - // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); - } - - case Vim.G3dNext.Attributes.SceneMeshVertexCountsAttribute.AttributeName: - { - // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); - } - - case Vim.G3dNext.Attributes.SceneMeshOpaqueIndexCountsAttribute.AttributeName: - { - // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); - } - - case Vim.G3dNext.Attributes.SceneMeshOpaqueVertexCountsAttribute.AttributeName: - { - // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); - } - - default: - throw new ArgumentException(nameof(attributeName)); - } + return new G3dChunk( + MeshOpaqueSubmeshCounts.MergeData(other.MeshOpaqueSubmeshCounts), + MeshSubmeshOffset.MergeIndices(other.MeshSubmeshOffset, Indices?.Length ?? 0), + SubmeshIndexOffsets.MergeIndices(other.SubmeshIndexOffsets, Indices?.Length ?? 0), + SubmeshVertexOffsets.MergeIndices(other.SubmeshVertexOffsets, Indices?.Length ?? 0), + SubmeshMaterials.MergeData(other.SubmeshMaterials), + Positions.MergeData(other.Positions), + Indices.MergeIndices(other.Indices, Positions?.Length ?? 0) + ); } public void Validate() { // Ensure all the indices are either -1 or within the bounds of the attributes they are indexing into. - + MeshSubmeshOffset?.ValidateIndex(Indices, "MeshSubmeshOffset"); + SubmeshIndexOffsets?.ValidateIndex(Indices, "SubmeshIndexOffsets"); + SubmeshVertexOffsets?.ValidateIndex(Indices, "SubmeshVertexOffsets"); + Indices?.ValidateIndex(Positions, "Indices"); } } - + // Please provide an explicit implementation in another partial class file. - public partial class G3dChunk : ISetup + public partial class G3dMaterials : ISetup { - public ChunkAttributeCollection Attributes; + public Vim.Math3d.Vector4[] MaterialColors; + public System.Single[] MaterialGlossiness; + public System.Single[] MaterialSmoothness; - public G3dChunk() : this(new ChunkAttributeCollection()) + public G3dMaterials( + Vim.Math3d.Vector4[] materialColors, + System.Single[] materialGlossiness, + System.Single[] materialSmoothness + ) { - // empty - } + MaterialColors = materialColors; + MaterialGlossiness = materialGlossiness; + MaterialSmoothness = materialSmoothness; - public G3dChunk(BFast bfast) : this(new ChunkAttributeCollection(bfast)) - { - // empty + (this as ISetup).Setup(); } - public G3dChunk(ChunkAttributeCollection attributes) + public G3dMaterials(BFast bfast) { - Attributes = attributes; + MaterialColors = bfast.GetArray("g3d:material:color:0:float32:4"); + MaterialGlossiness = bfast.GetArray("g3d:material:glossiness:0:float32:1"); + MaterialSmoothness = bfast.GetArray("g3d:material:smoothness:0:float32:1"); - // Method to implement in another partial class (this as ISetup).Setup(); } public BFast ToBFast() - => Attributes.ToBFast(); - - - public System.Int32[] MeshSubmeshOffset { - get => Attributes.MeshSubmeshOffset.TypedData; - set => Attributes.MeshSubmeshOffset.TypedData = value; - } + var bfast = new BFast(); - public System.Int32[] MeshOpaqueSubmeshCounts - { - get => Attributes.MeshOpaqueSubmeshCounts.TypedData; - set => Attributes.MeshOpaqueSubmeshCounts.TypedData = value; - } + bfast.SetArray("g3d:material:color:0:float32:4", MaterialColors); + bfast.SetArray("g3d:material:glossiness:0:float32:1", MaterialGlossiness); + bfast.SetArray("g3d:material:smoothness:0:float32:1", MaterialSmoothness); - public System.Int32[] SubmeshIndexOffsets - { - get => Attributes.SubmeshIndexOffsets.TypedData; - set => Attributes.SubmeshIndexOffsets.TypedData = value; + return bfast; } - public System.Int32[] SubmeshVertexOffsets + public bool Equals(G3dMaterials other ) { - get => Attributes.SubmeshVertexOffsets.TypedData; - set => Attributes.SubmeshVertexOffsets.TypedData = value; + return MaterialColors.SafeEquals(other.MaterialColors) && + MaterialGlossiness.SafeEquals(other.MaterialGlossiness) && + MaterialSmoothness.SafeEquals(other.MaterialSmoothness); } - public System.Int32[] SubmeshMaterials - { - get => Attributes.SubmeshMaterials.TypedData; - set => Attributes.SubmeshMaterials.TypedData = value; - } - public Vim.Math3d.Vector3[] Positions + public G3dMaterials Merge(G3dMaterials other) { - get => Attributes.Positions.TypedData; - set => Attributes.Positions.TypedData = value; + return new G3dMaterials( + MaterialColors.MergeData(other.MaterialColors), + MaterialGlossiness.MergeData(other.MaterialGlossiness), + MaterialSmoothness.MergeData(other.MaterialSmoothness) + ); } - public System.Int32[] Indices + public void Validate() { - get => Attributes.Indices.TypedData; - set => Attributes.Indices.TypedData = value; + // Ensure all the indices are either -1 or within the bounds of the attributes they are indexing into. + } } - - public partial class ChunkAttributeCollection : IAttributeCollection + // Please provide an explicit implementation in another partial class file. + public partial class G3dScene : ISetup { - public ChunkAttributeCollection() - { - // empty - } - - public ChunkAttributeCollection(BFast bfast) - { - this.ReadAttributes(bfast); - } - - public void ReadAttributes(BFast bfast) - { - foreach (var attribute in Map.Values) - { - attribute.ReadBFast(bfast); - } - } - - public IDictionary Map { get; } - = new Dictionary - { - [Vim.G3dNext.Attributes.ChunkMeshSubmeshOffsetAttribute.AttributeName] = new Vim.G3dNext.Attributes.ChunkMeshSubmeshOffsetAttribute(), - [Vim.G3dNext.Attributes.ChunkMeshOpaqueSubmeshCountsAttribute.AttributeName] = new Vim.G3dNext.Attributes.ChunkMeshOpaqueSubmeshCountsAttribute(), - [Vim.G3dNext.Attributes.ChunkSubmeshIndexOffsetsAttribute.AttributeName] = new Vim.G3dNext.Attributes.ChunkSubmeshIndexOffsetsAttribute(), - [Vim.G3dNext.Attributes.ChunkSubmeshVertexOffsetsAttribute.AttributeName] = new Vim.G3dNext.Attributes.ChunkSubmeshVertexOffsetsAttribute(), - [Vim.G3dNext.Attributes.ChunkSubmeshMaterialsAttribute.AttributeName] = new Vim.G3dNext.Attributes.ChunkSubmeshMaterialsAttribute(), - [Vim.G3dNext.Attributes.ChunkPositionsAttribute.AttributeName] = new Vim.G3dNext.Attributes.ChunkPositionsAttribute(), - [Vim.G3dNext.Attributes.ChunkIndicesAttribute.AttributeName] = new Vim.G3dNext.Attributes.ChunkIndicesAttribute(), - }; - - // Named Attributes. - - public Vim.G3dNext.Attributes.ChunkMeshSubmeshOffsetAttribute MeshSubmeshOffset - { - get => Map.TryGetValue(Vim.G3dNext.Attributes.ChunkMeshSubmeshOffsetAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.ChunkMeshSubmeshOffsetAttribute : default; - set => Map[Vim.G3dNext.Attributes.ChunkMeshSubmeshOffsetAttribute.AttributeName] = value as IAttribute; - } - - public Vim.G3dNext.Attributes.ChunkMeshOpaqueSubmeshCountsAttribute MeshOpaqueSubmeshCounts - { - get => Map.TryGetValue(Vim.G3dNext.Attributes.ChunkMeshOpaqueSubmeshCountsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.ChunkMeshOpaqueSubmeshCountsAttribute : default; - set => Map[Vim.G3dNext.Attributes.ChunkMeshOpaqueSubmeshCountsAttribute.AttributeName] = value as IAttribute; - } - - public Vim.G3dNext.Attributes.ChunkSubmeshIndexOffsetsAttribute SubmeshIndexOffsets - { - get => Map.TryGetValue(Vim.G3dNext.Attributes.ChunkSubmeshIndexOffsetsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.ChunkSubmeshIndexOffsetsAttribute : default; - set => Map[Vim.G3dNext.Attributes.ChunkSubmeshIndexOffsetsAttribute.AttributeName] = value as IAttribute; - } - - public Vim.G3dNext.Attributes.ChunkSubmeshVertexOffsetsAttribute SubmeshVertexOffsets - { - get => Map.TryGetValue(Vim.G3dNext.Attributes.ChunkSubmeshVertexOffsetsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.ChunkSubmeshVertexOffsetsAttribute : default; - set => Map[Vim.G3dNext.Attributes.ChunkSubmeshVertexOffsetsAttribute.AttributeName] = value as IAttribute; - } - - public Vim.G3dNext.Attributes.ChunkSubmeshMaterialsAttribute SubmeshMaterials - { - get => Map.TryGetValue(Vim.G3dNext.Attributes.ChunkSubmeshMaterialsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.ChunkSubmeshMaterialsAttribute : default; - set => Map[Vim.G3dNext.Attributes.ChunkSubmeshMaterialsAttribute.AttributeName] = value as IAttribute; - } - - public Vim.G3dNext.Attributes.ChunkPositionsAttribute Positions - { - get => Map.TryGetValue(Vim.G3dNext.Attributes.ChunkPositionsAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.ChunkPositionsAttribute : default; - set => Map[Vim.G3dNext.Attributes.ChunkPositionsAttribute.AttributeName] = value as IAttribute; - } + public System.Int32[] ChunkCount; + public System.Int32[] InstanceMeshes; + public Vim.Math3d.Matrix4x4[] InstanceTransformData; + public System.Int32[] InstanceNodes; + public System.Int32[] InstanceGroups; + public System.Int64[] InstanceTags; + public System.UInt16[] InstanceFlags; + public Vim.Math3d.Vector3[] InstanceMins; + public Vim.Math3d.Vector3[] InstanceMaxs; + public System.Int32[] MeshChunks; + public System.Int32[] MeshChunkIndices; + public System.Int32[] MeshVertexCounts; + public System.Int32[] MeshIndexCounts; + public System.Int32[] MeshOpaqueVertexCounts; + public System.Int32[] MeshOpaqueIndexCounts; + + public G3dScene( + System.Int32[] chunkCount, + System.Int32[] instanceMeshes, + Vim.Math3d.Matrix4x4[] instanceTransformData, + System.Int32[] instanceNodes, + System.Int32[] instanceGroups, + System.Int64[] instanceTags, + System.UInt16[] instanceFlags, + Vim.Math3d.Vector3[] instanceMins, + Vim.Math3d.Vector3[] instanceMaxs, + System.Int32[] meshChunks, + System.Int32[] meshChunkIndices, + System.Int32[] meshVertexCounts, + System.Int32[] meshIndexCounts, + System.Int32[] meshOpaqueVertexCounts, + System.Int32[] meshOpaqueIndexCounts + ) + { + ChunkCount = chunkCount; + InstanceMeshes = instanceMeshes; + InstanceTransformData = instanceTransformData; + InstanceNodes = instanceNodes; + InstanceGroups = instanceGroups; + InstanceTags = instanceTags; + InstanceFlags = instanceFlags; + InstanceMins = instanceMins; + InstanceMaxs = instanceMaxs; + MeshChunks = meshChunks; + MeshChunkIndices = meshChunkIndices; + MeshVertexCounts = meshVertexCounts; + MeshIndexCounts = meshIndexCounts; + MeshOpaqueVertexCounts = meshOpaqueVertexCounts; + MeshOpaqueIndexCounts = meshOpaqueIndexCounts; - public Vim.G3dNext.Attributes.ChunkIndicesAttribute Indices - { - get => Map.TryGetValue(Vim.G3dNext.Attributes.ChunkIndicesAttribute.AttributeName, out var attr) ? attr as Vim.G3dNext.Attributes.ChunkIndicesAttribute : default; - set => Map[Vim.G3dNext.Attributes.ChunkIndicesAttribute.AttributeName] = value as IAttribute; + (this as ISetup).Setup(); } - /// - public IAttribute GetAttribute(Type attributeType) - { - - - if (attributeType == typeof(Vim.G3dNext.Attributes.ChunkMeshSubmeshOffsetAttribute)) - return MeshSubmeshOffset; - - - if (attributeType == typeof(Vim.G3dNext.Attributes.ChunkMeshOpaqueSubmeshCountsAttribute)) - return MeshOpaqueSubmeshCounts; - - - if (attributeType == typeof(Vim.G3dNext.Attributes.ChunkSubmeshIndexOffsetsAttribute)) - return SubmeshIndexOffsets; - - - if (attributeType == typeof(Vim.G3dNext.Attributes.ChunkSubmeshVertexOffsetsAttribute)) - return SubmeshVertexOffsets; + public G3dScene(BFast bfast) + { + ChunkCount = bfast.GetArray("g3d:chunk:count:0:int32:1"); + InstanceMeshes = bfast.GetArray("g3d:instance:mesh:0:int32:1"); + InstanceTransformData = bfast.GetArray("g3d:instance:transform:0:float32:16"); + InstanceNodes = bfast.GetArray("g3d:instance:node:0:int32:1"); + InstanceGroups = bfast.GetArray("g3d:instance:group:0:int32:1"); + InstanceTags = bfast.GetArray("g3d:instance:tag:0:int64:1"); + InstanceFlags = bfast.GetArray("g3d:instance:flags:0:uint16:1"); + InstanceMins = bfast.GetArray("g3d:instance:min:0:float32:3"); + InstanceMaxs = bfast.GetArray("g3d:instance:max:0:float32:3"); + MeshChunks = bfast.GetArray("g3d:mesh:chunk:0:int32:1"); + MeshChunkIndices = bfast.GetArray("g3d:mesh:chunkindex:0:int32:1"); + MeshVertexCounts = bfast.GetArray("g3d:mesh:vertexcount:0:int32:1"); + MeshIndexCounts = bfast.GetArray("g3d:mesh:indexcount:0:int32:1"); + MeshOpaqueVertexCounts = bfast.GetArray("g3d:mesh:opaquevertexcount:0:int32:1"); + MeshOpaqueIndexCounts = bfast.GetArray("g3d:mesh:opaqueindexcount:0:int32:1"); - - if (attributeType == typeof(Vim.G3dNext.Attributes.ChunkSubmeshMaterialsAttribute)) - return SubmeshMaterials; - - - if (attributeType == typeof(Vim.G3dNext.Attributes.ChunkPositionsAttribute)) - return Positions; - - - if (attributeType == typeof(Vim.G3dNext.Attributes.ChunkIndicesAttribute)) - return Indices; - - throw new ArgumentException("Type {attributeType.ToString()} is not supported."); + (this as ISetup).Setup(); } - public IAttribute MergeAttribute(string attributeName, IReadOnlyList otherCollections) + public BFast ToBFast() { - var collections = otherCollections.Prepend(this).ToArray(); - switch (attributeName) - { - - case Vim.G3dNext.Attributes.ChunkMeshSubmeshOffsetAttribute.AttributeName: - { - // Index Attribute - return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); - } - - case Vim.G3dNext.Attributes.ChunkMeshOpaqueSubmeshCountsAttribute.AttributeName: - { - // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); - } - - case Vim.G3dNext.Attributes.ChunkSubmeshIndexOffsetsAttribute.AttributeName: - { - // Index Attribute - return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); - } - - case Vim.G3dNext.Attributes.ChunkSubmeshVertexOffsetsAttribute.AttributeName: - { - // Index Attribute - return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); - } - - case Vim.G3dNext.Attributes.ChunkSubmeshMaterialsAttribute.AttributeName: - { - // Index Attribute - return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); - } - - case Vim.G3dNext.Attributes.ChunkPositionsAttribute.AttributeName: - { - // Data Attribute - return collections.GetAttributesOfType().ToArray().MergeDataAttributes(); - } - - case Vim.G3dNext.Attributes.ChunkIndicesAttribute.AttributeName: - { - // Index Attribute - return collections.GetIndexedAttributesOfType().MergeIndexAttributes(); - } - - default: - throw new ArgumentException(nameof(attributeName)); - } + var bfast = new BFast(); + + bfast.SetArray("g3d:chunk:count:0:int32:1", ChunkCount); + bfast.SetArray("g3d:instance:mesh:0:int32:1", InstanceMeshes); + bfast.SetArray("g3d:instance:transform:0:float32:16", InstanceTransformData); + bfast.SetArray("g3d:instance:node:0:int32:1", InstanceNodes); + bfast.SetArray("g3d:instance:group:0:int32:1", InstanceGroups); + bfast.SetArray("g3d:instance:tag:0:int64:1", InstanceTags); + bfast.SetArray("g3d:instance:flags:0:uint16:1", InstanceFlags); + bfast.SetArray("g3d:instance:min:0:float32:3", InstanceMins); + bfast.SetArray("g3d:instance:max:0:float32:3", InstanceMaxs); + bfast.SetArray("g3d:mesh:chunk:0:int32:1", MeshChunks); + bfast.SetArray("g3d:mesh:chunkindex:0:int32:1", MeshChunkIndices); + bfast.SetArray("g3d:mesh:vertexcount:0:int32:1", MeshVertexCounts); + bfast.SetArray("g3d:mesh:indexcount:0:int32:1", MeshIndexCounts); + bfast.SetArray("g3d:mesh:opaquevertexcount:0:int32:1", MeshOpaqueVertexCounts); + bfast.SetArray("g3d:mesh:opaqueindexcount:0:int32:1", MeshOpaqueIndexCounts); + + return bfast; + } + + public bool Equals(G3dScene other ) + { + return ChunkCount.SafeEquals(other.ChunkCount) && + InstanceMeshes.SafeEquals(other.InstanceMeshes) && + InstanceTransformData.SafeEquals(other.InstanceTransformData) && + InstanceNodes.SafeEquals(other.InstanceNodes) && + InstanceGroups.SafeEquals(other.InstanceGroups) && + InstanceTags.SafeEquals(other.InstanceTags) && + InstanceFlags.SafeEquals(other.InstanceFlags) && + InstanceMins.SafeEquals(other.InstanceMins) && + InstanceMaxs.SafeEquals(other.InstanceMaxs) && + MeshChunks.SafeEquals(other.MeshChunks) && + MeshChunkIndices.SafeEquals(other.MeshChunkIndices) && + MeshVertexCounts.SafeEquals(other.MeshVertexCounts) && + MeshIndexCounts.SafeEquals(other.MeshIndexCounts) && + MeshOpaqueVertexCounts.SafeEquals(other.MeshOpaqueVertexCounts) && + MeshOpaqueIndexCounts.SafeEquals(other.MeshOpaqueIndexCounts); + } + + + public G3dScene Merge(G3dScene other) + { + return new G3dScene( + ChunkCount.MergeData(other.ChunkCount), + InstanceMeshes.MergeData(other.InstanceMeshes), + InstanceTransformData.MergeData(other.InstanceTransformData), + InstanceNodes.MergeData(other.InstanceNodes), + InstanceGroups.MergeData(other.InstanceGroups), + InstanceTags.MergeData(other.InstanceTags), + InstanceFlags.MergeData(other.InstanceFlags), + InstanceMins.MergeData(other.InstanceMins), + InstanceMaxs.MergeData(other.InstanceMaxs), + MeshChunks.MergeData(other.MeshChunks), + MeshChunkIndices.MergeData(other.MeshChunkIndices), + MeshVertexCounts.MergeData(other.MeshVertexCounts), + MeshIndexCounts.MergeData(other.MeshIndexCounts), + MeshOpaqueVertexCounts.MergeData(other.MeshOpaqueVertexCounts), + MeshOpaqueIndexCounts.MergeData(other.MeshOpaqueIndexCounts) + ); } public void Validate() { // Ensure all the indices are either -1 or within the bounds of the attributes they are indexing into. - - { - var maxIndex = GetAttribute(MeshSubmeshOffset.IndexInto).Data.Length - 1; - for (var i = 0; i < MeshSubmeshOffset.TypedData.Length; ++i) - { - var index = MeshSubmeshOffset.TypedData[i]; - - if (index == -1) - continue; // no relation. - - if (index < -1 || index > maxIndex) - throw new Exception($"Index out of range in Vim.G3dNext.Attributes.ChunkMeshSubmeshOffsetAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); - } - } - - { - var maxIndex = GetAttribute(SubmeshIndexOffsets.IndexInto).Data.Length - 1; - for (var i = 0; i < SubmeshIndexOffsets.TypedData.Length; ++i) - { - var index = SubmeshIndexOffsets.TypedData[i]; - - if (index == -1) - continue; // no relation. - - if (index < -1 || index > maxIndex) - throw new Exception($"Index out of range in Vim.G3dNext.Attributes.ChunkSubmeshIndexOffsetsAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); - } - } - - { - var maxIndex = GetAttribute(SubmeshVertexOffsets.IndexInto).Data.Length - 1; - for (var i = 0; i < SubmeshVertexOffsets.TypedData.Length; ++i) - { - var index = SubmeshVertexOffsets.TypedData[i]; - - if (index == -1) - continue; // no relation. - - if (index < -1 || index > maxIndex) - throw new Exception($"Index out of range in Vim.G3dNext.Attributes.ChunkSubmeshVertexOffsetsAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); - } - } - - { - var maxIndex = GetAttribute(SubmeshMaterials.IndexInto).Data.Length - 1; - for (var i = 0; i < SubmeshMaterials.TypedData.Length; ++i) - { - var index = SubmeshMaterials.TypedData[i]; - - if (index == -1) - continue; // no relation. - - if (index < -1 || index > maxIndex) - throw new Exception($"Index out of range in Vim.G3dNext.Attributes.ChunkSubmeshMaterialsAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); - } - } - - { - var maxIndex = GetAttribute(Indices.IndexInto).Data.Length - 1; - for (var i = 0; i < Indices.TypedData.Length; ++i) - { - var index = Indices.TypedData[i]; - - if (index == -1) - continue; // no relation. - - if (index < -1 || index > maxIndex) - throw new Exception($"Index out of range in Vim.G3dNext.Attributes.ChunkIndicesAttribute at position {i}. Expected either -1 for no relation, or a maximum of {maxIndex} but got {index}"); - } - } + } } + } diff --git a/src/cs/g3d/Vim.G3dNext.Attributes/G3dMaterials.cs b/src/cs/g3d/Vim.G3dNext.Attributes/G3dMaterials.cs index 4e9ef39a..6515edf8 100644 --- a/src/cs/g3d/Vim.G3dNext.Attributes/G3dMaterials.cs +++ b/src/cs/g3d/Vim.G3dNext.Attributes/G3dMaterials.cs @@ -9,12 +9,12 @@ void ISetup.Setup() // empty } - public G3dMaterials ReadFromVim(G3dVim vim) + + public G3dMaterials(G3dVim vim) { MaterialColors = vim.MaterialColors; MaterialGlossiness = vim.MaterialGlossiness; MaterialSmoothness = vim.MaterialSmoothness; - return this; } } } diff --git a/src/cs/g3d/Vim.G3dNext.Attributes/MaterialsAttributes.cs b/src/cs/g3d/Vim.G3dNext.Attributes/MaterialsAttributes.cs deleted file mode 100644 index e72d67f1..00000000 --- a/src/cs/g3d/Vim.G3dNext.Attributes/MaterialsAttributes.cs +++ /dev/null @@ -1,23 +0,0 @@ -using Vim.Math3d; - -namespace Vim.G3dNext.Attributes -{ - [AttributeCollection( - typeof(MaterialColorsAttribute), - typeof(MaterialGlossinessAttribute), - typeof(MaterialSmoothnessAttribute) - )] - public partial class MaterialsAttributeCollection // : IAttributeCollection - { - - } - - [AttributeDescriptor("g3d:material:color:0:float32:4", AttributeType.Data, ArrayType = typeof(Vector4))] - public partial class MaterialColorsAttribute { } - - [AttributeDescriptor("g3d:material:glossiness:0:float32:1", AttributeType.Data)] - public partial class MaterialGlossinessAttribute { } - - [AttributeDescriptor("g3d:material:smoothness:0:float32:1", AttributeType.Data)] - public partial class MaterialSmoothnessAttribute { } -} diff --git a/src/cs/g3d/Vim.G3dNext.Attributes/MeshAttributes.cs b/src/cs/g3d/Vim.G3dNext.Attributes/MeshAttributes.cs deleted file mode 100644 index 5b99ec9b..00000000 --- a/src/cs/g3d/Vim.G3dNext.Attributes/MeshAttributes.cs +++ /dev/null @@ -1,47 +0,0 @@ -using Vim.Math3d; - -namespace Vim.G3dNext.Attributes -{ - [AttributeCollection( - typeof(ChunkMeshSubmeshOffsetAttribute), - typeof(ChunkMeshOpaqueSubmeshCountsAttribute), - typeof(ChunkSubmeshIndexOffsetsAttribute), - typeof(ChunkSubmeshVertexOffsetsAttribute), - typeof(ChunkSubmeshMaterialsAttribute), - typeof(ChunkPositionsAttribute), - typeof(ChunkIndicesAttribute) - )] - public partial class ChunkAttributeCollection // : IAttributeCollection - { - - } - - [AttributeDescriptor("Chunk", "g3d:mesh:opaquesubmeshcount:0:int32:1", AttributeType.Data)] - public partial class ChunkMeshOpaqueSubmeshCountsAttribute { } - - [AttributeDescriptor("Chunk", "g3d:mesh:submeshOffset:0:int32:1", AttributeType.Index, IndexInto = typeof(ChunkIndicesAttribute))] - public partial class ChunkMeshSubmeshOffsetAttribute { } - - [AttributeDescriptor("Chunk", "g3d:submesh:indexoffset:0:int32:1", AttributeType.Index, IndexInto = typeof(ChunkIndicesAttribute))] - public partial class ChunkSubmeshIndexOffsetsAttribute { } - - [AttributeDescriptor("Chunk", "g3d:submesh:vertexoffset:0:int32:1", AttributeType.Index, IndexInto = typeof(ChunkIndicesAttribute))] - public partial class ChunkSubmeshVertexOffsetsAttribute { } - - [AttributeDescriptor("Chunk", "g3d:submesh:material:0:int32:1", AttributeType.Index)] - public partial class ChunkSubmeshMaterialsAttribute { } - - [AttributeDescriptor("Chunk", "g3d:vertex:position:0:float32:3", AttributeType.Data, ArrayType = typeof(Vector3))] - public partial class ChunkPositionsAttribute { } - - [AttributeDescriptor("Chunk", "g3d:corner:index:0:int32:1", AttributeType.Index, IndexInto = typeof(ChunkPositionsAttribute))] - public partial class ChunkIndicesAttribute { } -} - - -public enum MeshSection -{ - All, - Opaque, - Transparent -} diff --git a/src/cs/g3d/Vim.G3dNext.Attributes/SceneAttributes.cs b/src/cs/g3d/Vim.G3dNext.Attributes/SceneAttributes.cs deleted file mode 100644 index 3999e558..00000000 --- a/src/cs/g3d/Vim.G3dNext.Attributes/SceneAttributes.cs +++ /dev/null @@ -1,71 +0,0 @@ -using Vim.Math3d; - -namespace Vim.G3dNext.Attributes -{ - [AttributeCollection( - typeof(SceneChunkCountAttribute), - typeof(SceneInstanceMeshesAttribute), - typeof(SceneInstanceTransformDataAttribute), - typeof(SceneInstanceNodesAttribute), - typeof(SceneInstanceGroupsAttribute), - typeof(SceneInstanceTagsAttribute), - typeof(SceneInstanceFlagsAttribute), - typeof(SceneInstanceMinsAttribute), - typeof(SceneInstanceMaxsAttribute), - typeof(SceneMeshChunksAttribute), - typeof(SceneMeshChunkIndicesAttribute), - typeof(SceneMeshIndexCountsAttribute), - typeof(SceneMeshVertexCountsAttribute), - typeof(SceneMeshOpaqueIndexCountsAttribute), - typeof(SceneMeshOpaqueVertexCountsAttribute) - )] - public partial class SceneAttributeCollection // : IAttributeCollection - { - - } - - [AttributeDescriptor("Scene", "g3d:chunk:count:0:int32:1", AttributeType.Data)] - public partial class SceneChunkCountAttribute { } - - [AttributeDescriptor("Scene", "g3d:instance:mesh:0:int32:1", AttributeType.Data)] - public partial class SceneInstanceMeshesAttribute { } - - [AttributeDescriptor("Scene", "g3d:instance:transform:0:float32:16", AttributeType.Data, ArrayType = typeof(Matrix4x4))] - public partial class SceneInstanceTransformDataAttribute { } - - [AttributeDescriptor("Scene", "g3d:instance:node:0:int32:1", AttributeType.Data)] - public partial class SceneInstanceNodesAttribute { } - - [AttributeDescriptor("Scene", "g3d:instance:group:0:int32:1", AttributeType.Data)] - public partial class SceneInstanceGroupsAttribute { } - - [AttributeDescriptor("Scene", "g3d:instance:tag:0:int64:1", AttributeType.Data)] - public partial class SceneInstanceTagsAttribute { } - - [AttributeDescriptor("Scene", "g3d:instance:flags:0:uint16:1", AttributeType.Data)] - public partial class SceneInstanceFlagsAttribute { } - - [AttributeDescriptor("Scene", "g3d:instance:min:0:float32:3", AttributeType.Data, ArrayType = typeof(Vector3))] - public partial class SceneInstanceMinsAttribute { } - - [AttributeDescriptor("Scene", "g3d:instance:max:0:float32:3", AttributeType.Data, ArrayType = typeof(Vector3))] - public partial class SceneInstanceMaxsAttribute { } - - [AttributeDescriptor("Scene", "g3d:mesh:chunk:0:int32:1", AttributeType.Data)] - public partial class SceneMeshChunksAttribute { } - - [AttributeDescriptor("Scene", "g3d:mesh:chunkindex:0:int32:1", AttributeType.Data)] - public partial class SceneMeshChunkIndicesAttribute { } - - [AttributeDescriptor("Scene", "g3d:mesh:vertexcount:0:int32:1", AttributeType.Data)] - public partial class SceneMeshVertexCountsAttribute { } - - [AttributeDescriptor("Scene", "g3d:mesh:indexcount:0:int32:1", AttributeType.Data)] - public partial class SceneMeshIndexCountsAttribute { } - - [AttributeDescriptor("Scene", "g3d:mesh:opaquevertexcount:0:int32:1", AttributeType.Data)] - public partial class SceneMeshOpaqueVertexCountsAttribute { } - - [AttributeDescriptor("Scene", "g3d:mesh:opaqueindexcount:0:int32:1", AttributeType.Data)] - public partial class SceneMeshOpaqueIndexCountsAttribute { } -} diff --git a/src/cs/g3d/Vim.G3dNext.Attributes/VimAttributes.cs b/src/cs/g3d/Vim.G3dNext.Attributes/VimAttributes.cs deleted file mode 100644 index 95586801..00000000 --- a/src/cs/g3d/Vim.G3dNext.Attributes/VimAttributes.cs +++ /dev/null @@ -1,75 +0,0 @@ -using Vim.Math3d; - -namespace Vim.G3dNext.Attributes -{ - [AttributeCollection( - typeof(VimPositionsAttribute), - typeof(VimIndicesAttribute), - typeof(VimInstanceTransformsAttribute), - typeof(VimInstanceParentsAttribute), - typeof(VimInstanceFlagsAttribute), - typeof(VimInstanceMeshesAttribute), - typeof(VimMeshSubmeshOffsetsAttribute), - typeof(VimSubmeshIndexOffsetsAttribute), - typeof(VimSubmeshMaterialsAttribute), - typeof(VimMaterialColorsAttribute), - typeof(VimMaterialGlossinessAttribute), - typeof(VimMaterialSmoothnessAttribute), - typeof(VimShapeVerticesAttribute), - typeof(VimShapeVertexOffsetsAttribute), - typeof(VimShapeColorsAttribute), - typeof(VimShapeWidthsAttribute) - )] - public partial class VimAttributeCollection // : IAttributeCollection - { - - } - - [AttributeDescriptor("Vim", "g3d:vertex:position:0:float32:3", AttributeType.Data, ArrayType = typeof(Vector3))] - public partial class VimPositionsAttribute { } - - [AttributeDescriptor("Vim", "g3d:corner:index:0:int32:1", AttributeType.Index, IndexInto = typeof(VimPositionsAttribute))] - public partial class VimIndicesAttribute { } - - [AttributeDescriptor("Vim", "g3d:instance:transform:0:float32:16", AttributeType.Data, ArrayType = typeof(Matrix4x4))] - public partial class VimInstanceTransformsAttribute { } - - [AttributeDescriptor("Vim", "g3d:instance:parent:0:int32:1", AttributeType.Index, IndexInto = typeof(VimInstanceTransformsAttribute))] - public partial class VimInstanceParentsAttribute { } - - [AttributeDescriptor("Vim", "g3d:instance:flags:0:uint16:1", AttributeType.Data)] - public partial class VimInstanceFlagsAttribute { } - - [AttributeDescriptor("Vim", "g3d:instance:mesh:0:int32:1", AttributeType.Index, IndexInto = typeof(VimMeshSubmeshOffsetsAttribute))] - public partial class VimInstanceMeshesAttribute { } - - [AttributeDescriptor("Vim", "g3d:mesh:submeshoffset:0:int32:1", AttributeType.Index, IndexInto = typeof(VimSubmeshIndexOffsetsAttribute))] - public partial class VimMeshSubmeshOffsetsAttribute { } - - [AttributeDescriptor("Vim", "g3d:submesh:indexoffset:0:int32:1", AttributeType.Index, IndexInto = typeof(VimIndicesAttribute))] - public partial class VimSubmeshIndexOffsetsAttribute { } - - [AttributeDescriptor("Vim", "g3d:submesh:material:0:int32:1", AttributeType.Index, IndexInto = typeof(VimMaterialColorsAttribute))] - public partial class VimSubmeshMaterialsAttribute { } - - [AttributeDescriptor("Vim", "g3d:material:color:0:float32:4", AttributeType.Data, ArrayType = typeof(Vector4))] - public partial class VimMaterialColorsAttribute { } - - [AttributeDescriptor("Vim", "g3d:material:glossiness:0:float32:1", AttributeType.Data)] - public partial class VimMaterialGlossinessAttribute { } - - [AttributeDescriptor("Vim", "g3d:material:smoothness:0:float32:1", AttributeType.Data)] - public partial class VimMaterialSmoothnessAttribute { } - - [AttributeDescriptor("Vim", "g3d:shapevertex:position:0:float32:3", AttributeType.Data, ArrayType = typeof(Vector3))] - public partial class VimShapeVerticesAttribute { } - - [AttributeDescriptor("Vim", "g3d:shape:vertexoffset:0:int32:1", AttributeType.Index, IndexInto = typeof(VimShapeVerticesAttribute))] - public partial class VimShapeVertexOffsetsAttribute { } - - [AttributeDescriptor("Vim", "g3d:shape:color:0:float32:4", AttributeType.Data, ArrayType = typeof(Vector4))] - public partial class VimShapeColorsAttribute { } - - [AttributeDescriptor("Vim", "g3d:shape:width:0:float32:1", AttributeType.Data)] - public partial class VimShapeWidthsAttribute { } -} diff --git a/src/cs/g3d/Vim.G3dNext.CodeGen/CodeBuilder.cs b/src/cs/g3d/Vim.G3dNext.CodeGen/CodeBuilder.cs index b3bf8158..8dd3283a 100644 --- a/src/cs/g3d/Vim.G3dNext.CodeGen/CodeBuilder.cs +++ b/src/cs/g3d/Vim.G3dNext.CodeGen/CodeBuilder.cs @@ -1,4 +1,5 @@ -using System.Linq; +using System.Collections.Generic; +using System.Linq; using System.Text; namespace Vim.G3dNext.CodeGen @@ -15,6 +16,14 @@ public CodeBuilder AppendRaw(string line) return this; } + public CodeBuilder AppendLines(IEnumerable lines) + { + foreach(var l in lines) { + AppendLine(l); + } + return this; + } + public CodeBuilder AppendLine(string line = "") { var openBraces = line.Count(c => c == '{'); diff --git a/src/cs/g3d/Vim.G3dNext.CodeGen/Definitions.cs b/src/cs/g3d/Vim.G3dNext.CodeGen/Definitions.cs new file mode 100644 index 00000000..7df037ee --- /dev/null +++ b/src/cs/g3d/Vim.G3dNext.CodeGen/Definitions.cs @@ -0,0 +1,62 @@ +using Vim.Math3d; + +namespace Vim.G3dNext.CodeGen +{ + internal class Definitions + { + public static G3dEntity[] GetEntities() + { + return new G3dEntity[] { vim, mesh, materials, scene }; + } + + public static G3dEntity vim = new G3dEntity("G3dVim") + .Index("Indices", "g3d:corner:index:0:int32:1", "Positions") + .Data("Positions", "g3d:vertex:position:0:float32:3") + .Data("InstanceTransforms", "g3d:instance:transform:0:float32:16") + .Index("InstanceParents", "g3d:instance:parent:0:int32:1", "InstanceTransforms") + .Data("InstanceFlags", "g3d:instance:flags:0:uint16:1") + .Index("InstanceMeshes", "g3d:instance:mesh:0:int32:1", "MeshSubmeshOffsets") + .Index("MeshSubmeshOffsets", "g3d:mesh:submeshoffset:0:int32:1", "SubmeshIndexOffsets") + .Index("SubmeshIndexOffsets", "g3d:submesh:indexoffset:0:int32:1", "Indices") + .Index("SubmeshMaterials", "g3d:submesh:material:0:int32:1", "MaterialColors") + .Data("MaterialColors", "g3d:material:color:0:float32:4") + .Data("MaterialGlossiness", "g3d:material:glossiness:0:float32:1") + .Data("MaterialSmoothness", "g3d:material:smoothness:0:float32:1") + .Data("ShapeVertices", "g3d:shapevertex:position:0:float32:3") + .Index("ShapeVertexOffsets", "g3d:shape:vertexoffset:0:int32:1", "ShapeVertices") + .Data("ShapeColors", "g3d:shape:color:0:float32:4") + .Data("ShapeWidths", "g3d:shape:width:0:float32:1"); + + public static G3dEntity scene = new G3dEntity("G3dScene") + .Data("ChunkCount", "g3d:chunk:count:0:int32:1") + .Data("InstanceMeshes", "g3d:instance:mesh:0:int32:1") + .Data("InstanceTransformData", "g3d:instance:transform:0:float32:16") + .Data("InstanceNodes", "g3d:instance:node:0:int32:1") + .Data("InstanceGroups", "g3d:instance:group:0:int32:1") + .Data("InstanceTags", "g3d:instance:tag:0:int64:1") + .Data("InstanceFlags", "g3d:instance:flags:0:uint16:1") + .Data("InstanceMins", "g3d:instance:min:0:float32:3") + .Data("InstanceMaxs", "g3d:instance:max:0:float32:3") + .Data("MeshChunks", "g3d:mesh:chunk:0:int32:1") + .Data("MeshChunkIndices", "g3d:mesh:chunkindex:0:int32:1") + .Data("MeshVertexCounts", "g3d:mesh:vertexcount:0:int32:1") + .Data("MeshIndexCounts", "g3d:mesh:indexcount:0:int32:1") + .Data("MeshOpaqueVertexCounts", "g3d:mesh:opaquevertexcount:0:int32:1") + .Data("MeshOpaqueIndexCounts", "g3d:mesh:opaqueindexcount:0:int32:1"); + + public static G3dEntity materials = new G3dEntity("G3dMaterials") + .Data("MaterialColors", "g3d:material:color:0:float32:4") + .Data("MaterialGlossiness", "g3d:material:glossiness:0:float32:1") + .Data("MaterialSmoothness", "g3d:material:smoothness:0:float32:1"); + + + public static G3dEntity mesh = new G3dEntity("G3dChunk") + .Data("MeshOpaqueSubmeshCounts", "g3d:mesh:opaquesubmeshcount:0:int32:1") + .Index("MeshSubmeshOffset", "g3d:mesh:submeshOffset:0:int32:1", "Indices") + .Index("SubmeshIndexOffsets", "g3d:submesh:indexoffset:0:int32:1", "Indices") + .Index("SubmeshVertexOffsets", "g3d:submesh:vertexoffset:0:int32:1", "Indices") + .Index("SubmeshMaterials", "g3d:submesh:material:0:int32:1") + .Data("Positions", "g3d:vertex:position:0:float32:3") + .Index("Indices", "g3d:corner:index:0:int32:1", "Positions"); + } +} diff --git a/src/cs/g3d/Vim.G3dNext.CodeGen/G3dAttributeCollectionGenerator.cs b/src/cs/g3d/Vim.G3dNext.CodeGen/G3dAttributeCollectionGenerator.cs index c75c6562..7707e1ed 100644 --- a/src/cs/g3d/Vim.G3dNext.CodeGen/G3dAttributeCollectionGenerator.cs +++ b/src/cs/g3d/Vim.G3dNext.CodeGen/G3dAttributeCollectionGenerator.cs @@ -1,12 +1,9 @@ using System; -using System.Collections.Generic; using System.IO; using System.Linq; -using System.Reflection; namespace Vim.G3dNext.CodeGen { - public static class G3dAttributeCollectionGenerator { public static void WriteDocument(string filePath) @@ -15,18 +12,13 @@ public static void WriteDocument(string filePath) { var cb = new CodeBuilder(); - cb.AppendLine("// AUTO-GENERATED FILE, DO NOT MODIFY WACKO3."); + cb.AppendLine("// AUTO-GENERATED FILE, DO NOT MODIFY."); cb.AppendLine("// ReSharper disable All"); - cb.AppendLine("using System;"); - cb.AppendLine("using System.IO;"); - cb.AppendLine("using System.Collections.Generic;"); - cb.AppendLine("using System.Linq;"); cb.AppendLine("using Vim.BFastNS;"); cb.AppendLine(); cb.AppendLine("namespace Vim.G3dNext.Attributes"); cb.AppendLine("{"); - WriteVimG3dAttributes(cb); - WriteVimG3dAttributeCollections(cb); + WriteEntities(cb); cb.AppendLine("}"); var content = cb.ToString(); File.WriteAllText(filePath, content); @@ -38,292 +30,104 @@ public static void WriteDocument(string filePath) } } - public static IEnumerable GetAllClassesWithAttribute() where T: Attribute - { - // Load the assembly containing the classes you want to examine - var assembly = Assembly.GetExecutingAssembly(); - - // Find all the types in the assembly that have the MyAttribute attribute - return assembly.GetTypes() - .Where(type => type.GetCustomAttributes(false).Any()); - } - - public static void WriteVimG3dAttributes(CodeBuilder cb) - { - var adClasses = GetAllClassesWithAttribute(); - - foreach (var adClass in adClasses) - WriteVimG3dAttribute(cb, adClass); - } - - public static string GetTypedDataType(this AttributeDescriptorAttribute ada) - { - if (ada.ArrayType != null) - return ada.ArrayType.ToString(); - - if (!AttributeDescriptor.TryParse(ada.Name, out var ad)) - throw new Exception($"Could not parse attribute name {ada.Name}"); - - return ad.DataType.GetManagedType().ToString(); - } - - public static void WriteVimG3dAttribute(CodeBuilder cb, Type adClass) - { - var className = adClass.Name; - var ada = adClass.GetCustomAttribute(); - if (ada == null) - throw new Exception($"No attribute of type {nameof(AttributeDescriptorAttribute)} found on {className}"); - - var attributeName = ada.Name; - if (!AttributeDescriptor.TryParse(attributeName, out var ad)) - throw new Exception($"Invalid attribute descriptor: {attributeName}"); - - var typedDataType = ada.GetTypedDataType(); - var attributeType = ada.AttributeType; - var indexInto = ada.IndexInto; - - cb.AppendLine($@" - public partial class {className} : {nameof(IAttribute)}<{typedDataType}> - {{ - public const string AttributeName = ""{attributeName}""; - - public string Name - => AttributeName; - - public int Count => TypedData?.Length ?? 0; - - public void AddTo(BFast bfast) - {{ - if(TypedData != null) - {{ - bfast.SetArray(Name, TypedData); - }} - }} - - public void ReadBFast(BFast bfast) - {{ - TypedData = bfast.GetArray<{typedDataType}>(""{attributeName}""); - }} - - public {nameof(IAttributeDescriptor)} {nameof(AttributeDescriptor)} {{ get; }} - = new {nameof(AttributeDescriptor)}(AttributeName); - - public {nameof(AttributeType)} {nameof(IAttribute.AttributeType)} {{ get; }} - = {nameof(AttributeType)}.{attributeType}; - - public Type {nameof(IAttribute.IndexInto)} {{ get; }} - = {(indexInto == default ? "null" : $"typeof({indexInto})")}; - - public {typedDataType}[] TypedData {{ get; set; }} - = Array.Empty<{typedDataType}>(); - - public Array Data - => TypedData; - - public void Write(Stream stream) - {{ - if (TypedData == null || TypedData.Length == 0) - return; - stream.Write(TypedData); - }} - }}"); - } - - public static void WriteVimG3dAttributeCollections(CodeBuilder cb) + public static void WriteEntities(CodeBuilder cb) { - var acClasses = GetAllClassesWithAttribute(); - - foreach (var acClass in acClasses) - WriteVimG3dAttributeCollection(cb, acClass); + foreach(var entity in Definitions.GetEntities()) + { + cb.AppendLine(EntityToCode(entity)); + } } - public static void WriteVimG3dAttributeCollection(CodeBuilder cb, Type acClass) + public static string EntityToCode(G3dEntity entity) { - var className = acClass.Name; - - var ac = acClass.GetCustomAttribute(); - if (ac == null) - throw new Exception($"No attribute of type {(nameof(AttributeCollectionAttribute))} found on {className}"); - - var attributeClasses = ac.AttributeClasses; - var g3dName = "G3d" + className.Replace("AttributeCollection", ""); - - cb.AppendLine($@" - // Please provide an explicit implementation in another partial class file. - public partial class {g3dName} : ISetup + return $@"// Please provide an explicit implementation in another partial class file. + public partial class {entity.ClassName} : ISetup {{ - public {className} Attributes; + {string.Join("\n \t\t", entity.Buffers.Select(b => + { + return $"public {b.ValueType}[] {b.MemberName};"; + })).TrimStart()} - public {g3dName}() : this(new {className}()) + public {entity.ClassName}( + {string.Join(", \n \t\t\t", entity.Buffers.Select(b => + { + return $"{b.ValueType}[] {b.ArgumentName}"; + })).TrimStart()} + ) {{ - // empty - }} + {string.Join("\n \t\t\t", entity.Buffers.Select(b => + { + return $"{b.MemberName} = {b.ArgumentName};"; + })).TrimStart()} - public {g3dName}(BFast bfast) : this(new {className}(bfast)) - {{ - // empty + (this as ISetup).Setup(); }} - public {g3dName}({className} attributes) + public {entity.ClassName}(BFast bfast) {{ - Attributes = attributes; + {string.Join("\n \t\t\t", entity.Buffers.Select(b => + { + return $"{b.MemberName} = bfast.GetArray<{b.ValueType}>(\"{b.BufferName}\");"; + })).TrimStart()} - // Method to implement in another partial class (this as ISetup).Setup(); }} public BFast ToBFast() - => Attributes.ToBFast(); - - { - string.Join(Environment.NewLine, attributeClasses.Select(c => - { - var attribute = c.GetCustomAttribute(); - var typedDataType = attribute.GetTypedDataType(); - var name = attribute.FormatClassName(c.Name); - return $@" - public {typedDataType}[] {attribute.FormatClassName(name)} {{ - get => Attributes.{name}.TypedData; - set => Attributes.{name}.TypedData = value; - }}";})) - } - }} -"); - - - cb.AppendLine($@" - public partial class {className} : IAttributeCollection - {{ - public {className}() - {{ - // empty - }} + var bfast = new BFast(); - public {className}(BFast bfast) - {{ - this.ReadAttributes(bfast); - }} + {string.Join("\n \t\t\t", entity.Buffers.Select(b => + { + return $"bfast.SetArray<{b.ValueType}>(\"{b.BufferName}\", {b.MemberName});"; + })).TrimStart()} - public void ReadAttributes(BFast bfast) - {{ - foreach (var attribute in Map.Values) - {{ - attribute.ReadBFast(bfast); - }} + return bfast; }} - public IDictionary Map {{ get; }} - = new Dictionary - {{ -{string.Join(Environment.NewLine, attributeClasses.Select(c => - $" [{c}.AttributeName] = new {c}(),"))} - }}; - - // Named Attributes. -{string.Join(Environment.NewLine, attributeClasses.Select(c => - { - var attribute = c.GetCustomAttribute(); - var name = attribute.FormatClassName(c.Name); - return $@" - public {c} {name} - {{ - get => Map.TryGetValue({c}.AttributeName, out var attr) ? attr as {c} : default; - set => Map[{c}.AttributeName] = value as IAttribute; - }}"; - }) -)} - - /// - public IAttribute GetAttribute(Type attributeType) + public bool Equals({entity.ClassName} other ) {{ -{string.Join(Environment.NewLine, attributeClasses.Select(c => { - var attribute = c.GetCustomAttribute(); - var name = attribute.FormatClassName(c.Name); - return $@" - - if (attributeType == typeof({c})) - return {name};"; - - }))} - - throw new ArgumentException(""Type {{attributeType.ToString()}} is not supported.""); + return {string.Join(" && \n \t\t\t", entity.Buffers.Select(b => + { + return $"{b.MemberName}.SafeEquals(other.{b.MemberName})"; + }))}; }} - public IAttribute MergeAttribute(string attributeName, IReadOnlyList otherCollections) + public {entity.ClassName} Merge({entity.ClassName} other) {{ - var collections = otherCollections.Prepend(this).ToArray(); - switch (attributeName) - {{ -{string.Join(Environment.NewLine, attributeClasses.Select(c => { - var ada = c.GetCustomAttribute(); - var typedDataType = ada.GetTypedDataType(); - string caseBody = null; - switch (ada.AttributeType) - { - case AttributeType.Singleton: - caseBody = $@"// Singleton Attribute (no merging) - return {c.Name};"; - break; - case AttributeType.Data: - caseBody = $@"// Data Attribute - return collections.{nameof(AttributeCollectionExtensions.GetAttributesOfType)}<{c}>().ToArray().{nameof(AttributeExtensions.MergeDataAttributes)}<{c}, {typedDataType}>();"; - break; - case AttributeType.Index: - caseBody = $@"// Index Attribute - return collections.{nameof(AttributeCollectionExtensions.GetIndexedAttributesOfType)}<{c}>().{nameof(AttributeExtensions.MergeIndexAttributes)}();"; - break; - default: - throw new ArgumentOutOfRangeException(nameof(ada.AttributeType)); - } - - return $@" - case {c}.AttributeName: - {{ - {caseBody} - }}"; -}))} - - default: - throw new ArgumentException(nameof(attributeName)); - }} + return new {entity.ClassName}( + {string.Join(", \n \t\t\t\t", entity.Buffers.Select(b => { + + switch (b.BufferType) + { + case BufferType.Singleton: + return $"{b.MemberName}"; + case BufferType.Data: + return $"{b.MemberName}.MergeData(other.{b.MemberName})"; + case BufferType.Index: + return $"{b.MemberName}.MergeIndices(other.{b.MemberName}, {b.IndexInto}?.Length ?? 0)"; + default: + return ""; + } + }))} + ); }} public void Validate() {{ // Ensure all the indices are either -1 or within the bounds of the attributes they are indexing into. -{string.Join(Environment.NewLine, attributeClasses.Select(c => -{ - var ada = c.GetCustomAttribute(); - var typedDataType = ada.GetTypedDataType(); - var name = ada.FormatClassName(c.Name); - - switch (ada.AttributeType) - { - case AttributeType.Singleton: - case AttributeType.Data: - return null; - case AttributeType.Index: - return $@" - {{ - var maxIndex = GetAttribute({name}.IndexInto).Data.Length - 1; - for (var i = 0; i < {name}.TypedData.Length; ++i) - {{ - var index = {name}.TypedData[i]; - - if (index == -1) - continue; // no relation. - - if (index < -1 || index > maxIndex) - throw new Exception($""Index out of range in {c} at position {{i}}. Expected either -1 for no relation, or a maximum of {{maxIndex}} but got {{index}}""); - }} - }}"; - default: - throw new ArgumentOutOfRangeException(nameof(ada.AttributeType)); - } -}).Where(s => !string.IsNullOrEmpty(s)))} + {string.Join("\n \t\t\t", entity.Buffers.Select(c => + { + if (c.BufferType == BufferType.Index) + { + return $"{c.MemberName}?.ValidateIndex({c.IndexInto}, \"{c.MemberName}\");"; + } + return null; + }).Where(s => s != null))} }} - }}"); + }} +"; } } } + diff --git a/src/cs/g3d/Vim.G3dNext.CodeGen/G3dBuffer.cs b/src/cs/g3d/Vim.G3dNext.CodeGen/G3dBuffer.cs new file mode 100644 index 00000000..b2a832fa --- /dev/null +++ b/src/cs/g3d/Vim.G3dNext.CodeGen/G3dBuffer.cs @@ -0,0 +1,42 @@ +using System; + +namespace Vim.G3dNext.CodeGen +{ + public enum BufferType + { + Singleton, + Data, + Index + } + + public class G3dBuffer + { + public string MemberName; + public string BufferName; + public BufferType BufferType; + public Type ValueType; + public string IndexInto; + + public string ArgumentName => LowerFirst(MemberName); + + public G3dBuffer(string name, string bufferName, BufferType bufferType, Type valueType, string indexInto = null) + { + MemberName = name; + BufferName = bufferName; + BufferType = bufferType; + ValueType = valueType; + IndexInto = indexInto; + } + + public static string LowerFirst(string input) + { + if (string.IsNullOrEmpty(input)) + { + return input; + } + + return char.ToLower(input[0]) + input.Substring(1); + } + } +} + diff --git a/src/cs/g3d/Vim.G3dNext.CodeGen/G3dEntity.cs b/src/cs/g3d/Vim.G3dNext.CodeGen/G3dEntity.cs new file mode 100644 index 00000000..ae0c05dd --- /dev/null +++ b/src/cs/g3d/Vim.G3dNext.CodeGen/G3dEntity.cs @@ -0,0 +1,31 @@ +using System.Collections.Generic; + +namespace Vim.G3dNext.CodeGen +{ + public class G3dEntity + { + public string ClassName; + public List Buffers = new List(); + + public G3dEntity(string name) + { + ClassName = name; + } + + public G3dEntity Index(string name, string bufferName, string indexInto = null) + { + if (indexInto == null) + { + return Data(name, bufferName); + } + Buffers.Add(new G3dBuffer(name, bufferName, BufferType.Index, typeof(int), indexInto)); + return this; + } + + public G3dEntity Data(string name, string bufferName, string indexInto = null) + { + Buffers.Add(new G3dBuffer(name, bufferName, BufferType.Data, typeof(T), indexInto)); + return this; + } + } +} diff --git a/src/cs/g3d/Vim.G3dNext.CodeGen/Vim.G3dNext.CodeGen.csproj b/src/cs/g3d/Vim.G3dNext.CodeGen/Vim.G3dNext.CodeGen.csproj index 50f3a778..fdc9193d 100644 --- a/src/cs/g3d/Vim.G3dNext.CodeGen/Vim.G3dNext.CodeGen.csproj +++ b/src/cs/g3d/Vim.G3dNext.CodeGen/Vim.G3dNext.CodeGen.csproj @@ -10,13 +10,6 @@ Vim.G3dNext.CodeGen.Program - - - - - - - @@ -24,7 +17,7 @@ - + \ No newline at end of file diff --git a/src/cs/g3d/Vim.G3dNext/AttributeDescriptor.cs b/src/cs/g3d/Vim.G3dNext/AttributeDescriptor.cs deleted file mode 100644 index 4efc1157..00000000 --- a/src/cs/g3d/Vim.G3dNext/AttributeDescriptor.cs +++ /dev/null @@ -1,182 +0,0 @@ -using System; -using static Vim.G3dNext.Constants; - -namespace Vim.G3dNext -{ - public class AttributeDescriptor : IAttributeDescriptor - { - /// - public string Name - => string.Join(Separator, G3dPrefix, Association, Semantic, IndexStr, DataType, DataArity); - - /// - public string Association { get; } - - /// - public string Semantic { get; } - - /// - public int Index { get; } - private readonly string IndexStr; - - /// - public DataType DataType { get; } - public readonly string DataTypeStr; - - /// - public int DataArity { get; } - public readonly string DataArityStr; - - /// - public AttributeDescriptorErrors Errors { get; } - - /// - public bool HasErrors - => Errors != AttributeDescriptorErrors.None; - - /// - /// Returns true if the Errors contains a data type error. - /// - public bool HasDataTypeError - => (Errors & AttributeDescriptorErrors.DataTypeError) == AttributeDescriptorErrors.DataTypeError; - - /// - /// Returns true if the Errors contains a data arity error. - /// - public bool HasDataArityError - => (Errors & AttributeDescriptorErrors.DataArityError) == AttributeDescriptorErrors.DataArityError; - - /// - public int DataTypeSize { get; } - - /// - public int DataElementSize { get; } - - public static (int dataTypeSize, int dataElementSize) GetDataSizes(DataType dataType, int dataArity) - { - var dataTypeSize = dataType.GetDataTypeSize(); - return (dataTypeSize, dataTypeSize * dataArity); - } - - /// - /// Constructor. - /// - /// association semantic dataType - /// | | | - /// ~~~~~~~~ ~~~~~~~~~ ~~~~~~~ - /// "g3d:instance:transform:0:float32:16" - /// ^ ~~ - /// | | - /// index dataArity - /// - /// - public AttributeDescriptor( - string association, - string semantic, - int index, - DataType dataType, - int dataArity) - { - if (string.IsNullOrWhiteSpace(association)) - throw new ArgumentException($"The association cannot be null or whitespace."); - - if (association.Contains(Separator)) - throw new ArgumentException($"The association cannot contain a '{Separator}' character"); - - if (dataType == DataType.unknown) - throw new ArgumentException($"The data type cannot be '{DataType.unknown}'."); - - if (string.IsNullOrWhiteSpace(semantic)) - throw new ArgumentException($"The semantic cannot be null or whitespace."); - - if (semantic.Contains(Separator)) - throw new ArgumentException($"The semantic must not contain a '{Separator}' character"); - - Association = association; - Semantic = semantic; - Index = index; - IndexStr = Index.ToString(); - DataType = dataType; - DataTypeStr = DataType.ToString("G"); - DataArity = dataArity; - DataArityStr = DataArity.ToString(); - (DataTypeSize, DataElementSize) = GetDataSizes(DataType, DataArity); - } - - /// - /// Constructor. Parses an input string of the form: "g3d:instance:transform:0:float32:16". - /// - public AttributeDescriptor(string str) - { - var tokens = str.Split(SeparatorChar); - - if (tokens.Length != 6) - { - Errors = AttributeDescriptorErrors.UnexpectedNumberOfTokens; - return; - } - - if (tokens[0] != G3dPrefix) - { - Errors = AttributeDescriptorErrors.PrefixError; - return; - } - - Association = tokens[1]; - if (string.IsNullOrWhiteSpace(Association)) - Errors |= AttributeDescriptorErrors.AssociationError; // do not return; there may be more errors. - - Semantic = tokens[2]; - if (string.IsNullOrWhiteSpace(Semantic)) - Errors |= AttributeDescriptorErrors.SemanticError; // do not return; there may be more errors. - - IndexStr = tokens[3]; - if (!int.TryParse(IndexStr, out var index)) - Errors |= AttributeDescriptorErrors.IndexError; // do not return; there may be more errors. - Index = index; - - DataTypeStr = tokens[4]; - if (!Enum.TryParse(DataTypeStr, out DataType dataType)) - dataType = DataType.unknown; - - DataType = dataType; - if (DataType == DataType.unknown) - Errors |= AttributeDescriptorErrors.DataTypeError; // do not return; there may be more errors. - - DataArityStr = tokens[5]; - if (!int.TryParse(DataArityStr, out var dataArity)) - Errors |= AttributeDescriptorErrors.DataArityError; - DataArity = dataArity; - - if (!HasDataTypeError && !HasDataArityError) - { - (DataTypeSize, DataElementSize) = GetDataSizes(DataType, DataArity); - } - } - - /// - /// Returns the string representation of the attribute descriptor, in the form "g3d:instance:transform:0:float32:16" - /// - public override string ToString() - => Name; - - /// - /// Attempts to parse the given string as an AttributeDescriptor. - /// - public static bool TryParse(string str, out AttributeDescriptor attributeDescriptor) - { - attributeDescriptor = null; - - try - { - attributeDescriptor = new AttributeDescriptor(str); - } - catch - { - return false; - } - - return !attributeDescriptor.HasErrors; - } - } -} diff --git a/src/cs/g3d/Vim.G3dNext/AttributeDescriptorErrors.cs b/src/cs/g3d/Vim.G3dNext/AttributeDescriptorErrors.cs deleted file mode 100644 index db1908d4..00000000 --- a/src/cs/g3d/Vim.G3dNext/AttributeDescriptorErrors.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System; - -namespace Vim.G3dNext -{ - [Flags] - public enum AttributeDescriptorErrors - { - None = 0, - UnexpectedNumberOfTokens = 1, - PrefixError = 1 << 1, - AssociationError = 1 << 2, - SemanticError = 1 << 3, - IndexError = 1 << 4, - DataTypeError = 1 << 5, - DataArityError = 1 << 6, - } -} diff --git a/src/cs/g3d/Vim.G3dNext/AttributeType.cs b/src/cs/g3d/Vim.G3dNext/AttributeType.cs deleted file mode 100644 index 03568640..00000000 --- a/src/cs/g3d/Vim.G3dNext/AttributeType.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Vim.G3dNext -{ - public enum AttributeType - { - Singleton, - Data, - Index - } -} diff --git a/src/cs/g3d/Vim.G3dNext/CodeGenAttributes.cs b/src/cs/g3d/Vim.G3dNext/CodeGenAttributes.cs deleted file mode 100644 index 2ea57bc2..00000000 --- a/src/cs/g3d/Vim.G3dNext/CodeGenAttributes.cs +++ /dev/null @@ -1,51 +0,0 @@ -using System; - -namespace Vim.G3dNext -{ - [AttributeUsage(AttributeTargets.Class)] - public class AttributeDescriptorAttribute : Attribute - { - public string Name { get; set; } - public string Prefix { get; set; } = null; - public Type ArrayType { get; set; } = null; - public AttributeType AttributeType { get; set; } = AttributeType.Data; - public Type IndexInto { get; set; } = null; - - public string FormatClassName(string name) - { - var result = name.Replace("Attribute", ""); - return Prefix != null - ? result.Replace(Prefix,"") - : result; - } - public AttributeDescriptorAttribute(string name, AttributeType attributeType) - { - Name = name; - AttributeType = attributeType; - } - public AttributeDescriptorAttribute(string prefix, string name, AttributeType attributeType) - { - Prefix = prefix; - Name = name; - AttributeType = attributeType; - } - } - - [AttributeUsage(AttributeTargets.Class)] - public class AttributeCollectionAttribute : Attribute - { - public Type[] AttributeClasses { get; } - - public AttributeCollectionAttribute(params Type[] attributeClasses) - => AttributeClasses = attributeClasses; - } - - [AttributeUsage(AttributeTargets.Class)] - public class G3dDefinitionAttribute : Attribute - { - public Type[] AttributeClasses { get; } - - public G3dDefinitionAttribute(params Type[] attributeClasses) - => AttributeClasses = attributeClasses; - } -} diff --git a/src/cs/g3d/Vim.G3dNext/Constants.cs b/src/cs/g3d/Vim.G3dNext/Constants.cs index 77266c1f..c8cc2282 100644 --- a/src/cs/g3d/Vim.G3dNext/Constants.cs +++ b/src/cs/g3d/Vim.G3dNext/Constants.cs @@ -1,5 +1,36 @@ namespace Vim.G3dNext { + /// + /// Defines method for additionnal setup after constructors in generated G3d classes. + /// + public interface ISetup + { + void Setup(); + } + + public enum MeshSection + { + Opaque, + Transparent, + All + } + + + public static class Utils { + public static bool SafeEqual(this T[] a, T[] b) + { + if (a == null && b == null) return true; + if (a == null) return false; + if(b == null) return false; + if(a.Length != b.Length) return false; + for(var i= 0; i < a.Length; i++) + { + if (!a[i].Equals(b[i])) return false; + } + return true; + } + } + public static class Constants { public const string G3dPrefix = "g3d"; diff --git a/src/cs/g3d/Vim.G3dNext/DataType.cs b/src/cs/g3d/Vim.G3dNext/DataType.cs deleted file mode 100644 index 1621d7f5..00000000 --- a/src/cs/g3d/Vim.G3dNext/DataType.cs +++ /dev/null @@ -1,87 +0,0 @@ -using System; - -namespace Vim.G3dNext -{ - public enum DataType - { - /// - /// Exists to support future values which are currently unknown. - /// - unknown, - - // IMPORTANT: the string values of these data types, including their capitalization, - // are used in the parsing mechanism of the AttributeDescriptor, so be careful! - uint8, - int8, - uint16, - int16, - uint32, - int32, - uint64, - int64, - float32, - float64, - }; - - public static class DataTypeExtensions - { - /// - /// Returns the size in bytes of the given data type. - /// - public static int GetDataTypeSize(this DataType dt) - { - switch (dt) - { - case DataType.uint8: - case DataType.int8: - return 1; - case DataType.uint16: - case DataType.int16: - return 2; - case DataType.uint32: - case DataType.int32: - return 4; - case DataType.uint64: - case DataType.int64: - return 8; - case DataType.float32: - return 4; - case DataType.float64: - return 8; - case DataType.unknown: - default: - throw new ArgumentOutOfRangeException(nameof(dt), dt, null); - } - } - - public static Type GetManagedType(this DataType dt) - { - switch (dt) - { - case DataType.uint8: - return typeof(byte); - case DataType.int8: - return typeof(sbyte); - case DataType.uint16: - return typeof(ushort); - case DataType.int16: - return typeof(short); - case DataType.uint32: - return typeof(uint); - case DataType.int32: - return typeof(int); - case DataType.uint64: - return typeof(ulong); - case DataType.int64: - return typeof(long); - case DataType.float32: - return typeof(float); - case DataType.float64: - return typeof(double); - case DataType.unknown: - default: - throw new ArgumentOutOfRangeException(nameof(dt), dt, null); - } - } - } -} diff --git a/src/cs/g3d/Vim.G3dNext/Entities.g.cs b/src/cs/g3d/Vim.G3dNext/Entities.g.cs new file mode 100644 index 00000000..92e3b922 --- /dev/null +++ b/src/cs/g3d/Vim.G3dNext/Entities.g.cs @@ -0,0 +1,471 @@ +// AUTO-GENERATED FILE, DO NOT MODIFY. +// ReSharper disable All +using Vim.BFastNS; + +namespace Vim.G3dNext.Attributes +{ + // Please provide an explicit implementation in another partial class file. + public partial class G3dVim : ISetup + { + public System.Int32[] Indices; + public Vim.Math3d.Vector3[] Positions; + public Vim.Math3d.Matrix4x4[] InstanceTransforms; + public System.Int32[] InstanceParents; + public System.UInt16[] InstanceFlags; + public System.Int32[] InstanceMeshes; + public System.Int32[] MeshSubmeshOffsets; + public System.Int32[] SubmeshIndexOffsets; + public System.Int32[] SubmeshMaterials; + public Vim.Math3d.Vector4[] MaterialColors; + public System.Single[] MaterialGlossiness; + public System.Single[] MaterialSmoothness; + public Vim.Math3d.Vector3[] ShapeVertices; + public System.Int32[] ShapeVertexOffsets; + public Vim.Math3d.Vector4[] ShapeColors; + public System.Single[] ShapeWidths; + + public G3dVim( + System.Int32[] indices, + Vim.Math3d.Vector3[] positions, + Vim.Math3d.Matrix4x4[] instanceTransforms, + System.Int32[] instanceParents, + System.UInt16[] instanceFlags, + System.Int32[] instanceMeshes, + System.Int32[] meshSubmeshOffsets, + System.Int32[] submeshIndexOffsets, + System.Int32[] submeshMaterials, + Vim.Math3d.Vector4[] materialColors, + System.Single[] materialGlossiness, + System.Single[] materialSmoothness, + Vim.Math3d.Vector3[] shapeVertices, + System.Int32[] shapeVertexOffsets, + Vim.Math3d.Vector4[] shapeColors, + System.Single[] shapeWidths + ) + { + Indices = indices; + Positions = positions; + InstanceTransforms = instanceTransforms; + InstanceParents = instanceParents; + InstanceFlags = instanceFlags; + InstanceMeshes = instanceMeshes; + MeshSubmeshOffsets = meshSubmeshOffsets; + SubmeshIndexOffsets = submeshIndexOffsets; + SubmeshMaterials = submeshMaterials; + MaterialColors = materialColors; + MaterialGlossiness = materialGlossiness; + MaterialSmoothness = materialSmoothness; + ShapeVertices = shapeVertices; + ShapeVertexOffsets = shapeVertexOffsets; + ShapeColors = shapeColors; + ShapeWidths = shapeWidths; + + (this as ISetup).Setup(); + } + + public G3dVim(BFast bfast) + { + Indices = bfast.GetArray("g3d:corner:index:0:int32:1"); + Positions = bfast.GetArray("g3d:vertex:position:0:float32:3"); + InstanceTransforms = bfast.GetArray("g3d:instance:transform:0:float32:16"); + InstanceParents = bfast.GetArray("g3d:instance:parent:0:int32:1"); + InstanceFlags = bfast.GetArray("g3d:instance:flags:0:uint16:1"); + InstanceMeshes = bfast.GetArray("g3d:instance:mesh:0:int32:1"); + MeshSubmeshOffsets = bfast.GetArray("g3d:mesh:submeshoffset:0:int32:1"); + SubmeshIndexOffsets = bfast.GetArray("g3d:submesh:indexoffset:0:int32:1"); + SubmeshMaterials = bfast.GetArray("g3d:submesh:material:0:int32:1"); + MaterialColors = bfast.GetArray("g3d:material:color:0:float32:4"); + MaterialGlossiness = bfast.GetArray("g3d:material:glossiness:0:float32:1"); + MaterialSmoothness = bfast.GetArray("g3d:material:smoothness:0:float32:1"); + ShapeVertices = bfast.GetArray("g3d:shapevertex:position:0:float32:3"); + ShapeVertexOffsets = bfast.GetArray("g3d:shape:vertexoffset:0:int32:1"); + ShapeColors = bfast.GetArray("g3d:shape:color:0:float32:4"); + ShapeWidths = bfast.GetArray("g3d:shape:width:0:float32:1"); + + (this as ISetup).Setup(); + } + + public BFast ToBFast() + { + var bfast = new BFast(); + + bfast.SetArray("g3d:corner:index:0:int32:1", Indices); + bfast.SetArray("g3d:vertex:position:0:float32:3", Positions); + bfast.SetArray("g3d:instance:transform:0:float32:16", InstanceTransforms); + bfast.SetArray("g3d:instance:parent:0:int32:1", InstanceParents); + bfast.SetArray("g3d:instance:flags:0:uint16:1", InstanceFlags); + bfast.SetArray("g3d:instance:mesh:0:int32:1", InstanceMeshes); + bfast.SetArray("g3d:mesh:submeshoffset:0:int32:1", MeshSubmeshOffsets); + bfast.SetArray("g3d:submesh:indexoffset:0:int32:1", SubmeshIndexOffsets); + bfast.SetArray("g3d:submesh:material:0:int32:1", SubmeshMaterials); + bfast.SetArray("g3d:material:color:0:float32:4", MaterialColors); + bfast.SetArray("g3d:material:glossiness:0:float32:1", MaterialGlossiness); + bfast.SetArray("g3d:material:smoothness:0:float32:1", MaterialSmoothness); + bfast.SetArray("g3d:shapevertex:position:0:float32:3", ShapeVertices); + bfast.SetArray("g3d:shape:vertexoffset:0:int32:1", ShapeVertexOffsets); + bfast.SetArray("g3d:shape:color:0:float32:4", ShapeColors); + bfast.SetArray("g3d:shape:width:0:float32:1", ShapeWidths); + + return bfast; + } + + public bool Equals(G3dVim other ) + { + return Indices.SafeEquals(other.Indices) && + Positions.SafeEquals(other.Positions) && + InstanceTransforms.SafeEquals(other.InstanceTransforms) && + InstanceParents.SafeEquals(other.InstanceParents) && + InstanceFlags.SafeEquals(other.InstanceFlags) && + InstanceMeshes.SafeEquals(other.InstanceMeshes) && + MeshSubmeshOffsets.SafeEquals(other.MeshSubmeshOffsets) && + SubmeshIndexOffsets.SafeEquals(other.SubmeshIndexOffsets) && + SubmeshMaterials.SafeEquals(other.SubmeshMaterials) && + MaterialColors.SafeEquals(other.MaterialColors) && + MaterialGlossiness.SafeEquals(other.MaterialGlossiness) && + MaterialSmoothness.SafeEquals(other.MaterialSmoothness) && + ShapeVertices.SafeEquals(other.ShapeVertices) && + ShapeVertexOffsets.SafeEquals(other.ShapeVertexOffsets) && + ShapeColors.SafeEquals(other.ShapeColors) && + ShapeWidths.SafeEquals(other.ShapeWidths); + } + + public G3dVim Merge(G3dVim other) + { + return new G3dVim( + Indices.MergeIndices(other.Indices, Positions?.Length ?? 0), + Positions.MergeData(other.Positions), + InstanceTransforms.MergeData(other.InstanceTransforms), + InstanceParents.MergeIndices(other.InstanceParents, InstanceTransforms?.Length ?? 0), + InstanceFlags.MergeData(other.InstanceFlags), + InstanceMeshes.MergeIndices(other.InstanceMeshes, MeshSubmeshOffsets?.Length ?? 0), + MeshSubmeshOffsets.MergeIndices(other.MeshSubmeshOffsets, SubmeshIndexOffsets?.Length ?? 0), + SubmeshIndexOffsets.MergeIndices(other.SubmeshIndexOffsets, Indices?.Length ?? 0), + SubmeshMaterials.MergeIndices(other.SubmeshMaterials, MaterialColors?.Length ?? 0), + MaterialColors.MergeData(other.MaterialColors), + MaterialGlossiness.MergeData(other.MaterialGlossiness), + MaterialSmoothness.MergeData(other.MaterialSmoothness), + ShapeVertices.MergeData(other.ShapeVertices), + ShapeVertexOffsets.MergeIndices(other.ShapeVertexOffsets, ShapeVertices?.Length ?? 0), + ShapeColors.MergeData(other.ShapeColors), + ShapeWidths.MergeData(other.ShapeWidths) + ); + } + + public void Validate() + { + // Ensure all the indices are either -1 or within the bounds of the attributes they are indexing into. + Indices?.ValidateIndex(Positions, "Indices"); + InstanceParents?.ValidateIndex(InstanceTransforms, "InstanceParents"); + InstanceMeshes?.ValidateIndex(MeshSubmeshOffsets, "InstanceMeshes"); + MeshSubmeshOffsets?.ValidateIndex(SubmeshIndexOffsets, "MeshSubmeshOffsets"); + SubmeshIndexOffsets?.ValidateIndex(Indices, "SubmeshIndexOffsets"); + SubmeshMaterials?.ValidateIndex(MaterialColors, "SubmeshMaterials"); + ShapeVertexOffsets?.ValidateIndex(ShapeVertices, "ShapeVertexOffsets"); + } + } + + // Please provide an explicit implementation in another partial class file. + public partial class G3dChunk : ISetup + { + public System.Int32[] MeshOpaqueSubmeshCounts; + public System.Int32[] MeshSubmeshOffset; + public System.Int32[] SubmeshIndexOffsets; + public System.Int32[] SubmeshVertexOffsets; + public System.Int32[] SubmeshMaterials; + public Vim.Math3d.Vector3[] Positions; + public System.Int32[] Indices; + + public G3dChunk( + System.Int32[] meshOpaqueSubmeshCounts, + System.Int32[] meshSubmeshOffset, + System.Int32[] submeshIndexOffsets, + System.Int32[] submeshVertexOffsets, + System.Int32[] submeshMaterials, + Vim.Math3d.Vector3[] positions, + System.Int32[] indices + ) + { + MeshOpaqueSubmeshCounts = meshOpaqueSubmeshCounts; + MeshSubmeshOffset = meshSubmeshOffset; + SubmeshIndexOffsets = submeshIndexOffsets; + SubmeshVertexOffsets = submeshVertexOffsets; + SubmeshMaterials = submeshMaterials; + Positions = positions; + Indices = indices; + + (this as ISetup).Setup(); + } + + public G3dChunk(BFast bfast) + { + MeshOpaqueSubmeshCounts = bfast.GetArray("g3d:mesh:opaquesubmeshcount:0:int32:1"); + MeshSubmeshOffset = bfast.GetArray("g3d:mesh:submeshOffset:0:int32:1"); + SubmeshIndexOffsets = bfast.GetArray("g3d:submesh:indexoffset:0:int32:1"); + SubmeshVertexOffsets = bfast.GetArray("g3d:submesh:vertexoffset:0:int32:1"); + SubmeshMaterials = bfast.GetArray("g3d:submesh:material:0:int32:1"); + Positions = bfast.GetArray("g3d:vertex:position:0:float32:3"); + Indices = bfast.GetArray("g3d:corner:index:0:int32:1"); + + (this as ISetup).Setup(); + } + + public BFast ToBFast() + { + var bfast = new BFast(); + + bfast.SetArray("g3d:mesh:opaquesubmeshcount:0:int32:1", MeshOpaqueSubmeshCounts); + bfast.SetArray("g3d:mesh:submeshOffset:0:int32:1", MeshSubmeshOffset); + bfast.SetArray("g3d:submesh:indexoffset:0:int32:1", SubmeshIndexOffsets); + bfast.SetArray("g3d:submesh:vertexoffset:0:int32:1", SubmeshVertexOffsets); + bfast.SetArray("g3d:submesh:material:0:int32:1", SubmeshMaterials); + bfast.SetArray("g3d:vertex:position:0:float32:3", Positions); + bfast.SetArray("g3d:corner:index:0:int32:1", Indices); + + return bfast; + } + + public bool Equals(G3dChunk other ) + { + return MeshOpaqueSubmeshCounts.SafeEquals(other.MeshOpaqueSubmeshCounts) && + MeshSubmeshOffset.SafeEquals(other.MeshSubmeshOffset) && + SubmeshIndexOffsets.SafeEquals(other.SubmeshIndexOffsets) && + SubmeshVertexOffsets.SafeEquals(other.SubmeshVertexOffsets) && + SubmeshMaterials.SafeEquals(other.SubmeshMaterials) && + Positions.SafeEquals(other.Positions) && + Indices.SafeEquals(other.Indices); + } + + public G3dChunk Merge(G3dChunk other) + { + return new G3dChunk( + MeshOpaqueSubmeshCounts.MergeData(other.MeshOpaqueSubmeshCounts), + MeshSubmeshOffset.MergeIndices(other.MeshSubmeshOffset, Indices?.Length ?? 0), + SubmeshIndexOffsets.MergeIndices(other.SubmeshIndexOffsets, Indices?.Length ?? 0), + SubmeshVertexOffsets.MergeIndices(other.SubmeshVertexOffsets, Indices?.Length ?? 0), + SubmeshMaterials.MergeData(other.SubmeshMaterials), + Positions.MergeData(other.Positions), + Indices.MergeIndices(other.Indices, Positions?.Length ?? 0) + ); + } + + public void Validate() + { + // Ensure all the indices are either -1 or within the bounds of the attributes they are indexing into. + MeshSubmeshOffset?.ValidateIndex(Indices, "MeshSubmeshOffset"); + SubmeshIndexOffsets?.ValidateIndex(Indices, "SubmeshIndexOffsets"); + SubmeshVertexOffsets?.ValidateIndex(Indices, "SubmeshVertexOffsets"); + Indices?.ValidateIndex(Positions, "Indices"); + } + } + + // Please provide an explicit implementation in another partial class file. + public partial class G3dMaterials : ISetup + { + public Vim.Math3d.Vector4[] MaterialColors; + public System.Single[] MaterialGlossiness; + public System.Single[] MaterialSmoothness; + + public G3dMaterials( + Vim.Math3d.Vector4[] materialColors, + System.Single[] materialGlossiness, + System.Single[] materialSmoothness + ) + { + MaterialColors = materialColors; + MaterialGlossiness = materialGlossiness; + MaterialSmoothness = materialSmoothness; + + (this as ISetup).Setup(); + } + + public G3dMaterials(BFast bfast) + { + MaterialColors = bfast.GetArray("g3d:material:color:0:float32:4"); + MaterialGlossiness = bfast.GetArray("g3d:material:glossiness:0:float32:1"); + MaterialSmoothness = bfast.GetArray("g3d:material:smoothness:0:float32:1"); + + (this as ISetup).Setup(); + } + + public BFast ToBFast() + { + var bfast = new BFast(); + + bfast.SetArray("g3d:material:color:0:float32:4", MaterialColors); + bfast.SetArray("g3d:material:glossiness:0:float32:1", MaterialGlossiness); + bfast.SetArray("g3d:material:smoothness:0:float32:1", MaterialSmoothness); + + return bfast; + } + + public bool Equals(G3dMaterials other ) + { + return MaterialColors.SafeEquals(other.MaterialColors) && + MaterialGlossiness.SafeEquals(other.MaterialGlossiness) && + MaterialSmoothness.SafeEquals(other.MaterialSmoothness); + } + + public G3dMaterials Merge(G3dMaterials other) + { + return new G3dMaterials( + MaterialColors.MergeData(other.MaterialColors), + MaterialGlossiness.MergeData(other.MaterialGlossiness), + MaterialSmoothness.MergeData(other.MaterialSmoothness) + ); + } + + public void Validate() + { + // Ensure all the indices are either -1 or within the bounds of the attributes they are indexing into. + + } + } + + // Please provide an explicit implementation in another partial class file. + public partial class G3dScene : ISetup + { + public System.Int32[] ChunkCount; + public System.Int32[] InstanceMeshes; + public Vim.Math3d.Matrix4x4[] InstanceTransformData; + public System.Int32[] InstanceNodes; + public System.Int32[] InstanceGroups; + public System.Int64[] InstanceTags; + public System.UInt16[] InstanceFlags; + public Vim.Math3d.Vector3[] InstanceMins; + public Vim.Math3d.Vector3[] InstanceMaxs; + public System.Int32[] MeshChunks; + public System.Int32[] MeshChunkIndices; + public System.Int32[] MeshVertexCounts; + public System.Int32[] MeshIndexCounts; + public System.Int32[] MeshOpaqueVertexCounts; + public System.Int32[] MeshOpaqueIndexCounts; + + public G3dScene( + System.Int32[] chunkCount, + System.Int32[] instanceMeshes, + Vim.Math3d.Matrix4x4[] instanceTransformData, + System.Int32[] instanceNodes, + System.Int32[] instanceGroups, + System.Int64[] instanceTags, + System.UInt16[] instanceFlags, + Vim.Math3d.Vector3[] instanceMins, + Vim.Math3d.Vector3[] instanceMaxs, + System.Int32[] meshChunks, + System.Int32[] meshChunkIndices, + System.Int32[] meshVertexCounts, + System.Int32[] meshIndexCounts, + System.Int32[] meshOpaqueVertexCounts, + System.Int32[] meshOpaqueIndexCounts + ) + { + ChunkCount = chunkCount; + InstanceMeshes = instanceMeshes; + InstanceTransformData = instanceTransformData; + InstanceNodes = instanceNodes; + InstanceGroups = instanceGroups; + InstanceTags = instanceTags; + InstanceFlags = instanceFlags; + InstanceMins = instanceMins; + InstanceMaxs = instanceMaxs; + MeshChunks = meshChunks; + MeshChunkIndices = meshChunkIndices; + MeshVertexCounts = meshVertexCounts; + MeshIndexCounts = meshIndexCounts; + MeshOpaqueVertexCounts = meshOpaqueVertexCounts; + MeshOpaqueIndexCounts = meshOpaqueIndexCounts; + + (this as ISetup).Setup(); + } + + public G3dScene(BFast bfast) + { + ChunkCount = bfast.GetArray("g3d:chunk:count:0:int32:1"); + InstanceMeshes = bfast.GetArray("g3d:instance:mesh:0:int32:1"); + InstanceTransformData = bfast.GetArray("g3d:instance:transform:0:float32:16"); + InstanceNodes = bfast.GetArray("g3d:instance:node:0:int32:1"); + InstanceGroups = bfast.GetArray("g3d:instance:group:0:int32:1"); + InstanceTags = bfast.GetArray("g3d:instance:tag:0:int64:1"); + InstanceFlags = bfast.GetArray("g3d:instance:flags:0:uint16:1"); + InstanceMins = bfast.GetArray("g3d:instance:min:0:float32:3"); + InstanceMaxs = bfast.GetArray("g3d:instance:max:0:float32:3"); + MeshChunks = bfast.GetArray("g3d:mesh:chunk:0:int32:1"); + MeshChunkIndices = bfast.GetArray("g3d:mesh:chunkindex:0:int32:1"); + MeshVertexCounts = bfast.GetArray("g3d:mesh:vertexcount:0:int32:1"); + MeshIndexCounts = bfast.GetArray("g3d:mesh:indexcount:0:int32:1"); + MeshOpaqueVertexCounts = bfast.GetArray("g3d:mesh:opaquevertexcount:0:int32:1"); + MeshOpaqueIndexCounts = bfast.GetArray("g3d:mesh:opaqueindexcount:0:int32:1"); + + (this as ISetup).Setup(); + } + + public BFast ToBFast() + { + var bfast = new BFast(); + + bfast.SetArray("g3d:chunk:count:0:int32:1", ChunkCount); + bfast.SetArray("g3d:instance:mesh:0:int32:1", InstanceMeshes); + bfast.SetArray("g3d:instance:transform:0:float32:16", InstanceTransformData); + bfast.SetArray("g3d:instance:node:0:int32:1", InstanceNodes); + bfast.SetArray("g3d:instance:group:0:int32:1", InstanceGroups); + bfast.SetArray("g3d:instance:tag:0:int64:1", InstanceTags); + bfast.SetArray("g3d:instance:flags:0:uint16:1", InstanceFlags); + bfast.SetArray("g3d:instance:min:0:float32:3", InstanceMins); + bfast.SetArray("g3d:instance:max:0:float32:3", InstanceMaxs); + bfast.SetArray("g3d:mesh:chunk:0:int32:1", MeshChunks); + bfast.SetArray("g3d:mesh:chunkindex:0:int32:1", MeshChunkIndices); + bfast.SetArray("g3d:mesh:vertexcount:0:int32:1", MeshVertexCounts); + bfast.SetArray("g3d:mesh:indexcount:0:int32:1", MeshIndexCounts); + bfast.SetArray("g3d:mesh:opaquevertexcount:0:int32:1", MeshOpaqueVertexCounts); + bfast.SetArray("g3d:mesh:opaqueindexcount:0:int32:1", MeshOpaqueIndexCounts); + + return bfast; + } + + public bool Equals(G3dScene other ) + { + return ChunkCount.SafeEquals(other.ChunkCount) && + InstanceMeshes.SafeEquals(other.InstanceMeshes) && + InstanceTransformData.SafeEquals(other.InstanceTransformData) && + InstanceNodes.SafeEquals(other.InstanceNodes) && + InstanceGroups.SafeEquals(other.InstanceGroups) && + InstanceTags.SafeEquals(other.InstanceTags) && + InstanceFlags.SafeEquals(other.InstanceFlags) && + InstanceMins.SafeEquals(other.InstanceMins) && + InstanceMaxs.SafeEquals(other.InstanceMaxs) && + MeshChunks.SafeEquals(other.MeshChunks) && + MeshChunkIndices.SafeEquals(other.MeshChunkIndices) && + MeshVertexCounts.SafeEquals(other.MeshVertexCounts) && + MeshIndexCounts.SafeEquals(other.MeshIndexCounts) && + MeshOpaqueVertexCounts.SafeEquals(other.MeshOpaqueVertexCounts) && + MeshOpaqueIndexCounts.SafeEquals(other.MeshOpaqueIndexCounts); + } + + public G3dScene Merge(G3dScene other) + { + return new G3dScene( + ChunkCount.MergeData(other.ChunkCount), + InstanceMeshes.MergeData(other.InstanceMeshes), + InstanceTransformData.MergeData(other.InstanceTransformData), + InstanceNodes.MergeData(other.InstanceNodes), + InstanceGroups.MergeData(other.InstanceGroups), + InstanceTags.MergeData(other.InstanceTags), + InstanceFlags.MergeData(other.InstanceFlags), + InstanceMins.MergeData(other.InstanceMins), + InstanceMaxs.MergeData(other.InstanceMaxs), + MeshChunks.MergeData(other.MeshChunks), + MeshChunkIndices.MergeData(other.MeshChunkIndices), + MeshVertexCounts.MergeData(other.MeshVertexCounts), + MeshIndexCounts.MergeData(other.MeshIndexCounts), + MeshOpaqueVertexCounts.MergeData(other.MeshOpaqueVertexCounts), + MeshOpaqueIndexCounts.MergeData(other.MeshOpaqueIndexCounts) + ); + } + + public void Validate() + { + // Ensure all the indices are either -1 or within the bounds of the attributes they are indexing into. + + } + } + +} diff --git a/src/cs/g3d/Vim.G3dNext/G3dChunk.cs b/src/cs/g3d/Vim.G3dNext/G3dChunk.cs new file mode 100644 index 00000000..698a29de --- /dev/null +++ b/src/cs/g3d/Vim.G3dNext/G3dChunk.cs @@ -0,0 +1,169 @@ +using System; +using Vim.Math3d; + +namespace Vim.G3dNext.Attributes +{ + public partial class G3dChunk + { + void ISetup.Setup() + { + // empty + } + + /// + /// The total number of instances. + /// + + public int GetSubmeshCount() => SubmeshIndexOffsets?.Length ?? 0; + + + public int getMeshCount() => MeshSubmeshOffset?.Length ?? 0; + + /// + /// The total number of submeshes. + /// + public int GetSubmeshCount(int mesh, MeshSection section) => + GetMeshSubmeshEnd(mesh, section) - GetMeshSubmeshStart(mesh, section); + + public int GetMeshSubmeshStart(int mesh, MeshSection section) + { + if (section == MeshSection.Opaque || section == MeshSection.All) + { + return MeshSubmeshOffset[mesh]; + } + + return MeshSubmeshOffset[mesh] + MeshOpaqueSubmeshCounts[mesh]; + } + + public int GetMeshSubmeshEnd(int mesh, MeshSection section) + { + if (section == MeshSection.Opaque) + { + return MeshSubmeshOffset[mesh] + MeshOpaqueSubmeshCounts[mesh]; + } + if(mesh + 1 >= MeshSubmeshOffset.Length) + { + return SubmeshIndexOffsets.Length; + } + return MeshSubmeshOffset[mesh + 1]; + } + + public int GetMeshIndexStart(int mesh, MeshSection section) + { + var sub = GetMeshSubmeshStart(mesh, section); + return GetSubmeshIndexStart(sub); + } + + public int GetMeshIndexEnd(int mesh, MeshSection section) + { + var sub = GetMeshSubmeshEnd(mesh, section); + return GetSubmeshIndexEnd(sub); + } + + public int GetMeshIndexCount(int mesh, MeshSection section) + { + return GetMeshIndexEnd(mesh, section) - GetMeshIndexStart(mesh, section); + } + + public AABox GetAABox(int mesh, Matrix4x4 matrix) + { + var start = GetMeshVertexStart(mesh, MeshSection.All); + var end = GetMeshVertexEnd(mesh, MeshSection.All); + var min = Positions[start].Transform(matrix); + var max = min; + for (var v = start + 1; v < end; v++) + { + var pos = Positions[v].Transform(matrix); + min = min.Min(pos); + max = max.Max(pos); + } + return new AABox(min, max); + } + + /// + /// The total number of indices. + /// + public int GetIndexCount() => Indices?.Length ?? 0; + + public int GetMeshVertexStart(int mesh, MeshSection section) + { + var sub = GetMeshSubmeshStart(mesh, section); + return GetSubmeshVertexStart(sub); + } + + public int GetMeshVertexEnd(int mesh, MeshSection section) + { + var sub = GetMeshSubmeshEnd(mesh, section); + return GetSubmeshVertexEnd(sub); + } + + public int GetMeshVertexCount(int mesh, MeshSection section) + { + return GetMeshVertexEnd(mesh, section) - GetMeshVertexStart(mesh, section); + } + + /// + /// The total number of vertices. + /// + public int GetVertexCount() => (Positions?.Length ?? 0); + + public int GetSubmeshIndexStart(int submesh) + { + return SubmeshIndexOffsets[submesh]; + } + + public int GetSubmeshIndexEnd(int submesh) + { + return submesh + 1 < GetSubmeshCount() + ? SubmeshIndexOffsets[submesh + 1] + : GetIndexCount(); + } + + public int GetSubmeshIndexCount(int submesh) + { + return GetSubmeshIndexEnd(submesh) - GetSubmeshIndexStart(submesh); + } + + public int GetSubmeshVertexStart(int submesh) + { + return SubmeshVertexOffsets[submesh]; + } + + public int GetSubmeshVertexEnd(int submesh) + { + return submesh + 1 < GetSubmeshCount() ? SubmeshVertexOffsets[submesh + 1] : GetVertexCount(); + } + + public int GetSubmeshVertexCount(int submesh) + { + return GetSubmeshVertexEnd(submesh) - GetSubmeshVertexStart(submesh); + } + + public AABox GetAABB() + { + var box = new AABox(Positions[0], Positions[0]); + for (var p = 1; p < Positions.Length; p++) + { + var pos = Positions[p]; + box = Expand(box, pos); + } + return box; + } + + static AABox Expand(AABox box, Vector3 pos) + { + return new AABox( + new Vector3( + Math.Min(box.Min.X, pos.X), + Math.Min(box.Min.Y, pos.Y), + Math.Min(box.Min.Z, pos.Z) + ), + new Vector3( + Math.Max(box.Max.X, pos.X), + Math.Max(box.Max.Y, pos.Y), + Math.Max(box.Max.Z, pos.Z) + ) + ); + } + } +} diff --git a/src/cs/g3d/Vim.G3dNext/G3dMaterials.cs b/src/cs/g3d/Vim.G3dNext/G3dMaterials.cs new file mode 100644 index 00000000..6515edf8 --- /dev/null +++ b/src/cs/g3d/Vim.G3dNext/G3dMaterials.cs @@ -0,0 +1,20 @@ +using System.Runtime.ConstrainedExecution; + +namespace Vim.G3dNext.Attributes +{ + public partial class G3dMaterials + { + void ISetup.Setup() + { + // empty + } + + + public G3dMaterials(G3dVim vim) + { + MaterialColors = vim.MaterialColors; + MaterialGlossiness = vim.MaterialGlossiness; + MaterialSmoothness = vim.MaterialSmoothness; + } + } +} diff --git a/src/cs/g3d/Vim.G3dNext/G3dScene.cs b/src/cs/g3d/Vim.G3dNext/G3dScene.cs new file mode 100644 index 00000000..65e693dd --- /dev/null +++ b/src/cs/g3d/Vim.G3dNext/G3dScene.cs @@ -0,0 +1,12 @@ +namespace Vim.G3dNext.Attributes +{ + public partial class G3dScene + { + public int GetChunksCount() => ChunkCount[0]; + public int GetInstanceCount() => InstanceMeshes.Length; + void ISetup.Setup() + { + // empty + } + } +} diff --git a/src/cs/g3d/Vim.G3dNext/G3dVim.cs b/src/cs/g3d/Vim.G3dNext/G3dVim.cs new file mode 100644 index 00000000..10bd6732 --- /dev/null +++ b/src/cs/g3d/Vim.G3dNext/G3dVim.cs @@ -0,0 +1,186 @@ +using System; +using System.Collections.Generic; +using Vim.BFastNS; + +namespace Vim.G3dNext.Attributes +{ + public partial class G3dVim + { + // Computed field + public int[] MeshVertexOffsets; + private List[] _meshInstances; + + public IReadOnlyList GetMeshInstances(int mesh) + { + return _meshInstances[mesh]; + } + + public int GetApproxSize(int mesh) + { + return GetMeshVertexCount(mesh) * 12 + GetMeshIndexCount(mesh) * 4; + } + + void ISetup.Setup() + { + MeshVertexOffsets = ComputeMeshVertexOffsets(); + _meshInstances = ComputeMeshInstances(); + } + + public static G3dVim FromVim(string vimPath) + => vimPath.ReadBFast(b => new G3dVim(b.GetBFast("geometry"))); + + private int[] ComputeMeshVertexOffsets() + { + var result = new int[GetMeshCount()]; + for (var m = 0; m < result.Length; m++) + { + var min = int.MaxValue; + var start = GetMeshIndexStart(m); + var end = GetMeshIndexEnd(m); + for (var i = start; i < end; i++) + { + min = Math.Min(min, Indices[i]); + } + result[m] = min; + } + return result; + } + + private List[] ComputeMeshInstances() + { + var result = new List[GetMeshCount()]; + for (var i = 0; i < result.Length; i++) + { + result[i] = new List(); + } + + for (var i = 0; i < InstanceMeshes.Length; i++) + { + var mesh = InstanceMeshes[i]; + if (mesh >= 0) + { + result[mesh].Add(i); + } + } + + return result; + } + + + public int GetTriangleCount() + { + return GetIndexCount() / 3; + } + + /// + /// The total number of instances. + /// + public int GetInstanceCount() => InstanceTransforms?.Length ?? 0; + + #region meshes + /// + /// The total number of meshes. + /// + public int GetMeshCount() => MeshSubmeshOffsets?.Length ?? 0; + + public int GetMeshIndexStart(int mesh) + { + var submesh = GetMeshSubmeshStart(mesh); + return GetSubmeshIndexStart(submesh); + } + + public int GetMeshIndexEnd(int mesh) + { + var submesh = GetMeshSubmeshEnd(mesh) - 1; + return GetSubmeshIndexEnd(submesh); + } + + public int GetMeshIndexCount(int mesh) + { + return GetMeshIndexEnd(mesh) - GetMeshIndexStart(mesh); + } + + public int GetMeshVertexStart(int mesh) + { + return MeshVertexOffsets[mesh]; + } + + public int GetMeshVertexEnd(int mesh) + { + return mesh + 1 < GetMeshCount() ? MeshVertexOffsets[mesh + 1] : Positions.Length; + } + + public int GetMeshVertexCount(int mesh) + { + return GetMeshVertexEnd(mesh) - GetMeshVertexStart(mesh); + } + + public int GetMeshSubmeshStart(int mesh) + { + return MeshSubmeshOffsets[mesh]; + } + + public int GetMeshSubmeshEnd(int mesh) + { + return mesh + 1 < GetMeshCount() + ? MeshSubmeshOffsets[mesh + 1] + : GetSubmeshCount(); + } + + public int GetMeshSubmeshCount(int mesh) + { + return GetMeshSubmeshEnd(mesh) - GetMeshSubmeshStart(mesh); + } + + #endregion + + #region submesh + + /// + /// The total number of submeshes. + /// + public int GetSubmeshCount() => SubmeshIndexOffsets?.Length ?? 0; + + public int GetSubmeshIndexStart(int submesh) + { + return SubmeshIndexOffsets[submesh]; + } + + public int GetSubmeshIndexEnd(int submesh) + { + return submesh + 1 < GetSubmeshCount() ? SubmeshIndexOffsets[submesh + 1] : GetIndexCount(); + } + + public int GetSubmeshIndexCount(int submesh) + { + return GetSubmeshIndexEnd(submesh) - GetSubmeshIndexStart(submesh); + } + + #endregion + + /// + /// The total number of indices. + /// + public int GetIndexCount() => Indices?.Length ?? 0; + + /// + /// The total number of vertices. + /// + public int GetVertexCount() => Positions?.Length ?? 0; + + /// + /// The total number of materials. + /// + public int GetMaterialCount() => MaterialColors?.Length ?? 0; + + /// + /// The total number of shapes. + /// + public int GetShapeCount() => ShapeVertexOffsets?.Length ?? 0; + + /// + /// The total number of shape vertices. + /// + public int GetShapeVertexCount() => ShapeVertices?.Length ?? 0; + } +} diff --git a/src/cs/g3d/Vim.G3dNext/IAttribute.cs b/src/cs/g3d/Vim.G3dNext/IAttribute.cs deleted file mode 100644 index a2d280ef..00000000 --- a/src/cs/g3d/Vim.G3dNext/IAttribute.cs +++ /dev/null @@ -1,74 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using Vim.BFastNS; - -namespace Vim.G3dNext -{ - public interface IAttribute - { - string Name { get; } - IAttributeDescriptor AttributeDescriptor { get; } - AttributeType AttributeType { get; } - Type IndexInto { get; } - Array Data { get; } - void Write(Stream stream); - void AddTo(BFast bfast); - void ReadBFast(BFast bfast); - } - - public interface IAttribute : IAttribute - { - T[] TypedData { get; set; } - } - - public static class AttributeExtensions - { - public static long GetSizeInBytes(this IAttribute attribute) - => attribute.AttributeDescriptor.DataElementSize * (attribute.Data?.LongLength ?? 0); - - public static TAttr MergeDataAttributes(this IReadOnlyList attributes) where TAttr : IAttribute, new() - { - if (attributes.Count == 0) - return new TAttr(); - - // Check that all attributes have the same descriptor - var first = attributes.First(); - if (!attributes.All(attr => attr.Name.Equals(first.Name))) - throw new Exception($"All attributes must have the same descriptor ({first.Name}) to be merged."); - - var data = attributes.SelectMany(attr => attr.TypedData).ToArray(); - return new TAttr { TypedData = data }; - } - - public static TAttr MergeIndexAttributes( - this IEnumerable<(TAttr Attribute, int IndexedCount)> toMerge) - where TAttr : IAttribute, new() - { - var mergeList = toMerge.ToArray(); - var mergedIndices = new int[mergeList.Sum(t => t.Attribute.TypedData.Length)]; - - var valueOffset = 0; - var mergedCount = 0; - - foreach (var (attr, indexedCount) in toMerge) - { - var typedData = attr.TypedData; - var typedDataCount = typedData.Length; - - for (var i = 0; i < typedDataCount; ++i) - { - mergedIndices[mergedCount + i] = typedData[i] < 0 - ? typedData[i] // if the index is less than 0, then do not increment it (this preserves -1 value assignments) - : typedData[i] + valueOffset; // otherwise, apply the increment. - } - - mergedCount += typedDataCount; - valueOffset += indexedCount; - } - - return new TAttr { TypedData = mergedIndices }; - } - } -} diff --git a/src/cs/g3d/Vim.G3dNext/IAttributeCollection.cs b/src/cs/g3d/Vim.G3dNext/IAttributeCollection.cs deleted file mode 100644 index 2cf120dc..00000000 --- a/src/cs/g3d/Vim.G3dNext/IAttributeCollection.cs +++ /dev/null @@ -1,129 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Vim.BFastNS; - -namespace Vim.G3dNext -{ - /// - /// Defines method for additionnal setup after constructors in generated G3d classes. - /// - public interface ISetup - { - void Setup(); - } - - /// - /// A collection of attributes and readers which can be used to deserialize attributes from a stream.
- ///
- /// A class may implement this interface to define the specialized set of attributes and attribute readers for - /// a given context.
- ///
- /// For example, the geometry and instance information in a VIM file is defined in a class named VimAttributeCollection. - ///
- public interface IAttributeCollection - { - /// - /// A mapping from attribute name to its corresponding attribute.
- /// This is populated when reading attributes from a stream. - ///
- IDictionary Map { get; } - - /// - /// Returns the attribute corresponding to the given type. - /// - IAttribute GetAttribute(Type attributeType); - - /// - /// Merges the attribute with the given name with any other matching attributes in the other collections. - /// - IAttribute MergeAttribute(string attributeName, IReadOnlyList otherCollections); - - /// - /// Validates the attribute collection. May throw an exception if the collection is invalid. - /// - void Validate(); - - } - - /// - /// Extension functions and helpers for attribute collections - /// - public static class AttributeCollectionExtensions - { - public static IEnumerable GetAttributeNames(this IAttributeCollection attributeCollection) - => attributeCollection.Map.Keys; - - public static long GetSize(this IAttributeCollection attributeCollection) - => attributeCollection.Map.Values - .Sum(a => a.GetSizeInBytes()); - - public static BFast ToBFast(this IAttributeCollection attributeCollection) - { - var attributes = attributeCollection.Map.Values - .OrderBy(n => n.Name) - .ToArray(); // Order the attributes by name for consistency - - var bfast = new BFast(); - foreach (var a in attributes) - { - a.AddTo(bfast); - } - return bfast; - } - - public static IEnumerable GetAttributesOfType( - this IReadOnlyList collections) - where TAttr : IAttribute - => collections - .Select(c => c.Map.Values.OfType().FirstOrDefault()) - .Where(a => a != null); - - public static IEnumerable<(TAttr Attribute, int IndexedCount)> GetIndexedAttributesOfType( - this IReadOnlyList collections) - where TAttr : IAttribute - => collections - .Select(c => - { - var attr = c.Map.Values.OfType().FirstOrDefault(); - if (attr == null || attr.IndexInto == null) - return (attr, 0); - - var indexedAttr = c.GetAttribute(attr.IndexInto); - return (attr, indexedAttr.Data.Length); - }) - .Where(t => t.attr != null); - - public static T Merge(this IReadOnlyList collections) - where T: IAttributeCollection, new() - { - if (collections == null) - return new T(); - - if (collections.Count == 1) - return collections[0]; - - // More than one collection; the first collection dictates the attributes to merge. - var @base = collections.First(); - - var others = new List(); - for (var i = 1; i < collections.Count; ++i) - { - others.Add(collections[i]); - } - - var result = new T(); - - foreach (var item in @base.Map) - { - var name = item.Key; - - var merged = @base.MergeAttribute(name, others); - - result.Map[name] = merged; - } - - return result; - } - } -} diff --git a/src/cs/g3d/Vim.G3dNext/IAttributeDescriptor.cs b/src/cs/g3d/Vim.G3dNext/IAttributeDescriptor.cs deleted file mode 100644 index cd72c3fb..00000000 --- a/src/cs/g3d/Vim.G3dNext/IAttributeDescriptor.cs +++ /dev/null @@ -1,88 +0,0 @@ -namespace Vim.G3dNext -{ - public interface IAttributeDescriptor - { - /// - /// The string representation of the IAttributeDescriptor. - /// - /// ex: "g3d:instance:transform:0:float32:16" - /// ~~~ - /// | - /// "g3d" is the standard prefix. - /// - /// - string Name { get; } - - /// - /// The second token in the AttributeDescriptor; designates the object to - /// which the attribute is conceptually associated - /// - /// ex: "g3d:instance:transform:0:float32:16" - /// ~~~~~~~~ - /// - /// - string Association { get; } - - /// - /// The third token in the AttributeDescriptor; designates the semantic meaning of the data. - /// - /// ex: "g3d:instance:transform:0:float32:16" - /// ~~~~~~~~~ - /// - /// - string Semantic { get; } - - /// - /// The fourth token in the AttributeDescriptor; designates the index in case - /// the same Association:Semantic combination occurs more than once among the collection of attribute descriptors. - /// - /// ex: "g3d:instance:transform:0:float32:16" - /// ^ - /// - /// - int Index { get; } - - /// - /// The fifth token in the AttributeDescriptor; designates the data type which composes the buffer. - /// - /// ex: "g3d:instance:transform:0:float32:16" - /// ~~~~~~~ - /// | - /// a transformation matrix is composed of float32 values - /// - /// - DataType DataType { get; } - - /// - /// The sixth token in the AttributeDescriptor; designates arity, or the number of values which compose - /// one semantic element. - /// - /// ex: "g3d:instance:transform:0:float32:16" - /// ~~ - /// | - /// one transformation matrix is composed of 16 values - /// - /// - int DataArity { get; } - - /// - /// The current collection of errors defined as bitwise flags - /// - AttributeDescriptorErrors Errors { get; } - - /// - /// Returns true if the Errors is not AttributeDescriptorErrors.None. - /// - bool HasErrors { get; } - - /// - /// The size in bytes of the DataType. - /// - int DataTypeSize { get; } - - /// - /// The size in bytes of one semantic element (DataTypeSize * DataArity) - /// - int DataElementSize { get; } - } -} diff --git a/src/cs/vim/Vim.Format.Vimx.Conversion/Chunking.cs b/src/cs/vim/Vim.Format.Vimx.Conversion/Chunking.cs index f431c19b..ebc96d5e 100644 --- a/src/cs/vim/Vim.Format.Vimx.Conversion/Chunking.cs +++ b/src/cs/vim/Vim.Format.Vimx.Conversion/Chunking.cs @@ -96,16 +96,15 @@ public static G3dChunk CreateChunk(G3dVim g3d, List meshes) submeshOffsets.Add(submeshOffsets[i] + opaqueCount + transparentCount); } - return new G3dChunk() - { - MeshSubmeshOffset = submeshOffsets.ToArray(), - MeshOpaqueSubmeshCounts = opaqueCounts.ToArray(), - SubmeshIndexOffsets = submeshIndexOffsets.ToArray(), - SubmeshVertexOffsets = submeshVertexOffsets.ToArray(), - SubmeshMaterials = submeshMaterials.ToArray(), - Indices = indices.ToArray(), - Positions = vertices.ToArray() - }; + return new G3dChunk( + submeshOffsets.ToArray(), + opaqueCounts.ToArray(), + submeshIndexOffsets.ToArray(), + submeshVertexOffsets.ToArray(), + submeshMaterials.ToArray(), + vertices.ToArray(), + indices.ToArray() + ); } @@ -192,16 +191,15 @@ public static G3dChunk CreateChunk2(G3dVim g3d, List meshes) meshSubmeshOffsets[i + 1] = meshSubmeshOffsets[i] + opaqueCount + transparentCount; } - return new G3dChunk() - { - MeshSubmeshOffset = meshSubmeshOffsets, - MeshOpaqueSubmeshCounts = meshOpaqueCounts, - SubmeshIndexOffsets = submeshBuffer.IndexOffsets, - SubmeshVertexOffsets = submeshBuffer.VertexOffsets, - SubmeshMaterials = submeshBuffer.Materials, - Indices = pointsBuffer.indices, - Positions = pointsBuffer.vertices.ToArray() - }; + return new G3dChunk( + meshSubmeshOffsets, + meshOpaqueCounts, + submeshBuffer.IndexOffsets, + submeshBuffer.VertexOffsets, + submeshBuffer.Materials, + pointsBuffer.vertices.ToArray(), + pointsBuffer.indices + ); } private static int AppendSubmeshes( diff --git a/src/cs/vim/Vim.Format.Vimx.Conversion/VimxConverter.cs b/src/cs/vim/Vim.Format.Vimx.Conversion/VimxConverter.cs index 8b763fbe..a5e9d69f 100644 --- a/src/cs/vim/Vim.Format.Vimx.Conversion/VimxConverter.cs +++ b/src/cs/vim/Vim.Format.Vimx.Conversion/VimxConverter.cs @@ -48,7 +48,7 @@ public static Vimx FromVim(G3dVim g3d, DocumentModel bim) sw.Restart(); // Materials are reused from input g3d. - var materials = new G3dMaterials().ReadFromVim(g3d); + var materials = new G3dMaterials(g3d); Console.WriteLine(" G3dMaterials " + sw.ElapsedMilliseconds); var header = VimxHeader.CreateDefault(); @@ -149,24 +149,24 @@ public static G3dScene CreateScene(VimChunks chunks, DocumentModel bim) Console.WriteLine("AABB " + sw.ElapsedMilliseconds); - var scene = new G3dScene() - { - ChunkCount = new[] { chunks.ChunkCount}, - InstanceMeshes = instanceMeshes, - InstanceTransformData = instanceTransforms, - InstanceNodes = instanceNodes, - InstanceFlags = instanceFlags, - InstanceGroups = instanceGroups, - InstanceMaxs = instanceMaxs, - InstanceMins = instanceMins, - InstanceTags = instanceTags, - MeshChunks = chunks.MeshChunks, - MeshChunkIndices = chunks.MeshIndex, - MeshIndexCounts = indexCounts, - MeshVertexCounts = vertexCounts, - MeshOpaqueIndexCounts = opaqueIndexCounts, - MeshOpaqueVertexCounts = opaqueVertexCounts, - }; + var scene = new G3dScene( + + chunkCount: new[] { chunks.ChunkCount}, + instanceMeshes : instanceMeshes, + instanceTransformData: instanceTransforms, + instanceNodes: instanceNodes, + instanceFlags: instanceFlags, + instanceGroups: instanceGroups, + instanceMaxs: instanceMaxs, + instanceMins: instanceMins, + instanceTags: instanceTags, + meshChunks: chunks.MeshChunks, + meshChunkIndices: chunks.MeshIndex, + meshIndexCounts : indexCounts, + meshVertexCounts: vertexCounts, + meshOpaqueIndexCounts: opaqueIndexCounts, + meshOpaqueVertexCounts: opaqueVertexCounts + ); return scene; } diff --git a/src/cs/vim/Vim.Vimx.Test/TestUtils.cs b/src/cs/vim/Vim.Vimx.Test/TestUtils.cs index e3a6dcd0..b7952167 100644 --- a/src/cs/vim/Vim.Vimx.Test/TestUtils.cs +++ b/src/cs/vim/Vim.Vimx.Test/TestUtils.cs @@ -95,25 +95,30 @@ private static long GetMemoryConsumption(Action action) return GC.GetTotalMemory(true) - memBefore; } - public static VimAttributeCollection CreateTestG3d() + public static G3dVim CreateTestG3d() { - var attributes = new VimAttributeCollection(); - - attributes.Positions.TypedData = new Vector3[] { Vector3.Zero, Vector3.UnitX, Vector3.UnitY, Vector3.UnitZ }; - attributes.Indices.TypedData = new int[] { 0, 1, 2, 0, 3, 2, 1, 3, 2 }; - attributes.SubmeshIndexOffsets.TypedData = new int[] { 0, 3, 6 }; - attributes.SubmeshMaterials.TypedData = new int[] { 0 }; - attributes.MeshSubmeshOffsets.TypedData = new int[] { 0 }; - attributes.InstanceTransforms.TypedData = new Matrix4x4[] { Matrix4x4.Identity }; - attributes.InstanceMeshes.TypedData = new int[] { 0 }; - attributes.InstanceParents.TypedData = new int[] { -1 }; - attributes.MaterialColors.TypedData = new Vector4[] { new Vector4(0.25f, 0.5f, 0.75f, 1) }; - attributes.MaterialGlossiness.TypedData = new float[] { .95f }; - attributes.MaterialSmoothness.TypedData = new float[] { .5f }; - - attributes.Validate(); - - return attributes; + var g3d = new G3dVim( + instanceTransforms: new Matrix4x4[] { Matrix4x4.Identity }, + instanceMeshes: new int[] { 0 }, + instanceParents: new int[] { -1 }, + instanceFlags: null, + meshSubmeshOffsets: new int[] { 0 }, + submeshIndexOffsets: new int[] { 0, 3, 6 }, + submeshMaterials: new int[] { 0 }, + indices: new int[] { 0, 1, 2, 0, 3, 2, 1, 3, 2 }, + positions: new Vector3[] { Vector3.Zero, Vector3.UnitX, Vector3.UnitY, Vector3.UnitZ }, + materialColors: new Vector4[] { new Vector4(0.25f, 0.5f, 0.75f, 1) }, + materialGlossiness: new float[] { 0.95f }, + materialSmoothness: new float[] { 0.5f }, + shapeColors: null, + shapeVertexOffsets: null, + shapeVertices: null, + shapeWidths: null + ); + g3d.Validate(); + + + return g3d; } } } diff --git a/src/cs/vim/Vim.Vimx.Test/VimG3dTests.cs b/src/cs/vim/Vim.Vimx.Test/VimG3dTests.cs index e8ad967d..43da036b 100644 --- a/src/cs/vim/Vim.Vimx.Test/VimG3dTests.cs +++ b/src/cs/vim/Vim.Vimx.Test/VimG3dTests.cs @@ -2,61 +2,12 @@ using NUnit.Framework.Internal; using Vim.BFastNS; using Vim.G3dNext.Attributes; -using Vim.Math3d; -using Vim.BFastNS; namespace Vim.G3dNext.Tests { [TestFixture] public static class VimG3dTests { - [Test] - public static void Can_Parse_Attributes() - { - var attributeNames = new VimAttributeCollection().GetAttributeNames(); - foreach (var name in attributeNames) - { - // Test that the attribute descriptor parsing works as intended. - var parsed = AttributeDescriptor.TryParse(name, out var desc); - Assert.IsTrue(parsed); - Assert.AreEqual(name, desc.Name); - } - } - - [Test] - public static void Can_Read_Write_Triangle() - { - // Serialize a triangle g3d as bytes and read it back. - var vertices = new[] - { - new Vector3(0, 0, 0), - new Vector3(0, 1, 0), - new Vector3(0, 1, 1) - }; - - var indices = new[] { 0, 1, 2 }; - - var g3d1 = new VimAttributeCollection(); - g3d1.Positions.TypedData = vertices; - g3d1.Indices.TypedData = indices; - - var memoryStream = new MemoryStream(); - g3d1.ToBFast().Write(memoryStream); - memoryStream.Seek(0, SeekOrigin.Begin); - var bfast = new BFast(memoryStream); - - var g3d2 = new VimAttributeCollection(bfast); - Assert.IsNotNull(g3d2); - - Assert.AreEqual(3, g3d2.Positions.Count); - Assert.AreEqual(3, g3d2.Indices.Count); - Assert.AreEqual(0, g3d2.MeshSubmeshOffsets.Count); - Assert.AreEqual(0, (object)g3d2.InstanceTransforms.Count); - - Assert.AreEqual(vertices, g3d2.Positions.TypedData); - Assert.AreEqual(indices, g3d2.Indices.TypedData); - } - [Test] public static void Can_Read_G3d_From_Vim() { @@ -72,12 +23,8 @@ public static void Can_Ignore_Extra_Attributes() // We create a g3dMaterial from the bytes of a g3dVim // Shows that extra attributes are ignored as they should. - var memoryStream = new MemoryStream(); - var g3d = G3dVim.FromVim(TestUtils.ResidencePath); - g3d.ToBFast().Write(memoryStream); - memoryStream.Seek(0, SeekOrigin.Begin); - var bfast = new BFast(memoryStream); - var g3dMats = new G3dMaterials(bfast); + var g3d = TestUtils.CreateTestG3d(); + var g3dMats = new G3dMaterials(g3d.ToBFast()); Assert.IsNotNull(g3dMats); Assert.AreEqual(g3d.MaterialColors, g3dMats.MaterialColors); @@ -88,98 +35,36 @@ public static void Can_Ignore_Extra_Attributes() [Test] public static void Can_Write_And_Read() { - var testDir = TestUtils.PrepareTestDir(); - var g3d = TestUtils.CreateTestG3d(); - - var g3dFilePath = Path.Combine(testDir, "test.g3d"); - g3d.ToBFast().Write(g3dFilePath); - var result = g3dFilePath.ReadBFast((b) => new VimAttributeCollection(b)); - - foreach (var attributeName in result.GetAttributeNames()) - { - var attr0 = g3d.Map[attributeName]; - var attr1 = result.Map[attributeName]; - Assert.AreEqual(attr0.Data, attr1.Data); - } + var expected = TestUtils.CreateTestG3d(); + var g3d = new G3dVim(expected.ToBFast()); + Assert.IsTrue(g3d.Equals(expected)); } [Test] public static void Can_Merge_two_g3d() { - var testDir = TestUtils.PrepareTestDir(); var g3d = TestUtils.CreateTestG3d(); - - var mergedG3d = new[] { g3d, g3d }.Merge(); - - var memoryStream = new MemoryStream(); - var g3dFilePath = Path.Combine(testDir!, "merged.g3d"); - mergedG3d.ToBFast().Write(memoryStream); - memoryStream.Seek(0, SeekOrigin.Begin); - var bfast = new BFast(memoryStream); - - - var g3dResult = new VimAttributeCollection(bfast); - Assert.NotNull(g3d); - - { - var merged = Enumerable.Repeat(g3d.Positions.TypedData, 2).SelectMany(v => v).ToArray(); - Assert.AreEqual(merged, g3dResult.Positions.TypedData); - } - - { - var tmp = g3d.Indices.TypedData; - var merged = new[] { tmp, tmp.Select(i => i + g3d.Positions.Count).ToArray() }.SelectMany(v => v).ToArray(); - Assert.AreEqual(merged, g3dResult.Indices.TypedData); - } - - { - var tmp = g3d.SubmeshIndexOffsets.TypedData; - var merged = new[] { tmp, tmp.Select(i => i + g3d.Indices.Count).ToArray() }.SelectMany(v => v).ToArray(); - Assert.AreEqual(merged, g3dResult.SubmeshIndexOffsets.TypedData); - } - - { - var tmp = g3d.SubmeshMaterials.TypedData; - var merged = new[] { tmp, tmp.Select(i => i + g3d.MaterialColors.Count).ToArray() }.SelectMany(v => v).ToArray(); - Assert.AreEqual(merged, g3dResult.SubmeshMaterials.TypedData); - } - - { - var tmp = g3d.MeshSubmeshOffsets.TypedData; - var merged = new[] { tmp, tmp.Select(i => i + g3d.SubmeshIndexOffsets.Count).ToArray() }.SelectMany(v => v).ToArray(); - Assert.AreEqual(merged, g3dResult.MeshSubmeshOffsets.TypedData); - } - - { - var merged = Enumerable.Repeat(g3d.InstanceTransforms.TypedData, 2).SelectMany(v => v).ToArray(); - Assert.AreEqual((object)merged, (object)g3dResult.InstanceTransforms.TypedData); - } - - { - var tmp = g3d.InstanceMeshes.TypedData; - var merged = new[] { tmp, tmp.Select(i => i + g3d.MeshSubmeshOffsets.Count).ToArray() }.SelectMany(v => v).ToArray(); - Assert.AreEqual(merged, g3dResult.InstanceMeshes.TypedData); - } - - { - var merged = Enumerable.Repeat(g3d.InstanceParents.TypedData, 2).SelectMany(v => v).ToArray(); - Assert.AreEqual(merged, g3dResult.InstanceParents.TypedData); - } - - { - var merged = Enumerable.Repeat(g3d.MaterialColors.TypedData, 2).SelectMany(v => v).ToArray(); - Assert.AreEqual(merged, g3dResult.MaterialColors.TypedData); - } - - { - var merged = Enumerable.Repeat(g3d.MaterialGlossiness.TypedData, 2).SelectMany(v => v).ToArray(); - Assert.AreEqual(merged, g3dResult.MaterialGlossiness.TypedData); - } - - { - var merged = Enumerable.Repeat(g3d.MaterialSmoothness.TypedData, 2).SelectMany(v => v).ToArray(); - Assert.AreEqual(merged, g3dResult.MaterialSmoothness.TypedData); - } + var merged = g3d.Merge(g3d); + + var expected = new G3dVim( + instanceTransforms: g3d.InstanceTransforms.Concat(g3d.InstanceTransforms).ToArray(), + instanceMeshes: g3d.InstanceMeshes.Concat(g3d.InstanceMeshes.Select(i => i + g3d.GetMeshCount())).ToArray(), + instanceParents: g3d.InstanceParents.Concat(g3d.InstanceParents).ToArray(), + instanceFlags: null, + meshSubmeshOffsets: g3d.MeshSubmeshOffsets.Concat(g3d.MeshSubmeshOffsets.Select(i => g3d.GetSubmeshCount())).ToArray(), + submeshIndexOffsets: g3d.SubmeshIndexOffsets.Concat(g3d.SubmeshIndexOffsets.Select(i => i + g3d.GetIndexCount())).ToArray(), + submeshMaterials: g3d.SubmeshMaterials.Concat(g3d.SubmeshMaterials.Select(i => i + g3d.GetMaterialCount())).ToArray(), + indices: g3d.Indices.Concat(g3d.Indices.Select(i => i + g3d.Positions.Length)).ToArray(), + positions: g3d.Positions.Concat(g3d.Positions).ToArray(), + materialColors: g3d.MaterialColors.Concat(g3d.MaterialColors).ToArray(), + materialGlossiness: g3d.MaterialGlossiness.Concat(g3d.MaterialGlossiness).ToArray(), + materialSmoothness: g3d.MaterialSmoothness.Concat(g3d.MaterialSmoothness).ToArray(), + shapeColors: null, + shapeWidths: null, + shapeVertices: null, + shapeVertexOffsets: null + ); + Assert.IsTrue(merged.Equals(expected)); } } diff --git a/src/cs/vim/Vim.Vimx.Test/VimxActions.cs b/src/cs/vim/Vim.Vimx.Test/VimxActions.cs index f6db6697..2ee53818 100644 --- a/src/cs/vim/Vim.Vimx.Test/VimxActions.cs +++ b/src/cs/vim/Vim.Vimx.Test/VimxActions.cs @@ -16,8 +16,8 @@ public static class VimxActions public static void ConvertVimToVimx() { // var input = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); - //var input = Path.Join(VimFormatRepoPaths.DataDir, whiteleys); - var input = Path.Join(VimFormatRepoPaths.DataDir, "nbk.vim"); + var input = Path.Join(VimFormatRepoPaths.DataDir, residence); + // var input = Path.Join(VimFormatRepoPaths.DataDir, "nbk.vim"); var name = Path.GetFileNameWithoutExtension(input); var output = Path.Combine(VimFormatRepoPaths.OutDir, name + ".vimx"); From add8ea3cbf71848c10a193a9969a18239d0fac53 Mon Sep 17 00:00:00 2001 From: simon Date: Mon, 22 Jan 2024 13:41:04 -0500 Subject: [PATCH 051/111] fixed namespaces, removed dead code --- src/cs/Vim.G3dNext.Tests/G3dTestUtils.cs | 33 +++ .../Vim.G3dNext.Tests.csproj | 24 +++ src/cs/Vim.G3dNext.Tests/VimG3dTests.cs | 70 +++++++ src/cs/g3d/Vim.G3d.Tests/G3dTestUtils.cs | 69 ------- .../Properties/Resources.Designer.cs | 4 +- src/cs/g3d/Vim.G3d.Tests/Vim.G3d.Tests.csproj | 2 + ...teCollectionGenerator.cs => G3dCodeGen.cs} | 13 +- src/cs/g3d/Vim.G3dNext.CodeGen/Program.cs | 2 +- .../Vim.G3dNext.CodeGen.csproj | 3 +- src/cs/g3d/Vim.G3dNext/BufferMethods.cs | 63 ++++++ src/cs/g3d/Vim.G3dNext/G3dChunk.cs | 2 +- .../{Entities.g.cs => G3dGenerated.g.cs} | 188 +++++++++--------- src/cs/g3d/Vim.G3dNext/G3dMaterials.cs | 5 +- src/cs/g3d/Vim.G3dNext/G3dScene.cs | 2 +- src/cs/g3d/Vim.G3dNext/G3dVim.cs | 2 +- src/cs/g3d/Vim.G3dNext/Vim.G3dNext.csproj | 1 + src/cs/util/Vim.Util.Tests/TestUtils.cs | 101 ++++++++++ .../util/Vim.Util.Tests/Vim.Util.Tests.csproj | 1 + src/cs/vim-format.sln | 14 +- src/cs/vim/Vim.Format.Core/G3dBuilder.cs | 2 +- .../Vim.Format.Core/Vim.Format.Core.csproj | 1 - .../Vim.Format.Vimx.Conversion/Chunking.cs | 145 ++------------ .../Vim.Format.Vimx.Conversion/Ordering.cs | 2 +- .../Vim.Format.Vimx.Conversion.csproj | 1 - .../VimxConverter.cs | 28 +-- .../Vim.Format.Vimx/Vim.Format.Vimx.csproj | 1 - src/cs/vim/Vim.Format.Vimx/Vimx.cs | 4 +- src/cs/vim/Vim.Format.Vimx/VimxChunk.cs | 2 +- src/cs/vim/Vim.Vimx.Test/TestUtils.cs | 1 - .../Vim.Vimx.Test/Vim.Format.Vimx.Test.csproj | 1 - src/cs/vim/Vim.Vimx.Test/VimG3dTests.cs | 2 +- src/cs/vim/Vim.Vimx.Test/VimxActions.cs | 8 - src/cs/vim/Vim.Vimx.Test/VimxTests.cs | 16 -- src/ts/package-lock.json | 4 +- 34 files changed, 437 insertions(+), 380 deletions(-) create mode 100644 src/cs/Vim.G3dNext.Tests/G3dTestUtils.cs create mode 100644 src/cs/Vim.G3dNext.Tests/Vim.G3dNext.Tests.csproj create mode 100644 src/cs/Vim.G3dNext.Tests/VimG3dTests.cs delete mode 100644 src/cs/g3d/Vim.G3d.Tests/G3dTestUtils.cs rename src/cs/g3d/Vim.G3dNext.CodeGen/{G3dAttributeCollectionGenerator.cs => G3dCodeGen.cs} (87%) create mode 100644 src/cs/g3d/Vim.G3dNext/BufferMethods.cs rename src/cs/g3d/Vim.G3dNext/{Entities.g.cs => G3dGenerated.g.cs} (68%) create mode 100644 src/cs/util/Vim.Util.Tests/TestUtils.cs diff --git a/src/cs/Vim.G3dNext.Tests/G3dTestUtils.cs b/src/cs/Vim.G3dNext.Tests/G3dTestUtils.cs new file mode 100644 index 00000000..6de8060f --- /dev/null +++ b/src/cs/Vim.G3dNext.Tests/G3dTestUtils.cs @@ -0,0 +1,33 @@ +using Vim.Math3d; + +namespace Vim.G3dNext.Tests +{ + public static class G3dTestUtils + { + public static G3dVim CreateTestG3d() + { + var g3d = new G3dVim( + instanceTransforms: new Matrix4x4[] { Matrix4x4.Identity }, + instanceMeshes: new int[] { 0 }, + instanceParents: new int[] { -1 }, + instanceFlags: null, + meshSubmeshOffsets: new int[] { 0 }, + submeshIndexOffsets: new int[] { 0, 3, 6 }, + submeshMaterials: new int[] { 0 }, + indices: new int[] { 0, 1, 2, 0, 3, 2, 1, 3, 2 }, + positions: new Vector3[] { Vector3.Zero, Vector3.UnitX, Vector3.UnitY, Vector3.UnitZ }, + materialColors: new Vector4[] { new Vector4(0.25f, 0.5f, 0.75f, 1) }, + materialGlossiness: new float[] { 0.95f }, + materialSmoothness: new float[] { 0.5f }, + shapeColors: null, + shapeVertexOffsets: null, + shapeVertices: null, + shapeWidths: null + ); + g3d.Validate(); + + + return g3d; + } + } +} diff --git a/src/cs/Vim.G3dNext.Tests/Vim.G3dNext.Tests.csproj b/src/cs/Vim.G3dNext.Tests/Vim.G3dNext.Tests.csproj new file mode 100644 index 00000000..e11e95ad --- /dev/null +++ b/src/cs/Vim.G3dNext.Tests/Vim.G3dNext.Tests.csproj @@ -0,0 +1,24 @@ + + + + net6.0 + enable + enable + + false + true + + + + + + + + + + + + + + + diff --git a/src/cs/Vim.G3dNext.Tests/VimG3dTests.cs b/src/cs/Vim.G3dNext.Tests/VimG3dTests.cs new file mode 100644 index 00000000..75b84527 --- /dev/null +++ b/src/cs/Vim.G3dNext.Tests/VimG3dTests.cs @@ -0,0 +1,70 @@ +using NUnit.Framework; +using NUnit.Framework.Internal; +using Vim.BFastNS; + +namespace Vim.G3dNext.Tests +{ + [TestFixture] + public static class VimG3dTests + { + [Test] + public static void Can_Read_G3d_From_Vim() + { + var g3d = G3dVim.FromVim(TestUtils.ResidencePath); + Assert.IsNotNull(g3d); + } + + [Test] + public static void Can_Ignore_Extra_Attributes() + { + // Both G3dVim and G3dMaterial share 3 attributes + // G3dVim contains many more attributes + // We create a g3dMaterial from the bytes of a g3dVim + // Shows that extra attributes are ignored as they should. + + var g3d = G3dTestUtils.CreateTestG3d(); + var g3dMats = new G3dMaterials(g3d.ToBFast()); + + Assert.IsNotNull(g3dMats); + Assert.AreEqual(g3d.MaterialColors, g3dMats.MaterialColors); + Assert.AreEqual(g3d.MaterialGlossiness, g3dMats.MaterialGlossiness); + Assert.AreEqual(g3d.MaterialSmoothness, g3dMats.MaterialSmoothness); + } + + [Test] + public static void Can_Write_And_Read() + { + var expected = G3dTestUtils.CreateTestG3d(); + var g3d = new G3dVim(expected.ToBFast()); + Assert.IsTrue(g3d.Equals(expected)); + } + + [Test] + public static void Can_Merge_two_g3d() + { + var g3d = G3dTestUtils.CreateTestG3d(); + var merged = g3d.Merge(g3d); + + var expected = new G3dVim( + instanceTransforms: g3d.InstanceTransforms.Concat(g3d.InstanceTransforms).ToArray(), + instanceMeshes: g3d.InstanceMeshes.Concat(g3d.InstanceMeshes.Select(i => i + g3d.GetMeshCount())).ToArray(), + instanceParents: g3d.InstanceParents.Concat(g3d.InstanceParents).ToArray(), + instanceFlags: null, + meshSubmeshOffsets: g3d.MeshSubmeshOffsets.Concat(g3d.MeshSubmeshOffsets.Select(i => g3d.GetSubmeshCount())).ToArray(), + submeshIndexOffsets: g3d.SubmeshIndexOffsets.Concat(g3d.SubmeshIndexOffsets.Select(i => i + g3d.GetIndexCount())).ToArray(), + submeshMaterials: g3d.SubmeshMaterials.Concat(g3d.SubmeshMaterials.Select(i => i + g3d.GetMaterialCount())).ToArray(), + indices: g3d.Indices.Concat(g3d.Indices.Select(i => i + g3d.Positions.Length)).ToArray(), + positions: g3d.Positions.Concat(g3d.Positions).ToArray(), + materialColors: g3d.MaterialColors.Concat(g3d.MaterialColors).ToArray(), + materialGlossiness: g3d.MaterialGlossiness.Concat(g3d.MaterialGlossiness).ToArray(), + materialSmoothness: g3d.MaterialSmoothness.Concat(g3d.MaterialSmoothness).ToArray(), + shapeColors: null, + shapeWidths: null, + shapeVertices: null, + shapeVertexOffsets: null + ); + Assert.IsTrue(merged.Equals(expected)); + } + } +} + diff --git a/src/cs/g3d/Vim.G3d.Tests/G3dTestUtils.cs b/src/cs/g3d/Vim.G3d.Tests/G3dTestUtils.cs deleted file mode 100644 index 0ebb530f..00000000 --- a/src/cs/g3d/Vim.G3d.Tests/G3dTestUtils.cs +++ /dev/null @@ -1,69 +0,0 @@ -using Assimp; -using NUnit.Framework; -using System; -using System.Diagnostics; -using System.IO; -using System.Linq; -using Vim.G3d.AssimpWrapper; -using Vim.LinqArray; - -namespace Vim.G3d.Tests -{ - public static class G3dTestUtils - { - public static void OutputSceneStats(Scene scene) - => Console.WriteLine( -$@" #animations = {scene.AnimationCount} - #cameras = {scene.CameraCount} - #lights = {scene.LightCount} - #materials = {scene.MaterialCount} - #meshes = {scene.MeshCount} - #nodes = {scene.GetNodes().Count()} - #textures = {scene.TextureCount}"); - - // TODO: merge all of the meshes using the transform. - - public static void OutputMeshStats(Mesh mesh) - => Console.WriteLine( - $@" - mesh {mesh.Name} - #faces = {mesh.FaceCount} - #vertices = {mesh.VertexCount} - #normals = {mesh.Normals?.Count ?? 0} - #texture coordinate chanels = {mesh.TextureCoordinateChannelCount} - #vertex color chanels = {mesh.VertexColorChannelCount} - #bones = {mesh.BoneCount} - #tangents = {mesh.Tangents?.Count} - #bitangents = {mesh.BiTangents?.Count}"); - - public static T TimeLoadingFile(string fileName, Func func) - { - var sw = new Stopwatch(); - sw.Start(); - try - { - return func(fileName); - } - finally - { - Console.WriteLine($"Time to open {Path.GetFileName(fileName)} is {sw.ElapsedMilliseconds}msec"); - } - } - - public static void OutputStats(G3D g) - { - //Console.WriteLine("Header"); - - Console.WriteLine($"# corners per faces {g.NumCornersPerFace} "); - Console.WriteLine($"# vertices = {g.NumVertices}"); - Console.WriteLine($"# faces = {g.NumFaces}"); - Console.WriteLine($"# subgeos = {g.NumMeshes}"); - Console.WriteLine($"# indices (corners/edges0 = {g.NumCorners}"); - Console.WriteLine($"# instances = {g.NumInstances}"); - Console.WriteLine($"Number of attributes = {g.Attributes.Count}"); - - foreach (var attr in g.Attributes.ToEnumerable()) - Console.WriteLine($"{attr.Name} #items={attr.ElementCount}"); - } - } -} diff --git a/src/cs/g3d/Vim.G3d.Tests/Properties/Resources.Designer.cs b/src/cs/g3d/Vim.G3d.Tests/Properties/Resources.Designer.cs index 2f5f4dfd..dba826c3 100644 --- a/src/cs/g3d/Vim.G3d.Tests/Properties/Resources.Designer.cs +++ b/src/cs/g3d/Vim.G3d.Tests/Properties/Resources.Designer.cs @@ -19,7 +19,7 @@ namespace Vim.G3d.Tests.Properties { // class via a tool like ResGen or Visual Studio. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] internal class Resources { @@ -61,7 +61,7 @@ internal Resources() { } /// - /// Looks up a localized string similar to C:\DEV\g3d\csharp\Vim.G3d.Tests\ + /// Looks up a localized string similar to C:\Users\Rober\Desktop\Vim\vim-format\src\cs\g3d\Vim.G3d.Tests\ ///. /// internal static string ProjDir { diff --git a/src/cs/g3d/Vim.G3d.Tests/Vim.G3d.Tests.csproj b/src/cs/g3d/Vim.G3d.Tests/Vim.G3d.Tests.csproj index 285c4437..e5fca662 100644 --- a/src/cs/g3d/Vim.G3d.Tests/Vim.G3d.Tests.csproj +++ b/src/cs/g3d/Vim.G3d.Tests/Vim.G3d.Tests.csproj @@ -14,6 +14,8 @@ + + diff --git a/src/cs/g3d/Vim.G3dNext.CodeGen/G3dAttributeCollectionGenerator.cs b/src/cs/g3d/Vim.G3dNext.CodeGen/G3dCodeGen.cs similarity index 87% rename from src/cs/g3d/Vim.G3dNext.CodeGen/G3dAttributeCollectionGenerator.cs rename to src/cs/g3d/Vim.G3dNext.CodeGen/G3dCodeGen.cs index 7707e1ed..f092be93 100644 --- a/src/cs/g3d/Vim.G3dNext.CodeGen/G3dAttributeCollectionGenerator.cs +++ b/src/cs/g3d/Vim.G3dNext.CodeGen/G3dCodeGen.cs @@ -4,7 +4,7 @@ namespace Vim.G3dNext.CodeGen { - public static class G3dAttributeCollectionGenerator + public static class G3dCodeGen { public static void WriteDocument(string filePath) { @@ -16,7 +16,7 @@ public static void WriteDocument(string filePath) cb.AppendLine("// ReSharper disable All"); cb.AppendLine("using Vim.BFastNS;"); cb.AppendLine(); - cb.AppendLine("namespace Vim.G3dNext.Attributes"); + cb.AppendLine("namespace Vim.G3dNext"); cb.AppendLine("{"); WriteEntities(cb); cb.AppendLine("}"); @@ -89,7 +89,7 @@ public bool Equals({entity.ClassName} other ) {{ return {string.Join(" && \n \t\t\t", entity.Buffers.Select(b => { - return $"{b.MemberName}.SafeEquals(other.{b.MemberName})"; + return $"BufferMethods.SafeEquals({b.MemberName}, other.{b.MemberName})"; }))}; }} @@ -103,9 +103,9 @@ public bool Equals({entity.ClassName} other ) case BufferType.Singleton: return $"{b.MemberName}"; case BufferType.Data: - return $"{b.MemberName}.MergeData(other.{b.MemberName})"; + return $"BufferMethods.MergeData({b.MemberName}, other.{b.MemberName})"; case BufferType.Index: - return $"{b.MemberName}.MergeIndices(other.{b.MemberName}, {b.IndexInto}?.Length ?? 0)"; + return $"BufferMethods.MergeIndex({b.MemberName}, other.{b.MemberName}, {b.IndexInto}?.Length ?? 0)"; default: return ""; } @@ -120,7 +120,7 @@ public void Validate() { if (c.BufferType == BufferType.Index) { - return $"{c.MemberName}?.ValidateIndex({c.IndexInto}, \"{c.MemberName}\");"; + return $"BufferMethods.ValidateIndex({c.MemberName}, {c.IndexInto}, \"{c.MemberName}\");"; } return null; }).Where(s => s != null))} @@ -131,3 +131,4 @@ public void Validate() } } + diff --git a/src/cs/g3d/Vim.G3dNext.CodeGen/Program.cs b/src/cs/g3d/Vim.G3dNext.CodeGen/Program.cs index 15a810c1..5470fb2f 100644 --- a/src/cs/g3d/Vim.G3dNext.CodeGen/Program.cs +++ b/src/cs/g3d/Vim.G3dNext.CodeGen/Program.cs @@ -5,7 +5,7 @@ public static class Program public static void Main(string[] args) { var file = args[0]; - G3dAttributeCollectionGenerator.WriteDocument(file); + G3dCodeGen.WriteDocument(file); } } } diff --git a/src/cs/g3d/Vim.G3dNext.CodeGen/Vim.G3dNext.CodeGen.csproj b/src/cs/g3d/Vim.G3dNext.CodeGen/Vim.G3dNext.CodeGen.csproj index fdc9193d..46cd3717 100644 --- a/src/cs/g3d/Vim.G3dNext.CodeGen/Vim.G3dNext.CodeGen.csproj +++ b/src/cs/g3d/Vim.G3dNext.CodeGen/Vim.G3dNext.CodeGen.csproj @@ -13,11 +13,10 @@ - - + \ No newline at end of file diff --git a/src/cs/g3d/Vim.G3dNext/BufferMethods.cs b/src/cs/g3d/Vim.G3dNext/BufferMethods.cs new file mode 100644 index 00000000..e4f74d70 --- /dev/null +++ b/src/cs/g3d/Vim.G3dNext/BufferMethods.cs @@ -0,0 +1,63 @@ +using System; +using System.IO; +using System.Linq; + +namespace Vim.G3dNext +{ + public static class BufferMethods + { + public static bool SafeEquals(T[] a, T[] b) + { + if(a == null && b == null) return true; + if(a == null) return false; + if(b == null) return false; + if(a.Length != b.Length) return false; + for(var i=0; i(T[] a, T[] b) + { + if(a == null && b == null) return null; + if(a == null) { return b.ToArray(); } + if(b == null) { return a.ToArray(); } + var result = new T[a.Length + b.Length]; + Array.Copy(a, result, a.Length); + Array.Copy(b, 0, result, a.Length, b.Length); + return result; + } + + public static int[] MergeIndex(int[] a, int[] b, int offset) + { + if (a == null && b == null) return null; + if (a == null && b == null) return null; + if (a == null) { return b.ToArray(); } + if (b == null) { return a.ToArray(); } + var result = new int[a.Length + b.Length]; + Array.Copy(a, result, a.Length); + for(var i=0; i= 0 + ? offset + b[i] + : -1; + } + return result; + } + + public static void ValidateIndex(int[] array, T[] into, string name) + { + if (array == null) return; + var max = into?.Length -1 ?? int.MaxValue; + for(var i=0; i < array.Length; i++) + { + if (array[i] < -1 || array[i] > max) + { + throw new InvalidDataException($"Invalid value {array[i]} in {name} buffer."); + } + } + } + } +} diff --git a/src/cs/g3d/Vim.G3dNext/G3dChunk.cs b/src/cs/g3d/Vim.G3dNext/G3dChunk.cs index 698a29de..a4e35834 100644 --- a/src/cs/g3d/Vim.G3dNext/G3dChunk.cs +++ b/src/cs/g3d/Vim.G3dNext/G3dChunk.cs @@ -1,7 +1,7 @@ using System; using Vim.Math3d; -namespace Vim.G3dNext.Attributes +namespace Vim.G3dNext { public partial class G3dChunk { diff --git a/src/cs/g3d/Vim.G3dNext/Entities.g.cs b/src/cs/g3d/Vim.G3dNext/G3dGenerated.g.cs similarity index 68% rename from src/cs/g3d/Vim.G3dNext/Entities.g.cs rename to src/cs/g3d/Vim.G3dNext/G3dGenerated.g.cs index 92e3b922..2783b521 100644 --- a/src/cs/g3d/Vim.G3dNext/Entities.g.cs +++ b/src/cs/g3d/Vim.G3dNext/G3dGenerated.g.cs @@ -2,7 +2,7 @@ // ReSharper disable All using Vim.BFastNS; -namespace Vim.G3dNext.Attributes +namespace Vim.G3dNext { // Please provide an explicit implementation in another partial class file. public partial class G3dVim : ISetup @@ -111,56 +111,56 @@ public BFast ToBFast() public bool Equals(G3dVim other ) { - return Indices.SafeEquals(other.Indices) && - Positions.SafeEquals(other.Positions) && - InstanceTransforms.SafeEquals(other.InstanceTransforms) && - InstanceParents.SafeEquals(other.InstanceParents) && - InstanceFlags.SafeEquals(other.InstanceFlags) && - InstanceMeshes.SafeEquals(other.InstanceMeshes) && - MeshSubmeshOffsets.SafeEquals(other.MeshSubmeshOffsets) && - SubmeshIndexOffsets.SafeEquals(other.SubmeshIndexOffsets) && - SubmeshMaterials.SafeEquals(other.SubmeshMaterials) && - MaterialColors.SafeEquals(other.MaterialColors) && - MaterialGlossiness.SafeEquals(other.MaterialGlossiness) && - MaterialSmoothness.SafeEquals(other.MaterialSmoothness) && - ShapeVertices.SafeEquals(other.ShapeVertices) && - ShapeVertexOffsets.SafeEquals(other.ShapeVertexOffsets) && - ShapeColors.SafeEquals(other.ShapeColors) && - ShapeWidths.SafeEquals(other.ShapeWidths); + return BufferMethods.SafeEquals(Indices, other.Indices) && + BufferMethods.SafeEquals(Positions, other.Positions) && + BufferMethods.SafeEquals(InstanceTransforms, other.InstanceTransforms) && + BufferMethods.SafeEquals(InstanceParents, other.InstanceParents) && + BufferMethods.SafeEquals(InstanceFlags, other.InstanceFlags) && + BufferMethods.SafeEquals(InstanceMeshes, other.InstanceMeshes) && + BufferMethods.SafeEquals(MeshSubmeshOffsets, other.MeshSubmeshOffsets) && + BufferMethods.SafeEquals(SubmeshIndexOffsets, other.SubmeshIndexOffsets) && + BufferMethods.SafeEquals(SubmeshMaterials, other.SubmeshMaterials) && + BufferMethods.SafeEquals(MaterialColors, other.MaterialColors) && + BufferMethods.SafeEquals(MaterialGlossiness, other.MaterialGlossiness) && + BufferMethods.SafeEquals(MaterialSmoothness, other.MaterialSmoothness) && + BufferMethods.SafeEquals(ShapeVertices, other.ShapeVertices) && + BufferMethods.SafeEquals(ShapeVertexOffsets, other.ShapeVertexOffsets) && + BufferMethods.SafeEquals(ShapeColors, other.ShapeColors) && + BufferMethods.SafeEquals(ShapeWidths, other.ShapeWidths); } public G3dVim Merge(G3dVim other) { return new G3dVim( - Indices.MergeIndices(other.Indices, Positions?.Length ?? 0), - Positions.MergeData(other.Positions), - InstanceTransforms.MergeData(other.InstanceTransforms), - InstanceParents.MergeIndices(other.InstanceParents, InstanceTransforms?.Length ?? 0), - InstanceFlags.MergeData(other.InstanceFlags), - InstanceMeshes.MergeIndices(other.InstanceMeshes, MeshSubmeshOffsets?.Length ?? 0), - MeshSubmeshOffsets.MergeIndices(other.MeshSubmeshOffsets, SubmeshIndexOffsets?.Length ?? 0), - SubmeshIndexOffsets.MergeIndices(other.SubmeshIndexOffsets, Indices?.Length ?? 0), - SubmeshMaterials.MergeIndices(other.SubmeshMaterials, MaterialColors?.Length ?? 0), - MaterialColors.MergeData(other.MaterialColors), - MaterialGlossiness.MergeData(other.MaterialGlossiness), - MaterialSmoothness.MergeData(other.MaterialSmoothness), - ShapeVertices.MergeData(other.ShapeVertices), - ShapeVertexOffsets.MergeIndices(other.ShapeVertexOffsets, ShapeVertices?.Length ?? 0), - ShapeColors.MergeData(other.ShapeColors), - ShapeWidths.MergeData(other.ShapeWidths) + BufferMethods.MergeIndex(Indices, other.Indices, Positions?.Length ?? 0), + BufferMethods.MergeData(Positions, other.Positions), + BufferMethods.MergeData(InstanceTransforms, other.InstanceTransforms), + BufferMethods.MergeIndex(InstanceParents, other.InstanceParents, InstanceTransforms?.Length ?? 0), + BufferMethods.MergeData(InstanceFlags, other.InstanceFlags), + BufferMethods.MergeIndex(InstanceMeshes, other.InstanceMeshes, MeshSubmeshOffsets?.Length ?? 0), + BufferMethods.MergeIndex(MeshSubmeshOffsets, other.MeshSubmeshOffsets, SubmeshIndexOffsets?.Length ?? 0), + BufferMethods.MergeIndex(SubmeshIndexOffsets, other.SubmeshIndexOffsets, Indices?.Length ?? 0), + BufferMethods.MergeIndex(SubmeshMaterials, other.SubmeshMaterials, MaterialColors?.Length ?? 0), + BufferMethods.MergeData(MaterialColors, other.MaterialColors), + BufferMethods.MergeData(MaterialGlossiness, other.MaterialGlossiness), + BufferMethods.MergeData(MaterialSmoothness, other.MaterialSmoothness), + BufferMethods.MergeData(ShapeVertices, other.ShapeVertices), + BufferMethods.MergeIndex(ShapeVertexOffsets, other.ShapeVertexOffsets, ShapeVertices?.Length ?? 0), + BufferMethods.MergeData(ShapeColors, other.ShapeColors), + BufferMethods.MergeData(ShapeWidths, other.ShapeWidths) ); } public void Validate() { // Ensure all the indices are either -1 or within the bounds of the attributes they are indexing into. - Indices?.ValidateIndex(Positions, "Indices"); - InstanceParents?.ValidateIndex(InstanceTransforms, "InstanceParents"); - InstanceMeshes?.ValidateIndex(MeshSubmeshOffsets, "InstanceMeshes"); - MeshSubmeshOffsets?.ValidateIndex(SubmeshIndexOffsets, "MeshSubmeshOffsets"); - SubmeshIndexOffsets?.ValidateIndex(Indices, "SubmeshIndexOffsets"); - SubmeshMaterials?.ValidateIndex(MaterialColors, "SubmeshMaterials"); - ShapeVertexOffsets?.ValidateIndex(ShapeVertices, "ShapeVertexOffsets"); + BufferMethods.ValidateIndex(Indices, Positions, "Indices"); + BufferMethods.ValidateIndex(InstanceParents, InstanceTransforms, "InstanceParents"); + BufferMethods.ValidateIndex(InstanceMeshes, MeshSubmeshOffsets, "InstanceMeshes"); + BufferMethods.ValidateIndex(MeshSubmeshOffsets, SubmeshIndexOffsets, "MeshSubmeshOffsets"); + BufferMethods.ValidateIndex(SubmeshIndexOffsets, Indices, "SubmeshIndexOffsets"); + BufferMethods.ValidateIndex(SubmeshMaterials, MaterialColors, "SubmeshMaterials"); + BufferMethods.ValidateIndex(ShapeVertexOffsets, ShapeVertices, "ShapeVertexOffsets"); } } @@ -226,35 +226,35 @@ public BFast ToBFast() public bool Equals(G3dChunk other ) { - return MeshOpaqueSubmeshCounts.SafeEquals(other.MeshOpaqueSubmeshCounts) && - MeshSubmeshOffset.SafeEquals(other.MeshSubmeshOffset) && - SubmeshIndexOffsets.SafeEquals(other.SubmeshIndexOffsets) && - SubmeshVertexOffsets.SafeEquals(other.SubmeshVertexOffsets) && - SubmeshMaterials.SafeEquals(other.SubmeshMaterials) && - Positions.SafeEquals(other.Positions) && - Indices.SafeEquals(other.Indices); + return BufferMethods.SafeEquals(MeshOpaqueSubmeshCounts, other.MeshOpaqueSubmeshCounts) && + BufferMethods.SafeEquals(MeshSubmeshOffset, other.MeshSubmeshOffset) && + BufferMethods.SafeEquals(SubmeshIndexOffsets, other.SubmeshIndexOffsets) && + BufferMethods.SafeEquals(SubmeshVertexOffsets, other.SubmeshVertexOffsets) && + BufferMethods.SafeEquals(SubmeshMaterials, other.SubmeshMaterials) && + BufferMethods.SafeEquals(Positions, other.Positions) && + BufferMethods.SafeEquals(Indices, other.Indices); } public G3dChunk Merge(G3dChunk other) { return new G3dChunk( - MeshOpaqueSubmeshCounts.MergeData(other.MeshOpaqueSubmeshCounts), - MeshSubmeshOffset.MergeIndices(other.MeshSubmeshOffset, Indices?.Length ?? 0), - SubmeshIndexOffsets.MergeIndices(other.SubmeshIndexOffsets, Indices?.Length ?? 0), - SubmeshVertexOffsets.MergeIndices(other.SubmeshVertexOffsets, Indices?.Length ?? 0), - SubmeshMaterials.MergeData(other.SubmeshMaterials), - Positions.MergeData(other.Positions), - Indices.MergeIndices(other.Indices, Positions?.Length ?? 0) + BufferMethods.MergeData(MeshOpaqueSubmeshCounts, other.MeshOpaqueSubmeshCounts), + BufferMethods.MergeIndex(MeshSubmeshOffset, other.MeshSubmeshOffset, Indices?.Length ?? 0), + BufferMethods.MergeIndex(SubmeshIndexOffsets, other.SubmeshIndexOffsets, Indices?.Length ?? 0), + BufferMethods.MergeIndex(SubmeshVertexOffsets, other.SubmeshVertexOffsets, Indices?.Length ?? 0), + BufferMethods.MergeData(SubmeshMaterials, other.SubmeshMaterials), + BufferMethods.MergeData(Positions, other.Positions), + BufferMethods.MergeIndex(Indices, other.Indices, Positions?.Length ?? 0) ); } public void Validate() { // Ensure all the indices are either -1 or within the bounds of the attributes they are indexing into. - MeshSubmeshOffset?.ValidateIndex(Indices, "MeshSubmeshOffset"); - SubmeshIndexOffsets?.ValidateIndex(Indices, "SubmeshIndexOffsets"); - SubmeshVertexOffsets?.ValidateIndex(Indices, "SubmeshVertexOffsets"); - Indices?.ValidateIndex(Positions, "Indices"); + BufferMethods.ValidateIndex(MeshSubmeshOffset, Indices, "MeshSubmeshOffset"); + BufferMethods.ValidateIndex(SubmeshIndexOffsets, Indices, "SubmeshIndexOffsets"); + BufferMethods.ValidateIndex(SubmeshVertexOffsets, Indices, "SubmeshVertexOffsets"); + BufferMethods.ValidateIndex(Indices, Positions, "Indices"); } } @@ -300,17 +300,17 @@ public BFast ToBFast() public bool Equals(G3dMaterials other ) { - return MaterialColors.SafeEquals(other.MaterialColors) && - MaterialGlossiness.SafeEquals(other.MaterialGlossiness) && - MaterialSmoothness.SafeEquals(other.MaterialSmoothness); + return BufferMethods.SafeEquals(MaterialColors, other.MaterialColors) && + BufferMethods.SafeEquals(MaterialGlossiness, other.MaterialGlossiness) && + BufferMethods.SafeEquals(MaterialSmoothness, other.MaterialSmoothness); } public G3dMaterials Merge(G3dMaterials other) { return new G3dMaterials( - MaterialColors.MergeData(other.MaterialColors), - MaterialGlossiness.MergeData(other.MaterialGlossiness), - MaterialSmoothness.MergeData(other.MaterialSmoothness) + BufferMethods.MergeData(MaterialColors, other.MaterialColors), + BufferMethods.MergeData(MaterialGlossiness, other.MaterialGlossiness), + BufferMethods.MergeData(MaterialSmoothness, other.MaterialSmoothness) ); } @@ -423,41 +423,41 @@ public BFast ToBFast() public bool Equals(G3dScene other ) { - return ChunkCount.SafeEquals(other.ChunkCount) && - InstanceMeshes.SafeEquals(other.InstanceMeshes) && - InstanceTransformData.SafeEquals(other.InstanceTransformData) && - InstanceNodes.SafeEquals(other.InstanceNodes) && - InstanceGroups.SafeEquals(other.InstanceGroups) && - InstanceTags.SafeEquals(other.InstanceTags) && - InstanceFlags.SafeEquals(other.InstanceFlags) && - InstanceMins.SafeEquals(other.InstanceMins) && - InstanceMaxs.SafeEquals(other.InstanceMaxs) && - MeshChunks.SafeEquals(other.MeshChunks) && - MeshChunkIndices.SafeEquals(other.MeshChunkIndices) && - MeshVertexCounts.SafeEquals(other.MeshVertexCounts) && - MeshIndexCounts.SafeEquals(other.MeshIndexCounts) && - MeshOpaqueVertexCounts.SafeEquals(other.MeshOpaqueVertexCounts) && - MeshOpaqueIndexCounts.SafeEquals(other.MeshOpaqueIndexCounts); + return BufferMethods.SafeEquals(ChunkCount, other.ChunkCount) && + BufferMethods.SafeEquals(InstanceMeshes, other.InstanceMeshes) && + BufferMethods.SafeEquals(InstanceTransformData, other.InstanceTransformData) && + BufferMethods.SafeEquals(InstanceNodes, other.InstanceNodes) && + BufferMethods.SafeEquals(InstanceGroups, other.InstanceGroups) && + BufferMethods.SafeEquals(InstanceTags, other.InstanceTags) && + BufferMethods.SafeEquals(InstanceFlags, other.InstanceFlags) && + BufferMethods.SafeEquals(InstanceMins, other.InstanceMins) && + BufferMethods.SafeEquals(InstanceMaxs, other.InstanceMaxs) && + BufferMethods.SafeEquals(MeshChunks, other.MeshChunks) && + BufferMethods.SafeEquals(MeshChunkIndices, other.MeshChunkIndices) && + BufferMethods.SafeEquals(MeshVertexCounts, other.MeshVertexCounts) && + BufferMethods.SafeEquals(MeshIndexCounts, other.MeshIndexCounts) && + BufferMethods.SafeEquals(MeshOpaqueVertexCounts, other.MeshOpaqueVertexCounts) && + BufferMethods.SafeEquals(MeshOpaqueIndexCounts, other.MeshOpaqueIndexCounts); } public G3dScene Merge(G3dScene other) { return new G3dScene( - ChunkCount.MergeData(other.ChunkCount), - InstanceMeshes.MergeData(other.InstanceMeshes), - InstanceTransformData.MergeData(other.InstanceTransformData), - InstanceNodes.MergeData(other.InstanceNodes), - InstanceGroups.MergeData(other.InstanceGroups), - InstanceTags.MergeData(other.InstanceTags), - InstanceFlags.MergeData(other.InstanceFlags), - InstanceMins.MergeData(other.InstanceMins), - InstanceMaxs.MergeData(other.InstanceMaxs), - MeshChunks.MergeData(other.MeshChunks), - MeshChunkIndices.MergeData(other.MeshChunkIndices), - MeshVertexCounts.MergeData(other.MeshVertexCounts), - MeshIndexCounts.MergeData(other.MeshIndexCounts), - MeshOpaqueVertexCounts.MergeData(other.MeshOpaqueVertexCounts), - MeshOpaqueIndexCounts.MergeData(other.MeshOpaqueIndexCounts) + BufferMethods.MergeData(ChunkCount, other.ChunkCount), + BufferMethods.MergeData(InstanceMeshes, other.InstanceMeshes), + BufferMethods.MergeData(InstanceTransformData, other.InstanceTransformData), + BufferMethods.MergeData(InstanceNodes, other.InstanceNodes), + BufferMethods.MergeData(InstanceGroups, other.InstanceGroups), + BufferMethods.MergeData(InstanceTags, other.InstanceTags), + BufferMethods.MergeData(InstanceFlags, other.InstanceFlags), + BufferMethods.MergeData(InstanceMins, other.InstanceMins), + BufferMethods.MergeData(InstanceMaxs, other.InstanceMaxs), + BufferMethods.MergeData(MeshChunks, other.MeshChunks), + BufferMethods.MergeData(MeshChunkIndices, other.MeshChunkIndices), + BufferMethods.MergeData(MeshVertexCounts, other.MeshVertexCounts), + BufferMethods.MergeData(MeshIndexCounts, other.MeshIndexCounts), + BufferMethods.MergeData(MeshOpaqueVertexCounts, other.MeshOpaqueVertexCounts), + BufferMethods.MergeData(MeshOpaqueIndexCounts, other.MeshOpaqueIndexCounts) ); } diff --git a/src/cs/g3d/Vim.G3dNext/G3dMaterials.cs b/src/cs/g3d/Vim.G3dNext/G3dMaterials.cs index 6515edf8..e366aeec 100644 --- a/src/cs/g3d/Vim.G3dNext/G3dMaterials.cs +++ b/src/cs/g3d/Vim.G3dNext/G3dMaterials.cs @@ -1,6 +1,5 @@ -using System.Runtime.ConstrainedExecution; - -namespace Vim.G3dNext.Attributes + +namespace Vim.G3dNext { public partial class G3dMaterials { diff --git a/src/cs/g3d/Vim.G3dNext/G3dScene.cs b/src/cs/g3d/Vim.G3dNext/G3dScene.cs index 65e693dd..4d6adb03 100644 --- a/src/cs/g3d/Vim.G3dNext/G3dScene.cs +++ b/src/cs/g3d/Vim.G3dNext/G3dScene.cs @@ -1,4 +1,4 @@ -namespace Vim.G3dNext.Attributes +namespace Vim.G3dNext { public partial class G3dScene { diff --git a/src/cs/g3d/Vim.G3dNext/G3dVim.cs b/src/cs/g3d/Vim.G3dNext/G3dVim.cs index 10bd6732..845e1b49 100644 --- a/src/cs/g3d/Vim.G3dNext/G3dVim.cs +++ b/src/cs/g3d/Vim.G3dNext/G3dVim.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using Vim.BFastNS; -namespace Vim.G3dNext.Attributes +namespace Vim.G3dNext { public partial class G3dVim { diff --git a/src/cs/g3d/Vim.G3dNext/Vim.G3dNext.csproj b/src/cs/g3d/Vim.G3dNext/Vim.G3dNext.csproj index b312cc13..b411b844 100644 --- a/src/cs/g3d/Vim.G3dNext/Vim.G3dNext.csproj +++ b/src/cs/g3d/Vim.G3dNext/Vim.G3dNext.csproj @@ -10,6 +10,7 @@ + diff --git a/src/cs/util/Vim.Util.Tests/TestUtils.cs b/src/cs/util/Vim.Util.Tests/TestUtils.cs new file mode 100644 index 00000000..24bca1c3 --- /dev/null +++ b/src/cs/util/Vim.Util.Tests/TestUtils.cs @@ -0,0 +1,101 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Runtime.CompilerServices; +using Vim.Math3d; +using Vim.Util.Tests; + +namespace Vim.G3dNext.Tests +{ + public static class TestUtils + { + + public static string ResidencePath = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); + + /// + /// Deletes and/or creates a folder for given test case name. + /// + public static string PrepareTestDir([CallerMemberName] string testName = null) + { + if (testName == null) + throw new ArgumentException(nameof(testName)); + + var testDir = Path.Combine(VimFormatRepoPaths.OutDir, testName); + + // Prepare the test directory + if (Directory.Exists(testDir)) + Directory.Delete(testDir, true); + Directory.CreateDirectory(testDir); + + return testDir; + } + + public static (long, long) GetMemoryConsumptionAndMSecElapsed(Action action) + { + var time = 0L; + var mem = GetMemoryConsumption( + () => time = GetMSecElapsed(action)); + return (mem, time); + } + + public static long GetMSecElapsed(Action action) + { + var sw = Stopwatch.StartNew(); + action(); + return sw.ElapsedMilliseconds; + } + + /// + /// Creates a directory if needed, or clears all of its contents otherwise + /// + public static string CreateAndClearDirectory(string dirPath) + { + if (!Directory.Exists(dirPath)) + Directory.CreateDirectory(dirPath); + else + DeleteFolderContents(dirPath); + return dirPath; + } + + /// + /// Deletes all contents in a folder + /// + /// + /// https://stackoverflow.com/questions/1288718/how-to-delete-all-files-and-folders-in-a-directory + /// + private static void DeleteFolderContents(string folderPath) + { + var di = new DirectoryInfo(folderPath); + foreach (var dir in di.EnumerateDirectories().AsParallel()) + DeleteFolderAndAllContents(dir.FullName); + foreach (var file in di.EnumerateFiles().AsParallel()) + file.Delete(); + } + + /// + /// Deletes everything in a folder and then the folder. + /// + private static void DeleteFolderAndAllContents(string folderPath) + { + if (!Directory.Exists(folderPath)) + return; + + DeleteFolderContents(folderPath); + Directory.Delete(folderPath); + } + + // NOTE: Calling a function generates additional memory + private static long GetMemoryConsumption(Action action) + { + GC.Collect(); + GC.WaitForPendingFinalizers(); + var memBefore = GC.GetTotalMemory(true); + action(); + GC.Collect(); + GC.WaitForPendingFinalizers(); + return GC.GetTotalMemory(true) - memBefore; + } + + } +} diff --git a/src/cs/util/Vim.Util.Tests/Vim.Util.Tests.csproj b/src/cs/util/Vim.Util.Tests/Vim.Util.Tests.csproj index 8b38f884..88f0d49e 100644 --- a/src/cs/util/Vim.Util.Tests/Vim.Util.Tests.csproj +++ b/src/cs/util/Vim.Util.Tests/Vim.Util.Tests.csproj @@ -15,6 +15,7 @@ + diff --git a/src/cs/vim-format.sln b/src/cs/vim-format.sln index 5676f7be..a75b5a5b 100644 --- a/src/cs/vim-format.sln +++ b/src/cs/vim-format.sln @@ -45,8 +45,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vim.Util.Logging.Serilog", EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vim.G3dNext", "g3d\Vim.G3dNext\Vim.G3dNext.csproj", "{7A3255D6-444D-46B7-8BBD-ABED88C99009}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vim.G3dNext.Attributes", "g3d\Vim.G3dNext.Attributes\Vim.G3dNext.Attributes.csproj", "{43DD1349-03E9-407F-A52C-8CACC7801F3B}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vim.G3dNext.CodeGen", "g3d\Vim.G3dNext.CodeGen\Vim.G3dNext.CodeGen.csproj", "{F0FFC990-6358-4B17-B878-C6CA087CDF3F}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vim.Format.Vimx", "vim\Vim.Format.Vimx\Vim.Format.Vimx.csproj", "{B5C8E733-8D3F-45BD-BBBE-09A9F1965545}" @@ -59,6 +57,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vim.BFast.Tests", "bfast\Vi EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vim.Format.Vimx.Conversion", "vim\Vim.Format.Vimx.Conversion\Vim.Format.Vimx.Conversion.csproj", "{4C4F9826-0DEF-4A39-BFC8-A834522694A0}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Vim.G3dNext.Tests", "Vim.G3dNext.Tests\Vim.G3dNext.Tests.csproj", "{AD1A2A9F-18E9-4430-A192-3CD1A17DDA0D}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -125,10 +125,6 @@ Global {7A3255D6-444D-46B7-8BBD-ABED88C99009}.Debug|Any CPU.Build.0 = Debug|Any CPU {7A3255D6-444D-46B7-8BBD-ABED88C99009}.Release|Any CPU.ActiveCfg = Release|Any CPU {7A3255D6-444D-46B7-8BBD-ABED88C99009}.Release|Any CPU.Build.0 = Release|Any CPU - {43DD1349-03E9-407F-A52C-8CACC7801F3B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {43DD1349-03E9-407F-A52C-8CACC7801F3B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {43DD1349-03E9-407F-A52C-8CACC7801F3B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {43DD1349-03E9-407F-A52C-8CACC7801F3B}.Release|Any CPU.Build.0 = Release|Any CPU {F0FFC990-6358-4B17-B878-C6CA087CDF3F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F0FFC990-6358-4B17-B878-C6CA087CDF3F}.Debug|Any CPU.Build.0 = Debug|Any CPU {F0FFC990-6358-4B17-B878-C6CA087CDF3F}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -153,6 +149,10 @@ Global {4C4F9826-0DEF-4A39-BFC8-A834522694A0}.Debug|Any CPU.Build.0 = Debug|Any CPU {4C4F9826-0DEF-4A39-BFC8-A834522694A0}.Release|Any CPU.ActiveCfg = Release|Any CPU {4C4F9826-0DEF-4A39-BFC8-A834522694A0}.Release|Any CPU.Build.0 = Release|Any CPU + {AD1A2A9F-18E9-4430-A192-3CD1A17DDA0D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AD1A2A9F-18E9-4430-A192-3CD1A17DDA0D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AD1A2A9F-18E9-4430-A192-3CD1A17DDA0D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AD1A2A9F-18E9-4430-A192-3CD1A17DDA0D}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -173,13 +173,13 @@ Global {F7091670-1059-4F4F-AC3A-0B1DE4A724B5} = {A279C2F9-3418-484B-A36E-D1D1C67A0B2D} {6B9E6432-A7BB-4487-905A-0C3117398140} = {A279C2F9-3418-484B-A36E-D1D1C67A0B2D} {7A3255D6-444D-46B7-8BBD-ABED88C99009} = {705B8FB2-D707-4527-91FC-0AADEDBA4D80} - {43DD1349-03E9-407F-A52C-8CACC7801F3B} = {705B8FB2-D707-4527-91FC-0AADEDBA4D80} {F0FFC990-6358-4B17-B878-C6CA087CDF3F} = {705B8FB2-D707-4527-91FC-0AADEDBA4D80} {B5C8E733-8D3F-45BD-BBBE-09A9F1965545} = {D639C635-01D1-48C4-89B5-1FD70F1AFEE9} {BBF94CBD-CD39-49F5-979A-5C9E52C29330} = {D639C635-01D1-48C4-89B5-1FD70F1AFEE9} {408884EA-3CE5-4A34-97F6-1F2D64A0E745} = {F3260C54-834F-4C74-A3B7-EAB622AFA492} {FD149D64-5905-4F7D-97A8-9F7DA18A257D} = {F3260C54-834F-4C74-A3B7-EAB622AFA492} {4C4F9826-0DEF-4A39-BFC8-A834522694A0} = {D639C635-01D1-48C4-89B5-1FD70F1AFEE9} + {AD1A2A9F-18E9-4430-A192-3CD1A17DDA0D} = {705B8FB2-D707-4527-91FC-0AADEDBA4D80} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {7D1BF641-26E8-4809-B638-029241C51BE2} diff --git a/src/cs/vim/Vim.Format.Core/G3dBuilder.cs b/src/cs/vim/Vim.Format.Core/G3dBuilder.cs index db10261c..841fc83d 100644 --- a/src/cs/vim/Vim.Format.Core/G3dBuilder.cs +++ b/src/cs/vim/Vim.Format.Core/G3dBuilder.cs @@ -4,7 +4,7 @@ using Vim.BFastNS; using static Vim.Format.DocumentBuilder; using Vim.Math3d; -using Vim.G3dNext.Attributes; +using Vim.G3dNext; namespace Vim.Format { diff --git a/src/cs/vim/Vim.Format.Core/Vim.Format.Core.csproj b/src/cs/vim/Vim.Format.Core/Vim.Format.Core.csproj index a7b621ed..4abbc208 100644 --- a/src/cs/vim/Vim.Format.Core/Vim.Format.Core.csproj +++ b/src/cs/vim/Vim.Format.Core/Vim.Format.Core.csproj @@ -8,7 +8,6 @@ - diff --git a/src/cs/vim/Vim.Format.Vimx.Conversion/Chunking.cs b/src/cs/vim/Vim.Format.Vimx.Conversion/Chunking.cs index ebc96d5e..91345b95 100644 --- a/src/cs/vim/Vim.Format.Vimx.Conversion/Chunking.cs +++ b/src/cs/vim/Vim.Format.Vimx.Conversion/Chunking.cs @@ -2,23 +2,19 @@ using System.Linq; using Vim.LinqArray; using Vim.Math3d; -using Vim.G3dNext.Attributes; -using Vim.G3d; -using System.Xml.Serialization; -using System; +using Vim.G3dNext; namespace Vim.Format.VimxNS.Conversion { public static class Chunking { - public static VimChunks CreateChunks(ChunksDescription description) { var chunks = new G3dChunk[description.ChunkMeshes.Count]; for (var i = 0; i < chunks.Length; i++) { var meshes = description.ChunkMeshes[i]; - chunks[i] = CreateChunk2(description.g3d, meshes); + chunks[i] = CreateChunk(description.g3d, meshes); } return new VimChunks(description, chunks); } @@ -57,57 +53,6 @@ public static ChunksDescription ComputeChunks(MeshOrder ordering) return new ChunksDescription(ordering, meshChunks, meshIndex, chunks); } - public static G3dChunk CreateChunk(G3dVim g3d, List meshes) - { - var submeshOffsets = new List() { 0 }; - var opaqueCounts = new List(); - var submeshIndexOffsets = new List(); - var submeshVertexOffsets = new List(); - var submeshMaterials = new List(); - var indices = new List(); - var vertices = new List(); - - for (var i = 0; i < meshes.Count; i++) - { - var mesh = meshes[i]; - - var opaqueCount = AppendSubmeshes( - g3d, - mesh, - false, - submeshIndexOffsets, - submeshVertexOffsets, - submeshMaterials, - indices, - vertices - ); - - var transparentCount = AppendSubmeshes( - g3d, - mesh, - true, - submeshIndexOffsets, - submeshVertexOffsets, - submeshMaterials, - indices, - vertices - ); - opaqueCounts.Add(opaqueCount); - submeshOffsets.Add(submeshOffsets[i] + opaqueCount + transparentCount); - } - - return new G3dChunk( - submeshOffsets.ToArray(), - opaqueCounts.ToArray(), - submeshIndexOffsets.ToArray(), - submeshVertexOffsets.ToArray(), - submeshMaterials.ToArray(), - vertices.ToArray(), - indices.ToArray() - ); - } - - public class SubmeshBuffer { int index = 0; @@ -156,7 +101,7 @@ public void AddVertex(Vector3 vertex) } } - public static G3dChunk CreateChunk2(G3dVim g3d, List meshes) + public static G3dChunk CreateChunk(G3dVim g3d, List meshes) { var meshSubmeshOffsets = new int[meshes.Count + 1]; var meshOpaqueCounts = new int[meshes.Count]; @@ -172,7 +117,7 @@ public static G3dChunk CreateChunk2(G3dVim g3d, List meshes) { var mesh = meshes[i]; - var opaqueCount = AppendSubmeshes2( + var opaqueCount = AppendSubmeshes( g3d, mesh, false, @@ -180,7 +125,7 @@ public static G3dChunk CreateChunk2(G3dVim g3d, List meshes) pointsBuffer ); - var transparentCount = AppendSubmeshes2( + var transparentCount = AppendSubmeshes( g3d, mesh, true, @@ -192,50 +137,17 @@ public static G3dChunk CreateChunk2(G3dVim g3d, List meshes) } return new G3dChunk( - meshSubmeshOffsets, - meshOpaqueCounts, - submeshBuffer.IndexOffsets, - submeshBuffer.VertexOffsets, - submeshBuffer.Materials, - pointsBuffer.vertices.ToArray(), - pointsBuffer.indices + meshSubmeshOffset: meshSubmeshOffsets, + meshOpaqueSubmeshCounts: meshOpaqueCounts, + submeshIndexOffsets: submeshBuffer.IndexOffsets, + submeshVertexOffsets :submeshBuffer.VertexOffsets, + submeshMaterials: submeshBuffer.Materials, + indices: pointsBuffer.indices, + positions: pointsBuffer.vertices.ToArray() ); } private static int AppendSubmeshes( - G3dVim g3d, - int mesh, - bool transparent, - List submeshIndexOffsets, - List submeshVertexOffsets, - List submeshMaterials, - List indices, - List vertices - ) - { - var subStart = g3d.GetMeshSubmeshStart(mesh); - var subEnd = g3d.GetMeshSubmeshEnd(mesh); - var count = 0; - for (var sub = subStart; sub < subEnd; sub++) - { - var currentMat = g3d.SubmeshMaterials[sub]; - var color = currentMat > 0 ? g3d.MaterialColors[currentMat] : Vector4.One; - var accept = color.W < 1 == transparent; - - if (!accept) continue; - count++; - submeshMaterials.Add(currentMat); - submeshIndexOffsets.Add(indices.Count); - submeshVertexOffsets.Add(vertices.Count); - var (subIndices, subVertices) = g3d.GetSubmesh(sub); - indices.AddRange(subIndices.Select(i => i + vertices.Count)); - vertices.AddRange(subVertices); - } - return count; - } - - - private static int AppendSubmeshes2( G3dVim g3d, int mesh, bool transparent, @@ -255,39 +167,12 @@ PointsBuffer pointsBuffer if (!accept) continue; count++; submeshBuffer.Add(pointsBuffer.IndexCount, pointsBuffer.VertexCount, currentMat); - g3d.GetSubmesh2(sub, pointsBuffer); + g3d.GetSubmesh(sub, pointsBuffer); } return count; } - - - private static (List, List) GetSubmesh(this G3dVim g3d, int submesh) - { - var indices = new List(); - var vertices = new List(); - var dict = new Dictionary(); - - var start = g3d.GetSubmeshIndexStart(submesh); - var end = g3d.GetSubmeshIndexEnd(submesh); - - for (var i = start; i < end; i++) - { - var v = g3d.Indices[i]; - if (dict.ContainsKey(v)) - { - indices.Add(dict[v]); - } - else - { - indices.Add(vertices.Count); - dict.Add(v, vertices.Count); - vertices.Add(g3d.Positions[v]); - } - } - return (indices, vertices); - } - - private static void GetSubmesh2(this G3dVim g3d, int submesh, PointsBuffer points) + + private static void GetSubmesh(this G3dVim g3d, int submesh, PointsBuffer points) { var index = points.VertexCount; var dict = new Dictionary(); diff --git a/src/cs/vim/Vim.Format.Vimx.Conversion/Ordering.cs b/src/cs/vim/Vim.Format.Vimx.Conversion/Ordering.cs index c1ef1c27..1bb4fb17 100644 --- a/src/cs/vim/Vim.Format.Vimx.Conversion/Ordering.cs +++ b/src/cs/vim/Vim.Format.Vimx.Conversion/Ordering.cs @@ -1,6 +1,6 @@ using System; using Vim.Format.ObjectModel; -using Vim.G3dNext.Attributes; +using Vim.G3dNext; namespace Vim.Format.VimxNS.Conversion { diff --git a/src/cs/vim/Vim.Format.Vimx.Conversion/Vim.Format.Vimx.Conversion.csproj b/src/cs/vim/Vim.Format.Vimx.Conversion/Vim.Format.Vimx.Conversion.csproj index bb63c8ef..76983d94 100644 --- a/src/cs/vim/Vim.Format.Vimx.Conversion/Vim.Format.Vimx.Conversion.csproj +++ b/src/cs/vim/Vim.Format.Vimx.Conversion/Vim.Format.Vimx.Conversion.csproj @@ -5,7 +5,6 @@ - diff --git a/src/cs/vim/Vim.Format.Vimx.Conversion/VimxConverter.cs b/src/cs/vim/Vim.Format.Vimx.Conversion/VimxConverter.cs index a5e9d69f..55d72c09 100644 --- a/src/cs/vim/Vim.Format.Vimx.Conversion/VimxConverter.cs +++ b/src/cs/vim/Vim.Format.Vimx.Conversion/VimxConverter.cs @@ -1,7 +1,7 @@ using System.Linq; using Vim.LinqArray; using Vim.BFastNS; -using Vim.G3dNext.Attributes; +using Vim.G3dNext; using Vim.Format.ObjectModel; using Vim.G3dNext; using System.Collections.Generic; @@ -15,41 +15,28 @@ public static class VimxConverter { public static Vimx FromVimPath(string vimPath) { - var sw = Stopwatch.StartNew(); var vim = VimScene.LoadVim(vimPath, new LoadOptions() { SkipAssets = true, SkipGeometry = true, }); - Console.WriteLine(" LoadVim " + sw.ElapsedMilliseconds); - sw.Restart(); var g3d = G3dVim.FromVim(vimPath); - Console.WriteLine(" G3dVim.FromVim " + sw.ElapsedMilliseconds); - - sw.Restart(); - var vimx = FromVim(g3d, vim.DocumentModel); - Console.WriteLine(" FromVim " + sw.ElapsedMilliseconds); + var vimx = ConvertFromVim(g3d, vim.DocumentModel); return vimx; } - public static Vimx FromVim(G3dVim g3d, DocumentModel bim) + public static Vimx ConvertFromVim(G3dVim g3d, DocumentModel bim) { - var sw = Stopwatch.StartNew(); // Split input Vim into chunks. var chunks = CreateChunks(g3d, bim); - Console.WriteLine(" CreateChunks " + sw.ElapsedMilliseconds); - sw.Restart(); // Compute the scene definition from chunks. var scene = CreateScene(chunks, bim); - Console.WriteLine(" CreateScene " + sw.ElapsedMilliseconds); - sw.Restart(); // Materials are reused from input g3d. var materials = new G3dMaterials(g3d); - Console.WriteLine(" G3dMaterials " + sw.ElapsedMilliseconds); var header = VimxHeader.CreateDefault(); @@ -58,20 +45,14 @@ public static Vimx FromVim(G3dVim g3d, DocumentModel bim) public static VimChunks CreateChunks(G3dVim g3d, DocumentModel bim) { - var sw = Stopwatch.StartNew(); // First compute a desirable presentation order. var ordering = Ordering.ComputeOrder(g3d, bim); - Console.WriteLine(" ComputeOrder " + sw.ElapsedMilliseconds); - sw.Restart(); // Groups meshes up to a certain size. var groups = Chunking.ComputeChunks(ordering); // Append and merge geometry from g3d to create the chunks. - Console.WriteLine(" ComputeChunks " + sw.ElapsedMilliseconds); - sw.Restart(); var chunks = Chunking.CreateChunks(groups); - Console.WriteLine(" CreateChunks " + sw.ElapsedMilliseconds); return chunks; } @@ -147,8 +128,6 @@ public static G3dScene CreateScene(VimChunks chunks, DocumentModel bim) } } - Console.WriteLine("AABB " + sw.ElapsedMilliseconds); - var scene = new G3dScene( chunkCount: new[] { chunks.ChunkCount}, @@ -169,7 +148,6 @@ public static G3dScene CreateScene(VimChunks chunks, DocumentModel bim) ); return scene; } - } /// diff --git a/src/cs/vim/Vim.Format.Vimx/Vim.Format.Vimx.csproj b/src/cs/vim/Vim.Format.Vimx/Vim.Format.Vimx.csproj index fcb35ccc..dce33c13 100644 --- a/src/cs/vim/Vim.Format.Vimx/Vim.Format.Vimx.csproj +++ b/src/cs/vim/Vim.Format.Vimx/Vim.Format.Vimx.csproj @@ -10,7 +10,6 @@ - diff --git a/src/cs/vim/Vim.Format.Vimx/Vimx.cs b/src/cs/vim/Vim.Format.Vimx/Vimx.cs index c23f6b93..2a2a270c 100644 --- a/src/cs/vim/Vim.Format.Vimx/Vimx.cs +++ b/src/cs/vim/Vim.Format.Vimx/Vimx.cs @@ -1,8 +1,6 @@ -using System.Collections.Generic; -using System.Linq; +using System.Linq; using Vim.BFastNS; using Vim.G3dNext; -using Vim.G3dNext.Attributes; namespace Vim.Format.VimxNS { diff --git a/src/cs/vim/Vim.Format.Vimx/VimxChunk.cs b/src/cs/vim/Vim.Format.Vimx/VimxChunk.cs index 0b766bff..7303b49c 100644 --- a/src/cs/vim/Vim.Format.Vimx/VimxChunk.cs +++ b/src/cs/vim/Vim.Format.Vimx/VimxChunk.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; using System.Linq; using Vim.BFastNS; -using Vim.G3dNext.Attributes; +using Vim.G3dNext; namespace Vim.Format.VimxNS { diff --git a/src/cs/vim/Vim.Vimx.Test/TestUtils.cs b/src/cs/vim/Vim.Vimx.Test/TestUtils.cs index b7952167..a1af23e7 100644 --- a/src/cs/vim/Vim.Vimx.Test/TestUtils.cs +++ b/src/cs/vim/Vim.Vimx.Test/TestUtils.cs @@ -1,6 +1,5 @@ using System.Diagnostics; using System.Runtime.CompilerServices; -using Vim.G3dNext.Attributes; using Vim.Math3d; using Vim.Util.Tests; diff --git a/src/cs/vim/Vim.Vimx.Test/Vim.Format.Vimx.Test.csproj b/src/cs/vim/Vim.Vimx.Test/Vim.Format.Vimx.Test.csproj index b88dcd29..24ec0f34 100644 --- a/src/cs/vim/Vim.Vimx.Test/Vim.Format.Vimx.Test.csproj +++ b/src/cs/vim/Vim.Vimx.Test/Vim.Format.Vimx.Test.csproj @@ -17,7 +17,6 @@ - diff --git a/src/cs/vim/Vim.Vimx.Test/VimG3dTests.cs b/src/cs/vim/Vim.Vimx.Test/VimG3dTests.cs index 43da036b..ef390cb5 100644 --- a/src/cs/vim/Vim.Vimx.Test/VimG3dTests.cs +++ b/src/cs/vim/Vim.Vimx.Test/VimG3dTests.cs @@ -1,7 +1,7 @@ using NUnit.Framework; using NUnit.Framework.Internal; using Vim.BFastNS; -using Vim.G3dNext.Attributes; +using Vim.G3dNext; namespace Vim.G3dNext.Tests { diff --git a/src/cs/vim/Vim.Vimx.Test/VimxActions.cs b/src/cs/vim/Vim.Vimx.Test/VimxActions.cs index 2ee53818..4b069e29 100644 --- a/src/cs/vim/Vim.Vimx.Test/VimxActions.cs +++ b/src/cs/vim/Vim.Vimx.Test/VimxActions.cs @@ -22,17 +22,9 @@ public static void ConvertVimToVimx() var name = Path.GetFileNameWithoutExtension(input); var output = Path.Combine(VimFormatRepoPaths.OutDir, name + ".vimx"); - var sw = Stopwatch.StartNew(); var vimx = VimxConverter.FromVimPath(input); - Console.WriteLine("FromVimPath " + sw.ElapsedMilliseconds); - - sw.Restart(); var bfast = vimx.ToBFast(); - Console.WriteLine("Write " + sw.ElapsedMilliseconds); - - sw.Restart(); bfast.Write(output); - Console.WriteLine("Write " + sw.ElapsedMilliseconds); } } } diff --git a/src/cs/vim/Vim.Vimx.Test/VimxTests.cs b/src/cs/vim/Vim.Vimx.Test/VimxTests.cs index d7e6899d..0c7903bc 100644 --- a/src/cs/vim/Vim.Vimx.Test/VimxTests.cs +++ b/src/cs/vim/Vim.Vimx.Test/VimxTests.cs @@ -25,21 +25,5 @@ public static void Can_Convert_And_Read_Vimx() Assert.AreEqual(vimx.Chunks.Length, result.Chunks.Length); } } - - [TestFixture] - internal class VimTests - { - [Test] - public static void Write_BFastNext_VsOld() - { - using (var stream = new FileStream(VimFormatRepoPaths.GetLatestWolfordResidenceVim(), FileMode.OpenOrCreate)) - { - - } - - } - - - } } diff --git a/src/ts/package-lock.json b/src/ts/package-lock.json index 6befc896..687ab073 100644 --- a/src/ts/package-lock.json +++ b/src/ts/package-lock.json @@ -1,12 +1,12 @@ { "name": "vim-format", - "version": "1.0.6-dev.138", + "version": "1.0.6-dev.235", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "vim-format", - "version": "1.0.6-dev.138", + "version": "1.0.6-dev.235", "license": "MIT", "dependencies": { "pako": "^2.1.0" From 8838a11456657337fabf379408b771c6b260ddfd Mon Sep 17 00:00:00 2001 From: simon Date: Mon, 22 Jan 2024 16:05:33 -0500 Subject: [PATCH 052/111] create directory if needed --- src/cs/g3d/Vim.G3dNext.CodeGen/Vim.G3dNext.CodeGen.csproj | 1 - src/cs/g3d/Vim.G3dNext/G3dVim.cs | 1 - src/cs/vim/Vim.Vimx.Test/VimxTests.cs | 5 +++++ 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/cs/g3d/Vim.G3dNext.CodeGen/Vim.G3dNext.CodeGen.csproj b/src/cs/g3d/Vim.G3dNext.CodeGen/Vim.G3dNext.CodeGen.csproj index 46cd3717..cf094d6c 100644 --- a/src/cs/g3d/Vim.G3dNext.CodeGen/Vim.G3dNext.CodeGen.csproj +++ b/src/cs/g3d/Vim.G3dNext.CodeGen/Vim.G3dNext.CodeGen.csproj @@ -12,7 +12,6 @@ - diff --git a/src/cs/g3d/Vim.G3dNext/G3dVim.cs b/src/cs/g3d/Vim.G3dNext/G3dVim.cs index 845e1b49..6f19ecca 100644 --- a/src/cs/g3d/Vim.G3dNext/G3dVim.cs +++ b/src/cs/g3d/Vim.G3dNext/G3dVim.cs @@ -66,7 +66,6 @@ private List[] ComputeMeshInstances() return result; } - public int GetTriangleCount() { return GetIndexCount() / 3; diff --git a/src/cs/vim/Vim.Vimx.Test/VimxTests.cs b/src/cs/vim/Vim.Vimx.Test/VimxTests.cs index 0c7903bc..7977f978 100644 --- a/src/cs/vim/Vim.Vimx.Test/VimxTests.cs +++ b/src/cs/vim/Vim.Vimx.Test/VimxTests.cs @@ -12,6 +12,11 @@ public static class VimxTests [Test] public static void Can_Convert_And_Read_Vimx() { + if (!Directory.Exists(VimFormatRepoPaths.OutDir)) + { + Directory.CreateDirectory(VimFormatRepoPaths.OutDir); + } + var input = TestUtils.ResidencePath; var name = Path.GetFileNameWithoutExtension(TestUtils.ResidencePath); var output = Path.Combine(VimFormatRepoPaths.OutDir, name + ".vimx"); From ee5da48e596927de22fc27a6fd26763e6ba316e7 Mon Sep 17 00:00:00 2001 From: simon Date: Mon, 22 Jan 2024 16:31:07 -0500 Subject: [PATCH 053/111] create directory if needed, some test cleanup --- .../{G3dTestUtils.cs => G3dNextTestUtils.cs} | 2 +- .../{VimG3dTests.cs => VimG3dNextTests.cs} | 9 +- src/cs/util/Vim.Util.Tests/TestUtils.cs | 11 +- src/cs/vim/Vim.Vimx.Test/TestUtils.cs | 123 ------------------ src/cs/vim/Vim.Vimx.Test/VimG3dTests.cs | 72 ---------- src/cs/vim/Vim.Vimx.Test/VimxTests.cs | 8 +- 6 files changed, 15 insertions(+), 210 deletions(-) rename src/cs/Vim.G3dNext.Tests/{G3dTestUtils.cs => G3dNextTestUtils.cs} (96%) rename src/cs/Vim.G3dNext.Tests/{VimG3dTests.cs => VimG3dNextTests.cs} (92%) delete mode 100644 src/cs/vim/Vim.Vimx.Test/TestUtils.cs delete mode 100644 src/cs/vim/Vim.Vimx.Test/VimG3dTests.cs diff --git a/src/cs/Vim.G3dNext.Tests/G3dTestUtils.cs b/src/cs/Vim.G3dNext.Tests/G3dNextTestUtils.cs similarity index 96% rename from src/cs/Vim.G3dNext.Tests/G3dTestUtils.cs rename to src/cs/Vim.G3dNext.Tests/G3dNextTestUtils.cs index 6de8060f..118167fb 100644 --- a/src/cs/Vim.G3dNext.Tests/G3dTestUtils.cs +++ b/src/cs/Vim.G3dNext.Tests/G3dNextTestUtils.cs @@ -2,7 +2,7 @@ namespace Vim.G3dNext.Tests { - public static class G3dTestUtils + public static class G3dNextTestUtils { public static G3dVim CreateTestG3d() { diff --git a/src/cs/Vim.G3dNext.Tests/VimG3dTests.cs b/src/cs/Vim.G3dNext.Tests/VimG3dNextTests.cs similarity index 92% rename from src/cs/Vim.G3dNext.Tests/VimG3dTests.cs rename to src/cs/Vim.G3dNext.Tests/VimG3dNextTests.cs index 75b84527..b096b67f 100644 --- a/src/cs/Vim.G3dNext.Tests/VimG3dTests.cs +++ b/src/cs/Vim.G3dNext.Tests/VimG3dNextTests.cs @@ -1,11 +1,12 @@ using NUnit.Framework; using NUnit.Framework.Internal; using Vim.BFastNS; +using Vim.Util.Tests; namespace Vim.G3dNext.Tests { [TestFixture] - public static class VimG3dTests + public static class VimG3dNextTests { [Test] public static void Can_Read_G3d_From_Vim() @@ -22,7 +23,7 @@ public static void Can_Ignore_Extra_Attributes() // We create a g3dMaterial from the bytes of a g3dVim // Shows that extra attributes are ignored as they should. - var g3d = G3dTestUtils.CreateTestG3d(); + var g3d = G3dNextTestUtils.CreateTestG3d(); var g3dMats = new G3dMaterials(g3d.ToBFast()); Assert.IsNotNull(g3dMats); @@ -34,7 +35,7 @@ public static void Can_Ignore_Extra_Attributes() [Test] public static void Can_Write_And_Read() { - var expected = G3dTestUtils.CreateTestG3d(); + var expected = G3dNextTestUtils.CreateTestG3d(); var g3d = new G3dVim(expected.ToBFast()); Assert.IsTrue(g3d.Equals(expected)); } @@ -42,7 +43,7 @@ public static void Can_Write_And_Read() [Test] public static void Can_Merge_two_g3d() { - var g3d = G3dTestUtils.CreateTestG3d(); + var g3d = G3dNextTestUtils.CreateTestG3d(); var merged = g3d.Merge(g3d); var expected = new G3dVim( diff --git a/src/cs/util/Vim.Util.Tests/TestUtils.cs b/src/cs/util/Vim.Util.Tests/TestUtils.cs index 24bca1c3..db4f642a 100644 --- a/src/cs/util/Vim.Util.Tests/TestUtils.cs +++ b/src/cs/util/Vim.Util.Tests/TestUtils.cs @@ -3,10 +3,9 @@ using System.IO; using System.Linq; using System.Runtime.CompilerServices; -using Vim.Math3d; -using Vim.Util.Tests; +using System.Xml.Linq; -namespace Vim.G3dNext.Tests +namespace Vim.Util.Tests { public static class TestUtils { @@ -31,6 +30,12 @@ public static string PrepareTestDir([CallerMemberName] string testName = null) return testDir; } + public static string PrepareOutputPath(string fileName) + { + var outputFolder = PrepareTestDir("Can_Convert_And_Read_Vimx"); + return Path.Combine(outputFolder, fileName); + } + public static (long, long) GetMemoryConsumptionAndMSecElapsed(Action action) { var time = 0L; diff --git a/src/cs/vim/Vim.Vimx.Test/TestUtils.cs b/src/cs/vim/Vim.Vimx.Test/TestUtils.cs deleted file mode 100644 index a1af23e7..00000000 --- a/src/cs/vim/Vim.Vimx.Test/TestUtils.cs +++ /dev/null @@ -1,123 +0,0 @@ -using System.Diagnostics; -using System.Runtime.CompilerServices; -using Vim.Math3d; -using Vim.Util.Tests; - -namespace Vim.G3dNext.Tests -{ - public static class TestUtils - { - - public static string ResidencePath = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); - - /// - /// Deletes and/or creates a folder for given test case name. - /// - public static string PrepareTestDir([CallerMemberName] string testName = null) - { - if (testName == null) - throw new ArgumentException(nameof(testName)); - - var testDir = Path.Combine(VimFormatRepoPaths.OutDir, testName); - - // Prepare the test directory - if (Directory.Exists(testDir)) - Directory.Delete(testDir, true); - Directory.CreateDirectory(testDir); - - return testDir; - } - - public static (long, long) GetMemoryConsumptionAndMSecElapsed(Action action) - { - var time = 0L; - var mem = GetMemoryConsumption( - () => time = GetMSecElapsed(action)); - return (mem, time); - } - - public static long GetMSecElapsed(Action action) - { - var sw = Stopwatch.StartNew(); - action(); - return sw.ElapsedMilliseconds; - } - - /// - /// Creates a directory if needed, or clears all of its contents otherwise - /// - public static string CreateAndClearDirectory(string dirPath) - { - if (!Directory.Exists(dirPath)) - Directory.CreateDirectory(dirPath); - else - DeleteFolderContents(dirPath); - return dirPath; - } - - /// - /// Deletes all contents in a folder - /// - /// - /// https://stackoverflow.com/questions/1288718/how-to-delete-all-files-and-folders-in-a-directory - /// - private static void DeleteFolderContents(string folderPath) - { - var di = new DirectoryInfo(folderPath); - foreach (var dir in di.EnumerateDirectories().AsParallel()) - DeleteFolderAndAllContents(dir.FullName); - foreach (var file in di.EnumerateFiles().AsParallel()) - file.Delete(); - } - - /// - /// Deletes everything in a folder and then the folder. - /// - private static void DeleteFolderAndAllContents(string folderPath) - { - if (!Directory.Exists(folderPath)) - return; - - DeleteFolderContents(folderPath); - Directory.Delete(folderPath); - } - - // NOTE: Calling a function generates additional memory - private static long GetMemoryConsumption(Action action) - { - GC.Collect(); - GC.WaitForPendingFinalizers(); - var memBefore = GC.GetTotalMemory(true); - action(); - GC.Collect(); - GC.WaitForPendingFinalizers(); - return GC.GetTotalMemory(true) - memBefore; - } - - public static G3dVim CreateTestG3d() - { - var g3d = new G3dVim( - instanceTransforms: new Matrix4x4[] { Matrix4x4.Identity }, - instanceMeshes: new int[] { 0 }, - instanceParents: new int[] { -1 }, - instanceFlags: null, - meshSubmeshOffsets: new int[] { 0 }, - submeshIndexOffsets: new int[] { 0, 3, 6 }, - submeshMaterials: new int[] { 0 }, - indices: new int[] { 0, 1, 2, 0, 3, 2, 1, 3, 2 }, - positions: new Vector3[] { Vector3.Zero, Vector3.UnitX, Vector3.UnitY, Vector3.UnitZ }, - materialColors: new Vector4[] { new Vector4(0.25f, 0.5f, 0.75f, 1) }, - materialGlossiness: new float[] { 0.95f }, - materialSmoothness: new float[] { 0.5f }, - shapeColors: null, - shapeVertexOffsets: null, - shapeVertices: null, - shapeWidths: null - ); - g3d.Validate(); - - - return g3d; - } - } -} diff --git a/src/cs/vim/Vim.Vimx.Test/VimG3dTests.cs b/src/cs/vim/Vim.Vimx.Test/VimG3dTests.cs deleted file mode 100644 index ef390cb5..00000000 --- a/src/cs/vim/Vim.Vimx.Test/VimG3dTests.cs +++ /dev/null @@ -1,72 +0,0 @@ -using NUnit.Framework; -using NUnit.Framework.Internal; -using Vim.BFastNS; -using Vim.G3dNext; - -namespace Vim.G3dNext.Tests -{ - [TestFixture] - public static class VimG3dTests - { - [Test] - public static void Can_Read_G3d_From_Vim() - { - var g3d = G3dVim.FromVim(TestUtils.ResidencePath); - Assert.IsNotNull(g3d); - } - - [Test] - public static void Can_Ignore_Extra_Attributes() - { - // Both G3dVim and G3dMaterial share 3 attributes - // G3dVim contains many more attributes - // We create a g3dMaterial from the bytes of a g3dVim - // Shows that extra attributes are ignored as they should. - - var g3d = TestUtils.CreateTestG3d(); - var g3dMats = new G3dMaterials(g3d.ToBFast()); - - Assert.IsNotNull(g3dMats); - Assert.AreEqual(g3d.MaterialColors, g3dMats.MaterialColors); - Assert.AreEqual(g3d.MaterialGlossiness, g3dMats.MaterialGlossiness); - Assert.AreEqual(g3d.MaterialSmoothness, g3dMats.MaterialSmoothness); - } - - [Test] - public static void Can_Write_And_Read() - { - var expected = TestUtils.CreateTestG3d(); - var g3d = new G3dVim(expected.ToBFast()); - Assert.IsTrue(g3d.Equals(expected)); - } - - [Test] - public static void Can_Merge_two_g3d() - { - var g3d = TestUtils.CreateTestG3d(); - var merged = g3d.Merge(g3d); - - var expected = new G3dVim( - instanceTransforms: g3d.InstanceTransforms.Concat(g3d.InstanceTransforms).ToArray(), - instanceMeshes: g3d.InstanceMeshes.Concat(g3d.InstanceMeshes.Select(i => i + g3d.GetMeshCount())).ToArray(), - instanceParents: g3d.InstanceParents.Concat(g3d.InstanceParents).ToArray(), - instanceFlags: null, - meshSubmeshOffsets: g3d.MeshSubmeshOffsets.Concat(g3d.MeshSubmeshOffsets.Select(i => g3d.GetSubmeshCount())).ToArray(), - submeshIndexOffsets: g3d.SubmeshIndexOffsets.Concat(g3d.SubmeshIndexOffsets.Select(i => i + g3d.GetIndexCount())).ToArray(), - submeshMaterials: g3d.SubmeshMaterials.Concat(g3d.SubmeshMaterials.Select(i => i + g3d.GetMaterialCount())).ToArray(), - indices: g3d.Indices.Concat(g3d.Indices.Select(i => i + g3d.Positions.Length)).ToArray(), - positions: g3d.Positions.Concat(g3d.Positions).ToArray(), - materialColors: g3d.MaterialColors.Concat(g3d.MaterialColors).ToArray(), - materialGlossiness: g3d.MaterialGlossiness.Concat(g3d.MaterialGlossiness).ToArray(), - materialSmoothness: g3d.MaterialSmoothness.Concat(g3d.MaterialSmoothness).ToArray(), - shapeColors: null, - shapeWidths: null, - shapeVertices: null, - shapeVertexOffsets: null - ); - Assert.IsTrue(merged.Equals(expected)); - } - } - -} - diff --git a/src/cs/vim/Vim.Vimx.Test/VimxTests.cs b/src/cs/vim/Vim.Vimx.Test/VimxTests.cs index 7977f978..fbd0393c 100644 --- a/src/cs/vim/Vim.Vimx.Test/VimxTests.cs +++ b/src/cs/vim/Vim.Vimx.Test/VimxTests.cs @@ -1,6 +1,5 @@ using NUnit.Framework; using NUnit.Framework.Internal; -using Vim.G3dNext.Tests; using Vim.Format.VimxNS.Conversion; using Vim.Util.Tests; @@ -12,14 +11,9 @@ public static class VimxTests [Test] public static void Can_Convert_And_Read_Vimx() { - if (!Directory.Exists(VimFormatRepoPaths.OutDir)) - { - Directory.CreateDirectory(VimFormatRepoPaths.OutDir); - } - var input = TestUtils.ResidencePath; var name = Path.GetFileNameWithoutExtension(TestUtils.ResidencePath); - var output = Path.Combine(VimFormatRepoPaths.OutDir, name + ".vimx"); + var output = TestUtils.PrepareOutputPath(name + ".vimx"); var vimx = VimxConverter.FromVimPath(input); vimx.ToBFast().Write(output); From fd2b3410757707123b8d183dc38c41b6c621b281 Mon Sep 17 00:00:00 2001 From: simon Date: Mon, 22 Jan 2024 16:31:07 -0500 Subject: [PATCH 054/111] create directory if needed, some test cleanup --- .../{G3dTestUtils.cs => G3dNextTestUtils.cs} | 2 +- .../{VimG3dTests.cs => VimG3dNextTests.cs} | 9 +- src/cs/util/Vim.Util.Tests/TestUtils.cs | 11 +- src/cs/vim/Vim.Vimx.Test/TestUtils.cs | 123 ------------------ src/cs/vim/Vim.Vimx.Test/VimG3dTests.cs | 72 ---------- src/cs/vim/Vim.Vimx.Test/VimxTests.cs | 8 +- 6 files changed, 15 insertions(+), 210 deletions(-) rename src/cs/Vim.G3dNext.Tests/{G3dTestUtils.cs => G3dNextTestUtils.cs} (96%) rename src/cs/Vim.G3dNext.Tests/{VimG3dTests.cs => VimG3dNextTests.cs} (92%) delete mode 100644 src/cs/vim/Vim.Vimx.Test/TestUtils.cs delete mode 100644 src/cs/vim/Vim.Vimx.Test/VimG3dTests.cs diff --git a/src/cs/Vim.G3dNext.Tests/G3dTestUtils.cs b/src/cs/Vim.G3dNext.Tests/G3dNextTestUtils.cs similarity index 96% rename from src/cs/Vim.G3dNext.Tests/G3dTestUtils.cs rename to src/cs/Vim.G3dNext.Tests/G3dNextTestUtils.cs index 6de8060f..118167fb 100644 --- a/src/cs/Vim.G3dNext.Tests/G3dTestUtils.cs +++ b/src/cs/Vim.G3dNext.Tests/G3dNextTestUtils.cs @@ -2,7 +2,7 @@ namespace Vim.G3dNext.Tests { - public static class G3dTestUtils + public static class G3dNextTestUtils { public static G3dVim CreateTestG3d() { diff --git a/src/cs/Vim.G3dNext.Tests/VimG3dTests.cs b/src/cs/Vim.G3dNext.Tests/VimG3dNextTests.cs similarity index 92% rename from src/cs/Vim.G3dNext.Tests/VimG3dTests.cs rename to src/cs/Vim.G3dNext.Tests/VimG3dNextTests.cs index 75b84527..b096b67f 100644 --- a/src/cs/Vim.G3dNext.Tests/VimG3dTests.cs +++ b/src/cs/Vim.G3dNext.Tests/VimG3dNextTests.cs @@ -1,11 +1,12 @@ using NUnit.Framework; using NUnit.Framework.Internal; using Vim.BFastNS; +using Vim.Util.Tests; namespace Vim.G3dNext.Tests { [TestFixture] - public static class VimG3dTests + public static class VimG3dNextTests { [Test] public static void Can_Read_G3d_From_Vim() @@ -22,7 +23,7 @@ public static void Can_Ignore_Extra_Attributes() // We create a g3dMaterial from the bytes of a g3dVim // Shows that extra attributes are ignored as they should. - var g3d = G3dTestUtils.CreateTestG3d(); + var g3d = G3dNextTestUtils.CreateTestG3d(); var g3dMats = new G3dMaterials(g3d.ToBFast()); Assert.IsNotNull(g3dMats); @@ -34,7 +35,7 @@ public static void Can_Ignore_Extra_Attributes() [Test] public static void Can_Write_And_Read() { - var expected = G3dTestUtils.CreateTestG3d(); + var expected = G3dNextTestUtils.CreateTestG3d(); var g3d = new G3dVim(expected.ToBFast()); Assert.IsTrue(g3d.Equals(expected)); } @@ -42,7 +43,7 @@ public static void Can_Write_And_Read() [Test] public static void Can_Merge_two_g3d() { - var g3d = G3dTestUtils.CreateTestG3d(); + var g3d = G3dNextTestUtils.CreateTestG3d(); var merged = g3d.Merge(g3d); var expected = new G3dVim( diff --git a/src/cs/util/Vim.Util.Tests/TestUtils.cs b/src/cs/util/Vim.Util.Tests/TestUtils.cs index 24bca1c3..db4f642a 100644 --- a/src/cs/util/Vim.Util.Tests/TestUtils.cs +++ b/src/cs/util/Vim.Util.Tests/TestUtils.cs @@ -3,10 +3,9 @@ using System.IO; using System.Linq; using System.Runtime.CompilerServices; -using Vim.Math3d; -using Vim.Util.Tests; +using System.Xml.Linq; -namespace Vim.G3dNext.Tests +namespace Vim.Util.Tests { public static class TestUtils { @@ -31,6 +30,12 @@ public static string PrepareTestDir([CallerMemberName] string testName = null) return testDir; } + public static string PrepareOutputPath(string fileName) + { + var outputFolder = PrepareTestDir("Can_Convert_And_Read_Vimx"); + return Path.Combine(outputFolder, fileName); + } + public static (long, long) GetMemoryConsumptionAndMSecElapsed(Action action) { var time = 0L; diff --git a/src/cs/vim/Vim.Vimx.Test/TestUtils.cs b/src/cs/vim/Vim.Vimx.Test/TestUtils.cs deleted file mode 100644 index a1af23e7..00000000 --- a/src/cs/vim/Vim.Vimx.Test/TestUtils.cs +++ /dev/null @@ -1,123 +0,0 @@ -using System.Diagnostics; -using System.Runtime.CompilerServices; -using Vim.Math3d; -using Vim.Util.Tests; - -namespace Vim.G3dNext.Tests -{ - public static class TestUtils - { - - public static string ResidencePath = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); - - /// - /// Deletes and/or creates a folder for given test case name. - /// - public static string PrepareTestDir([CallerMemberName] string testName = null) - { - if (testName == null) - throw new ArgumentException(nameof(testName)); - - var testDir = Path.Combine(VimFormatRepoPaths.OutDir, testName); - - // Prepare the test directory - if (Directory.Exists(testDir)) - Directory.Delete(testDir, true); - Directory.CreateDirectory(testDir); - - return testDir; - } - - public static (long, long) GetMemoryConsumptionAndMSecElapsed(Action action) - { - var time = 0L; - var mem = GetMemoryConsumption( - () => time = GetMSecElapsed(action)); - return (mem, time); - } - - public static long GetMSecElapsed(Action action) - { - var sw = Stopwatch.StartNew(); - action(); - return sw.ElapsedMilliseconds; - } - - /// - /// Creates a directory if needed, or clears all of its contents otherwise - /// - public static string CreateAndClearDirectory(string dirPath) - { - if (!Directory.Exists(dirPath)) - Directory.CreateDirectory(dirPath); - else - DeleteFolderContents(dirPath); - return dirPath; - } - - /// - /// Deletes all contents in a folder - /// - /// - /// https://stackoverflow.com/questions/1288718/how-to-delete-all-files-and-folders-in-a-directory - /// - private static void DeleteFolderContents(string folderPath) - { - var di = new DirectoryInfo(folderPath); - foreach (var dir in di.EnumerateDirectories().AsParallel()) - DeleteFolderAndAllContents(dir.FullName); - foreach (var file in di.EnumerateFiles().AsParallel()) - file.Delete(); - } - - /// - /// Deletes everything in a folder and then the folder. - /// - private static void DeleteFolderAndAllContents(string folderPath) - { - if (!Directory.Exists(folderPath)) - return; - - DeleteFolderContents(folderPath); - Directory.Delete(folderPath); - } - - // NOTE: Calling a function generates additional memory - private static long GetMemoryConsumption(Action action) - { - GC.Collect(); - GC.WaitForPendingFinalizers(); - var memBefore = GC.GetTotalMemory(true); - action(); - GC.Collect(); - GC.WaitForPendingFinalizers(); - return GC.GetTotalMemory(true) - memBefore; - } - - public static G3dVim CreateTestG3d() - { - var g3d = new G3dVim( - instanceTransforms: new Matrix4x4[] { Matrix4x4.Identity }, - instanceMeshes: new int[] { 0 }, - instanceParents: new int[] { -1 }, - instanceFlags: null, - meshSubmeshOffsets: new int[] { 0 }, - submeshIndexOffsets: new int[] { 0, 3, 6 }, - submeshMaterials: new int[] { 0 }, - indices: new int[] { 0, 1, 2, 0, 3, 2, 1, 3, 2 }, - positions: new Vector3[] { Vector3.Zero, Vector3.UnitX, Vector3.UnitY, Vector3.UnitZ }, - materialColors: new Vector4[] { new Vector4(0.25f, 0.5f, 0.75f, 1) }, - materialGlossiness: new float[] { 0.95f }, - materialSmoothness: new float[] { 0.5f }, - shapeColors: null, - shapeVertexOffsets: null, - shapeVertices: null, - shapeWidths: null - ); - g3d.Validate(); - - - return g3d; - } - } -} diff --git a/src/cs/vim/Vim.Vimx.Test/VimG3dTests.cs b/src/cs/vim/Vim.Vimx.Test/VimG3dTests.cs deleted file mode 100644 index ef390cb5..00000000 --- a/src/cs/vim/Vim.Vimx.Test/VimG3dTests.cs +++ /dev/null @@ -1,72 +0,0 @@ -using NUnit.Framework; -using NUnit.Framework.Internal; -using Vim.BFastNS; -using Vim.G3dNext; - -namespace Vim.G3dNext.Tests -{ - [TestFixture] - public static class VimG3dTests - { - [Test] - public static void Can_Read_G3d_From_Vim() - { - var g3d = G3dVim.FromVim(TestUtils.ResidencePath); - Assert.IsNotNull(g3d); - } - - [Test] - public static void Can_Ignore_Extra_Attributes() - { - // Both G3dVim and G3dMaterial share 3 attributes - // G3dVim contains many more attributes - // We create a g3dMaterial from the bytes of a g3dVim - // Shows that extra attributes are ignored as they should. - - var g3d = TestUtils.CreateTestG3d(); - var g3dMats = new G3dMaterials(g3d.ToBFast()); - - Assert.IsNotNull(g3dMats); - Assert.AreEqual(g3d.MaterialColors, g3dMats.MaterialColors); - Assert.AreEqual(g3d.MaterialGlossiness, g3dMats.MaterialGlossiness); - Assert.AreEqual(g3d.MaterialSmoothness, g3dMats.MaterialSmoothness); - } - - [Test] - public static void Can_Write_And_Read() - { - var expected = TestUtils.CreateTestG3d(); - var g3d = new G3dVim(expected.ToBFast()); - Assert.IsTrue(g3d.Equals(expected)); - } - - [Test] - public static void Can_Merge_two_g3d() - { - var g3d = TestUtils.CreateTestG3d(); - var merged = g3d.Merge(g3d); - - var expected = new G3dVim( - instanceTransforms: g3d.InstanceTransforms.Concat(g3d.InstanceTransforms).ToArray(), - instanceMeshes: g3d.InstanceMeshes.Concat(g3d.InstanceMeshes.Select(i => i + g3d.GetMeshCount())).ToArray(), - instanceParents: g3d.InstanceParents.Concat(g3d.InstanceParents).ToArray(), - instanceFlags: null, - meshSubmeshOffsets: g3d.MeshSubmeshOffsets.Concat(g3d.MeshSubmeshOffsets.Select(i => g3d.GetSubmeshCount())).ToArray(), - submeshIndexOffsets: g3d.SubmeshIndexOffsets.Concat(g3d.SubmeshIndexOffsets.Select(i => i + g3d.GetIndexCount())).ToArray(), - submeshMaterials: g3d.SubmeshMaterials.Concat(g3d.SubmeshMaterials.Select(i => i + g3d.GetMaterialCount())).ToArray(), - indices: g3d.Indices.Concat(g3d.Indices.Select(i => i + g3d.Positions.Length)).ToArray(), - positions: g3d.Positions.Concat(g3d.Positions).ToArray(), - materialColors: g3d.MaterialColors.Concat(g3d.MaterialColors).ToArray(), - materialGlossiness: g3d.MaterialGlossiness.Concat(g3d.MaterialGlossiness).ToArray(), - materialSmoothness: g3d.MaterialSmoothness.Concat(g3d.MaterialSmoothness).ToArray(), - shapeColors: null, - shapeWidths: null, - shapeVertices: null, - shapeVertexOffsets: null - ); - Assert.IsTrue(merged.Equals(expected)); - } - } - -} - diff --git a/src/cs/vim/Vim.Vimx.Test/VimxTests.cs b/src/cs/vim/Vim.Vimx.Test/VimxTests.cs index 7977f978..fbd0393c 100644 --- a/src/cs/vim/Vim.Vimx.Test/VimxTests.cs +++ b/src/cs/vim/Vim.Vimx.Test/VimxTests.cs @@ -1,6 +1,5 @@ using NUnit.Framework; using NUnit.Framework.Internal; -using Vim.G3dNext.Tests; using Vim.Format.VimxNS.Conversion; using Vim.Util.Tests; @@ -12,14 +11,9 @@ public static class VimxTests [Test] public static void Can_Convert_And_Read_Vimx() { - if (!Directory.Exists(VimFormatRepoPaths.OutDir)) - { - Directory.CreateDirectory(VimFormatRepoPaths.OutDir); - } - var input = TestUtils.ResidencePath; var name = Path.GetFileNameWithoutExtension(TestUtils.ResidencePath); - var output = Path.Combine(VimFormatRepoPaths.OutDir, name + ".vimx"); + var output = TestUtils.PrepareOutputPath(name + ".vimx"); var vimx = VimxConverter.FromVimPath(input); vimx.ToBFast().Write(output); From 068cac6604b90acb8ef5e9cd6dfda0dbe59106d6 Mon Sep 17 00:00:00 2001 From: simon Date: Tue, 23 Jan 2024 00:16:20 -0500 Subject: [PATCH 055/111] removed attribute project --- .../Vim.G3dNext.Attributes/Attributes.g.cs | 476 ------------------ src/cs/g3d/Vim.G3dNext.Attributes/G3dChunk.cs | 169 ------- .../Vim.G3dNext.Attributes/G3dMaterials.cs | 20 - src/cs/g3d/Vim.G3dNext.Attributes/G3dScene.cs | 12 - src/cs/g3d/Vim.G3dNext.Attributes/G3dVim.cs | 186 ------- .../Vim.G3dNext.Attributes.csproj | 15 - 6 files changed, 878 deletions(-) delete mode 100644 src/cs/g3d/Vim.G3dNext.Attributes/Attributes.g.cs delete mode 100644 src/cs/g3d/Vim.G3dNext.Attributes/G3dChunk.cs delete mode 100644 src/cs/g3d/Vim.G3dNext.Attributes/G3dMaterials.cs delete mode 100644 src/cs/g3d/Vim.G3dNext.Attributes/G3dScene.cs delete mode 100644 src/cs/g3d/Vim.G3dNext.Attributes/G3dVim.cs delete mode 100644 src/cs/g3d/Vim.G3dNext.Attributes/Vim.G3dNext.Attributes.csproj diff --git a/src/cs/g3d/Vim.G3dNext.Attributes/Attributes.g.cs b/src/cs/g3d/Vim.G3dNext.Attributes/Attributes.g.cs deleted file mode 100644 index 7062796c..00000000 --- a/src/cs/g3d/Vim.G3dNext.Attributes/Attributes.g.cs +++ /dev/null @@ -1,476 +0,0 @@ -// AUTO-GENERATED FILE, DO NOT MODIFY. -// ReSharper disable All -using Vim.BFastNS; -using Vim.G3dNext; - -namespace Vim.G3dNext.Attributes -{ - // Please provide an explicit implementation in another partial class file. - public partial class G3dVim : ISetup - { - public System.Int32[] Indices; - public Vim.Math3d.Vector3[] Positions; - public Vim.Math3d.Matrix4x4[] InstanceTransforms; - public System.Int32[] InstanceParents; - public System.UInt16[] InstanceFlags; - public System.Int32[] InstanceMeshes; - public System.Int32[] MeshSubmeshOffsets; - public System.Int32[] SubmeshIndexOffsets; - public System.Int32[] SubmeshMaterials; - public Vim.Math3d.Vector4[] MaterialColors; - public System.Single[] MaterialGlossiness; - public System.Single[] MaterialSmoothness; - public Vim.Math3d.Vector3[] ShapeVertices; - public System.Int32[] ShapeVertexOffsets; - public Vim.Math3d.Vector4[] ShapeColors; - public System.Single[] ShapeWidths; - - public G3dVim( - System.Int32[] indices, - Vim.Math3d.Vector3[] positions, - Vim.Math3d.Matrix4x4[] instanceTransforms, - System.Int32[] instanceParents, - System.UInt16[] instanceFlags, - System.Int32[] instanceMeshes, - System.Int32[] meshSubmeshOffsets, - System.Int32[] submeshIndexOffsets, - System.Int32[] submeshMaterials, - Vim.Math3d.Vector4[] materialColors, - System.Single[] materialGlossiness, - System.Single[] materialSmoothness, - Vim.Math3d.Vector3[] shapeVertices, - System.Int32[] shapeVertexOffsets, - Vim.Math3d.Vector4[] shapeColors, - System.Single[] shapeWidths - ) - { - Indices = indices; - Positions = positions; - InstanceTransforms = instanceTransforms; - InstanceParents = instanceParents; - InstanceFlags = instanceFlags; - InstanceMeshes = instanceMeshes; - MeshSubmeshOffsets = meshSubmeshOffsets; - SubmeshIndexOffsets = submeshIndexOffsets; - SubmeshMaterials = submeshMaterials; - MaterialColors = materialColors; - MaterialGlossiness = materialGlossiness; - MaterialSmoothness = materialSmoothness; - ShapeVertices = shapeVertices; - ShapeVertexOffsets = shapeVertexOffsets; - ShapeColors = shapeColors; - ShapeWidths = shapeWidths; - - (this as ISetup).Setup(); - } - - public G3dVim(BFast bfast) - { - Indices = bfast.GetArray("g3d:corner:index:0:int32:1"); - Positions = bfast.GetArray("g3d:vertex:position:0:float32:3"); - InstanceTransforms = bfast.GetArray("g3d:instance:transform:0:float32:16"); - InstanceParents = bfast.GetArray("g3d:instance:parent:0:int32:1"); - InstanceFlags = bfast.GetArray("g3d:instance:flags:0:uint16:1"); - InstanceMeshes = bfast.GetArray("g3d:instance:mesh:0:int32:1"); - MeshSubmeshOffsets = bfast.GetArray("g3d:mesh:submeshoffset:0:int32:1"); - SubmeshIndexOffsets = bfast.GetArray("g3d:submesh:indexoffset:0:int32:1"); - SubmeshMaterials = bfast.GetArray("g3d:submesh:material:0:int32:1"); - MaterialColors = bfast.GetArray("g3d:material:color:0:float32:4"); - MaterialGlossiness = bfast.GetArray("g3d:material:glossiness:0:float32:1"); - MaterialSmoothness = bfast.GetArray("g3d:material:smoothness:0:float32:1"); - ShapeVertices = bfast.GetArray("g3d:shapevertex:position:0:float32:3"); - ShapeVertexOffsets = bfast.GetArray("g3d:shape:vertexoffset:0:int32:1"); - ShapeColors = bfast.GetArray("g3d:shape:color:0:float32:4"); - ShapeWidths = bfast.GetArray("g3d:shape:width:0:float32:1"); - - (this as ISetup).Setup(); - } - - public BFast ToBFast() - { - var bfast = new BFast(); - - bfast.SetArray("g3d:corner:index:0:int32:1", Indices); - bfast.SetArray("g3d:vertex:position:0:float32:3", Positions); - bfast.SetArray("g3d:instance:transform:0:float32:16", InstanceTransforms); - bfast.SetArray("g3d:instance:parent:0:int32:1", InstanceParents); - bfast.SetArray("g3d:instance:flags:0:uint16:1", InstanceFlags); - bfast.SetArray("g3d:instance:mesh:0:int32:1", InstanceMeshes); - bfast.SetArray("g3d:mesh:submeshoffset:0:int32:1", MeshSubmeshOffsets); - bfast.SetArray("g3d:submesh:indexoffset:0:int32:1", SubmeshIndexOffsets); - bfast.SetArray("g3d:submesh:material:0:int32:1", SubmeshMaterials); - bfast.SetArray("g3d:material:color:0:float32:4", MaterialColors); - bfast.SetArray("g3d:material:glossiness:0:float32:1", MaterialGlossiness); - bfast.SetArray("g3d:material:smoothness:0:float32:1", MaterialSmoothness); - bfast.SetArray("g3d:shapevertex:position:0:float32:3", ShapeVertices); - bfast.SetArray("g3d:shape:vertexoffset:0:int32:1", ShapeVertexOffsets); - bfast.SetArray("g3d:shape:color:0:float32:4", ShapeColors); - bfast.SetArray("g3d:shape:width:0:float32:1", ShapeWidths); - - return bfast; - } - - public bool Equals(G3dVim other ) - { - return Indices.SafeEquals(other.Indices) && - Positions.SafeEquals(other.Positions) && - InstanceTransforms.SafeEquals(other.InstanceTransforms) && - InstanceParents.SafeEquals(other.InstanceParents) && - InstanceFlags.SafeEquals(other.InstanceFlags) && - InstanceMeshes.SafeEquals(other.InstanceMeshes) && - MeshSubmeshOffsets.SafeEquals(other.MeshSubmeshOffsets) && - SubmeshIndexOffsets.SafeEquals(other.SubmeshIndexOffsets) && - SubmeshMaterials.SafeEquals(other.SubmeshMaterials) && - MaterialColors.SafeEquals(other.MaterialColors) && - MaterialGlossiness.SafeEquals(other.MaterialGlossiness) && - MaterialSmoothness.SafeEquals(other.MaterialSmoothness) && - ShapeVertices.SafeEquals(other.ShapeVertices) && - ShapeVertexOffsets.SafeEquals(other.ShapeVertexOffsets) && - ShapeColors.SafeEquals(other.ShapeColors) && - ShapeWidths.SafeEquals(other.ShapeWidths); - } - - - public G3dVim Merge(G3dVim other) - { - return new G3dVim( - Indices.MergeIndices(other.Indices, Positions?.Length ?? 0), - Positions.MergeData(other.Positions), - InstanceTransforms.MergeData(other.InstanceTransforms), - InstanceParents.MergeIndices(other.InstanceParents, InstanceTransforms?.Length ?? 0), - InstanceFlags.MergeData(other.InstanceFlags), - InstanceMeshes.MergeIndices(other.InstanceMeshes, MeshSubmeshOffsets?.Length ?? 0), - MeshSubmeshOffsets.MergeIndices(other.MeshSubmeshOffsets, SubmeshIndexOffsets?.Length ?? 0), - SubmeshIndexOffsets.MergeIndices(other.SubmeshIndexOffsets, Indices?.Length ?? 0), - SubmeshMaterials.MergeIndices(other.SubmeshMaterials, MaterialColors?.Length ?? 0), - MaterialColors.MergeData(other.MaterialColors), - MaterialGlossiness.MergeData(other.MaterialGlossiness), - MaterialSmoothness.MergeData(other.MaterialSmoothness), - ShapeVertices.MergeData(other.ShapeVertices), - ShapeVertexOffsets.MergeIndices(other.ShapeVertexOffsets, ShapeVertices?.Length ?? 0), - ShapeColors.MergeData(other.ShapeColors), - ShapeWidths.MergeData(other.ShapeWidths) - ); - } - - public void Validate() - { - // Ensure all the indices are either -1 or within the bounds of the attributes they are indexing into. - Indices?.ValidateIndex(Positions, "Indices"); - InstanceParents?.ValidateIndex(InstanceTransforms, "InstanceParents"); - InstanceMeshes?.ValidateIndex(MeshSubmeshOffsets, "InstanceMeshes"); - MeshSubmeshOffsets?.ValidateIndex(SubmeshIndexOffsets, "MeshSubmeshOffsets"); - SubmeshIndexOffsets?.ValidateIndex(Indices, "SubmeshIndexOffsets"); - SubmeshMaterials?.ValidateIndex(MaterialColors, "SubmeshMaterials"); - ShapeVertexOffsets?.ValidateIndex(ShapeVertices, "ShapeVertexOffsets"); - } - } - - // Please provide an explicit implementation in another partial class file. - public partial class G3dChunk : ISetup - { - public System.Int32[] MeshOpaqueSubmeshCounts; - public System.Int32[] MeshSubmeshOffset; - public System.Int32[] SubmeshIndexOffsets; - public System.Int32[] SubmeshVertexOffsets; - public System.Int32[] SubmeshMaterials; - public Vim.Math3d.Vector3[] Positions; - public System.Int32[] Indices; - - public G3dChunk( - System.Int32[] meshOpaqueSubmeshCounts, - System.Int32[] meshSubmeshOffset, - System.Int32[] submeshIndexOffsets, - System.Int32[] submeshVertexOffsets, - System.Int32[] submeshMaterials, - Vim.Math3d.Vector3[] positions, - System.Int32[] indices - ) - { - MeshOpaqueSubmeshCounts = meshOpaqueSubmeshCounts; - MeshSubmeshOffset = meshSubmeshOffset; - SubmeshIndexOffsets = submeshIndexOffsets; - SubmeshVertexOffsets = submeshVertexOffsets; - SubmeshMaterials = submeshMaterials; - Positions = positions; - Indices = indices; - - (this as ISetup).Setup(); - } - - public G3dChunk(BFast bfast) - { - MeshOpaqueSubmeshCounts = bfast.GetArray("g3d:mesh:opaquesubmeshcount:0:int32:1"); - MeshSubmeshOffset = bfast.GetArray("g3d:mesh:submeshOffset:0:int32:1"); - SubmeshIndexOffsets = bfast.GetArray("g3d:submesh:indexoffset:0:int32:1"); - SubmeshVertexOffsets = bfast.GetArray("g3d:submesh:vertexoffset:0:int32:1"); - SubmeshMaterials = bfast.GetArray("g3d:submesh:material:0:int32:1"); - Positions = bfast.GetArray("g3d:vertex:position:0:float32:3"); - Indices = bfast.GetArray("g3d:corner:index:0:int32:1"); - - (this as ISetup).Setup(); - } - - public BFast ToBFast() - { - var bfast = new BFast(); - - bfast.SetArray("g3d:mesh:opaquesubmeshcount:0:int32:1", MeshOpaqueSubmeshCounts); - bfast.SetArray("g3d:mesh:submeshOffset:0:int32:1", MeshSubmeshOffset); - bfast.SetArray("g3d:submesh:indexoffset:0:int32:1", SubmeshIndexOffsets); - bfast.SetArray("g3d:submesh:vertexoffset:0:int32:1", SubmeshVertexOffsets); - bfast.SetArray("g3d:submesh:material:0:int32:1", SubmeshMaterials); - bfast.SetArray("g3d:vertex:position:0:float32:3", Positions); - bfast.SetArray("g3d:corner:index:0:int32:1", Indices); - - return bfast; - } - - public bool Equals(G3dChunk other ) - { - return MeshOpaqueSubmeshCounts.SafeEquals(other.MeshOpaqueSubmeshCounts) && - MeshSubmeshOffset.SafeEquals(other.MeshSubmeshOffset) && - SubmeshIndexOffsets.SafeEquals(other.SubmeshIndexOffsets) && - SubmeshVertexOffsets.SafeEquals(other.SubmeshVertexOffsets) && - SubmeshMaterials.SafeEquals(other.SubmeshMaterials) && - Positions.SafeEquals(other.Positions) && - Indices.SafeEquals(other.Indices); - } - - - public G3dChunk Merge(G3dChunk other) - { - return new G3dChunk( - MeshOpaqueSubmeshCounts.MergeData(other.MeshOpaqueSubmeshCounts), - MeshSubmeshOffset.MergeIndices(other.MeshSubmeshOffset, Indices?.Length ?? 0), - SubmeshIndexOffsets.MergeIndices(other.SubmeshIndexOffsets, Indices?.Length ?? 0), - SubmeshVertexOffsets.MergeIndices(other.SubmeshVertexOffsets, Indices?.Length ?? 0), - SubmeshMaterials.MergeData(other.SubmeshMaterials), - Positions.MergeData(other.Positions), - Indices.MergeIndices(other.Indices, Positions?.Length ?? 0) - ); - } - - public void Validate() - { - // Ensure all the indices are either -1 or within the bounds of the attributes they are indexing into. - MeshSubmeshOffset?.ValidateIndex(Indices, "MeshSubmeshOffset"); - SubmeshIndexOffsets?.ValidateIndex(Indices, "SubmeshIndexOffsets"); - SubmeshVertexOffsets?.ValidateIndex(Indices, "SubmeshVertexOffsets"); - Indices?.ValidateIndex(Positions, "Indices"); - } - } - - // Please provide an explicit implementation in another partial class file. - public partial class G3dMaterials : ISetup - { - public Vim.Math3d.Vector4[] MaterialColors; - public System.Single[] MaterialGlossiness; - public System.Single[] MaterialSmoothness; - - public G3dMaterials( - Vim.Math3d.Vector4[] materialColors, - System.Single[] materialGlossiness, - System.Single[] materialSmoothness - ) - { - MaterialColors = materialColors; - MaterialGlossiness = materialGlossiness; - MaterialSmoothness = materialSmoothness; - - (this as ISetup).Setup(); - } - - public G3dMaterials(BFast bfast) - { - MaterialColors = bfast.GetArray("g3d:material:color:0:float32:4"); - MaterialGlossiness = bfast.GetArray("g3d:material:glossiness:0:float32:1"); - MaterialSmoothness = bfast.GetArray("g3d:material:smoothness:0:float32:1"); - - (this as ISetup).Setup(); - } - - public BFast ToBFast() - { - var bfast = new BFast(); - - bfast.SetArray("g3d:material:color:0:float32:4", MaterialColors); - bfast.SetArray("g3d:material:glossiness:0:float32:1", MaterialGlossiness); - bfast.SetArray("g3d:material:smoothness:0:float32:1", MaterialSmoothness); - - return bfast; - } - - public bool Equals(G3dMaterials other ) - { - return MaterialColors.SafeEquals(other.MaterialColors) && - MaterialGlossiness.SafeEquals(other.MaterialGlossiness) && - MaterialSmoothness.SafeEquals(other.MaterialSmoothness); - } - - - public G3dMaterials Merge(G3dMaterials other) - { - return new G3dMaterials( - MaterialColors.MergeData(other.MaterialColors), - MaterialGlossiness.MergeData(other.MaterialGlossiness), - MaterialSmoothness.MergeData(other.MaterialSmoothness) - ); - } - - public void Validate() - { - // Ensure all the indices are either -1 or within the bounds of the attributes they are indexing into. - - } - } - - // Please provide an explicit implementation in another partial class file. - public partial class G3dScene : ISetup - { - public System.Int32[] ChunkCount; - public System.Int32[] InstanceMeshes; - public Vim.Math3d.Matrix4x4[] InstanceTransformData; - public System.Int32[] InstanceNodes; - public System.Int32[] InstanceGroups; - public System.Int64[] InstanceTags; - public System.UInt16[] InstanceFlags; - public Vim.Math3d.Vector3[] InstanceMins; - public Vim.Math3d.Vector3[] InstanceMaxs; - public System.Int32[] MeshChunks; - public System.Int32[] MeshChunkIndices; - public System.Int32[] MeshVertexCounts; - public System.Int32[] MeshIndexCounts; - public System.Int32[] MeshOpaqueVertexCounts; - public System.Int32[] MeshOpaqueIndexCounts; - - public G3dScene( - System.Int32[] chunkCount, - System.Int32[] instanceMeshes, - Vim.Math3d.Matrix4x4[] instanceTransformData, - System.Int32[] instanceNodes, - System.Int32[] instanceGroups, - System.Int64[] instanceTags, - System.UInt16[] instanceFlags, - Vim.Math3d.Vector3[] instanceMins, - Vim.Math3d.Vector3[] instanceMaxs, - System.Int32[] meshChunks, - System.Int32[] meshChunkIndices, - System.Int32[] meshVertexCounts, - System.Int32[] meshIndexCounts, - System.Int32[] meshOpaqueVertexCounts, - System.Int32[] meshOpaqueIndexCounts - ) - { - ChunkCount = chunkCount; - InstanceMeshes = instanceMeshes; - InstanceTransformData = instanceTransformData; - InstanceNodes = instanceNodes; - InstanceGroups = instanceGroups; - InstanceTags = instanceTags; - InstanceFlags = instanceFlags; - InstanceMins = instanceMins; - InstanceMaxs = instanceMaxs; - MeshChunks = meshChunks; - MeshChunkIndices = meshChunkIndices; - MeshVertexCounts = meshVertexCounts; - MeshIndexCounts = meshIndexCounts; - MeshOpaqueVertexCounts = meshOpaqueVertexCounts; - MeshOpaqueIndexCounts = meshOpaqueIndexCounts; - - (this as ISetup).Setup(); - } - - public G3dScene(BFast bfast) - { - ChunkCount = bfast.GetArray("g3d:chunk:count:0:int32:1"); - InstanceMeshes = bfast.GetArray("g3d:instance:mesh:0:int32:1"); - InstanceTransformData = bfast.GetArray("g3d:instance:transform:0:float32:16"); - InstanceNodes = bfast.GetArray("g3d:instance:node:0:int32:1"); - InstanceGroups = bfast.GetArray("g3d:instance:group:0:int32:1"); - InstanceTags = bfast.GetArray("g3d:instance:tag:0:int64:1"); - InstanceFlags = bfast.GetArray("g3d:instance:flags:0:uint16:1"); - InstanceMins = bfast.GetArray("g3d:instance:min:0:float32:3"); - InstanceMaxs = bfast.GetArray("g3d:instance:max:0:float32:3"); - MeshChunks = bfast.GetArray("g3d:mesh:chunk:0:int32:1"); - MeshChunkIndices = bfast.GetArray("g3d:mesh:chunkindex:0:int32:1"); - MeshVertexCounts = bfast.GetArray("g3d:mesh:vertexcount:0:int32:1"); - MeshIndexCounts = bfast.GetArray("g3d:mesh:indexcount:0:int32:1"); - MeshOpaqueVertexCounts = bfast.GetArray("g3d:mesh:opaquevertexcount:0:int32:1"); - MeshOpaqueIndexCounts = bfast.GetArray("g3d:mesh:opaqueindexcount:0:int32:1"); - - (this as ISetup).Setup(); - } - - public BFast ToBFast() - { - var bfast = new BFast(); - - bfast.SetArray("g3d:chunk:count:0:int32:1", ChunkCount); - bfast.SetArray("g3d:instance:mesh:0:int32:1", InstanceMeshes); - bfast.SetArray("g3d:instance:transform:0:float32:16", InstanceTransformData); - bfast.SetArray("g3d:instance:node:0:int32:1", InstanceNodes); - bfast.SetArray("g3d:instance:group:0:int32:1", InstanceGroups); - bfast.SetArray("g3d:instance:tag:0:int64:1", InstanceTags); - bfast.SetArray("g3d:instance:flags:0:uint16:1", InstanceFlags); - bfast.SetArray("g3d:instance:min:0:float32:3", InstanceMins); - bfast.SetArray("g3d:instance:max:0:float32:3", InstanceMaxs); - bfast.SetArray("g3d:mesh:chunk:0:int32:1", MeshChunks); - bfast.SetArray("g3d:mesh:chunkindex:0:int32:1", MeshChunkIndices); - bfast.SetArray("g3d:mesh:vertexcount:0:int32:1", MeshVertexCounts); - bfast.SetArray("g3d:mesh:indexcount:0:int32:1", MeshIndexCounts); - bfast.SetArray("g3d:mesh:opaquevertexcount:0:int32:1", MeshOpaqueVertexCounts); - bfast.SetArray("g3d:mesh:opaqueindexcount:0:int32:1", MeshOpaqueIndexCounts); - - return bfast; - } - - public bool Equals(G3dScene other ) - { - return ChunkCount.SafeEquals(other.ChunkCount) && - InstanceMeshes.SafeEquals(other.InstanceMeshes) && - InstanceTransformData.SafeEquals(other.InstanceTransformData) && - InstanceNodes.SafeEquals(other.InstanceNodes) && - InstanceGroups.SafeEquals(other.InstanceGroups) && - InstanceTags.SafeEquals(other.InstanceTags) && - InstanceFlags.SafeEquals(other.InstanceFlags) && - InstanceMins.SafeEquals(other.InstanceMins) && - InstanceMaxs.SafeEquals(other.InstanceMaxs) && - MeshChunks.SafeEquals(other.MeshChunks) && - MeshChunkIndices.SafeEquals(other.MeshChunkIndices) && - MeshVertexCounts.SafeEquals(other.MeshVertexCounts) && - MeshIndexCounts.SafeEquals(other.MeshIndexCounts) && - MeshOpaqueVertexCounts.SafeEquals(other.MeshOpaqueVertexCounts) && - MeshOpaqueIndexCounts.SafeEquals(other.MeshOpaqueIndexCounts); - } - - - public G3dScene Merge(G3dScene other) - { - return new G3dScene( - ChunkCount.MergeData(other.ChunkCount), - InstanceMeshes.MergeData(other.InstanceMeshes), - InstanceTransformData.MergeData(other.InstanceTransformData), - InstanceNodes.MergeData(other.InstanceNodes), - InstanceGroups.MergeData(other.InstanceGroups), - InstanceTags.MergeData(other.InstanceTags), - InstanceFlags.MergeData(other.InstanceFlags), - InstanceMins.MergeData(other.InstanceMins), - InstanceMaxs.MergeData(other.InstanceMaxs), - MeshChunks.MergeData(other.MeshChunks), - MeshChunkIndices.MergeData(other.MeshChunkIndices), - MeshVertexCounts.MergeData(other.MeshVertexCounts), - MeshIndexCounts.MergeData(other.MeshIndexCounts), - MeshOpaqueVertexCounts.MergeData(other.MeshOpaqueVertexCounts), - MeshOpaqueIndexCounts.MergeData(other.MeshOpaqueIndexCounts) - ); - } - - public void Validate() - { - // Ensure all the indices are either -1 or within the bounds of the attributes they are indexing into. - - } - } - -} diff --git a/src/cs/g3d/Vim.G3dNext.Attributes/G3dChunk.cs b/src/cs/g3d/Vim.G3dNext.Attributes/G3dChunk.cs deleted file mode 100644 index 698a29de..00000000 --- a/src/cs/g3d/Vim.G3dNext.Attributes/G3dChunk.cs +++ /dev/null @@ -1,169 +0,0 @@ -using System; -using Vim.Math3d; - -namespace Vim.G3dNext.Attributes -{ - public partial class G3dChunk - { - void ISetup.Setup() - { - // empty - } - - /// - /// The total number of instances. - /// - - public int GetSubmeshCount() => SubmeshIndexOffsets?.Length ?? 0; - - - public int getMeshCount() => MeshSubmeshOffset?.Length ?? 0; - - /// - /// The total number of submeshes. - /// - public int GetSubmeshCount(int mesh, MeshSection section) => - GetMeshSubmeshEnd(mesh, section) - GetMeshSubmeshStart(mesh, section); - - public int GetMeshSubmeshStart(int mesh, MeshSection section) - { - if (section == MeshSection.Opaque || section == MeshSection.All) - { - return MeshSubmeshOffset[mesh]; - } - - return MeshSubmeshOffset[mesh] + MeshOpaqueSubmeshCounts[mesh]; - } - - public int GetMeshSubmeshEnd(int mesh, MeshSection section) - { - if (section == MeshSection.Opaque) - { - return MeshSubmeshOffset[mesh] + MeshOpaqueSubmeshCounts[mesh]; - } - if(mesh + 1 >= MeshSubmeshOffset.Length) - { - return SubmeshIndexOffsets.Length; - } - return MeshSubmeshOffset[mesh + 1]; - } - - public int GetMeshIndexStart(int mesh, MeshSection section) - { - var sub = GetMeshSubmeshStart(mesh, section); - return GetSubmeshIndexStart(sub); - } - - public int GetMeshIndexEnd(int mesh, MeshSection section) - { - var sub = GetMeshSubmeshEnd(mesh, section); - return GetSubmeshIndexEnd(sub); - } - - public int GetMeshIndexCount(int mesh, MeshSection section) - { - return GetMeshIndexEnd(mesh, section) - GetMeshIndexStart(mesh, section); - } - - public AABox GetAABox(int mesh, Matrix4x4 matrix) - { - var start = GetMeshVertexStart(mesh, MeshSection.All); - var end = GetMeshVertexEnd(mesh, MeshSection.All); - var min = Positions[start].Transform(matrix); - var max = min; - for (var v = start + 1; v < end; v++) - { - var pos = Positions[v].Transform(matrix); - min = min.Min(pos); - max = max.Max(pos); - } - return new AABox(min, max); - } - - /// - /// The total number of indices. - /// - public int GetIndexCount() => Indices?.Length ?? 0; - - public int GetMeshVertexStart(int mesh, MeshSection section) - { - var sub = GetMeshSubmeshStart(mesh, section); - return GetSubmeshVertexStart(sub); - } - - public int GetMeshVertexEnd(int mesh, MeshSection section) - { - var sub = GetMeshSubmeshEnd(mesh, section); - return GetSubmeshVertexEnd(sub); - } - - public int GetMeshVertexCount(int mesh, MeshSection section) - { - return GetMeshVertexEnd(mesh, section) - GetMeshVertexStart(mesh, section); - } - - /// - /// The total number of vertices. - /// - public int GetVertexCount() => (Positions?.Length ?? 0); - - public int GetSubmeshIndexStart(int submesh) - { - return SubmeshIndexOffsets[submesh]; - } - - public int GetSubmeshIndexEnd(int submesh) - { - return submesh + 1 < GetSubmeshCount() - ? SubmeshIndexOffsets[submesh + 1] - : GetIndexCount(); - } - - public int GetSubmeshIndexCount(int submesh) - { - return GetSubmeshIndexEnd(submesh) - GetSubmeshIndexStart(submesh); - } - - public int GetSubmeshVertexStart(int submesh) - { - return SubmeshVertexOffsets[submesh]; - } - - public int GetSubmeshVertexEnd(int submesh) - { - return submesh + 1 < GetSubmeshCount() ? SubmeshVertexOffsets[submesh + 1] : GetVertexCount(); - } - - public int GetSubmeshVertexCount(int submesh) - { - return GetSubmeshVertexEnd(submesh) - GetSubmeshVertexStart(submesh); - } - - public AABox GetAABB() - { - var box = new AABox(Positions[0], Positions[0]); - for (var p = 1; p < Positions.Length; p++) - { - var pos = Positions[p]; - box = Expand(box, pos); - } - return box; - } - - static AABox Expand(AABox box, Vector3 pos) - { - return new AABox( - new Vector3( - Math.Min(box.Min.X, pos.X), - Math.Min(box.Min.Y, pos.Y), - Math.Min(box.Min.Z, pos.Z) - ), - new Vector3( - Math.Max(box.Max.X, pos.X), - Math.Max(box.Max.Y, pos.Y), - Math.Max(box.Max.Z, pos.Z) - ) - ); - } - } -} diff --git a/src/cs/g3d/Vim.G3dNext.Attributes/G3dMaterials.cs b/src/cs/g3d/Vim.G3dNext.Attributes/G3dMaterials.cs deleted file mode 100644 index 6515edf8..00000000 --- a/src/cs/g3d/Vim.G3dNext.Attributes/G3dMaterials.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System.Runtime.ConstrainedExecution; - -namespace Vim.G3dNext.Attributes -{ - public partial class G3dMaterials - { - void ISetup.Setup() - { - // empty - } - - - public G3dMaterials(G3dVim vim) - { - MaterialColors = vim.MaterialColors; - MaterialGlossiness = vim.MaterialGlossiness; - MaterialSmoothness = vim.MaterialSmoothness; - } - } -} diff --git a/src/cs/g3d/Vim.G3dNext.Attributes/G3dScene.cs b/src/cs/g3d/Vim.G3dNext.Attributes/G3dScene.cs deleted file mode 100644 index 65e693dd..00000000 --- a/src/cs/g3d/Vim.G3dNext.Attributes/G3dScene.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace Vim.G3dNext.Attributes -{ - public partial class G3dScene - { - public int GetChunksCount() => ChunkCount[0]; - public int GetInstanceCount() => InstanceMeshes.Length; - void ISetup.Setup() - { - // empty - } - } -} diff --git a/src/cs/g3d/Vim.G3dNext.Attributes/G3dVim.cs b/src/cs/g3d/Vim.G3dNext.Attributes/G3dVim.cs deleted file mode 100644 index 10bd6732..00000000 --- a/src/cs/g3d/Vim.G3dNext.Attributes/G3dVim.cs +++ /dev/null @@ -1,186 +0,0 @@ -using System; -using System.Collections.Generic; -using Vim.BFastNS; - -namespace Vim.G3dNext.Attributes -{ - public partial class G3dVim - { - // Computed field - public int[] MeshVertexOffsets; - private List[] _meshInstances; - - public IReadOnlyList GetMeshInstances(int mesh) - { - return _meshInstances[mesh]; - } - - public int GetApproxSize(int mesh) - { - return GetMeshVertexCount(mesh) * 12 + GetMeshIndexCount(mesh) * 4; - } - - void ISetup.Setup() - { - MeshVertexOffsets = ComputeMeshVertexOffsets(); - _meshInstances = ComputeMeshInstances(); - } - - public static G3dVim FromVim(string vimPath) - => vimPath.ReadBFast(b => new G3dVim(b.GetBFast("geometry"))); - - private int[] ComputeMeshVertexOffsets() - { - var result = new int[GetMeshCount()]; - for (var m = 0; m < result.Length; m++) - { - var min = int.MaxValue; - var start = GetMeshIndexStart(m); - var end = GetMeshIndexEnd(m); - for (var i = start; i < end; i++) - { - min = Math.Min(min, Indices[i]); - } - result[m] = min; - } - return result; - } - - private List[] ComputeMeshInstances() - { - var result = new List[GetMeshCount()]; - for (var i = 0; i < result.Length; i++) - { - result[i] = new List(); - } - - for (var i = 0; i < InstanceMeshes.Length; i++) - { - var mesh = InstanceMeshes[i]; - if (mesh >= 0) - { - result[mesh].Add(i); - } - } - - return result; - } - - - public int GetTriangleCount() - { - return GetIndexCount() / 3; - } - - /// - /// The total number of instances. - /// - public int GetInstanceCount() => InstanceTransforms?.Length ?? 0; - - #region meshes - /// - /// The total number of meshes. - /// - public int GetMeshCount() => MeshSubmeshOffsets?.Length ?? 0; - - public int GetMeshIndexStart(int mesh) - { - var submesh = GetMeshSubmeshStart(mesh); - return GetSubmeshIndexStart(submesh); - } - - public int GetMeshIndexEnd(int mesh) - { - var submesh = GetMeshSubmeshEnd(mesh) - 1; - return GetSubmeshIndexEnd(submesh); - } - - public int GetMeshIndexCount(int mesh) - { - return GetMeshIndexEnd(mesh) - GetMeshIndexStart(mesh); - } - - public int GetMeshVertexStart(int mesh) - { - return MeshVertexOffsets[mesh]; - } - - public int GetMeshVertexEnd(int mesh) - { - return mesh + 1 < GetMeshCount() ? MeshVertexOffsets[mesh + 1] : Positions.Length; - } - - public int GetMeshVertexCount(int mesh) - { - return GetMeshVertexEnd(mesh) - GetMeshVertexStart(mesh); - } - - public int GetMeshSubmeshStart(int mesh) - { - return MeshSubmeshOffsets[mesh]; - } - - public int GetMeshSubmeshEnd(int mesh) - { - return mesh + 1 < GetMeshCount() - ? MeshSubmeshOffsets[mesh + 1] - : GetSubmeshCount(); - } - - public int GetMeshSubmeshCount(int mesh) - { - return GetMeshSubmeshEnd(mesh) - GetMeshSubmeshStart(mesh); - } - - #endregion - - #region submesh - - /// - /// The total number of submeshes. - /// - public int GetSubmeshCount() => SubmeshIndexOffsets?.Length ?? 0; - - public int GetSubmeshIndexStart(int submesh) - { - return SubmeshIndexOffsets[submesh]; - } - - public int GetSubmeshIndexEnd(int submesh) - { - return submesh + 1 < GetSubmeshCount() ? SubmeshIndexOffsets[submesh + 1] : GetIndexCount(); - } - - public int GetSubmeshIndexCount(int submesh) - { - return GetSubmeshIndexEnd(submesh) - GetSubmeshIndexStart(submesh); - } - - #endregion - - /// - /// The total number of indices. - /// - public int GetIndexCount() => Indices?.Length ?? 0; - - /// - /// The total number of vertices. - /// - public int GetVertexCount() => Positions?.Length ?? 0; - - /// - /// The total number of materials. - /// - public int GetMaterialCount() => MaterialColors?.Length ?? 0; - - /// - /// The total number of shapes. - /// - public int GetShapeCount() => ShapeVertexOffsets?.Length ?? 0; - - /// - /// The total number of shape vertices. - /// - public int GetShapeVertexCount() => ShapeVertices?.Length ?? 0; - } -} diff --git a/src/cs/g3d/Vim.G3dNext.Attributes/Vim.G3dNext.Attributes.csproj b/src/cs/g3d/Vim.G3dNext.Attributes/Vim.G3dNext.Attributes.csproj deleted file mode 100644 index b842cea6..00000000 --- a/src/cs/g3d/Vim.G3dNext.Attributes/Vim.G3dNext.Attributes.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - netstandard2.0 - - - - - - - - - - - - From 3646e0ca8fe3d45de8c545e8d960a1c5424a4e19 Mon Sep 17 00:00:00 2001 From: simon Date: Tue, 23 Jan 2024 13:45:14 -0500 Subject: [PATCH 056/111] removed writting to file, just test to and from bfast. --- src/cs/g3d/Vim.G3d.Tests/G3dTests.cs | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/cs/g3d/Vim.G3d.Tests/G3dTests.cs b/src/cs/g3d/Vim.G3d.Tests/G3dTests.cs index 60d23fd5..bd08a7c5 100644 --- a/src/cs/g3d/Vim.G3d.Tests/G3dTests.cs +++ b/src/cs/g3d/Vim.G3d.Tests/G3dTests.cs @@ -243,13 +243,10 @@ public static void TriangleTest() [Test] public static void UnexpectedAttributes_Are_Ignored() { - var unexpected = Path.Combine(TestInputFolder, "unexpected.g3d"); - var bfast = new BFast(); bfast.SetArray("g3d:instance:potato:0:int32:1", new int[] { 5 }); - bfast.Write(unexpected); - var g = G3D.Read(unexpected); + var g = G3D.Read(bfast); var parsedInstanceAttrs = g.Attributes.Where(ga => ga.Descriptor.Association == Association.assoc_instance).ToArray(); var parsedPotatoAttr = parsedInstanceAttrs.Single(ga => ga.Descriptor.Semantic == "potato"); Assert.AreEqual(new [] { 5 }, parsedPotatoAttr.AsType().Data.ToArray()); @@ -272,12 +269,13 @@ public static void BigFileTest() var vertices = nVerts.Select(i => new Vector3(i, i, i)); var bldr = new G3DBuilder(); bldr.AddVertices(vertices); - var g3d = bldr.ToG3D(); - Assert.AreEqual(nVerts, g3d.NumVertices); - var tempFile = Path.Combine(Path.GetTempPath(), "bigfile.g3d"); - g3d.ToBFast().Write(tempFile); - var tmp = G3D.Read(tempFile); - ValidateSameG3D(g3d, tmp); + + var expectedG3d = bldr.ToG3D(); + Assert.AreEqual(nVerts, expectedG3d.NumVertices); + var bfast = expectedG3d.ToBFast(); + var resultG3d = G3D.Read(bfast); + + ValidateSameG3D(expectedG3d, resultG3d); } [Test, Explicit] From 9ac5e8c2e68309ff21f481f9510d1cfff00c9dd4 Mon Sep 17 00:00:00 2001 From: simon Date: Tue, 23 Jan 2024 13:46:02 -0500 Subject: [PATCH 057/111] removed comment --- .../bfast/Vim.BFast/Buffers/UnsafeHelpers.cs | 31 ------------------- 1 file changed, 31 deletions(-) diff --git a/src/cs/bfast/Vim.BFast/Buffers/UnsafeHelpers.cs b/src/cs/bfast/Vim.BFast/Buffers/UnsafeHelpers.cs index 8c0428cd..c14765fd 100644 --- a/src/cs/bfast/Vim.BFast/Buffers/UnsafeHelpers.cs +++ b/src/cs/bfast/Vim.BFast/Buffers/UnsafeHelpers.cs @@ -82,7 +82,6 @@ public static unsafe void ReadArray(this Stream stream, T[] array, int count) } } - /// /// Equivalent to ReadArray to use when you know the byte count instead of element count. /// @@ -93,36 +92,6 @@ public static unsafe T[] ReadArrayBytes(this Stream stream, long byteLength) return ReadArray(stream, (int)count); } - /* - public static unsafe T[] ConvertByteArrayToTypeArray(byte[] byteArray) where T : unmanaged - { - if (byteArray.Length % sizeof(T) != 0) - { - throw new ArgumentException("Byte array length is not a multiple of the size of the target type."); - } - - var elementCount = byteArray.Length / sizeof(T); - var resultArray = new T[elementCount]; - - fixed (byte* bytePtr = byteArray) - { - byte* currentBytePtr = bytePtr; - fixed (T* resultPtr = resultArray) - { - var currentResultPtr = resultPtr; - for (var i = 0; i < elementCount; i++) - { - *currentResultPtr = *((T*)currentBytePtr); - currentBytePtr += sizeof(T); - currentResultPtr++; - } - } - } - - return resultArray; - } - - */ /// /// A wrapper for stream.Seek(numBytes, SeekOrigin.Current) to avoid allocating memory for unrecognized buffers. /// From f63a84609da0eb9c3415c9bb99150daadbe8f6db Mon Sep 17 00:00:00 2001 From: simon Date: Tue, 23 Jan 2024 13:46:25 -0500 Subject: [PATCH 058/111] removed rogue capital letter. --- src/cs/g3d/Vim.G3dNext.CodeGen/Definitions.cs | 2 +- src/cs/g3d/Vim.G3dNext.CodeGen/G3dBuffer.cs | 3 +++ src/cs/g3d/Vim.G3dNext/G3dGenerated.g.cs | 4 ++-- src/ts/src/g3dChunk.ts | 2 +- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/cs/g3d/Vim.G3dNext.CodeGen/Definitions.cs b/src/cs/g3d/Vim.G3dNext.CodeGen/Definitions.cs index 7df037ee..9eb47307 100644 --- a/src/cs/g3d/Vim.G3dNext.CodeGen/Definitions.cs +++ b/src/cs/g3d/Vim.G3dNext.CodeGen/Definitions.cs @@ -52,7 +52,7 @@ public static G3dEntity[] GetEntities() public static G3dEntity mesh = new G3dEntity("G3dChunk") .Data("MeshOpaqueSubmeshCounts", "g3d:mesh:opaquesubmeshcount:0:int32:1") - .Index("MeshSubmeshOffset", "g3d:mesh:submeshOffset:0:int32:1", "Indices") + .Index("MeshSubmeshOffset", "g3d:mesh:submeshoffset:0:int32:1", "Indices") .Index("SubmeshIndexOffsets", "g3d:submesh:indexoffset:0:int32:1", "Indices") .Index("SubmeshVertexOffsets", "g3d:submesh:vertexoffset:0:int32:1", "Indices") .Index("SubmeshMaterials", "g3d:submesh:material:0:int32:1") diff --git a/src/cs/g3d/Vim.G3dNext.CodeGen/G3dBuffer.cs b/src/cs/g3d/Vim.G3dNext.CodeGen/G3dBuffer.cs index b2a832fa..afdd3494 100644 --- a/src/cs/g3d/Vim.G3dNext.CodeGen/G3dBuffer.cs +++ b/src/cs/g3d/Vim.G3dNext.CodeGen/G3dBuffer.cs @@ -1,4 +1,5 @@ using System; +using System.Diagnostics; namespace Vim.G3dNext.CodeGen { @@ -21,6 +22,8 @@ public class G3dBuffer public G3dBuffer(string name, string bufferName, BufferType bufferType, Type valueType, string indexInto = null) { + Debug.Assert(bufferName.ToLower() == bufferName, "G3dCodeGen: Expected buffer name to be lowercase."); + MemberName = name; BufferName = bufferName; BufferType = bufferType; diff --git a/src/cs/g3d/Vim.G3dNext/G3dGenerated.g.cs b/src/cs/g3d/Vim.G3dNext/G3dGenerated.g.cs index 2783b521..b713c6b5 100644 --- a/src/cs/g3d/Vim.G3dNext/G3dGenerated.g.cs +++ b/src/cs/g3d/Vim.G3dNext/G3dGenerated.g.cs @@ -199,7 +199,7 @@ System.Int32[] indices public G3dChunk(BFast bfast) { MeshOpaqueSubmeshCounts = bfast.GetArray("g3d:mesh:opaquesubmeshcount:0:int32:1"); - MeshSubmeshOffset = bfast.GetArray("g3d:mesh:submeshOffset:0:int32:1"); + MeshSubmeshOffset = bfast.GetArray("g3d:mesh:submeshoffset:0:int32:1"); SubmeshIndexOffsets = bfast.GetArray("g3d:submesh:indexoffset:0:int32:1"); SubmeshVertexOffsets = bfast.GetArray("g3d:submesh:vertexoffset:0:int32:1"); SubmeshMaterials = bfast.GetArray("g3d:submesh:material:0:int32:1"); @@ -214,7 +214,7 @@ public BFast ToBFast() var bfast = new BFast(); bfast.SetArray("g3d:mesh:opaquesubmeshcount:0:int32:1", MeshOpaqueSubmeshCounts); - bfast.SetArray("g3d:mesh:submeshOffset:0:int32:1", MeshSubmeshOffset); + bfast.SetArray("g3d:mesh:submeshoffset:0:int32:1", MeshSubmeshOffset); bfast.SetArray("g3d:submesh:indexoffset:0:int32:1", SubmeshIndexOffsets); bfast.SetArray("g3d:submesh:vertexoffset:0:int32:1", SubmeshVertexOffsets); bfast.SetArray("g3d:submesh:material:0:int32:1", SubmeshMaterials); diff --git a/src/ts/src/g3dChunk.ts b/src/ts/src/g3dChunk.ts index 9bc94bc6..4e08d2bc 100644 --- a/src/ts/src/g3dChunk.ts +++ b/src/ts/src/g3dChunk.ts @@ -12,7 +12,7 @@ import { BFast } from './bfast'; * See https://github.com/vimaec/vim#vim-geometry-attributes */ export class MeshAttributes { - static meshSubmeshOffset = 'g3d:mesh:submeshOffset:0:int32:1' + static meshSubmeshOffset = 'g3d:mesh:submeshoffset:0:int32:1' static meshOpaqueSubmeshCount = 'g3d:mesh:opaquesubmeshcount:0:int32:1' static submeshIndexOffsets = 'g3d:submesh:indexoffset:0:int32:1' static submeshVertexOffsets = 'g3d:submesh:vertexoffset:0:int32:1' From 516bca80829e626e07e9c3c2b5b3042092cc296f Mon Sep 17 00:00:00 2001 From: simon Date: Tue, 23 Jan 2024 14:42:59 -0500 Subject: [PATCH 059/111] removed unneeded reference --- src/cs/vim/Vim.Format.Core/G3dBuilder.cs | 1 - src/cs/vim/Vim.Format.Core/Vim.Format.Core.csproj | 1 - 2 files changed, 2 deletions(-) diff --git a/src/cs/vim/Vim.Format.Core/G3dBuilder.cs b/src/cs/vim/Vim.Format.Core/G3dBuilder.cs index 841fc83d..f5d39d48 100644 --- a/src/cs/vim/Vim.Format.Core/G3dBuilder.cs +++ b/src/cs/vim/Vim.Format.Core/G3dBuilder.cs @@ -4,7 +4,6 @@ using Vim.BFastNS; using static Vim.Format.DocumentBuilder; using Vim.Math3d; -using Vim.G3dNext; namespace Vim.Format { diff --git a/src/cs/vim/Vim.Format.Core/Vim.Format.Core.csproj b/src/cs/vim/Vim.Format.Core/Vim.Format.Core.csproj index 4abbc208..d845180e 100644 --- a/src/cs/vim/Vim.Format.Core/Vim.Format.Core.csproj +++ b/src/cs/vim/Vim.Format.Core/Vim.Format.Core.csproj @@ -8,7 +8,6 @@ - From 0fa5786d6cec302d2d6ae2345f79d32bb7bf7547 Mon Sep 17 00:00:00 2001 From: simon Date: Thu, 8 Feb 2024 14:31:08 -0500 Subject: [PATCH 060/111] New write code for bfast. --- src/cs/bfast/Vim.BFast.Tests/BFastTests.cs | 83 ++++--- src/cs/bfast/Vim.BFast/BFast/BFast.cs | 78 +++---- .../Vim.BFast/BFast/BFastEnumerableNode.cs | 1 - .../Vim.BFast/BFast/BFastNextExtensions.cs | 33 +++ src/cs/bfast/Vim.BFast/BFast/BFastNode.cs | 7 - src/cs/bfast/Vim.BFast/BFast/IBFastNode.cs | 5 +- .../bfast/Vim.BFast/Buffers/UnsafeHelpers.cs | 10 + src/cs/bfast/Vim.BFast/Core/BFastAlignment.cs | 49 ----- src/cs/bfast/Vim.BFast/Core/BFastConstants.cs | 5 - src/cs/bfast/Vim.BFast/Core/BFastHeader.cs | 74 +++---- src/cs/bfast/Vim.BFast/Core/BFastPreamble.cs | 27 ++- src/cs/bfast/Vim.BFast/Core/BFastReader.cs | 43 ---- src/cs/bfast/Vim.BFast/Core/BFastSection.cs | 107 ++++++++++ src/cs/bfast/Vim.BFast/Core/BFastWriter.cs | 202 ++++++------------ 14 files changed, 348 insertions(+), 376 deletions(-) create mode 100644 src/cs/bfast/Vim.BFast/BFast/BFastNextExtensions.cs delete mode 100644 src/cs/bfast/Vim.BFast/Core/BFastAlignment.cs delete mode 100644 src/cs/bfast/Vim.BFast/Core/BFastReader.cs create mode 100644 src/cs/bfast/Vim.BFast/Core/BFastSection.cs diff --git a/src/cs/bfast/Vim.BFast.Tests/BFastTests.cs b/src/cs/bfast/Vim.BFast.Tests/BFastTests.cs index a1ec1a7f..fcab5218 100644 --- a/src/cs/bfast/Vim.BFast.Tests/BFastTests.cs +++ b/src/cs/bfast/Vim.BFast.Tests/BFastTests.cs @@ -1,4 +1,5 @@ using NUnit.Framework; +using Vim.BFastNS.Core; using Vim.Util.Tests; namespace Vim.BFastNS.Tests @@ -54,23 +55,18 @@ public void EmptyBFast_Remove_Does_Nothing() bfast.Remove("missing"); } - [Test] - public void EmptyBFast_GetSize_Return_64() - { - var bfast = new BFast(); - Assert.That(bfast.GetSize(), Is.EqualTo(64)); - } [Test] public void EmptyBFast_Writes_Header() { var bfast = new BFast(); - bfast.Write(ResultPath); - using (var stream = File.OpenRead(ResultPath)) - { - var bfast2 = new BFast(stream); - Assert.That(bfast2.GetSize(), Is.EqualTo(64)); - } + var stream = new MemoryStream(); + bfast.Write(stream); + + stream.Seek(0, SeekOrigin.Begin); + var raw = BFastHeader.FromStream(stream); + + Assert.That(raw.Ranges.Count, Is.EqualTo(0)); } [Test] @@ -298,6 +294,26 @@ public void SetBFast_Then_GetBFast_Returns_Same() Assert.That(result, Is.EqualTo(b)); } + [Test] + public void SetBFast_Then_GetBFast_Nested() + { + using (var file = File.Open(ResidencePath, FileMode.Open)) + { + var (b1, b2, b3) = (new BFast(), new BFast(), new BFast()); + b2.SetBFast("b3", b3); + b1.SetBFast("b2", b2); + + var mem = b1.ToMemoryStream(); + var r1 = new BFast(mem); + var r2 = r1.GetBFast("b2"); + var r3 = r2.GetBFast("b3"); + + Assert.NotNull(r1); + Assert.NotNull(r2); + Assert.NotNull(r3); + } + } + [Test] public void Inflate_NonDeflated_Throws() { @@ -313,7 +329,7 @@ public void Deflate_Inflate_Works() var bfast = new BFast(); var b = new BFast(); b.SetArray("B", new int[3] { 0, 1, 2 }); - bfast.SetBFast("A", b, deflate : true); + bfast.SetBFast("A", b, deflate: true); var result = bfast.GetBFast("A", inflate: true); var b2 = result.GetArray("B"); @@ -321,6 +337,23 @@ public void Deflate_Inflate_Works() Assert.That(b2, Is.EqualTo(new int[3] { 0, 1, 2 })); } + [Test] + public void Deflate_Inflate_WriteRead_Works() + { + var bfast = new BFast(); + var b = new BFast(); + b.SetArray("B", new int[3] { 0, 1, 2 }); + bfast.SetBFast("A", b, deflate: true); + var mem = bfast.ToMemoryStream(); + + var read = new BFast(mem); + + var result = read.GetBFast("A", inflate: true); + var b2 = result.GetArray("B"); + Assert.That(result.Entries.Count(), Is.EqualTo(1)); + Assert.That(b2, Is.EqualTo(new int[3] { 0, 1, 2 })); + } + [Test] public void SetBFast_Then_SetBFast_Replaces() { @@ -537,22 +570,22 @@ public void Write_Then_Read_NestedBFast_WithArray() public void Write_Then_Read_Mixed_Sources() { var basic = new BFast(); + var dummy = new MemoryStream(); basic.SetArray("ints", new int[1] { 1 }); basic.SetArray("floats", new float[1] { 2.0f }); - basic.Write(ResultPath); + basic.Write(dummy); - using (var stream = File.OpenRead(ResultPath)) + using (var residence = File.OpenRead(ResidencePath)) { - using (var residence = File.OpenRead(ResidencePath)) - { - var input = new BFast(stream); - var inputResidence = new BFast(residence); - var output = new BFast(); - - output.SetBFast("input", input); - output.SetBFast("residence", inputResidence); - output.Write(ResultPath2); - } + dummy.Seek(0, SeekOrigin.Begin); + var input = new BFast(dummy); + + var inputResidence = new BFast(residence); + var output = new BFast(); + + output.SetBFast("input", input); + output.SetBFast("residence", inputResidence); + output.Write(ResultPath2); } using (var stream = File.OpenRead(ResultPath2)) diff --git a/src/cs/bfast/Vim.BFast/BFast/BFast.cs b/src/cs/bfast/Vim.BFast/BFast/BFast.cs index 3a38c4b5..07cec61d 100644 --- a/src/cs/bfast/Vim.BFast/BFast/BFast.cs +++ b/src/cs/bfast/Vim.BFast/BFast/BFast.cs @@ -11,7 +11,7 @@ public class BFast : IBFastNode { private readonly Dictionary _children = new Dictionary(); public IEnumerable Entries => _children.Keys; - private IEnumerable<(string, IWritable)> Writables => _children.Select(kvp => (kvp.Key, kvp.Value as IWritable)); + private IEnumerable<(string name, IWritable buffer)> Writables => _children.Select(kvp => (kvp.Key, kvp.Value as IWritable)); public BFast() { } public BFast(Stream stream) @@ -37,7 +37,7 @@ public void SetBFast(string name, BFast bfast, bool deflate = false) } else { - var a = Deflate(bfast); + var a = Deflate2(bfast); SetArray(name, a); } } @@ -54,6 +54,22 @@ private byte[] Deflate(BFast bfast) } } + private byte[] Deflate2(BFast bfast) + { + using (var input = new MemoryStream()) + using (var output = new MemoryStream()) + { + bfast.Write(input); + input.Seek(0, SeekOrigin.Begin); + using (var decompress = new DeflateStream(output, CompressionMode.Compress, true)) + { + input.CopyTo(decompress); + } + // This need to happen after the deflate stream is disposed. + return output.ToArray(); + } + } + public void SetEnumerable(string name, Func> enumerable) where T : unmanaged { if (enumerable == null) @@ -130,11 +146,13 @@ public IBFastNode GetNode(string name) public void Remove(string name) => _children.Remove(name); - public long GetSize() => GetBFastSize(Writables); - public void Write(Stream stream) { - WriteBFast(stream, Writables); + var list = Writables.ToList(); + var strings = list.Select(n => n.name).ToArray(); + var buffers = list.Select(n => n.buffer).ToArray(); + var writer = new BFastWriter(strings, buffers); + writer.Write(stream); } public void Write(string path) @@ -177,58 +195,16 @@ public IEnumerable AsEnumerable() where T : unmanaged private static IEnumerable<(string name, BFastNode value)> GetBFastNodes(Stream stream) { var offset = stream.Position; - var header = BFastReader.ReadHeader(stream); - for (var i = 1; i < header.Preamble.NumArrays; i++) + var raw = BFastHeader.FromStream(stream); + foreach(var kvp in raw.Ranges) { var node = new BFastNode( stream, - header.Ranges[i].OffsetBy(offset) + kvp.Value.OffsetBy(offset) ); - yield return (header.Names[i - 1], node); - } - } - - private static void WriteBFast(Stream stream, IEnumerable<(string name, IWritable value)> writables) - { - var values = writables.Select(w => w.value).ToArray(); - var sizes = values.Select(v => v.GetSize()).ToArray(); - var names = writables.Select(w => w.name).ToArray(); - - long onBuffer(Stream writingStream, int bufferIdx, string bufferName, long bytesToWrite) - { - values[bufferIdx].Write(writingStream); - return bytesToWrite; + yield return (kvp.Key, node); } - - BFastWriter.Write(stream, names, sizes, onBuffer); - } - - private static long GetBFastSize(IEnumerable<(string name, IWritable value)> writables) - { - var values = writables.Select(w => w.value).ToArray(); - var sizes = values.Select(v => v.GetSize()).ToArray(); - var names = writables.Select(w => w.name).ToArray(); - - var header = BFastWriter.CreateHeader(sizes, names); - return header.Preamble.DataEnd; - } - } - - public static class BFastNextExtensions - { - public static T ReadBFast(this string path, Func process) - { - using (var file = new FileStream(path, FileMode.Open)) - { - var bfast = new BFast(file); - return process(bfast); - } - } - - public static IEnumerable ToNamedBuffers(this BFast bfast) - { - return bfast.Entries.Select(name => bfast.GetArray(name).ToNamedBuffer(name)); } } } diff --git a/src/cs/bfast/Vim.BFast/BFast/BFastEnumerableNode.cs b/src/cs/bfast/Vim.BFast/BFast/BFastEnumerableNode.cs index ff7162dd..418f1d50 100644 --- a/src/cs/bfast/Vim.BFast/BFast/BFastEnumerableNode.cs +++ b/src/cs/bfast/Vim.BFast/BFast/BFastEnumerableNode.cs @@ -79,7 +79,6 @@ private unsafe int ReadArray(MemoryStream stream, T[] array) where T : unmana return count; } - public unsafe long GetSize() => _source().Count() * sizeof(TNode); public void Write(Stream stream) { //TODO: Use bigger chunks diff --git a/src/cs/bfast/Vim.BFast/BFast/BFastNextExtensions.cs b/src/cs/bfast/Vim.BFast/BFast/BFastNextExtensions.cs new file mode 100644 index 00000000..f8bcbe29 --- /dev/null +++ b/src/cs/bfast/Vim.BFast/BFast/BFastNextExtensions.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; + +namespace Vim.BFastNS +{ + public static class BFastNextExtensions + { + public static T ReadBFast(this string path, Func process) + { + using (var file = new FileStream(path, FileMode.Open)) + { + var bfast = new BFast(file); + return process(bfast); + } + } + + public static IEnumerable ToNamedBuffers(this BFast bfast) + { + return bfast.Entries.Select(name => bfast.GetArray(name).ToNamedBuffer(name)); + } + + public static MemoryStream ToMemoryStream(this BFast bfast) + { + var stream = new MemoryStream(); + bfast.Write(stream); + stream.Seek(0, SeekOrigin.Begin); + return stream; + } + } +} + diff --git a/src/cs/bfast/Vim.BFast/BFast/BFastNode.cs b/src/cs/bfast/Vim.BFast/BFast/BFastNode.cs index 19d1d747..deb6f4e1 100644 --- a/src/cs/bfast/Vim.BFast/BFast/BFastNode.cs +++ b/src/cs/bfast/Vim.BFast/BFast/BFastNode.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.IO; using Vim.BFastNS.Core; @@ -57,12 +56,6 @@ public T[] AsArray() where T : unmanaged public IEnumerable AsEnumerable() where T : unmanaged => AsArray(); - - public long GetSize() - { - return _range.Count; - } - public void Write(Stream stream) { _stream.Seek(_range.Begin, SeekOrigin.Begin); diff --git a/src/cs/bfast/Vim.BFast/BFast/IBFastNode.cs b/src/cs/bfast/Vim.BFast/BFast/IBFastNode.cs index c5412f79..e10aadd6 100644 --- a/src/cs/bfast/Vim.BFast/BFast/IBFastNode.cs +++ b/src/cs/bfast/Vim.BFast/BFast/IBFastNode.cs @@ -1,6 +1,4 @@ -using System; -using System.Collections; -using System.Collections.Generic; +using System.Collections.Generic; using System.IO; namespace Vim.BFastNS @@ -10,7 +8,6 @@ namespace Vim.BFastNS /// public interface IWritable { - long GetSize(); void Write(Stream stream); } diff --git a/src/cs/bfast/Vim.BFast/Buffers/UnsafeHelpers.cs b/src/cs/bfast/Vim.BFast/Buffers/UnsafeHelpers.cs index c14765fd..527a82f3 100644 --- a/src/cs/bfast/Vim.BFast/Buffers/UnsafeHelpers.cs +++ b/src/cs/bfast/Vim.BFast/Buffers/UnsafeHelpers.cs @@ -53,6 +53,16 @@ public static unsafe void WriteBytesBuffered(this Stream stream, byte* src, long public static unsafe void Read(this Stream stream, T* dest) where T : unmanaged => stream.ReadBytesBuffered((byte*)dest, sizeof(T)); + /// + /// Helper for reading arbitrary unmanaged types from a Stream. + /// + public static unsafe T Read(this Stream stream) where T : unmanaged + { + T r; + stream.ReadBytesBuffered((byte*)&r, sizeof(T)); + return r; + } + /// /// Helper for reading arrays of arbitrary unmanaged types from a Stream, that might be over 2GB of size. /// That said, in C#, you can never load more int.MaxValue numbers of items. diff --git a/src/cs/bfast/Vim.BFast/Core/BFastAlignment.cs b/src/cs/bfast/Vim.BFast/Core/BFastAlignment.cs deleted file mode 100644 index c70555e9..00000000 --- a/src/cs/bfast/Vim.BFast/Core/BFastAlignment.cs +++ /dev/null @@ -1,49 +0,0 @@ -using System; -using System.IO; - -namespace Vim.BFastNS.Core -{ - internal class BFastAlignment - { - /// - /// Computes the padding requires after the array of BFastRanges are written out. - /// - /// - /// - public static long ComputePadding(BFastRange[] ranges) - => ComputePadding(BFastPreamble.Size + ranges.Length * BFastRange.Size); - - /// - /// Given a position in the stream, computes how much padding is required to bring the value to an aligned point. - /// - public static long ComputePadding(long n) - => ComputeNext(n) - n; - - /// - /// Given a position in the stream, tells us where the the next aligned position will be, if it the current position is not aligned. - /// - public static long ComputeNext(long n) - => IsAligned(n) ? n : n + BFastConstants.ALIGNMENT - (n % BFastConstants.ALIGNMENT); - - /// - /// Checks that the stream (if seekable) is well aligned - /// - public static void Check(Stream stream) - { - if (!stream.CanSeek) - return; - // TODO: Check with CD: Should we bail out here? This means that any - // alignment checks for a currently-writing stream are effectively ignored. - if (stream.Position == stream.Length) - return; - if (!IsAligned(stream.Position)) - throw new Exception($"Stream position {stream.Position} is not well aligned"); - } - - /// - /// Given a position in the stream, tells us whether the position is aligned. - /// - public static bool IsAligned(long n) - => n % BFastConstants.ALIGNMENT == 0; - } -} diff --git a/src/cs/bfast/Vim.BFast/Core/BFastConstants.cs b/src/cs/bfast/Vim.BFast/Core/BFastConstants.cs index 4b0524c5..60857658 100644 --- a/src/cs/bfast/Vim.BFast/Core/BFastConstants.cs +++ b/src/cs/bfast/Vim.BFast/Core/BFastConstants.cs @@ -11,10 +11,5 @@ public static class BFastConstants public const long SameEndian = Magic; public const long SwappedEndian = 0xA5BFL << 48; - /// - /// Data arrays are aligned to 64 bytes, so that they can be cast directly to AVX-512 registers. - /// This is useful for efficiently working with floating point data. - /// - public const long ALIGNMENT = 64; } } diff --git a/src/cs/bfast/Vim.BFast/Core/BFastHeader.cs b/src/cs/bfast/Vim.BFast/Core/BFastHeader.cs index 06cac970..6719c521 100644 --- a/src/cs/bfast/Vim.BFast/Core/BFastHeader.cs +++ b/src/cs/bfast/Vim.BFast/Core/BFastHeader.cs @@ -1,66 +1,56 @@ using System; +using System.Collections.Generic; using System.IO; using System.Linq; namespace Vim.BFastNS.Core { - /// - /// This contains the BFAST data loaded or written from disk. - /// public class BFastHeader { - public BFastPreamble Preamble = new BFastPreamble(); - public BFastRange[] Ranges; - public string[] Names; + public readonly BFastPreamble Preamble = new BFastPreamble(); + public readonly Dictionary Ranges; - public override bool Equals(object o) - => o is BFastHeader other && Equals(other); - - public bool Equals(BFastHeader other) - => Preamble.Equals(other.Preamble) && - Ranges.Length == other.Ranges.Length && - Ranges.Zip(other.Ranges, (x, y) => x.Equals(y)).All(x => x) && - Names.Zip(other.Names, (x, y) => x.Equals(y)).All(x => x); + public BFastHeader(BFastPreamble preamble, Dictionary ranges) + { + Preamble = preamble; + Ranges = ranges; + } /// - /// Checks that the header values are sensible, and throws an exception otherwise. + /// Reads the preamble, the ranges, and the names of the rest of the buffers. /// - public BFastHeader Validate() + public static BFastHeader FromStream(Stream stream) { - var preamble = Preamble.Validate(); - var ranges = Ranges; - var names = Names; + if (stream.Length - stream.Position < sizeof(long) * 4) + throw new Exception("Stream too short"); - if (preamble.RangesEnd > preamble.DataStart) - throw new Exception($"Computed arrays ranges end must be less than the start of data {preamble.DataStart}"); + var preamble = stream.Read(); - if (ranges == null) - throw new Exception("Ranges must not be null"); + var ranges = stream.ReadArray((int)preamble.NumArrays); - var min = preamble.DataStart; - var max = preamble.DataEnd; + var nameBytes = stream.ReadArray((int)ranges[0].Count); + var names = BFastStrings.Unpack(nameBytes); + var map = names + .Zip(ranges.Skip(1), (n, r) => (n, r)) + .ToDictionary(p => p.n, p => p.r); - for (var i = 0; i < ranges.Length; ++i) + return new BFastHeader(preamble, map).Validate(); + } + + public BFastHeader Validate() + { + Preamble.Validate(); + foreach (var range in Ranges.Values) { - var begin = ranges[i].Begin; - if (!BFastAlignment.IsAligned(begin)) - throw new Exception($"The beginning of the range is not well aligned {begin}"); - var end = ranges[i].End; - if (begin < min || begin > max) - throw new Exception($"Array offset begin {begin} is not in valid span of {min} to {max}"); - if (i > 0) + if (range.Begin < Preamble.DataStart) { - if (begin < ranges[i - 1].End) - throw new Exception($"Array offset begin {begin} is overlapping with previous array {ranges[i - 1].End}"); + throw new Exception("range.Begin must be larger than Data Start"); + } + if (range.End > Preamble.DataEnd) + { + throw new Exception("range.End must be smaller than Data End"); } - - if (end < begin || end > max) - throw new Exception($"Array offset end {end} is not in valid span of {begin} to {max}"); } - - if (names.Length < ranges.Length - 1) - throw new Exception($"Number of buffer names {names.Length} is not one less than the number of ranges {ranges.Length}"); - return this; } } diff --git a/src/cs/bfast/Vim.BFast/Core/BFastPreamble.cs b/src/cs/bfast/Vim.BFast/Core/BFastPreamble.cs index 28c78a30..f0d7b0ff 100644 --- a/src/cs/bfast/Vim.BFast/Core/BFastPreamble.cs +++ b/src/cs/bfast/Vim.BFast/Core/BFastPreamble.cs @@ -14,13 +14,6 @@ public struct BFastPreamble [FieldOffset(16)] public long DataEnd; // >= DataStart and <= file size [FieldOffset(24)] public long NumArrays; // number of arrays - /// - /// This is where the array ranges are finished. - /// Must be less than or equal to DataStart. - /// Must be greater than or equal to FileHeader.ByteCount - /// - public long RangesEnd => Size + NumArrays * 16; - /// /// The size of the FileHeader structure /// @@ -52,20 +45,24 @@ public BFastPreamble Validate() if (DataStart > DataEnd) throw new Exception($"Data start {DataStart} cannot be after the data end {DataEnd}"); - if (!BFastAlignment.IsAligned(DataEnd)) - throw new Exception($"Data end {DataEnd} should be aligned"); - if (NumArrays < 0) - throw new Exception($"Number of arrays {NumArrays} is not a positive number"); + throw new Exception($"Number of arrays {NumArrays} should be at least one"); if (NumArrays > DataEnd) throw new Exception($"Number of arrays {NumArrays} can't be more than the total size"); - if (RangesEnd > DataStart) - throw new Exception($"End of range {RangesEnd} can't be after data-start {DataStart}"); - return this; } - }; + public override int GetHashCode() + { + var hashCode = 275654494; + hashCode = hashCode * -1521134295 + Magic.GetHashCode(); + hashCode = hashCode * -1521134295 + DataStart.GetHashCode(); + hashCode = hashCode * -1521134295 + DataEnd.GetHashCode(); + hashCode = hashCode * -1521134295 + NumArrays.GetHashCode(); + hashCode = hashCode * -1521134295 + SameEndian.GetHashCode(); + return hashCode; + } + } } diff --git a/src/cs/bfast/Vim.BFast/Core/BFastReader.cs b/src/cs/bfast/Vim.BFast/Core/BFastReader.cs deleted file mode 100644 index d22bf3f0..00000000 --- a/src/cs/bfast/Vim.BFast/Core/BFastReader.cs +++ /dev/null @@ -1,43 +0,0 @@ -using System; -using System.IO; - -namespace Vim.BFastNS.Core -{ - public static class BFastReader - { - /// - /// Reads the preamble, the ranges, and the names of the rest of the buffers. - /// - public static BFastHeader ReadHeader(Stream stream) - { - var r = new BFastHeader(); - var br = new BinaryReader(stream); - - if (stream.Length - stream.Position < sizeof(long) * 4) - throw new Exception("Stream too short"); - - r.Preamble = new BFastPreamble - { - Magic = br.ReadInt64(), - DataStart = br.ReadInt64(), - DataEnd = br.ReadInt64(), - NumArrays = br.ReadInt64(), - }.Validate(); - - r.Ranges = stream.ReadArray((int)r.Preamble.NumArrays); - - var padding = BFastAlignment.ComputePadding(r.Ranges); - br.ReadBytes((int)padding); - BFastAlignment.Check(br.BaseStream); - - var nameBytes = br.ReadBytes((int)r.Ranges[0].Count); - r.Names = BFastStrings.Unpack(nameBytes); - - padding = BFastAlignment.ComputePadding(r.Ranges[0].End); - br.ReadBytes((int)padding); - BFastAlignment.Check(br.BaseStream); - - return r.Validate(); - } - } -} diff --git a/src/cs/bfast/Vim.BFast/Core/BFastSection.cs b/src/cs/bfast/Vim.BFast/Core/BFastSection.cs new file mode 100644 index 00000000..0e8c6061 --- /dev/null +++ b/src/cs/bfast/Vim.BFast/Core/BFastSection.cs @@ -0,0 +1,107 @@ +using System; +using System.Diagnostics; +using System.IO; + +namespace Vim.BFastNS.Core +{ + /// + /// Represents a section of the bfast that will be written to at some point. + /// + public class BFastSection + { + public readonly long Origin; + public readonly long LocalStart; + public readonly long Length; + public long AbsoluteStart => LocalStart + Origin; + + public long AbsoluteEnd => AbsoluteStart + Length; + public long LocalEnd => LocalStart + Length; + + + + public long End => AbsoluteStart + Length; + public BFastRange LocalRange => new BFastRange() + { + Begin = LocalStart, + End = LocalEnd + }; + + public BFastSection(long start, long length, long origin = 0) + { + LocalStart = start; + Length = length; + Origin = origin; + } + + /// + /// Returns a new range offset by given amount. + /// + public BFastSection Offset(long offset) + { + return new BFastSection(AbsoluteStart, Length, offset); + } + + /// + /// Returns an equivalent section but with given origin. + /// + public BFastSection Rebase(long origin) + { + return new BFastSection(LocalStart - origin, Length, origin); + } + + /// + /// Returns a new range Starting where this one ends. + /// + /// Byte length of the section + public BFastSection Next(long length) + { + return new BFastSection(LocalEnd, length, Origin); + } + + /// + /// Writes 0 bytes over the whole section. + /// + public void Clear(Stream stream) + { + stream.Seek(AbsoluteStart, SeekOrigin.Begin); + for (var i = 0; i < Length; i++) + { + stream.WriteByte(0); + } + } + + /// + /// Writes given bytes in the section. Throws if bytes don't match section length. + /// + public void Write(Stream stream, byte[] bytes) + { + if (bytes.Length != Length) + throw new Exception("Data length not matching section length"); + + stream.Seek(AbsoluteStart, SeekOrigin.Begin); + stream.Write(bytes); + } + + /// + /// Writes given value in the section. Throws if value don't match section length. + /// + unsafe public void Write(Stream stream, T value) where T : unmanaged + { + Debug.Assert(sizeof(T) == Length); + stream.Seek(AbsoluteStart, SeekOrigin.Begin); + stream.WriteValue(value); + } + + /// + /// Writes given buffer and returns resulting section. + /// + public static BFastSection Write(Stream stream, IWritable buffer) + { + var start = stream.Position; + buffer.Write(stream); + return new BFastSection(start, stream.Position - start); + } + } + +} + diff --git a/src/cs/bfast/Vim.BFast/Core/BFastWriter.cs b/src/cs/bfast/Vim.BFast/Core/BFastWriter.cs index 5596070d..9e4e0a73 100644 --- a/src/cs/bfast/Vim.BFast/Core/BFastWriter.cs +++ b/src/cs/bfast/Vim.BFast/Core/BFastWriter.cs @@ -1,167 +1,101 @@ -using System; -using System.Diagnostics; -using System.IO; -using System.Linq; +using System.IO; namespace Vim.BFastNS.Core { - public static class BFastWriter + /// + /// Provide methods to write a buffer collection to a stream. + /// + public class BFastWriter { - /// - /// Callback function allows clients to control writing the data to the output stream - /// - public delegate long BFastWriterFn(Stream writingStream, int bufferIdx, string bufferName, long bytesToWrite); - - /// - /// Enables a user to write a BFAST from an array of names, sizes, and a custom writing function. - /// The function will receive a BinaryWriter, the index of the buffer, and is expected to return the number of bytes written. - /// Simplifies the process of creating custom BinaryWriters, or writing extremely large arrays if necessary. - /// - public static void Write(Stream stream, string[] bufferNames, long[] bufferSizes, BFastWriterFn onBuffer) - { - if (bufferSizes.Any(sz => sz < 0)) - throw new Exception("All buffer sizes must be zero or greater than zero"); - - if (bufferNames.Length != bufferSizes.Length) - throw new Exception($"The number of buffer names {bufferNames.Length} is not equal to the number of buffer sizes {bufferSizes}"); + private readonly string[] _bufferNames; + private readonly IWritable[] _buffers; + private readonly byte[] _packedNames; - var header = CreateHeader(bufferSizes, bufferNames); - Write(stream, header, bufferNames, bufferSizes, onBuffer); - } + private readonly BFastSection _preamble; + private readonly BFastSection _ranges; + private readonly BFastSection _names; - /// - /// Enables a user to write a BFAST from an array of names, sizes, and a custom writing function. - /// This is useful when the header is already computed. - /// - public static void Write(Stream stream, BFastHeader header, string[] bufferNames, long[] bufferSizes, BFastWriterFn onBuffer) - { - WriteHeader(stream, header); - BFastAlignment.Check(stream); - WriteBody(stream, bufferNames, bufferSizes, onBuffer); - } + public long Start => _preamble.AbsoluteStart; - /// - /// Must be called after "WriteBFastHeader" - /// Enables a user to write the contents of a BFAST from an array of names, sizes, and a custom writing function. - /// The function will receive a BinaryWriter, the index of the buffer, and is expected to return the number of bytes written. - /// Simplifies the process of creating custom BinaryWriters, or writing extremely large arrays if necessary. - /// - public static void WriteBody(Stream stream, string[] bufferNames, long[] bufferSizes, BFastWriterFn onBuffer) + public BFastWriter(string[] names, IWritable[] buffers, long offset = 0) { - BFastAlignment.Check(stream); - - if (bufferSizes.Any(sz => sz < 0)) - throw new Exception("All buffer sizes must be zero or greater than zero"); - - if (bufferNames.Length != bufferSizes.Length) - throw new Exception($"The number of buffer names {bufferNames.Length} is not equal to the number of buffer sizes {bufferSizes}"); - - // Then passes the binary writer for each buffer: checking that the correct amount of data was written. - for (var i = 0; i < bufferNames.Length; ++i) + if(names.Length != buffers.Length) { - BFastAlignment.Check(stream); - var nBytes = bufferSizes[i]; - var pos = stream.CanSeek ? stream.Position : 0; - var nWrittenBytes = onBuffer(stream, i, bufferNames[i], nBytes); - if (stream.CanSeek) - { - if (stream.Position - pos != nWrittenBytes) - throw new NotImplementedException($"Buffer:{bufferNames[i]}. Stream movement {stream.Position - pos} does not reflect number of bytes claimed to be written {nWrittenBytes}"); - } - - if (nBytes != nWrittenBytes) - throw new Exception($"Number of bytes written {nWrittenBytes} not equal to expected bytes{nBytes}"); - var padding = BFastAlignment.ComputePadding(nBytes); - for (var j = 0; j < padding; ++j) - stream.WriteByte(0); - BFastAlignment.Check(stream); + throw new System.Exception("Names and buffer length must match"); } + + _bufferNames = names; + _buffers = buffers; + _packedNames = BFastStrings.Pack(names); + + _preamble = new BFastSection(0, 32).Offset(offset); + _ranges = _preamble.Next((buffers.Length + 1) * 16); + _names = _ranges.Next(_packedNames.Length); } /// - /// Creates a BFAST structure, without any actual data buffers, from a list of sizes of buffers (not counting the name buffer). - /// Used as an intermediate step to create a BFAST. + /// Writes to given stream, which may or may not be at Position 0. /// - public static BFastHeader CreateHeader(long[] bufferSizes, string[] bufferNames) + public unsafe void Write(Stream stream) { - if (bufferNames.Length != bufferSizes.Length) - throw new Exception($"The number of buffer sizes {bufferSizes.Length} is not equal to the number of buffer names {bufferNames.Length}"); - - var header = new BFastHeader + var offset = stream.Position; + if (Start != stream.Position) { - Names = bufferNames - }; - header.Preamble.Magic = BFastConstants.Magic; - header.Preamble.NumArrays = bufferSizes.Length + 1; + // Offset sections if stream not at 0 + Offset(stream.Position).Write(stream); + return; + } - // Allocate the data for the ranges - header.Ranges = new BFastRange[header.Preamble.NumArrays]; - header.Preamble.DataStart = BFastAlignment.ComputeNext(header.Preamble.RangesEnd); + // Leave space for preamble + _preamble.Clear(stream); - var nameBufferLength = BFastStrings.Pack(bufferNames).LongLength; - var sizes = (new[] { nameBufferLength }).Concat(bufferSizes).ToArray(); + // Leave space for ranges and write Names range. + _ranges.Clear(stream); + WriteRange(stream, _ranges.AbsoluteStart, 0, _names.LocalRange); - // Compute the offsets for the data buffers - var curIndex = header.Preamble.DataStart; - var i = 0; - foreach (var size in sizes) - { - curIndex = BFastAlignment.ComputeNext(curIndex); - Debug.Assert(BFastAlignment.IsAligned(curIndex)); + // Write Names + _names.Write(stream, _packedNames); - header.Ranges[i].Begin = curIndex; - curIndex += size; - - header.Ranges[i].End = curIndex; - i++; + // Write each buffer and go back to write its Range. + var dataPointer = _names.End; + for (var i = 0; i < _buffers.Length; i++) + { + var section = WriteBuffer(stream, dataPointer, _buffers[i]).Rebase(offset); + WriteRange(stream, _ranges.AbsoluteStart, i + 1, section.LocalRange); + dataPointer = section.End; } - // Finish with the header - // Each buffer we contain is padded to ensure the next one - // starts on alignment, so we pad our DataEnd to reflect this reality - header.Preamble.DataEnd = BFastAlignment.ComputeNext(curIndex); + // Finally go back to write the preamble. + var preamble = new BFastPreamble() + { + Magic = BFastConstants.Magic, + NumArrays = _buffers.Length + 1, + DataStart = _ranges.End - offset, + DataEnd = dataPointer - offset, + }; + _preamble.Write(stream, preamble); - // Check that everything adds up - return header.Validate(); + // Move pointer back to end as the caller would expect + stream.Seek(dataPointer, SeekOrigin.Begin); } - - /// - /// Writes the BFAST header and name buffer to stream using the provided BinaryWriter. The BinaryWriter will be properly aligned by padding zeros - /// - public static BinaryWriter WriteHeader(Stream stream, BFastHeader header) + private BFastWriter Offset(long offset) { - if (header.Ranges.Length != header.Names.Length + 1) - throw new Exception($"The number of ranges {header.Ranges.Length} must be equal to one more than the number of names {header.Names.Length}"); - var bw = new BinaryWriter(stream); - bw.Write(header.Preamble.Magic); - bw.Write(header.Preamble.DataStart); - bw.Write(header.Preamble.DataEnd); - bw.Write(header.Preamble.NumArrays); - foreach (var r in header.Ranges) - { - bw.Write(r.Begin); - bw.Write(r.End); - } - WriteZeroBytes(bw, BFastAlignment.ComputePadding(header.Ranges)); - - BFastAlignment.Check(stream); - var nameBuffer = BFastStrings.Pack(header.Names); - bw.Write(nameBuffer); - WriteZeroBytes(bw, BFastAlignment.ComputePadding(nameBuffer.LongLength)); - - BFastAlignment.Check(stream); - return bw; + return new BFastWriter(_bufferNames, _buffers, offset); } - /// - /// Writes n zero bytes. - /// - public static void WriteZeroBytes(BinaryWriter bw, long n) + private void WriteRange(Stream stream, long start, int index, BFastRange range) { - for (var i = 0L; i < n; ++i) - bw.Write((byte)0); + stream.Seek(start + index * 16, SeekOrigin.Begin); + stream.WriteValue(range); } + private BFastSection WriteBuffer(Stream stream, long start, IWritable buffer) + { + stream.Seek(start, SeekOrigin.Begin); + return BFastSection.Write(stream, buffer); + + } } } + From 0a64944ec256d694800d6b860c77485d9e3bd913 Mon Sep 17 00:00:00 2001 From: simon Date: Mon, 12 Feb 2024 13:36:07 -0500 Subject: [PATCH 061/111] BFast update --- src/cs/bfast/Vim.BFast.Tests/BFastTests.cs | 445 ++++++++---------- src/cs/bfast/Vim.BFast/BFast/BFast.cs | 153 +++--- .../bfast/Vim.BFast/BFast/BFastArrayNode.cs | 45 ++ .../Vim.BFast/BFast/BFastEnumerableNode.cs | 72 +-- .../Vim.BFast/BFast/BFastNextExtensions.cs | 15 +- src/cs/bfast/Vim.BFast/BFast/BFastNode.cs | 77 --- .../bfast/Vim.BFast/BFast/BFastStreamNode.cs | 60 +++ .../bfast/Vim.BFast/BFast/CompressibleNode.cs | 57 +++ .../Vim.BFast/Buffers/MemStreamHelpers.cs | 38 ++ .../bfast/Vim.BFast/Buffers/UnsafeConvert.cs | 92 ++++ .../bfast/Vim.BFast/Buffers/UnsafeHelpers.cs | 157 ------ src/cs/bfast/Vim.BFast/Buffers/UnsafeRead.cs | 94 ++++ src/cs/bfast/Vim.BFast/Buffers/UnsafeWrite.cs | 55 +++ src/cs/bfast/Vim.BFast/Core/BFastHeader.cs | 2 +- src/cs/g3d/Vim.G3dNext/G3dVim.cs | 2 +- src/cs/vim/Vim.Format.Vimx/Vimx.cs | 7 +- 16 files changed, 725 insertions(+), 646 deletions(-) create mode 100644 src/cs/bfast/Vim.BFast/BFast/BFastArrayNode.cs delete mode 100644 src/cs/bfast/Vim.BFast/BFast/BFastNode.cs create mode 100644 src/cs/bfast/Vim.BFast/BFast/BFastStreamNode.cs create mode 100644 src/cs/bfast/Vim.BFast/BFast/CompressibleNode.cs create mode 100644 src/cs/bfast/Vim.BFast/Buffers/MemStreamHelpers.cs create mode 100644 src/cs/bfast/Vim.BFast/Buffers/UnsafeConvert.cs delete mode 100644 src/cs/bfast/Vim.BFast/Buffers/UnsafeHelpers.cs create mode 100644 src/cs/bfast/Vim.BFast/Buffers/UnsafeRead.cs create mode 100644 src/cs/bfast/Vim.BFast/Buffers/UnsafeWrite.cs diff --git a/src/cs/bfast/Vim.BFast.Tests/BFastTests.cs b/src/cs/bfast/Vim.BFast.Tests/BFastTests.cs index fcab5218..649e1b6e 100644 --- a/src/cs/bfast/Vim.BFast.Tests/BFastTests.cs +++ b/src/cs/bfast/Vim.BFast.Tests/BFastTests.cs @@ -1,4 +1,6 @@ using NUnit.Framework; +using NUnit.Framework.Constraints; +using System.Data; using Vim.BFastNS.Core; using Vim.Util.Tests; @@ -10,9 +12,13 @@ public class BFastTests public static string ResultPath2 = Path.Combine(VimFormatRepoPaths.OutDir, "input.bfast"); public static string ResidencePath = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); + BFast bfast; + [SetUp] public void Setup() { + bfast = new BFast(); + if (!Directory.Exists(VimFormatRepoPaths.OutDir)) { Directory.CreateDirectory(VimFormatRepoPaths.OutDir); @@ -27,6 +33,49 @@ public void Setup() } } + private void TestBeforeAfter(Action method) + { + method(bfast); + + // Test that it also works after write/read + var next = new BFast(bfast.ToMemoryStream()); + method(next); + } + + private void TestBeforeAfter(Func method, IResolveConstraint constraint) + { + Assert.That(method(bfast), constraint); + + // Test that it also works after write/read + var next = new BFast(bfast.ToMemoryStream()); + Assert.That(method(next), constraint); + } + + private void TestBeforeAfter(Action method, IResolveConstraint constraint) + { + Assert.That(method, constraint); + + // Test that it also works after write/read + var next = new BFast(bfast.ToMemoryStream()); + Assert.That(method, constraint); + } + + private void TestBeforeAfterFile(Func method, IResolveConstraint constraint) + { + Assert.That(method(bfast), constraint); + using (var file = File.Open(ResultPath, FileMode.CreateNew)) + { + bfast.Write(file); + file.Seek(0, SeekOrigin.Begin); + + // Test that it also works after write/read + var next = new BFast(file); + Assert.That(method(next), constraint); + } + } + + #region empty + [Test] public void EmptyBFast_Has_No_Entries() { @@ -38,7 +87,7 @@ public void EmptyBFast_Has_No_Entries() public void EmptyBFast_GetArray_Returns_Null() { var bfast = new BFast(); - Assert.IsNull(bfast.GetArray("missing")); + Assert.IsNull(bfast.GetArray("missing")); } [Test] @@ -48,6 +97,13 @@ public void EmptyBFast_GetBfast_Returns_Null() Assert.IsNull(bfast.GetBFast("missing")); } + [Test] + public void EmptyBFast_GetEnumerable_Returns_Null() + { + var bfast = new BFast(); + Assert.IsNull(bfast.GetEnumerable("missing")); + } + [Test] public void EmptyBFast_Remove_Does_Nothing() { @@ -68,230 +124,202 @@ public void EmptyBFast_Writes_Header() Assert.That(raw.Ranges.Count, Is.EqualTo(0)); } + #endregion + + #region enumerable [Test] public void SetEnumerable_Adds_Entry() { - var bfast = new BFast(); bfast.SetEnumerable("A", () => new int[3] { 0, 1, 2 }); - Assert.That(bfast.Entries.Count(), Is.EqualTo(1)); + TestBeforeAfter(b => b.Entries.Count(), Is.EqualTo(1)); } - [Test] - public void SetEnumerable_Then_GetArray() + public void SetEnumerable_Then_GetEnumerable() { - var bfast = new BFast(); - bfast.SetEnumerable("A", () => new int[3] { 0, 1, 2 }); - var result = bfast.GetArray("A"); - - Assert.That(result, Is.EqualTo(new int[3] { 0, 1, 2 })); + var expected = new int[3] { 0, 1, 2 }; + bfast.SetEnumerable("A", () => expected); + TestBeforeAfter(b => b.GetEnumerable("A"), Is.EqualTo(expected)); } [Test] - public void SetEnumerable_Then_GetArray_Bytes() + public void SetEnumerable_Then_GetEnumerable_Bytes() { - var bfast = new BFast(); bfast.SetEnumerable("A", () => new int[3] { 0, 1, 2 }); - var result = bfast.GetArray("A"); - - var bytes = (new int[3] { 0, 1, 2 }).SelectMany(i => BitConverter.GetBytes(i)); - Assert.That(result, Is.EqualTo(bytes)); + var expected = (new int[3] { 0, 1, 2 }).SelectMany(i => BitConverter.GetBytes(i)); + TestBeforeAfter(b => b.GetEnumerable("A"), Is.EqualTo(expected)); } - [Test] - public void SetEnumerable_Then_GetEnumerable_Bytes() + public void SetEnumerable_Then_GetEnumerable_Float() { - var bfast = new BFast(); bfast.SetEnumerable("A", () => new int[3] { 0, 1, 2 }); - var result = bfast.GetEnumerable("A"); - - var bytes = (new int[3] { 0, 1, 2 }).SelectMany(i => BitConverter.GetBytes(i)); - Assert.That(result, Is.EqualTo(bytes)); + var expected = (new int[3] { 0, 1, 2 }).Select(i => BitConverter.Int32BitsToSingle(i)); + TestBeforeAfter(b => b.GetEnumerable("A"), Is.EqualTo(expected)); } [Test] - public void SetEnumerable_Then_GetEnumerable_Float() + public void SetEnumerable_Then_GetArray() { - var bfast = new BFast(); bfast.SetEnumerable("A", () => new int[3] { 0, 1, 2 }); - var result = bfast.GetEnumerable("A"); - - var floats = (new int[3] { 0, 1, 2 }).Select(i => BitConverter.Int32BitsToSingle(i)); - Assert.That(result, Is.EqualTo(floats)); + var expected = new int[3] { 0, 1, 2 }; + TestBeforeAfter(b => b.GetArray("A"), Is.EqualTo(expected)); } [Test] - public void SetEnumerable_Then_GetArray_Float() + public void SetEnumerable_Then_GetArray_Bytes() { - var bfast = new BFast(); bfast.SetEnumerable("A", () => new int[3] { 0, 1, 2 }); - var result = bfast.GetArray("A"); - - var floats = (new int[3] { 0, 1, 2 }).Select(i => BitConverter.Int32BitsToSingle(i)); - Assert.That(result, Is.EqualTo(floats)); + var expected = (new int[3] { 0, 1, 2 }).SelectMany(i => BitConverter.GetBytes(i)); + TestBeforeAfter(b => b.GetArray("A"), Is.EqualTo(expected)); } - [Test] - public void SetEnumerable_Then_GetEnumerable() + public void SetEnumerable_Then_GetArray_Float() { - var bfast = new BFast(); bfast.SetEnumerable("A", () => new int[3] { 0, 1, 2 }); - var result = bfast.GetEnumerable("A").ToArray(); - Assert.That(result, Is.EqualTo(new int[3] { 0, 1, 2 })); + var expected = (new int[3] { 0, 1, 2 }).Select(i => BitConverter.Int32BitsToSingle(i)); + // MemoryStream can't handle such size. + TestBeforeAfter(b => b.GetArray("A"), Is.EqualTo(expected)); + } [Test] public void SetEnumerable_Then_GetBFast() { - var bfast = new BFast(); bfast.SetEnumerable("A", () => new int[3] { 0, 1, 2 }); - var result = bfast.GetBFast("A"); - Assert.That(result, Is.Null); + TestBeforeAfter(b => b.GetBFast("A"), Is.Null); } - IEnumerable GetLots() + [Test] + public void SetEnumerable_Then_GetBFast_ValidBytes() { - return Enumerable.Range(0, int.MaxValue).Concat(Enumerable.Range(0, 10)); + var sub = new BFast(); + bfast.SetBFast("A", sub); + var bytes = bfast.GetArray("A"); + bfast.SetEnumerable("A",() => bytes); + + TestBeforeAfter(b => b.GetBFast("A"), Is.EqualTo(sub)); } - [Test, Explicit] public void SetEnumerable_Then_GetEnumerable_Lots() { - var bfast = new BFast(); + IEnumerable GetLots() + { + return Enumerable.Range(0, int.MaxValue).Concat(Enumerable.Range(0, 10)); + } bfast.SetEnumerable("A", GetLots); - var result = bfast.GetEnumerable("A"); - Assert.That(result, Is.EqualTo(GetLots())); + TestBeforeAfterFile(b => b.GetEnumerable("A"), Is.EqualTo(GetLots())); } + #endregion + #region array [Test] public void SetArray_Adds_Entry() { - var bfast = new BFast(); bfast.SetArray("A", new int[3] { 0, 1, 2 }); - - Assert.That(bfast.Entries.Count(), Is.EqualTo(1)); + TestBeforeAfter(b => b.Entries.Count(), Is.EqualTo(1)); } [Test] public void SetArray_Then_GetArray() { - var bfast = new BFast(); - bfast.SetArray("A", new int[3] { 0, 1, 2 }); - var result = bfast.GetArray("A"); - - Assert.That(result, Is.EqualTo(new int[3] { 0, 1, 2 })); + var array = new int[3] { 0, 1, 2 }; + bfast.SetArray("A", array); + TestBeforeAfter(b => b.GetArray("A"), Is.EqualTo(array)); } [Test] public void SetArray_Then_GetArray_Bytes() { - var bfast = new BFast(); - bfast.SetArray("A", new int[3] { 0, 1, 2 }); - var result = bfast.GetArray("A"); + var array = new int[3] { 0, 1, 2 }; + var expected = array.SelectMany(i => BitConverter.GetBytes(i)); - var bytes = (new int[3] { 0, 1, 2 }).SelectMany(i => BitConverter.GetBytes(i)); - Assert.That(result, Is.EqualTo(bytes)); + bfast.SetArray("A", array); + TestBeforeAfter(b => bfast.GetArray("A"), Is.EqualTo(expected)); } [Test] public void SetArray_Then_GetArray_Float() { - var bfast = new BFast(); - bfast.SetArray("A", new int[3] { 0, 1, 2 }); - var result = bfast.GetArray("A"); - - var floats = (new int[3] { 0, 1, 2 }).Select(i => BitConverter.Int32BitsToSingle(i)); - Assert.That(result, Is.EqualTo(floats)); + var array = new int[3] { 0, 1, 2 }; + var expected = array.Select(i => BitConverter.Int32BitsToSingle(i)); + + bfast.SetArray("A", array); + TestBeforeAfter(b => bfast.GetArray("A"), Is.EqualTo(expected)); } [Test] public void SetArray_Then_GetEnumerable() { - var bfast = new BFast(); - bfast.SetArray("A", new int[3] { 0, 1, 2 }); - var result = bfast.GetEnumerable("A"); - - Assert.That(result, Is.EqualTo(new int[3] { 0, 1, 2 })); + var array = new int[3] { 0, 1, 2 }; + bfast.SetArray("A", array); + TestBeforeAfter(b => b.GetEnumerable("A"), Is.EqualTo(array)); } [Test] public void SetArray_Then_GetEnumerable_Bytes() { - var bfast = new BFast(); - bfast.SetArray("A", new int[3] { 0, 1, 2 }); - var result = bfast.GetEnumerable("A"); - - var bytes = (new int[3] { 0, 1, 2 }).SelectMany(i => BitConverter.GetBytes(i)); - Assert.That(result, Is.EqualTo(bytes)); + var array = new int[3] { 0, 1, 2 }; + var expected = array.SelectMany(i => BitConverter.GetBytes(i)); + + bfast.SetArray("A", array); + TestBeforeAfter(b => b.GetEnumerable("A"), Is.EqualTo(expected)); } [Test] public void SetArray_Then_GetEnumerable_Float() { - var bfast = new BFast(); - bfast.SetArray("A", new int[3] { 0, 1, 2 }); + var array = new int[3] { 0, 1, 2 }; + var expected = array.Select(i => BitConverter.Int32BitsToSingle(i)); + + bfast.SetArray("A", array); var result = bfast.GetEnumerable("A"); - - var floats = (new int[3] { 0, 1, 2 }).Select(i => BitConverter.Int32BitsToSingle(i)); - Assert.That(result, Is.EqualTo(floats)); } [Test] public void SetArray_Then_GetBFast_Returns_Null() { - var bfast = new BFast(); bfast.SetArray("A", new int[3] { 0, 1, 2 }); - var result = bfast.GetBFast("A"); - - Assert.IsNull(result); + TestBeforeAfter(b => b.GetBFast("A"), Is.Null); } [Test] public void SetArray_Then_SetArray_Replaces() { - var bfast = new BFast(); - bfast.SetArray("A", new int[3] { 0, 1, 2 }); - bfast.SetArray("A", new float[3] { 0.1f, 0.2f, 0.3f }); - var result = bfast.GetArray("A"); - - Assert.That(result, Is.EqualTo(new float[3] { 0.1f, 0.2f, 0.3f })); + var ints = new int[3] { 0, 1, 2 }; + var floats = new float[3] { 0.1f, 0.2f, 0.3f }; + bfast.SetArray("A", ints); + bfast.SetArray("A", floats); + TestBeforeAfter(b => b.GetArray("A"), Is.EqualTo(floats)); } [Test] public void SetArray_Then_SetBFast_Replaces() { - var bfast = new BFast(); - bfast.SetArray("A", new int[3] { 0, 1, 2 }); bfast.SetBFast("A", new BFast()); - var result = bfast.GetArray("A"); - Assert.That(result.Length > 3); + TestBeforeAfter(b => b.GetArray("A").Length, Is.GreaterThan(3)); } + #endregion [Test] public void SetBFast_Adds_Entry() { - var bfast = new BFast(); bfast.SetBFast("A", new BFast()); - - Assert.That(bfast.Entries.Count(), Is.EqualTo(1)); + TestBeforeAfter(b => b.Entries.Count(), Is.EqualTo(1)); } [Test] public void SetBFast_Then_GetBFast_Returns_Same() { - var bfast = new BFast(); - var b = new BFast(); - bfast.SetBFast("A", b); - var result = bfast.GetBFast("A"); - - Assert.That(result, Is.EqualTo(b)); + var expected = new BFast(); + bfast.SetBFast("A", expected); + TestBeforeAfter(b => b.GetBFast("A"), Is.EqualTo(expected)); } [Test] @@ -299,143 +327,118 @@ public void SetBFast_Then_GetBFast_Nested() { using (var file = File.Open(ResidencePath, FileMode.Open)) { - var (b1, b2, b3) = (new BFast(), new BFast(), new BFast()); - b2.SetBFast("b3", b3); + var (b1, b2) = (new BFast(), new BFast()); b1.SetBFast("b2", b2); + bfast.SetBFast("b1", b1); - var mem = b1.ToMemoryStream(); - var r1 = new BFast(mem); + var mem = bfast.ToMemoryStream(); + var r = new BFast(mem); + var r1 = r.GetBFast("b1"); var r2 = r1.GetBFast("b2"); - var r3 = r2.GetBFast("b3"); + Assert.NotNull(r); Assert.NotNull(r1); Assert.NotNull(r2); - Assert.NotNull(r3); } } + #region compress [Test] - public void Inflate_NonDeflated_Throws() + public void Decompress_NonCompressed_Ignored() { - var bfast = new BFast(); - var b = new BFast(); - bfast.SetBFast("A", b); - Assert.That(() => bfast.GetBFast("A", inflate: true), Throws.Exception); + var expected = new BFast(); + bfast.SetBFast("A", expected); + TestBeforeAfter(b => bfast.GetBFast("A", decompress: true), Is.EqualTo(expected)); } [Test] - public void Deflate_Inflate_Works() + public void Compress_Decompress_Works() { - var bfast = new BFast(); - var b = new BFast(); - b.SetArray("B", new int[3] { 0, 1, 2 }); - bfast.SetBFast("A", b, deflate: true); - - var result = bfast.GetBFast("A", inflate: true); - var b2 = result.GetArray("B"); - Assert.That(result.Entries.Count(), Is.EqualTo(1)); - Assert.That(b2, Is.EqualTo(new int[3] { 0, 1, 2 })); - } + var ints = new int[3] { 0, 1, 2 }; - [Test] - public void Deflate_Inflate_WriteRead_Works() - { - var bfast = new BFast(); - var b = new BFast(); - b.SetArray("B", new int[3] { 0, 1, 2 }); - bfast.SetBFast("A", b, deflate: true); - var mem = bfast.ToMemoryStream(); + var bfastA = new BFast(); + bfastA.SetArray("B", ints); + bfast.SetBFast("A", bfastA, compress: true); - var read = new BFast(mem); + TestBeforeAfter((b) => + { + var result = b.GetBFast("A", decompress: true); + var b2 = result.GetArray("B"); - var result = read.GetBFast("A", inflate: true); - var b2 = result.GetArray("B"); - Assert.That(result.Entries.Count(), Is.EqualTo(1)); - Assert.That(b2, Is.EqualTo(new int[3] { 0, 1, 2 })); + Assert.That(result.Entries.Count(), Is.EqualTo(1)); + Assert.That(b2, Is.EqualTo(ints)); + }); } + #endregion + + #region bfast [Test] public void SetBFast_Then_SetBFast_Replaces() { - var bfast = new BFast(); - var a = new BFast(); - var b = new BFast(); - bfast.SetBFast("A", a); - bfast.SetBFast("A", b); - var result = bfast.GetBFast("A"); - Assert.That(a != b); - Assert.That(result == b); + var bfastA = new BFast(); + bfast.SetBFast("A", bfastA); + + var bfastB = new BFast(); + bfastB.SetArray("A", new int[] { 1, 2, 3 }); + bfast.SetBFast("A", bfastB); + + TestBeforeAfter((b) => + { + var result = b.GetBFast("A"); + Assert.That(bfastA, Is.Not.EqualTo(bfastB)); + Assert.That(result, Is.Not.EqualTo(bfastA)); + Assert.That(result, Is.EqualTo(bfastB)); + }); } [Test] public void SetBFast_Then_SetArray_Replaces() { - var bfast = new BFast(); bfast.SetBFast("A", new BFast()); bfast.SetArray("A", new int[3] { 0, 1, 2 }); - var result = bfast.GetBFast("A"); - Assert.IsNull(result); + TestBeforeAfter((b) => + { + var result = b.GetBFast("A"); + Assert.IsNull(result); + }); + } + #endregion [Test] public void Remove_Missing_DoesNothing() { - var bfast = new BFast(); - bfast.Remove("A"); - Assert.That(bfast.Entries.Count() == 0); + TestBeforeAfter((b) => + { + b.Remove("A"); + Assert.That(b.Entries.Count() == 0); + }); } [Test] public void Remove_Array() { - var bfast = new BFast(); bfast.SetArray("A", new int[3] { 0, 1, 2 }); bfast.Remove("A"); - Assert.IsNull(bfast.GetArray("A")); - Assert.That(bfast.Entries.Count() == 0); + TestBeforeAfter((b) => + { + Assert.IsNull(b.GetArray("A")); + Assert.That(b.Entries.Count() == 0); + }); } [Test] public void Remove_BFast() { - var bfast = new BFast(); - bfast.SetBFast("A", new BFast()); - bfast.Remove("A"); - Assert.IsNull(bfast.GetBFast("A")); - Assert.That(bfast.Entries.Count() == 0); - } - - [Test] - public void Removed_BFast_Not_Written() - { - var bfast = new BFast(); bfast.SetBFast("A", new BFast()); bfast.Remove("A"); - bfast.Write(ResultPath); - - using (var stream = File.OpenRead(ResultPath)) + TestBeforeAfter((b) => { - var other = new BFast(stream); - Assert.IsNull(other.GetBFast("A")); - Assert.That(other.Entries.Count() == 0); - } - } - - [Test] - public void Removed_Array_Not_Written() - { - var bfast = new BFast(); - bfast.SetArray("A", new int[3] { 0, 1, 2 }); - bfast.Remove("A"); - bfast.Write(ResultPath); - - using (var stream = File.OpenRead(ResultPath)) - { - var other = new BFast(stream); - Assert.IsNull(other.GetArray("A")); - Assert.That(other.Entries.Count() == 0); - } + Assert.IsNull(bfast.GetBFast("A")); + Assert.That(bfast.Entries.Count() == 0); + }); } [Test] @@ -460,62 +463,6 @@ public void Removed_InChild_Not_Written() } } - [Test] - public void Write_Then_Read_Array() - { - var bfast = new BFast(); - - bfast.SetArray("A", new int[3] { 0, 1, 2 }); - bfast.Write(ResultPath); - - using (var stream = File.OpenRead(ResultPath)) - { - var other = new BFast(stream); - var result = other.GetArray("A"); - Assert.That(result, Is.EqualTo(new int[3] { 0, 1, 2 })); - } - } - - [Test] - public void Write_Then_Read_Enumerable() - { - var bfast = new BFast(); - - bfast.SetEnumerable("A", () => new int[3] { 0, 1, 2 }); - bfast.Write(ResultPath); - - using (var stream = File.OpenRead(ResultPath)) - { - var other = new BFast(stream); - var array = other.GetArray("A"); - var enumerable = other.GetEnumerable("A"); - Assert.That(array, Is.EqualTo(new int[3] { 0, 1, 2 })); - Assert.That(enumerable, Is.EqualTo(new int[3] { 0, 1, 2 })); - } - } - - [Test] - public void Write_Then_Read_SimpleBFast() - { - var bfast = new BFast(); - var child = new BFast(); - - bfast.SetBFast("child", child); - child.SetArray("A", new int[3] { 0, 1, 2 }); - bfast.Write(ResultPath); - - using (var stream = File.OpenRead(ResultPath)) - { - var other = new BFast(stream); - var child2 = other.GetBFast("child"); - var result = child2.GetArray("A"); - - Assert.That(other.Entries.Count() == 1); - Assert.That(child2.Entries.Count() == 1); - Assert.That(result, Is.EqualTo(new int[3] { 0, 1, 2 })); - } - } - [Test] public void Write_Then_Read_NestedBFast() { diff --git a/src/cs/bfast/Vim.BFast/BFast/BFast.cs b/src/cs/bfast/Vim.BFast/BFast/BFast.cs index 07cec61d..6224bb44 100644 --- a/src/cs/bfast/Vim.BFast/BFast/BFast.cs +++ b/src/cs/bfast/Vim.BFast/BFast/BFast.cs @@ -1,73 +1,37 @@ using System; using System.Collections.Generic; using System.IO; -using System.IO.Compression; using System.Linq; +using Vim.BFastNS; using Vim.BFastNS.Core; namespace Vim.BFastNS { public class BFast : IBFastNode { - private readonly Dictionary _children = new Dictionary(); + private readonly Dictionary _children = new Dictionary(); public IEnumerable Entries => _children.Keys; private IEnumerable<(string name, IWritable buffer)> Writables => _children.Select(kvp => (kvp.Key, kvp.Value as IWritable)); public BFast() { } public BFast(Stream stream) { - var node = GetBFastNodes(stream); - _children = node.ToDictionary(c => c.name, c => c.value as IBFastNode); + var nodes = GetBFastNodes(stream); + _children = nodes.ToDictionary(c => c.name, c => new CompressibleNode(c.value)); } - public void SetBFast(Func getName, IEnumerable others, bool deflate = false) + public void SetBFast(Func getName, IEnumerable others, bool compress = false) { var i = 0; foreach (var b in others) { - SetBFast(getName(i++), b, deflate); + SetBFast(getName(i++), b, compress); } } - public void SetBFast(string name, BFast bfast, bool deflate = false) + public void SetBFast(string name, BFast bfast, bool compress = false) { - if (deflate == false) - { - _children[name] = bfast; - } - else - { - var a = Deflate2(bfast); - SetArray(name, a); - } - } - - private byte[] Deflate(BFast bfast) - { - using (var output = new MemoryStream()) - { - using (var decompress = new DeflateStream(output, CompressionMode.Compress, true)) - { - bfast.Write(decompress); - } - return output.ToArray(); - } - } - - private byte[] Deflate2(BFast bfast) - { - using (var input = new MemoryStream()) - using (var output = new MemoryStream()) - { - bfast.Write(input); - input.Seek(0, SeekOrigin.Begin); - using (var decompress = new DeflateStream(output, CompressionMode.Compress, true)) - { - input.CopyTo(decompress); - } - // This need to happen after the deflate stream is disposed. - return output.ToArray(); - } + _children[name] = new CompressibleNode(bfast, compress); } public void SetEnumerable(string name, Func> enumerable) where T : unmanaged @@ -77,7 +41,7 @@ public void SetEnumerable(string name, Func> enumerable) where _children.Remove(name); return; } - _children[name] = new BFastEnumerableNode(enumerable); + _children[name] = new CompressibleNode(new BFastEnumerableNode(enumerable)); } public void SetArray(string name, T[] array) where T : unmanaged @@ -87,60 +51,30 @@ public void SetArray(string name, T[] array) where T : unmanaged _children.Remove(name); return; } - _children[name] = BFastNode.FromArray(array); - } - - public void SetArrays(Func getName, IEnumerable arrays) where T : unmanaged - { - var index = 0; - foreach (var array in arrays) - { - SetArray(getName(index++), array); - } - } - - public void SetNode(string name, BFastNode node) - { - _children[name] = node; + _children[name] = new CompressibleNode(new BFastArrayNode(array)); } - public BFast GetBFast(string name, bool inflate = false) + public BFast GetBFast(string name, bool decompress = false) { var node = GetNode(name); if (node == null) return null; - if (inflate == false) return node.AsBFast(); - return InflateNode(node); - } - - private BFast InflateNode(IBFastNode node) - { - var output = new MemoryStream(); - using (var input = new MemoryStream()) - { - node.Write(input); - input.Seek(0, SeekOrigin.Begin); - using (var compress = new DeflateStream(input, CompressionMode.Decompress, true)) - { - compress.CopyTo(output); - output.Seek(0, SeekOrigin.Begin); - return new BFast(output); - } - } + var n = decompress ? node.Decompress() : node.Node; + return n.AsBFast(); } public IEnumerable GetEnumerable(string name) where T : unmanaged { if (!_children.ContainsKey(name)) return null; - return _children[name].AsEnumerable(); + return _children[name].Node.AsEnumerable(); } public T[] GetArray(string name) where T : unmanaged { if (!_children.ContainsKey(name)) return null; - return _children[name].AsArray(); + return _children[name].Node.AsArray(); } - public IBFastNode GetNode(string name) + public CompressibleNode GetNode(string name) => _children.TryGetValue(name, out var value) ? value : null; public void Remove(string name) @@ -163,8 +97,6 @@ public void Write(string path) } } - public byte[] AsBytes() => (this as IBFastNode).AsArray(); - BFast IBFastNode.AsBFast() { return this; @@ -172,33 +104,24 @@ BFast IBFastNode.AsBFast() T[] IBFastNode.AsArray() { - using (var stream = new MemoryStream()) + using (var mem = ToMemoryStream()) { - Write(stream); - var end = stream.Position; - stream.Seek(0, SeekOrigin.Begin); - return stream.ReadArrayBytes((int)end); + return mem.ReadArrayBytes(); } } - public IEnumerable AsEnumerable() where T : unmanaged + IEnumerable IBFastNode.AsEnumerable() { - using (var stream = new MemoryStream()) - { - Write(stream); - var end = stream.Position; - stream.Seek(0, SeekOrigin.Begin); - return stream.ReadArrayBytes((int)end); - } + return (this as IBFastNode).AsArray(); } - private static IEnumerable<(string name, BFastNode value)> GetBFastNodes(Stream stream) + private static IEnumerable<(string name, BFastStreamNode value)> GetBFastNodes(Stream stream) { var offset = stream.Position; var raw = BFastHeader.FromStream(stream); - foreach(var kvp in raw.Ranges) + foreach (var kvp in raw.Ranges) { - var node = new BFastNode( + var node = new BFastStreamNode( stream, kvp.Value.OffsetBy(offset) ); @@ -206,6 +129,36 @@ public IEnumerable AsEnumerable() where T : unmanaged yield return (kvp.Key, node); } } + + /// + /// Writes the current bfast to a new memory streams + /// The stream is returned at position 0. + /// + public MemoryStream ToMemoryStream() + { + var stream = new MemoryStream(); + Write(stream); + stream.Seek(0, SeekOrigin.Begin); + return stream; + } + + public override bool Equals(object obj) + { + if (obj is BFast) + { + return Equals((BFast)obj); + } + return false; + } + + public bool Equals(BFast other) + { + var a = (this as IBFastNode).AsEnumerable(); + var b = (other as IBFastNode).AsEnumerable(); + return a.SequenceEqual(b); + } + + public override int GetHashCode() => (this as IBFastNode).AsEnumerable().GetHashCode(); } } diff --git a/src/cs/bfast/Vim.BFast/BFast/BFastArrayNode.cs b/src/cs/bfast/Vim.BFast/BFast/BFastArrayNode.cs new file mode 100644 index 00000000..adc18739 --- /dev/null +++ b/src/cs/bfast/Vim.BFast/BFast/BFastArrayNode.cs @@ -0,0 +1,45 @@ +using System.Collections.Generic; +using System.IO; + +namespace Vim.BFastNS +{ + public class BFastArrayNode : IBFastNode where TData : unmanaged + { + private readonly TData[] _array; + + public BFastArrayNode(TData[] array) + { + _array = array; + } + + public T[] AsArray() where T : unmanaged + { + if (typeof(T) == typeof(TData)) + { + return _array as T[]; + } + return _array.Convert(); + } + + public BFast AsBFast() + { + try + { + return new BFast(_array.ToMemoryStream()); + } + catch + { + return null; + } + } + + public IEnumerable AsEnumerable() where T: unmanaged { + return (_array as IEnumerable).Convert(); + } + + public void Write(Stream stream) + { + stream.Write(_array); + } + } +} diff --git a/src/cs/bfast/Vim.BFast/BFast/BFastEnumerableNode.cs b/src/cs/bfast/Vim.BFast/BFast/BFastEnumerableNode.cs index 418f1d50..e40da913 100644 --- a/src/cs/bfast/Vim.BFast/BFast/BFastEnumerableNode.cs +++ b/src/cs/bfast/Vim.BFast/BFast/BFastEnumerableNode.cs @@ -7,76 +7,46 @@ namespace Vim.BFastNS { public class BFastEnumerableNode : IBFastNode where TNode : unmanaged { - private Func> _source; + private readonly Func> _source; + public BFastEnumerableNode(Func> source) { _source = source; } - private BFastNode AsMemNode() - => BFastNode.FromArray(_source().ToArray()); - public T[] AsArray() where T : unmanaged - => AsMemNode().AsArray(); - - public BFast AsBFast() => AsMemNode().AsBFast(); - public IEnumerable AsEnumerable() where T : unmanaged { - var stream = new MemoryStream(); - var array = new T[1048576]; - var chunks = Chunkify(_source(), 1048576); - while (chunks.MoveNext()) + if (typeof(T) == typeof(TNode)) { - (var chunk, var chunkSize) = chunks.Current; - stream.Seek(0, SeekOrigin.Begin); - stream.Write(chunk, chunkSize); - var count = ReadArray(stream, array); - - if (count > 0) - { - for( var i = 0; i < count; i++) - { - yield return array[i]; - } - } + return _source().Cast().ToArray(); + } + else + { + return _source().ToArray().Convert(); } } - static IEnumerator<(T[], int)> Chunkify(IEnumerable source, int chunkSize) + public BFast AsBFast() { - var chunk = new T[chunkSize]; - var index = 0; - - foreach (var item in source) + try { - chunk[index++] = item; - - if (index == chunkSize) - { - yield return (chunk, index); - index = 0; - } + return new BFast(_source().ToMemoryStream()); } - - if (index > 0) + catch { - yield return (chunk, index); + return null; } - } - - // Function is extracted because unsafe code cannot appear in generator - private unsafe int ReadArray(MemoryStream stream, T[] array) where T : unmanaged + } + public IEnumerable AsEnumerable() where T : unmanaged { - var length = (int)stream.Position; - if (length < sizeof(T)) + if (typeof(T) == typeof(TNode)) { - return 0; + return _source().Cast(); + } + else + { + return _source().Convert(); } - - var count = length / sizeof(T); - stream.Seek(0, SeekOrigin.Begin); - stream.ReadArray(array, count); - return count; } public void Write(Stream stream) diff --git a/src/cs/bfast/Vim.BFast/BFast/BFastNextExtensions.cs b/src/cs/bfast/Vim.BFast/BFast/BFastNextExtensions.cs index f8bcbe29..24e30d4a 100644 --- a/src/cs/bfast/Vim.BFast/BFast/BFastNextExtensions.cs +++ b/src/cs/bfast/Vim.BFast/BFast/BFastNextExtensions.cs @@ -5,23 +5,30 @@ namespace Vim.BFastNS { - public static class BFastNextExtensions + public static class BFastHelper { - public static T ReadBFast(this string path, Func process) + public static T Read(string path, Func func) { using (var file = new FileStream(path, FileMode.Open)) { var bfast = new BFast(file); - return process(bfast); + return func(bfast); } } + } + public static class BFastNextExtensions + { public static IEnumerable ToNamedBuffers(this BFast bfast) { return bfast.Entries.Select(name => bfast.GetArray(name).ToNamedBuffer(name)); } - public static MemoryStream ToMemoryStream(this BFast bfast) + /// + /// Writes the current bfast to a new memory streams + /// The stream is returned at position 0. + /// + public static MemoryStream ToMemoryStream(this IBFastNode bfast) { var stream = new MemoryStream(); bfast.Write(stream); diff --git a/src/cs/bfast/Vim.BFast/BFast/BFastNode.cs b/src/cs/bfast/Vim.BFast/BFast/BFastNode.cs deleted file mode 100644 index deb6f4e1..00000000 --- a/src/cs/bfast/Vim.BFast/BFast/BFastNode.cs +++ /dev/null @@ -1,77 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using Vim.BFastNS.Core; - -namespace Vim.BFastNS -{ - public class BFastNode : IBFastNode - { - private readonly Stream _stream; - private readonly BFastRange _range; - - public static BFastNode FromArray(T[] array) where T : unmanaged - { - /* - Is a memory leak created if a MemoryStream in .NET is not closed? - -----------------------------------------]------------------------- - You won't leak anything - at least in the current implementation. - Calling Dispose won't clean up the memory used by MemoryStream any faster. It will stop your stream from being viable for Read/Write calls after the call, which may or may not be useful to you. - If you're absolutely sure that you never want to move from a MemoryStream to another kind of stream, it's not going to do you any harm to not call Dispose. However, it's generally good practice partly because if you ever do change to use a different Stream, you don't want to get bitten by a hard-to-find bug because you chose the easy way out early on. (On the other hand, there's the YAGNI argument...) - The other reason to do it anyway is that a new implementation may introduce resources which would be freed on Dispose. - https://stackoverflow.com/questions/234059/is-a-memory-leak-created-if-a-memorystream-in-net-is-not-closed - */ - var stream = new MemoryStream(); - stream.Write(array); - return new BFastNode(stream, stream.FullRange()); - } - - - public BFastNode(Stream stream, BFastRange range, Action cleanup = null) - { - _stream = stream; - _range = range; - } - - public BFast AsBFast() - { - _stream.Seek(_range.Begin, SeekOrigin.Begin); - try - { - return new BFast(_stream); - } - catch (Exception ex) - { - // It is expected most buffers are not valid bfasts. - return null; - } - } - - public T[] AsArray() where T : unmanaged - { - _stream.Seek(_range.Begin, SeekOrigin.Begin); - return _stream.ReadArrayBytes(_range.Count); - } - - public IEnumerable AsEnumerable() where T : unmanaged - => AsArray(); - - public void Write(Stream stream) - { - _stream.Seek(_range.Begin, SeekOrigin.Begin); - CopyStream(_stream, stream, (int)_range.Count); - } - - private static void CopyStream(Stream input, Stream output, int bytes) - { - var buffer = new byte[32768]; - int read; - while (bytes > 0 && - (read = input.Read(buffer, 0, Math.Min(buffer.Length, bytes))) > 0) - { - output.Write(buffer, 0, read); - bytes -= read; - } - } - } -} diff --git a/src/cs/bfast/Vim.BFast/BFast/BFastStreamNode.cs b/src/cs/bfast/Vim.BFast/BFast/BFastStreamNode.cs new file mode 100644 index 00000000..ff06a296 --- /dev/null +++ b/src/cs/bfast/Vim.BFast/BFast/BFastStreamNode.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections.Generic; +using System.IO; +using Vim.BFastNS.Core; + +namespace Vim.BFastNS +{ + public class BFastStreamNode : IBFastNode + { + private readonly Stream _stream; + private readonly BFastRange _range; + + public BFastStreamNode(Stream stream, BFastRange range, Action cleanup = null) + { + _stream = stream; + _range = range; + } + + public BFast AsBFast() + { + _stream.Seek(_range.Begin, SeekOrigin.Begin); + try + { + return new BFast(_stream); + } + catch + { + // It is expected most buffers are not valid bfasts. + return null; + } + } + + public T[] AsArray() where T : unmanaged + { + _stream.Seek(_range.Begin, SeekOrigin.Begin); + return _stream.ReadArrayBytes(_range.Count); + } + + public IEnumerable AsEnumerable() where T : unmanaged + => AsArray(); + + public void Write(Stream stream) + { + _stream.Seek(_range.Begin, SeekOrigin.Begin); + CopyStream(_stream, stream, (int)_range.Count); + } + + private static void CopyStream(Stream input, Stream output, int bytes) + { + var buffer = new byte[32768]; //2^15 + int read; + while (bytes > 0 && + (read = input.Read(buffer, 0, Math.Min(buffer.Length, bytes))) > 0) + { + output.Write(buffer, 0, read); + bytes -= read; + } + } + } +} diff --git a/src/cs/bfast/Vim.BFast/BFast/CompressibleNode.cs b/src/cs/bfast/Vim.BFast/BFast/CompressibleNode.cs new file mode 100644 index 00000000..e69da905 --- /dev/null +++ b/src/cs/bfast/Vim.BFast/BFast/CompressibleNode.cs @@ -0,0 +1,57 @@ +using System.IO; +using System.IO.Compression; +using Vim.BFastNS.Core; + +namespace Vim.BFastNS +{ + public class CompressibleNode : IWritable + { + public readonly IBFastNode Node; + private readonly bool _compress; + + public CompressibleNode(IBFastNode node, bool compress = false) + { + Node = node; + _compress = compress; + } + + public void Write(Stream stream) + { + if (_compress) + { + WriteCompress(stream); + } + else + { + Node.Write(stream); + } + } + + public IBFastNode Decompress() + { + if (!(Node is BFastStreamNode)) return Node; + + var output = new MemoryStream(); + using (var input = new MemoryStream()) + { + Node.Write(input); + input.Seek(0, SeekOrigin.Begin); + using (var compress = new DeflateStream(input, CompressionMode.Decompress, true)) + { + compress.CopyTo(output); + output.Seek(0, SeekOrigin.Begin); + return new BFastStreamNode(output, output.FullRange()); + } + } + } + + private void WriteCompress(Stream stream) + { + using (var input = Node.ToMemoryStream()) + using (var compress = new DeflateStream(stream, CompressionMode.Compress, true)) + { + input.CopyTo(compress); + } + } + } +} diff --git a/src/cs/bfast/Vim.BFast/Buffers/MemStreamHelpers.cs b/src/cs/bfast/Vim.BFast/Buffers/MemStreamHelpers.cs new file mode 100644 index 00000000..c45e4f74 --- /dev/null +++ b/src/cs/bfast/Vim.BFast/Buffers/MemStreamHelpers.cs @@ -0,0 +1,38 @@ +using System.Collections.Generic; +using System.IO; + +namespace Vim.BFastNS +{ + /// + /// This class would benefit from being in a generic utilities class, however, having it here allows BFAST to be a standalone without dependencies. + /// + public static class MemStreamHelpers + { + /// + /// Creates and fills a new Memory Stream from the given array. + /// The stream is returned at Position 0. + /// + public static unsafe MemoryStream ToMemoryStream(this T[] array) where T : unmanaged + { + var mem = new MemoryStream(); + mem.Write(array); + mem.Seek(0, SeekOrigin.Begin); + return mem; + } + + /// + /// Creates and fills a new Memory Stream from the given array. + /// The stream is returned at Position 0. + /// + public static unsafe MemoryStream ToMemoryStream(this IEnumerable enumerable) where T : unmanaged + { + var mem = new MemoryStream(); + foreach(var e in enumerable) + { + mem.WriteValue(e); + } + mem.Seek(0, SeekOrigin.Begin); + return mem; + } + } +} diff --git a/src/cs/bfast/Vim.BFast/Buffers/UnsafeConvert.cs b/src/cs/bfast/Vim.BFast/Buffers/UnsafeConvert.cs new file mode 100644 index 00000000..8430e3e3 --- /dev/null +++ b/src/cs/bfast/Vim.BFast/Buffers/UnsafeConvert.cs @@ -0,0 +1,92 @@ +using System.Collections.Generic; +using System.IO; + +namespace Vim.BFastNS +{ + public static class UnsafeConvert + { + + /// + /// Converts an array of type TInput to an array of type TOutput + /// This is not a Cast but an actual byte level conversion. + /// + public static unsafe TResult[] Convert(this TInput[] array) + where TInput : unmanaged + where TResult : unmanaged + { + var count = array.Length * (sizeof(TInput) / sizeof(TResult)); + using (var mem = array.ToMemoryStream()) + { + return mem.ReadArray(count); + } + } + + /// + /// Converts an enumerable of type TInput to an enumerable of type TOutput + /// This is not a Cast but an actual byte level conversion. + /// + public static IEnumerable Convert(this IEnumerable input, int chunksize = 1048576) + where TInput : unmanaged + where TResult : unmanaged + { + var stream = new MemoryStream(); + var array = new TResult[chunksize]; + var chunks = Chunkify(input, chunksize); + while (chunks.MoveNext()) + { + (var chunk, var size) = chunks.Current; + stream.Seek(0, SeekOrigin.Begin); + stream.Write(chunk, size); + var count = ReadArray(stream, array); + + if (count > 0) + { + for (var i = 0; i < count; i++) + { + yield return array[i]; + } + } + } + } + + // Function is extracted because unsafe code cannot appear in generator + private static unsafe int ReadArray(MemoryStream stream, T[] array) where T : unmanaged + { + var length = (int)stream.Position; + if (length < sizeof(T)) + { + return 0; + } + + var count = length / sizeof(T); + stream.Seek(0, SeekOrigin.Begin); + stream.ReadArray(array, count); + return count; + } + + /// + /// Returns an enumeration of chunks of the given size from the given enumeration. + /// + private static IEnumerator<(T[], int)> Chunkify(IEnumerable source, int chunkSize) + { + var chunk = new T[chunkSize]; + var index = 0; + + foreach (var item in source) + { + chunk[index++] = item; + + if (index == chunkSize) + { + yield return (chunk, index); + index = 0; + } + } + + if (index > 0) + { + yield return (chunk, index); + } + } + } +} diff --git a/src/cs/bfast/Vim.BFast/Buffers/UnsafeHelpers.cs b/src/cs/bfast/Vim.BFast/Buffers/UnsafeHelpers.cs deleted file mode 100644 index 527a82f3..00000000 --- a/src/cs/bfast/Vim.BFast/Buffers/UnsafeHelpers.cs +++ /dev/null @@ -1,157 +0,0 @@ -using System; -using System.Diagnostics; -using System.IO; - -namespace Vim.BFastNS -{ - /// - /// This class would benefit from being in a generic utilities class, however, having it here allows BFAST to be a standalone without dependencies. - /// - public static class UnsafeHelpers - { - /// - /// Helper for reading arbitrary unmanaged types from a Stream. - /// - public static unsafe void ReadBytesBuffered(this Stream stream, byte* dest, long count, int bufferSize = 4096) - { - var buffer = new byte[bufferSize]; - int bytesRead; - fixed (byte* pBuffer = buffer) - { - while ((bytesRead = stream.Read(buffer, 0, (int)Math.Min(buffer.Length, count))) > 0) - { - if (dest != null) - Buffer.MemoryCopy(pBuffer, dest, count, bytesRead); - count -= bytesRead; - dest += bytesRead; - } - } - } - - /// - /// Helper for writing arbitrary large numbers of bytes - /// - public static unsafe void WriteBytesBuffered(this Stream stream, byte* src, long count, int bufferSize = 4096) - { - var buffer = new byte[bufferSize]; - fixed (byte* pBuffer = buffer) - { - while (count > 0) - { - var toWrite = (int)Math.Min(count, buffer.Length); - Buffer.MemoryCopy(src, pBuffer, buffer.Length, toWrite); - stream.Write(buffer, 0, toWrite); - count -= toWrite; - src += toWrite; - } - } - } - - /// - /// Helper for reading arbitrary unmanaged types from a Stream. - /// - public static unsafe void Read(this Stream stream, T* dest) where T : unmanaged - => stream.ReadBytesBuffered((byte*)dest, sizeof(T)); - - /// - /// Helper for reading arbitrary unmanaged types from a Stream. - /// - public static unsafe T Read(this Stream stream) where T : unmanaged - { - T r; - stream.ReadBytesBuffered((byte*)&r, sizeof(T)); - return r; - } - - /// - /// Helper for reading arrays of arbitrary unmanaged types from a Stream, that might be over 2GB of size. - /// That said, in C#, you can never load more int.MaxValue numbers of items. - /// NOTE: Arrays are still limited to 2gb in size unless gcAllowVeryLargeObjects is set to true - /// in the runtime environment. - /// https://docs.microsoft.com/en-us/dotnet/api/system.array?redirectedfrom=MSDN&view=netframework-4.7.2#remarks - /// Alternatively, we could convert to .Net Core - /// - public static unsafe T[] ReadArray(this Stream stream, int count) where T : unmanaged - { - var r = new T[count]; - fixed (T* pDest = r) - { - - var pBytes = (byte*)pDest; - stream.ReadBytesBuffered(pBytes, (long)count * sizeof(T)); - } - return r; - } - - public static unsafe void ReadArray(this Stream stream, T[] array, int count) where T : unmanaged - { - fixed (T* pDest = array) - { - var pBytes = (byte*)pDest; - stream.ReadBytesBuffered(pBytes, (long)count * sizeof(T)); - } - } - - /// - /// Equivalent to ReadArray to use when you know the byte count instead of element count. - /// - public static unsafe T[] ReadArrayBytes(this Stream stream, long byteLength) where T : unmanaged - { - var count = byteLength / sizeof(T); - Debug.Assert(count <= int.MaxValue); - return ReadArray(stream, (int)count); - } - - /// - /// A wrapper for stream.Seek(numBytes, SeekOrigin.Current) to avoid allocating memory for unrecognized buffers. - /// - public static void SkipBytes(this Stream stream, long numBytes) - => stream.Seek(numBytes, SeekOrigin.Current); - - /// - /// Helper for reading arrays of arbitrary unmanaged types from a Stream, that might be over 2GB of size. - /// That said, in C#, you can never load more int.MaxValue numbers of items. - /// - public static unsafe T[] ReadArrayFromNumberOfBytes(this Stream stream, long numBytes) where T : unmanaged - { - var count = numBytes / sizeof(T); - if (numBytes % sizeof(T) != 0) - throw new Exception($"The number of bytes {numBytes} is not divisible by the size of the type {sizeof(T)}"); - if (count >= int.MaxValue) - throw new Exception($"{count} exceeds the maximum number of items that can be read into an array {int.MaxValue}"); - return stream.ReadArray((int)count); - } - - /// - /// Helper for writing arbitrary unmanaged types - /// - public static unsafe void WriteValue(this Stream stream, T x) where T : unmanaged - { - var p = &x; - stream.WriteBytesBuffered((byte*)p, sizeof(T)); - } - - - /// - /// Helper for writing arrays of unmanaged types - /// - public static unsafe void Write(this Stream stream, T[] xs) where T : unmanaged - { - fixed (T* p = xs) - { - stream.WriteBytesBuffered((byte*)p, xs.LongLength * sizeof(T)); - } - } - - /// - /// Helper for writing arrays of unmanaged types - /// - public static unsafe void Write(this Stream stream, T[] xs, long count) where T : unmanaged - { - fixed (T* p = xs) - { - stream.WriteBytesBuffered((byte*)p, count * sizeof(T)); - } - } - } -} diff --git a/src/cs/bfast/Vim.BFast/Buffers/UnsafeRead.cs b/src/cs/bfast/Vim.BFast/Buffers/UnsafeRead.cs new file mode 100644 index 00000000..c46e9786 --- /dev/null +++ b/src/cs/bfast/Vim.BFast/Buffers/UnsafeRead.cs @@ -0,0 +1,94 @@ +using System; +using System.IO; + +namespace Vim.BFastNS +{ + public static class UnsafeRead + { + /// + /// Reads and converts the next value of the stream. + /// + public static unsafe T ReadValue(this Stream stream) where T : unmanaged + { + T r; + stream.ReadBytesBuffered((byte*)&r, sizeof(T)); + return r; + } + + /// + /// Reads bytes until the end of the stream and converts them to T. + /// + public static unsafe T[] ReadArray(this Stream stream) where T : unmanaged + { + return ReadArrayBytes(stream, stream.Length - stream.Position); + } + + /// + /// Reads and converts the next ByteCount bytes from the stream and returns the result as a new array. + /// Will throw if ByteCount is not a multiple of sizeof T. + /// + public static unsafe T[] ReadArrayBytes(this Stream stream, long byteCount) where T : unmanaged + { + var count = byteCount / sizeof(T); + if (byteCount % sizeof(T) != 0) + throw new Exception($"The number of bytes {byteCount} is not divisible by the size of the type {sizeof(T)}"); + if (count >= int.MaxValue) + throw new Exception($"{count} exceeds the maximum number of items that can be read into an array {int.MaxValue}"); + return ReadArray(stream, (int)count); + } + + /// + /// Reads and converts the next Count value from the stream and returns the result as a new array. + /// + public static unsafe T[] ReadArray(this Stream stream, int count) where T : unmanaged + { + var r = new T[count]; + fixed (T* pDest = r) + { + + var pBytes = (byte*)pDest; + stream.ReadBytesBuffered(pBytes, (long)count * sizeof(T)); + } + return r; + } + + /// + /// Reads and converts the next Count values from the stream and writes the result into the given array. + /// + public static unsafe void ReadArray(this Stream stream, T[] array, int count) where T : unmanaged + { + if (array.Length < count) + throw new Exception("Destination array needs to be larger than count."); + + fixed (T* pDest = array) + { + var pBytes = (byte*)pDest; + stream.ReadBytesBuffered(pBytes, (long)count * sizeof(T)); + } + } + + /// + /// Helper for reading arrays of arbitrary unmanaged types from a Stream, that might be over 2GB of size. + /// That said, in C#, you can never load more int.MaxValue numbers of items. + /// NOTE: Arrays are still limited to 2gb in size unless gcAllowVeryLargeObjects is set to true + /// in the runtime environment. + /// https://docs.microsoft.com/en-us/dotnet/api/system.array?redirectedfrom=MSDN&view=netframework-4.7.2#remarks + /// Alternatively, we could convert to .Net Core + /// + private static unsafe void ReadBytesBuffered(this Stream stream, byte* dest, long count, int bufferSize = 4096) + { + var buffer = new byte[bufferSize]; + int bytesRead; + fixed (byte* pBuffer = buffer) + { + while ((bytesRead = stream.Read(buffer, 0, (int)Math.Min(buffer.Length, count))) > 0) + { + if (dest != null) + Buffer.MemoryCopy(pBuffer, dest, count, bytesRead); + count -= bytesRead; + dest += bytesRead; + } + } + } + } +} diff --git a/src/cs/bfast/Vim.BFast/Buffers/UnsafeWrite.cs b/src/cs/bfast/Vim.BFast/Buffers/UnsafeWrite.cs new file mode 100644 index 00000000..d39ea158 --- /dev/null +++ b/src/cs/bfast/Vim.BFast/Buffers/UnsafeWrite.cs @@ -0,0 +1,55 @@ +using System; +using System.IO; + +namespace Vim.BFastNS +{ + public static class UnsafeWrite + { + /// + /// Converts given value to bytes and writes resulting bytes to the stream + /// + public static unsafe void WriteValue(this Stream stream, T x) where T : unmanaged + { + var p = &x; + stream.WriteBytesBuffered((byte*)p, sizeof(T)); + } + + /// + /// Converts values of the given array to bytes and writes the resulting bytes to the stream. + /// + public static unsafe void Write(this Stream stream, T[] xs) where T : unmanaged + { + Write(stream, xs, xs.LongLength); + } + + /// + /// Converts the first Count elements of an array to bytes and writes the resulting bytes to the stream. + /// + public static unsafe void Write(this Stream stream, T[] xs, long count) where T : unmanaged + { + fixed (T* p = xs) + { + stream.WriteBytesBuffered((byte*)p, count * sizeof(T)); + } + } + + /// + /// Writes an arbitrary large numbers of bytes to the stream. + /// + private static unsafe void WriteBytesBuffered(this Stream stream, byte* src, long count, int bufferSize = 4096) + { + var buffer = new byte[bufferSize]; + fixed (byte* pBuffer = buffer) + { + while (count > 0) + { + var toWrite = (int)Math.Min(count, buffer.Length); + Buffer.MemoryCopy(src, pBuffer, buffer.Length, toWrite); + stream.Write(buffer, 0, toWrite); + count -= toWrite; + src += toWrite; + } + } + } + } +} diff --git a/src/cs/bfast/Vim.BFast/Core/BFastHeader.cs b/src/cs/bfast/Vim.BFast/Core/BFastHeader.cs index 6719c521..90f9edf7 100644 --- a/src/cs/bfast/Vim.BFast/Core/BFastHeader.cs +++ b/src/cs/bfast/Vim.BFast/Core/BFastHeader.cs @@ -24,7 +24,7 @@ public static BFastHeader FromStream(Stream stream) if (stream.Length - stream.Position < sizeof(long) * 4) throw new Exception("Stream too short"); - var preamble = stream.Read(); + var preamble = stream.ReadValue(); var ranges = stream.ReadArray((int)preamble.NumArrays); diff --git a/src/cs/g3d/Vim.G3dNext/G3dVim.cs b/src/cs/g3d/Vim.G3dNext/G3dVim.cs index 6f19ecca..b2efc947 100644 --- a/src/cs/g3d/Vim.G3dNext/G3dVim.cs +++ b/src/cs/g3d/Vim.G3dNext/G3dVim.cs @@ -27,7 +27,7 @@ void ISetup.Setup() } public static G3dVim FromVim(string vimPath) - => vimPath.ReadBFast(b => new G3dVim(b.GetBFast("geometry"))); + => BFastHelper.Read(vimPath, b => new G3dVim(b.GetBFast("geometry"))); private int[] ComputeMeshVertexOffsets() { diff --git a/src/cs/vim/Vim.Format.Vimx/Vimx.cs b/src/cs/vim/Vim.Format.Vimx/Vimx.cs index 2a2a270c..49da65c8 100644 --- a/src/cs/vim/Vim.Format.Vimx/Vimx.cs +++ b/src/cs/vim/Vim.Format.Vimx/Vimx.cs @@ -15,11 +15,8 @@ public static class BufferNames public static class BufferCompression { - public const bool Header = false; - public const bool Meta = false; public const bool Scene = true; public const bool Materials = true; - public const bool Meshes = false; public const bool Chunks = true; } @@ -59,7 +56,7 @@ public Vimx(BFast bfast) } public static Vimx FromPath(string path) - => path.ReadBFast((b) => new Vimx(b)); + => BFastHelper.Read(path, b => new Vimx(b)); public BFast ToBFast() { @@ -71,7 +68,5 @@ public BFast ToBFast() bfast.SetBFast(BufferNames.Chunk, Chunks.Select(c => c.ToBFast()), BufferCompression.Chunks); return bfast; } - - } } From 7bcc35b97f1829c6e75b2954a0f9bd6a733b46ac Mon Sep 17 00:00:00 2001 From: simon Date: Mon, 12 Feb 2024 14:21:46 -0500 Subject: [PATCH 062/111] small changes --- src/cs/bfast/Vim.BFast.Tests/BFastTests.cs | 29 +++++++++++-------- src/cs/bfast/Vim.BFast/BFast/BFast.cs | 2 +- .../Vim.BFast/Buffers/BufferExtensions.cs | 2 +- 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/src/cs/bfast/Vim.BFast.Tests/BFastTests.cs b/src/cs/bfast/Vim.BFast.Tests/BFastTests.cs index 649e1b6e..29ce1f85 100644 --- a/src/cs/bfast/Vim.BFast.Tests/BFastTests.cs +++ b/src/cs/bfast/Vim.BFast.Tests/BFastTests.cs @@ -51,15 +51,6 @@ private void TestBeforeAfter(Func method, IResolveConstraint constr Assert.That(method(next), constraint); } - private void TestBeforeAfter(Action method, IResolveConstraint constraint) - { - Assert.That(method, constraint); - - // Test that it also works after write/read - var next = new BFast(bfast.ToMemoryStream()); - Assert.That(method, constraint); - } - private void TestBeforeAfterFile(Func method, IResolveConstraint constraint) { Assert.That(method(bfast), constraint); @@ -344,15 +335,29 @@ public void SetBFast_Then_GetBFast_Nested() #region compress [Test] - public void Decompress_NonCompressed_Ignored() + public void Compression_Decompress_Uncompressed_Returns_Null() { var expected = new BFast(); bfast.SetBFast("A", expected); - TestBeforeAfter(b => bfast.GetBFast("A", decompress: true), Is.EqualTo(expected)); + TestBeforeAfter(b => b.GetBFast("A", decompress: true), Is.Null); + } + + [Test] + public void Compression_Get_Compressed_Returns_Null() + { + var expected = new BFast(); + bfast.SetBFast("A", expected, compress: true); + TestBeforeAfter(b => b.GetBFast("A"), Is.Null); + } + + [Test] + public void Compression_Get_Uncompressed_Works() + { + // This is tested by the bfast tests. } [Test] - public void Compress_Decompress_Works() + public void Compression_Decompress_Compressed_Works() { var ints = new int[3] { 0, 1, 2 }; diff --git a/src/cs/bfast/Vim.BFast/BFast/BFast.cs b/src/cs/bfast/Vim.BFast/BFast/BFast.cs index 6224bb44..e33a54fa 100644 --- a/src/cs/bfast/Vim.BFast/BFast/BFast.cs +++ b/src/cs/bfast/Vim.BFast/BFast/BFast.cs @@ -106,7 +106,7 @@ T[] IBFastNode.AsArray() { using (var mem = ToMemoryStream()) { - return mem.ReadArrayBytes(); + return mem.ReadArray(); } } diff --git a/src/cs/bfast/Vim.BFast/Buffers/BufferExtensions.cs b/src/cs/bfast/Vim.BFast/Buffers/BufferExtensions.cs index 673530c2..dcc5c97a 100644 --- a/src/cs/bfast/Vim.BFast/Buffers/BufferExtensions.cs +++ b/src/cs/bfast/Vim.BFast/Buffers/BufferExtensions.cs @@ -75,7 +75,7 @@ public static long NumBytes(this IBuffer buffer) => (long)buffer.NumElements() * buffer.ElementSize; public static Buffer ReadBufferFromNumberOfBytes(this Stream stream, long numBytes) where T : unmanaged - => stream.ReadArrayFromNumberOfBytes(numBytes).ToBuffer(); + => stream.ReadArrayBytes(numBytes).ToBuffer(); public static Buffer ReadBuffer(this Stream stream, int numElements) where T : unmanaged => stream.ReadArray(numElements).ToBuffer(); From 4bf88eb1c60ecbd392fd7eb68d6db85bc88b0797 Mon Sep 17 00:00:00 2001 From: simon Date: Mon, 12 Feb 2024 14:34:28 -0500 Subject: [PATCH 063/111] Renamed BFastNS to BFastLib --- src/cs/Vim.G3dNext.Tests/VimG3dNextTests.cs | 2 +- src/cs/bfast/Vim.BFast.Tests/BFastTests.cs | 4 ++-- src/cs/bfast/Vim.BFast/BFast/BFast.cs | 5 ++--- src/cs/bfast/Vim.BFast/BFast/BFastArrayNode.cs | 2 +- src/cs/bfast/Vim.BFast/BFast/BFastEnumerableNode.cs | 2 +- src/cs/bfast/Vim.BFast/BFast/BFastNextExtensions.cs | 2 +- src/cs/bfast/Vim.BFast/BFast/BFastStreamNode.cs | 4 ++-- src/cs/bfast/Vim.BFast/BFast/CompressibleNode.cs | 4 ++-- src/cs/bfast/Vim.BFast/BFast/IBFastNode.cs | 2 +- src/cs/bfast/Vim.BFast/Buffers/BufferExtensions.cs | 2 +- src/cs/bfast/Vim.BFast/Buffers/Buffers.cs | 2 +- src/cs/bfast/Vim.BFast/Buffers/MemStreamHelpers.cs | 2 +- src/cs/bfast/Vim.BFast/Buffers/UnsafeConvert.cs | 2 +- src/cs/bfast/Vim.BFast/Buffers/UnsafeRead.cs | 2 +- src/cs/bfast/Vim.BFast/Buffers/UnsafeWrite.cs | 2 +- src/cs/bfast/Vim.BFast/Core/BFastConstants.cs | 2 +- src/cs/bfast/Vim.BFast/Core/BFastHeader.cs | 2 +- src/cs/bfast/Vim.BFast/Core/BFastPreamble.cs | 2 +- src/cs/bfast/Vim.BFast/Core/BFastRange.cs | 2 +- src/cs/bfast/Vim.BFast/Core/BFastSection.cs | 2 +- src/cs/bfast/Vim.BFast/Core/BFastStrings.cs | 2 +- src/cs/bfast/Vim.BFast/Core/BFastWriter.cs | 2 +- src/cs/g3d/Vim.G3d.Tests/G3dTests.cs | 2 +- src/cs/g3d/Vim.G3d/G3D.cs | 2 +- src/cs/g3d/Vim.G3d/G3dSerialization.cs | 2 +- src/cs/g3d/Vim.G3d/GeometryAttribute.cs | 2 +- src/cs/g3d/Vim.G3dNext/G3dGenerated.g.cs | 4 ++-- src/cs/g3d/Vim.G3dNext/G3dVim.cs | 2 +- src/cs/vim/Vim.Format.Core/AssetInfo.cs | 2 +- src/cs/vim/Vim.Format.Core/ColumnExtensions.Buffer.cs | 2 +- src/cs/vim/Vim.Format.Core/Document.cs | 2 +- src/cs/vim/Vim.Format.Core/DocumentBuilder.cs | 2 +- src/cs/vim/Vim.Format.Core/DocumentBuilderExtensions.cs | 4 ++-- src/cs/vim/Vim.Format.Core/DocumentExtensions.cs | 2 +- src/cs/vim/Vim.Format.Core/EntityTable.cs | 2 +- src/cs/vim/Vim.Format.Core/EntityTableBuilder.cs | 2 +- src/cs/vim/Vim.Format.Core/G3dBuilder.cs | 2 +- src/cs/vim/Vim.Format.Core/Geometry/Validation.cs | 2 +- src/cs/vim/Vim.Format.Core/SerializableDocument.cs | 4 ++-- src/cs/vim/Vim.Format.Core/SerializableEntityTable.cs | 2 +- src/cs/vim/Vim.Format.Core/SerializableHeader.cs | 2 +- src/cs/vim/Vim.Format.Core/Validation.cs | 2 +- src/cs/vim/Vim.Format.Tests/FormatTests.cs | 2 +- src/cs/vim/Vim.Format.Vimx.Conversion/VimxConverter.cs | 2 +- src/cs/vim/Vim.Format.Vimx/Vimx.cs | 2 +- src/cs/vim/Vim.Format.Vimx/VimxChunk.cs | 2 +- src/cs/vim/Vim.Format/SceneBuilder/Validation.cs | 2 +- src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs | 2 +- 48 files changed, 55 insertions(+), 56 deletions(-) diff --git a/src/cs/Vim.G3dNext.Tests/VimG3dNextTests.cs b/src/cs/Vim.G3dNext.Tests/VimG3dNextTests.cs index b096b67f..2d357abd 100644 --- a/src/cs/Vim.G3dNext.Tests/VimG3dNextTests.cs +++ b/src/cs/Vim.G3dNext.Tests/VimG3dNextTests.cs @@ -1,6 +1,6 @@ using NUnit.Framework; using NUnit.Framework.Internal; -using Vim.BFastNS; +using Vim.BFastLib; using Vim.Util.Tests; namespace Vim.G3dNext.Tests diff --git a/src/cs/bfast/Vim.BFast.Tests/BFastTests.cs b/src/cs/bfast/Vim.BFast.Tests/BFastTests.cs index 29ce1f85..931e6609 100644 --- a/src/cs/bfast/Vim.BFast.Tests/BFastTests.cs +++ b/src/cs/bfast/Vim.BFast.Tests/BFastTests.cs @@ -1,10 +1,10 @@ using NUnit.Framework; using NUnit.Framework.Constraints; using System.Data; -using Vim.BFastNS.Core; +using Vim.BFastLib.Core; using Vim.Util.Tests; -namespace Vim.BFastNS.Tests +namespace Vim.BFastLib.Tests { public class BFastTests { diff --git a/src/cs/bfast/Vim.BFast/BFast/BFast.cs b/src/cs/bfast/Vim.BFast/BFast/BFast.cs index e33a54fa..281269f2 100644 --- a/src/cs/bfast/Vim.BFast/BFast/BFast.cs +++ b/src/cs/bfast/Vim.BFast/BFast/BFast.cs @@ -2,10 +2,9 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using Vim.BFastNS; -using Vim.BFastNS.Core; +using Vim.BFastLib.Core; -namespace Vim.BFastNS +namespace Vim.BFastLib { public class BFast : IBFastNode { diff --git a/src/cs/bfast/Vim.BFast/BFast/BFastArrayNode.cs b/src/cs/bfast/Vim.BFast/BFast/BFastArrayNode.cs index adc18739..df7e11f0 100644 --- a/src/cs/bfast/Vim.BFast/BFast/BFastArrayNode.cs +++ b/src/cs/bfast/Vim.BFast/BFast/BFastArrayNode.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; using System.IO; -namespace Vim.BFastNS +namespace Vim.BFastLib { public class BFastArrayNode : IBFastNode where TData : unmanaged { diff --git a/src/cs/bfast/Vim.BFast/BFast/BFastEnumerableNode.cs b/src/cs/bfast/Vim.BFast/BFast/BFastEnumerableNode.cs index e40da913..bcca6a47 100644 --- a/src/cs/bfast/Vim.BFast/BFast/BFastEnumerableNode.cs +++ b/src/cs/bfast/Vim.BFast/BFast/BFastEnumerableNode.cs @@ -3,7 +3,7 @@ using System.IO; using System.Linq; -namespace Vim.BFastNS +namespace Vim.BFastLib { public class BFastEnumerableNode : IBFastNode where TNode : unmanaged { diff --git a/src/cs/bfast/Vim.BFast/BFast/BFastNextExtensions.cs b/src/cs/bfast/Vim.BFast/BFast/BFastNextExtensions.cs index 24e30d4a..3bf5d565 100644 --- a/src/cs/bfast/Vim.BFast/BFast/BFastNextExtensions.cs +++ b/src/cs/bfast/Vim.BFast/BFast/BFastNextExtensions.cs @@ -3,7 +3,7 @@ using System.IO; using System.Linq; -namespace Vim.BFastNS +namespace Vim.BFastLib { public static class BFastHelper { diff --git a/src/cs/bfast/Vim.BFast/BFast/BFastStreamNode.cs b/src/cs/bfast/Vim.BFast/BFast/BFastStreamNode.cs index ff06a296..e4833c3c 100644 --- a/src/cs/bfast/Vim.BFast/BFast/BFastStreamNode.cs +++ b/src/cs/bfast/Vim.BFast/BFast/BFastStreamNode.cs @@ -1,9 +1,9 @@ using System; using System.Collections.Generic; using System.IO; -using Vim.BFastNS.Core; +using Vim.BFastLib.Core; -namespace Vim.BFastNS +namespace Vim.BFastLib { public class BFastStreamNode : IBFastNode { diff --git a/src/cs/bfast/Vim.BFast/BFast/CompressibleNode.cs b/src/cs/bfast/Vim.BFast/BFast/CompressibleNode.cs index e69da905..e8264794 100644 --- a/src/cs/bfast/Vim.BFast/BFast/CompressibleNode.cs +++ b/src/cs/bfast/Vim.BFast/BFast/CompressibleNode.cs @@ -1,8 +1,8 @@ using System.IO; using System.IO.Compression; -using Vim.BFastNS.Core; +using Vim.BFastLib.Core; -namespace Vim.BFastNS +namespace Vim.BFastLib { public class CompressibleNode : IWritable { diff --git a/src/cs/bfast/Vim.BFast/BFast/IBFastNode.cs b/src/cs/bfast/Vim.BFast/BFast/IBFastNode.cs index e10aadd6..08d22038 100644 --- a/src/cs/bfast/Vim.BFast/BFast/IBFastNode.cs +++ b/src/cs/bfast/Vim.BFast/BFast/IBFastNode.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; using System.IO; -namespace Vim.BFastNS +namespace Vim.BFastLib { /// /// Anything that can be added to a BFAST must have a size and write to a stream. diff --git a/src/cs/bfast/Vim.BFast/Buffers/BufferExtensions.cs b/src/cs/bfast/Vim.BFast/Buffers/BufferExtensions.cs index dcc5c97a..22d2c6da 100644 --- a/src/cs/bfast/Vim.BFast/Buffers/BufferExtensions.cs +++ b/src/cs/bfast/Vim.BFast/Buffers/BufferExtensions.cs @@ -3,7 +3,7 @@ using System.IO; using System.Linq; -namespace Vim.BFastNS +namespace Vim.BFastLib { /// /// Helper functions for working with buffers diff --git a/src/cs/bfast/Vim.BFast/Buffers/Buffers.cs b/src/cs/bfast/Vim.BFast/Buffers/Buffers.cs index 8dd9c266..274926bc 100644 --- a/src/cs/bfast/Vim.BFast/Buffers/Buffers.cs +++ b/src/cs/bfast/Vim.BFast/Buffers/Buffers.cs @@ -1,7 +1,7 @@ using System; using System.IO; -namespace Vim.BFastNS +namespace Vim.BFastLib { /// /// Provides an interface to an object that manages a potentially large array of elements all of the same unmanaged type. diff --git a/src/cs/bfast/Vim.BFast/Buffers/MemStreamHelpers.cs b/src/cs/bfast/Vim.BFast/Buffers/MemStreamHelpers.cs index c45e4f74..a4369a79 100644 --- a/src/cs/bfast/Vim.BFast/Buffers/MemStreamHelpers.cs +++ b/src/cs/bfast/Vim.BFast/Buffers/MemStreamHelpers.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; using System.IO; -namespace Vim.BFastNS +namespace Vim.BFastLib { /// /// This class would benefit from being in a generic utilities class, however, having it here allows BFAST to be a standalone without dependencies. diff --git a/src/cs/bfast/Vim.BFast/Buffers/UnsafeConvert.cs b/src/cs/bfast/Vim.BFast/Buffers/UnsafeConvert.cs index 8430e3e3..08dc590d 100644 --- a/src/cs/bfast/Vim.BFast/Buffers/UnsafeConvert.cs +++ b/src/cs/bfast/Vim.BFast/Buffers/UnsafeConvert.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; using System.IO; -namespace Vim.BFastNS +namespace Vim.BFastLib { public static class UnsafeConvert { diff --git a/src/cs/bfast/Vim.BFast/Buffers/UnsafeRead.cs b/src/cs/bfast/Vim.BFast/Buffers/UnsafeRead.cs index c46e9786..c3afb350 100644 --- a/src/cs/bfast/Vim.BFast/Buffers/UnsafeRead.cs +++ b/src/cs/bfast/Vim.BFast/Buffers/UnsafeRead.cs @@ -1,7 +1,7 @@ using System; using System.IO; -namespace Vim.BFastNS +namespace Vim.BFastLib { public static class UnsafeRead { diff --git a/src/cs/bfast/Vim.BFast/Buffers/UnsafeWrite.cs b/src/cs/bfast/Vim.BFast/Buffers/UnsafeWrite.cs index d39ea158..940c8d59 100644 --- a/src/cs/bfast/Vim.BFast/Buffers/UnsafeWrite.cs +++ b/src/cs/bfast/Vim.BFast/Buffers/UnsafeWrite.cs @@ -1,7 +1,7 @@ using System; using System.IO; -namespace Vim.BFastNS +namespace Vim.BFastLib { public static class UnsafeWrite { diff --git a/src/cs/bfast/Vim.BFast/Core/BFastConstants.cs b/src/cs/bfast/Vim.BFast/Core/BFastConstants.cs index 60857658..c6934caf 100644 --- a/src/cs/bfast/Vim.BFast/Core/BFastConstants.cs +++ b/src/cs/bfast/Vim.BFast/Core/BFastConstants.cs @@ -1,4 +1,4 @@ -namespace Vim.BFastNS.Core +namespace Vim.BFastLib.Core { /// /// Constants. diff --git a/src/cs/bfast/Vim.BFast/Core/BFastHeader.cs b/src/cs/bfast/Vim.BFast/Core/BFastHeader.cs index 90f9edf7..bed271b6 100644 --- a/src/cs/bfast/Vim.BFast/Core/BFastHeader.cs +++ b/src/cs/bfast/Vim.BFast/Core/BFastHeader.cs @@ -3,7 +3,7 @@ using System.IO; using System.Linq; -namespace Vim.BFastNS.Core +namespace Vim.BFastLib.Core { public class BFastHeader { diff --git a/src/cs/bfast/Vim.BFast/Core/BFastPreamble.cs b/src/cs/bfast/Vim.BFast/Core/BFastPreamble.cs index f0d7b0ff..9aac30f8 100644 --- a/src/cs/bfast/Vim.BFast/Core/BFastPreamble.cs +++ b/src/cs/bfast/Vim.BFast/Core/BFastPreamble.cs @@ -1,7 +1,7 @@ using System; using System.Runtime.InteropServices; -namespace Vim.BFastNS.Core +namespace Vim.BFastLib.Core { /// /// The header contains a magic number, the begin and end indices of data, and the number of arrays. diff --git a/src/cs/bfast/Vim.BFast/Core/BFastRange.cs b/src/cs/bfast/Vim.BFast/Core/BFastRange.cs index 52cbe0e8..e16c6d35 100644 --- a/src/cs/bfast/Vim.BFast/Core/BFastRange.cs +++ b/src/cs/bfast/Vim.BFast/Core/BFastRange.cs @@ -1,7 +1,7 @@ using System.IO; using System.Runtime.InteropServices; -namespace Vim.BFastNS.Core +namespace Vim.BFastLib.Core { /// /// This tells us where a particular array begins and ends in relation to the beginning of a file. diff --git a/src/cs/bfast/Vim.BFast/Core/BFastSection.cs b/src/cs/bfast/Vim.BFast/Core/BFastSection.cs index 0e8c6061..eb9ec678 100644 --- a/src/cs/bfast/Vim.BFast/Core/BFastSection.cs +++ b/src/cs/bfast/Vim.BFast/Core/BFastSection.cs @@ -2,7 +2,7 @@ using System.Diagnostics; using System.IO; -namespace Vim.BFastNS.Core +namespace Vim.BFastLib.Core { /// /// Represents a section of the bfast that will be written to at some point. diff --git a/src/cs/bfast/Vim.BFast/Core/BFastStrings.cs b/src/cs/bfast/Vim.BFast/Core/BFastStrings.cs index a8988584..f2bc1e67 100644 --- a/src/cs/bfast/Vim.BFast/Core/BFastStrings.cs +++ b/src/cs/bfast/Vim.BFast/Core/BFastStrings.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; using System.Text; -namespace Vim.BFastNS.Core +namespace Vim.BFastLib.Core { public static class BFastStrings { diff --git a/src/cs/bfast/Vim.BFast/Core/BFastWriter.cs b/src/cs/bfast/Vim.BFast/Core/BFastWriter.cs index 9e4e0a73..ca58d331 100644 --- a/src/cs/bfast/Vim.BFast/Core/BFastWriter.cs +++ b/src/cs/bfast/Vim.BFast/Core/BFastWriter.cs @@ -1,6 +1,6 @@ using System.IO; -namespace Vim.BFastNS.Core +namespace Vim.BFastLib.Core { /// /// Provide methods to write a buffer collection to a stream. diff --git a/src/cs/g3d/Vim.G3d.Tests/G3dTests.cs b/src/cs/g3d/Vim.G3d.Tests/G3dTests.cs index bd08a7c5..fa9f38ed 100644 --- a/src/cs/g3d/Vim.G3d.Tests/G3dTests.cs +++ b/src/cs/g3d/Vim.G3d.Tests/G3dTests.cs @@ -4,7 +4,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using Vim.BFastNS; +using Vim.BFastLib; using Vim.G3d.AssimpWrapper; using Vim.LinqArray; using Vim.Math3d; diff --git a/src/cs/g3d/Vim.G3d/G3D.cs b/src/cs/g3d/Vim.G3d/G3D.cs index ac63b84d..a9f44b68 100644 --- a/src/cs/g3d/Vim.G3d/G3D.cs +++ b/src/cs/g3d/Vim.G3d/G3D.cs @@ -11,7 +11,7 @@ Usage licensed under terms of MIT License using System.Linq; using Vim.LinqArray; using Vim.Math3d; -using Vim.BFastNS; +using Vim.BFastLib; namespace Vim.G3d { diff --git a/src/cs/g3d/Vim.G3d/G3dSerialization.cs b/src/cs/g3d/Vim.G3d/G3dSerialization.cs index a8cadb6e..4f47b27d 100644 --- a/src/cs/g3d/Vim.G3d/G3dSerialization.cs +++ b/src/cs/g3d/Vim.G3d/G3dSerialization.cs @@ -1,6 +1,6 @@ using System; using System.IO; -using Vim.BFastNS; +using Vim.BFastLib; using Vim.LinqArray; using System.Collections.Generic; diff --git a/src/cs/g3d/Vim.G3d/GeometryAttribute.cs b/src/cs/g3d/Vim.G3d/GeometryAttribute.cs index dc0ce989..b9d424b9 100644 --- a/src/cs/g3d/Vim.G3d/GeometryAttribute.cs +++ b/src/cs/g3d/Vim.G3d/GeometryAttribute.cs @@ -4,7 +4,7 @@ using System.Linq; using Vim.LinqArray; using Vim.Math3d; -using Vim.BFastNS; +using Vim.BFastLib; namespace Vim.G3d { diff --git a/src/cs/g3d/Vim.G3dNext/G3dGenerated.g.cs b/src/cs/g3d/Vim.G3dNext/G3dGenerated.g.cs index b713c6b5..58b8569b 100644 --- a/src/cs/g3d/Vim.G3dNext/G3dGenerated.g.cs +++ b/src/cs/g3d/Vim.G3dNext/G3dGenerated.g.cs @@ -1,6 +1,6 @@ // AUTO-GENERATED FILE, DO NOT MODIFY. // ReSharper disable All -using Vim.BFastNS; +using Vim.BFastLib; namespace Vim.G3dNext { @@ -287,7 +287,7 @@ public G3dMaterials(BFast bfast) (this as ISetup).Setup(); } - public BFast ToBFast() + public Vim.BFastLib.BFast ToBFast() { var bfast = new BFast(); diff --git a/src/cs/g3d/Vim.G3dNext/G3dVim.cs b/src/cs/g3d/Vim.G3dNext/G3dVim.cs index b2efc947..b014bd35 100644 --- a/src/cs/g3d/Vim.G3dNext/G3dVim.cs +++ b/src/cs/g3d/Vim.G3dNext/G3dVim.cs @@ -1,6 +1,6 @@ using System; using System.Collections.Generic; -using Vim.BFastNS; +using Vim.BFastLib; namespace Vim.G3dNext { diff --git a/src/cs/vim/Vim.Format.Core/AssetInfo.cs b/src/cs/vim/Vim.Format.Core/AssetInfo.cs index 7d07297a..009d7d37 100644 --- a/src/cs/vim/Vim.Format.Core/AssetInfo.cs +++ b/src/cs/vim/Vim.Format.Core/AssetInfo.cs @@ -3,7 +3,7 @@ using System.IO; using Vim.Util; using Vim.LinqArray; -using Vim.BFastNS; +using Vim.BFastLib; namespace Vim.Format { diff --git a/src/cs/vim/Vim.Format.Core/ColumnExtensions.Buffer.cs b/src/cs/vim/Vim.Format.Core/ColumnExtensions.Buffer.cs index ecd6f52a..0b213bd8 100644 --- a/src/cs/vim/Vim.Format.Core/ColumnExtensions.Buffer.cs +++ b/src/cs/vim/Vim.Format.Core/ColumnExtensions.Buffer.cs @@ -3,7 +3,7 @@ using System.Diagnostics; using System.Linq; using Vim.LinqArray; -using Vim.BFastNS; +using Vim.BFastLib; namespace Vim.Format { diff --git a/src/cs/vim/Vim.Format.Core/Document.cs b/src/cs/vim/Vim.Format.Core/Document.cs index cf70001a..8465ea7d 100644 --- a/src/cs/vim/Vim.Format.Core/Document.cs +++ b/src/cs/vim/Vim.Format.Core/Document.cs @@ -1,5 +1,5 @@ using Vim.LinqArray; -using Vim.BFastNS; +using Vim.BFastLib; namespace Vim.Format { diff --git a/src/cs/vim/Vim.Format.Core/DocumentBuilder.cs b/src/cs/vim/Vim.Format.Core/DocumentBuilder.cs index 371c41e9..d90c1d6a 100644 --- a/src/cs/vim/Vim.Format.Core/DocumentBuilder.cs +++ b/src/cs/vim/Vim.Format.Core/DocumentBuilder.cs @@ -3,7 +3,7 @@ using System.Diagnostics; using System.Linq; using Vim.Math3d; -using Vim.BFastNS; +using Vim.BFastLib; using System.IO; using Vim.Util; diff --git a/src/cs/vim/Vim.Format.Core/DocumentBuilderExtensions.cs b/src/cs/vim/Vim.Format.Core/DocumentBuilderExtensions.cs index 1a374667..927dea1f 100644 --- a/src/cs/vim/Vim.Format.Core/DocumentBuilderExtensions.cs +++ b/src/cs/vim/Vim.Format.Core/DocumentBuilderExtensions.cs @@ -1,11 +1,11 @@ using System.Collections.Generic; using System.Linq; -using Vim.BFastNS; +using Vim.BFastLib; using Vim.Format.Geometry; using Vim.G3d; using Vim.LinqArray; using static Vim.Format.DocumentBuilder; -using Vim.BFastNS; +using Vim.BFastLib; namespace Vim.Format { diff --git a/src/cs/vim/Vim.Format.Core/DocumentExtensions.cs b/src/cs/vim/Vim.Format.Core/DocumentExtensions.cs index 23a53fbe..9d7a9cfd 100644 --- a/src/cs/vim/Vim.Format.Core/DocumentExtensions.cs +++ b/src/cs/vim/Vim.Format.Core/DocumentExtensions.cs @@ -1,7 +1,7 @@ using System; using System.Text.RegularExpressions; using Vim.LinqArray; -using Vim.BFastNS; +using Vim.BFastLib; namespace Vim.Format { diff --git a/src/cs/vim/Vim.Format.Core/EntityTable.cs b/src/cs/vim/Vim.Format.Core/EntityTable.cs index 86b73e01..d35097cc 100644 --- a/src/cs/vim/Vim.Format.Core/EntityTable.cs +++ b/src/cs/vim/Vim.Format.Core/EntityTable.cs @@ -1,6 +1,6 @@ using System; using Vim.LinqArray; -using Vim.BFastNS; +using Vim.BFastLib; namespace Vim.Format { diff --git a/src/cs/vim/Vim.Format.Core/EntityTableBuilder.cs b/src/cs/vim/Vim.Format.Core/EntityTableBuilder.cs index d5b60dd7..08582b99 100644 --- a/src/cs/vim/Vim.Format.Core/EntityTableBuilder.cs +++ b/src/cs/vim/Vim.Format.Core/EntityTableBuilder.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; -using Vim.BFastNS; +using Vim.BFastLib; namespace Vim.Format { diff --git a/src/cs/vim/Vim.Format.Core/G3dBuilder.cs b/src/cs/vim/Vim.Format.Core/G3dBuilder.cs index f5d39d48..258e1f52 100644 --- a/src/cs/vim/Vim.Format.Core/G3dBuilder.cs +++ b/src/cs/vim/Vim.Format.Core/G3dBuilder.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; using System.Linq; using Vim.G3d; -using Vim.BFastNS; +using Vim.BFastLib; using static Vim.Format.DocumentBuilder; using Vim.Math3d; diff --git a/src/cs/vim/Vim.Format.Core/Geometry/Validation.cs b/src/cs/vim/Vim.Format.Core/Geometry/Validation.cs index e984f61a..abf23eef 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/Validation.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/Validation.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using Vim.G3d; using Vim.LinqArray; -using Vim.BFastNS; +using Vim.BFastLib; namespace Vim.Format.Geometry { diff --git a/src/cs/vim/Vim.Format.Core/SerializableDocument.cs b/src/cs/vim/Vim.Format.Core/SerializableDocument.cs index a57ae7e9..948db855 100644 --- a/src/cs/vim/Vim.Format.Core/SerializableDocument.cs +++ b/src/cs/vim/Vim.Format.Core/SerializableDocument.cs @@ -3,8 +3,8 @@ using System.IO; using System.Linq; using System.Text; -using Vim.BFastNS; -using Vim.BFastNS.Core; +using Vim.BFastLib; +using Vim.BFastLib.Core; using Vim.G3d; namespace Vim.Format diff --git a/src/cs/vim/Vim.Format.Core/SerializableEntityTable.cs b/src/cs/vim/Vim.Format.Core/SerializableEntityTable.cs index 87c234c9..dd724bb9 100644 --- a/src/cs/vim/Vim.Format.Core/SerializableEntityTable.cs +++ b/src/cs/vim/Vim.Format.Core/SerializableEntityTable.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; using System.Linq; using System.Text.RegularExpressions; -using Vim.BFastNS; +using Vim.BFastLib; namespace Vim.Format { diff --git a/src/cs/vim/Vim.Format.Core/SerializableHeader.cs b/src/cs/vim/Vim.Format.Core/SerializableHeader.cs index c3e6a57d..41d076f2 100644 --- a/src/cs/vim/Vim.Format.Core/SerializableHeader.cs +++ b/src/cs/vim/Vim.Format.Core/SerializableHeader.cs @@ -3,7 +3,7 @@ using System.Globalization; using System.Linq; using System.Text; -using Vim.BFastNS; +using Vim.BFastLib; using Vim.Util; namespace Vim.Format diff --git a/src/cs/vim/Vim.Format.Core/Validation.cs b/src/cs/vim/Vim.Format.Core/Validation.cs index a16f9bc4..5419ef54 100644 --- a/src/cs/vim/Vim.Format.Core/Validation.cs +++ b/src/cs/vim/Vim.Format.Core/Validation.cs @@ -1,6 +1,6 @@ using System; using System.Collections.Generic; -using Vim.BFastNS; +using Vim.BFastLib; using Vim.G3d; using Vim.LinqArray; diff --git a/src/cs/vim/Vim.Format.Tests/FormatTests.cs b/src/cs/vim/Vim.Format.Tests/FormatTests.cs index 1cc20934..544469ff 100644 --- a/src/cs/vim/Vim.Format.Tests/FormatTests.cs +++ b/src/cs/vim/Vim.Format.Tests/FormatTests.cs @@ -2,7 +2,7 @@ using System.Linq; using NUnit.Framework; using Vim.LinqArray; -using Vim.BFastNS; +using Vim.BFastLib; namespace Vim.Format.Tests { diff --git a/src/cs/vim/Vim.Format.Vimx.Conversion/VimxConverter.cs b/src/cs/vim/Vim.Format.Vimx.Conversion/VimxConverter.cs index 55d72c09..f62b2731 100644 --- a/src/cs/vim/Vim.Format.Vimx.Conversion/VimxConverter.cs +++ b/src/cs/vim/Vim.Format.Vimx.Conversion/VimxConverter.cs @@ -1,6 +1,6 @@ using System.Linq; using Vim.LinqArray; -using Vim.BFastNS; +using Vim.BFastLib; using Vim.G3dNext; using Vim.Format.ObjectModel; using Vim.G3dNext; diff --git a/src/cs/vim/Vim.Format.Vimx/Vimx.cs b/src/cs/vim/Vim.Format.Vimx/Vimx.cs index 49da65c8..b49ed45c 100644 --- a/src/cs/vim/Vim.Format.Vimx/Vimx.cs +++ b/src/cs/vim/Vim.Format.Vimx/Vimx.cs @@ -1,5 +1,5 @@ using System.Linq; -using Vim.BFastNS; +using Vim.BFastLib; using Vim.G3dNext; namespace Vim.Format.VimxNS diff --git a/src/cs/vim/Vim.Format.Vimx/VimxChunk.cs b/src/cs/vim/Vim.Format.Vimx/VimxChunk.cs index 7303b49c..7f9127b4 100644 --- a/src/cs/vim/Vim.Format.Vimx/VimxChunk.cs +++ b/src/cs/vim/Vim.Format.Vimx/VimxChunk.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; using System.Linq; -using Vim.BFastNS; +using Vim.BFastLib; using Vim.G3dNext; namespace Vim.Format.VimxNS diff --git a/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs b/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs index adcdcc9b..66365bb4 100644 --- a/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs +++ b/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs @@ -3,7 +3,7 @@ using System.Linq; using System.Reflection; using System.Threading.Tasks; -using Vim.BFastNS; +using Vim.BFastLib; using Vim.Format.Geometry; using Vim.Format.ObjectModel; using Vim.Util; diff --git a/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs b/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs index 4a34a9da..6dc55869 100644 --- a/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs +++ b/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs @@ -10,7 +10,7 @@ using Vim.LinqArray; using Vim.Math3d; using IVimSceneProgress = System.IProgress<(string, double)>; -using Vim.BFastNS; +using Vim.BFastLib; namespace Vim { From a50271e47caef1350183b1651055139e7b7e429e Mon Sep 17 00:00:00 2001 From: simon Date: Mon, 12 Feb 2024 15:09:53 -0500 Subject: [PATCH 064/111] changed namespace suffix from NS to Lib --- src/cs/vim/Vim.Format.Vimx.Conversion/Chunking.cs | 2 +- src/cs/vim/Vim.Format.Vimx.Conversion/Ordering.cs | 2 +- src/cs/vim/Vim.Format.Vimx.Conversion/VimxConverter.cs | 2 +- src/cs/vim/Vim.Format.Vimx/Vimx.cs | 2 +- src/cs/vim/Vim.Format.Vimx/VimxChunk.cs | 2 +- src/cs/vim/Vim.Format.Vimx/VimxHeader.cs | 2 +- src/cs/vim/Vim.Vimx.Test/VimxActions.cs | 4 ++-- src/cs/vim/Vim.Vimx.Test/VimxTests.cs | 4 ++-- 8 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/cs/vim/Vim.Format.Vimx.Conversion/Chunking.cs b/src/cs/vim/Vim.Format.Vimx.Conversion/Chunking.cs index 91345b95..2e42bc8d 100644 --- a/src/cs/vim/Vim.Format.Vimx.Conversion/Chunking.cs +++ b/src/cs/vim/Vim.Format.Vimx.Conversion/Chunking.cs @@ -4,7 +4,7 @@ using Vim.Math3d; using Vim.G3dNext; -namespace Vim.Format.VimxNS.Conversion +namespace Vim.Format.VimxLib.Conversion { public static class Chunking { diff --git a/src/cs/vim/Vim.Format.Vimx.Conversion/Ordering.cs b/src/cs/vim/Vim.Format.Vimx.Conversion/Ordering.cs index 1bb4fb17..d079bf0b 100644 --- a/src/cs/vim/Vim.Format.Vimx.Conversion/Ordering.cs +++ b/src/cs/vim/Vim.Format.Vimx.Conversion/Ordering.cs @@ -2,7 +2,7 @@ using Vim.Format.ObjectModel; using Vim.G3dNext; -namespace Vim.Format.VimxNS.Conversion +namespace Vim.Format.VimxLib.Conversion { public static class Ordering { diff --git a/src/cs/vim/Vim.Format.Vimx.Conversion/VimxConverter.cs b/src/cs/vim/Vim.Format.Vimx.Conversion/VimxConverter.cs index f62b2731..31d3e45f 100644 --- a/src/cs/vim/Vim.Format.Vimx.Conversion/VimxConverter.cs +++ b/src/cs/vim/Vim.Format.Vimx.Conversion/VimxConverter.cs @@ -9,7 +9,7 @@ using System.Diagnostics; using System; -namespace Vim.Format.VimxNS.Conversion +namespace Vim.Format.VimxLib.Conversion { public static class VimxConverter { diff --git a/src/cs/vim/Vim.Format.Vimx/Vimx.cs b/src/cs/vim/Vim.Format.Vimx/Vimx.cs index b49ed45c..c74347f8 100644 --- a/src/cs/vim/Vim.Format.Vimx/Vimx.cs +++ b/src/cs/vim/Vim.Format.Vimx/Vimx.cs @@ -2,7 +2,7 @@ using Vim.BFastLib; using Vim.G3dNext; -namespace Vim.Format.VimxNS +namespace Vim.Format.VimxLib { public static class BufferNames { diff --git a/src/cs/vim/Vim.Format.Vimx/VimxChunk.cs b/src/cs/vim/Vim.Format.Vimx/VimxChunk.cs index 7f9127b4..fdfd6907 100644 --- a/src/cs/vim/Vim.Format.Vimx/VimxChunk.cs +++ b/src/cs/vim/Vim.Format.Vimx/VimxChunk.cs @@ -3,7 +3,7 @@ using Vim.BFastLib; using Vim.G3dNext; -namespace Vim.Format.VimxNS +namespace Vim.Format.VimxLib { public class VimxChunk { diff --git a/src/cs/vim/Vim.Format.Vimx/VimxHeader.cs b/src/cs/vim/Vim.Format.Vimx/VimxHeader.cs index 3ce69b58..d664ae58 100644 --- a/src/cs/vim/Vim.Format.Vimx/VimxHeader.cs +++ b/src/cs/vim/Vim.Format.Vimx/VimxHeader.cs @@ -1,7 +1,7 @@ using System.Text; using Vim.Util; -namespace Vim.Format.VimxNS +namespace Vim.Format.VimxLib { public static class VimxHeader { diff --git a/src/cs/vim/Vim.Vimx.Test/VimxActions.cs b/src/cs/vim/Vim.Vimx.Test/VimxActions.cs index 4b069e29..39ea9353 100644 --- a/src/cs/vim/Vim.Vimx.Test/VimxActions.cs +++ b/src/cs/vim/Vim.Vimx.Test/VimxActions.cs @@ -1,9 +1,9 @@ using NUnit.Framework; using System.Diagnostics; -using Vim.Format.VimxNS.Conversion; +using Vim.Format.VimxLib.Conversion; using Vim.Util.Tests; -namespace Vim.Format.VimxNS.Actions +namespace Vim.Format.VimxLib.Actions { [TestFixture] public static class VimxActions diff --git a/src/cs/vim/Vim.Vimx.Test/VimxTests.cs b/src/cs/vim/Vim.Vimx.Test/VimxTests.cs index fbd0393c..b851dd23 100644 --- a/src/cs/vim/Vim.Vimx.Test/VimxTests.cs +++ b/src/cs/vim/Vim.Vimx.Test/VimxTests.cs @@ -1,9 +1,9 @@ using NUnit.Framework; using NUnit.Framework.Internal; -using Vim.Format.VimxNS.Conversion; +using Vim.Format.VimxLib.Conversion; using Vim.Util.Tests; -namespace Vim.Format.VimxNS.Tests +namespace Vim.Format.VimxLib.Tests { [TestFixture] public static class VimxTests From 29923c720410b2ec81218f92abfdc0b131889999 Mon Sep 17 00:00:00 2001 From: simon Date: Mon, 12 Feb 2024 18:11:38 -0500 Subject: [PATCH 065/111] updated codegen --- src/cs/g3d/Vim.G3dNext.CodeGen/G3dCodeGen.cs | 2 +- src/cs/g3d/Vim.G3dNext/G3dGenerated.g.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cs/g3d/Vim.G3dNext.CodeGen/G3dCodeGen.cs b/src/cs/g3d/Vim.G3dNext.CodeGen/G3dCodeGen.cs index f092be93..5724b22f 100644 --- a/src/cs/g3d/Vim.G3dNext.CodeGen/G3dCodeGen.cs +++ b/src/cs/g3d/Vim.G3dNext.CodeGen/G3dCodeGen.cs @@ -14,7 +14,7 @@ public static void WriteDocument(string filePath) cb.AppendLine("// AUTO-GENERATED FILE, DO NOT MODIFY."); cb.AppendLine("// ReSharper disable All"); - cb.AppendLine("using Vim.BFastNS;"); + cb.AppendLine("using Vim.BFastLib;"); cb.AppendLine(); cb.AppendLine("namespace Vim.G3dNext"); cb.AppendLine("{"); diff --git a/src/cs/g3d/Vim.G3dNext/G3dGenerated.g.cs b/src/cs/g3d/Vim.G3dNext/G3dGenerated.g.cs index 58b8569b..5d2a7b8d 100644 --- a/src/cs/g3d/Vim.G3dNext/G3dGenerated.g.cs +++ b/src/cs/g3d/Vim.G3dNext/G3dGenerated.g.cs @@ -287,7 +287,7 @@ public G3dMaterials(BFast bfast) (this as ISetup).Setup(); } - public Vim.BFastLib.BFast ToBFast() + public BFast ToBFast() { var bfast = new BFast(); From b4cfbfee610508ce6f939fb7c97c5d4cb28bd74b Mon Sep 17 00:00:00 2001 From: simon Date: Tue, 13 Feb 2024 02:12:03 -0500 Subject: [PATCH 066/111] BFast now throws when trying to convert invalid data to bfast --- src/cs/bfast/Vim.BFast.Tests/BFastTests.cs | 43 +++++++++++++------ src/cs/bfast/Vim.BFast/BFast/BFast.cs | 7 +-- .../bfast/Vim.BFast/BFast/BFastArrayNode.cs | 7 +-- .../Vim.BFast/BFast/BFastEnumerableNode.cs | 4 +- .../bfast/Vim.BFast/BFast/BFastStreamNode.cs | 5 +-- .../bfast/Vim.BFast/BFast/CompressibleNode.cs | 33 +++++++++++--- 6 files changed, 69 insertions(+), 30 deletions(-) diff --git a/src/cs/bfast/Vim.BFast.Tests/BFastTests.cs b/src/cs/bfast/Vim.BFast.Tests/BFastTests.cs index 931e6609..e3dec5b1 100644 --- a/src/cs/bfast/Vim.BFast.Tests/BFastTests.cs +++ b/src/cs/bfast/Vim.BFast.Tests/BFastTests.cs @@ -177,10 +177,12 @@ public void SetEnumerable_Then_GetArray_Float() } [Test] - public void SetEnumerable_Then_GetBFast() + public void SetEnumerable_Then_GetBFast_Throws() { bfast.SetEnumerable("A", () => new int[3] { 0, 1, 2 }); - TestBeforeAfter(b => b.GetBFast("A"), Is.Null); + TestBeforeAfter(b => { + Assert.That(() => b.GetBFast("A"), Throws.Exception); + }); } [Test] @@ -273,10 +275,12 @@ public void SetArray_Then_GetEnumerable_Float() } [Test] - public void SetArray_Then_GetBFast_Returns_Null() + public void SetArray_Then_GetBFast_Throws() { bfast.SetArray("A", new int[3] { 0, 1, 2 }); - TestBeforeAfter(b => b.GetBFast("A"), Is.Null); + TestBeforeAfter(b => { + Assert.That(() => b.GetBFast("A"), Throws.Exception); + }); } [Test] @@ -286,7 +290,10 @@ public void SetArray_Then_SetArray_Replaces() var floats = new float[3] { 0.1f, 0.2f, 0.3f }; bfast.SetArray("A", ints); bfast.SetArray("A", floats); - TestBeforeAfter(b => b.GetArray("A"), Is.EqualTo(floats)); + TestBeforeAfter(b => { + Assert.That(b.GetArray("A"), Is.EqualTo(floats)); + Assert.That(b.GetArray("A"), Is.Not.EqualTo(ints)); + }); } [Test] @@ -294,7 +301,12 @@ public void SetArray_Then_SetBFast_Replaces() { bfast.SetArray("A", new int[3] { 0, 1, 2 }); bfast.SetBFast("A", new BFast()); - TestBeforeAfter(b => b.GetArray("A").Length, Is.GreaterThan(3)); + TestBeforeAfter(b => + { + // That's the bfast read as an ints. + Assert.That(b.GetArray("A").Length, Is.GreaterThan(3)); + Assert.That(b.GetBFast("A"), Is.EqualTo(new BFast())); + }); } #endregion @@ -335,11 +347,14 @@ public void SetBFast_Then_GetBFast_Nested() #region compress [Test] - public void Compression_Decompress_Uncompressed_Returns_Null() + public void Compression_Decompress_Uncompressed_Returns_Throws() { var expected = new BFast(); bfast.SetBFast("A", expected); - TestBeforeAfter(b => b.GetBFast("A", decompress: true), Is.Null); + TestBeforeAfter(b => + { + Assert.That(() => b.GetBFast("A", decompress: true), Throws.Exception); + }); } [Test] @@ -347,7 +362,10 @@ public void Compression_Get_Compressed_Returns_Null() { var expected = new BFast(); bfast.SetBFast("A", expected, compress: true); - TestBeforeAfter(b => b.GetBFast("A"), Is.Null); + TestBeforeAfter(b => + { + Assert.That(() => b.GetBFast("A"), Throws.Exception); + }); } [Test] @@ -400,12 +418,13 @@ public void SetBFast_Then_SetBFast_Replaces() [Test] public void SetBFast_Then_SetArray_Replaces() { + var ints = new int[3] { 0, 1, 2 }; bfast.SetBFast("A", new BFast()); - bfast.SetArray("A", new int[3] { 0, 1, 2 }); + bfast.SetArray("A", ints); TestBeforeAfter((b) => { - var result = b.GetBFast("A"); - Assert.IsNull(result); + Assert.That(() => b.GetBFast("A"), Throws.Exception); + Assert.That(b.GetArray("A"), Is.EqualTo(ints)); }); } diff --git a/src/cs/bfast/Vim.BFast/BFast/BFast.cs b/src/cs/bfast/Vim.BFast/BFast/BFast.cs index 281269f2..ad5508b0 100644 --- a/src/cs/bfast/Vim.BFast/BFast/BFast.cs +++ b/src/cs/bfast/Vim.BFast/BFast/BFast.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Xml.Linq; using Vim.BFastLib.Core; namespace Vim.BFastLib @@ -57,20 +58,20 @@ public BFast GetBFast(string name, bool decompress = false) { var node = GetNode(name); if (node == null) return null; - var n = decompress ? node.Decompress() : node.Node; + var n = node.GetNode(decompress); return n.AsBFast(); } public IEnumerable GetEnumerable(string name) where T : unmanaged { if (!_children.ContainsKey(name)) return null; - return _children[name].Node.AsEnumerable(); + return _children[name].GetNode().AsEnumerable(); } public T[] GetArray(string name) where T : unmanaged { if (!_children.ContainsKey(name)) return null; - return _children[name].Node.AsArray(); + return _children[name].GetNode().AsArray(); } public CompressibleNode GetNode(string name) diff --git a/src/cs/bfast/Vim.BFast/BFast/BFastArrayNode.cs b/src/cs/bfast/Vim.BFast/BFast/BFastArrayNode.cs index df7e11f0..617effdd 100644 --- a/src/cs/bfast/Vim.BFast/BFast/BFastArrayNode.cs +++ b/src/cs/bfast/Vim.BFast/BFast/BFastArrayNode.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.IO; namespace Vim.BFastLib @@ -27,9 +28,9 @@ public BFast AsBFast() { return new BFast(_array.ToMemoryStream()); } - catch + catch (Exception e) { - return null; + throw new Exception("Array data is not a valid BFast.", e); } } diff --git a/src/cs/bfast/Vim.BFast/BFast/BFastEnumerableNode.cs b/src/cs/bfast/Vim.BFast/BFast/BFastEnumerableNode.cs index bcca6a47..978969a1 100644 --- a/src/cs/bfast/Vim.BFast/BFast/BFastEnumerableNode.cs +++ b/src/cs/bfast/Vim.BFast/BFast/BFastEnumerableNode.cs @@ -32,9 +32,9 @@ public BFast AsBFast() { return new BFast(_source().ToMemoryStream()); } - catch + catch (Exception e) { - return null; + throw new Exception("Enumerable data is not a valid BFast", e); } } public IEnumerable AsEnumerable() where T : unmanaged diff --git a/src/cs/bfast/Vim.BFast/BFast/BFastStreamNode.cs b/src/cs/bfast/Vim.BFast/BFast/BFastStreamNode.cs index e4833c3c..75065c04 100644 --- a/src/cs/bfast/Vim.BFast/BFast/BFastStreamNode.cs +++ b/src/cs/bfast/Vim.BFast/BFast/BFastStreamNode.cs @@ -23,10 +23,9 @@ public BFast AsBFast() { return new BFast(_stream); } - catch + catch (Exception e) { - // It is expected most buffers are not valid bfasts. - return null; + throw new Exception("Requested data is not a valid BFast or is compressed and needs decompression.", e); } } diff --git a/src/cs/bfast/Vim.BFast/BFast/CompressibleNode.cs b/src/cs/bfast/Vim.BFast/BFast/CompressibleNode.cs index e8264794..c4a36fb9 100644 --- a/src/cs/bfast/Vim.BFast/BFast/CompressibleNode.cs +++ b/src/cs/bfast/Vim.BFast/BFast/CompressibleNode.cs @@ -6,12 +6,12 @@ namespace Vim.BFastLib { public class CompressibleNode : IWritable { - public readonly IBFastNode Node; + private readonly IBFastNode _node; private readonly bool _compress; public CompressibleNode(IBFastNode node, bool compress = false) { - Node = node; + _node = node; _compress = compress; } @@ -23,18 +23,37 @@ public void Write(Stream stream) } else { - Node.Write(stream); + _node.Write(stream); } } - public IBFastNode Decompress() + public IBFastNode GetNode(bool decompress = false) { - if (!(Node is BFastStreamNode)) return Node; + if (decompress) + { + if (_node is BFastStreamNode) + { + return Decompress(); + } + if (!_compress) + { + throw new System.Exception("Cannot uncompress a non-compressed node."); + } + return _node; + } + if(_compress) + { + throw new System.Exception("Compressed node needs to be decompressed."); + } + return _node; + } + private IBFastNode Decompress() + { var output = new MemoryStream(); using (var input = new MemoryStream()) { - Node.Write(input); + _node.Write(input); input.Seek(0, SeekOrigin.Begin); using (var compress = new DeflateStream(input, CompressionMode.Decompress, true)) { @@ -47,7 +66,7 @@ public IBFastNode Decompress() private void WriteCompress(Stream stream) { - using (var input = Node.ToMemoryStream()) + using (var input = _node.ToMemoryStream()) using (var compress = new DeflateStream(stream, CompressionMode.Compress, true)) { input.CopyTo(compress); From 3f0dae2d5c7a88e20f5707e4220fe9c302fb8330 Mon Sep 17 00:00:00 2001 From: simon Date: Tue, 13 Feb 2024 13:21:48 -0500 Subject: [PATCH 067/111] handle padding in existing vims --- src/cs/bfast/Vim.BFast/Core/BFastHeader.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/cs/bfast/Vim.BFast/Core/BFastHeader.cs b/src/cs/bfast/Vim.BFast/Core/BFastHeader.cs index bed271b6..a64fc2b9 100644 --- a/src/cs/bfast/Vim.BFast/Core/BFastHeader.cs +++ b/src/cs/bfast/Vim.BFast/Core/BFastHeader.cs @@ -21,14 +21,19 @@ public BFastHeader(BFastPreamble preamble, Dictionary ranges /// public static BFastHeader FromStream(Stream stream) { + if (stream.Length - stream.Position < sizeof(long) * 4) throw new Exception("Stream too short"); - var preamble = stream.ReadValue(); + var offset = stream.Position; + var preamble = stream.ReadValue(); var ranges = stream.ReadArray((int)preamble.NumArrays); + // In a lot of existing vim there is padding before the first buffer. + stream.Seek(offset + ranges[0].Begin, SeekOrigin.Begin); var nameBytes = stream.ReadArray((int)ranges[0].Count); + var names = BFastStrings.Unpack(nameBytes); var map = names .Zip(ranges.Skip(1), (n, r) => (n, r)) From a8d0f523cdfd67af8013b51b751bc862ae272375 Mon Sep 17 00:00:00 2001 From: simon Date: Tue, 13 Feb 2024 13:43:39 -0500 Subject: [PATCH 068/111] check that names are distincts --- src/cs/bfast/Vim.BFast/Core/BFastHeader.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/cs/bfast/Vim.BFast/Core/BFastHeader.cs b/src/cs/bfast/Vim.BFast/Core/BFastHeader.cs index a64fc2b9..8922cea1 100644 --- a/src/cs/bfast/Vim.BFast/Core/BFastHeader.cs +++ b/src/cs/bfast/Vim.BFast/Core/BFastHeader.cs @@ -21,7 +21,6 @@ public BFastHeader(BFastPreamble preamble, Dictionary ranges /// public static BFastHeader FromStream(Stream stream) { - if (stream.Length - stream.Position < sizeof(long) * 4) throw new Exception("Stream too short"); @@ -33,8 +32,13 @@ public static BFastHeader FromStream(Stream stream) // In a lot of existing vim there is padding before the first buffer. stream.Seek(offset + ranges[0].Begin, SeekOrigin.Begin); var nameBytes = stream.ReadArray((int)ranges[0].Count); - var names = BFastStrings.Unpack(nameBytes); + + if (names.Distinct().Count() < names.Length) + { + throw new Exception($"Buffer names should be unique. It contains duplicates. " + string.Join(",", names)); + } + var map = names .Zip(ranges.Skip(1), (n, r) => (n, r)) .ToDictionary(p => p.n, p => p.r); From 95523d36327646f1c441d8aae6534e3f53967759 Mon Sep 17 00:00:00 2001 From: simon Date: Tue, 13 Feb 2024 14:46:12 -0500 Subject: [PATCH 069/111] changed path \ to / --- src/cs/Vim.G3dNext.Tests/Vim.G3dNext.Tests.csproj | 6 +++--- .../bfast/Vim.BFast.Tests/Vim.BFast.Tests.csproj | 4 ++-- src/cs/g3d/Vim.G3d.Tests/Vim.G3d.Tests.csproj | 4 ++-- src/cs/g3d/Vim.G3d/Vim.G3d.csproj | 8 ++++---- src/cs/g3d/Vim.G3d/Vim.G3dNext.csproj | 14 -------------- .../Vim.G3dNext.CodeGen/Vim.G3dNext.CodeGen.csproj | 2 +- .../g3d/Vim.G3dNext.Tests/Vim.G3dNext.Tests.csproj | 6 +++--- src/cs/g3d/Vim.G3dNext/Vim.G3dNext.csproj | 4 ++-- .../Vim.LinqArray.Tests/Vim.LinqArray.Tests.csproj | 2 +- .../linqarray/Vim.LinqArray/Vim.LinqArray.csproj | 2 +- .../Vim.Math3D.Tests/Vim.Math3D.Tests.csproj | 2 +- src/cs/math3d/Vim.Math3D/Vim.Math3D.csproj | 2 +- .../Vim.Util.Logging.Serilog.csproj | 2 +- src/cs/util/Vim.Util.Tests/Vim.Util.Tests.csproj | 6 +++--- .../Vim.Format.CodeGen/Vim.Format.CodeGen.csproj | 6 +++--- src/cs/vim/Vim.Format.Core/Vim.Format.Core.csproj | 10 +++++----- .../vim/Vim.Format.Tests/Vim.Format.Tests.csproj | 4 ++-- .../Vim.Format.Vimx.Conversion.csproj | 8 ++++---- src/cs/vim/Vim.Format.Vimx/Vim.Format.Vimx.csproj | 8 ++++---- src/cs/vim/Vim.Format/Vim.Format.csproj | 10 +++++----- .../vim/Vim.Vimx.Test/Vim.Format.Vimx.Test.csproj | 10 +++++----- 21 files changed, 53 insertions(+), 67 deletions(-) delete mode 100644 src/cs/g3d/Vim.G3d/Vim.G3dNext.csproj diff --git a/src/cs/Vim.G3dNext.Tests/Vim.G3dNext.Tests.csproj b/src/cs/Vim.G3dNext.Tests/Vim.G3dNext.Tests.csproj index e11e95ad..f3342e58 100644 --- a/src/cs/Vim.G3dNext.Tests/Vim.G3dNext.Tests.csproj +++ b/src/cs/Vim.G3dNext.Tests/Vim.G3dNext.Tests.csproj @@ -16,9 +16,9 @@ - - - + + + diff --git a/src/cs/bfast/Vim.BFast.Tests/Vim.BFast.Tests.csproj b/src/cs/bfast/Vim.BFast.Tests/Vim.BFast.Tests.csproj index 98f7f7a7..b53eefb7 100644 --- a/src/cs/bfast/Vim.BFast.Tests/Vim.BFast.Tests.csproj +++ b/src/cs/bfast/Vim.BFast.Tests/Vim.BFast.Tests.csproj @@ -16,8 +16,8 @@ - - + + diff --git a/src/cs/g3d/Vim.G3d.Tests/Vim.G3d.Tests.csproj b/src/cs/g3d/Vim.G3d.Tests/Vim.G3d.Tests.csproj index e5fca662..63df1e99 100644 --- a/src/cs/g3d/Vim.G3d.Tests/Vim.G3d.Tests.csproj +++ b/src/cs/g3d/Vim.G3d.Tests/Vim.G3d.Tests.csproj @@ -14,8 +14,8 @@ - - + + diff --git a/src/cs/g3d/Vim.G3d/Vim.G3d.csproj b/src/cs/g3d/Vim.G3d/Vim.G3d.csproj index 7f4cdcb4..47cee1d3 100644 --- a/src/cs/g3d/Vim.G3d/Vim.G3d.csproj +++ b/src/cs/g3d/Vim.G3d/Vim.G3d.csproj @@ -19,7 +19,7 @@ It can be easily and efficiently deserialized and rendered in different language - + True @@ -48,9 +48,9 @@ It can be easily and efficiently deserialized and rendered in different language - - - + + + diff --git a/src/cs/g3d/Vim.G3d/Vim.G3dNext.csproj b/src/cs/g3d/Vim.G3d/Vim.G3dNext.csproj deleted file mode 100644 index 379ef62d..00000000 --- a/src/cs/g3d/Vim.G3d/Vim.G3dNext.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - netstandard2.0 - - - - - - - - diff --git a/src/cs/g3d/Vim.G3dNext.CodeGen/Vim.G3dNext.CodeGen.csproj b/src/cs/g3d/Vim.G3dNext.CodeGen/Vim.G3dNext.CodeGen.csproj index cf094d6c..69dc732d 100644 --- a/src/cs/g3d/Vim.G3dNext.CodeGen/Vim.G3dNext.CodeGen.csproj +++ b/src/cs/g3d/Vim.G3dNext.CodeGen/Vim.G3dNext.CodeGen.csproj @@ -11,7 +11,7 @@ - + diff --git a/src/cs/g3d/Vim.G3dNext.Tests/Vim.G3dNext.Tests.csproj b/src/cs/g3d/Vim.G3dNext.Tests/Vim.G3dNext.Tests.csproj index 7cc5875b..913affa1 100644 --- a/src/cs/g3d/Vim.G3dNext.Tests/Vim.G3dNext.Tests.csproj +++ b/src/cs/g3d/Vim.G3dNext.Tests/Vim.G3dNext.Tests.csproj @@ -12,9 +12,9 @@ - - - + + + diff --git a/src/cs/g3d/Vim.G3dNext/Vim.G3dNext.csproj b/src/cs/g3d/Vim.G3dNext/Vim.G3dNext.csproj index b411b844..0b3a84d9 100644 --- a/src/cs/g3d/Vim.G3dNext/Vim.G3dNext.csproj +++ b/src/cs/g3d/Vim.G3dNext/Vim.G3dNext.csproj @@ -9,8 +9,8 @@ - - + + diff --git a/src/cs/linqarray/Vim.LinqArray.Tests/Vim.LinqArray.Tests.csproj b/src/cs/linqarray/Vim.LinqArray.Tests/Vim.LinqArray.Tests.csproj index fb957c18..09cce693 100644 --- a/src/cs/linqarray/Vim.LinqArray.Tests/Vim.LinqArray.Tests.csproj +++ b/src/cs/linqarray/Vim.LinqArray.Tests/Vim.LinqArray.Tests.csproj @@ -12,7 +12,7 @@ - + diff --git a/src/cs/linqarray/Vim.LinqArray/Vim.LinqArray.csproj b/src/cs/linqarray/Vim.LinqArray/Vim.LinqArray.csproj index 110fabe9..8993be59 100644 --- a/src/cs/linqarray/Vim.LinqArray/Vim.LinqArray.csproj +++ b/src/cs/linqarray/Vim.LinqArray/Vim.LinqArray.csproj @@ -27,7 +27,7 @@ - + True diff --git a/src/cs/math3d/Vim.Math3D.Tests/Vim.Math3D.Tests.csproj b/src/cs/math3d/Vim.Math3D.Tests/Vim.Math3D.Tests.csproj index a6f30d42..4cca0b39 100644 --- a/src/cs/math3d/Vim.Math3D.Tests/Vim.Math3D.Tests.csproj +++ b/src/cs/math3d/Vim.Math3D.Tests/Vim.Math3D.Tests.csproj @@ -12,7 +12,7 @@ - + diff --git a/src/cs/math3d/Vim.Math3D/Vim.Math3D.csproj b/src/cs/math3d/Vim.Math3D/Vim.Math3D.csproj index b2138f57..13897683 100644 --- a/src/cs/math3d/Vim.Math3D/Vim.Math3D.csproj +++ b/src/cs/math3d/Vim.Math3D/Vim.Math3D.csproj @@ -62,7 +62,7 @@ - + True diff --git a/src/cs/util/Vim.Util.Logging.Serilog/Vim.Util.Logging.Serilog.csproj b/src/cs/util/Vim.Util.Logging.Serilog/Vim.Util.Logging.Serilog.csproj index 31723bd0..f1fe7e5b 100644 --- a/src/cs/util/Vim.Util.Logging.Serilog/Vim.Util.Logging.Serilog.csproj +++ b/src/cs/util/Vim.Util.Logging.Serilog/Vim.Util.Logging.Serilog.csproj @@ -12,7 +12,7 @@ - + diff --git a/src/cs/util/Vim.Util.Tests/Vim.Util.Tests.csproj b/src/cs/util/Vim.Util.Tests/Vim.Util.Tests.csproj index 88f0d49e..07c8b634 100644 --- a/src/cs/util/Vim.Util.Tests/Vim.Util.Tests.csproj +++ b/src/cs/util/Vim.Util.Tests/Vim.Util.Tests.csproj @@ -15,9 +15,9 @@ - - - + + + diff --git a/src/cs/vim/Vim.Format.CodeGen/Vim.Format.CodeGen.csproj b/src/cs/vim/Vim.Format.CodeGen/Vim.Format.CodeGen.csproj index ec673b10..b0d25f82 100644 --- a/src/cs/vim/Vim.Format.CodeGen/Vim.Format.CodeGen.csproj +++ b/src/cs/vim/Vim.Format.CodeGen/Vim.Format.CodeGen.csproj @@ -8,7 +8,7 @@ OnOutputUpdated - + @@ -16,8 +16,8 @@ - - + + diff --git a/src/cs/vim/Vim.Format.Core/Vim.Format.Core.csproj b/src/cs/vim/Vim.Format.Core/Vim.Format.Core.csproj index d845180e..2dee6267 100644 --- a/src/cs/vim/Vim.Format.Core/Vim.Format.Core.csproj +++ b/src/cs/vim/Vim.Format.Core/Vim.Format.Core.csproj @@ -7,11 +7,11 @@ - - - - - + + + + + diff --git a/src/cs/vim/Vim.Format.Tests/Vim.Format.Tests.csproj b/src/cs/vim/Vim.Format.Tests/Vim.Format.Tests.csproj index 0badffcf..9fbd7fdf 100644 --- a/src/cs/vim/Vim.Format.Tests/Vim.Format.Tests.csproj +++ b/src/cs/vim/Vim.Format.Tests/Vim.Format.Tests.csproj @@ -16,8 +16,8 @@ - - + + diff --git a/src/cs/vim/Vim.Format.Vimx.Conversion/Vim.Format.Vimx.Conversion.csproj b/src/cs/vim/Vim.Format.Vimx.Conversion/Vim.Format.Vimx.Conversion.csproj index 76983d94..1ea6cd4f 100644 --- a/src/cs/vim/Vim.Format.Vimx.Conversion/Vim.Format.Vimx.Conversion.csproj +++ b/src/cs/vim/Vim.Format.Vimx.Conversion/Vim.Format.Vimx.Conversion.csproj @@ -5,10 +5,10 @@ - - - - + + + + diff --git a/src/cs/vim/Vim.Format.Vimx/Vim.Format.Vimx.csproj b/src/cs/vim/Vim.Format.Vimx/Vim.Format.Vimx.csproj index dce33c13..cce7a46e 100644 --- a/src/cs/vim/Vim.Format.Vimx/Vim.Format.Vimx.csproj +++ b/src/cs/vim/Vim.Format.Vimx/Vim.Format.Vimx.csproj @@ -9,10 +9,10 @@ - - - - + + + + diff --git a/src/cs/vim/Vim.Format/Vim.Format.csproj b/src/cs/vim/Vim.Format/Vim.Format.csproj index 5d73fc41..8b279fa0 100644 --- a/src/cs/vim/Vim.Format/Vim.Format.csproj +++ b/src/cs/vim/Vim.Format/Vim.Format.csproj @@ -18,11 +18,11 @@ - - - - - + + + + + -The official reference implementation of BFAST is written in C# and targets .NET Standard 2.0. The C# -test suite uses NUnit and targets .NET Core 2.1. At VIM AEC we are using BFAST in production code that -targets Unity 2019.1 and .NET Framework 4.7.1. - -There is currently a C++ encoder and a JavaScript decoder implementation under development, but they -are not tested and supported yet. \ No newline at end of file From 5ed7681543fd33609a92e6d15587aa73ed924264 Mon Sep 17 00:00:00 2001 From: simon Date: Fri, 16 Feb 2024 11:21:34 -0500 Subject: [PATCH 080/111] added licence to all project --- src/cs/Vim.G3dNext.Tests/Vim.G3dNext.Tests.csproj | 5 +++++ src/cs/bfast/Vim.BFast.Tests/Vim.BFast.Tests.csproj | 5 +++++ src/cs/bfast/Vim.BFast/Vim.BFast.csproj | 6 +++++- .../g3d/Vim.G3d.AssimpWrapper/Vim.G3d.AssimpWrapper.csproj | 6 +++++- src/cs/g3d/Vim.G3d.Tests/Vim.G3d.Tests.csproj | 5 +++++ src/cs/g3d/Vim.G3dNext.CodeGen/Vim.G3dNext.CodeGen.csproj | 6 +++++- src/cs/g3d/Vim.G3dNext/Vim.G3dNext.csproj | 5 +++++ .../Vim.LinqArray.Tests/Vim.LinqArray.Tests.csproj | 5 +++++ src/cs/linqarray/Vim.LinqArray/Vim.LinqArray.csproj | 3 +-- src/cs/math3d/Vim.Math3D.Tests/Vim.Math3D.Tests.csproj | 5 +++++ src/cs/math3d/Vim.Math3D/Vim.Math3D.csproj | 5 ++--- .../Vim.Util.Logging.Serilog.csproj | 5 +++++ src/cs/util/Vim.Util.Tests/Vim.Util.Tests.csproj | 5 +++++ src/cs/util/Vim.Util/Vim.Util.csproj | 5 +++++ src/cs/vim/Vim.Format.CodeGen/Vim.Format.CodeGen.csproj | 5 +++++ src/cs/vim/Vim.Format.Core/Vim.Format.Core.csproj | 5 +++++ src/cs/vim/Vim.Format.Tests/Vim.Format.Tests.csproj | 5 +++++ .../Vim.Format.Vimx.Conversion.csproj | 5 +++++ src/cs/vim/Vim.Format.Vimx/Vim.Format.Vimx.csproj | 5 +++++ src/cs/vim/Vim.Format/Vim.Format.csproj | 5 +++++ src/cs/vim/Vim.Vimx.Test/Vim.Format.Vimx.Test.csproj | 5 +++++ 21 files changed, 98 insertions(+), 8 deletions(-) diff --git a/src/cs/Vim.G3dNext.Tests/Vim.G3dNext.Tests.csproj b/src/cs/Vim.G3dNext.Tests/Vim.G3dNext.Tests.csproj index f3342e58..188a58c3 100644 --- a/src/cs/Vim.G3dNext.Tests/Vim.G3dNext.Tests.csproj +++ b/src/cs/Vim.G3dNext.Tests/Vim.G3dNext.Tests.csproj @@ -20,5 +20,10 @@ + + + True + + diff --git a/src/cs/bfast/Vim.BFast.Tests/Vim.BFast.Tests.csproj b/src/cs/bfast/Vim.BFast.Tests/Vim.BFast.Tests.csproj index b53eefb7..5a73b0bc 100644 --- a/src/cs/bfast/Vim.BFast.Tests/Vim.BFast.Tests.csproj +++ b/src/cs/bfast/Vim.BFast.Tests/Vim.BFast.Tests.csproj @@ -8,6 +8,11 @@ false true + + + True + + diff --git a/src/cs/bfast/Vim.BFast/Vim.BFast.csproj b/src/cs/bfast/Vim.BFast/Vim.BFast.csproj index 7f22bfd6..646a78e8 100644 --- a/src/cs/bfast/Vim.BFast/Vim.BFast.csproj +++ b/src/cs/bfast/Vim.BFast/Vim.BFast.csproj @@ -4,5 +4,9 @@ netstandard2.0 true - + + + True + + diff --git a/src/cs/g3d/Vim.G3d.AssimpWrapper/Vim.G3d.AssimpWrapper.csproj b/src/cs/g3d/Vim.G3d.AssimpWrapper/Vim.G3d.AssimpWrapper.csproj index afd6d77d..9dd379f7 100644 --- a/src/cs/g3d/Vim.G3d.AssimpWrapper/Vim.G3d.AssimpWrapper.csproj +++ b/src/cs/g3d/Vim.G3d.AssimpWrapper/Vim.G3d.AssimpWrapper.csproj @@ -12,5 +12,9 @@ - + + + True + + diff --git a/src/cs/g3d/Vim.G3d.Tests/Vim.G3d.Tests.csproj b/src/cs/g3d/Vim.G3d.Tests/Vim.G3d.Tests.csproj index 63df1e99..9bbcc776 100644 --- a/src/cs/g3d/Vim.G3d.Tests/Vim.G3d.Tests.csproj +++ b/src/cs/g3d/Vim.G3d.Tests/Vim.G3d.Tests.csproj @@ -36,4 +36,9 @@ + + + True + + diff --git a/src/cs/g3d/Vim.G3dNext.CodeGen/Vim.G3dNext.CodeGen.csproj b/src/cs/g3d/Vim.G3dNext.CodeGen/Vim.G3dNext.CodeGen.csproj index 69dc732d..a5109829 100644 --- a/src/cs/g3d/Vim.G3dNext.CodeGen/Vim.G3dNext.CodeGen.csproj +++ b/src/cs/g3d/Vim.G3dNext.CodeGen/Vim.G3dNext.CodeGen.csproj @@ -17,5 +17,9 @@ - + + + True + + \ No newline at end of file diff --git a/src/cs/g3d/Vim.G3dNext/Vim.G3dNext.csproj b/src/cs/g3d/Vim.G3dNext/Vim.G3dNext.csproj index 0b3a84d9..6bcd3546 100644 --- a/src/cs/g3d/Vim.G3dNext/Vim.G3dNext.csproj +++ b/src/cs/g3d/Vim.G3dNext/Vim.G3dNext.csproj @@ -12,5 +12,10 @@ + + + True + + diff --git a/src/cs/linqarray/Vim.LinqArray.Tests/Vim.LinqArray.Tests.csproj b/src/cs/linqarray/Vim.LinqArray.Tests/Vim.LinqArray.Tests.csproj index 09cce693..a206263e 100644 --- a/src/cs/linqarray/Vim.LinqArray.Tests/Vim.LinqArray.Tests.csproj +++ b/src/cs/linqarray/Vim.LinqArray.Tests/Vim.LinqArray.Tests.csproj @@ -14,5 +14,10 @@ + + + True + + diff --git a/src/cs/linqarray/Vim.LinqArray/Vim.LinqArray.csproj b/src/cs/linqarray/Vim.LinqArray/Vim.LinqArray.csproj index 8993be59..73c2a6df 100644 --- a/src/cs/linqarray/Vim.LinqArray/Vim.LinqArray.csproj +++ b/src/cs/linqarray/Vim.LinqArray/Vim.LinqArray.csproj @@ -27,9 +27,8 @@ - + True - diff --git a/src/cs/math3d/Vim.Math3D.Tests/Vim.Math3D.Tests.csproj b/src/cs/math3d/Vim.Math3D.Tests/Vim.Math3D.Tests.csproj index 4cca0b39..b245bbb0 100644 --- a/src/cs/math3d/Vim.Math3D.Tests/Vim.Math3D.Tests.csproj +++ b/src/cs/math3d/Vim.Math3D.Tests/Vim.Math3D.Tests.csproj @@ -14,5 +14,10 @@ + + + True + + diff --git a/src/cs/math3d/Vim.Math3D/Vim.Math3D.csproj b/src/cs/math3d/Vim.Math3D/Vim.Math3D.csproj index 13897683..7ee3eb40 100644 --- a/src/cs/math3d/Vim.Math3D/Vim.Math3D.csproj +++ b/src/cs/math3d/Vim.Math3D/Vim.Math3D.csproj @@ -60,11 +60,10 @@ Structs.tt - + - + True - diff --git a/src/cs/util/Vim.Util.Logging.Serilog/Vim.Util.Logging.Serilog.csproj b/src/cs/util/Vim.Util.Logging.Serilog/Vim.Util.Logging.Serilog.csproj index f1fe7e5b..1ace7be0 100644 --- a/src/cs/util/Vim.Util.Logging.Serilog/Vim.Util.Logging.Serilog.csproj +++ b/src/cs/util/Vim.Util.Logging.Serilog/Vim.Util.Logging.Serilog.csproj @@ -15,4 +15,9 @@ + + + True + + diff --git a/src/cs/util/Vim.Util.Tests/Vim.Util.Tests.csproj b/src/cs/util/Vim.Util.Tests/Vim.Util.Tests.csproj index 07c8b634..b39a484c 100644 --- a/src/cs/util/Vim.Util.Tests/Vim.Util.Tests.csproj +++ b/src/cs/util/Vim.Util.Tests/Vim.Util.Tests.csproj @@ -38,5 +38,10 @@ + + + True + + diff --git a/src/cs/util/Vim.Util/Vim.Util.csproj b/src/cs/util/Vim.Util/Vim.Util.csproj index dbdcea46..a731a7c3 100644 --- a/src/cs/util/Vim.Util/Vim.Util.csproj +++ b/src/cs/util/Vim.Util/Vim.Util.csproj @@ -4,4 +4,9 @@ netstandard2.0 + + + True + + diff --git a/src/cs/vim/Vim.Format.CodeGen/Vim.Format.CodeGen.csproj b/src/cs/vim/Vim.Format.CodeGen/Vim.Format.CodeGen.csproj index b0d25f82..b22d814d 100644 --- a/src/cs/vim/Vim.Format.CodeGen/Vim.Format.CodeGen.csproj +++ b/src/cs/vim/Vim.Format.CodeGen/Vim.Format.CodeGen.csproj @@ -23,5 +23,10 @@ + + + True + + diff --git a/src/cs/vim/Vim.Format.Core/Vim.Format.Core.csproj b/src/cs/vim/Vim.Format.Core/Vim.Format.Core.csproj index 2dee6267..04bb0373 100644 --- a/src/cs/vim/Vim.Format.Core/Vim.Format.Core.csproj +++ b/src/cs/vim/Vim.Format.Core/Vim.Format.Core.csproj @@ -38,5 +38,10 @@ ArrayOps.tt + + + True + + diff --git a/src/cs/vim/Vim.Format.Tests/Vim.Format.Tests.csproj b/src/cs/vim/Vim.Format.Tests/Vim.Format.Tests.csproj index 9fbd7fdf..da9ad0f7 100644 --- a/src/cs/vim/Vim.Format.Tests/Vim.Format.Tests.csproj +++ b/src/cs/vim/Vim.Format.Tests/Vim.Format.Tests.csproj @@ -19,5 +19,10 @@ + + + True + + diff --git a/src/cs/vim/Vim.Format.Vimx.Conversion/Vim.Format.Vimx.Conversion.csproj b/src/cs/vim/Vim.Format.Vimx.Conversion/Vim.Format.Vimx.Conversion.csproj index 1ea6cd4f..0f7c97d0 100644 --- a/src/cs/vim/Vim.Format.Vimx.Conversion/Vim.Format.Vimx.Conversion.csproj +++ b/src/cs/vim/Vim.Format.Vimx.Conversion/Vim.Format.Vimx.Conversion.csproj @@ -10,5 +10,10 @@ + + + True + + diff --git a/src/cs/vim/Vim.Format.Vimx/Vim.Format.Vimx.csproj b/src/cs/vim/Vim.Format.Vimx/Vim.Format.Vimx.csproj index cce7a46e..6be989dd 100644 --- a/src/cs/vim/Vim.Format.Vimx/Vim.Format.Vimx.csproj +++ b/src/cs/vim/Vim.Format.Vimx/Vim.Format.Vimx.csproj @@ -14,5 +14,10 @@ + + + True + + diff --git a/src/cs/vim/Vim.Format/Vim.Format.csproj b/src/cs/vim/Vim.Format/Vim.Format.csproj index 8b279fa0..b7d17ede 100644 --- a/src/cs/vim/Vim.Format/Vim.Format.csproj +++ b/src/cs/vim/Vim.Format/Vim.Format.csproj @@ -44,5 +44,10 @@ + + + True + + diff --git a/src/cs/vim/Vim.Vimx.Test/Vim.Format.Vimx.Test.csproj b/src/cs/vim/Vim.Vimx.Test/Vim.Format.Vimx.Test.csproj index 7131b4e7..808fb736 100644 --- a/src/cs/vim/Vim.Vimx.Test/Vim.Format.Vimx.Test.csproj +++ b/src/cs/vim/Vim.Vimx.Test/Vim.Format.Vimx.Test.csproj @@ -22,5 +22,10 @@ + + + True + + From c345cd6228dee0385ac535f85aa5ce2c5c69782d Mon Sep 17 00:00:00 2001 From: simon Date: Wed, 21 Feb 2024 13:10:30 -0500 Subject: [PATCH 081/111] added folder src/ts/dist/ to git ignore --- src/ts/.gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ts/.gitignore b/src/ts/.gitignore index 460b930c..3964553f 100644 --- a/src/ts/.gitignore +++ b/src/ts/.gitignore @@ -1,2 +1,3 @@ node_modules/ +src/ts/dist/* *.d.ts \ No newline at end of file From 9c890d06feafe029537a9562a5f063670880a5be Mon Sep 17 00:00:00 2001 From: simon Date: Wed, 21 Feb 2024 13:10:53 -0500 Subject: [PATCH 082/111] removed useless using --- src/cs/vim/Vim.Format.Core/DocumentBuilderExtensions.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/cs/vim/Vim.Format.Core/DocumentBuilderExtensions.cs b/src/cs/vim/Vim.Format.Core/DocumentBuilderExtensions.cs index 927dea1f..77c0d209 100644 --- a/src/cs/vim/Vim.Format.Core/DocumentBuilderExtensions.cs +++ b/src/cs/vim/Vim.Format.Core/DocumentBuilderExtensions.cs @@ -5,7 +5,6 @@ using Vim.G3d; using Vim.LinqArray; using static Vim.Format.DocumentBuilder; -using Vim.BFastLib; namespace Vim.Format { From 4134b4f6cdf56ee4e75a26d23decfb5afba57c5d Mon Sep 17 00:00:00 2001 From: simon Date: Wed, 21 Feb 2024 13:11:01 -0500 Subject: [PATCH 083/111] renames --- src/cs/vim/Vim.Format.Core/SerializableDocument.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cs/vim/Vim.Format.Core/SerializableDocument.cs b/src/cs/vim/Vim.Format.Core/SerializableDocument.cs index b906cd45..75466197 100644 --- a/src/cs/vim/Vim.Format.Core/SerializableDocument.cs +++ b/src/cs/vim/Vim.Format.Core/SerializableDocument.cs @@ -122,7 +122,7 @@ private static IEnumerable GetEntityTables( foreach (var entry in bfast.Entries) { var b = bfast.GetBFast(entry); - var table = ReadEntityTable2(b, schemaOnly); + var table = ReadEntityTable(b, schemaOnly); table.Name = entry; yield return table; } @@ -131,7 +131,7 @@ private static IEnumerable GetEntityTables( /// /// Returns a SerializableEntityTable based on the given buffer reader. /// - public static SerializableEntityTable ReadEntityTable2( + public static SerializableEntityTable ReadEntityTable( BFast bfast, bool schemaOnly ) From d5cde87a0b91b49ab48be0ce3d885fc3faac1cf1 Mon Sep 17 00:00:00 2001 From: simon Date: Wed, 21 Feb 2024 13:11:20 -0500 Subject: [PATCH 084/111] Added Try versions of Get --- .../vim/Vim.Format/SceneBuilder/VimScene.cs | 67 ++++++++++++++++--- 1 file changed, 59 insertions(+), 8 deletions(-) diff --git a/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs b/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs index 6dc55869..9218a9ff 100644 --- a/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs +++ b/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs @@ -25,7 +25,27 @@ public class VimScene : IScene /// Returns the VIM file's header schema version. Returns null if the header schema is not found. /// public static string GetSchemaVersion(string path) - => string.IsNullOrEmpty(path) ? null : GetHeader(path)?.Schema?.ToString(); + { + return GetHeader(path).Schema.ToString(); + } + + /// + /// Returns the VIM file's header schema version. Returns null if the header schema is not found. + /// + public static bool TryGetSchemaVersion(string path, out string schema) + { + try + { + schema = GetSchemaVersion(path); + return true; + } + catch (Exception e) + { + Console.WriteLine(e); + schema = null; + return false; + } + } public static SerializableHeader GetHeader(string path) { @@ -35,6 +55,18 @@ public static SerializableHeader GetHeader(string path) } } + public static bool TryGetHeader(string path, out SerializableHeader header) + { + using (var file = new FileStream(path, FileMode.OpenOrCreate)) + { + return TryGetHeader(file, out header); + } + } + + /// + /// Returns the VIM header from a vim file stream. + /// Will throw if the file is not a valid VIM. + /// public static SerializableHeader GetHeader(Stream stream) { var bfast = new BFast(stream); @@ -43,6 +75,32 @@ public static SerializableHeader GetHeader(Stream stream) return SerializableHeader.FromBytes(bytes); } + /// + /// Returns true along along with the VIM header from a valid vim file stream. + /// Returns false and null and resets the stream at given position for invalid file. + /// + public static bool TryGetHeader(Stream stream, out SerializableHeader header) + { + var position = stream.Position; + try + { + header = GetHeader(stream); + return true; + } + catch (Exception e) + { + Console.WriteLine(e); + + if (stream.CanSeek) + { + stream.Seek(position, SeekOrigin.Begin); + } + + header = null; + return false; + } + } + public static VimScene LoadVim(string f, LoadOptions loadOptions, IVimSceneProgress progress = null, bool inParallel = false, int vimIndex = 0) => new VimScene(SerializableDocument.FromPath(f, loadOptions), progress, inParallel, vimIndex); @@ -52,13 +110,6 @@ public static VimScene LoadVim(string f, IVimSceneProgress progress = null, bool public static VimScene LoadVim(Stream stream, LoadOptions loadOptions, IVimSceneProgress progress = null, bool inParallel = false) => new VimScene(SerializableDocument.FromBFast(new BFast(stream), loadOptions), progress, inParallel); - public static VimScene LoadVim2(Stream stream, LoadOptions loadOptions = null, IVimSceneProgress progress = null, bool inParallel = false) - { - var bfast = new BFast(stream); - var doc = SerializableDocument.FromBFast(bfast, loadOptions); - return new VimScene(doc, progress, inParallel); - } - public static VimScene LoadVim(Stream stream, IVimSceneProgress progress = null, bool skipGeometry = false, bool skipAssets = false, bool skipNodes = false, bool inParallel = false) => LoadVim(stream, new LoadOptions { SkipGeometry = skipGeometry, SkipAssets = skipAssets}, progress, inParallel); From eb9b6d232afe57b2c4953e1cf45889f0eb20af16 Mon Sep 17 00:00:00 2001 From: simon Date: Wed, 21 Feb 2024 13:28:43 -0500 Subject: [PATCH 085/111] remove to rename --- license.txt | 21 --------------------- 1 file changed, 21 deletions(-) delete mode 100644 license.txt diff --git a/license.txt b/license.txt deleted file mode 100644 index 05d2550a..00000000 --- a/license.txt +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2023 VIMaec LLC. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. From 41537162a5b56f32259364a0d284a0b06bad1e7e Mon Sep 17 00:00:00 2001 From: simon Date: Wed, 21 Feb 2024 13:29:04 -0500 Subject: [PATCH 086/111] License with capital letters --- LICENSE.txt | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 LICENSE.txt diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 00000000..05d2550a --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 VIMaec LLC. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. From a4dd3bc9d10b95ae138bd0f0b34fd089712359bd Mon Sep 17 00:00:00 2001 From: simon Date: Wed, 21 Feb 2024 13:44:41 -0500 Subject: [PATCH 087/111] added attributes to all package license item --- src/cs/Vim.G3dNext.Tests/Vim.G3dNext.Tests.csproj | 1 + src/cs/bfast/Vim.BFast.Tests/Vim.BFast.Tests.csproj | 1 + src/cs/bfast/Vim.BFast/Vim.BFast.csproj | 4 ++++ src/cs/g3d/Vim.G3d.AssimpWrapper/Vim.G3d.AssimpWrapper.csproj | 1 + src/cs/g3d/Vim.G3d.Tests/Vim.G3d.Tests.csproj | 1 + src/cs/g3d/Vim.G3d/Vim.G3d.csproj | 1 + src/cs/g3d/Vim.G3dNext.CodeGen/Vim.G3dNext.CodeGen.csproj | 1 + src/cs/g3d/Vim.G3dNext/Vim.G3dNext.csproj | 1 + .../linqarray/Vim.LinqArray.Tests/Vim.LinqArray.Tests.csproj | 1 + src/cs/linqarray/Vim.LinqArray/Vim.LinqArray.csproj | 1 + src/cs/math3d/Vim.Math3D.Tests/Vim.Math3D.Tests.csproj | 1 + src/cs/math3d/Vim.Math3D/Vim.Math3D.csproj | 1 + .../Vim.Util.Logging.Serilog/Vim.Util.Logging.Serilog.csproj | 1 + src/cs/util/Vim.Util.Tests/Vim.Util.Tests.csproj | 1 + src/cs/util/Vim.Util/Vim.Util.csproj | 1 + src/cs/vim/Vim.Format.CodeGen/Vim.Format.CodeGen.csproj | 1 + src/cs/vim/Vim.Format.Core/Vim.Format.Core.csproj | 1 + src/cs/vim/Vim.Format.Tests/Vim.Format.Tests.csproj | 1 + .../Vim.Format.Vimx.Conversion.csproj | 1 + src/cs/vim/Vim.Format.Vimx/Vim.Format.Vimx.csproj | 1 + src/cs/vim/Vim.Format/Vim.Format.csproj | 1 + src/cs/vim/Vim.Vimx.Test/Vim.Format.Vimx.Test.csproj | 1 + 22 files changed, 25 insertions(+) diff --git a/src/cs/Vim.G3dNext.Tests/Vim.G3dNext.Tests.csproj b/src/cs/Vim.G3dNext.Tests/Vim.G3dNext.Tests.csproj index 188a58c3..032e77f2 100644 --- a/src/cs/Vim.G3dNext.Tests/Vim.G3dNext.Tests.csproj +++ b/src/cs/Vim.G3dNext.Tests/Vim.G3dNext.Tests.csproj @@ -23,6 +23,7 @@ True + diff --git a/src/cs/bfast/Vim.BFast.Tests/Vim.BFast.Tests.csproj b/src/cs/bfast/Vim.BFast.Tests/Vim.BFast.Tests.csproj index 5a73b0bc..c7ddf233 100644 --- a/src/cs/bfast/Vim.BFast.Tests/Vim.BFast.Tests.csproj +++ b/src/cs/bfast/Vim.BFast.Tests/Vim.BFast.Tests.csproj @@ -11,6 +11,7 @@ True + diff --git a/src/cs/bfast/Vim.BFast/Vim.BFast.csproj b/src/cs/bfast/Vim.BFast/Vim.BFast.csproj index 646a78e8..16404976 100644 --- a/src/cs/bfast/Vim.BFast/Vim.BFast.csproj +++ b/src/cs/bfast/Vim.BFast/Vim.BFast.csproj @@ -4,9 +4,13 @@ netstandard2.0 true + True + + + diff --git a/src/cs/g3d/Vim.G3d.AssimpWrapper/Vim.G3d.AssimpWrapper.csproj b/src/cs/g3d/Vim.G3d.AssimpWrapper/Vim.G3d.AssimpWrapper.csproj index 9dd379f7..3b567b9f 100644 --- a/src/cs/g3d/Vim.G3d.AssimpWrapper/Vim.G3d.AssimpWrapper.csproj +++ b/src/cs/g3d/Vim.G3d.AssimpWrapper/Vim.G3d.AssimpWrapper.csproj @@ -15,6 +15,7 @@ True + diff --git a/src/cs/g3d/Vim.G3d.Tests/Vim.G3d.Tests.csproj b/src/cs/g3d/Vim.G3d.Tests/Vim.G3d.Tests.csproj index 9bbcc776..ae2d33e9 100644 --- a/src/cs/g3d/Vim.G3d.Tests/Vim.G3d.Tests.csproj +++ b/src/cs/g3d/Vim.G3d.Tests/Vim.G3d.Tests.csproj @@ -39,6 +39,7 @@ True + diff --git a/src/cs/g3d/Vim.G3d/Vim.G3d.csproj b/src/cs/g3d/Vim.G3d/Vim.G3d.csproj index 47cee1d3..f3bb78c2 100644 --- a/src/cs/g3d/Vim.G3d/Vim.G3d.csproj +++ b/src/cs/g3d/Vim.G3d/Vim.G3d.csproj @@ -21,6 +21,7 @@ It can be easily and efficiently deserialized and rendered in different language True + diff --git a/src/cs/g3d/Vim.G3dNext.CodeGen/Vim.G3dNext.CodeGen.csproj b/src/cs/g3d/Vim.G3dNext.CodeGen/Vim.G3dNext.CodeGen.csproj index a5109829..41239fb1 100644 --- a/src/cs/g3d/Vim.G3dNext.CodeGen/Vim.G3dNext.CodeGen.csproj +++ b/src/cs/g3d/Vim.G3dNext.CodeGen/Vim.G3dNext.CodeGen.csproj @@ -20,6 +20,7 @@ True + \ No newline at end of file diff --git a/src/cs/g3d/Vim.G3dNext/Vim.G3dNext.csproj b/src/cs/g3d/Vim.G3dNext/Vim.G3dNext.csproj index 6bcd3546..b0086596 100644 --- a/src/cs/g3d/Vim.G3dNext/Vim.G3dNext.csproj +++ b/src/cs/g3d/Vim.G3dNext/Vim.G3dNext.csproj @@ -15,6 +15,7 @@ True + diff --git a/src/cs/linqarray/Vim.LinqArray.Tests/Vim.LinqArray.Tests.csproj b/src/cs/linqarray/Vim.LinqArray.Tests/Vim.LinqArray.Tests.csproj index a206263e..38321c15 100644 --- a/src/cs/linqarray/Vim.LinqArray.Tests/Vim.LinqArray.Tests.csproj +++ b/src/cs/linqarray/Vim.LinqArray.Tests/Vim.LinqArray.Tests.csproj @@ -17,6 +17,7 @@ True + diff --git a/src/cs/linqarray/Vim.LinqArray/Vim.LinqArray.csproj b/src/cs/linqarray/Vim.LinqArray/Vim.LinqArray.csproj index 73c2a6df..093e8b50 100644 --- a/src/cs/linqarray/Vim.LinqArray/Vim.LinqArray.csproj +++ b/src/cs/linqarray/Vim.LinqArray/Vim.LinqArray.csproj @@ -29,6 +29,7 @@ True + diff --git a/src/cs/math3d/Vim.Math3D.Tests/Vim.Math3D.Tests.csproj b/src/cs/math3d/Vim.Math3D.Tests/Vim.Math3D.Tests.csproj index b245bbb0..e4e11fda 100644 --- a/src/cs/math3d/Vim.Math3D.Tests/Vim.Math3D.Tests.csproj +++ b/src/cs/math3d/Vim.Math3D.Tests/Vim.Math3D.Tests.csproj @@ -17,6 +17,7 @@ True + diff --git a/src/cs/math3d/Vim.Math3D/Vim.Math3D.csproj b/src/cs/math3d/Vim.Math3D/Vim.Math3D.csproj index 7ee3eb40..309fc8d2 100644 --- a/src/cs/math3d/Vim.Math3D/Vim.Math3D.csproj +++ b/src/cs/math3d/Vim.Math3D/Vim.Math3D.csproj @@ -64,6 +64,7 @@ True + diff --git a/src/cs/util/Vim.Util.Logging.Serilog/Vim.Util.Logging.Serilog.csproj b/src/cs/util/Vim.Util.Logging.Serilog/Vim.Util.Logging.Serilog.csproj index 1ace7be0..ab531508 100644 --- a/src/cs/util/Vim.Util.Logging.Serilog/Vim.Util.Logging.Serilog.csproj +++ b/src/cs/util/Vim.Util.Logging.Serilog/Vim.Util.Logging.Serilog.csproj @@ -18,6 +18,7 @@ True + diff --git a/src/cs/util/Vim.Util.Tests/Vim.Util.Tests.csproj b/src/cs/util/Vim.Util.Tests/Vim.Util.Tests.csproj index b39a484c..6d419428 100644 --- a/src/cs/util/Vim.Util.Tests/Vim.Util.Tests.csproj +++ b/src/cs/util/Vim.Util.Tests/Vim.Util.Tests.csproj @@ -41,6 +41,7 @@ True + diff --git a/src/cs/util/Vim.Util/Vim.Util.csproj b/src/cs/util/Vim.Util/Vim.Util.csproj index a731a7c3..fc964269 100644 --- a/src/cs/util/Vim.Util/Vim.Util.csproj +++ b/src/cs/util/Vim.Util/Vim.Util.csproj @@ -7,6 +7,7 @@ True + diff --git a/src/cs/vim/Vim.Format.CodeGen/Vim.Format.CodeGen.csproj b/src/cs/vim/Vim.Format.CodeGen/Vim.Format.CodeGen.csproj index b22d814d..89a08ae0 100644 --- a/src/cs/vim/Vim.Format.CodeGen/Vim.Format.CodeGen.csproj +++ b/src/cs/vim/Vim.Format.CodeGen/Vim.Format.CodeGen.csproj @@ -26,6 +26,7 @@ True + diff --git a/src/cs/vim/Vim.Format.Core/Vim.Format.Core.csproj b/src/cs/vim/Vim.Format.Core/Vim.Format.Core.csproj index 04bb0373..382777aa 100644 --- a/src/cs/vim/Vim.Format.Core/Vim.Format.Core.csproj +++ b/src/cs/vim/Vim.Format.Core/Vim.Format.Core.csproj @@ -41,6 +41,7 @@ True + diff --git a/src/cs/vim/Vim.Format.Tests/Vim.Format.Tests.csproj b/src/cs/vim/Vim.Format.Tests/Vim.Format.Tests.csproj index da9ad0f7..3f9308b8 100644 --- a/src/cs/vim/Vim.Format.Tests/Vim.Format.Tests.csproj +++ b/src/cs/vim/Vim.Format.Tests/Vim.Format.Tests.csproj @@ -22,6 +22,7 @@ True + diff --git a/src/cs/vim/Vim.Format.Vimx.Conversion/Vim.Format.Vimx.Conversion.csproj b/src/cs/vim/Vim.Format.Vimx.Conversion/Vim.Format.Vimx.Conversion.csproj index 0f7c97d0..4e1f53c1 100644 --- a/src/cs/vim/Vim.Format.Vimx.Conversion/Vim.Format.Vimx.Conversion.csproj +++ b/src/cs/vim/Vim.Format.Vimx.Conversion/Vim.Format.Vimx.Conversion.csproj @@ -13,6 +13,7 @@ True + diff --git a/src/cs/vim/Vim.Format.Vimx/Vim.Format.Vimx.csproj b/src/cs/vim/Vim.Format.Vimx/Vim.Format.Vimx.csproj index 6be989dd..78fe3dbf 100644 --- a/src/cs/vim/Vim.Format.Vimx/Vim.Format.Vimx.csproj +++ b/src/cs/vim/Vim.Format.Vimx/Vim.Format.Vimx.csproj @@ -17,6 +17,7 @@ True + diff --git a/src/cs/vim/Vim.Format/Vim.Format.csproj b/src/cs/vim/Vim.Format/Vim.Format.csproj index b7d17ede..8fa44b7a 100644 --- a/src/cs/vim/Vim.Format/Vim.Format.csproj +++ b/src/cs/vim/Vim.Format/Vim.Format.csproj @@ -47,6 +47,7 @@ True + diff --git a/src/cs/vim/Vim.Vimx.Test/Vim.Format.Vimx.Test.csproj b/src/cs/vim/Vim.Vimx.Test/Vim.Format.Vimx.Test.csproj index 808fb736..52f8b154 100644 --- a/src/cs/vim/Vim.Vimx.Test/Vim.Format.Vimx.Test.csproj +++ b/src/cs/vim/Vim.Vimx.Test/Vim.Format.Vimx.Test.csproj @@ -25,6 +25,7 @@ True + From 7d49db2453aff51bc6667ffab947734094cce879 Mon Sep 17 00:00:00 2001 From: simon Date: Wed, 21 Feb 2024 13:47:41 -0500 Subject: [PATCH 088/111] renamed license --- src/cs/linqarray/Vim.LinqArray/Vim.LinqArray.csproj | 2 +- src/cs/math3d/Vim.Math3D/Vim.Math3D.csproj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cs/linqarray/Vim.LinqArray/Vim.LinqArray.csproj b/src/cs/linqarray/Vim.LinqArray/Vim.LinqArray.csproj index 093e8b50..558465f5 100644 --- a/src/cs/linqarray/Vim.LinqArray/Vim.LinqArray.csproj +++ b/src/cs/linqarray/Vim.LinqArray/Vim.LinqArray.csproj @@ -10,7 +10,7 @@ https://github.com/vimaec/linqarray GitHub true - license.txt + LICENSE.txt 1.1.3 true true diff --git a/src/cs/math3d/Vim.Math3D/Vim.Math3D.csproj b/src/cs/math3d/Vim.Math3D/Vim.Math3D.csproj index 309fc8d2..ac941449 100644 --- a/src/cs/math3d/Vim.Math3D/Vim.Math3D.csproj +++ b/src/cs/math3d/Vim.Math3D/Vim.Math3D.csproj @@ -10,7 +10,7 @@ https://github.com/vimaec/math3d GitHub true - license.txt + LICENSE.txt 1.6.2 true true From 999a7cfc5bc857f13507053193f5f22836a52778 Mon Sep 17 00:00:00 2001 From: simon Date: Thu, 22 Feb 2024 10:38:48 -0500 Subject: [PATCH 089/111] Added support for duplicated buffer names --- src/cs/bfast/Vim.BFast/Core/BFastHeader.cs | 27 ++++++++++++++++++---- src/cs/g3d/Vim.G3d/G3D.cs | 3 +++ 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/cs/bfast/Vim.BFast/Core/BFastHeader.cs b/src/cs/bfast/Vim.BFast/Core/BFastHeader.cs index 07edb205..21191e25 100644 --- a/src/cs/bfast/Vim.BFast/Core/BFastHeader.cs +++ b/src/cs/bfast/Vim.BFast/Core/BFastHeader.cs @@ -34,11 +34,10 @@ public static BFastHeader FromStream(Stream stream) stream.Seek(offset + ranges[0].Begin, SeekOrigin.Begin); var nameBytes = stream.ReadArray((int)ranges[0].Count); var names = BFastStrings.Unpack(nameBytes); - - if (names.Distinct().Count() < names.Length) - { - throw new Exception($"Buffer names should be unique. It contains duplicates. " + string.Join(",", names)); - } + + // Some old vim have duplicated buffers + // It is wrong but such is life. + MakeNamesUnique(names); var map = names .Zip(ranges.Skip(1), (n, r) => (n, r)) @@ -47,6 +46,24 @@ public static BFastHeader FromStream(Stream stream) return new BFastHeader(preamble, map).Validate(); } + private static void MakeNamesUnique(string[] names) + { + var nameSet = new Dictionary(); + for (var i = 0; i < names.Length; i++) + { + if (nameSet.ContainsKey(names[i])) + { + var count = nameSet[names[i]]; + names[i] = names[i] + "_" + count; + Console.WriteLine($"Duplicated Name {names[i]} in BFAST. Making name unique. This can result in unexpected behaviour."); + } + if (!nameSet.ContainsKey(names[i])) + { + nameSet.Add(names[i], i); + } + } + } + public BFastHeader Validate() { Preamble.Validate(); diff --git a/src/cs/g3d/Vim.G3d/G3D.cs b/src/cs/g3d/Vim.G3d/G3D.cs index a9f44b68..220b588c 100644 --- a/src/cs/g3d/Vim.G3d/G3D.cs +++ b/src/cs/g3d/Vim.G3d/G3D.cs @@ -308,6 +308,7 @@ public static G3D Read(BFast bfast) { if (name == "meta") continue; var attribute = GetEmptyAttribute(name); + if (attribute == null) continue; var a = attribute.Read(bfast); attributes.Add(a); } @@ -318,6 +319,7 @@ private static GeometryAttribute GetEmptyAttribute(string name) { if (!AttributeDescriptor.TryParse(name, out var attributeDescriptor)) { + Console.WriteLine("G3D Error: Could not parse attribute " + name); return null; } try @@ -326,6 +328,7 @@ private static GeometryAttribute GetEmptyAttribute(string name) } catch { + Console.WriteLine("G3D Error: Could not parse attribute " + name); return null; } } From 6ba6c131c48286d52bb76061ade451010537d6b7 Mon Sep 17 00:00:00 2001 From: simon Date: Thu, 22 Feb 2024 10:57:23 -0500 Subject: [PATCH 090/111] added missing header to serialized header --- src/cs/vim/Vim.Format.Core/SerializableDocument.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cs/vim/Vim.Format.Core/SerializableDocument.cs b/src/cs/vim/Vim.Format.Core/SerializableDocument.cs index 75466197..d5e80a6b 100644 --- a/src/cs/vim/Vim.Format.Core/SerializableDocument.cs +++ b/src/cs/vim/Vim.Format.Core/SerializableDocument.cs @@ -61,6 +61,7 @@ public class SerializableDocument public BFast ToBFast() { var bfast = new BFast(); + bfast.SetArray(BufferNames.Header, Header.ToBytes()); var assets = new BFast(); foreach (var asset in Assets) From 52e1f054baf8858d6682fa8431305e764219cb9a Mon Sep 17 00:00:00 2001 From: simon Date: Thu, 22 Feb 2024 11:47:01 -0500 Subject: [PATCH 091/111] removed dead reference --- src/cs/g3d/Vim.G3dNext.Tests/Vim.G3dNext.Tests.csproj | 1 - 1 file changed, 1 deletion(-) diff --git a/src/cs/g3d/Vim.G3dNext.Tests/Vim.G3dNext.Tests.csproj b/src/cs/g3d/Vim.G3dNext.Tests/Vim.G3dNext.Tests.csproj index 913affa1..158c815b 100644 --- a/src/cs/g3d/Vim.G3dNext.Tests/Vim.G3dNext.Tests.csproj +++ b/src/cs/g3d/Vim.G3dNext.Tests/Vim.G3dNext.Tests.csproj @@ -13,7 +13,6 @@ - From 1428db48ba94daf5f5084604145da24d045d2acb Mon Sep 17 00:00:00 2001 From: simon Date: Tue, 27 Feb 2024 11:00:04 -0500 Subject: [PATCH 092/111] removed verbose flag and exposed logs --- src/ts/src/remoteBuffer.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/ts/src/remoteBuffer.ts b/src/ts/src/remoteBuffer.ts index 3ef4ac61..0c7b4160 100644 --- a/src/ts/src/remoteBuffer.ts +++ b/src/ts/src/remoteBuffer.ts @@ -73,15 +73,15 @@ export class RemoteBuffer { maxConcurency: number = RemoteBufferMaxConcurency onProgress: (progress : IProgressLogs) => void private _tracker: RequestTracker - private _logs : Logger + private logs : Logger private _queue: RetryRequest[] = [] private _active: Set = new Set() private _encoded: RemoteValue - constructor (url: string, verbose: boolean = false) { + constructor (url: string) { this.url = url - this._logs = verbose ? new DefaultLog() : new NoLog() - this._tracker = new RequestTracker(url, this._logs) + this.logs = new NoLog() + this._tracker = new RequestTracker(url, this.logs) this._tracker.onUpdate = (p) => this.onProgress?.(p) this._encoded = new RemoteValue(() => this.requestEncoding()) } @@ -90,7 +90,7 @@ export class RemoteBuffer { const xhr = new XMLHttpRequest() xhr.open('HEAD', this.url) xhr.send() - this._logs.log(`Requesting header for ${this.url}`) + this.logs.log(`Requesting header for ${this.url}`) const promise = new Promise((resolve, reject) => { xhr.onload = (_) => { @@ -98,7 +98,7 @@ export class RemoteBuffer { try { encoding = xhr.getResponseHeader('content-encoding') } catch (e) { - this._logs.error(e) + this.logs.error(e) } resolve(encoding ?? undefined) } @@ -108,9 +108,9 @@ export class RemoteBuffer { const encoding = await promise const encoded = !!encoding - this._logs.log(`Encoding for ${this.url} = ${encoding}`) + this.logs.log(`Encoding for ${this.url} = ${encoding}`) if (encoded) { - this._logs.log( + this.logs.log( `Defaulting to download strategy for encoded content at ${this.url}` ) } @@ -183,6 +183,6 @@ export class RemoteBuffer { this._queue.shift() this._active.add(next) next.send() - this._logs.log('Starting ' + next.msg) + this.logs.log('Starting ' + next.msg) } } From 87813ffa4cbe55780e234e5c7a0c186943a67e23 Mon Sep 17 00:00:00 2001 From: simon Date: Tue, 27 Feb 2024 11:00:17 -0500 Subject: [PATCH 093/111] typo --- src/ts/dist/types/vimHelpers.d.ts | 2 +- src/ts/dist/vimHelpers.d.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ts/dist/types/vimHelpers.d.ts b/src/ts/dist/types/vimHelpers.d.ts index 052cde0d..db2fff7c 100644 --- a/src/ts/dist/types/vimHelpers.d.ts +++ b/src/ts/dist/types/vimHelpers.d.ts @@ -1,6 +1,6 @@ import { VimDocument } from "./objectModel"; /** - * Representation of ElementParamter entity from the entity model + * Representation of ElementParameter entity from the entity model * See https://github.com/vimaec/vim/blob/master/ObjectModel/object-model-schema.json */ export declare type ElementParameter = { diff --git a/src/ts/dist/vimHelpers.d.ts b/src/ts/dist/vimHelpers.d.ts index 052cde0d..db2fff7c 100644 --- a/src/ts/dist/vimHelpers.d.ts +++ b/src/ts/dist/vimHelpers.d.ts @@ -1,6 +1,6 @@ import { VimDocument } from "./objectModel"; /** - * Representation of ElementParamter entity from the entity model + * Representation of ElementParameter entity from the entity model * See https://github.com/vimaec/vim/blob/master/ObjectModel/object-model-schema.json */ export declare type ElementParameter = { From 8ba3c4ddcbfb165526181a1fb37f0818bb59b913 Mon Sep 17 00:00:00 2001 From: simon Date: Tue, 27 Feb 2024 11:01:23 -0500 Subject: [PATCH 094/111] fixed attribute name --- src/ts/dist/g3dChunk.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ts/dist/g3dChunk.js b/src/ts/dist/g3dChunk.js index 0630de04..3b6dacf0 100644 --- a/src/ts/dist/g3dChunk.js +++ b/src/ts/dist/g3dChunk.js @@ -14,7 +14,7 @@ exports.G3dChunk = exports.MeshAttributes = void 0; class MeshAttributes { } exports.MeshAttributes = MeshAttributes; -MeshAttributes.meshSubmeshOffset = 'g3d:mesh:submeshOffset:0:int32:1'; +MeshAttributes.meshSubmeshOffset = 'g3d:mesh:submeshoffset:0:int32:1'; MeshAttributes.meshOpaqueSubmeshCount = 'g3d:mesh:opaquesubmeshcount:0:int32:1'; MeshAttributes.submeshIndexOffsets = 'g3d:submesh:indexoffset:0:int32:1'; MeshAttributes.submeshVertexOffsets = 'g3d:submesh:vertexoffset:0:int32:1'; From 37a8fc204947f7a582a78ad83c90a9740d1f497e Mon Sep 17 00:00:00 2001 From: simon Date: Tue, 27 Feb 2024 11:02:24 -0500 Subject: [PATCH 095/111] model update --- src/ts/dist/g3dMesh.d.ts | 12 -- src/ts/dist/g3dMesh.js | 15 +- src/ts/dist/index.d.ts | 1 + src/ts/dist/index.js | 1 + src/ts/dist/objectModel.d.ts | 130 ++++++++++++++++ src/ts/dist/objectModel.js | 236 ++++++++++++++++++++++++++++- src/ts/dist/types/g3dMesh.d.ts | 12 -- src/ts/dist/types/index.d.ts | 1 + src/ts/dist/types/objectModel.d.ts | 130 ++++++++++++++++ src/ts/package.json | 2 +- 10 files changed, 500 insertions(+), 40 deletions(-) diff --git a/src/ts/dist/g3dMesh.d.ts b/src/ts/dist/g3dMesh.d.ts index 637da62d..138a72a8 100644 --- a/src/ts/dist/g3dMesh.d.ts +++ b/src/ts/dist/g3dMesh.d.ts @@ -4,18 +4,6 @@ import { G3dChunk } from './g3dChunk'; import { MeshSection } from './g3d'; import { G3dScene } from './g3dScene'; -/** - * See https://github.com/vimaec/vim#vim-geometry-attributes - */ -export declare class MeshAttributes { - static meshSubmeshOffset: string; - static meshOpaqueSubmeshCount: string; - static submeshIndexOffsets: string; - static submeshVertexOffsets: string; - static submeshMaterials: string; - static positions: string; - static indices: string; -} export declare class G3dMesh { readonly scene: G3dScene; readonly chunk: G3dChunk; diff --git a/src/ts/dist/g3dMesh.js b/src/ts/dist/g3dMesh.js index 732cd452..89da49fe 100644 --- a/src/ts/dist/g3dMesh.js +++ b/src/ts/dist/g3dMesh.js @@ -3,21 +3,8 @@ * @module vim-ts */ Object.defineProperty(exports, "__esModule", { value: true }); -exports.G3dMesh = exports.MeshAttributes = void 0; +exports.G3dMesh = void 0; const g3d_1 = require("./g3d"); -/** - * See https://github.com/vimaec/vim#vim-geometry-attributes - */ -class MeshAttributes { -} -exports.MeshAttributes = MeshAttributes; -MeshAttributes.meshSubmeshOffset = 'g3d:mesh:submeshOffset:0:int32:1'; -MeshAttributes.meshOpaqueSubmeshCount = 'g3d:mesh:opaquesubmeshcount:0:int32:1'; -MeshAttributes.submeshIndexOffsets = 'g3d:submesh:indexoffset:0:int32:1'; -MeshAttributes.submeshVertexOffsets = 'g3d:submesh:vertexoffset:0:int32:1'; -MeshAttributes.submeshMaterials = 'g3d:submesh:material:0:int32:1'; -MeshAttributes.positions = 'g3d:vertex:position:0:float32:3'; -MeshAttributes.indices = 'g3d:corner:index:0:int32:1'; class G3dMesh { constructor(scene, chunk, index) { this.scene = scene; diff --git a/src/ts/dist/index.d.ts b/src/ts/dist/index.d.ts index b90db4ff..26013896 100644 --- a/src/ts/dist/index.d.ts +++ b/src/ts/dist/index.d.ts @@ -3,6 +3,7 @@ export * from './g3d'; export * from './remoteVimx'; export * from './g3dMaterials'; export * from './g3dMesh'; +export * from './g3dChunk'; export * from './g3dScene'; export * from './remoteBuffer'; export * from './requestTracker'; diff --git a/src/ts/dist/index.js b/src/ts/dist/index.js index d1133d3a..1afb0cd2 100644 --- a/src/ts/dist/index.js +++ b/src/ts/dist/index.js @@ -33,6 +33,7 @@ __exportStar(require("./g3d"), exports); __exportStar(require("./remoteVimx"), exports); __exportStar(require("./g3dMaterials"), exports); __exportStar(require("./g3dMesh"), exports); +__exportStar(require("./g3dChunk"), exports); __exportStar(require("./g3dScene"), exports); __exportStar(require("./remoteBuffer"), exports); __exportStar(require("./requestTracker"), exports); diff --git a/src/ts/dist/objectModel.d.ts b/src/ts/dist/objectModel.d.ts index 29ffa83b..4b40b00b 100644 --- a/src/ts/dist/objectModel.d.ts +++ b/src/ts/dist/objectModel.d.ts @@ -593,6 +593,8 @@ export interface ILevel { elevation?: number; familyTypeIndex?: number; familyType?: IFamilyType; + buildingIndex?: number; + building?: IBuilding; elementIndex?: number; element?: IElement; } @@ -605,6 +607,9 @@ export interface ILevelTable { getFamilyTypeIndex(levelIndex: number): Promise; getAllFamilyTypeIndex(): Promise; getFamilyType(levelIndex: number): Promise; + getBuildingIndex(levelIndex: number): Promise; + getAllBuildingIndex(): Promise; + getBuilding(levelIndex: number): Promise; getElementIndex(levelIndex: number): Promise; getAllElementIndex(): Promise; getElement(levelIndex: number): Promise; @@ -614,6 +619,8 @@ export declare class Level implements ILevel { elevation?: number; familyTypeIndex?: number; familyType?: IFamilyType; + buildingIndex?: number; + building?: IBuilding; elementIndex?: number; element?: IElement; static createFromTable(table: ILevelTable, index: number): Promise; @@ -630,6 +637,9 @@ export declare class LevelTable implements ILevelTable { getFamilyTypeIndex(levelIndex: number): Promise; getAllFamilyTypeIndex(): Promise; getFamilyType(levelIndex: number): Promise; + getBuildingIndex(levelIndex: number): Promise; + getAllBuildingIndex(): Promise; + getBuilding(levelIndex: number): Promise; getElementIndex(levelIndex: number): Promise; getAllElementIndex(): Promise; getElement(levelIndex: number): Promise; @@ -3296,6 +3306,124 @@ export declare class ViewInViewSheetTable implements IViewInViewSheetTable { getAllViewSheetIndex(): Promise; getViewSheet(viewInViewSheetIndex: number): Promise; } +export interface ISite { + index: number; + latitude?: number; + longitude?: number; + address?: string; + elevation?: number; + number?: string; + elementIndex?: number; + element?: IElement; +} +export interface ISiteTable { + getCount(): Promise; + get(siteIndex: number): Promise; + getAll(): Promise; + getLatitude(siteIndex: number): Promise; + getAllLatitude(): Promise; + getLongitude(siteIndex: number): Promise; + getAllLongitude(): Promise; + getAddress(siteIndex: number): Promise; + getAllAddress(): Promise; + getElevation(siteIndex: number): Promise; + getAllElevation(): Promise; + getNumber(siteIndex: number): Promise; + getAllNumber(): Promise; + getElementIndex(siteIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(siteIndex: number): Promise; +} +export declare class Site implements ISite { + index: number; + latitude?: number; + longitude?: number; + address?: string; + elevation?: number; + number?: string; + elementIndex?: number; + element?: IElement; + static createFromTable(table: ISiteTable, index: number): Promise; +} +export declare class SiteTable implements ISiteTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(siteIndex: number): Promise; + getAll(): Promise; + getLatitude(siteIndex: number): Promise; + getAllLatitude(): Promise; + getLongitude(siteIndex: number): Promise; + getAllLongitude(): Promise; + getAddress(siteIndex: number): Promise; + getAllAddress(): Promise; + getElevation(siteIndex: number): Promise; + getAllElevation(): Promise; + getNumber(siteIndex: number): Promise; + getAllNumber(): Promise; + getElementIndex(siteIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(siteIndex: number): Promise; +} +export interface IBuilding { + index: number; + elevation?: number; + terrainElevation?: number; + address?: string; + siteIndex?: number; + site?: ISite; + elementIndex?: number; + element?: IElement; +} +export interface IBuildingTable { + getCount(): Promise; + get(buildingIndex: number): Promise; + getAll(): Promise; + getElevation(buildingIndex: number): Promise; + getAllElevation(): Promise; + getTerrainElevation(buildingIndex: number): Promise; + getAllTerrainElevation(): Promise; + getAddress(buildingIndex: number): Promise; + getAllAddress(): Promise; + getSiteIndex(buildingIndex: number): Promise; + getAllSiteIndex(): Promise; + getSite(buildingIndex: number): Promise; + getElementIndex(buildingIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(buildingIndex: number): Promise; +} +export declare class Building implements IBuilding { + index: number; + elevation?: number; + terrainElevation?: number; + address?: string; + siteIndex?: number; + site?: ISite; + elementIndex?: number; + element?: IElement; + static createFromTable(table: IBuildingTable, index: number): Promise; +} +export declare class BuildingTable implements IBuildingTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(buildingIndex: number): Promise; + getAll(): Promise; + getElevation(buildingIndex: number): Promise; + getAllElevation(): Promise; + getTerrainElevation(buildingIndex: number): Promise; + getAllTerrainElevation(): Promise; + getAddress(buildingIndex: number): Promise; + getAllAddress(): Promise; + getSiteIndex(buildingIndex: number): Promise; + getAllSiteIndex(): Promise; + getSite(buildingIndex: number): Promise; + getElementIndex(buildingIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(buildingIndex: number): Promise; +} export declare class VimDocument { asset: IAssetTable | undefined; displayUnit: IDisplayUnitTable | undefined; @@ -3349,6 +3477,8 @@ export declare class VimDocument { viewSheetInViewSheetSet: IViewSheetInViewSheetSetTable | undefined; viewInViewSheetSet: IViewInViewSheetSetTable | undefined; viewInViewSheet: IViewInViewSheetTable | undefined; + site: ISiteTable | undefined; + building: IBuildingTable | undefined; entities: BFast; strings: string[] | undefined; private constructor(); diff --git a/src/ts/dist/objectModel.js b/src/ts/dist/objectModel.js index c691d974..6db34700 100644 --- a/src/ts/dist/objectModel.js +++ b/src/ts/dist/objectModel.js @@ -2,7 +2,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.LevelInViewTable = exports.LevelInView = exports.AssetInViewSheetTable = exports.AssetInViewSheet = exports.AssetInViewTable = exports.AssetInView = exports.ShapeInViewTable = exports.ShapeInView = exports.ElementInViewTable = exports.ElementInView = exports.ViewTable = exports.View = exports.FamilyInstanceTable = exports.FamilyInstance = exports.FamilyTypeTable = exports.FamilyType = exports.FamilyTable = exports.Family = exports.CategoryTable = exports.Category = exports.PhaseOrderInBimDocumentTable = exports.PhaseOrderInBimDocument = exports.DisplayUnitInBimDocumentTable = exports.DisplayUnitInBimDocument = exports.BimDocumentTable = exports.BimDocument = exports.RoomTable = exports.Room = exports.PhaseTable = exports.Phase = exports.LevelTable = exports.Level = exports.DesignOptionTable = exports.DesignOption = exports.GroupTable = exports.Group = exports.AssemblyInstanceTable = exports.AssemblyInstance = exports.WorksetTable = exports.Workset = exports.ElementTable = exports.Element = exports.ParameterTable = exports.Parameter = exports.ParameterDescriptorTable = exports.ParameterDescriptor = exports.DisplayUnitTable = exports.DisplayUnit = exports.AssetTable = exports.Asset = void 0; exports.ViewSheetInViewSheetSetTable = exports.ViewSheetInViewSheetSet = exports.ViewSheetTable = exports.ViewSheet = exports.ViewSheetSetTable = exports.ViewSheetSet = exports.ScheduleCellTable = exports.ScheduleCell = exports.ScheduleColumnTable = exports.ScheduleColumn = exports.ScheduleTable = exports.Schedule = exports.AreaSchemeTable = exports.AreaScheme = exports.AreaTable = exports.Area = exports.GridTable = exports.Grid = exports.PhaseFilterTable = exports.PhaseFilter = exports.BasePointTable = exports.BasePoint = exports.ElementInWarningTable = exports.ElementInWarning = exports.WarningTable = exports.Warning = exports.ElementInSystemTable = exports.ElementInSystem = exports.SystemTable = exports.System = exports.ShapeInShapeCollectionTable = exports.ShapeInShapeCollection = exports.ShapeCollectionTable = exports.ShapeCollection = exports.ShapeTable = exports.Shape = exports.GeometryTable = exports.Geometry = exports.NodeTable = exports.Node = exports.CompoundStructureTable = exports.CompoundStructure = exports.CompoundStructureLayerTable = exports.CompoundStructureLayer = exports.MaterialInElementTable = exports.MaterialInElement = exports.MaterialTable = exports.Material = exports.CameraTable = exports.Camera = void 0; -exports.VimDocument = exports.ViewInViewSheetTable = exports.ViewInViewSheet = exports.ViewInViewSheetSetTable = exports.ViewInViewSheetSet = void 0; +exports.VimDocument = exports.BuildingTable = exports.Building = exports.SiteTable = exports.Site = exports.ViewInViewSheetTable = exports.ViewInViewSheet = exports.ViewInViewSheetSetTable = exports.ViewInViewSheetSet = void 0; const entityTable_1 = require("./entityTable"); const vimLoader_1 = require("./vimLoader"); class Asset { @@ -1074,6 +1074,7 @@ class Level { await Promise.all([ table.getElevation(index).then(v => result.elevation = v), table.getFamilyTypeIndex(index).then(v => result.familyTypeIndex = v), + table.getBuildingIndex(index).then(v => result.buildingIndex = v), table.getElementIndex(index).then(v => result.elementIndex = v), ]); return result; @@ -1101,10 +1102,12 @@ class LevelTable { const localTable = await this.entityTable.getLocal(); let elevation; let familyTypeIndex; + let buildingIndex; let elementIndex; await Promise.all([ (async () => { elevation = (await localTable.getNumberArray("double:Elevation")); })(), (async () => { familyTypeIndex = (await localTable.getNumberArray("index:Vim.FamilyType:FamilyType")); })(), + (async () => { buildingIndex = (await localTable.getNumberArray("index:Vim.Building:Building")); })(), (async () => { elementIndex = (await localTable.getNumberArray("index:Vim.Element:Element")); })(), ]); let level = []; @@ -1114,6 +1117,7 @@ class LevelTable { index: i, elevation: elevation ? elevation[i] : undefined, familyTypeIndex: familyTypeIndex ? familyTypeIndex[i] : undefined, + buildingIndex: buildingIndex ? buildingIndex[i] : undefined, elementIndex: elementIndex ? elementIndex[i] : undefined }); } @@ -1138,6 +1142,19 @@ class LevelTable { } return await this.document.familyType?.get(index); } + async getBuildingIndex(levelIndex) { + return await this.entityTable.getNumber(levelIndex, "index:Vim.Building:Building"); + } + async getAllBuildingIndex() { + return await this.entityTable.getNumberArray("index:Vim.Building:Building"); + } + async getBuilding(levelIndex) { + const index = await this.getBuildingIndex(levelIndex); + if (index === undefined) { + return undefined; + } + return await this.document.building?.get(index); + } async getElementIndex(levelIndex) { return await this.entityTable.getNumber(levelIndex, "index:Vim.Element:Element"); } @@ -5980,6 +5997,221 @@ class ViewInViewSheetTable { } } exports.ViewInViewSheetTable = ViewInViewSheetTable; +class Site { + static async createFromTable(table, index) { + let result = new Site(); + result.index = index; + await Promise.all([ + table.getLatitude(index).then(v => result.latitude = v), + table.getLongitude(index).then(v => result.longitude = v), + table.getAddress(index).then(v => result.address = v), + table.getElevation(index).then(v => result.elevation = v), + table.getNumber(index).then(v => result.number = v), + table.getElementIndex(index).then(v => result.elementIndex = v), + ]); + return result; + } +} +exports.Site = Site; +class SiteTable { + static async createFromDocument(document) { + const entity = await document.entities.getBfast("Vim.Site"); + if (!entity) { + return undefined; + } + let table = new SiteTable(); + table.document = document; + table.entityTable = new entityTable_1.EntityTable(entity, document.strings); + return table; + } + getCount() { + return this.entityTable.getCount(); + } + async get(siteIndex) { + return await Site.createFromTable(this, siteIndex); + } + async getAll() { + const localTable = await this.entityTable.getLocal(); + let latitude; + let longitude; + let address; + let elevation; + let number; + let elementIndex; + await Promise.all([ + (async () => { latitude = (await localTable.getNumberArray("double:Latitude")); })(), + (async () => { longitude = (await localTable.getNumberArray("double:Longitude")); })(), + (async () => { address = (await localTable.getStringArray("string:Address")); })(), + (async () => { elevation = (await localTable.getNumberArray("double:Elevation")); })(), + (async () => { number = (await localTable.getStringArray("string:Number")); })(), + (async () => { elementIndex = (await localTable.getNumberArray("index:Vim.Element:Element")); })(), + ]); + let site = []; + const rowCount = await this.getCount(); + for (let i = 0; i < rowCount; i++) { + site.push({ + index: i, + latitude: latitude ? latitude[i] : undefined, + longitude: longitude ? longitude[i] : undefined, + address: address ? address[i] : undefined, + elevation: elevation ? elevation[i] : undefined, + number: number ? number[i] : undefined, + elementIndex: elementIndex ? elementIndex[i] : undefined + }); + } + return site; + } + async getLatitude(siteIndex) { + return (await this.entityTable.getNumber(siteIndex, "double:Latitude")); + } + async getAllLatitude() { + return (await this.entityTable.getNumberArray("double:Latitude")); + } + async getLongitude(siteIndex) { + return (await this.entityTable.getNumber(siteIndex, "double:Longitude")); + } + async getAllLongitude() { + return (await this.entityTable.getNumberArray("double:Longitude")); + } + async getAddress(siteIndex) { + return (await this.entityTable.getString(siteIndex, "string:Address")); + } + async getAllAddress() { + return (await this.entityTable.getStringArray("string:Address")); + } + async getElevation(siteIndex) { + return (await this.entityTable.getNumber(siteIndex, "double:Elevation")); + } + async getAllElevation() { + return (await this.entityTable.getNumberArray("double:Elevation")); + } + async getNumber(siteIndex) { + return (await this.entityTable.getString(siteIndex, "string:Number")); + } + async getAllNumber() { + return (await this.entityTable.getStringArray("string:Number")); + } + async getElementIndex(siteIndex) { + return await this.entityTable.getNumber(siteIndex, "index:Vim.Element:Element"); + } + async getAllElementIndex() { + return await this.entityTable.getNumberArray("index:Vim.Element:Element"); + } + async getElement(siteIndex) { + const index = await this.getElementIndex(siteIndex); + if (index === undefined) { + return undefined; + } + return await this.document.element?.get(index); + } +} +exports.SiteTable = SiteTable; +class Building { + static async createFromTable(table, index) { + let result = new Building(); + result.index = index; + await Promise.all([ + table.getElevation(index).then(v => result.elevation = v), + table.getTerrainElevation(index).then(v => result.terrainElevation = v), + table.getAddress(index).then(v => result.address = v), + table.getSiteIndex(index).then(v => result.siteIndex = v), + table.getElementIndex(index).then(v => result.elementIndex = v), + ]); + return result; + } +} +exports.Building = Building; +class BuildingTable { + static async createFromDocument(document) { + const entity = await document.entities.getBfast("Vim.Building"); + if (!entity) { + return undefined; + } + let table = new BuildingTable(); + table.document = document; + table.entityTable = new entityTable_1.EntityTable(entity, document.strings); + return table; + } + getCount() { + return this.entityTable.getCount(); + } + async get(buildingIndex) { + return await Building.createFromTable(this, buildingIndex); + } + async getAll() { + const localTable = await this.entityTable.getLocal(); + let elevation; + let terrainElevation; + let address; + let siteIndex; + let elementIndex; + await Promise.all([ + (async () => { elevation = (await localTable.getNumberArray("double:Elevation")); })(), + (async () => { terrainElevation = (await localTable.getNumberArray("double:TerrainElevation")); })(), + (async () => { address = (await localTable.getStringArray("string:Address")); })(), + (async () => { siteIndex = (await localTable.getNumberArray("index:Vim.Site:Site")); })(), + (async () => { elementIndex = (await localTable.getNumberArray("index:Vim.Element:Element")); })(), + ]); + let building = []; + const rowCount = await this.getCount(); + for (let i = 0; i < rowCount; i++) { + building.push({ + index: i, + elevation: elevation ? elevation[i] : undefined, + terrainElevation: terrainElevation ? terrainElevation[i] : undefined, + address: address ? address[i] : undefined, + siteIndex: siteIndex ? siteIndex[i] : undefined, + elementIndex: elementIndex ? elementIndex[i] : undefined + }); + } + return building; + } + async getElevation(buildingIndex) { + return (await this.entityTable.getNumber(buildingIndex, "double:Elevation")); + } + async getAllElevation() { + return (await this.entityTable.getNumberArray("double:Elevation")); + } + async getTerrainElevation(buildingIndex) { + return (await this.entityTable.getNumber(buildingIndex, "double:TerrainElevation")); + } + async getAllTerrainElevation() { + return (await this.entityTable.getNumberArray("double:TerrainElevation")); + } + async getAddress(buildingIndex) { + return (await this.entityTable.getString(buildingIndex, "string:Address")); + } + async getAllAddress() { + return (await this.entityTable.getStringArray("string:Address")); + } + async getSiteIndex(buildingIndex) { + return await this.entityTable.getNumber(buildingIndex, "index:Vim.Site:Site"); + } + async getAllSiteIndex() { + return await this.entityTable.getNumberArray("index:Vim.Site:Site"); + } + async getSite(buildingIndex) { + const index = await this.getSiteIndex(buildingIndex); + if (index === undefined) { + return undefined; + } + return await this.document.site?.get(index); + } + async getElementIndex(buildingIndex) { + return await this.entityTable.getNumber(buildingIndex, "index:Vim.Element:Element"); + } + async getAllElementIndex() { + return await this.entityTable.getNumberArray("index:Vim.Element:Element"); + } + async getElement(buildingIndex) { + const index = await this.getElementIndex(buildingIndex); + if (index === undefined) { + return undefined; + } + return await this.document.element?.get(index); + } +} +exports.BuildingTable = BuildingTable; class VimDocument { constructor(entities, strings) { this.entities = entities; @@ -6042,6 +6274,8 @@ class VimDocument { doc.viewSheetInViewSheetSet = await ViewSheetInViewSheetSetTable.createFromDocument(doc); doc.viewInViewSheetSet = await ViewInViewSheetSetTable.createFromDocument(doc); doc.viewInViewSheet = await ViewInViewSheetTable.createFromDocument(doc); + doc.site = await SiteTable.createFromDocument(doc); + doc.building = await BuildingTable.createFromDocument(doc); return doc; } } diff --git a/src/ts/dist/types/g3dMesh.d.ts b/src/ts/dist/types/g3dMesh.d.ts index 637da62d..138a72a8 100644 --- a/src/ts/dist/types/g3dMesh.d.ts +++ b/src/ts/dist/types/g3dMesh.d.ts @@ -4,18 +4,6 @@ import { G3dChunk } from './g3dChunk'; import { MeshSection } from './g3d'; import { G3dScene } from './g3dScene'; -/** - * See https://github.com/vimaec/vim#vim-geometry-attributes - */ -export declare class MeshAttributes { - static meshSubmeshOffset: string; - static meshOpaqueSubmeshCount: string; - static submeshIndexOffsets: string; - static submeshVertexOffsets: string; - static submeshMaterials: string; - static positions: string; - static indices: string; -} export declare class G3dMesh { readonly scene: G3dScene; readonly chunk: G3dChunk; diff --git a/src/ts/dist/types/index.d.ts b/src/ts/dist/types/index.d.ts index b90db4ff..26013896 100644 --- a/src/ts/dist/types/index.d.ts +++ b/src/ts/dist/types/index.d.ts @@ -3,6 +3,7 @@ export * from './g3d'; export * from './remoteVimx'; export * from './g3dMaterials'; export * from './g3dMesh'; +export * from './g3dChunk'; export * from './g3dScene'; export * from './remoteBuffer'; export * from './requestTracker'; diff --git a/src/ts/dist/types/objectModel.d.ts b/src/ts/dist/types/objectModel.d.ts index 29ffa83b..4b40b00b 100644 --- a/src/ts/dist/types/objectModel.d.ts +++ b/src/ts/dist/types/objectModel.d.ts @@ -593,6 +593,8 @@ export interface ILevel { elevation?: number; familyTypeIndex?: number; familyType?: IFamilyType; + buildingIndex?: number; + building?: IBuilding; elementIndex?: number; element?: IElement; } @@ -605,6 +607,9 @@ export interface ILevelTable { getFamilyTypeIndex(levelIndex: number): Promise; getAllFamilyTypeIndex(): Promise; getFamilyType(levelIndex: number): Promise; + getBuildingIndex(levelIndex: number): Promise; + getAllBuildingIndex(): Promise; + getBuilding(levelIndex: number): Promise; getElementIndex(levelIndex: number): Promise; getAllElementIndex(): Promise; getElement(levelIndex: number): Promise; @@ -614,6 +619,8 @@ export declare class Level implements ILevel { elevation?: number; familyTypeIndex?: number; familyType?: IFamilyType; + buildingIndex?: number; + building?: IBuilding; elementIndex?: number; element?: IElement; static createFromTable(table: ILevelTable, index: number): Promise; @@ -630,6 +637,9 @@ export declare class LevelTable implements ILevelTable { getFamilyTypeIndex(levelIndex: number): Promise; getAllFamilyTypeIndex(): Promise; getFamilyType(levelIndex: number): Promise; + getBuildingIndex(levelIndex: number): Promise; + getAllBuildingIndex(): Promise; + getBuilding(levelIndex: number): Promise; getElementIndex(levelIndex: number): Promise; getAllElementIndex(): Promise; getElement(levelIndex: number): Promise; @@ -3296,6 +3306,124 @@ export declare class ViewInViewSheetTable implements IViewInViewSheetTable { getAllViewSheetIndex(): Promise; getViewSheet(viewInViewSheetIndex: number): Promise; } +export interface ISite { + index: number; + latitude?: number; + longitude?: number; + address?: string; + elevation?: number; + number?: string; + elementIndex?: number; + element?: IElement; +} +export interface ISiteTable { + getCount(): Promise; + get(siteIndex: number): Promise; + getAll(): Promise; + getLatitude(siteIndex: number): Promise; + getAllLatitude(): Promise; + getLongitude(siteIndex: number): Promise; + getAllLongitude(): Promise; + getAddress(siteIndex: number): Promise; + getAllAddress(): Promise; + getElevation(siteIndex: number): Promise; + getAllElevation(): Promise; + getNumber(siteIndex: number): Promise; + getAllNumber(): Promise; + getElementIndex(siteIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(siteIndex: number): Promise; +} +export declare class Site implements ISite { + index: number; + latitude?: number; + longitude?: number; + address?: string; + elevation?: number; + number?: string; + elementIndex?: number; + element?: IElement; + static createFromTable(table: ISiteTable, index: number): Promise; +} +export declare class SiteTable implements ISiteTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(siteIndex: number): Promise; + getAll(): Promise; + getLatitude(siteIndex: number): Promise; + getAllLatitude(): Promise; + getLongitude(siteIndex: number): Promise; + getAllLongitude(): Promise; + getAddress(siteIndex: number): Promise; + getAllAddress(): Promise; + getElevation(siteIndex: number): Promise; + getAllElevation(): Promise; + getNumber(siteIndex: number): Promise; + getAllNumber(): Promise; + getElementIndex(siteIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(siteIndex: number): Promise; +} +export interface IBuilding { + index: number; + elevation?: number; + terrainElevation?: number; + address?: string; + siteIndex?: number; + site?: ISite; + elementIndex?: number; + element?: IElement; +} +export interface IBuildingTable { + getCount(): Promise; + get(buildingIndex: number): Promise; + getAll(): Promise; + getElevation(buildingIndex: number): Promise; + getAllElevation(): Promise; + getTerrainElevation(buildingIndex: number): Promise; + getAllTerrainElevation(): Promise; + getAddress(buildingIndex: number): Promise; + getAllAddress(): Promise; + getSiteIndex(buildingIndex: number): Promise; + getAllSiteIndex(): Promise; + getSite(buildingIndex: number): Promise; + getElementIndex(buildingIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(buildingIndex: number): Promise; +} +export declare class Building implements IBuilding { + index: number; + elevation?: number; + terrainElevation?: number; + address?: string; + siteIndex?: number; + site?: ISite; + elementIndex?: number; + element?: IElement; + static createFromTable(table: IBuildingTable, index: number): Promise; +} +export declare class BuildingTable implements IBuildingTable { + private document; + private entityTable; + static createFromDocument(document: VimDocument): Promise; + getCount(): Promise; + get(buildingIndex: number): Promise; + getAll(): Promise; + getElevation(buildingIndex: number): Promise; + getAllElevation(): Promise; + getTerrainElevation(buildingIndex: number): Promise; + getAllTerrainElevation(): Promise; + getAddress(buildingIndex: number): Promise; + getAllAddress(): Promise; + getSiteIndex(buildingIndex: number): Promise; + getAllSiteIndex(): Promise; + getSite(buildingIndex: number): Promise; + getElementIndex(buildingIndex: number): Promise; + getAllElementIndex(): Promise; + getElement(buildingIndex: number): Promise; +} export declare class VimDocument { asset: IAssetTable | undefined; displayUnit: IDisplayUnitTable | undefined; @@ -3349,6 +3477,8 @@ export declare class VimDocument { viewSheetInViewSheetSet: IViewSheetInViewSheetSetTable | undefined; viewInViewSheetSet: IViewInViewSheetSetTable | undefined; viewInViewSheet: IViewInViewSheetTable | undefined; + site: ISiteTable | undefined; + building: IBuildingTable | undefined; entities: BFast; strings: string[] | undefined; private constructor(); diff --git a/src/ts/package.json b/src/ts/package.json index 0853030f..bf424868 100644 --- a/src/ts/package.json +++ b/src/ts/package.json @@ -1,6 +1,6 @@ { "name": "vim-format", - "version": "1.0.6-dev.235", + "version": "1.0.6-dev.236", "description": "The VIM format is a modern and efficient open 3D data interchange format designed for BIM and manufacturing data optimized for efficient loading and rendering on low-power devices.", "directories": { "test": "tests" From 38f780b4560f7c3ac49eb7cf67bb6066a95e275e Mon Sep 17 00:00:00 2001 From: simon Date: Tue, 27 Feb 2024 11:30:28 -0500 Subject: [PATCH 096/111] made logs field public --- src/ts/package.json | 2 +- src/ts/src/remoteBuffer.ts | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/ts/package.json b/src/ts/package.json index bf424868..c24a4034 100644 --- a/src/ts/package.json +++ b/src/ts/package.json @@ -1,6 +1,6 @@ { "name": "vim-format", - "version": "1.0.6-dev.236", + "version": "1.0.6-dev.238", "description": "The VIM format is a modern and efficient open 3D data interchange format designed for BIM and manufacturing data optimized for efficient loading and rendering on low-power devices.", "directories": { "test": "tests" diff --git a/src/ts/src/remoteBuffer.ts b/src/ts/src/remoteBuffer.ts index 0c7b4160..e50579d9 100644 --- a/src/ts/src/remoteBuffer.ts +++ b/src/ts/src/remoteBuffer.ts @@ -72,8 +72,9 @@ export class RemoteBuffer { url: string maxConcurency: number = RemoteBufferMaxConcurency onProgress: (progress : IProgressLogs) => void + logs : Logger private _tracker: RequestTracker - private logs : Logger + private _queue: RetryRequest[] = [] private _active: Set = new Set() private _encoded: RemoteValue From 2f986cf839450864eee6822fef1819373d91478c Mon Sep 17 00:00:00 2001 From: simon Date: Tue, 27 Feb 2024 13:41:35 -0500 Subject: [PATCH 097/111] Moved http scripts to http folder Moved g3d scripts to g3d folder --- src/ts/dist/bfast.d.ts | 2 +- src/ts/dist/bfast.js | 8 +- src/ts/dist/g3d/g3d.js | 598 ++++++++++++++++++++++++ src/ts/dist/g3d/g3dChunk.js | 53 +++ src/ts/dist/g3d/g3dMaterials.js | 49 ++ src/ts/dist/g3d/g3dMesh.js | 86 ++++ src/ts/dist/g3d/g3dScene.js | 104 +++++ src/ts/dist/http/logging.js | 25 + src/ts/dist/http/remoteBuffer.js | 149 ++++++ src/ts/dist/http/remoteValue.js | 39 ++ src/ts/dist/http/requestTracker.js | 107 +++++ src/ts/dist/http/requester.js | 73 +++ src/ts/dist/http/retriableRequest.js | 37 ++ src/ts/dist/index.d.ts | 18 +- src/ts/dist/index.js | 18 +- src/ts/dist/remoteBuffer.d.ts | 24 +- src/ts/dist/remoteBuffer.js | 84 +--- src/ts/dist/remoteVimx.d.ts | 10 +- src/ts/dist/remoteVimx.js | 10 +- src/ts/dist/requester.js | 4 +- src/ts/dist/retriableRequest.js | 37 ++ src/ts/dist/types/remoteBuffer.d.ts | 5 +- src/ts/package.json | 2 +- src/ts/src/bfast.ts | 8 +- src/ts/src/{ => g3d}/g3d.ts | 2 +- src/ts/src/{ => g3d}/g3dChunk.ts | 2 +- src/ts/src/{ => g3d}/g3dMaterials.ts | 2 +- src/ts/src/{ => g3d}/g3dMesh.ts | 0 src/ts/src/{ => g3d}/g3dScene.ts | 2 +- src/ts/src/{ => http}/logging.ts | 0 src/ts/src/{ => http}/remoteBuffer.ts | 2 +- src/ts/src/{ => http}/remoteValue.ts | 0 src/ts/src/{ => http}/requestTracker.ts | 0 src/ts/src/{ => http}/requester.ts | 0 src/ts/src/http/retriableRequest.ts | 53 +++ src/ts/src/index.ts | 18 +- src/ts/src/remoteVimx.ts | 10 +- src/ts/tsconfig.json | 2 +- 38 files changed, 1489 insertions(+), 154 deletions(-) create mode 100644 src/ts/dist/g3d/g3d.js create mode 100644 src/ts/dist/g3d/g3dChunk.js create mode 100644 src/ts/dist/g3d/g3dMaterials.js create mode 100644 src/ts/dist/g3d/g3dMesh.js create mode 100644 src/ts/dist/g3d/g3dScene.js create mode 100644 src/ts/dist/http/logging.js create mode 100644 src/ts/dist/http/remoteBuffer.js create mode 100644 src/ts/dist/http/remoteValue.js create mode 100644 src/ts/dist/http/requestTracker.js create mode 100644 src/ts/dist/http/requester.js create mode 100644 src/ts/dist/http/retriableRequest.js create mode 100644 src/ts/dist/retriableRequest.js rename src/ts/src/{ => g3d}/g3d.ts (99%) rename src/ts/src/{ => g3d}/g3dChunk.ts (98%) rename src/ts/src/{ => g3d}/g3dMaterials.ts (98%) rename src/ts/src/{ => g3d}/g3dMesh.ts (100%) rename src/ts/src/{ => g3d}/g3dScene.ts (99%) rename src/ts/src/{ => http}/logging.ts (100%) rename src/ts/src/{ => http}/remoteBuffer.ts (99%) rename src/ts/src/{ => http}/remoteValue.ts (100%) rename src/ts/src/{ => http}/requestTracker.ts (100%) rename src/ts/src/{ => http}/requester.ts (100%) create mode 100644 src/ts/src/http/retriableRequest.ts diff --git a/src/ts/dist/bfast.d.ts b/src/ts/dist/bfast.d.ts index 33cea1c5..d1d39cb6 100644 --- a/src/ts/dist/bfast.d.ts +++ b/src/ts/dist/bfast.d.ts @@ -1,7 +1,7 @@ /** * @module vim-ts */ -import { RemoteBuffer } from './remoteBuffer'; +import { RemoteBuffer } from './http/remoteBuffer'; declare type NumericArrayConstructor = Int8ArrayConstructor | Uint8ArrayConstructor | Int16ArrayConstructor | Uint16ArrayConstructor | Int32ArrayConstructor | Uint32ArrayConstructor | BigInt64ArrayConstructor | BigUint64ArrayConstructor | Float32ArrayConstructor | Float64ArrayConstructor; export declare type NumericArray = Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array | BigInt64Array | BigUint64Array; export declare class Range { diff --git a/src/ts/dist/bfast.js b/src/ts/dist/bfast.js index e88e2bb6..83904969 100644 --- a/src/ts/dist/bfast.js +++ b/src/ts/dist/bfast.js @@ -27,8 +27,8 @@ var __importStar = (this && this.__importStar) || function (mod) { }; Object.defineProperty(exports, "__esModule", { value: true }); exports.BFast = exports.BFastHeader = exports.typeSize = exports.parseName = exports.Range = void 0; -const remoteValue_1 = require("./remoteValue"); -const remoteBuffer_1 = require("./remoteBuffer"); +const remoteValue_1 = require("./http/remoteValue"); +const remoteBuffer_1 = require("./http/remoteBuffer"); const pako = __importStar(require("pako")); class Range { constructor(start, end) { @@ -176,12 +176,12 @@ exports.BFastHeader = BFastHeader; * Remote mode can transition to buffer mode if server doesnt support partial http request */ class BFast { - constructor(source, offset = 0, name) { + constructor(source, offset = 0, name = '') { this.source = typeof source === 'string' ? new remoteBuffer_1.RemoteBuffer(source) : source; this.offset = offset; - this.name = name ?? (typeof source === 'string' ? source : ''); + this.name = name; this._header = new remoteValue_1.RemoteValue(() => this.requestHeader(), name + '.header'); this._children = new Map(); this._ranges = new remoteValue_1.RemoteValue(() => this.requestRanges(), name + '.ranges'); diff --git a/src/ts/dist/g3d/g3d.js b/src/ts/dist/g3d/g3d.js new file mode 100644 index 00000000..aec3893a --- /dev/null +++ b/src/ts/dist/g3d/g3d.js @@ -0,0 +1,598 @@ +"use strict"; +/** + * @module vim-ts + */ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.G3d = exports.VimAttributes = void 0; +const bfast_1 = require("../bfast"); +/** + * See https://github.com/vimaec/vim#vim-geometry-attributes + */ +class VimAttributes { +} +exports.VimAttributes = VimAttributes; +VimAttributes.positions = 'g3d:vertex:position:0:float32:3'; +VimAttributes.indices = 'g3d:corner:index:0:int32:1'; +VimAttributes.instanceMeshes = 'g3d:instance:mesh:0:int32:1'; +VimAttributes.instanceTransforms = 'g3d:instance:transform:0:float32:16'; +VimAttributes.instanceNodes = 'g3d:instance:element:0:int32:1'; +VimAttributes.instanceFlags = 'g3d:instance:flags:0:uint16:1'; +VimAttributes.meshSubmeshes = 'g3d:mesh:submeshoffset:0:int32:1'; +VimAttributes.submeshIndexOffsets = 'g3d:submesh:indexoffset:0:int32:1'; +VimAttributes.submeshMaterials = 'g3d:submesh:material:0:int32:1'; +VimAttributes.materialColors = 'g3d:material:color:0:float32:4'; +VimAttributes.all = [ + VimAttributes.positions, + VimAttributes.indices, + VimAttributes.instanceMeshes, + VimAttributes.instanceTransforms, + VimAttributes.instanceFlags, + VimAttributes.meshSubmeshes, + VimAttributes.submeshIndexOffsets, + VimAttributes.submeshMaterials, + VimAttributes.materialColors +]; +/** + * G3D is a simple, efficient, generic binary format for storing and transmitting geometry. + * The G3D format is designed to be used either as a serialization format or as an in-memory data structure. + * A G3d with specific attributes according to the VIM format specification. + * See https://github.com/vimaec/vim#vim-geometry-attributes for the vim specification. + * See https://github.com/vimaec/g3d for the g3d specification. + */ +class G3d { + constructor(instanceMeshes, instanceFlags, instanceTransforms, instanceNodes, meshSubmeshes, submeshIndexOffsets, submeshMaterials, indices, positions, materialColors) { + /** + * Opaque white + */ + this.DEFAULT_COLOR = new Float32Array([1, 1, 1, 1]); + this.getVertexCount = () => this.positions.length / G3d.POSITION_SIZE; + this.getIndexCount = () => this.indices.length; + // ------------- Meshes ----------------- + this.getMeshCount = () => this.meshSubmeshes.length; + // ------------- Instances ----------------- + this.getInstanceCount = () => this.instanceMeshes.length; + // ------------- Material ----------------- + this.getMaterialCount = () => this.materialColors.length / G3d.COLOR_SIZE; + this.instanceMeshes = instanceMeshes; + this.instanceFlags = instanceFlags; + this.instanceTransforms = instanceTransforms; + this.instanceNodes = instanceNodes; + this.meshSubmeshes = meshSubmeshes; + this.submeshIndexOffset = submeshIndexOffsets; + this.submeshMaterial = submeshMaterials; + this.indices = indices instanceof Uint32Array ? indices : new Uint32Array(indices.buffer); + this.positions = positions; + this.materialColors = materialColors; + if (this.instanceFlags === undefined) { + this.instanceFlags = new Uint16Array(this.instanceMeshes.length); + } + if (this.instanceNodes === undefined) { + this.instanceNodes = new Int32Array(instanceMeshes.length); + for (let i = 0; i < this.instanceNodes.length; i++) { + this.instanceNodes[i] = i; + } + } + this.meshVertexOffsets = this.computeMeshVertexOffsets(); + this.rebaseIndices(); + this.meshInstances = this.computeMeshInstances(); + this.meshOpaqueCount = this.computeMeshOpaqueCount(); + this.sortSubmeshes(); + const range = this.computeSubmeshVertexRange(); + this.submeshVertexStart = range.start; + this.submeshVertexEnd = range.end; + } + computeSubmeshVertexRange() { + const submeshCount = this.getSubmeshCount(); + const start = new Int32Array(submeshCount); + const end = new Int32Array(submeshCount); + for (let sub = 0; sub < submeshCount; sub++) { + let min = Number.MAX_SAFE_INTEGER; + let max = Number.MIN_SAFE_INTEGER; + const subStart = this.getSubmeshIndexStart(sub); + const subEnd = this.getSubmeshIndexEnd(sub); + for (let i = subStart; i < subEnd; i++) { + const index = this.indices[i]; + min = Math.min(min, index); + max = Math.max(min, index); + } + start[sub] = min; + end[sub] = max; + } + return { start, end }; + } + static async createFromPath(path) { + const f = await fetch(path); + const buffer = await f.arrayBuffer(); + const bfast = new bfast_1.BFast(buffer); + return this.createFromBfast(bfast); + } + static async createFromBfast(bfast) { + const values = await Promise.all([ + bfast.getInt32Array(VimAttributes.instanceMeshes), + bfast.getUint16Array(VimAttributes.instanceFlags), + bfast.getFloat32Array(VimAttributes.instanceTransforms), + bfast.getInt32Array(VimAttributes.instanceNodes), + bfast.getInt32Array(VimAttributes.meshSubmeshes), + bfast.getInt32Array(VimAttributes.submeshIndexOffsets), + bfast.getInt32Array(VimAttributes.submeshMaterials), + bfast.getInt32Array(VimAttributes.indices), + bfast.getFloat32Array(VimAttributes.positions), + bfast.getFloat32Array(VimAttributes.materialColors) + ]); + return new G3d(...values); + } + /** + * Computes the index of the first vertex of each mesh + */ + computeMeshVertexOffsets() { + const result = new Int32Array(this.getMeshCount()); + for (let m = 0; m < result.length; m++) { + let min = Number.MAX_SAFE_INTEGER; + const start = this.getMeshIndexStart(m, 'all'); + const end = this.getMeshIndexEnd(m, 'all'); + for (let i = start; i < end; i++) { + min = Math.min(min, this.indices[i]); + } + result[m] = min; + } + return result; + } + /** + * Computes all instances pointing to each mesh. + */ + computeMeshInstances() { + const result = new Array(this.getMeshCount()); + for (let i = 0; i < this.instanceMeshes.length; i++) { + const mesh = this.instanceMeshes[i]; + if (mesh < 0) + continue; + const instanceIndices = result[mesh]; + if (instanceIndices) + instanceIndices.push(i); + else + result[mesh] = [i]; + } + return result; + } + /** + * Reorders submeshIndexOffset, submeshMaterials and indices + * such that for each mesh, submeshes are sorted according to material alpha. + * This enables efficient splitting of arrays into opaque and transparent continuous ranges. + */ + sortSubmeshes() { + // We need to compute where submeshes end before we can reorder them. + const submeshEnd = this.computeSubmeshEnd(); + // We need to compute mesh index offsets from before we swap thins around to recompute new submesh offsets. + const meshIndexOffsets = this.computeMeshIndexOffsets(); + const meshCount = this.getMeshCount(); + const meshReordered = new Array(meshCount); + const submeshArrays = [ + this.submeshIndexOffset, + this.submeshMaterial, + submeshEnd + ]; + // Largest mesh size thus minimum buffer size to use to reorder indices. + const largestMesh = this.reorderSubmeshes(submeshArrays, meshReordered); + this.reorderIndices(meshIndexOffsets, submeshEnd, meshReordered, largestMesh); + } + /** + * Stores result of getSubmeshIndexEnd for each submesh in an array + */ + computeSubmeshEnd() { + const submeshCount = this.getSubmeshCount(); + const result = new Int32Array(submeshCount); + for (let s = 0; s < submeshCount; s++) { + result[s] = this.getSubmeshIndexEnd(s); + } + return result; + } + /** + * Stores result of getMeshIndexStart for each mesh in an array + */ + computeMeshIndexOffsets() { + const meshCount = this.getMeshCount(); + const result = new Int32Array(meshCount); + for (let m = 0; m < meshCount; m++) { + result[m] = this.getMeshIndexStart(m, 'all'); + } + return result; + } + /** + * Reorder submesh arrays and returns size of largest reordered mesh + */ + reorderSubmeshes(submeshArrays, reordered) { + const meshCount = this.getMeshCount(); + let largestMesh = 0; + for (let m = 0; m < meshCount; m++) { + const subStart = this.getMeshSubmeshStart(m, 'all'); + const subEnd = this.getMeshSubmeshEnd(m, 'all'); + if (subEnd - subStart <= 1) { + continue; + } + largestMesh = Math.max(largestMesh, this.getMeshIndexCount(m, 'all')); + reordered[m] = this.Sort(subStart, subEnd, (i) => this.getSubmeshAlpha(i), submeshArrays); + } + return largestMesh; + } + /** + * Sorts the range from start to end in every array provided in arrays in increasing criterion order. + * Using a simple bubble sort, there is a limited number of submeshes per mesh. + */ + Sort(start, end, criterion, arrays) { + let swapped = false; + while (true) { + let loop = false; + for (let i = start; i < end - 1; i++) { + if (criterion(i) < criterion(i + 1)) { + loop = true; + swapped = true; + for (let j = 0; j < arrays.length; j++) { + const array = arrays[j]; + const t = array[i]; + array[i] = array[i + 1]; + array[i + 1] = t; + } + } + } + if (!loop) { + break; + } + } + return swapped; + } + /** + * Reorders the index buffer to match the new order of the submesh arrays. + */ + reorderIndices(meshIndexOffsets, submeshEnd, meshReordered, bufferSize) { + const meshCount = this.getMeshCount(); + const buffer = new Float32Array(bufferSize); + for (let m = 0; m < meshCount; m++) { + if (!meshReordered[m]) + continue; + const meshOffset = meshIndexOffsets[m]; + const subStart = this.getMeshSubmeshStart(m, 'all'); + const subEnd = this.getMeshSubmeshEnd(m, 'all'); + let index = 0; + // Copy indices -> buffer, in sorted order. + for (let s = subStart; s < subEnd; s++) { + const start = this.submeshIndexOffset[s]; + const end = submeshEnd[s]; + // Change submesh offset to match new ordering + this.submeshIndexOffset[s] = meshOffset + index; + for (let i = start; i < end; i++) { + buffer[index++] = this.indices[i]; + } + } + // Copy buffer -> indices + for (let i = 0; i < index; i++) { + this.indices[meshOffset + i] = buffer[i]; + } + } + } + /** + * Rebase indices to be relative to its own mesh instead of to the whole g3d + */ + rebaseIndices() { + const count = this.getMeshCount(); + for (let m = 0; m < count; m++) { + const offset = this.meshVertexOffsets[m]; + const start = this.getMeshIndexStart(m, 'all'); + const end = this.getMeshIndexEnd(m, 'all'); + for (let i = start; i < end; i++) { + this.indices[i] -= offset; + } + } + } + unbaseIndices() { + const count = this.getMeshCount(); + for (let m = 0; m < count; m++) { + const offset = this.meshVertexOffsets[m]; + const start = this.getMeshIndexStart(m, 'all'); + const end = this.getMeshIndexEnd(m, 'all'); + for (let i = start; i < end; i++) { + this.indices[i] += offset; + } + } + } + /** + * Computes an array where true if any of the materials used by a mesh has transparency. + */ + computeMeshOpaqueCount() { + const result = new Int32Array(this.getMeshCount()); + for (let m = 0; m < result.length; m++) { + const subStart = this.getMeshSubmeshStart(m, 'all'); + const subEnd = this.getMeshSubmeshEnd(m, 'all'); + for (let s = subStart; s < subEnd; s++) { + const alpha = this.getSubmeshAlpha(s); + result[m] += alpha === 1 ? 1 : 0; + } + } + return result; + } + // ------------- All ----------------- + /**Given VIM instance indices returns the corresponding G3d indices */ + remapInstances(instances) { + const map = new Map(); + for (let i = 0; i < instances.length; i++) { + map.set(this.instanceNodes[i], i); + } + return instances.map((i) => map.get(i)); + } + getMeshInstanceCount(mesh) { + return this.meshInstances[mesh]?.length ?? 0; + } + getMeshIndexStart(mesh, section = 'all') { + const sub = this.getMeshSubmeshStart(mesh, section); + return this.getSubmeshIndexStart(sub); + } + getMeshIndexEnd(mesh, section = 'all') { + const sub = this.getMeshSubmeshEnd(mesh, section); + return this.getSubmeshIndexEnd(sub - 1); + } + getMeshIndexCount(mesh, section = 'all') { + return (this.getMeshIndexEnd(mesh, section) - + this.getMeshIndexStart(mesh, section)); + } + getMeshVertexStart(mesh) { + return this.meshVertexOffsets[mesh]; + } + getMeshVertexEnd(mesh) { + return mesh < this.meshVertexOffsets.length - 1 + ? this.meshVertexOffsets[mesh + 1] + : this.getVertexCount(); + } + getMeshVertexCount(mesh) { + return this.getMeshVertexEnd(mesh) - this.getMeshVertexStart(mesh); + } + getMeshSubmeshStart(mesh, section = 'all') { + if (section === 'transparent') { + return this.getMeshSubmeshEnd(mesh, 'opaque'); + } + return this.meshSubmeshes[mesh]; + } + getMeshSubmeshEnd(mesh, section = 'all') { + if (section === 'opaque') { + return this.meshSubmeshes[mesh] + this.meshOpaqueCount[mesh]; + } + return mesh < this.meshSubmeshes.length - 1 + ? this.meshSubmeshes[mesh + 1] + : this.getSubmeshCount(); + } + getMeshSubmeshCount(mesh, section = 'all') { + const end = this.getMeshSubmeshEnd(mesh, section); + const start = this.getMeshSubmeshStart(mesh, section); + return end - start; + } + getMeshHasTransparency(mesh) { + return this.getMeshSubmeshCount(mesh, 'transparent') > 0; + } + // ------------- Submeshes ----------------- + getSubmeshIndexStart(submesh) { + return submesh < this.submeshIndexOffset.length + ? this.submeshIndexOffset[submesh] + : this.indices.length; + } + getSubmeshIndexEnd(submesh) { + return submesh < this.submeshIndexOffset.length - 1 + ? this.submeshIndexOffset[submesh + 1] + : this.indices.length; + } + getSubmeshIndexCount(submesh) { + return this.getSubmeshIndexEnd(submesh) - this.getSubmeshIndexStart(submesh); + } + getSubmeshVertexStart(submesh) { + return this.submeshVertexStart[submesh]; + } + getSubmeshVertexEnd(submesh) { + return this.submeshVertexEnd[submesh]; + } + getSubmeshVertexCount(submesh) { + return this.getSubmeshVertexEnd(submesh) - this.getSubmeshVertexStart(submesh); + } + /** + * Returns color of given submesh as a 4-number array (RGBA) + * @param submesh g3d submesh index + */ + getSubmeshColor(submesh) { + return this.getMaterialColor(this.submeshMaterial[submesh]); + } + /** + * Returns color of given submesh as a 4-number array (RGBA) + * @param submesh g3d submesh index + */ + getSubmeshAlpha(submesh) { + return this.getMaterialAlpha(this.submeshMaterial[submesh]); + } + /** + * Returns true if submesh is transparent. + * @param submesh g3d submesh index + */ + getSubmeshIsTransparent(submesh) { + return this.getSubmeshAlpha(submesh) < 1; + } + /** + * Returns the total number of mesh in the g3d + */ + getSubmeshCount() { + return this.submeshIndexOffset.length; + } + /** + * Returns true if instance has given flag enabled. + * @param instance instance to check. + * @param flag to check against. + */ + getInstanceHasFlag(instance, flag) { + return (this.instanceFlags[instance] & flag) > 0; + } + /** + * Returns mesh index of given instance + * @param instance g3d instance index + */ + getInstanceMesh(instance) { + return this.instanceMeshes[instance]; + } + /** + * Returns an 16 number array representation of the matrix for given instance + * @param instance g3d instance index + */ + getInstanceMatrix(instance) { + return this.instanceTransforms.subarray(instance * G3d.MATRIX_SIZE, (instance + 1) * G3d.MATRIX_SIZE); + } + /** + * Returns color of given material as a 4-number array (RGBA) + * @param material g3d material index + */ + getMaterialColor(material) { + if (material < 0) + return this.DEFAULT_COLOR; + return this.materialColors.subarray(material * G3d.COLOR_SIZE, (material + 1) * G3d.COLOR_SIZE); + } + /** + * Returns the alpha component of given material + * @param material + */ + getMaterialAlpha(material) { + if (material < 0) + return 1; + const index = material * G3d.COLOR_SIZE + G3d.COLOR_SIZE - 1; + const result = this.materialColors[index]; + return result; + } + /** + * Concatenates two g3ds into a new g3d. + * @deprecated + */ + append(other) { + const _instanceFlags = new Uint16Array(this.instanceFlags.length + other.instanceFlags.length); + _instanceFlags.set(this.instanceFlags); + _instanceFlags.set(other.instanceFlags, this.instanceFlags.length); + const _instanceMeshes = new Int32Array(this.instanceMeshes.length + other.instanceMeshes.length); + _instanceMeshes.set(this.instanceMeshes); + _instanceMeshes.set(other.instanceMeshes.map(m => m >= 0 ? (m + this.meshSubmeshes.length) : -1), this.instanceMeshes.length); + const _instanceTransforms = new Float32Array(this.instanceTransforms.length + other.instanceTransforms.length); + _instanceTransforms.set(this.instanceTransforms); + _instanceTransforms.set(other.instanceTransforms, this.instanceTransforms.length); + const _positions = new Float32Array(this.positions.length + other.positions.length); + _positions.set(this.positions); + _positions.set(other.positions, this.positions.length); + this.unbaseIndices(); + other.unbaseIndices(); + const _indices = new Uint32Array(this.indices.length + other.indices.length); + _indices.set(this.indices); + _indices.set(other.indices.map(i => i + this.positions.length / 3), this.indices.length); + this.rebaseIndices(); + other.rebaseIndices(); + const _meshSubmeshes = new Int32Array(this.meshSubmeshes.length + other.meshSubmeshes.length); + _meshSubmeshes.set(this.meshSubmeshes); + _meshSubmeshes.set(other.meshSubmeshes.map(s => s + this.submeshIndexOffset.length), this.meshSubmeshes.length); + const _submeshIndexOffsets = new Int32Array(this.submeshIndexOffset.length + other.submeshIndexOffset.length); + _submeshIndexOffsets.set(this.submeshIndexOffset); + _submeshIndexOffsets.set(other.submeshIndexOffset.map(s => s + this.indices.length), this.submeshIndexOffset.length); + const _submeshMaterials = new Int32Array(this.submeshMaterial.length + other.submeshMaterial.length); + _submeshMaterials.set(this.submeshMaterial); + _submeshMaterials.set(other.submeshMaterial.map(s => s >= 0 ? (s + this.materialColors.length / 4) : -1), this.submeshMaterial.length); + const _materialColors = new Float32Array(this.materialColors.length + other.materialColors.length); + _materialColors.set(this.materialColors); + _materialColors.set(other.materialColors, this.materialColors.length); + const g3d = new G3d(_instanceMeshes, _instanceFlags, _instanceTransforms, undefined, _meshSubmeshes, _submeshIndexOffsets, _submeshMaterials, _indices, _positions, _materialColors); + return g3d; + } + validate() { + const isPresent = (attribute, label) => { + if (!attribute) { + throw new Error(`Missing Attribute Buffer: ${label}`); + } + }; + isPresent(this.positions, 'position'); + isPresent(this.indices, 'indices'); + isPresent(this.instanceMeshes, 'instanceMeshes'); + isPresent(this.instanceTransforms, 'instanceTransforms'); + isPresent(this.meshSubmeshes, 'meshSubmeshes'); + isPresent(this.submeshIndexOffset, 'submeshIndexOffset'); + isPresent(this.submeshMaterial, 'submeshMaterial'); + isPresent(this.materialColors, 'materialColors'); + // Basic + if (this.positions.length % G3d.POSITION_SIZE !== 0) { + throw new Error('Invalid position buffer, must be divisible by ' + G3d.POSITION_SIZE); + } + if (this.indices.length % 3 !== 0) { + throw new Error('Invalid Index Count, must be divisible by 3'); + } + for (let i = 0; i < this.indices.length; i++) { + if (this.indices[i] < 0 || this.indices[i] >= this.positions.length) { + throw new Error('Vertex index out of bound'); + } + } + // Instances + if (this.instanceMeshes.length !== + this.instanceTransforms.length / G3d.MATRIX_SIZE) { + throw new Error('Instance buffers mismatched'); + } + if (this.instanceTransforms.length % G3d.MATRIX_SIZE !== 0) { + throw new Error('Invalid InstanceTransform buffer, must respect arity ' + + G3d.MATRIX_SIZE); + } + for (let i = 0; i < this.instanceMeshes.length; i++) { + if (this.instanceMeshes[i] >= this.meshSubmeshes.length) { + throw new Error('Instance Mesh Out of range.'); + } + } + // Meshes + for (let i = 0; i < this.meshSubmeshes.length; i++) { + if (this.meshSubmeshes[i] < 0 || + this.meshSubmeshes[i] >= this.submeshIndexOffset.length) { + throw new Error('MeshSubmeshOffset out of bound at'); + } + } + for (let i = 0; i < this.meshSubmeshes.length - 1; i++) { + if (this.meshSubmeshes[i] >= this.meshSubmeshes[i + 1]) { + throw new Error('MeshSubmesh out of sequence.'); + } + } + // Submeshes + if (this.submeshIndexOffset.length !== this.submeshMaterial.length) { + throw new Error('Mismatched submesh buffers'); + } + for (let i = 0; i < this.submeshIndexOffset.length; i++) { + if (this.submeshIndexOffset[i] < 0 || + this.submeshIndexOffset[i] >= this.indices.length) { + throw new Error('SubmeshIndexOffset out of bound'); + } + } + for (let i = 0; i < this.submeshIndexOffset.length; i++) { + if (this.submeshIndexOffset[i] % 3 !== 0) { + throw new Error('Invalid SubmeshIndexOffset, must be divisible by 3'); + } + } + for (let i = 0; i < this.submeshIndexOffset.length - 1; i++) { + if (this.submeshIndexOffset[i] >= this.submeshIndexOffset[i + 1]) { + throw new Error('SubmeshIndexOffset out of sequence.'); + } + } + for (let i = 0; i < this.submeshMaterial.length; i++) { + if (this.submeshMaterial[i] >= this.materialColors.length) { + throw new Error('submeshMaterial out of bound'); + } + } + // Materials + if (this.materialColors.length % G3d.COLOR_SIZE !== 0) { + throw new Error('Invalid material color buffer, must be divisible by ' + G3d.COLOR_SIZE); + } + console.assert(this.meshInstances.length === this.getMeshCount()); + console.assert(this.meshOpaqueCount.length === this.getMeshCount()); + console.assert(this.meshSubmeshes.length === this.getMeshCount()); + console.assert(this.meshVertexOffsets.length === this.getMeshCount()); + for (let m = 0; m < this.getMeshCount(); m++) { + console.assert(this.getMeshSubmeshCount(m, 'opaque') + + this.getMeshSubmeshCount(m, 'transparent') === + this.getMeshSubmeshCount(m, 'all')); + console.assert(this.getMeshIndexCount(m, 'opaque') + + this.getMeshIndexCount(m, 'transparent') === + this.getMeshIndexCount(m, 'all')); + } + } +} +exports.G3d = G3d; +G3d.MATRIX_SIZE = 16; +G3d.COLOR_SIZE = 4; +G3d.POSITION_SIZE = 3; diff --git a/src/ts/dist/g3d/g3dChunk.js b/src/ts/dist/g3d/g3dChunk.js new file mode 100644 index 00000000..3b6dacf0 --- /dev/null +++ b/src/ts/dist/g3d/g3dChunk.js @@ -0,0 +1,53 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.G3dChunk = exports.MeshAttributes = void 0; +/** + * G3D is a simple, efficient, generic binary format for storing and transmitting geometry. + * The G3D format is designed to be used either as a serialization format or as an in-memory data structure. + * A G3d with specific attributes according to the VIM format specification. + * See https://github.com/vimaec/vim#vim-geometry-attributes for the vim specification. + * See https://github.com/vimaec/g3d for the g3d specification. + */ +/** + * See https://github.com/vimaec/vim#vim-geometry-attributes + */ +class MeshAttributes { +} +exports.MeshAttributes = MeshAttributes; +MeshAttributes.meshSubmeshOffset = 'g3d:mesh:submeshoffset:0:int32:1'; +MeshAttributes.meshOpaqueSubmeshCount = 'g3d:mesh:opaquesubmeshcount:0:int32:1'; +MeshAttributes.submeshIndexOffsets = 'g3d:submesh:indexoffset:0:int32:1'; +MeshAttributes.submeshVertexOffsets = 'g3d:submesh:vertexoffset:0:int32:1'; +MeshAttributes.submeshMaterials = 'g3d:submesh:material:0:int32:1'; +MeshAttributes.positions = 'g3d:vertex:position:0:float32:3'; +MeshAttributes.indices = 'g3d:corner:index:0:int32:1'; +class G3dChunk { + constructor(meshSubmeshOffset, meshOpaqueSubmeshCount, submeshIndexOffsets, submeshVertexOffsets, submeshMaterials, indices, positions) { + this.meshSubmeshOffset = meshSubmeshOffset; + this.meshOpaqueSubmeshCount = meshOpaqueSubmeshCount; + this.submeshIndexOffset = submeshIndexOffsets; + this.submeshVertexOffset = submeshVertexOffsets; + this.submeshMaterial = submeshMaterials; + this.indices = indices instanceof Uint32Array ? indices : new Uint32Array(indices.buffer); + this.positions = positions; + } + static async createFromBfast(bfast) { + const values = await Promise.all([ + bfast.getInt32Array(MeshAttributes.meshSubmeshOffset), + bfast.getInt32Array(MeshAttributes.meshOpaqueSubmeshCount), + bfast.getInt32Array(MeshAttributes.submeshIndexOffsets), + bfast.getInt32Array(MeshAttributes.submeshVertexOffsets), + bfast.getInt32Array(MeshAttributes.submeshMaterials), + bfast.getInt32Array(MeshAttributes.indices), + bfast.getFloat32Array(MeshAttributes.positions) + ]); + return new G3dChunk(...values); + } +} +exports.G3dChunk = G3dChunk; +G3dChunk.COLOR_SIZE = 4; +G3dChunk.POSITION_SIZE = 3; +/** + * Opaque white + */ +G3dChunk.DEFAULT_COLOR = new Float32Array([1, 1, 1, 1]); diff --git a/src/ts/dist/g3d/g3dMaterials.js b/src/ts/dist/g3d/g3dMaterials.js new file mode 100644 index 00000000..cba9a150 --- /dev/null +++ b/src/ts/dist/g3d/g3dMaterials.js @@ -0,0 +1,49 @@ +"use strict"; +/** + * @module vim-ts + */ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.G3dMaterial = exports.MaterialAttributes = void 0; +/** + * See https://github.com/vimaec/vim#vim-geometry-attributes + */ +class MaterialAttributes { +} +exports.MaterialAttributes = MaterialAttributes; +MaterialAttributes.materialColors = 'g3d:material:color:0:float32:4'; +/** + * G3D is a simple, efficient, generic binary format for storing and transmitting geometry. + * The G3D format is designed to be used either as a serialization format or as an in-memory data structure. + * A G3d with specific attributes according to the VIM format specification. + * See https://github.com/vimaec/vim#vim-geometry-attributes for the vim specification. + * See https://github.com/vimaec/g3d for the g3d specification. + */ +class G3dMaterial { + constructor(materialColors) { + this.getMaterialCount = () => this.materialColors.length / G3dMaterial.COLOR_SIZE; + this.materialColors = materialColors; + } + static async createFromBfast(bfast) { + const mats = await bfast.getFloat32Array(MaterialAttributes.materialColors); + return new G3dMaterial(mats); + } + /** + * Returns color of given material as a 4-number array (RGBA) + * @param material g3d material index + */ + getMaterialColor(material) { + if (material < 0) + return G3dMaterial.DEFAULT_COLOR; + return this.materialColors.subarray(material * G3dMaterial.COLOR_SIZE, (material + 1) * G3dMaterial.COLOR_SIZE); + } + getMaterialAlpha(material) { + if (material < 0) + return 1; + const index = material * G3dMaterial.COLOR_SIZE + G3dMaterial.COLOR_SIZE - 1; + const result = this.materialColors[index]; + return result; + } +} +exports.G3dMaterial = G3dMaterial; +G3dMaterial.COLOR_SIZE = 4; +G3dMaterial.DEFAULT_COLOR = new Float32Array([1, 1, 1, 1]); diff --git a/src/ts/dist/g3d/g3dMesh.js b/src/ts/dist/g3d/g3dMesh.js new file mode 100644 index 00000000..89da49fe --- /dev/null +++ b/src/ts/dist/g3d/g3dMesh.js @@ -0,0 +1,86 @@ +"use strict"; +/** + * @module vim-ts + */ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.G3dMesh = void 0; +const g3d_1 = require("./g3d"); +class G3dMesh { + constructor(scene, chunk, index) { + this.scene = scene; + this.chunk = chunk; + this.index = index; + } + // ------------- Mesh ----------------- + getVertexStart(section = 'all') { + const sub = this.getSubmeshStart(section); + return this.getSubmeshVertexStart(sub); + } + getVertexEnd(section = 'all') { + const sub = this.getSubmeshEnd(section); + return this.getSubmeshVertexStart(sub); + } + getVertexCount(section = 'all') { + return this.getVertexEnd(section) - this.getVertexStart(section); + } + getIndexStart(section = 'all') { + const sub = this.getSubmeshStart(section); + return this.getSubmeshIndexStart(sub); + } + getIndexEnd(section = 'all') { + const sub = this.getSubmeshEnd(section); + return this.getSubmeshIndexStart(sub); + } + getIndexCount(section = 'all') { + return this.getIndexEnd(section) - this.getIndexStart(section); + } + getHasTransparency(mesh) { + return this.getSubmeshCount('transparent') > 0; + } + // ------------- Submeshes ----------------- + getSubmeshStart(section) { + if (section === 'all' || section === 'opaque') { + return this.chunk.meshSubmeshOffset[this.index]; + } + return this.chunk.meshSubmeshOffset[this.index] + this.chunk.meshOpaqueSubmeshCount[this.index]; + } + getSubmeshEnd(section) { + if (section === 'opaque') { + return this.chunk.meshSubmeshOffset[this.index] + this.chunk.meshOpaqueSubmeshCount[this.index]; + } + if (this.index + 1 < this.chunk.meshSubmeshOffset.length) { + return this.chunk.meshSubmeshOffset[this.index + 1]; + } + return this.chunk.submeshIndexOffset.length; + } + getSubmeshCount(section) { + return this.getSubmeshEnd(section) - this.getSubmeshStart(section); + } + getSubmeshIndexStart(submesh) { + return submesh < this.chunk.submeshIndexOffset.length + ? this.chunk.submeshIndexOffset[submesh] + : this.chunk.indices.length; + } + getSubmeshIndexEnd(submesh) { + return submesh < this.chunk.submeshIndexOffset.length - 1 + ? this.chunk.submeshIndexOffset[submesh + 1] + : this.chunk.indices.length; + } + getSubmeshIndexCount(submesh) { + return this.getSubmeshIndexEnd(submesh) - this.getSubmeshIndexStart(submesh); + } + getSubmeshVertexStart(submesh) { + return submesh < this.chunk.submeshIndexOffset.length + ? this.chunk.submeshVertexOffset[submesh] + : this.chunk.positions.length / g3d_1.G3d.POSITION_SIZE; + } + getSubmeshVertexEnd(submesh) { + return submesh < this.chunk.submeshVertexOffset.length - 1 + ? this.chunk.submeshVertexOffset[submesh + 1] + : this.chunk.positions.length / g3d_1.G3d.POSITION_SIZE; + } + getSubmeshVertexCount(submesh) { + return this.getSubmeshVertexEnd(submesh) - this.getSubmeshVertexStart(submesh); + } +} +exports.G3dMesh = G3dMesh; diff --git a/src/ts/dist/g3d/g3dScene.js b/src/ts/dist/g3d/g3dScene.js new file mode 100644 index 00000000..9c0f5e83 --- /dev/null +++ b/src/ts/dist/g3d/g3dScene.js @@ -0,0 +1,104 @@ +"use strict"; +/** + * @module vim-ts + */ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.G3dScene = exports.SceneAttributes = void 0; +const g3d_1 = require("./g3d"); +/** + * See https://github.com/vimaec/vim#vim-geometry-attributes + */ +class SceneAttributes { +} +exports.SceneAttributes = SceneAttributes; +SceneAttributes.chunkCount = 'g3d:chunk:count:0:int32:1'; +SceneAttributes.instanceMesh = 'g3d:instance:mesh:0:int32:1'; +SceneAttributes.instanceMatrix = 'g3d:instance:transform:0:float32:16'; +SceneAttributes.instanceNodes = 'g3d:instance:node:0:int32:1'; +SceneAttributes.instanceGroups = 'g3d:instance:group:0:int32:1'; +SceneAttributes.instanceTags = 'g3d:instance:tag:0:int64:1'; +SceneAttributes.instanceFlags = 'g3d:instance:tag:0:uint16:1'; +SceneAttributes.instanceMins = 'g3d:instance:min:0:float32:3'; +SceneAttributes.instanceMaxs = 'g3d:instance:max:0:float32:3'; +SceneAttributes.meshChunk = 'g3d:mesh:chunk:0:int32:1'; +SceneAttributes.meshChunkIndices = 'g3d:mesh:chunkindex:0:int32:1'; +SceneAttributes.meshIndexCounts = 'g3d:mesh:indexcount:0:int32:1'; +SceneAttributes.meshVertexCounts = 'g3d:mesh:vertexcount:0:int32:1'; +SceneAttributes.meshOpaqueIndexCount = "g3d:mesh:opaqueindexcount:0:int32:1"; +SceneAttributes.meshOpaqueVertexCount = "g3d:mesh:opaquevertexcount:0:int32:1"; +/** + * Represents the index, as in book index, of a collection of G3dMesh. + * Allows to find and download G3dMesh as needed. + * Allows to preallocate geometry to render G3dMeshes. + */ +class G3dScene { + constructor(chunkCount, instanceMeshes, instanceMatrices, instanceNodes, instanceGroups, instanceTags, instanceFlags, instanceMins, instanceMaxs, meshChunks, meshChunkIndices, meshIndexCounts, meshVertexCounts, meshOpaqueIndexCounts, meshOpaqueVertexCounts) { + this.chunkCount = chunkCount[0]; + this.instanceMeshes = instanceMeshes; + this.instanceMatrices = instanceMatrices; + this.instanceNodes = instanceNodes; + this.instanceGroups = instanceGroups; + this.instanceTags = instanceTags; + this.instanceFlags = instanceFlags; + this.instanceMins = instanceMins; + this.instanceMaxs = instanceMaxs; + this.meshChunks = meshChunks; + this.meshChunkIndices = meshChunkIndices; + this.meshIndexCounts = meshIndexCounts; + this.meshVertexCounts = meshVertexCounts; + this.meshOpaqueIndexCounts = meshOpaqueIndexCounts; + this.meshOpaqueVertexCounts = meshOpaqueVertexCounts; + // Reverse instanceNodes + this.nodeToInstance = new Map(); + for (let i = 0; i < this.instanceNodes.length; i++) { + this.nodeToInstance.set(this.instanceNodes[i], i); + } + } + static async createFromBfast(bfast) { + const values = await Promise.all([ + bfast.getInt32Array(SceneAttributes.chunkCount), + bfast.getInt32Array(SceneAttributes.instanceMesh), + bfast.getFloat32Array(SceneAttributes.instanceMatrix), + bfast.getInt32Array(SceneAttributes.instanceNodes), + bfast.getInt32Array(SceneAttributes.instanceGroups), + bfast.getBigInt64Array(SceneAttributes.instanceTags), + bfast.getUint16Array(SceneAttributes.instanceFlags), + bfast.getFloat32Array(SceneAttributes.instanceMins), + bfast.getFloat32Array(SceneAttributes.instanceMaxs), + bfast.getInt32Array(SceneAttributes.meshChunk), + bfast.getInt32Array(SceneAttributes.meshChunkIndices), + bfast.getInt32Array(SceneAttributes.meshIndexCounts), + bfast.getInt32Array(SceneAttributes.meshVertexCounts), + bfast.getInt32Array(SceneAttributes.meshOpaqueIndexCount), + bfast.getInt32Array(SceneAttributes.meshOpaqueVertexCount), + ]); + return new G3dScene(...values); + } + getMeshCount() { + return this.meshChunks.length; + } + getMeshIndexCount(mesh, section) { + const all = this.meshIndexCounts[mesh]; + if (section === 'all') + return all; + const opaque = this.meshOpaqueIndexCounts[mesh]; + return section === 'opaque' ? opaque : all - opaque; + } + getMeshVertexCount(mesh, section) { + const all = this.meshVertexCounts[mesh]; + if (section === 'all') + return all; + const opaque = this.meshOpaqueVertexCounts[mesh]; + return section === 'opaque' ? opaque : all - opaque; + } + getInstanceMin(instance) { + return this.instanceMins.subarray(instance * g3d_1.G3d.POSITION_SIZE); + } + getInstanceMax(instance) { + return this.instanceMaxs.subarray(instance * g3d_1.G3d.POSITION_SIZE); + } + getInstanceMatrix(instance) { + return this.instanceMatrices.subarray(instance * g3d_1.G3d.MATRIX_SIZE, (instance + 1) * g3d_1.G3d.MATRIX_SIZE); + } +} +exports.G3dScene = G3dScene; diff --git a/src/ts/dist/http/logging.js b/src/ts/dist/http/logging.js new file mode 100644 index 00000000..5fd14219 --- /dev/null +++ b/src/ts/dist/http/logging.js @@ -0,0 +1,25 @@ +"use strict"; +/** + * @module vim-ts + */ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.NoLog = exports.DefaultLog = exports.Logger = void 0; +class Logger { +} +exports.Logger = Logger; +class DefaultLog { + constructor() { + this.log = (s) => console.log(s); + this.warn = (s) => console.warn(s); + this.error = (s) => console.error(s); + } +} +exports.DefaultLog = DefaultLog; +class NoLog { + constructor() { + this.log = (s) => { }; + this.warn = (s) => { }; + this.error = (s) => { }; + } +} +exports.NoLog = NoLog; diff --git a/src/ts/dist/http/remoteBuffer.js b/src/ts/dist/http/remoteBuffer.js new file mode 100644 index 00000000..6266ff57 --- /dev/null +++ b/src/ts/dist/http/remoteBuffer.js @@ -0,0 +1,149 @@ +"use strict"; +/** + * @module vim-ts + */ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.RemoteBuffer = exports.RetryRequest = exports.setRemoteBufferMaxConcurency = void 0; +const remoteValue_1 = require("./remoteValue"); +const requestTracker_1 = require("./requestTracker"); +const logging_1 = require("./logging"); +let RemoteBufferMaxConcurency = 10; +function setRemoteBufferMaxConcurency(value) { + RemoteBufferMaxConcurency = value; +} +exports.setRemoteBufferMaxConcurency = setRemoteBufferMaxConcurency; +class RetryRequest { + constructor(url, range, + // eslint-disable-next-line no-undef + responseType) { + this.url = url; + this.range = range; + this.responseType = responseType; + } + abort() { + this.xhr?.abort(); + } + send() { + this.xhr?.abort(); + const xhr = new XMLHttpRequest(); + xhr.open('GET', this.url); + xhr.responseType = this.responseType; + if (this.range) { + xhr.setRequestHeader('Range', this.range); + } + xhr.onprogress = (e) => { + this.onProgress?.(e); + }; + xhr.onload = (e) => { + this.onProgress?.(e); + this.onLoad?.(xhr.response); + }; + xhr.onerror = (_) => { + this.onError?.(); + }; + xhr.send(); + this.xhr = xhr; + } +} +exports.RetryRequest = RetryRequest; +/** + * Wrapper to provide tracking for all webrequests via request logger. + */ +class RemoteBuffer { + constructor(url) { + this.maxConcurency = RemoteBufferMaxConcurency; + this._queue = []; + this._active = new Set(); + this.url = url; + this.logs = new logging_1.NoLog(); + this._tracker = new requestTracker_1.RequestTracker(url, this.logs); + this._tracker.onUpdate = (p) => this.onProgress?.(p); + this._encoded = new remoteValue_1.RemoteValue(() => this.requestEncoding()); + } + async requestEncoding() { + const xhr = new XMLHttpRequest(); + xhr.open('HEAD', this.url); + xhr.send(); + this.logs.log(`Requesting header for ${this.url}`); + const promise = new Promise((resolve, reject) => { + xhr.onload = (_) => { + let encoding; + try { + encoding = xhr.getResponseHeader('content-encoding'); + } + catch (e) { + this.logs.error(e); + } + resolve(encoding ?? undefined); + }; + xhr.onerror = (_) => resolve(undefined); + }); + const encoding = await promise; + const encoded = !!encoding; + this.logs.log(`Encoding for ${this.url} = ${encoding}`); + if (encoded) { + this.logs.log(`Defaulting to download strategy for encoded content at ${this.url}`); + } + return encoded; + } + abort() { + this._active.forEach(request => { + request.abort(); + }); + this._active.clear(); + this._queue.length = 0; + } + async http(range, label) { + const useRange = range && !(await this._encoded.get()); + const rangeStr = useRange + ? `bytes=${range.start}-${range.end - 1}` + : undefined; + const request = new RetryRequest(this.url, rangeStr, 'arraybuffer'); + request.msg = useRange + ? `${label} : [${range.start}, ${range.end}] of ${this.url}` + : `${label} of ${this.url}`; + this.enqueue(request); + return new Promise((resolve, reject) => { + this._tracker.start(label); + request.onProgress = (e) => { + this._tracker.update(label, e); + }; + request.onLoad = (result) => { + this._tracker.end(label); + resolve(result); + this.end(request); + }; + request.onError = () => { + this._tracker.fail(label); + this.retry(request); + }; + }); + } + enqueue(xhr) { + this._queue.push(xhr); + this.next(); + } + retry(xhr) { + this._active.delete(xhr); + this.maxConcurency = Math.max(1, this.maxConcurency - 1); + setTimeout(() => this.enqueue(xhr), 2000); + } + end(xhr) { + this._active.delete(xhr); + this.next(); + } + next() { + if (this._queue.length === 0) { + return; + } + if (this._active.size >= this.maxConcurency) { + return; + } + const next = this._queue[0]; + this._queue.shift(); + this._active.add(next); + next.send(); + this.logs.log('Starting ' + next.msg); + } +} +exports.RemoteBuffer = RemoteBuffer; diff --git a/src/ts/dist/http/remoteValue.js b/src/ts/dist/http/remoteValue.js new file mode 100644 index 00000000..e28c42ad --- /dev/null +++ b/src/ts/dist/http/remoteValue.js @@ -0,0 +1,39 @@ +"use strict"; +/** + * @module vim-ts + */ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.RemoteValue = void 0; +/** + * Returns a value from cache or queue up existing request or start a new requests + */ +class RemoteValue { + constructor(getter, label) { + this._getter = getter; + this.label = label ?? ''; + } + abort() { + this._request = undefined; + } + /** + * Returns a value from cache or queue up existing request or start a new requests + */ + get() { + if (this._value !== undefined) { + // console.log(this.label + ' returning cached value ') + return Promise.resolve(this._value); + } + if (this._request) { + // console.log(this.label + ' returning existing request') + return this._request; + } + // console.log(this.label + ' creating new request') + this._request = this._getter().then((value) => { + this._value = value; + this._request = undefined; + return this._value; + }); + return this._request; + } +} +exports.RemoteValue = RemoteValue; diff --git a/src/ts/dist/http/requestTracker.js b/src/ts/dist/http/requestTracker.js new file mode 100644 index 00000000..e2cef64b --- /dev/null +++ b/src/ts/dist/http/requestTracker.js @@ -0,0 +1,107 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.RequestTracker = void 0; +const logging_1 = require("./logging"); +/** + * Represents the state of a single web request + */ +class Request { + constructor(field) { + this.status = 'active'; + this.loaded = 0; + this.total = 0; + this.lengthComputable = true; + this.field = field; + } +} +/** + * Represents a collection of webrequests + * Will only send update signal at most every delay + * Provides convenient aggregation of metrics. + */ +class RequestTracker { + constructor(source, logger = new logging_1.NoLog()) { + this.all = new Map(); + this.lastUpdate = 0; + this.delay = 500; + this.sleeping = false; + /** + * callback on update, called at most every delay time. + */ + this.onUpdate = undefined; + this.source = source; + this.logs = logger; + } + /** + * Returns the sum of .loaded across all requests + */ + get loaded() { + let result = 0; + this.all.forEach((request) => { + result += request.loaded; + }); + return result; + } + /** + * Returns the sum of .total across all requests + */ + get total() { + let result = 0; + this.all.forEach((request) => { + result += request.total; + }); + return result; + } + /** + * Starts tracking a new web request + */ + start(field) { + this.all.set(field, new Request(field)); + this.signal(); + } + /** + * Update an existing web request + */ + update(field, progress) { + const r = this.all.get(field); + if (!r) + throw new Error('Updating missing download'); + if (r.status !== 'active') + return; + r.loaded = progress.loaded; + r.total = progress.total; + r.lengthComputable = progress.lengthComputable; + this.signal(); + } + /** + * Notify a webrequest of failure + */ + fail(field) { + this.logs.error(`${field} failed`); + const download = this.all.get(field); + if (!download) + throw new Error('Failing missing download'); + download.status = 'failed'; + this.signal(); + } + /** + * Notify a webrequest of success + */ + end(field) { + this.logs.log(`${field} completed`); + const download = this.all.get(field); + if (!download) + throw new Error('Failing missing download'); + download.status = 'completed'; + // We don't want to throttle end update. + this.onUpdate?.(this); + } + signal() { + if (this.sleeping) + return; + this.sleeping = true; + setTimeout(() => (this.sleeping = false), this.delay); + this.onUpdate?.(this); + } +} +exports.RequestTracker = RequestTracker; diff --git a/src/ts/dist/http/requester.js b/src/ts/dist/http/requester.js new file mode 100644 index 00000000..707c9566 --- /dev/null +++ b/src/ts/dist/http/requester.js @@ -0,0 +1,73 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Requester = void 0; +const logging_1 = require("./logging"); +const remoteBuffer_1 = require("./remoteBuffer"); +const requestTracker_1 = require("./requestTracker"); +/** + * Wrapper to provide tracking for all webrequests via request logger. + */ +class Requester { + constructor(verbose = false) { + this.maxConcurency = 10; + this._queue = []; + this._active = new Set(); + this._logs = verbose ? new logging_1.DefaultLog() : new logging_1.NoLog(); + this._tracker = new requestTracker_1.RequestTracker(undefined, this._logs); + this._tracker.onUpdate = (p) => this.onProgress?.(p); + } + abort() { + this._active.forEach(request => { + request.abort(); + }); + this._active.clear(); + this._queue.length = 0; + } + async http(url, label) { + const request = new remoteBuffer_1.RetryRequest(url, undefined, 'arraybuffer'); + request.msg = url; + this.enqueue(request); + return new Promise((resolve, reject) => { + this._tracker.start(label); + request.onProgress = (e) => { + this._tracker.update(label, e); + }; + request.onLoad = (result) => { + this._tracker.end(label); + resolve(result); + this.end(request); + }; + request.onError = () => { + this._tracker.fail(label); + this.retry(request); + }; + }); + } + enqueue(xhr) { + this._queue.push(xhr); + this.next(); + } + retry(xhr) { + this._active.delete(xhr); + this.maxConcurency = Math.max(1, this.maxConcurency - 1); + setTimeout(() => this.enqueue(xhr), 2000); + } + end(xhr) { + this._active.delete(xhr); + this.next(); + } + next() { + if (this._queue.length === 0) { + return; + } + if (this._active.size >= this.maxConcurency) { + return; + } + const next = this._queue[0]; + this._queue.shift(); + this._active.add(next); + next.send(); + this._logs.log('Starting ' + next.msg); + } +} +exports.Requester = Requester; diff --git a/src/ts/dist/http/retriableRequest.js b/src/ts/dist/http/retriableRequest.js new file mode 100644 index 00000000..c27ea8ed --- /dev/null +++ b/src/ts/dist/http/retriableRequest.js @@ -0,0 +1,37 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.RetriableRequest = void 0; +class RetriableRequest { + constructor(url, range, + // eslint-disable-next-line no-undef + responseType) { + this.url = url; + this.range = range; + this.responseType = responseType; + } + abort() { + this.xhr?.abort(); + } + send() { + this.xhr?.abort(); + const xhr = new XMLHttpRequest(); + xhr.open('GET', this.url); + xhr.responseType = this.responseType; + if (this.range) { + xhr.setRequestHeader('Range', this.range); + } + xhr.onprogress = (e) => { + this.onProgress?.(e); + }; + xhr.onload = (e) => { + this.onProgress?.(e); + this.onLoad?.(xhr.response); + }; + xhr.onerror = (_) => { + this.onError?.(); + }; + xhr.send(); + this.xhr = xhr; + } +} +exports.RetriableRequest = RetriableRequest; diff --git a/src/ts/dist/index.d.ts b/src/ts/dist/index.d.ts index 26013896..eeacd585 100644 --- a/src/ts/dist/index.d.ts +++ b/src/ts/dist/index.d.ts @@ -1,14 +1,14 @@ export * from './bfast'; -export * from './g3d'; +export * from './g3d/g3d'; export * from './remoteVimx'; -export * from './g3dMaterials'; -export * from './g3dMesh'; -export * from './g3dChunk'; -export * from './g3dScene'; -export * from './remoteBuffer'; -export * from './requestTracker'; -export * from './requester'; -export * from './remoteValue'; +export * from './g3d/g3dMaterials'; +export * from './g3d/g3dMesh'; +export * from './g3d/g3dChunk'; +export * from './g3d/g3dScene'; +export * from './http/remoteBuffer'; +export * from './http/requestTracker'; +export * from './http/requester'; +export * from './http/remoteValue'; export * from './vimHeader'; export * from './objectModel'; export * from './structures'; diff --git a/src/ts/dist/index.js b/src/ts/dist/index.js index 1afb0cd2..9ab9170c 100644 --- a/src/ts/dist/index.js +++ b/src/ts/dist/index.js @@ -29,16 +29,16 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.VimHelpers = void 0; // Links files to generate package type exports __exportStar(require("./bfast"), exports); -__exportStar(require("./g3d"), exports); +__exportStar(require("./g3d/g3d"), exports); __exportStar(require("./remoteVimx"), exports); -__exportStar(require("./g3dMaterials"), exports); -__exportStar(require("./g3dMesh"), exports); -__exportStar(require("./g3dChunk"), exports); -__exportStar(require("./g3dScene"), exports); -__exportStar(require("./remoteBuffer"), exports); -__exportStar(require("./requestTracker"), exports); -__exportStar(require("./requester"), exports); -__exportStar(require("./remoteValue"), exports); +__exportStar(require("./g3d/g3dMaterials"), exports); +__exportStar(require("./g3d/g3dMesh"), exports); +__exportStar(require("./g3d/g3dChunk"), exports); +__exportStar(require("./g3d/g3dScene"), exports); +__exportStar(require("./http/remoteBuffer"), exports); +__exportStar(require("./http/requestTracker"), exports); +__exportStar(require("./http/requester"), exports); +__exportStar(require("./http/remoteValue"), exports); __exportStar(require("./vimHeader"), exports); __exportStar(require("./objectModel"), exports); __exportStar(require("./structures"), exports); diff --git a/src/ts/dist/remoteBuffer.d.ts b/src/ts/dist/remoteBuffer.d.ts index eddb9302..b8ee59af 100644 --- a/src/ts/dist/remoteBuffer.d.ts +++ b/src/ts/dist/remoteBuffer.d.ts @@ -3,34 +3,20 @@ */ import { Range } from './bfast'; import { IProgressLogs } from './requestTracker'; +import { Logger } from './logging'; export declare function setRemoteBufferMaxConcurency(value: number): void; -export declare class RetryRequest { - url: string; - range: string | undefined; - responseType: XMLHttpRequestResponseType; - msg: string | undefined; - xhr: XMLHttpRequest | undefined; - constructor(url: string, range: string | undefined, responseType: XMLHttpRequestResponseType); - onLoad: ((result: any) => void) | undefined; - onError: (() => void) | undefined; - onProgress: ((e: ProgressEvent) => void) | undefined; - abort(): void; - send(): void; -} /** - * Wrapper to provide tracking for all webrequests via request logger. - */ +* Wrapper to provide tracking for all webrequests via request logger. +*/ export declare class RemoteBuffer { url: string; maxConcurency: number; onProgress: (progress: IProgressLogs) => void; + logs: Logger; private _tracker; - private _logs; private _queue; private _active; - private _encoded; - constructor(url: string, verbose?: boolean); - private requestEncoding; + constructor(url: string); abort(): void; http(range: Range | undefined, label: string): Promise; private enqueue; diff --git a/src/ts/dist/remoteBuffer.js b/src/ts/dist/remoteBuffer.js index 13a9b1f2..5ec75663 100644 --- a/src/ts/dist/remoteBuffer.js +++ b/src/ts/dist/remoteBuffer.js @@ -3,88 +3,27 @@ * @module vim-ts */ Object.defineProperty(exports, "__esModule", { value: true }); -exports.RemoteBuffer = exports.RetryRequest = exports.setRemoteBufferMaxConcurency = void 0; -const remoteValue_1 = require("./remoteValue"); +exports.RemoteBuffer = exports.setRemoteBufferMaxConcurency = void 0; const requestTracker_1 = require("./requestTracker"); const logging_1 = require("./logging"); +const retriableRequest_1 = require("./retriableRequest"); let RemoteBufferMaxConcurency = 10; function setRemoteBufferMaxConcurency(value) { RemoteBufferMaxConcurency = value; } exports.setRemoteBufferMaxConcurency = setRemoteBufferMaxConcurency; -class RetryRequest { - constructor(url, range, - // eslint-disable-next-line no-undef - responseType) { - this.url = url; - this.range = range; - this.responseType = responseType; - } - abort() { - this.xhr?.abort(); - } - send() { - this.xhr?.abort(); - const xhr = new XMLHttpRequest(); - xhr.open('GET', this.url); - xhr.responseType = this.responseType; - if (this.range) { - xhr.setRequestHeader('Range', this.range); - } - xhr.onprogress = (e) => { - this.onProgress?.(e); - }; - xhr.onload = (e) => { - this.onProgress?.(e); - this.onLoad?.(xhr.response); - }; - xhr.onerror = (_) => { - this.onError?.(); - }; - xhr.send(); - this.xhr = xhr; - } -} -exports.RetryRequest = RetryRequest; /** - * Wrapper to provide tracking for all webrequests via request logger. - */ +* Wrapper to provide tracking for all webrequests via request logger. +*/ class RemoteBuffer { - constructor(url, verbose = false) { + constructor(url) { this.maxConcurency = RemoteBufferMaxConcurency; this._queue = []; this._active = new Set(); this.url = url; - this._logs = verbose ? new logging_1.DefaultLog() : new logging_1.NoLog(); - this._tracker = new requestTracker_1.RequestTracker(url, this._logs); + this.logs = new logging_1.NoLog(); + this._tracker = new requestTracker_1.RequestTracker(url, this.logs); this._tracker.onUpdate = (p) => this.onProgress?.(p); - this._encoded = new remoteValue_1.RemoteValue(() => this.requestEncoding()); - } - async requestEncoding() { - const xhr = new XMLHttpRequest(); - xhr.open('HEAD', this.url); - xhr.send(); - this._logs.log(`Requesting header for ${this.url}`); - const promise = new Promise((resolve, reject) => { - xhr.onload = (_) => { - let encoding; - try { - encoding = xhr.getResponseHeader('content-encoding'); - } - catch (e) { - this._logs.error(e); - } - resolve(encoding ?? undefined); - }; - xhr.onerror = (_) => resolve(undefined); - }); - const encoding = await promise; - const encoded = !!encoding; - this._logs.log(`Encoding for ${this.url} = ${encoding}`); - if (encoded) { - this._logs.log(`Defaulting to download strategy for encoded content at ${this.url}`); - } - return encoded; } abort() { this._active.forEach(request => { @@ -94,12 +33,11 @@ class RemoteBuffer { this._queue.length = 0; } async http(range, label) { - const useRange = range && !(await this._encoded.get()); - const rangeStr = useRange + const rangeStr = range ? `bytes=${range.start}-${range.end - 1}` : undefined; - const request = new RetryRequest(this.url, rangeStr, 'arraybuffer'); - request.msg = useRange + const request = new retriableRequest_1.RetriableRequest(this.url, rangeStr, 'arraybuffer'); + request.msg = range ? `${label} : [${range.start}, ${range.end}] of ${this.url}` : `${label} of ${this.url}`; this.enqueue(request); @@ -143,7 +81,7 @@ class RemoteBuffer { this._queue.shift(); this._active.add(next); next.send(); - this._logs.log('Starting ' + next.msg); + this.logs.log('Starting ' + next.msg); } } exports.RemoteBuffer = RemoteBuffer; diff --git a/src/ts/dist/remoteVimx.d.ts b/src/ts/dist/remoteVimx.d.ts index 9286f409..5a565285 100644 --- a/src/ts/dist/remoteVimx.d.ts +++ b/src/ts/dist/remoteVimx.d.ts @@ -1,9 +1,9 @@ import { BFast } from "./bfast"; -import { G3dMaterial as G3dMaterials } from "./g3dMaterials"; -import { G3dChunk } from './g3dChunk'; -import { G3dScene } from "./g3dScene"; -import { RemoteValue } from "./remoteValue"; -import { G3dMesh } from "./g3dMesh"; +import { G3dMaterial as G3dMaterials } from "./g3d/g3dMaterials"; +import { G3dChunk } from './g3d/g3dChunk'; +import { G3dScene } from "./g3d/g3dScene"; +import { RemoteValue } from "./http/remoteValue"; +import { G3dMesh } from "./g3d/g3dMesh"; export declare class RemoteVimx { bfast: BFast; scene: RemoteValue; diff --git a/src/ts/dist/remoteVimx.js b/src/ts/dist/remoteVimx.js index 04e28d7c..eb54aa0f 100644 --- a/src/ts/dist/remoteVimx.js +++ b/src/ts/dist/remoteVimx.js @@ -2,12 +2,12 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.RemoteVimx = void 0; const bfast_1 = require("./bfast"); -const g3dMaterials_1 = require("./g3dMaterials"); -const g3dChunk_1 = require("./g3dChunk"); -const g3dScene_1 = require("./g3dScene"); -const remoteValue_1 = require("./remoteValue"); +const g3dMaterials_1 = require("./g3d/g3dMaterials"); +const g3dChunk_1 = require("./g3d/g3dChunk"); +const g3dScene_1 = require("./g3d/g3dScene"); +const remoteValue_1 = require("./http/remoteValue"); const vimHeader_1 = require("./vimHeader"); -const g3dMesh_1 = require("./g3dMesh"); +const g3dMesh_1 = require("./g3d/g3dMesh"); class RemoteVimx { constructor(source) { this.chunkCache = new Map(); diff --git a/src/ts/dist/requester.js b/src/ts/dist/requester.js index 707c9566..cf495a38 100644 --- a/src/ts/dist/requester.js +++ b/src/ts/dist/requester.js @@ -2,7 +2,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.Requester = void 0; const logging_1 = require("./logging"); -const remoteBuffer_1 = require("./remoteBuffer"); +const retriableRequest_1 = require("./retriableRequest"); const requestTracker_1 = require("./requestTracker"); /** * Wrapper to provide tracking for all webrequests via request logger. @@ -24,7 +24,7 @@ class Requester { this._queue.length = 0; } async http(url, label) { - const request = new remoteBuffer_1.RetryRequest(url, undefined, 'arraybuffer'); + const request = new retriableRequest_1.RetriableRequest(url, undefined, 'arraybuffer'); request.msg = url; this.enqueue(request); return new Promise((resolve, reject) => { diff --git a/src/ts/dist/retriableRequest.js b/src/ts/dist/retriableRequest.js new file mode 100644 index 00000000..c27ea8ed --- /dev/null +++ b/src/ts/dist/retriableRequest.js @@ -0,0 +1,37 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.RetriableRequest = void 0; +class RetriableRequest { + constructor(url, range, + // eslint-disable-next-line no-undef + responseType) { + this.url = url; + this.range = range; + this.responseType = responseType; + } + abort() { + this.xhr?.abort(); + } + send() { + this.xhr?.abort(); + const xhr = new XMLHttpRequest(); + xhr.open('GET', this.url); + xhr.responseType = this.responseType; + if (this.range) { + xhr.setRequestHeader('Range', this.range); + } + xhr.onprogress = (e) => { + this.onProgress?.(e); + }; + xhr.onload = (e) => { + this.onProgress?.(e); + this.onLoad?.(xhr.response); + }; + xhr.onerror = (_) => { + this.onError?.(); + }; + xhr.send(); + this.xhr = xhr; + } +} +exports.RetriableRequest = RetriableRequest; diff --git a/src/ts/dist/types/remoteBuffer.d.ts b/src/ts/dist/types/remoteBuffer.d.ts index eddb9302..15aa9814 100644 --- a/src/ts/dist/types/remoteBuffer.d.ts +++ b/src/ts/dist/types/remoteBuffer.d.ts @@ -3,6 +3,7 @@ */ import { Range } from './bfast'; import { IProgressLogs } from './requestTracker'; +import { Logger } from './logging'; export declare function setRemoteBufferMaxConcurency(value: number): void; export declare class RetryRequest { url: string; @@ -24,12 +25,12 @@ export declare class RemoteBuffer { url: string; maxConcurency: number; onProgress: (progress: IProgressLogs) => void; + logs: Logger; private _tracker; - private _logs; private _queue; private _active; private _encoded; - constructor(url: string, verbose?: boolean); + constructor(url: string); private requestEncoding; abort(): void; http(range: Range | undefined, label: string): Promise; diff --git a/src/ts/package.json b/src/ts/package.json index c24a4034..8c23a476 100644 --- a/src/ts/package.json +++ b/src/ts/package.json @@ -1,6 +1,6 @@ { "name": "vim-format", - "version": "1.0.6-dev.238", + "version": "1.0.6-dev.240", "description": "The VIM format is a modern and efficient open 3D data interchange format designed for BIM and manufacturing data optimized for efficient loading and rendering on low-power devices.", "directories": { "test": "tests" diff --git a/src/ts/src/bfast.ts b/src/ts/src/bfast.ts index 092f5431..3c454f87 100644 --- a/src/ts/src/bfast.ts +++ b/src/ts/src/bfast.ts @@ -2,8 +2,8 @@ * @module vim-ts */ - import { RemoteValue } from './remoteValue' - import { RemoteBuffer } from './remoteBuffer' + import { RemoteValue } from './http/remoteValue' + import { RemoteBuffer } from './http/remoteBuffer' import * as pako from 'pako' type NumericArrayConstructor = @@ -208,14 +208,14 @@ export function parseName(name: string): [number, NumericArrayConstructor]{ constructor ( source: RemoteBuffer | ArrayBuffer | string, offset: number = 0, - name?: string + name: string = '' ) { this.source = typeof source === 'string' ? new RemoteBuffer(source) : source this.offset = offset - this.name = name ?? (typeof source === 'string' ? source : '') + this.name = name this._header = new RemoteValue(() => this.requestHeader(), name + '.header') this._children = new Map>() diff --git a/src/ts/src/g3d.ts b/src/ts/src/g3d/g3d.ts similarity index 99% rename from src/ts/src/g3d.ts rename to src/ts/src/g3d/g3d.ts index 07ed9c63..71fd447f 100644 --- a/src/ts/src/g3d.ts +++ b/src/ts/src/g3d/g3d.ts @@ -2,7 +2,7 @@ * @module vim-ts */ -import { BFast } from './bfast' +import { BFast } from '../bfast' export type MeshSection = 'opaque' | 'transparent' | 'all' diff --git a/src/ts/src/g3dChunk.ts b/src/ts/src/g3d/g3dChunk.ts similarity index 98% rename from src/ts/src/g3dChunk.ts rename to src/ts/src/g3d/g3dChunk.ts index 4e08d2bc..7d73a137 100644 --- a/src/ts/src/g3dChunk.ts +++ b/src/ts/src/g3d/g3dChunk.ts @@ -1,4 +1,4 @@ -import { BFast } from './bfast'; +import { BFast } from '../bfast'; /** * G3D is a simple, efficient, generic binary format for storing and transmitting geometry. diff --git a/src/ts/src/g3dMaterials.ts b/src/ts/src/g3d/g3dMaterials.ts similarity index 98% rename from src/ts/src/g3dMaterials.ts rename to src/ts/src/g3d/g3dMaterials.ts index ebc5524f..5586d524 100644 --- a/src/ts/src/g3dMaterials.ts +++ b/src/ts/src/g3d/g3dMaterials.ts @@ -2,7 +2,7 @@ * @module vim-ts */ -import { BFast } from './bfast' +import { BFast } from '../bfast' /** * See https://github.com/vimaec/vim#vim-geometry-attributes diff --git a/src/ts/src/g3dMesh.ts b/src/ts/src/g3d/g3dMesh.ts similarity index 100% rename from src/ts/src/g3dMesh.ts rename to src/ts/src/g3d/g3dMesh.ts diff --git a/src/ts/src/g3dScene.ts b/src/ts/src/g3d/g3dScene.ts similarity index 99% rename from src/ts/src/g3dScene.ts rename to src/ts/src/g3d/g3dScene.ts index 903f5e59..88c92866 100644 --- a/src/ts/src/g3dScene.ts +++ b/src/ts/src/g3d/g3dScene.ts @@ -2,7 +2,7 @@ * @module vim-ts */ -import { BFast } from './bfast' +import { BFast } from '../bfast' import { G3d, MeshSection } from './g3d' export type FilterMode = undefined | 'mesh' | 'instance' | 'group' | 'tag' diff --git a/src/ts/src/logging.ts b/src/ts/src/http/logging.ts similarity index 100% rename from src/ts/src/logging.ts rename to src/ts/src/http/logging.ts diff --git a/src/ts/src/remoteBuffer.ts b/src/ts/src/http/remoteBuffer.ts similarity index 99% rename from src/ts/src/remoteBuffer.ts rename to src/ts/src/http/remoteBuffer.ts index e50579d9..46e02616 100644 --- a/src/ts/src/remoteBuffer.ts +++ b/src/ts/src/http/remoteBuffer.ts @@ -2,7 +2,7 @@ * @module vim-ts */ -import { Range } from './bfast' +import { Range } from '../bfast' import { RemoteValue } from './remoteValue' import {IProgressLogs, RequestTracker} from './requestTracker' import {DefaultLog, Logger, NoLog} from './logging' diff --git a/src/ts/src/remoteValue.ts b/src/ts/src/http/remoteValue.ts similarity index 100% rename from src/ts/src/remoteValue.ts rename to src/ts/src/http/remoteValue.ts diff --git a/src/ts/src/requestTracker.ts b/src/ts/src/http/requestTracker.ts similarity index 100% rename from src/ts/src/requestTracker.ts rename to src/ts/src/http/requestTracker.ts diff --git a/src/ts/src/requester.ts b/src/ts/src/http/requester.ts similarity index 100% rename from src/ts/src/requester.ts rename to src/ts/src/http/requester.ts diff --git a/src/ts/src/http/retriableRequest.ts b/src/ts/src/http/retriableRequest.ts new file mode 100644 index 00000000..34abd312 --- /dev/null +++ b/src/ts/src/http/retriableRequest.ts @@ -0,0 +1,53 @@ + + +export class RetriableRequest { + url: string; + range: string | undefined; + // eslint-disable-next-line no-undef + responseType: XMLHttpRequestResponseType; + msg: string | undefined; + xhr: XMLHttpRequest | undefined; + + constructor( + url: string, + range: string | undefined, + // eslint-disable-next-line no-undef + responseType: XMLHttpRequestResponseType + ) { + this.url = url; + this.range = range; + this.responseType = responseType; + } + + onLoad: ((result: any) => void) | undefined; + onError: (() => void) | undefined; + onProgress: ((e: ProgressEvent) => void) | undefined; + + abort() { + this.xhr?.abort(); + } + + send() { + this.xhr?.abort(); + const xhr = new XMLHttpRequest(); + xhr.open('GET', this.url); + xhr.responseType = this.responseType; + + if (this.range) { + xhr.setRequestHeader('Range', this.range); + } + + xhr.onprogress = (e) => { + this.onProgress?.(e); + }; + xhr.onload = (e) => { + this.onProgress?.(e); + this.onLoad?.(xhr.response); + }; + xhr.onerror = (_) => { + this.onError?.(); + }; + xhr.send(); + this.xhr = xhr; + } +} diff --git a/src/ts/src/index.ts b/src/ts/src/index.ts index c4f05ee2..31d527db 100644 --- a/src/ts/src/index.ts +++ b/src/ts/src/index.ts @@ -1,15 +1,15 @@ // Links files to generate package type exports export * from './bfast' -export * from './g3d' +export * from './g3d/g3d' export * from './remoteVimx' -export * from './g3dMaterials' -export * from './g3dMesh' -export * from './g3dChunk' -export * from './g3dScene' -export * from './remoteBuffer' -export * from './requestTracker' -export * from './requester' -export * from './remoteValue' +export * from './g3d/g3dMaterials' +export * from './g3d/g3dMesh' +export * from './g3d/g3dChunk' +export * from './g3d/g3dScene' +export * from './http/remoteBuffer' +export * from './http/requestTracker' +export * from './http/requester' +export * from './http/remoteValue' export * from './vimHeader' export * from './objectModel' diff --git a/src/ts/src/remoteVimx.ts b/src/ts/src/remoteVimx.ts index 73e6c2b1..075b6e60 100644 --- a/src/ts/src/remoteVimx.ts +++ b/src/ts/src/remoteVimx.ts @@ -1,10 +1,10 @@ import { BFast } from "./bfast"; -import { G3dMaterial as G3dMaterials } from "./g3dMaterials"; -import { G3dChunk } from './g3dChunk'; -import { G3dScene } from "./g3dScene"; -import { RemoteValue } from "./remoteValue"; +import { G3dMaterial as G3dMaterials } from "./g3d/g3dMaterials"; +import { G3dChunk } from './g3d/g3dChunk'; +import { G3dScene } from "./g3d/g3dScene"; +import { RemoteValue } from "./http/remoteValue"; import { requestHeader } from "./vimHeader"; -import { G3dMesh } from "./g3dMesh"; +import { G3dMesh } from "./g3d/g3dMesh"; export class RemoteVimx{ bfast : BFast diff --git a/src/ts/tsconfig.json b/src/ts/tsconfig.json index 52936dcb..978d48db 100644 --- a/src/ts/tsconfig.json +++ b/src/ts/tsconfig.json @@ -16,6 +16,6 @@ "src/**/*" ], "files": [ - "src/index.ts" + "src/index.ts", ] } \ No newline at end of file From 235c6786a0307d2e60c659020c40b7766d9ea303 Mon Sep 17 00:00:00 2001 From: simon Date: Tue, 27 Feb 2024 13:51:53 -0500 Subject: [PATCH 098/111] removed get encoding from remote buffer --- src/ts/dist/types/bfast.d.ts | 2 +- src/ts/dist/types/index.d.ts | 18 ++--- src/ts/dist/types/remoteVimx.d.ts | 10 +-- src/ts/src/http/remoteBuffer.ts | 110 ++++-------------------------- 4 files changed, 28 insertions(+), 112 deletions(-) diff --git a/src/ts/dist/types/bfast.d.ts b/src/ts/dist/types/bfast.d.ts index 33cea1c5..d1d39cb6 100644 --- a/src/ts/dist/types/bfast.d.ts +++ b/src/ts/dist/types/bfast.d.ts @@ -1,7 +1,7 @@ /** * @module vim-ts */ -import { RemoteBuffer } from './remoteBuffer'; +import { RemoteBuffer } from './http/remoteBuffer'; declare type NumericArrayConstructor = Int8ArrayConstructor | Uint8ArrayConstructor | Int16ArrayConstructor | Uint16ArrayConstructor | Int32ArrayConstructor | Uint32ArrayConstructor | BigInt64ArrayConstructor | BigUint64ArrayConstructor | Float32ArrayConstructor | Float64ArrayConstructor; export declare type NumericArray = Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array | BigInt64Array | BigUint64Array; export declare class Range { diff --git a/src/ts/dist/types/index.d.ts b/src/ts/dist/types/index.d.ts index 26013896..eeacd585 100644 --- a/src/ts/dist/types/index.d.ts +++ b/src/ts/dist/types/index.d.ts @@ -1,14 +1,14 @@ export * from './bfast'; -export * from './g3d'; +export * from './g3d/g3d'; export * from './remoteVimx'; -export * from './g3dMaterials'; -export * from './g3dMesh'; -export * from './g3dChunk'; -export * from './g3dScene'; -export * from './remoteBuffer'; -export * from './requestTracker'; -export * from './requester'; -export * from './remoteValue'; +export * from './g3d/g3dMaterials'; +export * from './g3d/g3dMesh'; +export * from './g3d/g3dChunk'; +export * from './g3d/g3dScene'; +export * from './http/remoteBuffer'; +export * from './http/requestTracker'; +export * from './http/requester'; +export * from './http/remoteValue'; export * from './vimHeader'; export * from './objectModel'; export * from './structures'; diff --git a/src/ts/dist/types/remoteVimx.d.ts b/src/ts/dist/types/remoteVimx.d.ts index 9286f409..5a565285 100644 --- a/src/ts/dist/types/remoteVimx.d.ts +++ b/src/ts/dist/types/remoteVimx.d.ts @@ -1,9 +1,9 @@ import { BFast } from "./bfast"; -import { G3dMaterial as G3dMaterials } from "./g3dMaterials"; -import { G3dChunk } from './g3dChunk'; -import { G3dScene } from "./g3dScene"; -import { RemoteValue } from "./remoteValue"; -import { G3dMesh } from "./g3dMesh"; +import { G3dMaterial as G3dMaterials } from "./g3d/g3dMaterials"; +import { G3dChunk } from './g3d/g3dChunk'; +import { G3dScene } from "./g3d/g3dScene"; +import { RemoteValue } from "./http/remoteValue"; +import { G3dMesh } from "./g3d/g3dMesh"; export declare class RemoteVimx { bfast: BFast; scene: RemoteValue; diff --git a/src/ts/src/http/remoteBuffer.ts b/src/ts/src/http/remoteBuffer.ts index 46e02616..d0f09746 100644 --- a/src/ts/src/http/remoteBuffer.ts +++ b/src/ts/src/http/remoteBuffer.ts @@ -5,66 +5,14 @@ import { Range } from '../bfast' import { RemoteValue } from './remoteValue' import {IProgressLogs, RequestTracker} from './requestTracker' -import {DefaultLog, Logger, NoLog} from './logging' +import { Logger, NoLog} from './logging' +import { RetriableRequest } from './retriableRequest' let RemoteBufferMaxConcurency = 10 export function setRemoteBufferMaxConcurency(value: number){ RemoteBufferMaxConcurency =value } - -export class RetryRequest { - url: string - range: string | undefined - // eslint-disable-next-line no-undef - responseType: XMLHttpRequestResponseType - msg: string | undefined - xhr: XMLHttpRequest | undefined - - constructor ( - url: string, - range: string | undefined, - // eslint-disable-next-line no-undef - responseType: XMLHttpRequestResponseType - ) { - this.url = url - this.range = range - this.responseType = responseType - } - - onLoad: ((result: any) => void) | undefined - onError: (() => void) | undefined - onProgress: ((e: ProgressEvent) => void) | undefined - - abort(){ - this.xhr?.abort() - } - - send () { - this.xhr?.abort() - const xhr = new XMLHttpRequest() - xhr.open('GET', this.url) - xhr.responseType = this.responseType - - if (this.range) { - xhr.setRequestHeader('Range', this.range) - } - - xhr.onprogress = (e) => { - this.onProgress?.(e) - } - xhr.onload = (e) => { - this.onProgress?.(e) - this.onLoad?.(xhr.response) - } - xhr.onerror = (_) => { - this.onError?.() - } - xhr.send() - this.xhr = xhr - } -} - /** * Wrapper to provide tracking for all webrequests via request logger. */ @@ -73,49 +21,16 @@ export class RemoteBuffer { maxConcurency: number = RemoteBufferMaxConcurency onProgress: (progress : IProgressLogs) => void logs : Logger - private _tracker: RequestTracker - private _queue: RetryRequest[] = [] - private _active: Set = new Set() - private _encoded: RemoteValue + private _tracker: RequestTracker + private _queue: RetriableRequest[] = [] + private _active: Set = new Set() constructor (url: string) { this.url = url this.logs = new NoLog() this._tracker = new RequestTracker(url, this.logs) this._tracker.onUpdate = (p) => this.onProgress?.(p) - this._encoded = new RemoteValue(() => this.requestEncoding()) - } - - private async requestEncoding () { - const xhr = new XMLHttpRequest() - xhr.open('HEAD', this.url) - xhr.send() - this.logs.log(`Requesting header for ${this.url}`) - - const promise = new Promise((resolve, reject) => { - xhr.onload = (_) => { - let encoding: string | null | undefined - try { - encoding = xhr.getResponseHeader('content-encoding') - } catch (e) { - this.logs.error(e) - } - resolve(encoding ?? undefined) - } - xhr.onerror = (_) => resolve(undefined) - }) - - const encoding = await promise - const encoded = !!encoding - - this.logs.log(`Encoding for ${this.url} = ${encoding}`) - if (encoded) { - this.logs.log( - `Defaulting to download strategy for encoded content at ${this.url}` - ) - } - return encoded } abort(){ @@ -127,12 +42,13 @@ export class RemoteBuffer { } async http (range: Range | undefined, label: string) { - const useRange = range && !(await this._encoded.get()) - const rangeStr = useRange + const rangeStr = range ? `bytes=${range.start}-${range.end - 1}` : undefined - const request = new RetryRequest(this.url, rangeStr, 'arraybuffer') - request.msg = useRange + + const request = new RetriableRequest(this.url, rangeStr, 'arraybuffer') + + request.msg = range ? `${label} : [${range.start}, ${range.end}] of ${this.url}` : `${label} of ${this.url}` @@ -155,18 +71,18 @@ export class RemoteBuffer { }) } - private enqueue (xhr: RetryRequest) { + private enqueue (xhr: RetriableRequest) { this._queue.push(xhr) this.next() } - private retry (xhr: RetryRequest) { + private retry (xhr: RetriableRequest) { this._active.delete(xhr) this.maxConcurency = Math.max(1, this.maxConcurency - 1) setTimeout(() => this.enqueue(xhr), 2000) } - private end (xhr: RetryRequest) { + private end (xhr: RetriableRequest) { this._active.delete(xhr) this.next() } From 6f0494d86eab8f92b8763a85d265e4c8b4f88554 Mon Sep 17 00:00:00 2001 From: simon Date: Tue, 27 Feb 2024 14:08:24 -0500 Subject: [PATCH 099/111] renamed RetryRequest added ended log --- src/ts/dist/http/remoteBuffer.js | 72 +++----------------------------- src/ts/dist/http/requester.js | 4 +- src/ts/package.json | 2 +- src/ts/src/bfast.ts | 2 +- src/ts/src/http/remoteBuffer.ts | 17 ++++---- src/ts/src/http/requester.ts | 14 +++---- 6 files changed, 25 insertions(+), 86 deletions(-) diff --git a/src/ts/dist/http/remoteBuffer.js b/src/ts/dist/http/remoteBuffer.js index 6266ff57..98c40ec8 100644 --- a/src/ts/dist/http/remoteBuffer.js +++ b/src/ts/dist/http/remoteBuffer.js @@ -3,49 +3,15 @@ * @module vim-ts */ Object.defineProperty(exports, "__esModule", { value: true }); -exports.RemoteBuffer = exports.RetryRequest = exports.setRemoteBufferMaxConcurency = void 0; -const remoteValue_1 = require("./remoteValue"); +exports.RemoteBuffer = exports.setRemoteBufferMaxConcurency = void 0; const requestTracker_1 = require("./requestTracker"); const logging_1 = require("./logging"); +const retriableRequest_1 = require("./retriableRequest"); let RemoteBufferMaxConcurency = 10; function setRemoteBufferMaxConcurency(value) { RemoteBufferMaxConcurency = value; } exports.setRemoteBufferMaxConcurency = setRemoteBufferMaxConcurency; -class RetryRequest { - constructor(url, range, - // eslint-disable-next-line no-undef - responseType) { - this.url = url; - this.range = range; - this.responseType = responseType; - } - abort() { - this.xhr?.abort(); - } - send() { - this.xhr?.abort(); - const xhr = new XMLHttpRequest(); - xhr.open('GET', this.url); - xhr.responseType = this.responseType; - if (this.range) { - xhr.setRequestHeader('Range', this.range); - } - xhr.onprogress = (e) => { - this.onProgress?.(e); - }; - xhr.onload = (e) => { - this.onProgress?.(e); - this.onLoad?.(xhr.response); - }; - xhr.onerror = (_) => { - this.onError?.(); - }; - xhr.send(); - this.xhr = xhr; - } -} -exports.RetryRequest = RetryRequest; /** * Wrapper to provide tracking for all webrequests via request logger. */ @@ -58,33 +24,6 @@ class RemoteBuffer { this.logs = new logging_1.NoLog(); this._tracker = new requestTracker_1.RequestTracker(url, this.logs); this._tracker.onUpdate = (p) => this.onProgress?.(p); - this._encoded = new remoteValue_1.RemoteValue(() => this.requestEncoding()); - } - async requestEncoding() { - const xhr = new XMLHttpRequest(); - xhr.open('HEAD', this.url); - xhr.send(); - this.logs.log(`Requesting header for ${this.url}`); - const promise = new Promise((resolve, reject) => { - xhr.onload = (_) => { - let encoding; - try { - encoding = xhr.getResponseHeader('content-encoding'); - } - catch (e) { - this.logs.error(e); - } - resolve(encoding ?? undefined); - }; - xhr.onerror = (_) => resolve(undefined); - }); - const encoding = await promise; - const encoded = !!encoding; - this.logs.log(`Encoding for ${this.url} = ${encoding}`); - if (encoded) { - this.logs.log(`Defaulting to download strategy for encoded content at ${this.url}`); - } - return encoded; } abort() { this._active.forEach(request => { @@ -94,12 +33,11 @@ class RemoteBuffer { this._queue.length = 0; } async http(range, label) { - const useRange = range && !(await this._encoded.get()); - const rangeStr = useRange + const rangeStr = range ? `bytes=${range.start}-${range.end - 1}` : undefined; - const request = new RetryRequest(this.url, rangeStr, 'arraybuffer'); - request.msg = useRange + const request = new retriableRequest_1.RetriableRequest(this.url, rangeStr, 'arraybuffer'); + request.msg = range ? `${label} : [${range.start}, ${range.end}] of ${this.url}` : `${label} of ${this.url}`; this.enqueue(request); diff --git a/src/ts/dist/http/requester.js b/src/ts/dist/http/requester.js index 707c9566..cf495a38 100644 --- a/src/ts/dist/http/requester.js +++ b/src/ts/dist/http/requester.js @@ -2,7 +2,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.Requester = void 0; const logging_1 = require("./logging"); -const remoteBuffer_1 = require("./remoteBuffer"); +const retriableRequest_1 = require("./retriableRequest"); const requestTracker_1 = require("./requestTracker"); /** * Wrapper to provide tracking for all webrequests via request logger. @@ -24,7 +24,7 @@ class Requester { this._queue.length = 0; } async http(url, label) { - const request = new remoteBuffer_1.RetryRequest(url, undefined, 'arraybuffer'); + const request = new retriableRequest_1.RetriableRequest(url, undefined, 'arraybuffer'); request.msg = url; this.enqueue(request); return new Promise((resolve, reject) => { diff --git a/src/ts/package.json b/src/ts/package.json index 8c23a476..c1d3fce5 100644 --- a/src/ts/package.json +++ b/src/ts/package.json @@ -1,6 +1,6 @@ { "name": "vim-format", - "version": "1.0.6-dev.240", + "version": "1.0.6-dev.241", "description": "The VIM format is a modern and efficient open 3D data interchange format designed for BIM and manufacturing data optimized for efficient loading and rendering on low-power devices.", "directories": { "test": "tests" diff --git a/src/ts/src/bfast.ts b/src/ts/src/bfast.ts index 3c454f87..4d611695 100644 --- a/src/ts/src/bfast.ts +++ b/src/ts/src/bfast.ts @@ -215,7 +215,7 @@ export function parseName(name: string): [number, NumericArrayConstructor]{ : source this.offset = offset - this.name = name + this.name = name ?? "root" this._header = new RemoteValue(() => this.requestHeader(), name + '.header') this._children = new Map>() diff --git a/src/ts/src/http/remoteBuffer.ts b/src/ts/src/http/remoteBuffer.ts index d0f09746..67d87713 100644 --- a/src/ts/src/http/remoteBuffer.ts +++ b/src/ts/src/http/remoteBuffer.ts @@ -71,19 +71,20 @@ export class RemoteBuffer { }) } - private enqueue (xhr: RetriableRequest) { - this._queue.push(xhr) + private enqueue (request: RetriableRequest) { + this._queue.push(request) this.next() } - private retry (xhr: RetriableRequest) { - this._active.delete(xhr) + private retry (request: RetriableRequest) { + this._active.delete(request) this.maxConcurency = Math.max(1, this.maxConcurency - 1) - setTimeout(() => this.enqueue(xhr), 2000) + setTimeout(() => this.enqueue(request), 2000) } - private end (xhr: RetriableRequest) { - this._active.delete(xhr) + private end (request: RetriableRequest) { + this.logs.log('Finished ' + request.msg) + this._active.delete(request) this.next() } @@ -100,6 +101,6 @@ export class RemoteBuffer { this._queue.shift() this._active.add(next) next.send() - this.logs.log('Starting ' + next.msg) + this.logs.log('Started ' + next.msg) } } diff --git a/src/ts/src/http/requester.ts b/src/ts/src/http/requester.ts index 194930d0..61c020af 100644 --- a/src/ts/src/http/requester.ts +++ b/src/ts/src/http/requester.ts @@ -1,5 +1,5 @@ import { DefaultLog, Logger, NoLog } from "./logging" -import { RetryRequest } from "./remoteBuffer" +import { RetriableRequest } from "./retriableRequest" import { IProgressLogs, RequestTracker } from "./requestTracker" /** @@ -10,8 +10,8 @@ export class Requester { onProgress: (progress : IProgressLogs) => void private _tracker: RequestTracker private _logs : Logger - private _queue: RetryRequest[] = [] - private _active: Set = new Set() + private _queue: RetriableRequest[] = [] + private _active: Set = new Set() constructor (verbose: boolean = false) { this._logs = verbose ? new DefaultLog() : new NoLog() @@ -28,7 +28,7 @@ export class Requester { } async http (url : string, label?: string) { - const request = new RetryRequest(url, undefined, 'arraybuffer') + const request = new RetriableRequest(url, undefined, 'arraybuffer') request.msg = url this.enqueue(request) @@ -50,18 +50,18 @@ export class Requester { }) } - private enqueue (xhr: RetryRequest) { + private enqueue (xhr: RetriableRequest) { this._queue.push(xhr) this.next() } - private retry (xhr: RetryRequest) { + private retry (xhr: RetriableRequest) { this._active.delete(xhr) this.maxConcurency = Math.max(1, this.maxConcurency - 1) setTimeout(() => this.enqueue(xhr), 2000) } - private end (xhr: RetryRequest) { + private end (xhr: RetriableRequest) { this._active.delete(xhr) this.next() } From c292b2ab50dcf6d790a2c4a106d6ab8f2db981c1 Mon Sep 17 00:00:00 2001 From: simon Date: Thu, 29 Feb 2024 11:25:26 -0500 Subject: [PATCH 100/111] rename xhr to request --- src/ts/dist/http/remoteBuffer.js | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/ts/dist/http/remoteBuffer.js b/src/ts/dist/http/remoteBuffer.js index 98c40ec8..38c1d63f 100644 --- a/src/ts/dist/http/remoteBuffer.js +++ b/src/ts/dist/http/remoteBuffer.js @@ -57,17 +57,18 @@ class RemoteBuffer { }; }); } - enqueue(xhr) { - this._queue.push(xhr); + enqueue(request) { + this._queue.push(request); this.next(); } - retry(xhr) { - this._active.delete(xhr); + retry(request) { + this._active.delete(request); this.maxConcurency = Math.max(1, this.maxConcurency - 1); - setTimeout(() => this.enqueue(xhr), 2000); + setTimeout(() => this.enqueue(request), 2000); } - end(xhr) { - this._active.delete(xhr); + end(request) { + this.logs.log('Finished ' + request.msg); + this._active.delete(request); this.next(); } next() { @@ -81,7 +82,7 @@ class RemoteBuffer { this._queue.shift(); this._active.add(next); next.send(); - this.logs.log('Starting ' + next.msg); + this.logs.log('Started ' + next.msg); } } exports.RemoteBuffer = RemoteBuffer; From e87c30152bfa3ce60b56342179405d807852d3a5 Mon Sep 17 00:00:00 2001 From: simon Date: Thu, 29 Feb 2024 11:25:56 -0500 Subject: [PATCH 101/111] Made root be default source name --- src/ts/dist/bfast.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ts/dist/bfast.js b/src/ts/dist/bfast.js index 83904969..c395da7e 100644 --- a/src/ts/dist/bfast.js +++ b/src/ts/dist/bfast.js @@ -181,7 +181,7 @@ class BFast { ? new remoteBuffer_1.RemoteBuffer(source) : source; this.offset = offset; - this.name = name; + this.name = name ?? "root"; this._header = new remoteValue_1.RemoteValue(() => this.requestHeader(), name + '.header'); this._children = new Map(); this._ranges = new remoteValue_1.RemoteValue(() => this.requestRanges(), name + '.ranges'); From 958908b14b9a5b0c0c9b96bc3a98961b79dbb30b Mon Sep 17 00:00:00 2001 From: simon Date: Thu, 29 Feb 2024 11:28:25 -0500 Subject: [PATCH 102/111] "version": "1.0.6" --- src/ts/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ts/package.json b/src/ts/package.json index c1d3fce5..cd2418db 100644 --- a/src/ts/package.json +++ b/src/ts/package.json @@ -1,6 +1,6 @@ { "name": "vim-format", - "version": "1.0.6-dev.241", + "version": "1.0.6", "description": "The VIM format is a modern and efficient open 3D data interchange format designed for BIM and manufacturing data optimized for efficient loading and rendering on low-power devices.", "directories": { "test": "tests" From f4370ab9e575c52249a18f15c003a5325afb017c Mon Sep 17 00:00:00 2001 From: simon Date: Fri, 15 Mar 2024 09:02:59 -0400 Subject: [PATCH 103/111] fixed off by one issue in bounding boxes --- src/cs/g3d/Vim.G3dNext/G3dChunk.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cs/g3d/Vim.G3dNext/G3dChunk.cs b/src/cs/g3d/Vim.G3dNext/G3dChunk.cs index 147dfd90..8ad82bd3 100644 --- a/src/cs/g3d/Vim.G3dNext/G3dChunk.cs +++ b/src/cs/g3d/Vim.G3dNext/G3dChunk.cs @@ -88,7 +88,7 @@ public int GetMeshVertexStart(int mesh, MeshSection section) public int GetMeshVertexEnd(int mesh, MeshSection section) { - var sub = GetMeshSubmeshEnd(mesh, section); + var sub = GetMeshSubmeshEnd(mesh, section) - 1; return GetSubmeshVertexEnd(sub); } From 26d6c782065c7daf3083fb0337892c3c55388959 Mon Sep 17 00:00:00 2001 From: simon Date: Mon, 25 Mar 2024 13:53:38 -0400 Subject: [PATCH 104/111] Check for nulls before writing document components --- .../Vim.Format.Core/SerializableDocument.cs | 40 ++++++++++++++----- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/src/cs/vim/Vim.Format.Core/SerializableDocument.cs b/src/cs/vim/Vim.Format.Core/SerializableDocument.cs index d5e80a6b..3a9ae487 100644 --- a/src/cs/vim/Vim.Format.Core/SerializableDocument.cs +++ b/src/cs/vim/Vim.Format.Core/SerializableDocument.cs @@ -61,23 +61,41 @@ public class SerializableDocument public BFast ToBFast() { var bfast = new BFast(); - bfast.SetArray(BufferNames.Header, Header.ToBytes()); + if(Header != null) + { + bfast.SetArray(BufferNames.Header, Header.ToBytes()); + } - var assets = new BFast(); - foreach (var asset in Assets) + if(Assets != null) { - assets.SetArray(asset.Name, asset.ToArray()); + var assets = new BFast(); + foreach (var asset in Assets) + { + assets.SetArray(asset.Name, asset.ToArray()); + } + bfast.SetBFast(BufferNames.Assets, assets); } - bfast.SetBFast(BufferNames.Assets, assets); - var entities = new BFast(); - foreach (var entity in EntityTables) + if(EntityTables != null) + { + var entities = new BFast(); + foreach (var entity in EntityTables) + { + entities.SetBFast(entity.Name, entity.ToBFast()); + } + bfast.SetBFast(BufferNames.Entities, entities); + } + + if (StringTable != null) + { + bfast.SetArray(BufferNames.Strings, BFastStrings.Pack(StringTable)); + } + + if(Geometry != null) { - entities.SetBFast(entity.Name, entity.ToBFast()); + bfast.SetBFast(BufferNames.Geometry, Geometry?.ToBFast()); } - bfast.SetBFast(BufferNames.Entities, entities); - bfast.SetArray(BufferNames.Strings, BFastStrings.Pack(StringTable)); - bfast.SetBFast(BufferNames.Geometry, Geometry.ToBFast()); + return bfast; } From 511ff4af3fb7f25ad49c40e4c1ddeb7e146b8cf5 Mon Sep 17 00:00:00 2001 From: simon Date: Mon, 25 Mar 2024 13:54:13 -0400 Subject: [PATCH 105/111] Change console.write to debug.write --- src/cs/bfast/Vim.BFast/Core/BFastHeader.cs | 3 ++- src/cs/g3d/Vim.G3d/G3D.cs | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/cs/bfast/Vim.BFast/Core/BFastHeader.cs b/src/cs/bfast/Vim.BFast/Core/BFastHeader.cs index 21191e25..bc0e62c4 100644 --- a/src/cs/bfast/Vim.BFast/Core/BFastHeader.cs +++ b/src/cs/bfast/Vim.BFast/Core/BFastHeader.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.IO; using System.Linq; @@ -55,7 +56,7 @@ private static void MakeNamesUnique(string[] names) { var count = nameSet[names[i]]; names[i] = names[i] + "_" + count; - Console.WriteLine($"Duplicated Name {names[i]} in BFAST. Making name unique. This can result in unexpected behaviour."); + Debug.WriteLine($"Duplicated Name {names[i]} in BFAST. Making name unique. This can result in unexpected behaviour."); } if (!nameSet.ContainsKey(names[i])) { diff --git a/src/cs/g3d/Vim.G3d/G3D.cs b/src/cs/g3d/Vim.G3d/G3D.cs index 220b588c..36e90ca7 100644 --- a/src/cs/g3d/Vim.G3d/G3D.cs +++ b/src/cs/g3d/Vim.G3d/G3D.cs @@ -12,6 +12,7 @@ Usage licensed under terms of MIT License using Vim.LinqArray; using Vim.Math3d; using Vim.BFastLib; +using System.Diagnostics; namespace Vim.G3d { @@ -319,7 +320,7 @@ private static GeometryAttribute GetEmptyAttribute(string name) { if (!AttributeDescriptor.TryParse(name, out var attributeDescriptor)) { - Console.WriteLine("G3D Error: Could not parse attribute " + name); + Debug.WriteLine("G3D Error: Could not parse attribute " + name); return null; } try @@ -328,7 +329,7 @@ private static GeometryAttribute GetEmptyAttribute(string name) } catch { - Console.WriteLine("G3D Error: Could not parse attribute " + name); + Debug.WriteLine("G3D Error: Could not parse attribute " + name); return null; } } From 9054031408ec01c6e55f7ab4dc11055c8ce21035 Mon Sep 17 00:00:00 2001 From: simon Date: Mon, 25 Mar 2024 13:54:23 -0400 Subject: [PATCH 106/111] removed unused code --- .../Vim.Format.Core/Geometry/Serialization.cs | 22 ------------------- 1 file changed, 22 deletions(-) delete mode 100644 src/cs/vim/Vim.Format.Core/Geometry/Serialization.cs diff --git a/src/cs/vim/Vim.Format.Core/Geometry/Serialization.cs b/src/cs/vim/Vim.Format.Core/Geometry/Serialization.cs deleted file mode 100644 index 7619d097..00000000 --- a/src/cs/vim/Vim.Format.Core/Geometry/Serialization.cs +++ /dev/null @@ -1,22 +0,0 @@ -using Vim.G3d; - -namespace Vim.Format.Geometry -{ - public static class Serialization - { - public static IMesh ReadG3D(string filePath) - => G3D.Read(filePath).ToIMesh(); - - public static G3D ToG3d(this IMesh mesh) - => mesh is G3D r ? r : mesh.Attributes.ToG3d(); - - public static void WriteG3d(this IMesh mesh, string filePath) - => mesh.ToG3d().ToBFast().Write(filePath); - - public static void WriteObj(this IMesh mesh, string filePath) - => mesh.ToG3d().WriteObj(filePath); - - public static void WritePly(this IMesh mesh, string filePath) - => mesh.ToG3d().WritePly(filePath); - } -} From 71182eed8b260d2f8256db7bfea73196daa4ec11 Mon Sep 17 00:00:00 2001 From: simon Date: Tue, 26 Mar 2024 15:30:49 -0400 Subject: [PATCH 107/111] getHeader from stream --- src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs b/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs index 9218a9ff..d9cfb483 100644 --- a/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs +++ b/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs @@ -101,6 +101,14 @@ public static bool TryGetHeader(Stream stream, out SerializableHeader header) } } + /// + /// Returns the VIM file's header. Returns null if the Vim has no header. + /// + public static SerializableHeader GetHeader(Stream stream) + { + return SerializableHeader.FromStream(stream); + } + public static VimScene LoadVim(string f, LoadOptions loadOptions, IVimSceneProgress progress = null, bool inParallel = false, int vimIndex = 0) => new VimScene(SerializableDocument.FromPath(f, loadOptions), progress, inParallel, vimIndex); From 32ff68cc2346ecd6ec250bc5881c373bd549ffab Mon Sep 17 00:00:00 2001 From: simon Date: Tue, 26 Mar 2024 15:30:49 -0400 Subject: [PATCH 108/111] getHeader from stream --- src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs b/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs index d9cfb483..6598d034 100644 --- a/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs +++ b/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs @@ -109,6 +109,14 @@ public static SerializableHeader GetHeader(Stream stream) return SerializableHeader.FromStream(stream); } + /// + /// Returns the VIM file's header. Returns null if the Vim has no header. + /// + public static SerializableHeader GetHeader(Stream stream) + { + return SerializableHeader.FromStream(stream); + } + public static VimScene LoadVim(string f, LoadOptions loadOptions, IVimSceneProgress progress = null, bool inParallel = false, int vimIndex = 0) => new VimScene(SerializableDocument.FromPath(f, loadOptions), progress, inParallel, vimIndex); From 320c28d22d3bb151af4ff2d9f14cc17a90165615 Mon Sep 17 00:00:00 2001 From: simon Date: Tue, 26 Mar 2024 14:51:39 -0400 Subject: [PATCH 109/111] added a test for partial documents --- .../SerializableDocumentTests.cs | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs diff --git a/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs b/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs new file mode 100644 index 00000000..497180d5 --- /dev/null +++ b/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs @@ -0,0 +1,29 @@ +using NUnit.Framework; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using Vim.Util.Tests; + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using NUnit.Framework; +using Vim.Util.Tests; + +namespace Vim.Format.Tests; + + + +[TestFixture] +public static class SerializableDocumentTests +{ + [Test] + public static void TestEmpty() + { + var doc = new SerializableDocument(); + Assert.DoesNotThrow(() => doc.ToBFast()); + } +} + From 0ea66a621582cdfd4ca60b5cb082ce2516b6a276 Mon Sep 17 00:00:00 2001 From: simon Date: Tue, 26 Mar 2024 14:51:18 -0400 Subject: [PATCH 110/111] extracted header logic to header file. Removed Try method versions --- .../vim/Vim.Format.Core/SerializableHeader.cs | 24 +++++- src/cs/vim/Vim.Format.Vimx/VimxHeader.cs | 2 +- .../vim/Vim.Format/SceneBuilder/VimScene.cs | 74 ++----------------- 3 files changed, 28 insertions(+), 72 deletions(-) diff --git a/src/cs/vim/Vim.Format.Core/SerializableHeader.cs b/src/cs/vim/Vim.Format.Core/SerializableHeader.cs index 41d076f2..c2e9010b 100644 --- a/src/cs/vim/Vim.Format.Core/SerializableHeader.cs +++ b/src/cs/vim/Vim.Format.Core/SerializableHeader.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Globalization; +using System.IO; using System.Linq; using System.Text; using Vim.BFastLib; @@ -97,7 +98,26 @@ public SerializableHeader(string generator, SerializableVersion schema, string v public static SerializableHeader FromBytes(byte[] input) { - return Parse(Encoding.UTF8.GetString(input)); + return FromString(Encoding.UTF8.GetString(input)); + } + + + /// + /// Returns the VIM header from a vim file stream. + /// Will throw if the file is not a valid VIM. + /// + public static SerializableHeader FromStream(Stream stream) + { + var bfast = new BFast(stream); + var bytes = bfast.GetArray(BufferNames.Header); + if (bytes == null) return null; + return SerializableHeader.FromBytes(bytes); + } + + public static SerializableHeader FromPath(string path) + { + using (var file = new FileStream(path, FileMode.OpenOrCreate)) + return FromStream(file); } /// @@ -107,7 +127,7 @@ public static SerializableHeader FromBytes(byte[] input) /// /// /// - public static SerializableHeader Parse(string input) + public static SerializableHeader FromString(string input) { var lines = input.Split(EndOfLineChar) .Where(str => !string.IsNullOrEmpty(str)); diff --git a/src/cs/vim/Vim.Format.Vimx/VimxHeader.cs b/src/cs/vim/Vim.Format.Vimx/VimxHeader.cs index d664ae58..a513ae82 100644 --- a/src/cs/vim/Vim.Format.Vimx/VimxHeader.cs +++ b/src/cs/vim/Vim.Format.Vimx/VimxHeader.cs @@ -8,7 +8,7 @@ public static class VimxHeader static SerializableVersion CurrentVersion = SerializableVersion.Parse("0.1.0"); public static SerializableHeader FromString(string header) { - return SerializableHeader.Parse(header.Replace("vimx", "vim")); + return SerializableHeader.FromString(header.Replace("vimx", "vim")); } public static SerializableHeader FromBytes(byte[] header) { diff --git a/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs b/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs index 6598d034..1920cabe 100644 --- a/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs +++ b/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs @@ -22,83 +22,19 @@ namespace Vim public class VimScene : IScene { /// - /// Returns the VIM file's header schema version. Returns null if the header schema is not found. + /// Returns the VIM file's header schema version. Returns null if the Vim has no header. /// - public static string GetSchemaVersion(string path) + public static SerializableVersion GetSchemaVersion(string path) { - return GetHeader(path).Schema.ToString(); + return GetHeader(path)?.Schema; } /// - /// Returns the VIM file's header schema version. Returns null if the header schema is not found. + /// Returns the VIM file's header. Returns null if the Vim has no header. /// - public static bool TryGetSchemaVersion(string path, out string schema) - { - try - { - schema = GetSchemaVersion(path); - return true; - } - catch (Exception e) - { - Console.WriteLine(e); - schema = null; - return false; - } - } - public static SerializableHeader GetHeader(string path) { - using (var file = new FileStream(path, FileMode.OpenOrCreate)) - { - return GetHeader(file); - } - } - - public static bool TryGetHeader(string path, out SerializableHeader header) - { - using (var file = new FileStream(path, FileMode.OpenOrCreate)) - { - return TryGetHeader(file, out header); - } - } - - /// - /// Returns the VIM header from a vim file stream. - /// Will throw if the file is not a valid VIM. - /// - public static SerializableHeader GetHeader(Stream stream) - { - var bfast = new BFast(stream); - var bytes = bfast.GetArray(BufferNames.Header); - if (bytes == null) return null; - return SerializableHeader.FromBytes(bytes); - } - - /// - /// Returns true along along with the VIM header from a valid vim file stream. - /// Returns false and null and resets the stream at given position for invalid file. - /// - public static bool TryGetHeader(Stream stream, out SerializableHeader header) - { - var position = stream.Position; - try - { - header = GetHeader(stream); - return true; - } - catch (Exception e) - { - Console.WriteLine(e); - - if (stream.CanSeek) - { - stream.Seek(position, SeekOrigin.Begin); - } - - header = null; - return false; - } + return SerializableHeader.FromPath(path); } /// From 69662accbd6212a973ddd2d1966f80aafd74510a Mon Sep 17 00:00:00 2001 From: simon Date: Tue, 26 Mar 2024 15:48:35 -0400 Subject: [PATCH 111/111] duplicated method --- src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs b/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs index 1920cabe..a502aaa8 100644 --- a/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs +++ b/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs @@ -45,14 +45,6 @@ public static SerializableHeader GetHeader(Stream stream) return SerializableHeader.FromStream(stream); } - /// - /// Returns the VIM file's header. Returns null if the Vim has no header. - /// - public static SerializableHeader GetHeader(Stream stream) - { - return SerializableHeader.FromStream(stream); - } - public static VimScene LoadVim(string f, LoadOptions loadOptions, IVimSceneProgress progress = null, bool inParallel = false, int vimIndex = 0) => new VimScene(SerializableDocument.FromPath(f, loadOptions), progress, inParallel, vimIndex);