From 74ae5944b5ce1c6ea303b1ab4edd0b713beddc0d Mon Sep 17 00:00:00 2001 From: simon Date: Mon, 28 Aug 2023 14:13:21 -0400 Subject: [PATCH 001/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] "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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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/204] 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); From 41a603e7123498d2e1abc1497bd7bf544cc43c39 Mon Sep 17 00:00:00 2001 From: simon Date: Mon, 1 Apr 2024 13:30:13 -0400 Subject: [PATCH 112/204] Added VimMesh to replace IMesh eventually --- src/cs/g3d/Vim.G3dNext.CodeGen/G3dCodeGen.cs | 8 ++ src/cs/g3d/Vim.G3dNext/G3dChunk.cs | 62 +++++++++++++++ src/cs/g3d/Vim.G3dNext/G3dGenerated.g.cs | 61 +++++++++++++++ src/cs/g3d/Vim.G3dNext/G3dVim.cs | 45 +++++++++++ .../util/Vim.Util.Tests/VimFormatRepoPaths.cs | 2 +- src/cs/vim/Vim.Format.Core/Document.cs | 3 + .../Vim.Format.Core/SerializableDocument.cs | 75 ++---------------- .../SerializableEntityTable.cs | 70 +++++++++++++++-- .../Vim.Format.Core/Vim.Format.Core.csproj | 1 + .../SerializableDocumentTests.cs | 75 +++++++++++++++--- .../vim/Vim.Format/SceneBuilder/Validation.cs | 76 ++++++++++++++++++- .../vim/Vim.Format/SceneBuilder/VimScene.cs | 10 ++- src/cs/vim/Vim.Format/Vim.Format.csproj | 1 + 13 files changed, 401 insertions(+), 88 deletions(-) diff --git a/src/cs/g3d/Vim.G3dNext.CodeGen/G3dCodeGen.cs b/src/cs/g3d/Vim.G3dNext.CodeGen/G3dCodeGen.cs index 5724b22f..59cd7b22 100644 --- a/src/cs/g3d/Vim.G3dNext.CodeGen/G3dCodeGen.cs +++ b/src/cs/g3d/Vim.G3dNext.CodeGen/G3dCodeGen.cs @@ -113,6 +113,14 @@ public bool Equals({entity.ClassName} other ) ); }} + public int CountOf(string name) + {{ + {string.Join("\n \t\t\t", entity.Buffers.Select(c => { + return $"if(name == \"{c.BufferName}\") return {c.MemberName}?.Length ?? -1;"; + }))} + return -1; + }} + 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 index 8ad82bd3..b445ba11 100644 --- a/src/cs/g3d/Vim.G3dNext/G3dChunk.cs +++ b/src/cs/g3d/Vim.G3dNext/G3dChunk.cs @@ -1,8 +1,33 @@ using System; +using System.Linq; using Vim.Math3d; namespace Vim.G3dNext { + public class VimMesh : ITransformable3D + { + public int[] indices; + public Vector3[] vertices; + public int[] submeshes; + public int[] submeshMaterials; + + public VimMesh Transform(Matrix4x4 mat) + { + var mesh = new VimMesh(); + mesh.indices = indices.ToArray(); + mesh.vertices = new Vector3[vertices.Length]; + mesh.submeshes = submeshes.ToArray(); + mesh.submeshMaterials = submeshMaterials.ToArray(); + + for(var i =0; i < vertices.Length;i++ ) + { + mesh.vertices[i] = vertices[i].Transform(mat); + } + return mesh; + } + } + + public partial class G3dChunk { void ISetup.Setup() @@ -10,6 +35,43 @@ void ISetup.Setup() // empty } + public VimMesh GetMesh(int index) + { + var mesh = new VimMesh(); + + var vStart = GetMeshVertexStart(index, MeshSection.All); + var vEnd = GetMeshVertexEnd(index, MeshSection.All); + mesh.vertices = new Vector3[vEnd - vStart]; + for (var i = 0; i < mesh.vertices.Length; i++) + { + var v = vStart + i; + mesh.vertices[i] = Positions[v]; + } + + var iStart = GetMeshIndexStart(index, MeshSection.All); + var iEnd = GetMeshIndexEnd(index, MeshSection.All); + mesh.indices = new int[iEnd - iStart]; + for (var i = 0; i < mesh.indices.Length; i++) + { + var j = iStart + i; + mesh.indices[i] = Indices[j] - vStart; + } + + var sStart = GetMeshSubmeshStart(index, MeshSection.All); + var sEnd = GetMeshSubmeshEnd(index, MeshSection.All); + mesh.submeshes = new int[sEnd - sStart]; + mesh.submeshMaterials = new int[sEnd - sStart]; + + for (var i =0; i < mesh.submeshMaterials.Length; i++) + { + var s = sStart + i; + mesh.submeshes[i] = SubmeshIndexOffsets[s] - vStart; + mesh.submeshMaterials[i] = SubmeshMaterials[s]; + } + + return mesh; + } + public int GetSubmeshCount() => SubmeshIndexOffsets?.Length ?? 0; public int getMeshCount() => MeshSubmeshOffset?.Length ?? 0; diff --git a/src/cs/g3d/Vim.G3dNext/G3dGenerated.g.cs b/src/cs/g3d/Vim.G3dNext/G3dGenerated.g.cs index 5d2a7b8d..5a2a9801 100644 --- a/src/cs/g3d/Vim.G3dNext/G3dGenerated.g.cs +++ b/src/cs/g3d/Vim.G3dNext/G3dGenerated.g.cs @@ -151,6 +151,27 @@ public G3dVim Merge(G3dVim other) ); } + public int CountOf(string name) + { + if(name == "g3d:corner:index:0:int32:1") return Indices?.Length ?? -1; + if(name == "g3d:vertex:position:0:float32:3") return Positions?.Length ?? -1; + if(name == "g3d:instance:transform:0:float32:16") return InstanceTransforms?.Length ?? -1; + if(name == "g3d:instance:parent:0:int32:1") return InstanceParents?.Length ?? -1; + if(name == "g3d:instance:flags:0:uint16:1") return InstanceFlags?.Length ?? -1; + if(name == "g3d:instance:mesh:0:int32:1") return InstanceMeshes?.Length ?? -1; + if(name == "g3d:mesh:submeshoffset:0:int32:1") return MeshSubmeshOffsets?.Length ?? -1; + if(name == "g3d:submesh:indexoffset:0:int32:1") return SubmeshIndexOffsets?.Length ?? -1; + if(name == "g3d:submesh:material:0:int32:1") return SubmeshMaterials?.Length ?? -1; + if(name == "g3d:material:color:0:float32:4") return MaterialColors?.Length ?? -1; + if(name == "g3d:material:glossiness:0:float32:1") return MaterialGlossiness?.Length ?? -1; + if(name == "g3d:material:smoothness:0:float32:1") return MaterialSmoothness?.Length ?? -1; + if(name == "g3d:shapevertex:position:0:float32:3") return ShapeVertices?.Length ?? -1; + if(name == "g3d:shape:vertexoffset:0:int32:1") return ShapeVertexOffsets?.Length ?? -1; + if(name == "g3d:shape:color:0:float32:4") return ShapeColors?.Length ?? -1; + if(name == "g3d:shape:width:0:float32:1") return ShapeWidths?.Length ?? -1; + return -1; + } + public void Validate() { // Ensure all the indices are either -1 or within the bounds of the attributes they are indexing into. @@ -248,6 +269,18 @@ public G3dChunk Merge(G3dChunk other) ); } + public int CountOf(string name) + { + if(name == "g3d:mesh:opaquesubmeshcount:0:int32:1") return MeshOpaqueSubmeshCounts?.Length ?? -1; + if(name == "g3d:mesh:submeshoffset:0:int32:1") return MeshSubmeshOffset?.Length ?? -1; + if(name == "g3d:submesh:indexoffset:0:int32:1") return SubmeshIndexOffsets?.Length ?? -1; + if(name == "g3d:submesh:vertexoffset:0:int32:1") return SubmeshVertexOffsets?.Length ?? -1; + if(name == "g3d:submesh:material:0:int32:1") return SubmeshMaterials?.Length ?? -1; + if(name == "g3d:vertex:position:0:float32:3") return Positions?.Length ?? -1; + if(name == "g3d:corner:index:0:int32:1") return Indices?.Length ?? -1; + return -1; + } + public void Validate() { // Ensure all the indices are either -1 or within the bounds of the attributes they are indexing into. @@ -314,6 +347,14 @@ public G3dMaterials Merge(G3dMaterials other) ); } + public int CountOf(string name) + { + if(name == "g3d:material:color:0:float32:4") return MaterialColors?.Length ?? -1; + if(name == "g3d:material:glossiness:0:float32:1") return MaterialGlossiness?.Length ?? -1; + if(name == "g3d:material:smoothness:0:float32:1") return MaterialSmoothness?.Length ?? -1; + return -1; + } + public void Validate() { // Ensure all the indices are either -1 or within the bounds of the attributes they are indexing into. @@ -461,6 +502,26 @@ public G3dScene Merge(G3dScene other) ); } + public int CountOf(string name) + { + if(name == "g3d:chunk:count:0:int32:1") return ChunkCount?.Length ?? -1; + if(name == "g3d:instance:mesh:0:int32:1") return InstanceMeshes?.Length ?? -1; + if(name == "g3d:instance:transform:0:float32:16") return InstanceTransformData?.Length ?? -1; + if(name == "g3d:instance:node:0:int32:1") return InstanceNodes?.Length ?? -1; + if(name == "g3d:instance:group:0:int32:1") return InstanceGroups?.Length ?? -1; + if(name == "g3d:instance:tag:0:int64:1") return InstanceTags?.Length ?? -1; + if(name == "g3d:instance:flags:0:uint16:1") return InstanceFlags?.Length ?? -1; + if(name == "g3d:instance:min:0:float32:3") return InstanceMins?.Length ?? -1; + if(name == "g3d:instance:max:0:float32:3") return InstanceMaxs?.Length ?? -1; + if(name == "g3d:mesh:chunk:0:int32:1") return MeshChunks?.Length ?? -1; + if(name == "g3d:mesh:chunkindex:0:int32:1") return MeshChunkIndices?.Length ?? -1; + if(name == "g3d:mesh:vertexcount:0:int32:1") return MeshVertexCounts?.Length ?? -1; + if(name == "g3d:mesh:indexcount:0:int32:1") return MeshIndexCounts?.Length ?? -1; + if(name == "g3d:mesh:opaquevertexcount:0:int32:1") return MeshOpaqueVertexCounts?.Length ?? -1; + if(name == "g3d:mesh:opaqueindexcount:0:int32:1") return MeshOpaqueIndexCounts?.Length ?? -1; + return -1; + } + 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/G3dVim.cs b/src/cs/g3d/Vim.G3dNext/G3dVim.cs index 3ddb9885..0801564d 100644 --- a/src/cs/g3d/Vim.G3dNext/G3dVim.cs +++ b/src/cs/g3d/Vim.G3dNext/G3dVim.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; +using System.Linq; using Vim.BFastLib; +using Vim.Math3d; namespace Vim.G3dNext { @@ -10,6 +12,49 @@ public partial class G3dVim public int[] MeshVertexOffsets; private List[] _meshInstances; + + public VimMesh GetMesh(int index) + { + var mesh = new VimMesh(); + + var vStart = GetMeshVertexStart(index); + var vEnd = GetMeshVertexEnd(index); + mesh.vertices = new Vector3[vEnd - vStart]; + for (var i = 0; i < mesh.vertices.Length; i++) + { + var v = vStart + i; + mesh.vertices[i] = Positions[v]; + } + + var iStart = GetMeshIndexStart(index); + var iEnd = GetMeshIndexEnd(index); + mesh.indices = new int[iEnd - iStart]; + for (var i = 0; i < mesh.indices.Length; i++) + { + var j = iStart + i; + mesh.indices[i] = Indices[j] - vStart; + } + + var sStart = GetMeshSubmeshStart(index); + var sEnd = GetMeshSubmeshEnd(index); + mesh.submeshes = new int[sEnd - sStart]; + mesh.submeshMaterials = new int[sEnd - sStart]; + + for (var i = 0; i < mesh.submeshMaterials.Length; i++) + { + var s = sStart + i; + mesh.submeshes[i] = SubmeshIndexOffsets[s] - iStart; + mesh.submeshMaterials[i] = SubmeshMaterials[s]; + } + + return mesh; + } + + public IEnumerable GetAllMeshes() + { + return Enumerable.Range(0, GetMeshCount()).Select(i => GetMesh(i)); + } + public IReadOnlyList GetMeshInstances(int mesh) { return _meshInstances[mesh]; diff --git a/src/cs/util/Vim.Util.Tests/VimFormatRepoPaths.cs b/src/cs/util/Vim.Util.Tests/VimFormatRepoPaths.cs index 2a76d8b7..5816c16f 100644 --- a/src/cs/util/Vim.Util.Tests/VimFormatRepoPaths.cs +++ b/src/cs/util/Vim.Util.Tests/VimFormatRepoPaths.cs @@ -26,7 +26,7 @@ public static class VimFormatRepoPaths /// public static string GetLatestWolfordResidenceVim() { - var matchingVim = Directory.GetFiles(DataDir, "Wolford_Residence*.vim", SearchOption.AllDirectories).FirstOrDefault(); + var matchingVim = Directory.GetFiles(DataDir, "Wolford_Residence*.vim", SearchOption.AllDirectories).OrderByDescending(p => p).FirstOrDefault(); if (matchingVim == null) throw new FileNotFoundException($"Could not find the latest Wolford Residence VIM."); diff --git a/src/cs/vim/Vim.Format.Core/Document.cs b/src/cs/vim/Vim.Format.Core/Document.cs index 8465ea7d..eecebb48 100644 --- a/src/cs/vim/Vim.Format.Core/Document.cs +++ b/src/cs/vim/Vim.Format.Core/Document.cs @@ -1,5 +1,6 @@ using Vim.LinqArray; using Vim.BFastLib; +using Vim.G3dNext; namespace Vim.Format { @@ -11,6 +12,7 @@ public Document(SerializableDocument document) _Document = document; Header = _Document.Header; Geometry = _Document.Geometry; + GeometryNext = _Document.GeometryNext; StringTable = _Document.StringTable.ToIArray(); EntityTables = _Document.EntityTables.ToLookup( et => et.Name, @@ -26,5 +28,6 @@ public Document(SerializableDocument document) public IArray StringTable { get; } public string GetString(int index) => StringTable.ElementAtOrDefault(index); public G3d.G3D Geometry { get; } + public G3dVim GeometryNext { get; } } } diff --git a/src/cs/vim/Vim.Format.Core/SerializableDocument.cs b/src/cs/vim/Vim.Format.Core/SerializableDocument.cs index 3a9ae487..99318a01 100644 --- a/src/cs/vim/Vim.Format.Core/SerializableDocument.cs +++ b/src/cs/vim/Vim.Format.Core/SerializableDocument.cs @@ -1,11 +1,11 @@ using System; using System.Collections.Generic; -using System.IO; using System.Linq; using System.Text; using Vim.BFastLib; using Vim.BFastLib.Core; using Vim.G3d; +using Vim.G3dNext; namespace Vim.Format { @@ -54,6 +54,11 @@ public class SerializableDocument /// public G3d.G3D Geometry; + /// + /// The uninstanced / untransformed geometry + /// + public G3dVim GeometryNext; + /// /// The originating file name (if provided) /// @@ -123,6 +128,7 @@ public static SerializableDocument FromBFast(BFast bfast, LoadOptions options = { var geo = bfast.GetBFast(BufferNames.Geometry); doc.Geometry = G3D.Read(geo); + doc.GeometryNext = new G3dVim(geo); } var entities = bfast.GetBFast(BufferNames.Entities); @@ -141,75 +147,10 @@ private static IEnumerable GetEntityTables( foreach (var entry in bfast.Entries) { var b = bfast.GetBFast(entry); - var table = ReadEntityTable(b, schemaOnly); + var table = SerializableEntityTable.FromBFast(b, schemaOnly); table.Name = entry; yield return table; } } - - /// - /// Returns a SerializableEntityTable based on the given buffer reader. - /// - public static SerializableEntityTable ReadEntityTable( - BFast bfast, - bool schemaOnly - ) - { - var et = new SerializableEntityTable(); - foreach (var entry in bfast.Entries) - { - var typePrefix = SerializableEntityTable.GetTypeFromName(entry); - - 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; - } } } diff --git a/src/cs/vim/Vim.Format.Core/SerializableEntityTable.cs b/src/cs/vim/Vim.Format.Core/SerializableEntityTable.cs index dd724bb9..4b86268c 100644 --- a/src/cs/vim/Vim.Format.Core/SerializableEntityTable.cs +++ b/src/cs/vim/Vim.Format.Core/SerializableEntityTable.cs @@ -43,11 +43,6 @@ public IEnumerable AllColumns .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) @@ -56,6 +51,71 @@ public static string GetTypeFromName(string name) return match.Success ? match.Groups[1].Value : ""; } + /// + /// Returns a SerializableEntityTable based on the given buffer reader. + /// + public static SerializableEntityTable FromBFast( + BFast bfast, + bool schemaOnly + ) + { + var et = new SerializableEntityTable(); + foreach (var entry in bfast.Entries) + { + var typePrefix = SerializableEntityTable.GetTypeFromName(entry); + + 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; + } + public BFast ToBFast() { var bfast = new 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 382777aa..f02d4460 100644 --- a/src/cs/vim/Vim.Format.Core/Vim.Format.Core.csproj +++ b/src/cs/vim/Vim.Format.Core/Vim.Format.Core.csproj @@ -12,6 +12,7 @@ + diff --git a/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs b/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs index 497180d5..2f2eeec8 100644 --- a/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs +++ b/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs @@ -1,16 +1,10 @@ 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; +using Vim.Format.SceneBuilder; +using Vim.G3dNext; +using Vim.Format.Geometry; +using Vim.LinqArray; +using Vim.Math3d; namespace Vim.Format.Tests; @@ -25,5 +19,64 @@ public static void TestEmpty() var doc = new SerializableDocument(); Assert.DoesNotThrow(() => doc.ToBFast()); } + + [Test] + public static void CanOpenVim() + { + var path = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); + var scene = VimScene.LoadVim(path); + scene.Validate(); + } + + [Test] + public static void MaterialColor_IsSame() + { + var path = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); + var scene = VimScene.LoadVim(path); + for(var i=0; i < scene.GetMaterialCount(); i++) + { + Assert.AreEqual(scene.GetMaterialColor(i),scene.GetMaterialColorNext(i)); + } + } + + [Test] + public static void GetMesh_IsSameMesh() + { + var path = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); + var scene = VimScene.LoadVim(path); + for (var i = 0; i < scene.GetMeshCount(); i++) + { + var mesh = scene.Meshes[i]; + var next = scene.MeshesNext[i]; + MeshesAreSame(mesh, next); + } + } + + [Test] + public static void GetMesh_Transform_IsSame() + { + var path = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); + var scene = VimScene.LoadVim(path); + for (var i = 0; i < scene.GetMeshCount(); i++) + { + var mat = Matrix4x4.CreateWorld( + new Vector3(1, -2, 3), + new Vector3(0, 0, 1), + new Vector3(0, 1, 0) + ); + var mesh = scene.Meshes[i].Transform(mat); + var next = scene.MeshesNext[i].Transform(mat); + MeshesAreSame(mesh, next); + } + } + + private static void MeshesAreSame(IMesh mesh, VimMesh next) + { + + Assert.That(mesh.Indices.SequenceEquals(next.indices.ToIArray())); + Assert.That(mesh.Vertices.SequenceEquals(next.vertices.ToIArray())); + Assert.That(mesh.SubmeshIndexOffsets.SequenceEquals(next.submeshes.ToIArray())); + Assert.That(mesh.SubmeshMaterials.SequenceEquals(next.submeshMaterials.ToIArray())); + } } diff --git a/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs b/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs index 66365bb4..a1eaa15f 100644 --- a/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs +++ b/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs @@ -9,6 +9,7 @@ using Vim.Util; using Vim.LinqArray; using Vim.Math3d; +using Vim.G3d; namespace Vim.Format.SceneBuilder { @@ -28,19 +29,27 @@ public static void ValidateGeometry(this VimScene vim) { // Validate the packed geometry. vim.Document.Geometry.ToIMesh().Validate(); + var errors = new List(); + + G3d.Validation.Validate(vim.Document.Geometry); + // Validate the individual meshes. foreach (var g in vim.Meshes.ToEnumerable()) g.Validate(); } + public static void ValidateGeometryNext(this VimScene vim) + { + //TODO: Sronger validation maybe. + vim.Document.GeometryNext.Validate(); + } + public static void ValidateDocumentModelToG3dInvariants(this VimScene vim) { var g3d = vim._SerializableDocument.Geometry; var errors = new List(); - errors.AddRange(Vim.G3d.Validation.Validate(g3d).Select(e => e.ToString("G"))); - var entityTypesWithG3dReferences = new HashSet<(Type, G3dAttributeReferenceAttribute[])>( ObjectModelReflection.GetEntityTypes() .Select(t => ( @@ -94,6 +103,65 @@ public static void ValidateDocumentModelToG3dInvariants(this VimScene vim) } } + + + public static void ValidateDocumentModelToG3dInvariantsNext(this VimScene vim) + { + var g3d = vim.Document.GeometryNext; + var errors = new List(); + + var entityTypesWithG3dReferences = new HashSet<(Type, G3dAttributeReferenceAttribute[])>( + ObjectModelReflection.GetEntityTypes() + .Select(t => ( + type: t, + attrs: t.GetCustomAttributes(typeof(G3dAttributeReferenceAttribute)) + .Select(a => a as G3dAttributeReferenceAttribute) + .ToArray())) + .Where(tuple => tuple.attrs.Length != 0)); + + var dm = vim.DocumentModel; + + foreach (var tuple in entityTypesWithG3dReferences) + { + var (type, attrs) = tuple; + var propertyName = type.Name + "List"; + if (dm.GetPropertyValue(propertyName) is IArray arr) + { + var numEntities = arr.Count; + + foreach (var attr in attrs) + { + var attributeName = attr.AttributeName; + var isOptional = attr.AttributeIsOptional; + + var count = g3d.CountOf(attributeName); + + // We don't check the relation if the attribute is optional and absent (null). + if (isOptional && count < 0) + continue; + + var mult = attr.AttributeReferenceMultiplicity; + + // Validate one-to-one relationships + if (mult == G3dAttributeReferenceMultiplicity.OneToOne && numEntities != count) + { + errors.Add($"Multiplicity Error ({mult}); the number of entities of type \"{type.Name}\" ({numEntities}) is not equal to the number of elements in the g3d attribute \"{attributeName}\" ({count})"); + } + } + } + else + { + throw new VimValidationException($"DocumentModel.{propertyName} not found"); + } + } + + if (errors.Count > 0) + { + throw new VimValidationException( + $"DocumentModel to G3d invariant error(s):{Environment.NewLine}{string.Join(Environment.NewLine, errors)}"); + } + } + public static void ValidateNodes(this VimScene vim) { if (vim.VimNodes.Count != vim.DocumentModel.NumNode) @@ -138,7 +206,11 @@ public static void Validate(this VimScene vim, VimValidationOptions options = nu vim.Document.Validate(); vim.DocumentModel.Validate(options.ObjectModelValidationOptions); vim.ValidateGeometry(); + vim.ValidateGeometryNext(); + vim.ValidateDocumentModelToG3dInvariants(); + vim.ValidateDocumentModelToG3dInvariantsNext(); + vim.ValidateNodes(); vim.ValidateShapes(); } diff --git a/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs b/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs index a502aaa8..ce3e7c51 100644 --- a/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs +++ b/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs @@ -11,6 +11,7 @@ using Vim.Math3d; using IVimSceneProgress = System.IProgress<(string, double)>; using Vim.BFastLib; +using Vim.G3dNext; namespace Vim { @@ -59,6 +60,7 @@ public static VimScene LoadVim(Stream stream, IVimSceneProgress progress = null, public int VimIndex { get; set; } public IArray Meshes { get; private set; } + public VimMesh[] MeshesNext { get; private set; } public IArray Nodes { get; private set; } public IArray VimNodes { get; private set; } public IArray VimShapes { get; private set; } @@ -71,12 +73,15 @@ public static VimScene LoadVim(Stream stream, IVimSceneProgress progress = null, public string PersistingId => Document.Header.PersistingId; - public Material GetMaterial(int materialIndex) - => DocumentModel.MaterialList.ElementAtOrDefault(materialIndex); + public int GetMeshCount() => Meshes.Count; + public int GetMaterialCount() => Materials.Count; public Vector4 GetMaterialColor(int materialIndex) => _SerializableDocument.Geometry.MaterialColors[materialIndex]; + public Vector4 GetMaterialColorNext(int materialIndex) + => _SerializableDocument.GeometryNext.MaterialColors[materialIndex]; + public static IMesh ToIMesh(G3dMesh g3d) => Primitives.TriMesh( g3d.Vertices.ToPositionAttribute(), @@ -200,6 +205,7 @@ private void CreateMeshes(bool inParallel) : inParallel ? tmp.EvaluateInParallel() : tmp.Evaluate(); + MeshesNext = _SerializableDocument.GeometryNext.GetAllMeshes().ToArray(); } private void CreateShapes(bool inParallel) diff --git a/src/cs/vim/Vim.Format/Vim.Format.csproj b/src/cs/vim/Vim.Format/Vim.Format.csproj index 8fa44b7a..6f385377 100644 --- a/src/cs/vim/Vim.Format/Vim.Format.csproj +++ b/src/cs/vim/Vim.Format/Vim.Format.csproj @@ -35,6 +35,7 @@ true true + From 9b169ea520242c27c513155559045b20171ee002 Mon Sep 17 00:00:00 2001 From: simon Date: Mon, 1 Apr 2024 13:34:04 -0400 Subject: [PATCH 113/204] removed unused methods --- .../Geometry/SceneExtensions.cs | 42 +------------------ 1 file changed, 1 insertion(+), 41 deletions(-) diff --git a/src/cs/vim/Vim.Format.Core/Geometry/SceneExtensions.cs b/src/cs/vim/Vim.Format.Core/Geometry/SceneExtensions.cs index 8f6e2f9a..d760f734 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/SceneExtensions.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/SceneExtensions.cs @@ -13,50 +13,16 @@ public static IMesh TransformedMesh(this ISceneNode node) public static IEnumerable TransformedMeshes(this IScene scene) => scene.Nodes.Where(n => n.GetMesh() != null).Select(TransformedMesh); - - public static IMesh ToIMesh(this IScene scene) - => scene.TransformedMeshes().Merge(); - - public static bool HasLoop(this ISceneNode n) - { - if (n == null) return false; - var visited = new HashSet(); - for (; n != null; n = n.Parent) - { - if (visited.Contains(n)) - return true; - visited.Add(n); - } - - return false; - } - + public static IMesh MergedGeometry(this IScene scene) => scene.Nodes.ToEnumerable().MergedGeometry(); public static IMesh MergedGeometry(this IEnumerable nodes) => nodes.Where(n => n.GetMesh() != null).Select(TransformedMesh).Merge(); - public static Matrix4x4 LocalTransform(this ISceneNode node) - => node.Parent != null - ? node.Transform * node.Parent.Transform.Inverse() - : node.Transform; - - public static IEnumerable AllDistinctMeshes(this IScene scene) - => scene.UntransformedMeshes().Where(x => x != null).Distinct(); - - public static IndexedSet GeometryLookup(this IScene scene) - => scene.Meshes.ToEnumerable().ToIndexedSet(); - public static IArray UntransformedMeshes(this IScene scene) => scene.Nodes.Select(n => n.GetMesh()); - public static bool HasGeometry(this IScene scene) - => scene.Nodes.Any(n => n.GetMesh() != null); - - public static Dictionary GeometryCounts(this IScene scene) - => scene.Nodes.ToEnumerable().CountInstances(x => x.GetMesh()); - public static IEnumerable AllVertices(this IScene scene) => scene.TransformedMeshes().SelectMany(g => g.Vertices.ToEnumerable()); @@ -69,15 +35,9 @@ public static IArray Transforms(this IScene scene) public static IArray NodePositions(this IScene scene) => scene.Transforms().Select(m => m.Translation); - public static AABox NodePositionBoundingBox(this IScene scene) - => AABox.Create(scene.NodePositions().ToEnumerable()); - public static Sphere BoundingSphere(this IScene scene) => scene.BoundingBox().ToSphere(); - public static float BoundingRadius(this IScene scene) - => scene.BoundingSphere().Radius; - public static IArray TransformedVertices(this ISceneNode node) => node.TransformedMesh()?.Vertices; From e84b315cef04d09c594f876cd15765994d6eeb6d Mon Sep 17 00:00:00 2001 From: simon Date: Mon, 1 Apr 2024 13:36:33 -0400 Subject: [PATCH 114/204] removed more unused methods --- .../vim/Vim.Format.Core/Geometry/SceneExtensions.cs | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/cs/vim/Vim.Format.Core/Geometry/SceneExtensions.cs b/src/cs/vim/Vim.Format.Core/Geometry/SceneExtensions.cs index d760f734..555baefa 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/SceneExtensions.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/SceneExtensions.cs @@ -20,24 +20,12 @@ public static IMesh MergedGeometry(this IScene scene) public static IMesh MergedGeometry(this IEnumerable nodes) => nodes.Where(n => n.GetMesh() != null).Select(TransformedMesh).Merge(); - public static IArray UntransformedMeshes(this IScene scene) - => scene.Nodes.Select(n => n.GetMesh()); - public static IEnumerable AllVertices(this IScene scene) => scene.TransformedMeshes().SelectMany(g => g.Vertices.ToEnumerable()); public static AABox BoundingBox(this IScene scene) => AABox.Create(scene.AllVertices()); - public static IArray Transforms(this IScene scene) - => scene.Nodes.Select(n => n.Transform); - - public static IArray NodePositions(this IScene scene) - => scene.Transforms().Select(m => m.Translation); - - public static Sphere BoundingSphere(this IScene scene) - => scene.BoundingBox().ToSphere(); - public static IArray TransformedVertices(this ISceneNode node) => node.TransformedMesh()?.Vertices; From f617135e1c4d4034799632f0048cbbbce08b5991 Mon Sep 17 00:00:00 2001 From: simon Date: Mon, 1 Apr 2024 13:51:20 -0400 Subject: [PATCH 115/204] removed unused code --- .../Geometry/MeshOptimization.cs | 78 ------------------- 1 file changed, 78 deletions(-) diff --git a/src/cs/vim/Vim.Format.Core/Geometry/MeshOptimization.cs b/src/cs/vim/Vim.Format.Core/Geometry/MeshOptimization.cs index 6efb92f3..4db387a7 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/MeshOptimization.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/MeshOptimization.cs @@ -58,87 +58,9 @@ public override int GetHashCode() => Hash.Combine(NumFaces, NumVertices, TopologyHash, BoxMin.GetHashCode(), BoxExtents.GetHashCode()); } - public class IntegerPositionColorNormal - { - public Int3 Position; - public Int3 Color; - public Int3 Normal; - - public IntegerPositionColorNormal(Int3 pos, Int3 color, Int3 normal) - => (Position, Color, Normal) = (pos, color, normal); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override int GetHashCode() - => Hash.Combine(Position.GetHashCode(), Color.GetHashCode(), Normal.GetHashCode()); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override bool Equals(object obj) - => Equals(obj as IntegerPositionColorNormal); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Equals(IntegerPositionColorNormal other) - => other != null && Position.Equals(other.Position) && Color.Equals(other.Color) && Normal.Equals(other.Normal); - } - public static class Optimization { - public static Dictionary> GroupMeshesByHash(this IArray meshes, float tolerance) - => meshes.ToEnumerable().GroupMeshesByHash(tolerance); - public static Dictionary> GroupMeshesByHash(this IEnumerable meshes, float tolerance) => meshes.AsParallel().GroupBy(m => new MeshHash(m, tolerance)).ToDictionary(grp => grp.Key, grp => grp.ToList()); - - /// - /// Merges vertices that are within a certain distance and have similar normals and colors. - /// - public static IMesh WeldVertices(this IMesh g, float threshold = (float)Math3d.Constants.MmToFeet) - { - var positions = g.Vertices; - var normals = g.GetOrComputeVertexNormals().ToArray(); - var colors = g.VertexColors ?? Vector4.Zero.Repeat(positions.Count); - - // Vertex indices by color, and then by normal - var d = new Dictionary(); - - // The mapping of old indices to new ones - var indexRemap = new int[g.Vertices.Count]; - - // This is a list of vertex indices that we are keeping - var vertRemap = new List(); - - // Local helper function - Int3 ToInt3(Vector3 v) - => new Int3((int)v.X, (int)v.Y, (int)v.Z); - - for (var i = 0; i < g.NumVertices; ++i) - { - var p = ToInt3(positions[i] * (1 / threshold)); - var c = ToInt3(colors[i].ToVector3() * 10000); - var n = ToInt3(normals[i] * 10000); - - var pcn = new IntegerPositionColorNormal(p, c, n); - - if (d.TryGetValue(pcn, out var index)) - { - indexRemap[i] = index; - continue; - } - - var newVertIndex = vertRemap.Count; - indexRemap[i] = newVertIndex; - vertRemap.Add(i); - - d.Add(pcn, newVertIndex); - } - - Debug.Assert(vertRemap.Count <= g.NumVertices); - for (var i = 1; i < vertRemap.Count; ++i) - Debug.Assert(vertRemap[i - 1] < vertRemap[i]); - - return g.RemapVertices( - vertRemap.ToIArray(), - g.Indices.Select(i => indexRemap[i])) - .ToIMesh(); - } } } From 6f058a6f14c60feff846f4741aa9d810c3aa1e48 Mon Sep 17 00:00:00 2001 From: simon Date: Mon, 1 Apr 2024 14:14:02 -0400 Subject: [PATCH 116/204] removed unused methods --- .../Geometry/MeshExtensions.cs | 254 +----------------- .../Geometry/PerimeterProjection.cs | 59 ---- 2 files changed, 2 insertions(+), 311 deletions(-) diff --git a/src/cs/vim/Vim.Format.Core/Geometry/MeshExtensions.cs b/src/cs/vim/Vim.Format.Core/Geometry/MeshExtensions.cs index 506cb3d3..f9a3610f 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/MeshExtensions.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/MeshExtensions.cs @@ -32,30 +32,9 @@ public static IMesh ToIMesh(this IGeometryAttributes g) => g is IMesh m ? m : g is QuadMesh q ? q.ToIMesh() : g.Attributes.ToIMesh(); #endregion - // Computes the topology: this is a slow O(N) operation - public static Topology ComputeTopology(this IMesh mesh) - => new Topology(mesh); - public static double Area(this IMesh mesh) => mesh.Triangles().Sum(t => t.Area); - #region validation - public static bool IsDegenerateVertexIndices(this Int3 vertexIndices) - => vertexIndices.X == vertexIndices.Y || vertexIndices.X == vertexIndices.Z || vertexIndices.Y == vertexIndices.Z; - - public static bool HasDegenerateFaceVertexIndices(this IMesh self) - => self.AllFaceVertexIndices().Any(IsDegenerateVertexIndices); - #endregion - - // TODO: find a better location for this function. DotNetUtilties doesn't know about IArray unfortunately, so maybe this project needs its own Utility class. - public static DictionaryOfLists GroupBy(this IArray xs, Func groupingFunc) - { - var r = new DictionaryOfLists(); - for (var i = 0; i < xs.Count; ++i) - r.Add(groupingFunc(i), xs[i]); - return r; - } - public static IArray GetFaceMaterials(this IMesh mesh) { // SubmeshIndexOffsets: [0, A, B] @@ -70,15 +49,6 @@ public static IArray GetFaceMaterials(this IMesh mesh) .ToIArray(); } - public static IEnumerable DisctinctMaterials(this IMesh mesh) - => mesh.GetFaceMaterials().ToEnumerable().Distinct(); - - public static DictionaryOfLists IndicesByMaterial(this IMesh mesh) - { - var faceMaterials = mesh.GetFaceMaterials(); - return mesh.Indices.GroupBy(i => faceMaterials[i / 3]); - } - public static IMesh Merge(this IArray meshes) => meshes.Select(m => (IGeometryAttributes)m).Merge().ToIMesh(); @@ -107,7 +77,7 @@ public static IMesh Merge(this IMesh mesh, params IMesh[] others) submeshMaterials.Count <= 1 || submeshIndexOffets.Count <= 1 || submeshIndexCounts.Count <= 1) { // Base case: only one submesh material. - return new [] { (submeshMaterials[0], mesh) }; + return new[] { (submeshMaterials[0], mesh) }; } // Example: @@ -161,7 +131,7 @@ public static IMesh Merge(this IMesh mesh, params IMesh[] others) var newSubmeshIndexOffsets = 0.Repeat(1).ToSubmeshIndexOffsetAttribute(); var newSubmeshMaterials = submeshMaterial.Repeat(1).ToSubmeshMaterialAttribute(); - + return newVertexAttributes .Concat(mesh.NoneAttributes()) .Concat(mesh.WholeGeometryAttributes()) @@ -176,50 +146,12 @@ public static IMesh Merge(this IMesh mesh, params IMesh[] others) return meshes.Select(m => (material, m)); }); } - - public static IGeometryAttributes DeleteUnusedVertices(this IMesh mesh) - { - var tmp = new bool[mesh.Vertices.Count]; - for (var i = 0; i < mesh.Indices.Count; ++i) - tmp[mesh.Indices[i]] = true; - - var remap = new List(); - for (var i = 0; i < tmp.Length; ++i) - { - if (tmp[i]) - remap.Add(i); - } - - return mesh.RemapVertices(remap.ToIArray()); - } - public static bool GeometryEquals(this IMesh mesh, IMesh other, float tolerance = Math3d.Constants.Tolerance) { if (mesh.NumFaces != other.NumFaces) return false; return mesh.Triangles().Zip(other.Triangles(), (t1, t2) => t1.AlmostEquals(t2, tolerance)).All(x => x); } - - public static IMesh SimplePolygonTessellate(this IEnumerable points) - { - var pts = points.ToList(); - var cnt = pts.Count; - var sum = Vector3.Zero; - var idxs = new List(pts.Count * 3); - for (var i = 0; i < pts.Count; ++i) - { - idxs.Add(i); - idxs.Add(i + 1 % cnt); - idxs.Add(cnt); - sum += pts[i]; - } - - var midPoint = sum / pts.Count; - pts.Add(midPoint); - - return Primitives.TriMesh(pts.ToIArray(), idxs.ToIArray()); - } - public static IGeometryAttributes ReverseWindingOrder(this IMesh mesh) { var n = mesh.Indices.Count; @@ -233,125 +165,16 @@ public static IGeometryAttributes ReverseWindingOrder(this IMesh mesh) return mesh.SetAttribute(r.ToIArray().ToIndexAttribute()); } - /// - /// Returns the closest point in a sequence of points - /// - public static Vector3 NearestPoint(this IEnumerable points, Vector3 x) - => points.Minimize(float.MaxValue, p => p.DistanceSquared(x)); - - /// - /// Returns the closest point in a sequence of points - /// - public static Vector3 NearestPoint(this IArray points, Vector3 x) - => points.ToEnumerable().NearestPoint(x); - - /// - /// Returns the closest point in a geometry - /// - public static Vector3 NearestPoint(this IMesh mesh, Vector3 x) - => mesh.Vertices.NearestPoint(x); - - public static Vector3 FurthestPoint(this IMesh mesh, Vector3 x0, Vector3 x1) - => mesh.Vertices.FurthestPoint(x0, x1); - - public static Vector3 FurthestPoint(this IArray points, Vector3 x0, Vector3 x1) - => points.ToEnumerable().FurthestPoint(x0, x1); - - public static Vector3 FurthestPoint(this IEnumerable points, Vector3 x0, Vector3 x1) - => points.Maximize(float.MinValue, v => v.Distance(x0).Min(v.Distance(x1))); - - public static Vector3 FurthestPoint(this IMesh mesh, Vector3 x) - => mesh.Vertices.FurthestPoint(x); - - public static Vector3 FurthestPoint(this IArray points, Vector3 x) - => points.ToEnumerable().FurthestPoint(x); - - public static Vector3 FurthestPoint(this IEnumerable points, Vector3 x) - => points.Maximize(float.MinValue, v => v.Distance(x)); - - public static IGeometryAttributes SnapPoints(this IMesh mesh, float snapSize) - => snapSize.Abs() >= Math3d.Constants.Tolerance - ? mesh.Deform(v => (v * snapSize.Inverse()).Truncate() * snapSize) - : mesh.Deform(v => Vector3.Zero); - - /// - /// Returns the vertices organized by face corner. - /// - public static IArray VerticesByIndex(this IMesh mesh) - => mesh.Vertices.SelectByIndex(mesh.Indices); - - /// - /// Returns the vertices organized by face corner, normalized to the first position. - /// This is useful for detecting if two meshes are the same except offset by - /// position. - /// - public static IArray NormalizedVerticesByCorner(this IMesh m) - { - if (m.NumCorners == 0) - return Vector3.Zero.Repeat(0); - var firstVertex = m.Vertices[m.Indices[0]]; - return m.VerticesByIndex().Select(v => v - firstVertex); - } - - /// - /// Compares the face positions of two meshes normalized by the vertex buffer, returning the maximum distance, or null - /// if the meshes have different topology. - /// - public static float? MaxNormalizedDistance(this IMesh mesh, IMesh other) - { - var xs = mesh.NormalizedVerticesByCorner(); - var ys = other.NormalizedVerticesByCorner(); - if (xs.Count != ys.Count) - return null; - return xs.Zip(ys, (x, y) => x.Distance(y)).Max(); - } public static AABox BoundingBox(this IMesh mesh) => AABox.Create(mesh.Vertices.ToEnumerable()); - public static Sphere BoundingSphere(this IMesh mesh) - => mesh.BoundingBox().ToSphere(); - - public static float BoundingRadius(this IMesh mesh) - => mesh.BoundingSphere().Radius; public static Vector3 Center(this IMesh mesh) => mesh.BoundingBox().Center; - public static Vector3 Centroid(this IMesh mesh) - => mesh.Vertices.Aggregate(Vector3.Zero, (x, y) => x + y) / mesh.Vertices.Count; - - public static bool AreIndicesValid(this IMesh mesh) - => mesh.Indices.All(i => i >= 0 && i < mesh.Vertices.Count); - - public static bool AreAllVerticesUsed(this IMesh mesh) - { - var used = new bool[mesh.Vertices.Count]; - mesh.Indices.ForEach(idx => used[idx] = true); - return used.All(b => b); - } - - public static IMesh ResetPivot(this IMesh mesh) - => mesh.Translate(-mesh.BoundingBox().CenterBottom); - #region Face operations - /// - /// Given an array of face data, creates an array of indexed data to match vertices - /// - public static IArray FaceDataToVertexData(this IMesh mesh, IArray data) - { - if (data.Count != mesh.NumFaces) - throw new Exception("Cannot match input Face data to existing faces"); - - var vertexData = new T[mesh.NumVertices]; - for (var i = 0; i < mesh.Indices.Count; ++i) - vertexData[mesh.Indices[i]] = data[i / 3]; - return vertexData.ToIArray(); - } - - public static IArray AllFaceVertexIndices(this IMesh mesh) - => mesh.NumFaces.Select(mesh.FaceVertexIndices); public static Int3 FaceVertexIndices(this IMesh mesh, int faceIndex) => new Int3(mesh.Indices[faceIndex * 3], mesh.Indices[faceIndex * 3 + 1], mesh.Indices[faceIndex * 3 + 2]); @@ -365,9 +188,6 @@ public static Triangle Triangle(this IMesh mesh, int face) public static IArray Triangles(this IMesh mesh) => mesh.NumFaces.Select(mesh.Triangle); - public static IArray GetAllEdgesAsLines(this IMesh mesh) - => mesh.Triangles().SelectMany(tri => Tuple.Create(tri.AB, tri.BC, tri.CA)); - public static IArray ComputedNormals(this IMesh mesh) => mesh.Triangles().Select(t => t.Normal); @@ -378,76 +198,6 @@ public static bool Planar(this IMesh mesh, float tolerance = Math3d.Constants.To return mesh.ComputedNormals().All(n => n.AlmostEquals(normal, tolerance)); } - public static IArray MidPoints(this IMesh mesh) - => mesh.Triangles().Select(t => t.MidPoint); - - public static IArray FacesToCorners(this IMesh mesh) - => mesh.NumFaces.Select(i => i * 3); - - public static IArray FaceDataToCornerData(this IMesh mesh, IArray data) - => mesh.NumCorners.Select(i => data[i / 3]); - - public static IArray GetOrComputeFaceNormals(this IMesh mesh) - => mesh.GetAttributeFaceNormal()?.Data ?? mesh.ComputedNormals(); - - public static IArray GetOrComputeVertexNormals(this IMesh mesh) - => mesh.VertexNormals ?? mesh.ComputeTopology().GetOrComputeVertexNormals(); - - /// - /// Returns vertex normals if present, otherwise computes vertex normals naively by averaging them. - /// Given a pre-computed topology, will-leverage that. - /// A more sophisticated algorithm would compute the weighted normal - /// based on an angle. - /// - public static IArray GetOrComputeVertexNormals(this Topology topo) - { - var mesh = topo.Mesh; - var r = mesh.VertexNormals; - if (r != null) return r; - var faceNormals = mesh.GetOrComputeFaceNormals().ToArray(); - return mesh - .NumVertices - .Select(vi => - { - var tmp = topo - .FacesFromVertexIndex(vi) - .Select(fi => faceNormals[fi]) - .Average(); - if (tmp.IsNaN()) - return Vector3.Zero; - return tmp.SafeNormalize(); - }); - } - - public static IMesh CopyFaces(this IMesh mesh, Func predicate) - => (mesh as IGeometryAttributes).CopyFaces(predicate).ToIMesh(); - - public static IMesh CopyFaces(this IMesh mesh, IArray keep) - => mesh.CopyFaces(i => keep[i]); - - public static IMesh CopyFaces(this IMesh mesh, IArray keep) - => mesh.RemapFaces(keep).ToIMesh(); - - public static IMesh DeleteFaces(this IMesh mesh, Func predicate) - => mesh.CopyFaces(f => !predicate(f)); #endregion - - #region Corner extensions - /// - /// Given an array of data associated with corners, return an array of data associated with - /// vertices. If a vertex is not referenced, no data is returned. If a vertex is referenced - /// multiple times, the last reference is used. - /// TODO: supplement with a proper interpolation system. - /// - public static IArray CornerDataToVertexData(this IMesh mesh, IArray data) - { - var vertexData = new T[mesh.NumVertices]; - for (var i = 0; i < data.Count; ++i) - vertexData[mesh.Indices[i]] = data[i]; - return vertexData.ToIArray(); - } - #endregion - - } } diff --git a/src/cs/vim/Vim.Format.Core/Geometry/PerimeterProjection.cs b/src/cs/vim/Vim.Format.Core/Geometry/PerimeterProjection.cs index 854e7292..8ea41c6b 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/PerimeterProjection.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/PerimeterProjection.cs @@ -11,65 +11,6 @@ namespace Vim.Format.Geometry { public static class PerimeterProjection { - public static Int2 ToXYApproximation(this Vector3 v, float tolerance) - => new Int2((int)(v.X / tolerance), (int)(v.Y / tolerance)); - - public static Vector2 FromXYApproximation(this Int2 v, float tolerance) - => new Vector2(v.X * tolerance, v.Y * tolerance); - - public static LineApprox ToXYApproximation(this Line line, float tolerance) - => Tuple.Create(line.A.ToXYApproximation(tolerance), line.B.ToXYApproximation(tolerance)); - - public static double Angle(this Int2 v) - => Math.Atan2(v.Y, v.X); - - public static double Angle(this Int2 a, Int2 b) - => (a - b).Angle(); - - public static IEnumerable PerimeterXY(this IMesh mesh, float tolerance = 0.001f) - { - var srcLines = mesh.GetAllEdgesAsLines(); - var approxLines = srcLines.Select(line => line.ToXYApproximation(tolerance)); - var lineSet = new HashSet(approxLines.ToArrayInParallel()); - Debug.WriteLine($"Went from {srcLines.Count} to {lineSet.Count}"); - var d = new DictionaryOfLists(); - foreach (var ab in lineSet) - { - d.Add(ab.Item1, ab); - d.Add(ab.Item2, ab); - } - var r = new List(); - if (d.Count == 0) - return r; - - var firstKey = d.Keys.Minimize(int.MaxValue, ab => ab.X.Min(ab.Y)); - var currentKey = firstKey; - var prevAngle = 0.0; - - // If we can't find the point in the dictionary we have completed - while (d.ContainsKey(currentKey)) - { - // Find the candidate points; - var candidates = d[currentKey].Select(line => line.Item1 == currentKey ? line.Item2 : line.Item1); - - // Find the best match by maximizing angle - var bestMatch = candidates.Maximize(0.0, c => currentKey.Angle(c) - prevAngle); - - // Update the return set - r.Add(bestMatch.FromXYApproximation(tolerance)); - - // Now save the angle for the next stage. - prevAngle = currentKey.Angle(bestMatch); - - // Remove this key from the dictionary - d.Remove(currentKey); - - // Now we are at a new point - currentKey = bestMatch; - } - - return r; - } public static List> GeneratePerimeter(this IMesh mesh, Vector3 planeNormal, float degenerateSegmentEpsilon = 10.0f, float edgeLoopThreshold = 1e-6f) { From 63dc31e406bbdb9d38a81e6b46bea55956c4e235 Mon Sep 17 00:00:00 2001 From: simon Date: Mon, 1 Apr 2024 15:36:06 -0400 Subject: [PATCH 117/204] Created IMeshCommon interface that respond to most of IMesh --- src/cs/g3d/Vim.G3dNext/G3dChunk.cs | 58 ---------- src/cs/g3d/Vim.G3dNext/G3dVim.cs | 41 ------- src/cs/vim/Vim.Format.Core/Geometry/IMesh.cs | 21 +++- .../Geometry/PerimeterProjection.cs | 1 - .../vim/Vim.Format.Core/Geometry/VimMesh.cs | 101 ++++++++++++++++++ .../SerializableDocumentTests.cs | 10 +- .../vim/Vim.Format/SceneBuilder/VimScene.cs | 4 +- 7 files changed, 126 insertions(+), 110 deletions(-) create mode 100644 src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs diff --git a/src/cs/g3d/Vim.G3dNext/G3dChunk.cs b/src/cs/g3d/Vim.G3dNext/G3dChunk.cs index b445ba11..b89414dd 100644 --- a/src/cs/g3d/Vim.G3dNext/G3dChunk.cs +++ b/src/cs/g3d/Vim.G3dNext/G3dChunk.cs @@ -4,28 +4,6 @@ namespace Vim.G3dNext { - public class VimMesh : ITransformable3D - { - public int[] indices; - public Vector3[] vertices; - public int[] submeshes; - public int[] submeshMaterials; - - public VimMesh Transform(Matrix4x4 mat) - { - var mesh = new VimMesh(); - mesh.indices = indices.ToArray(); - mesh.vertices = new Vector3[vertices.Length]; - mesh.submeshes = submeshes.ToArray(); - mesh.submeshMaterials = submeshMaterials.ToArray(); - - for(var i =0; i < vertices.Length;i++ ) - { - mesh.vertices[i] = vertices[i].Transform(mat); - } - return mesh; - } - } public partial class G3dChunk @@ -35,42 +13,6 @@ void ISetup.Setup() // empty } - public VimMesh GetMesh(int index) - { - var mesh = new VimMesh(); - - var vStart = GetMeshVertexStart(index, MeshSection.All); - var vEnd = GetMeshVertexEnd(index, MeshSection.All); - mesh.vertices = new Vector3[vEnd - vStart]; - for (var i = 0; i < mesh.vertices.Length; i++) - { - var v = vStart + i; - mesh.vertices[i] = Positions[v]; - } - - var iStart = GetMeshIndexStart(index, MeshSection.All); - var iEnd = GetMeshIndexEnd(index, MeshSection.All); - mesh.indices = new int[iEnd - iStart]; - for (var i = 0; i < mesh.indices.Length; i++) - { - var j = iStart + i; - mesh.indices[i] = Indices[j] - vStart; - } - - var sStart = GetMeshSubmeshStart(index, MeshSection.All); - var sEnd = GetMeshSubmeshEnd(index, MeshSection.All); - mesh.submeshes = new int[sEnd - sStart]; - mesh.submeshMaterials = new int[sEnd - sStart]; - - for (var i =0; i < mesh.submeshMaterials.Length; i++) - { - var s = sStart + i; - mesh.submeshes[i] = SubmeshIndexOffsets[s] - vStart; - mesh.submeshMaterials[i] = SubmeshMaterials[s]; - } - - return mesh; - } public int GetSubmeshCount() => SubmeshIndexOffsets?.Length ?? 0; diff --git a/src/cs/g3d/Vim.G3dNext/G3dVim.cs b/src/cs/g3d/Vim.G3dNext/G3dVim.cs index 0801564d..c0ddeb67 100644 --- a/src/cs/g3d/Vim.G3dNext/G3dVim.cs +++ b/src/cs/g3d/Vim.G3dNext/G3dVim.cs @@ -13,47 +13,6 @@ public partial class G3dVim private List[] _meshInstances; - public VimMesh GetMesh(int index) - { - var mesh = new VimMesh(); - - var vStart = GetMeshVertexStart(index); - var vEnd = GetMeshVertexEnd(index); - mesh.vertices = new Vector3[vEnd - vStart]; - for (var i = 0; i < mesh.vertices.Length; i++) - { - var v = vStart + i; - mesh.vertices[i] = Positions[v]; - } - - var iStart = GetMeshIndexStart(index); - var iEnd = GetMeshIndexEnd(index); - mesh.indices = new int[iEnd - iStart]; - for (var i = 0; i < mesh.indices.Length; i++) - { - var j = iStart + i; - mesh.indices[i] = Indices[j] - vStart; - } - - var sStart = GetMeshSubmeshStart(index); - var sEnd = GetMeshSubmeshEnd(index); - mesh.submeshes = new int[sEnd - sStart]; - mesh.submeshMaterials = new int[sEnd - sStart]; - - for (var i = 0; i < mesh.submeshMaterials.Length; i++) - { - var s = sStart + i; - mesh.submeshes[i] = SubmeshIndexOffsets[s] - iStart; - mesh.submeshMaterials[i] = SubmeshMaterials[s]; - } - - return mesh; - } - - public IEnumerable GetAllMeshes() - { - return Enumerable.Range(0, GetMeshCount()).Select(i => GetMesh(i)); - } public IReadOnlyList GetMeshInstances(int mesh) { diff --git a/src/cs/vim/Vim.Format.Core/Geometry/IMesh.cs b/src/cs/vim/Vim.Format.Core/Geometry/IMesh.cs index f330d0e4..42865e0c 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/IMesh.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/IMesh.cs @@ -13,12 +13,27 @@ public interface IMesh : { IArray Vertices { get; } IArray Indices { get; } - IArray VertexColors { get; } - IArray VertexNormals { get; } - IArray VertexUvs { get; } IArray SubmeshMaterials { get; } IArray SubmeshIndexOffsets { get; } IArray SubmeshIndexCount { get; } } + + public interface IMeshCommon : ITransformable3D + { + IArray Vertices { get; } + IArray Indices { get; } + + IArray SubmeshMaterials { get; } + IArray SubmeshIndexOffsets { get; } + IArray SubmeshIndexCount { get; } + int NumCornersPerFace { get; } + int NumVertices { get; } + int NumCorners { get; } + int NumFaces { get; } + int NumInstances { get; } + int NumMeshes { get; } + int NumShapeVertices { get; } + int NumShapes { get; } + } } diff --git a/src/cs/vim/Vim.Format.Core/Geometry/PerimeterProjection.cs b/src/cs/vim/Vim.Format.Core/Geometry/PerimeterProjection.cs index 8ea41c6b..9d249161 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/PerimeterProjection.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/PerimeterProjection.cs @@ -5,7 +5,6 @@ using Vim.Util; using Vim.LinqArray; using Vim.Math3d; -using LineApprox = System.Tuple; namespace Vim.Format.Geometry { diff --git a/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs b/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs new file mode 100644 index 00000000..0c172db6 --- /dev/null +++ b/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs @@ -0,0 +1,101 @@ +using System.Collections.Generic; +using System.Linq; +using Vim.G3d; +using Vim.G3dNext; +using Vim.LinqArray; +using Vim.Math3d; + +namespace Vim.Format.Geometry +{ + public class VimMesh : IMeshCommon + { + public IArray Vertices => vertices.ToIArray(); + + public IArray Indices => indices.ToIArray(); + + public IArray SubmeshMaterials =>submeshMaterials.ToIArray(); + public IArray SubmeshIndexOffsets => submeshes.ToIArray(); + public IArray SubmeshIndexCount => submeshSizes.ToIArray(); + + public int NumCornersPerFace => 3; + + public int NumVertices => vertices.Length; + + public int NumCorners => indices.Length; + + public int NumFaces => indices.Length / 3; + + public int NumInstances => 0; + + public int NumMeshes => 1; + + public int NumShapeVertices => 0; + + public int NumShapes => 0; + + public int[] indices; + public Vector3[] vertices; + public int[] submeshes; + public int[] submeshMaterials; + public int[] submeshSizes; + + public IMeshCommon Transform(Matrix4x4 mat) + { + var mesh = new VimMesh(); + mesh.indices = indices.ToArray(); + mesh.vertices = new Vector3[vertices.Length]; + mesh.submeshes = submeshes.ToArray(); + mesh.submeshMaterials = submeshMaterials.ToArray(); + + for (var i = 0; i < vertices.Length; i++) + { + mesh.vertices[i] = vertices[i].Transform(mat); + } + return mesh; + } + + public static VimMesh FromG3d(G3dVim g3d, int index) + { + var mesh = new VimMesh(); + + var vStart = g3d.GetMeshVertexStart(index); + var vEnd = g3d.GetMeshVertexEnd(index); + mesh.vertices = new Vector3[vEnd - vStart]; + for (var i = 0; i < mesh.vertices.Length; i++) + { + var v = vStart + i; + mesh.vertices[i] = g3d.Positions[v]; + } + + var iStart = g3d.GetMeshIndexStart(index); + var iEnd = g3d.GetMeshIndexEnd(index); + mesh.indices = new int[iEnd - iStart]; + for (var i = 0; i < mesh.indices.Length; i++) + { + var j = iStart + i; + mesh.indices[i] = g3d.Indices[j] - vStart; + } + + var sStart = g3d.GetMeshSubmeshStart(index); + var sEnd = g3d.GetMeshSubmeshEnd(index); + mesh.submeshes = new int[sEnd - sStart]; + mesh.submeshMaterials = new int[sEnd - sStart]; + mesh.submeshSizes = new int[sEnd - sStart]; + + for (var i = 0; i < mesh.submeshMaterials.Length; i++) + { + var s = sStart + i; + mesh.submeshes[i] = g3d.SubmeshIndexOffsets[s] - iStart; + mesh.submeshMaterials[i] = g3d.SubmeshMaterials[s]; + mesh.submeshSizes[i] = g3d.GetSubmeshIndexCount(s); + } + + return mesh; + } + + public static IEnumerable GetAllMeshes(G3dVim g3d) + { + return Enumerable.Range(0, g3d.GetMeshCount()).Select(i => FromG3d(g3d, i)); + } + } +} diff --git a/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs b/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs index 2f2eeec8..9e9ea552 100644 --- a/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs +++ b/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs @@ -70,13 +70,13 @@ public static void GetMesh_Transform_IsSame() } } - private static void MeshesAreSame(IMesh mesh, VimMesh next) + private static void MeshesAreSame(IMesh mesh, IMeshCommon next) { - Assert.That(mesh.Indices.SequenceEquals(next.indices.ToIArray())); - Assert.That(mesh.Vertices.SequenceEquals(next.vertices.ToIArray())); - Assert.That(mesh.SubmeshIndexOffsets.SequenceEquals(next.submeshes.ToIArray())); - Assert.That(mesh.SubmeshMaterials.SequenceEquals(next.submeshMaterials.ToIArray())); + Assert.That(mesh.Indices.SequenceEquals(next.Indices)); + Assert.That(mesh.Vertices.SequenceEquals(next.Vertices)); + Assert.That(mesh.SubmeshIndexOffsets.SequenceEquals(next.SubmeshIndexOffsets)); + Assert.That(mesh.SubmeshMaterials.SequenceEquals(next.SubmeshMaterials)); } } diff --git a/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs b/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs index ce3e7c51..aa63dcc2 100644 --- a/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs +++ b/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs @@ -60,7 +60,7 @@ public static VimScene LoadVim(Stream stream, IVimSceneProgress progress = null, public int VimIndex { get; set; } public IArray Meshes { get; private set; } - public VimMesh[] MeshesNext { get; private set; } + public IMeshCommon[] MeshesNext { get; private set; } public IArray Nodes { get; private set; } public IArray VimNodes { get; private set; } public IArray VimShapes { get; private set; } @@ -205,7 +205,7 @@ private void CreateMeshes(bool inParallel) : inParallel ? tmp.EvaluateInParallel() : tmp.Evaluate(); - MeshesNext = _SerializableDocument.GeometryNext.GetAllMeshes().ToArray(); + MeshesNext = VimMesh.GetAllMeshes(_SerializableDocument.GeometryNext).ToArray(); } private void CreateShapes(bool inParallel) From de587da8ac70fe4606990723a020ce3b64b8b7cc Mon Sep 17 00:00:00 2001 From: simon Date: Thu, 4 Apr 2024 15:18:58 -0400 Subject: [PATCH 118/204] removed unused method --- src/cs/vim/Vim.Format.Core/Geometry/MeshExtensions.cs | 3 --- src/cs/vim/Vim.Format.Tests/Geometry/GeometryTests.cs | 2 -- 2 files changed, 5 deletions(-) diff --git a/src/cs/vim/Vim.Format.Core/Geometry/MeshExtensions.cs b/src/cs/vim/Vim.Format.Core/Geometry/MeshExtensions.cs index f9a3610f..deacbe26 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/MeshExtensions.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/MeshExtensions.cs @@ -32,9 +32,6 @@ public static IMesh ToIMesh(this IGeometryAttributes g) => g is IMesh m ? m : g is QuadMesh q ? q.ToIMesh() : g.Attributes.ToIMesh(); #endregion - public static double Area(this IMesh mesh) - => mesh.Triangles().Sum(t => t.Area); - public static IArray GetFaceMaterials(this IMesh mesh) { // SubmeshIndexOffsets: [0, A, B] diff --git a/src/cs/vim/Vim.Format.Tests/Geometry/GeometryTests.cs b/src/cs/vim/Vim.Format.Tests/Geometry/GeometryTests.cs index 62cdac6f..5eb5ea40 100644 --- a/src/cs/vim/Vim.Format.Tests/Geometry/GeometryTests.cs +++ b/src/cs/vim/Vim.Format.Tests/Geometry/GeometryTests.cs @@ -130,7 +130,6 @@ public static void BasicTests() Assert.AreEqual(3, XYTriangle.Vertices.Count); Assert.AreEqual(3, XYTriangle.Indices.Count); Assert.AreEqual(1, XYTriangle.Triangles().Count); - Assert.AreEqual(0.5, XYTriangle.Area(), SmallTolerance); Assert.IsTrue(XYTriangle.Planar()); Assert.AreEqual(new[] { 0, 1, 2 }, XYTriangle.Indices.ToArray()); @@ -163,7 +162,6 @@ public static void BasicTests() Assert.AreEqual(6, XYTriangleTwice.Vertices.Count); Assert.AreEqual(6, XYTriangleTwice.Indices.Count); Assert.AreEqual(2, XYTriangleTwice.Triangles().Count); - Assert.AreEqual(1.0, XYTriangleTwice.Area(), SmallTolerance); Assert.IsTrue(XYTriangleTwice.Planar()); Assert.AreEqual(new[] { 0, 1, 2, 3, 4, 5 }, XYTriangleTwice.Indices.ToArray()); } From 95d16490a3632e09f1f8f9c41cbda06af776dafc Mon Sep 17 00:00:00 2001 From: simon Date: Thu, 4 Apr 2024 15:20:46 -0400 Subject: [PATCH 119/204] Added IMeshCommon as an intermediate step to removing g3d Implemented chunky IMesh methods in IMeshCommon --- src/cs/g3d/Vim.G3d/G3dMesh.cs | 102 ++++++-- src/cs/vim/Vim.Format.Core/Geometry/IMesh.cs | 17 -- .../vim/Vim.Format.Core/Geometry/VimMesh.cs | 226 ++++++++++++++-- .../SerializableDocumentTests.cs | 244 +++++++++++++++++- .../vim/Vim.Format/SceneBuilder/VimScene.cs | 8 +- 5 files changed, 531 insertions(+), 66 deletions(-) diff --git a/src/cs/g3d/Vim.G3d/G3dMesh.cs b/src/cs/g3d/Vim.G3d/G3dMesh.cs index 689122c5..837ac11f 100644 --- a/src/cs/g3d/Vim.G3d/G3dMesh.cs +++ b/src/cs/g3d/Vim.G3d/G3dMesh.cs @@ -5,11 +5,39 @@ namespace Vim.G3d { + + public interface IMeshCommon : ITransformable3D + { + IMeshCommon Clone(); + void SetVertices(Vector3[] vertices); + void SetIndices(int[] indices); + + // To be compatible with IMesh + IArray Vertices { get; } + IArray Indices { get; } + + IArray SubmeshMaterials { get; } + IArray SubmeshIndexOffsets { get; } + IArray SubmeshIndexCounts { get; } + + + + // To be compatible with IGeometryAttributes + int NumCornersPerFace { get; } + int NumVertices { get; } + int NumCorners { get; } + int NumFaces { get; } + int NumInstances { get; } + int NumMeshes { get; } + int NumShapeVertices { get; } + int NumShapes { get; } + } + /// /// A G3dMesh is a section of the G3D data that defines a mesh. /// This does not implement IGeometryAttributes for performance reasons. /// - public class G3dMesh + public class G3dMesh : IMeshCommon { public G3D G3D { get; } public int Index { get; } @@ -22,18 +50,28 @@ public class G3dMesh public int NumFaces => NumCorners / NumCornersPerFace; public int NumCornersPerFace => G3D.NumCornersPerFace; + + // Fillers to fullfil IGeometryAttributes for now + public int NumInstances => 0; + public int NumMeshes => 1; + public int NumShapeVertices => 0; + public int NumShapes => 0; + + // Data + public IArray Vertices { get; private set; } + public IArray Indices { get; private set; } + public IArray SubmeshMaterials { get; private set; } + public IArray SubmeshIndexOffsets { get; private set; } + public IArray SubmeshIndexCounts { get; private set; } + + public G3dMesh(G3D parent, int index) { (G3D, Index) = (parent, index); Vertices = G3D.Vertices?.SubArray(VertexOffset, NumVertices); var offset = VertexOffset; Indices = G3D.Indices?.SubArray(IndexOffset, NumCorners).Select(i => i - offset); - VertexUvs = G3D.VertexUvs?.SubArray(VertexOffset, NumVertices); - VertexNormals = G3D.VertexNormals?.SubArray(VertexOffset, NumVertices); - VertexColors = G3D.VertexColors?.SubArray(VertexOffset, NumVertices); - VertexTangents = G3D.VertexTangents?.SubArray(VertexOffset, NumVertices); - FaceNormals = G3D.FaceNormals?.SubArray(FaceOffset, NumFaces); - + // TODO: Remove need for this. var submeshArray = (G3D.SubmeshIndexOffsets as ArrayAdapter).Array; var submeshIndex = Array.BinarySearch(submeshArray, IndexOffset); @@ -45,28 +83,38 @@ public G3dMesh(G3D parent, int index) break; submeshCount++; } - SubmeshMaterials = G3D.SubmeshMaterials?.SubArray(submeshIndex, submeshCount); - SubmeshIndexOffsets = G3D.SubmeshIndexOffsets?.SubArray(submeshIndex, submeshCount).Select(i => i-IndexOffset); - MeshSubmeshOffset = new List() {0}.ToIArray(); + SubmeshMaterials = G3D.SubmeshMaterials?.SubArray(submeshIndex, submeshCount).Evaluate(); + SubmeshIndexOffsets = G3D.SubmeshIndexOffsets?.SubArray(submeshIndex, submeshCount).Select(i => i - IndexOffset).Evaluate(); + + var last = NumCorners - SubmeshIndexOffsets.Last(); + SubmeshIndexCounts = SubmeshIndexOffsets.AdjacentDifferences().Append(last).Evaluate(); } - // Vertex buffer. Usually present. - public IArray Vertices { get; } - - // Index buffer (one index per corner, and per half-edge) - public IArray Indices { get; } - - // Vertex associated data - public IArray VertexUvs { get; } - public IArray VertexNormals { get; } - public IArray VertexColors { get; } - public IArray VertexTangents { get; } - - // Face associated data. - public IArray FaceNormals { get; } + public IMeshCommon Transform(Matrix4x4 mat) + { + var mesh = Clone(); + mesh.Vertices = mesh.Vertices.Select(v => v.Transform(mat)).Evaluate(); + return mesh; + } - public IArray SubmeshMaterials { get; } - public IArray SubmeshIndexOffsets { get; } - public IArray MeshSubmeshOffset { get; } + public G3dMesh Clone() + { + var mesh = new G3dMesh(G3D, Index); + mesh.Vertices = mesh.Vertices; + mesh.Indices = mesh.Indices; + mesh.SubmeshMaterials = mesh.SubmeshMaterials; + mesh.SubmeshIndexOffsets = mesh.SubmeshIndexOffsets; + mesh.SubmeshIndexCounts = mesh.SubmeshIndexCounts; + return mesh; + } + IMeshCommon IMeshCommon.Clone() => Clone(); + public void SetVertices(Vector3[] vertices) + { + Vertices = vertices.ToIArray(); + } + public void SetIndices(int[] indices) + { + Indices = indices.ToIArray(); + } } } diff --git a/src/cs/vim/Vim.Format.Core/Geometry/IMesh.cs b/src/cs/vim/Vim.Format.Core/Geometry/IMesh.cs index 42865e0c..4e98afd8 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/IMesh.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/IMesh.cs @@ -19,21 +19,4 @@ public interface IMesh : IArray SubmeshIndexCount { get; } } - public interface IMeshCommon : ITransformable3D - { - IArray Vertices { get; } - IArray Indices { get; } - - IArray SubmeshMaterials { get; } - IArray SubmeshIndexOffsets { get; } - IArray SubmeshIndexCount { get; } - int NumCornersPerFace { get; } - int NumVertices { get; } - int NumCorners { get; } - int NumFaces { get; } - int NumInstances { get; } - int NumMeshes { get; } - int NumShapeVertices { get; } - int NumShapes { get; } - } } diff --git a/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs b/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs index 0c172db6..47fbdfb9 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs @@ -1,9 +1,12 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Linq; using Vim.G3d; using Vim.G3dNext; using Vim.LinqArray; using Vim.Math3d; +using Vim.Util; +using static Vim.Format.DocumentBuilder; namespace Vim.Format.Geometry { @@ -13,9 +16,9 @@ public class VimMesh : IMeshCommon public IArray Indices => indices.ToIArray(); - public IArray SubmeshMaterials =>submeshMaterials.ToIArray(); - public IArray SubmeshIndexOffsets => submeshes.ToIArray(); - public IArray SubmeshIndexCount => submeshSizes.ToIArray(); + public IArray SubmeshMaterials => submeshMaterials.ToIArray(); + public IArray SubmeshIndexOffsets => submeshIndexOffsets.ToIArray(); + public IArray SubmeshIndexCounts => submeshIndexCounts.ToIArray(); public int NumCornersPerFace => 3; @@ -35,22 +38,44 @@ public class VimMesh : IMeshCommon public int[] indices; public Vector3[] vertices; - public int[] submeshes; + public int[] submeshIndexOffsets; public int[] submeshMaterials; - public int[] submeshSizes; + public int[] submeshIndexCounts; - public IMeshCommon Transform(Matrix4x4 mat) + public VimMesh() + { + + } + public VimMesh(int indexCount, int vertexCount, int submeshCount) + { + indices = new int[indexCount]; + vertices = new Vector3[vertexCount]; + submeshIndexOffsets = new int[submeshCount]; + submeshMaterials = new int[submeshCount]; + submeshIndexCounts = new int[submeshCount]; + } + + public VimMesh Clone() { var mesh = new VimMesh(); - mesh.indices = indices.ToArray(); - mesh.vertices = new Vector3[vertices.Length]; - mesh.submeshes = submeshes.ToArray(); - mesh.submeshMaterials = submeshMaterials.ToArray(); + mesh.indices = indices; + mesh.vertices = vertices; + mesh.submeshIndexOffsets = submeshIndexOffsets; + mesh.submeshMaterials = submeshMaterials; + mesh.submeshIndexCounts = submeshIndexCounts; + return mesh; + } + IMeshCommon IMeshCommon.Clone() => Clone(); + + public IMeshCommon Transform(Matrix4x4 mat) + { + var mesh = Clone(); for (var i = 0; i < vertices.Length; i++) { mesh.vertices[i] = vertices[i].Transform(mat); } + return mesh; } @@ -78,16 +103,16 @@ public static VimMesh FromG3d(G3dVim g3d, int index) var sStart = g3d.GetMeshSubmeshStart(index); var sEnd = g3d.GetMeshSubmeshEnd(index); - mesh.submeshes = new int[sEnd - sStart]; + mesh.submeshIndexOffsets = new int[sEnd - sStart]; mesh.submeshMaterials = new int[sEnd - sStart]; - mesh.submeshSizes = new int[sEnd - sStart]; + mesh.submeshIndexCounts = new int[sEnd - sStart]; for (var i = 0; i < mesh.submeshMaterials.Length; i++) { var s = sStart + i; - mesh.submeshes[i] = g3d.SubmeshIndexOffsets[s] - iStart; + mesh.submeshIndexOffsets[i] = g3d.SubmeshIndexOffsets[s] - iStart; mesh.submeshMaterials[i] = g3d.SubmeshMaterials[s]; - mesh.submeshSizes[i] = g3d.GetSubmeshIndexCount(s); + mesh.submeshIndexCounts[i] = g3d.GetSubmeshIndexCount(s); } return mesh; @@ -97,5 +122,176 @@ public static IEnumerable GetAllMeshes(G3dVim g3d) { return Enumerable.Range(0, g3d.GetMeshCount()).Select(i => FromG3d(g3d, i)); } + + public void SetVertices(Vector3[] vertices) + { + this.vertices = vertices; + } + public void SetIndices(int[] indices) + { + this.indices = indices; + } + } + + public static class MeshCommonExtensions + { + public static IMeshCommon ReverseWindingOrder(this IMeshCommon mesh) + { + var result = mesh.Clone(); + var count = mesh.Indices.Count; + var indices = new int[count]; + for (var i = 0; i < count; i += 3) + { + indices[i + 0] = mesh.Indices[i + 2]; + indices[i + 1] = mesh.Indices[i + 1]; + indices[i + 2] = mesh.Indices[i + 0]; + } + result.SetIndices(indices); + return result; + } + + + public static IArray GetFaceMaterials(this IMeshCommon mesh) + { + // SubmeshIndexOffsets: [0, A, B] + // SubmeshIndexCount: [X, Y, Z] + // SubmeshMaterials: [L, M, N] + // --- + // FaceMaterials: [...Repeat(L, X / 3), ...Repeat(M, Y / 3), ...Repeat(N, Z / 3)] <-- divide by 3 for the number of corners per Triangular face + var numCornersPerFace = mesh.NumCornersPerFace; + return mesh.SubmeshIndexCounts + .ToEnumerable() + .SelectMany((indexCount, i) => Enumerable.Repeat(mesh.SubmeshMaterials[i], indexCount / numCornersPerFace)) + .ToIArray(); + } + + public static IMeshCommon Merge2(this IMeshCommon mesh, params IMeshCommon[] others) + { + var meshes = Enumerable.Empty() + .Append(mesh) + .Append(others) + .ToArray(); + + return meshes.Merge(); + } + + public static IMeshCommon Merge(this IMeshCommon[] meshes) + { + void Merge(IArray from, int[] to, int offset, int increment) + { + for (var i = 0; i < from.Count; i++) + { + to[i + offset] = from[i] + increment; + } + } + + // Init arrays + var indexCount = meshes.Sum(m => m.Indices.Count); + var vertexCount = meshes.Sum(m => m.Vertices.Count); + var submeshCount = meshes.Sum(m => m.SubmeshIndexOffsets.Count); + var result = new VimMesh(indexCount, vertexCount, submeshCount); + + var indexOffset = 0; + var vertexOffset = 0; + var submeshOffset = 0; + // Copy and merge meshes + for (var m = 0; m < meshes.Length; m++) + { + var mesh = meshes[m]; + + Merge(mesh.Indices, result.indices, indexOffset, vertexOffset); + mesh.Vertices.CopyTo(result.vertices, vertexOffset); + mesh.SubmeshMaterials.CopyTo(result.submeshMaterials, submeshOffset); + mesh.SubmeshIndexCounts.CopyTo(result.submeshIndexCounts, submeshOffset); + Merge(mesh.SubmeshIndexOffsets, result.submeshIndexOffsets, submeshOffset, indexOffset); + + indexOffset += mesh.Indices.Count; + vertexOffset += mesh.Vertices.Count; + submeshOffset += mesh.SubmeshIndexOffsets.Count; + + } + return result; + } + + public static VimMesh[] SplitSubmeshes(this IMeshCommon mesh) + { + return null; + } + + public static (int, List)[] GroupSubmeshesByMaterials(this IMeshCommon mesh) + { + var submeshCount = mesh.SubmeshIndexOffsets.Count; + var map = new Dictionary>(); + for (var i = 0; i < submeshCount; i++) + { + var mat = mesh.SubmeshMaterials[i]; + if (map.ContainsKey(mat)) + { + map[mat].Add(i); + } + else + { + map.Add(mat, new List() { i }); + } + } + return map.Select(kvp => (kvp.Key, kvp.Value)).ToArray(); + } + + + public static (int mat, IMeshCommon mesh)[] SplitByMaterial(this IMeshCommon mesh) + { + var map = mesh.GroupSubmeshesByMaterials(); + + var result = new (int, IMeshCommon)[map.Length]; + if (map.Length == 1) + { + result[0] = (mesh.SubmeshMaterials[0], mesh); + return result; + } + + for (var i =0; i < map.Length; i++) + { + var (mat, subs) = map[i]; + var pick = mesh.PickSubmeshes(subs); + result[i] = (mat, pick); + } + return result; + } + + public static VimMesh PickSubmeshes(this IMeshCommon mesh, IList submeshes) + { + var map = mesh.GroupSubmeshesByMaterials(); + + // Allocate arrays of the final sizes + var indexCount = submeshes.Sum(s => mesh.SubmeshIndexCounts[s]); + var result = new VimMesh(indexCount, indexCount, submeshes.Count); + + var indexOffset = 0; + var index = 0; + for (var s = 0; s < submeshes.Count; s++) + { + var submesh = submeshes[s]; + + // copy indices at their new positions + var indexStart = mesh.SubmeshIndexOffsets[submesh]; + var indexEnd = indexStart + mesh.SubmeshIndexCounts[submesh]; + for (var i = indexStart; i < indexEnd; i++) + { + result.indices[index] = indexOffset + i - indexStart; + result.vertices[index] = mesh.Vertices[mesh.Indices[i]]; + index++; + } + + // submesh data is mostly the same + result.submeshIndexCounts[s] = mesh.SubmeshIndexCounts[submesh]; + result.submeshMaterials[s] = mesh.SubmeshMaterials[submesh]; + result.submeshIndexOffsets[s] = indexOffset; + + // Update offset for next submesh + indexOffset += indexEnd - indexStart; + } + + return result; + } } } diff --git a/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs b/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs index 9e9ea552..2ff6240a 100644 --- a/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs +++ b/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs @@ -5,6 +5,13 @@ using Vim.Format.Geometry; using Vim.LinqArray; using Vim.Math3d; +using Vim.G3d; +using System.Linq; +using System.Diagnostics; +using System; +using Newtonsoft.Json.Linq; +using static System.Net.Mime.MediaTypeNames; +using static Vim.Format.DocumentBuilder; namespace Vim.Format.Tests; @@ -33,9 +40,9 @@ public static void MaterialColor_IsSame() { var path = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); var scene = VimScene.LoadVim(path); - for(var i=0; i < scene.GetMaterialCount(); i++) + for (var i = 0; i < scene.GetMaterialCount(); i++) { - Assert.AreEqual(scene.GetMaterialColor(i),scene.GetMaterialColorNext(i)); + Assert.AreEqual(scene.GetMaterialColor(i), scene.GetMaterialColorNext(i)); } } @@ -48,7 +55,9 @@ public static void GetMesh_IsSameMesh() { var mesh = scene.Meshes[i]; var next = scene.MeshesNext[i]; + var raw = scene.MeshesRaw[i]; MeshesAreSame(mesh, next); + MeshesAreSame(mesh, raw); } } @@ -66,17 +75,246 @@ public static void GetMesh_Transform_IsSame() ); var mesh = scene.Meshes[i].Transform(mat); var next = scene.MeshesNext[i].Transform(mat); + var raw = scene.MeshesRaw[i].Transform(mat); MeshesAreSame(mesh, next); + MeshesAreSame(mesh, raw); } } - private static void MeshesAreSame(IMesh mesh, IMeshCommon next) + [Test] + public static void ReverseWindingOrder_IsSame() + { + var path = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); + var scene = VimScene.LoadVim(path); + for (var i = 0; i < scene.GetMeshCount(); i++) + { + + var mesh = scene.Meshes[i].ReverseWindingOrder().ToIMesh(); + var next = scene.MeshesNext[i].ReverseWindingOrder(); + var raw = scene.MeshesRaw[i].ReverseWindingOrder(); + MeshesAreSame(mesh, next); + MeshesAreSame(mesh, raw); + } + } + + [Test] + public static void FaceMaterial_IsSame() + { + var path = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); + var scene = VimScene.LoadVim(path); + for (var i = 0; i < scene.GetMeshCount(); i++) + { + var mesh = scene.Meshes[i].GetFaceMaterials(); + var next = scene.MeshesNext[i].GetFaceMaterials(); + var raw = scene.MeshesRaw[i].GetFaceMaterials(); + Assert.That(mesh.SequenceEquals(next)); + Assert.That(next.SequenceEquals(raw)); + } + } + + [Test] + public static void Merge_ByPair_IsSame() + { + var path = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); + var scene = VimScene.LoadVim(path); + for (var i = 1; i < scene.GetMeshCount(); i++) + { + var mesh = scene.Meshes[i].Merge(scene.Meshes[i - 1]); + var next = scene.MeshesNext[i].Merge2(scene.MeshesNext[i - 1]); + var raw = scene.MeshesRaw[i].Merge2(scene.MeshesRaw[i - 1]); + MeshesAreSame(mesh, next); + MeshesAreSame(mesh, raw); + } + } + + [Test] + public static void Merge_All_IsSame() + { + var path = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); + var scene = VimScene.LoadVim(path); + + var mesh = scene.Meshes[0].Merge(scene.Meshes.Skip(1).ToArray()); + var next = scene.MeshesNext[0].Merge2(scene.MeshesNext.Skip(1).ToArray()); + var raw = scene.MeshesRaw[0].Merge2(scene.MeshesRaw.Skip(1).ToArray()); + MeshesAreSame(mesh, next); + MeshesAreSame(mesh, raw); + } + + [Test] + public static void SplitByMaterials_IsSame() + { + var path = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); + var scene = VimScene.LoadVim(path); + for (var i = 0; i < scene.GetMeshCount(); i++) + { + var mesh = scene.Meshes[i].SplitByMaterial().ToArray(); + var next = scene.MeshesNext[i].SplitByMaterial(); + var raw = scene.MeshesRaw[i].SplitByMaterial(); + Assert.AreEqual(mesh.Length, next.Length); + Assert.AreEqual(mesh.Length, raw.Length); + + for (var j = 0; j < mesh.Length; j++) + { + MeshesAreSame(mesh[j].Mesh, next[j].mesh); + MeshesAreSame(mesh[j].Mesh, raw[j].mesh); + } + } + } + + + [Test] + public static void SplitByMaterials_Benchmark() + { + var path = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); + var scene = VimScene.LoadVim(path); + var sw = new Stopwatch(); + + long time = 0; + long consumeTime =0; + long consumeAgain = 0; + for (var j=0; j < 100; j++) + { + for (var i = 0; i < scene.GetMeshCount(); i++) + { + sw.Restart(); + var mesh = scene.Meshes[i].SplitByMaterial().ToArray(); + sw.Stop(); + time += sw.ElapsedTicks; + + sw.Restart(); + foreach (var (mat, m) in mesh) + { + Consume(m); + } + sw.Stop(); + consumeTime += sw.ElapsedTicks; + + sw.Restart(); + foreach (var (mat, m) in mesh) + { + Consume(m); + } + sw.Stop(); + consumeAgain += sw.ElapsedTicks; + } + } + + Console.WriteLine("==Meshes=="); + Console.WriteLine("Split:" + (time * 1.0) / Stopwatch.Frequency); + Console.WriteLine("Consume:" + (consumeTime * 1.0) / Stopwatch.Frequency); + Console.WriteLine("Consume Again:" + (consumeAgain * 1.0) / Stopwatch.Frequency); + Console.WriteLine("Total:" + (time + consumeTime + consumeAgain * 1.0) / Stopwatch.Frequency); + + time = 0; + consumeTime = 0; + consumeAgain = 0; + for (var j = 0; j < 100; j++) + { + for (var i = 0; i < scene.GetMeshCount(); i++) + { + sw.Restart(); + var next = scene.MeshesNext[i].SplitByMaterial(); + sw.Stop(); + time += sw.ElapsedTicks; + + sw.Restart(); + foreach (var (mat, mesh) in next) + { + Consume(mesh); + } + sw.Stop(); + consumeTime += sw.ElapsedTicks; + + sw.Restart(); + foreach (var (mat, m) in next) + { + Consume(m); + } + sw.Stop(); + consumeAgain += sw.ElapsedTicks; + } + } + Console.WriteLine("==Next=="); + Console.WriteLine("Split:" + (time * 1.0) / Stopwatch.Frequency); + Console.WriteLine("Consume:" + (consumeTime * 1.0) / Stopwatch.Frequency); + Console.WriteLine("Consume Again:" + (consumeAgain * 1.0) / Stopwatch.Frequency); + Console.WriteLine("Total:" + (time + consumeTime + consumeAgain * 1.0) / Stopwatch.Frequency); + + time =0; + consumeTime = 0; + consumeAgain = 0; + for (var j = 0; j < 100; j++) + { + for (var i = 0; i < scene.GetMeshCount(); i++) + { + sw.Restart(); + var raw = scene.MeshesRaw[i].SplitByMaterial(); + sw.Stop(); + time += sw.ElapsedTicks; + + sw.Restart(); + foreach (var (mat, mesh) in raw) + { + Consume(mesh); + } + sw.Stop(); + consumeTime += sw.ElapsedTicks; + + sw.Restart(); + foreach (var (mat, m) in raw) + { + Consume(m); + } + sw.Stop(); + consumeAgain += sw.ElapsedTicks; + } + } + Console.WriteLine("==Raw=="); + Console.WriteLine("Split:" + (time *1.0) / Stopwatch.Frequency); + Console.WriteLine("Consume:" + (consumeTime * 1.0) / Stopwatch.Frequency); + Console.WriteLine("Consume Again:" + (consumeAgain * 1.0) / Stopwatch.Frequency); + Console.WriteLine("Total:" + (time + consumeTime + consumeAgain * 1.0) / Stopwatch.Frequency); + + } + + private static void Consume(IMesh mesh) { + mesh.Indices.Sum(); + mesh.Vertices.Sum(v => v.X); + mesh.SubmeshIndexOffsets.Sum(); + mesh.SubmeshIndexCount.Sum(); + mesh.SubmeshMaterials.Sum(); + } + private static void Consume(IMeshCommon mesh) + { + mesh.Indices.Sum(); + mesh.Vertices.Sum(v => v.X); + mesh.SubmeshIndexOffsets.Sum(); + mesh.SubmeshIndexCounts.Sum(); + mesh.SubmeshMaterials.Sum(); + } + + + private static void MeshesAreSame(IMesh mesh, IMeshCommon next) + { Assert.That(mesh.Indices.SequenceEquals(next.Indices)); Assert.That(mesh.Vertices.SequenceEquals(next.Vertices)); Assert.That(mesh.SubmeshIndexOffsets.SequenceEquals(next.SubmeshIndexOffsets)); Assert.That(mesh.SubmeshMaterials.SequenceEquals(next.SubmeshMaterials)); + Assert.That(mesh.SubmeshIndexCount.SequenceEquals(next.SubmeshIndexCounts)); } + private static void MeshesAreSame(IMeshCommon mesh, IMeshCommon next) + { + Assert.That(mesh.Indices.SequenceEquals(next.Indices)); + Assert.That(mesh.Vertices.SequenceEquals(next.Vertices)); + Assert.That(mesh.SubmeshIndexOffsets.SequenceEquals(next.SubmeshIndexOffsets)); + Assert.That(mesh.SubmeshMaterials.SequenceEquals(next.SubmeshMaterials)); + Assert.That(mesh.SubmeshIndexCounts.SequenceEquals(next.SubmeshIndexCounts)); + } + + + + } diff --git a/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs b/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs index aa63dcc2..1e57e383 100644 --- a/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs +++ b/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs @@ -60,7 +60,8 @@ public static VimScene LoadVim(Stream stream, IVimSceneProgress progress = null, public int VimIndex { get; set; } public IArray Meshes { get; private set; } - public IMeshCommon[] MeshesNext { get; private set; } + public VimMesh[] MeshesNext { get; private set; } + public G3dMesh[] MeshesRaw { get; private set; } public IArray Nodes { get; private set; } public IArray VimNodes { get; private set; } public IArray VimShapes { get; private set; } @@ -86,10 +87,8 @@ public static IMesh ToIMesh(G3dMesh g3d) => Primitives.TriMesh( g3d.Vertices.ToPositionAttribute(), g3d.Indices.ToIndexAttribute(), - g3d.VertexUvs?.ToVertexUvAttribute(), g3d.SubmeshIndexOffsets?.ToSubmeshIndexOffsetAttribute(), - g3d.SubmeshMaterials?.ToSubmeshMaterialAttribute(), - g3d.MeshSubmeshOffset?.ToMeshSubmeshOffsetAttribute() + g3d.SubmeshMaterials?.ToSubmeshMaterialAttribute() ); private VimScene(SerializableDocument doc) @@ -206,6 +205,7 @@ private void CreateMeshes(bool inParallel) ? tmp.EvaluateInParallel() : tmp.Evaluate(); MeshesNext = VimMesh.GetAllMeshes(_SerializableDocument.GeometryNext).ToArray(); + MeshesRaw = srcGeo?.Meshes.ToArray(); } private void CreateShapes(bool inParallel) From 60d87261ccc4155092d252936cfbc108b3d97e40 Mon Sep 17 00:00:00 2001 From: simon Date: Thu, 4 Apr 2024 15:36:03 -0400 Subject: [PATCH 120/204] replace VimScene.Meshes with the G3dMesh --- src/cs/vim/Vim.Format.Core/Geometry/IScene.cs | 3 +- .../SerializableDocumentTests.cs | 144 ++---------------- .../vim/Vim.Format/SceneBuilder/Validation.cs | 4 +- .../vim/Vim.Format/SceneBuilder/VimScene.cs | 10 +- 4 files changed, 23 insertions(+), 138 deletions(-) diff --git a/src/cs/vim/Vim.Format.Core/Geometry/IScene.cs b/src/cs/vim/Vim.Format.Core/Geometry/IScene.cs index eb2e5821..d87f6a7a 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/IScene.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/IScene.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using Vim.G3d; using Vim.LinqArray; using Vim.Math3d; @@ -10,7 +11,7 @@ namespace Vim.Format.Geometry public interface IScene { IArray Nodes { get; } - IArray Meshes { get; } + IArray Meshes { get; } } /// diff --git a/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs b/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs index 2ff6240a..e40de3ca 100644 --- a/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs +++ b/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs @@ -53,9 +53,9 @@ public static void GetMesh_IsSameMesh() var scene = VimScene.LoadVim(path); for (var i = 0; i < scene.GetMeshCount(); i++) { - var mesh = scene.Meshes[i]; + var mesh = scene.MeshesOld[i]; var next = scene.MeshesNext[i]; - var raw = scene.MeshesRaw[i]; + var raw = scene.Meshes[i]; MeshesAreSame(mesh, next); MeshesAreSame(mesh, raw); } @@ -73,9 +73,9 @@ public static void GetMesh_Transform_IsSame() new Vector3(0, 0, 1), new Vector3(0, 1, 0) ); - var mesh = scene.Meshes[i].Transform(mat); + var mesh = scene.MeshesOld[i].Transform(mat); var next = scene.MeshesNext[i].Transform(mat); - var raw = scene.MeshesRaw[i].Transform(mat); + var raw = scene.Meshes[i].Transform(mat); MeshesAreSame(mesh, next); MeshesAreSame(mesh, raw); } @@ -89,9 +89,9 @@ public static void ReverseWindingOrder_IsSame() for (var i = 0; i < scene.GetMeshCount(); i++) { - var mesh = scene.Meshes[i].ReverseWindingOrder().ToIMesh(); + var mesh = scene.MeshesOld[i].ReverseWindingOrder().ToIMesh(); var next = scene.MeshesNext[i].ReverseWindingOrder(); - var raw = scene.MeshesRaw[i].ReverseWindingOrder(); + var raw = scene.Meshes[i].ReverseWindingOrder(); MeshesAreSame(mesh, next); MeshesAreSame(mesh, raw); } @@ -104,9 +104,9 @@ public static void FaceMaterial_IsSame() var scene = VimScene.LoadVim(path); for (var i = 0; i < scene.GetMeshCount(); i++) { - var mesh = scene.Meshes[i].GetFaceMaterials(); + var mesh = scene.MeshesOld[i].GetFaceMaterials(); var next = scene.MeshesNext[i].GetFaceMaterials(); - var raw = scene.MeshesRaw[i].GetFaceMaterials(); + var raw = scene.Meshes[i].GetFaceMaterials(); Assert.That(mesh.SequenceEquals(next)); Assert.That(next.SequenceEquals(raw)); } @@ -119,9 +119,9 @@ public static void Merge_ByPair_IsSame() var scene = VimScene.LoadVim(path); for (var i = 1; i < scene.GetMeshCount(); i++) { - var mesh = scene.Meshes[i].Merge(scene.Meshes[i - 1]); + var mesh = scene.MeshesOld[i].Merge(scene.MeshesOld[i - 1]); var next = scene.MeshesNext[i].Merge2(scene.MeshesNext[i - 1]); - var raw = scene.MeshesRaw[i].Merge2(scene.MeshesRaw[i - 1]); + var raw = scene.Meshes[i].Merge2(scene.Meshes[i - 1]); MeshesAreSame(mesh, next); MeshesAreSame(mesh, raw); } @@ -133,9 +133,9 @@ public static void Merge_All_IsSame() var path = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); var scene = VimScene.LoadVim(path); - var mesh = scene.Meshes[0].Merge(scene.Meshes.Skip(1).ToArray()); + var mesh = scene.MeshesOld[0].Merge(scene.MeshesOld.Skip(1).ToArray()); var next = scene.MeshesNext[0].Merge2(scene.MeshesNext.Skip(1).ToArray()); - var raw = scene.MeshesRaw[0].Merge2(scene.MeshesRaw.Skip(1).ToArray()); + var raw = scene.Meshes[0].Merge2(scene.Meshes.Skip(1).ToArray()); MeshesAreSame(mesh, next); MeshesAreSame(mesh, raw); } @@ -147,9 +147,9 @@ public static void SplitByMaterials_IsSame() var scene = VimScene.LoadVim(path); for (var i = 0; i < scene.GetMeshCount(); i++) { - var mesh = scene.Meshes[i].SplitByMaterial().ToArray(); + var mesh = scene.MeshesOld[i].SplitByMaterial().ToArray(); var next = scene.MeshesNext[i].SplitByMaterial(); - var raw = scene.MeshesRaw[i].SplitByMaterial(); + var raw = scene.Meshes[i].SplitByMaterial(); Assert.AreEqual(mesh.Length, next.Length); Assert.AreEqual(mesh.Length, raw.Length); @@ -161,122 +161,6 @@ public static void SplitByMaterials_IsSame() } } - - [Test] - public static void SplitByMaterials_Benchmark() - { - var path = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); - var scene = VimScene.LoadVim(path); - var sw = new Stopwatch(); - - long time = 0; - long consumeTime =0; - long consumeAgain = 0; - for (var j=0; j < 100; j++) - { - for (var i = 0; i < scene.GetMeshCount(); i++) - { - sw.Restart(); - var mesh = scene.Meshes[i].SplitByMaterial().ToArray(); - sw.Stop(); - time += sw.ElapsedTicks; - - sw.Restart(); - foreach (var (mat, m) in mesh) - { - Consume(m); - } - sw.Stop(); - consumeTime += sw.ElapsedTicks; - - sw.Restart(); - foreach (var (mat, m) in mesh) - { - Consume(m); - } - sw.Stop(); - consumeAgain += sw.ElapsedTicks; - } - } - - Console.WriteLine("==Meshes=="); - Console.WriteLine("Split:" + (time * 1.0) / Stopwatch.Frequency); - Console.WriteLine("Consume:" + (consumeTime * 1.0) / Stopwatch.Frequency); - Console.WriteLine("Consume Again:" + (consumeAgain * 1.0) / Stopwatch.Frequency); - Console.WriteLine("Total:" + (time + consumeTime + consumeAgain * 1.0) / Stopwatch.Frequency); - - time = 0; - consumeTime = 0; - consumeAgain = 0; - for (var j = 0; j < 100; j++) - { - for (var i = 0; i < scene.GetMeshCount(); i++) - { - sw.Restart(); - var next = scene.MeshesNext[i].SplitByMaterial(); - sw.Stop(); - time += sw.ElapsedTicks; - - sw.Restart(); - foreach (var (mat, mesh) in next) - { - Consume(mesh); - } - sw.Stop(); - consumeTime += sw.ElapsedTicks; - - sw.Restart(); - foreach (var (mat, m) in next) - { - Consume(m); - } - sw.Stop(); - consumeAgain += sw.ElapsedTicks; - } - } - Console.WriteLine("==Next=="); - Console.WriteLine("Split:" + (time * 1.0) / Stopwatch.Frequency); - Console.WriteLine("Consume:" + (consumeTime * 1.0) / Stopwatch.Frequency); - Console.WriteLine("Consume Again:" + (consumeAgain * 1.0) / Stopwatch.Frequency); - Console.WriteLine("Total:" + (time + consumeTime + consumeAgain * 1.0) / Stopwatch.Frequency); - - time =0; - consumeTime = 0; - consumeAgain = 0; - for (var j = 0; j < 100; j++) - { - for (var i = 0; i < scene.GetMeshCount(); i++) - { - sw.Restart(); - var raw = scene.MeshesRaw[i].SplitByMaterial(); - sw.Stop(); - time += sw.ElapsedTicks; - - sw.Restart(); - foreach (var (mat, mesh) in raw) - { - Consume(mesh); - } - sw.Stop(); - consumeTime += sw.ElapsedTicks; - - sw.Restart(); - foreach (var (mat, m) in raw) - { - Consume(m); - } - sw.Stop(); - consumeAgain += sw.ElapsedTicks; - } - } - Console.WriteLine("==Raw=="); - Console.WriteLine("Split:" + (time *1.0) / Stopwatch.Frequency); - Console.WriteLine("Consume:" + (consumeTime * 1.0) / Stopwatch.Frequency); - Console.WriteLine("Consume Again:" + (consumeAgain * 1.0) / Stopwatch.Frequency); - Console.WriteLine("Total:" + (time + consumeTime + consumeAgain * 1.0) / Stopwatch.Frequency); - - } - private static void Consume(IMesh mesh) { mesh.Indices.Sum(); diff --git a/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs b/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs index a1eaa15f..ddf0713f 100644 --- a/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs +++ b/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs @@ -35,7 +35,7 @@ public static void ValidateGeometry(this VimScene vim) // Validate the individual meshes. - foreach (var g in vim.Meshes.ToEnumerable()) + foreach (var g in vim.MeshesOld.ToEnumerable()) g.Validate(); } @@ -230,7 +230,7 @@ public static void ValidateEquality(this DocumentBuilder db, VimScene vim) 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.Geometry.GetMesh(i).ToIMesh().GeometryEquals(vim.Meshes[i])) + if (!db.Geometry.GetMesh(i).ToIMesh().GeometryEquals(vim.MeshesOld[i])) throw new VimValidationException($"{nameof(DocumentBuilder)} mesh {i} geometry is not equal to {nameof(VimScene)} mesh {i}"); } diff --git a/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs b/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs index 1e57e383..b5704969 100644 --- a/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs +++ b/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs @@ -59,9 +59,9 @@ public static VimScene LoadVim(Stream stream, IVimSceneProgress progress = null, => LoadVim(stream, new LoadOptions { SkipGeometry = skipGeometry, SkipAssets = skipAssets}, progress, inParallel); public int VimIndex { get; set; } - public IArray Meshes { get; private set; } + public IArray MeshesOld { get; private set; } public VimMesh[] MeshesNext { get; private set; } - public G3dMesh[] MeshesRaw { get; private set; } + public IArray Meshes { get; private set; } public IArray Nodes { get; private set; } public IArray VimNodes { get; private set; } public IArray VimShapes { get; private set; } @@ -199,13 +199,13 @@ private void CreateMeshes(bool inParallel) var srcGeo = _SerializableDocument.Geometry; var tmp = srcGeo?.Meshes.Select(ToIMesh); - Meshes = (tmp == null) + MeshesOld = (tmp == null) ? LinqArray.LinqArray.Empty() : inParallel ? tmp.EvaluateInParallel() : tmp.Evaluate(); MeshesNext = VimMesh.GetAllMeshes(_SerializableDocument.GeometryNext).ToArray(); - MeshesRaw = srcGeo?.Meshes.ToArray(); + Meshes = srcGeo?.Meshes.Select(m => m as IMeshCommon); } private void CreateShapes(bool inParallel) @@ -256,7 +256,7 @@ public void Save(string filePath) public string FileName => _SerializableDocument.FileName; - public void TransformSceneInPlace(Func meshTransform = null, Func nodeTransform = null) + public void TransformSceneInPlace(Func meshTransform = null, Func nodeTransform = null) { if (meshTransform != null) Meshes = Meshes.Select(meshTransform).EvaluateInParallel(); From 5cb0f05547a3084a4952c35138a1882ba0352928 Mon Sep 17 00:00:00 2001 From: simon Date: Thu, 4 Apr 2024 16:12:35 -0400 Subject: [PATCH 121/204] missing IMeshCommon stuff --- src/cs/vim/Vim.Format.Core/Geometry/IScene.cs | 6 +++--- .../vim/Vim.Format.Core/Geometry/SceneExtensions.cs | 11 ++++++----- src/cs/vim/Vim.Format/SceneBuilder/VimSceneNode.cs | 2 +- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/cs/vim/Vim.Format.Core/Geometry/IScene.cs b/src/cs/vim/Vim.Format.Core/Geometry/IScene.cs index d87f6a7a..4f7208cd 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/IScene.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/IScene.cs @@ -23,7 +23,7 @@ public interface ISceneNode IScene Scene { get; } Matrix4x4 Transform { get; } int MeshIndex { get; } - IMesh GetMesh(); + IMeshCommon GetMesh(); ISceneNode Parent { get; } // TODO: DEPRECATE: this needs to be removed, currently only used in Vim.Max.Bridge. @@ -52,7 +52,7 @@ public class NullNode : ISceneNode public int MeshIndex => 0; public ISceneNode Parent => null; public IArray Children => null; - public IMesh GetMesh() => null; + public IMeshCommon GetMesh() => null; } public class IdNode : ISceneNode @@ -63,6 +63,6 @@ public class IdNode : ISceneNode public int MeshIndex => 0; public ISceneNode Parent => null; public IArray Children => null; - public IMesh GetMesh() => null; + public IMeshCommon GetMesh() => null; } } diff --git a/src/cs/vim/Vim.Format.Core/Geometry/SceneExtensions.cs b/src/cs/vim/Vim.Format.Core/Geometry/SceneExtensions.cs index 555baefa..d59455aa 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/SceneExtensions.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/SceneExtensions.cs @@ -3,22 +3,23 @@ using Vim.Util; using Vim.LinqArray; using Vim.Math3d; +using Vim.G3d; namespace Vim.Format.Geometry { public static class SceneExtensions { - public static IMesh TransformedMesh(this ISceneNode node) + public static IMeshCommon TransformedMesh(this ISceneNode node) => node.GetMesh()?.Transform(node.Transform); - public static IEnumerable TransformedMeshes(this IScene scene) + public static IEnumerable TransformedMeshes(this IScene scene) => scene.Nodes.Where(n => n.GetMesh() != null).Select(TransformedMesh); - public static IMesh MergedGeometry(this IScene scene) + public static IMeshCommon MergedGeometry(this IScene scene) => scene.Nodes.ToEnumerable().MergedGeometry(); - public static IMesh MergedGeometry(this IEnumerable nodes) - => nodes.Where(n => n.GetMesh() != null).Select(TransformedMesh).Merge(); + public static IMeshCommon MergedGeometry(this IEnumerable nodes) + => nodes.Where(n => n.GetMesh() != null).Select(TransformedMesh).ToArray().Merge(); public static IEnumerable AllVertices(this IScene scene) => scene.TransformedMeshes().SelectMany(g => g.Vertices.ToEnumerable()); diff --git a/src/cs/vim/Vim.Format/SceneBuilder/VimSceneNode.cs b/src/cs/vim/Vim.Format/SceneBuilder/VimSceneNode.cs index 9bb7a754..9dcf686a 100644 --- a/src/cs/vim/Vim.Format/SceneBuilder/VimSceneNode.cs +++ b/src/cs/vim/Vim.Format/SceneBuilder/VimSceneNode.cs @@ -36,7 +36,7 @@ public bool HideByDefault public int VimIndex { get; } = -1; public int NodeIndex { get; } = -1; - public IMesh GetMesh() + public IMeshCommon GetMesh() => _Scene.Meshes.ElementAtOrDefault(MeshIndex); public int MeshIndex { get; } From 7bf7b9a78f8ff3774bc45a325ffb5b8da5614898 Mon Sep 17 00:00:00 2001 From: simon Date: Thu, 4 Apr 2024 16:52:37 -0400 Subject: [PATCH 122/204] implemented hash for meshcommon --- .../Geometry/MeshOptimization.cs | 53 +++++++++++++++++++ .../vim/Vim.Format.Core/Geometry/VimMesh.cs | 29 ++++++++++ 2 files changed, 82 insertions(+) diff --git a/src/cs/vim/Vim.Format.Core/Geometry/MeshOptimization.cs b/src/cs/vim/Vim.Format.Core/Geometry/MeshOptimization.cs index 4db387a7..a7a4691e 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/MeshOptimization.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/MeshOptimization.cs @@ -58,9 +58,62 @@ public override int GetHashCode() => Hash.Combine(NumFaces, NumVertices, TopologyHash, BoxMin.GetHashCode(), BoxExtents.GetHashCode()); } + /// + /// This class is used to compare quickly two meshes within a lookup table (e.g. Dictionary, HashTable). + /// it looks at the positions of each corner, and the number of faces, and assures that the object ID + /// and material IDs are the same. + /// When using a class within a dictionary or hash table, the equals operator is called frequently. + /// By converting an IMesh to a MeshHash we minimize the amount of comparisons done. It becomes + /// possible, but highly unlikely that two different meshes would have the same hash. + /// + public class MeshCommonHash + { + public IMeshCommon Mesh; + public float Tolerance; + public int NumFaces; + public int NumVertices; + public int TopologyHash; + public Int3 BoxExtents; + public Int3 BoxMin; + + public int Round(float f) + => (int)(f / Tolerance); + + public Int3 Round(Vector3 v) + => new Int3(Round(v.X), Round(v.Y), Round(v.Z)); + + public MeshCommonHash(IMeshCommon mesh, float tolerance) + { + Mesh = mesh; + Tolerance = tolerance; + NumFaces = mesh.NumFaces; + NumVertices = mesh.NumVertices; + TopologyHash = Hash.Combine(mesh.Indices.ToArray()); + var box = mesh.BoundingBox(); + BoxMin = Round(box.Min); + BoxExtents = Round(box.Extent); + } + + public override bool Equals(object obj) + => obj is MeshHash other && Equals(other); + + public bool Equals(MeshCommonHash other) + => NumFaces == other.NumFaces + && NumVertices == other.NumVertices + && BoxMin.Equals(other.BoxMin) + && BoxExtents.Equals(other.BoxExtents) + && Mesh.GeometryEquals(other.Mesh); + + public override int GetHashCode() + => Hash.Combine(NumFaces, NumVertices, TopologyHash, BoxMin.GetHashCode(), BoxExtents.GetHashCode()); + } + public static class Optimization { public static Dictionary> GroupMeshesByHash(this IEnumerable meshes, float tolerance) => meshes.AsParallel().GroupBy(m => new MeshHash(m, tolerance)).ToDictionary(grp => grp.Key, grp => grp.ToList()); + + public static Dictionary> GroupMeshesByHash(this IEnumerable meshes, float tolerance) + => meshes.AsParallel().GroupBy(m => new MeshCommonHash(m, tolerance)).ToDictionary(grp => grp.Key, grp => grp.ToList()); } } diff --git a/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs b/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs index 47fbdfb9..b38fb6a9 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs @@ -6,6 +6,7 @@ using Vim.LinqArray; using Vim.Math3d; using Vim.Util; +using static System.Net.Mime.MediaTypeNames; using static Vim.Format.DocumentBuilder; namespace Vim.Format.Geometry @@ -237,6 +238,34 @@ public static (int, List)[] GroupSubmeshesByMaterials(this IMeshCommon mesh return map.Select(kvp => (kvp.Key, kvp.Value)).ToArray(); } + public static AABox BoundingBox(this IMeshCommon mesh) + => AABox.Create(mesh.Vertices.ToEnumerable()); + + public static bool GeometryEquals(this IMeshCommon mesh, IMeshCommon other, float tolerance = Math3d.Constants.Tolerance) + { + if (!mesh.Indices.SequenceEquals(other.Indices)) + return false; + + if (!mesh.SubmeshIndexOffsets.SequenceEquals(other.SubmeshIndexOffsets)) + return false; + + if (!mesh.SubmeshMaterials.SequenceEquals(other.SubmeshMaterials)) + return false; + + if (!mesh.SubmeshIndexCounts.SequenceEquals(other.SubmeshIndexCounts)) + return false; + + if (mesh.Vertices.Count != other.Vertices.Count) + return false; + + for(var i = 0; i < mesh.Vertices.Count; i++) + { + if(!mesh.Vertices[i].AlmostEquals(other.Vertices[i], tolerance)) + return false; + } + + return true; + } public static (int mat, IMeshCommon mesh)[] SplitByMaterial(this IMeshCommon mesh) { From 311ba673920a2bf6cf2ab22214d99c143379e3db Mon Sep 17 00:00:00 2001 From: simon Date: Thu, 4 Apr 2024 17:09:49 -0400 Subject: [PATCH 123/204] added meshcommon toDocumentbuildersubdividedMesh --- src/cs/vim/Vim.Format.Core/DocumentBuilderExtensions.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/cs/vim/Vim.Format.Core/DocumentBuilderExtensions.cs b/src/cs/vim/Vim.Format.Core/DocumentBuilderExtensions.cs index 77c0d209..9ffdd818 100644 --- a/src/cs/vim/Vim.Format.Core/DocumentBuilderExtensions.cs +++ b/src/cs/vim/Vim.Format.Core/DocumentBuilderExtensions.cs @@ -30,8 +30,12 @@ public static SubdividedMesh ToDocumentBuilderSubdividedMesh(this IMesh m) m.SubmeshIndexOffsets.ToList(), m.SubmeshMaterials.ToList()); - public static void AddMesh(this DocumentBuilder db, IMesh m) - => db.AddMesh(m.ToDocumentBuilderSubdividedMesh()); + public static SubdividedMesh ToDocumentBuilderSubdividedMesh(this IMeshCommon m) + => new SubdividedMesh( + m.Indices.ToList(), + m.Vertices.ToList(), + m.SubmeshIndexOffsets.ToList(), + m.SubmeshMaterials.ToList()); public static EntityTableBuilder CreateTableCopy(this DocumentBuilder db, EntityTable table, List nodeIndexRemapping = null) { From 510e4dc6130e253b60d06d252826cf54720a9c9a Mon Sep 17 00:00:00 2001 From: simon Date: Thu, 4 Apr 2024 22:32:35 -0400 Subject: [PATCH 124/204] added meshcommon version of method --- src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs b/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs index b38fb6a9..bb4107dc 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs @@ -241,6 +241,10 @@ public static (int, List)[] GroupSubmeshesByMaterials(this IMeshCommon mesh public static AABox BoundingBox(this IMeshCommon mesh) => AABox.Create(mesh.Vertices.ToEnumerable()); + public static Int3 FaceVertexIndices(this IMeshCommon mesh, int faceIndex) + => new Int3(mesh.Indices[faceIndex * 3], mesh.Indices[faceIndex * 3 + 1], mesh.Indices[faceIndex * 3 + 2]); + + public static bool GeometryEquals(this IMeshCommon mesh, IMeshCommon other, float tolerance = Math3d.Constants.Tolerance) { if (!mesh.Indices.SequenceEquals(other.Indices)) From 47c180c883bf6374d3794a55706de2ed3d585db6 Mon Sep 17 00:00:00 2001 From: simon Date: Fri, 5 Apr 2024 10:05:33 -0400 Subject: [PATCH 125/204] added center for meshcommon --- src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs b/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs index bb4107dc..e5f2f8c4 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs @@ -238,6 +238,9 @@ public static (int, List)[] GroupSubmeshesByMaterials(this IMeshCommon mesh return map.Select(kvp => (kvp.Key, kvp.Value)).ToArray(); } + public static Vector3 Center(this IMesh mesh) + => mesh.BoundingBox().Center; + public static AABox BoundingBox(this IMeshCommon mesh) => AABox.Create(mesh.Vertices.ToEnumerable()); From 2362b4299c717a1340eeb68b3c5e704bf10d8ac5 Mon Sep 17 00:00:00 2001 From: simon Date: Fri, 5 Apr 2024 10:09:44 -0400 Subject: [PATCH 126/204] wrong type --- src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs b/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs index e5f2f8c4..424f765f 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs @@ -238,7 +238,7 @@ public static (int, List)[] GroupSubmeshesByMaterials(this IMeshCommon mesh return map.Select(kvp => (kvp.Key, kvp.Value)).ToArray(); } - public static Vector3 Center(this IMesh mesh) + public static Vector3 Center(this IMeshCommon mesh) => mesh.BoundingBox().Center; public static AABox BoundingBox(this IMeshCommon mesh) From a521e21041051cfeb4e489f37b118e1d5cdeed2a Mon Sep 17 00:00:00 2001 From: simon Date: Fri, 5 Apr 2024 13:21:09 -0400 Subject: [PATCH 127/204] Added quad method to vimmesh --- .../Vim.G3d/GeometryAttributesExtensions.cs | 1 + .../Vim.Format.Core/Geometry/Primitives.cs | 4 +- .../vim/Vim.Format.Core/Geometry/VimMesh.cs | 45 +++++++++++++++++++ .../SerializableDocumentTests.cs | 20 +++++++++ 4 files changed, 69 insertions(+), 1 deletion(-) diff --git a/src/cs/g3d/Vim.G3d/GeometryAttributesExtensions.cs b/src/cs/g3d/Vim.G3d/GeometryAttributesExtensions.cs index ba7c1cfa..5d7e07d5 100644 --- a/src/cs/g3d/Vim.G3d/GeometryAttributesExtensions.cs +++ b/src/cs/g3d/Vim.G3d/GeometryAttributesExtensions.cs @@ -311,6 +311,7 @@ public static IEnumerable SetFaceSizeAttribute(this IEnumerab /// public static IGeometryAttributes RemapFacesAndCorners(this IGeometryAttributes g, IArray faceRemap, IArray cornerRemap, int numCornersPerFace = -1) => g.VertexAttributes() + .Concat(g.SubMeshAttributes()) .Concat(g.NoneAttributes()) .Concat(g.FaceAttributes().Select(attr => attr.Remap(faceRemap))) .Concat(g.EdgeAttributes().Select(attr => attr.Remap(cornerRemap))) diff --git a/src/cs/vim/Vim.Format.Core/Geometry/Primitives.cs b/src/cs/vim/Vim.Format.Core/Geometry/Primitives.cs index 4a0e5a63..570d9dda 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/Primitives.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/Primitives.cs @@ -49,7 +49,9 @@ public static IMesh QuadMesh(this IArray vertices, IArray indices vertices.ToPositionAttribute(), indices?.ToIndexAttribute(), uvs?.ToVertexUvAttribute(), - materials?.ToFaceMaterialAttribute() + materials?.ToFaceMaterialAttribute(), + (new int[] {0}).ToSubmeshIndexOffsetAttribute(), + (new int[] { -1 }).ToSubmeshMaterialAttribute() ); public static IMesh QuadMesh(Vector3 a, Vector3 b, Vector3 c, Vector3 d) diff --git a/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs b/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs index 424f765f..96c0681d 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs @@ -47,6 +47,15 @@ public VimMesh() { } + + public VimMesh(int[] indices, Vector3[] vertices, int[] submeshIndexOffsets = null, int[] submeshMaterials = null, int[] submeshIndexCounts = null) + { + this.indices = indices; + this.vertices = vertices; + this.submeshIndexOffsets = submeshIndexOffsets ?? new int[1] { 0 }; + this.submeshMaterials = submeshMaterials ?? new int[1] { -1}; + this.submeshIndexCounts = submeshIndexCounts ?? new int[1] { indices.Length }; + } public VimMesh(int indexCount, int vertexCount, int submeshCount) { indices = new int[indexCount]; @@ -119,6 +128,27 @@ public static VimMesh FromG3d(G3dVim g3d, int index) return mesh; } + public static VimMesh FromQuad(int[] indices, Vector3[] vertices) + { + if(indices.Length % 4 != 0) + { + throw new ArgumentException("Indices count should be a multiple of 4."); + } + var faceCount = indices.Length / 4; + var triIndices = new int[faceCount * 6]; + var cur = 0; + for (var i = 0; i < faceCount; ++i) + { + triIndices[cur++] = indices[i * 4 + 0]; + triIndices[cur++] = indices[i * 4 + 1]; + triIndices[cur++] = indices[i * 4 + 2]; + triIndices[cur++] = indices[i * 4 + 0]; + triIndices[cur++] = indices[i * 4 + 2]; + triIndices[cur++] = indices[i * 4 + 3]; + } + return new VimMesh(triIndices, vertices); + } + public static IEnumerable GetAllMeshes(G3dVim g3d) { return Enumerable.Range(0, g3d.GetMeshCount()).Select(i => FromG3d(g3d, i)); @@ -247,6 +277,21 @@ public static AABox BoundingBox(this IMeshCommon mesh) public static Int3 FaceVertexIndices(this IMeshCommon mesh, int faceIndex) => new Int3(mesh.Indices[faceIndex * 3], mesh.Indices[faceIndex * 3 + 1], mesh.Indices[faceIndex * 3 + 2]); + /// + /// Low-level remap function. Maps faces and corners at the same time. + /// In some cases, this is important (e.g. triangulating quads). + /// Note: meshes are lost. + /// + public static IGeometryAttributes RemapFacesAndCorners(this IGeometryAttributes g, IArray faceRemap, IArray cornerRemap, int numCornersPerFace = -1) + => g.VertexAttributes() + .Concat(g.NoneAttributes()) + .Concat(g.FaceAttributes().Select(attr => attr.Remap(faceRemap))) + .Concat(g.EdgeAttributes().Select(attr => attr.Remap(cornerRemap))) + .Concat(g.CornerAttributes().Select(attr => attr.Remap(cornerRemap))) + .Concat(g.WholeGeometryAttributes()) + .SetFaceSizeAttribute(numCornersPerFace) + .ToGeometryAttributes(); + public static bool GeometryEquals(this IMeshCommon mesh, IMeshCommon other, float tolerance = Math3d.Constants.Tolerance) { diff --git a/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs b/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs index e40de3ca..e44959b1 100644 --- a/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs +++ b/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs @@ -127,6 +127,26 @@ public static void Merge_ByPair_IsSame() } } + [Test] + public static void QuadToTri_IsSame() + { + var indices = new int[] { 0, 1, 4, 3, 1, 2, 5, 4 }; + var vertices = new Vector3[] + { + new Vector3(1,0,0), + new Vector3(1,1,0), + new Vector3(1,2,0), + new Vector3(0,0,0), + new Vector3(0,1,0), + new Vector3(0,2,0), + }; + + var mesh = Primitives.QuadMesh(vertices.ToIArray(), indices.ToIArray()); + var next = VimMesh.FromQuad(indices, vertices); + + MeshesAreSame(mesh, next); + } + [Test] public static void Merge_All_IsSame() { From e8138d0b0c74cf241cbb0f2b0ec7403c985d7523 Mon Sep 17 00:00:00 2001 From: simon Date: Fri, 5 Apr 2024 14:23:05 -0400 Subject: [PATCH 128/204] Added FromG3d to turn whole g3d into a vimMesh --- .../vim/Vim.Format.Core/Geometry/VimMesh.cs | 52 +++++++++++++++---- .../SerializableDocumentTests.cs | 11 ++++ 2 files changed, 52 insertions(+), 11 deletions(-) diff --git a/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs b/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs index 96c0681d..aaac9cf3 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs @@ -6,8 +6,6 @@ using Vim.LinqArray; using Vim.Math3d; using Vim.Util; -using static System.Net.Mime.MediaTypeNames; -using static Vim.Format.DocumentBuilder; namespace Vim.Format.Geometry { @@ -48,14 +46,34 @@ public VimMesh() } - public VimMesh(int[] indices, Vector3[] vertices, int[] submeshIndexOffsets = null, int[] submeshMaterials = null, int[] submeshIndexCounts = null) + public VimMesh( + int[] indices, + Vector3[] vertices, + int[] submeshIndexOffsets = null, + int[] submeshMaterials = null, + int[] submeshIndexCounts = null + ) { this.indices = indices; this.vertices = vertices; + this.submeshIndexOffsets = submeshIndexOffsets ?? new int[1] { 0 }; - this.submeshMaterials = submeshMaterials ?? new int[1] { -1}; - this.submeshIndexCounts = submeshIndexCounts ?? new int[1] { indices.Length }; + this.submeshMaterials = submeshMaterials ?? new int[1] { -1 }; + this.submeshIndexCounts = submeshIndexCounts ?? ComputeCounts(this.submeshIndexOffsets, this.indices.Length); + } + + private static int[] ComputeCounts(int[] offsets, int max) + { + var result = new int[offsets.Length]; + for (var i = 0; i < result.Length - 1; i++) + { + result[i] = offsets[i + 1] - offsets[i]; + } + var last = result.Length - 1; + result[last] = max - offsets[last]; + return result; } + public VimMesh(int indexCount, int vertexCount, int submeshCount) { indices = new int[indexCount]; @@ -67,12 +85,12 @@ public VimMesh(int indexCount, int vertexCount, int submeshCount) public VimMesh Clone() { - var mesh = new VimMesh(); - mesh.indices = indices; - mesh.vertices = vertices; - mesh.submeshIndexOffsets = submeshIndexOffsets; - mesh.submeshMaterials = submeshMaterials; - mesh.submeshIndexCounts = submeshIndexCounts; + var mesh = new VimMesh( + indices, + vertices, + submeshIndexOffsets, + submeshMaterials + ); return mesh; } IMeshCommon IMeshCommon.Clone() => Clone(); @@ -128,6 +146,18 @@ public static VimMesh FromG3d(G3dVim g3d, int index) return mesh; } + public static VimMesh FromG3d(G3dVim g3d) + { + var mesh = new VimMesh( + g3d.Indices, + g3d.Positions, + g3d.SubmeshIndexOffsets, + g3d.SubmeshMaterials + ); + + return mesh; + } + public static VimMesh FromQuad(int[] indices, Vector3[] vertices) { if(indices.Length % 4 != 0) diff --git a/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs b/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs index e44959b1..23c3d8b0 100644 --- a/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs +++ b/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs @@ -147,6 +147,17 @@ public static void QuadToTri_IsSame() MeshesAreSame(mesh, next); } + [Test] + public static void FromG3d_Equals_ToIMesh() + { + var path = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); + var scene = VimScene.LoadVim(path); + var mesh = scene.Document.Geometry.ToIMesh(); + var next = VimMesh.FromG3d(scene.Document.GeometryNext); + MeshesAreSame(mesh, next); + + } + [Test] public static void Merge_All_IsSame() { From 745da752fd0c00299da73fc27f503617a81b3aea Mon Sep 17 00:00:00 2001 From: simon Date: Fri, 5 Apr 2024 14:31:48 -0400 Subject: [PATCH 129/204] removed unused code --- .../vim/Vim.Format.Core/Geometry/Topology.cs | 236 ------------------ 1 file changed, 236 deletions(-) delete mode 100644 src/cs/vim/Vim.Format.Core/Geometry/Topology.cs diff --git a/src/cs/vim/Vim.Format.Core/Geometry/Topology.cs b/src/cs/vim/Vim.Format.Core/Geometry/Topology.cs deleted file mode 100644 index f7ef75c5..00000000 --- a/src/cs/vim/Vim.Format.Core/Geometry/Topology.cs +++ /dev/null @@ -1,236 +0,0 @@ -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using Vim.G3d; -using Vim.LinqArray; -using Vim.Math3d; - -namespace Vim.Format.Geometry -{ - /// - /// The base class of topology face, topology edge, topology vertex, and topology element - /// - public class TopoElement - { - public TopoElement(Topology topology, int index) - => (Topology, Index) = (topology, index); - public Topology Topology { get; } - public int Index { get; } - } - - /// - /// A topological face. - /// - public class TopoFace : TopoElement - { - public TopoFace(Topology topology, int index) - : base(topology, index) - => Debug.Assert(index >= 0 && index < topology.Mesh.NumFaces); - } - - /// - /// A directed edge around a polygon (aka a half-edge). There is exactly one half-edge per "corner" in a mesh. - /// A non-border edge in a manifold mesh has exactly two half-edges, and a border edge has one edge. - /// - public class TopoEdge : TopoElement - { - public TopoEdge(Topology topology, int index) - : base(topology, index) - => Debug.Assert(index >= 0 && index < topology.Mesh.NumCorners); - } - - /// - /// A vertex in the mesh. - /// - public class TopoVertex : TopoElement - { - public TopoVertex(Topology topology, int index) - : base(topology, index) - => Debug.Assert(index >= 0 && index < topology.Mesh.NumVertices); - } - - /// - /// Also called a "face-corner". Associated with exactly one face, and one vertex. - /// A vertex may be associated with multiple corners - /// - public class TopoCorner : TopoElement - { - public TopoCorner(Topology topology, int index) - : base(topology, index) - => Debug.Assert(index >= 0 && index < topology.Mesh.NumCorners); - } - - /// - /// This class is used to make efficient topological queries for an IGeometry. - /// Construction is a O(N) operation, so it is not created automatically. - /// - public class Topology - { - public TopoFace Face(int f) - => new TopoFace(this, f); - - public TopoEdge Edge(int e) - => new TopoEdge(this, e); - - public Topology(IMesh m) - { - Mesh = m; - Corners = Mesh.Indices.Indices(); - Faces = Mesh.NumFaces.Range(); - Vertices = Mesh.Vertices.Indices(); - - // Compute the mapping from vertex indices to faces that reference them - VerticesToFaces = new List[m.Vertices.Count]; - for (var c = 0; c < m.Indices.Count; ++c) - { - var v = m.Indices[c]; - var f = m.CornerToFace(c); - - Debug.Assert(f.Within(0, m.NumFaces)); - Debug.Assert(v.Within(0, m.NumVertices)); - Debug.Assert(c.Within(0, m.NumCorners)); - - if (VerticesToFaces[v] == null) - VerticesToFaces[v] = new List { f }; - else - VerticesToFaces[v].Add(f); - } - - // NOTE: the same edge can occur in more than two faces, only in non-manifold meshes - - // Compute the face on the other side of an edge - EdgeToOtherFace = (-1).Repeat(Mesh.NumCorners).ToArray(); - for (var c = 0; c < Mesh.NumCorners; ++c) - { - var c2 = NextCorner(c); - var f0 = CornerToFace(c); - foreach (var f1 in FacesFromCorner(c).ToEnumerable()) - { - if (f1 != f0) - { - foreach (var f2 in FacesFromCorner(c2).ToEnumerable()) - { - if (f2 == f1) - { - if (EdgeToOtherFace[c] != -1) - NonManifold = true; - EdgeToOtherFace[c] = f2; - } - } - } - } - } - - // TODO: there is some serious validation I coudl be doing doing here. - } - - public IMesh Mesh { get; } - - public List[] VerticesToFaces { get; } - public int[] EdgeToOtherFace { get; } // Assumes manifold meshes - public bool NonManifold { get; } - public IArray Corners { get; } - public IArray Vertices { get; } - public IArray Edges => Corners; - public IArray Faces { get; } - - public int CornerToFace(int i) - => Mesh.CornerToFace(i); - - public IArray FacesFromVertexIndex(int v) - => VerticesToFaces[v]?.ToIArray() ?? 0.Repeat(0); - - public IArray FacesFromCorner(int c) - => FacesFromVertexIndex(Mesh.Indices[c]); - - public int VertexIndexFromCorner(int c) - => Mesh.Indices[c]; - - /// - /// Differs from neighbour faces in that the faces have to share an edge, not just a vertex. - /// An alternative construction would have been to getNeighbourFaces and filter out those that don't share - /// - public IEnumerable BorderingFacesFromFace(int f) - => EdgesFromFace(f).Select(BorderFace).Where(bf => bf >= 0); - - public int BorderFace(int e) - => EdgeToOtherFace[e]; - - public bool IsBorderEdge(int e) - => EdgeToOtherFace[e] < 0; - - public bool IsBorderFace(int f) - => EdgesFromFace(f).Any(IsBorderEdge); - - public IArray CornersFromFace(int f) - => Mesh.NumCornersPerFace.Range().Add(FirstCornerInFace(f)); - - public IArray EdgesFromFace(int f) - => CornersFromFace(f); - - public int FirstCornerInFace(int f) - => f * Mesh.NumCornersPerFace; - - public bool FaceHasCorner(int f, int c) - => CornersFromFace(f).Contains(c); - - public int NextCorner(int c) - { - var f = CornerToFace(c); - var begin = FirstCornerInFace(f); - var end = begin + Mesh.NumCornersPerFace; - Debug.Assert(c >= begin); - Debug.Assert(c < end); - var c2 = c + 1; - if (c2 < end) - return c2; - Debug.Assert(c2 == end); - return begin; - } - - public IArray CornersFromEdge(int e) - => LinqArray.LinqArray.Create(e, NextCorner(e)); - - public IArray VertexIndicesFromEdge(int e) - => CornersFromEdge(e).Select(VertexIndexFromCorner); - - public IArray VertexIndicesFromFace(int f) - => Mesh.Indices.SelectByIndex(LinqArray.LinqArray.Create(f * 3, f * 3 + 1, f * 3 + 2)); - - public IEnumerable NeighbourVertices(int v) - => FacesFromVertexIndex(v).SelectMany(f => VertexIndicesFromFace(f)).Where(v2 => v2 != v).Distinct(); - - public IEnumerable BorderEdges - => Edges.Where(IsBorderEdge); - - public IEnumerable BorderFaces - => Faces.Where(IsBorderFace); - - public int EdgeFirstCorner(int e) - => e; - - public int EdgeNextCorner(int e) - => NextCorner(e); - - public int EdgeFirstVertex(int e) - => VertexIndexFromCorner(EdgeFirstCorner(e)); - - public int EdgeNextVertex(int e) - => VertexIndexFromCorner(EdgeFirstCorner(e)); - - public IArray EdgeVertices(int e) - => LinqArray.LinqArray.Create(EdgeFirstVertex(e), EdgeNextVertex(e)); - - public Vector3 PointFromVertex(int v) - => Mesh.Vertices[v]; - - public IArray EdgePoints(int e) - => EdgeVertices(e).Select(PointFromVertex); - } - - public static class TopologyExtensions - { - public static IMesh Mesh(this TopoElement self) - => self.Topology.Mesh; - } -} From 66df4c71ecda18f065345eba263611835d1e144f Mon Sep 17 00:00:00 2001 From: simon Date: Fri, 5 Apr 2024 14:35:32 -0400 Subject: [PATCH 130/204] removed redundant check --- src/cs/vim/Vim.Format/SceneBuilder/Validation.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs b/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs index ddf0713f..282ad544 100644 --- a/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs +++ b/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs @@ -229,9 +229,6 @@ public static void ValidateEquality(this DocumentBuilder db, VimScene vim) { 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.Geometry.GetMesh(i).ToIMesh().GeometryEquals(vim.MeshesOld[i])) - throw new VimValidationException($"{nameof(DocumentBuilder)} mesh {i} geometry is not equal to {nameof(VimScene)} mesh {i}"); } // Test the assets. From c464aae6e66ff580b1c90b5ec2a09714a73e4d42 Mon Sep 17 00:00:00 2001 From: simon Date: Fri, 5 Apr 2024 14:37:02 -0400 Subject: [PATCH 131/204] remove unused code --- .../vim/Vim.Format.Core/DocumentBuilderExtensions.cs | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/cs/vim/Vim.Format.Core/DocumentBuilderExtensions.cs b/src/cs/vim/Vim.Format.Core/DocumentBuilderExtensions.cs index 9ffdd818..abdfeb48 100644 --- a/src/cs/vim/Vim.Format.Core/DocumentBuilderExtensions.cs +++ b/src/cs/vim/Vim.Format.Core/DocumentBuilderExtensions.cs @@ -10,11 +10,6 @@ namespace Vim.Format { public static class DocumentBuilderExtensions { - public static IMesh ToIMesh(this SubdividedMesh gb) - => gb.Vertices.ToIArray().TriMesh( - gb.Indices.ToIArray(), - submeshMaterials: gb.SubmeshMaterials.ToIArray()); - public static Material ToDocumentBuilderMaterial(this G3dMaterial g3dMaterial) => new Material { @@ -23,13 +18,6 @@ public static Material ToDocumentBuilderMaterial(this G3dMaterial g3dMaterial) Smoothness = g3dMaterial.Smoothness, }; - public static SubdividedMesh ToDocumentBuilderSubdividedMesh(this IMesh m) - => new SubdividedMesh( - m.Indices.ToList(), - m.Vertices.ToList(), - m.SubmeshIndexOffsets.ToList(), - m.SubmeshMaterials.ToList()); - public static SubdividedMesh ToDocumentBuilderSubdividedMesh(this IMeshCommon m) => new SubdividedMesh( m.Indices.ToList(), From 5db4640a8161bd04f2809ff15dcbde84f60c3265 Mon Sep 17 00:00:00 2001 From: simon Date: Fri, 5 Apr 2024 14:40:06 -0400 Subject: [PATCH 132/204] imesh -> imeshcommon --- .../vim/Vim.Format.Core/Geometry/CatmullClark.cs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/cs/vim/Vim.Format.Core/Geometry/CatmullClark.cs b/src/cs/vim/Vim.Format.Core/Geometry/CatmullClark.cs index 4ffbd54a..2f0da338 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/CatmullClark.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/CatmullClark.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using Vim.G3d; using Vim.LinqArray; using Vim.Math3d; @@ -39,7 +40,7 @@ public class GeometryEdge public static class CatmullClarkSmoothing { - public static Dictionary CreateEdgeMap(this IMesh geometry) + public static Dictionary CreateEdgeMap(this IMeshCommon geometry) { var globalEdgeIndex = 0; var edgeMap = new Dictionary(); @@ -68,7 +69,7 @@ public static Dictionary CreateEdgeMap(this IMesh return edgeMap; } - public static IMesh CatmullClark(this IMesh geometry, float smoothing = 0.0f) + public static IMeshCommon CatmullClark(this IMeshCommon geometry, float smoothing = 0.0f) { var edgeMap = geometry.CreateEdgeMap(); @@ -129,7 +130,7 @@ public static IMesh CatmullClark(this IMesh geometry, float smoothing = 0.0f) return GenerateMesh(geometry, newVertices, newIndices, edgeMap, facePointStartIndex, edgePointStartIndex, numQuads); } - public static void CalculateFaceCentroidPoints(IMesh geometry, Vector3[] outFacePoints, float[] outVertexNumFaces, Vector3[] outVertexFPoints) + public static void CalculateFaceCentroidPoints(IMeshCommon geometry, Vector3[] outFacePoints, float[] outVertexNumFaces, Vector3[] outVertexFPoints) { var currentVertexIndex = 0; for (var faceIndex = 0; faceIndex < geometry.NumFaces; faceIndex++) @@ -159,7 +160,7 @@ public static void CalculateFaceCentroidPoints(IMesh geometry, Vector3[] outFace } } - public static void CalculateEdgePoints(IMesh geometry, Dictionary edgeMap, Vector3[] facePoints, float[] outVertexNumEdges, Vector3[] outVertexRPoints, float smoothing) + public static void CalculateEdgePoints(IMeshCommon geometry, Dictionary edgeMap, Vector3[] facePoints, float[] outVertexNumEdges, Vector3[] outVertexRPoints, float smoothing) { foreach (var edge in edgeMap) { @@ -186,7 +187,7 @@ public static void CalculateEdgePoints(IMesh geometry, Dictionary edgeMap, int facePointStartIndex, int edgePointStartIndex, int numQuads) + public static IMeshCommon GenerateMesh(IMeshCommon geometry, Vector3[] newVertices, int[] newIndices, Dictionary edgeMap, int facePointStartIndex, int edgePointStartIndex, int numQuads) { var currentNewVertexIndex = 0; var currentOldVertexIndex = 0; @@ -224,7 +225,7 @@ public static IMesh GenerateMesh(IMesh geometry, Vector3[] newVertices, int[] ne currentOldVertexIndex += faceSize; } - return Primitives.QuadMesh(newVertices.ToIArray(), newIndices.ToIArray()); + return new VimMesh(newIndices, newVertices); } } } From a6c08b3e312c9868e40f22c049889faee6fb5f6e Mon Sep 17 00:00:00 2001 From: simon Date: Fri, 5 Apr 2024 14:44:53 -0400 Subject: [PATCH 133/204] removed old imesh version of meshhash --- .../Geometry/MeshOptimization.cs | 53 ------------------- 1 file changed, 53 deletions(-) diff --git a/src/cs/vim/Vim.Format.Core/Geometry/MeshOptimization.cs b/src/cs/vim/Vim.Format.Core/Geometry/MeshOptimization.cs index a7a4691e..5e858acb 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/MeshOptimization.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/MeshOptimization.cs @@ -7,56 +7,6 @@ using Vim.Math3d; namespace Vim.Format.Geometry -{ - /// - /// This class is used to compare quickly two meshes within a lookup table (e.g. Dictionary, HashTable). - /// it looks at the positions of each corner, and the number of faces, and assures that the object ID - /// and material IDs are the same. - /// When using a class within a dictionary or hash table, the equals operator is called frequently. - /// By converting an IMesh to a MeshHash we minimize the amount of comparisons done. It becomes - /// possible, but highly unlikely that two different meshes would have the same hash. - /// - public class MeshHash - { - public IMesh Mesh; - public float Tolerance; - public int NumFaces; - public int NumVertices; - public int TopologyHash; - public Int3 BoxExtents; - public Int3 BoxMin; - - public int Round(float f) - => (int)(f / Tolerance); - - public Int3 Round(Vector3 v) - => new Int3(Round(v.X), Round(v.Y), Round(v.Z)); - - public MeshHash(IMesh mesh, float tolerance) - { - Mesh = mesh; - Tolerance = tolerance; - NumFaces = mesh.NumFaces; - NumVertices = mesh.NumVertices; - TopologyHash = Hash.Combine(mesh.Indices.ToArray()); - var box = mesh.BoundingBox(); - BoxMin = Round(box.Min); - BoxExtents = Round(box.Extent); - } - - public override bool Equals(object obj) - => obj is MeshHash other && Equals(other); - - public bool Equals(MeshHash other) - => NumFaces == other.NumFaces - && NumVertices == other.NumVertices - && BoxMin.Equals(other.BoxMin) - && BoxExtents.Equals(other.BoxExtents) - && Mesh.GeometryEquals(other.Mesh); - - public override int GetHashCode() - => Hash.Combine(NumFaces, NumVertices, TopologyHash, BoxMin.GetHashCode(), BoxExtents.GetHashCode()); - } /// /// This class is used to compare quickly two meshes within a lookup table (e.g. Dictionary, HashTable). @@ -110,9 +60,6 @@ public override int GetHashCode() public static class Optimization { - public static Dictionary> GroupMeshesByHash(this IEnumerable meshes, float tolerance) - => meshes.AsParallel().GroupBy(m => new MeshHash(m, tolerance)).ToDictionary(grp => grp.Key, grp => grp.ToList()); - public static Dictionary> GroupMeshesByHash(this IEnumerable meshes, float tolerance) => meshes.AsParallel().GroupBy(m => new MeshCommonHash(m, tolerance)).ToDictionary(grp => grp.Key, grp => grp.ToList()); } From 07019fccf7056226093307e31a23565cd36e0161 Mon Sep 17 00:00:00 2001 From: simon Date: Fri, 5 Apr 2024 14:45:03 -0400 Subject: [PATCH 134/204] imesh -> imeshcommon --- .../vim/Vim.Format.Core/Geometry/PerimeterProjection.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/cs/vim/Vim.Format.Core/Geometry/PerimeterProjection.cs b/src/cs/vim/Vim.Format.Core/Geometry/PerimeterProjection.cs index 9d249161..d232a460 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/PerimeterProjection.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/PerimeterProjection.cs @@ -2,16 +2,16 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; -using Vim.Util; using Vim.LinqArray; using Vim.Math3d; +using Vim.G3d; namespace Vim.Format.Geometry { public static class PerimeterProjection { - public static List> GeneratePerimeter(this IMesh mesh, Vector3 planeNormal, float degenerateSegmentEpsilon = 10.0f, float edgeLoopThreshold = 1e-6f) + public static List> GeneratePerimeter(this IMeshCommon mesh, Vector3 planeNormal, float degenerateSegmentEpsilon = 10.0f, float edgeLoopThreshold = 1e-6f) { var q = GetClusterRotation(planeNormal.Normalize(), Vector3.UnitZ); @@ -307,7 +307,7 @@ public int GetHashCode(Tuple obj) => obj.Item1.GetHashCode() ^ obj.Item2.GetHashCode(); } - public static Dictionary, int> BuildEdgeDictionary(this IMesh mesh) + public static Dictionary, int> BuildEdgeDictionary(this IMeshCommon mesh) { var edges = new Dictionary, int>(new EdgeEqualityComparer()); @@ -327,7 +327,7 @@ public static Dictionary, int> BuildEdgeDictionary(this IMesh me return edges; } - public static List> BuildBoundarySegments(this IMesh mesh, Dictionary, int> edgeDictionary, Func transform) + public static List> BuildBoundarySegments(this IMeshCommon mesh, Dictionary, int> edgeDictionary, Func transform) { var segments = new List>(); From 17f488e8bd8c0fa89262bc91de06716d49caf041 Mon Sep 17 00:00:00 2001 From: simon Date: Fri, 5 Apr 2024 14:46:53 -0400 Subject: [PATCH 135/204] minor mistakes --- src/cs/vim/Vim.Format.Core/Geometry/MeshOptimization.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/cs/vim/Vim.Format.Core/Geometry/MeshOptimization.cs b/src/cs/vim/Vim.Format.Core/Geometry/MeshOptimization.cs index 5e858acb..fac1c90b 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/MeshOptimization.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/MeshOptimization.cs @@ -1,12 +1,11 @@ using System.Collections.Generic; -using System.Diagnostics; using System.Linq; -using System.Runtime.CompilerServices; using Vim.G3d; using Vim.LinqArray; using Vim.Math3d; namespace Vim.Format.Geometry +{ /// /// This class is used to compare quickly two meshes within a lookup table (e.g. Dictionary, HashTable). @@ -45,7 +44,7 @@ public MeshCommonHash(IMeshCommon mesh, float tolerance) } public override bool Equals(object obj) - => obj is MeshHash other && Equals(other); + => obj is MeshCommonHash other && Equals(other); public bool Equals(MeshCommonHash other) => NumFaces == other.NumFaces From 8e0419fbbd80ec6767944f604d7900a79e068820 Mon Sep 17 00:00:00 2001 From: simon Date: Fri, 5 Apr 2024 14:47:51 -0400 Subject: [PATCH 136/204] removed unused file --- .../Vim.Format.Core/Geometry/MeshDebugView.cs | 21 ------------------- 1 file changed, 21 deletions(-) delete mode 100644 src/cs/vim/Vim.Format.Core/Geometry/MeshDebugView.cs diff --git a/src/cs/vim/Vim.Format.Core/Geometry/MeshDebugView.cs b/src/cs/vim/Vim.Format.Core/Geometry/MeshDebugView.cs deleted file mode 100644 index 54a216e3..00000000 --- a/src/cs/vim/Vim.Format.Core/Geometry/MeshDebugView.cs +++ /dev/null @@ -1,21 +0,0 @@ -using Vim.LinqArray; -using Vim.Math3d; - -namespace Vim.Format.Geometry -{ - public class MeshDebugView - { - IMesh Interface { get; } - - public int NumCorners => Interface.NumCorners; - public int NumFaces => Interface.NumFaces; - public int NumMeshes => Interface.NumMeshes; - public int NumInstances => Interface.NumInstances; - - public Vector3[] Vertices => Interface.Vertices.ToArray(); - public int[] Indices => Interface.Indices.ToArray(); - - public MeshDebugView(IMesh g) - => Interface = g; - } -} From 54abe40d184e3fa603b4ce7d50b9bc17fc4f4776 Mon Sep 17 00:00:00 2001 From: simon Date: Fri, 5 Apr 2024 16:57:02 -0400 Subject: [PATCH 137/204] replacing more Imesh --- src/cs/g3d/Vim.G3dNext/G3dVim.cs | 5 +- .../Vim.Format.Core/Geometry/Primitives.cs | 201 +++++++----------- .../Vim.Format.Core/Geometry/Validation.cs | 4 +- .../vim/Vim.Format.Core/Geometry/VimMesh.cs | 40 ++++ .../Geometry/GeometryTests.cs | 163 +++++--------- .../SerializableDocumentTests.cs | 20 -- .../vim/Vim.Format/SceneBuilder/Validation.cs | 7 +- .../vim/Vim.Format/SceneBuilder/VimScene.cs | 14 -- 8 files changed, 174 insertions(+), 280 deletions(-) diff --git a/src/cs/g3d/Vim.G3dNext/G3dVim.cs b/src/cs/g3d/Vim.G3dNext/G3dVim.cs index c0ddeb67..dd2af2c6 100644 --- a/src/cs/g3d/Vim.G3dNext/G3dVim.cs +++ b/src/cs/g3d/Vim.G3dNext/G3dVim.cs @@ -1,19 +1,16 @@ using System; using System.Collections.Generic; -using System.Linq; using Vim.BFastLib; -using Vim.Math3d; namespace Vim.G3dNext { public partial class G3dVim { + // Computed field public int[] MeshVertexOffsets; private List[] _meshInstances; - - public IReadOnlyList GetMeshInstances(int mesh) { return _meshInstances[mesh]; diff --git a/src/cs/vim/Vim.Format.Core/Geometry/Primitives.cs b/src/cs/vim/Vim.Format.Core/Geometry/Primitives.cs index 570d9dda..a0c737d8 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/Primitives.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/Primitives.cs @@ -10,129 +10,77 @@ namespace Vim.Format.Geometry // TODO: plane, cylinder, cone, ruled face, public static class Primitives { - public static IMesh TriMesh(IEnumerable attributes) - => attributes.Where(x => x != null).ToIMesh(); - - public static IMesh TriMesh(params GeometryAttribute[] attributes) - => TriMesh(attributes.AsEnumerable()); - - public static IMesh TriMesh( - this IArray vertices, - IArray indices = null, - IArray uvs = null, - IArray colors = null, - IArray materials = null, - IArray submeshMaterials = null) - => TriMesh( - vertices?.ToPositionAttribute(), - indices?.ToIndexAttribute(), - uvs?.ToVertexUvAttribute(), - materials?.ToFaceMaterialAttribute(), - colors?.ToVertexColorAttribute(), - submeshMaterials?.ToSubmeshMaterialAttribute() - ); - - public static IMesh TriMesh(this IArray vertices, IArray indices = null, params GeometryAttribute[] attributes) - => new GeometryAttribute[] { - vertices?.ToPositionAttribute(), - indices?.ToIndexAttribute(), - }.Concat(attributes).ToIMesh(); - - public static IMesh QuadMesh(params GeometryAttribute[] attributes) - => QuadMesh(attributes.AsEnumerable()); - - public static IMesh QuadMesh(this IEnumerable attributes) - => new QuadMesh(attributes.Where(x => x != null)).ToTriMesh(); - - public static IMesh QuadMesh(this IArray vertices, IArray indices = null, IArray uvs = null, IArray materials = null, IArray objectIds = null) - => QuadMesh( - vertices.ToPositionAttribute(), - indices?.ToIndexAttribute(), - uvs?.ToVertexUvAttribute(), - materials?.ToFaceMaterialAttribute(), - (new int[] {0}).ToSubmeshIndexOffsetAttribute(), - (new int[] { -1 }).ToSubmeshMaterialAttribute() - ); - - public static IMesh QuadMesh(Vector3 a, Vector3 b, Vector3 c, Vector3 d) - => QuadMesh(new[] { a, b, c, d }.ToIArray()); - - public static IMesh Cube + public static IMeshCommon CreateCube() { - get - { - var vertices = new[] { - // front - new Vector3(-0.5f, -0.5f, 0.5f), - new Vector3(0.5f, -0.5f, 0.5f), - new Vector3(0.5f, 0.5f, 0.5f), - new Vector3(-0.5f, 0.5f, 0.5f), - // back - new Vector3(-0.5f, -0.5f, -0.5f), - new Vector3(0.5f, -0.5f, -0.5f), - new Vector3(0.5f, 0.5f, -0.5f), - new Vector3(-0.5f, 0.5f, -0.5f) - }.ToIArray(); - - var indices = new[] { - // front - 0, 1, 2, - 2, 3, 0, - // right - 1, 5, 6, - 6, 2, 1, - // back - 7, 6, 5, - 5, 4, 7, - // left - 4, 0, 3, - 3, 7, 4, - // bottom - 4, 5, 1, - 1, 0, 4, - // top - 3, 2, 6, - 6, 7, 3 - }.ToIArray(); - - return vertices.TriMesh(indices); - } + var vertices = new[] { + // front + new Vector3(-0.5f, -0.5f, 0.5f), + new Vector3(0.5f, -0.5f, 0.5f), + new Vector3(0.5f, 0.5f, 0.5f), + new Vector3(-0.5f, 0.5f, 0.5f), + // back + new Vector3(-0.5f, -0.5f, -0.5f), + new Vector3(0.5f, -0.5f, -0.5f), + new Vector3(0.5f, 0.5f, -0.5f), + new Vector3(-0.5f, 0.5f, -0.5f) + }; + + var indices = new[] { + // front + 0, 1, 2, + 2, 3, 0, + // right + 1, 5, 6, + 6, 2, 1, + // back + 7, 6, 5, + 5, 4, 7, + // left + 4, 0, 3, + 3, 7, 4, + // bottom + 4, 5, 1, + 1, 0, 4, + // top + 3, 2, 6, + 6, 7, 3 + }; + + return new VimMesh(indices, vertices); } - public static IMesh CubeFaceted + public static IMeshCommon CreateCube(AABox box) { - get - { - var cube = Cube; - return cube.Indices.Select(i => cube.Vertices[i]).TriMesh(cube.Indices.Count.Range()); - } + return CreateCube().Scale(box.Extent).Translate(box.Center); } - public static IMesh ToIMesh(this AABox box) - => Cube.Scale(box.Extent).Translate(box.Center); - - public static float Sqrt2 = 2.0f.Sqrt(); - - public static readonly IMesh Tetrahedron - = TriMesh(LinqArray.LinqArray.Create( + private static float Sqrt2 = 2.0f.Sqrt(); + public static IMeshCommon CreateTetrahedron() + { + var vertices = new[] + { new Vector3(1f, 0.0f, -1f / Sqrt2), new Vector3(-1f, 0.0f, -1f / Sqrt2), new Vector3(0.0f, 1f, 1f / Sqrt2), - new Vector3(0.0f, -1f, 1f / Sqrt2)), - LinqArray.LinqArray.Create(0, 1, 2, 1, 0, 3, 0, 2, 3, 1, 3, 2)); - - public static readonly IMesh Square - = LinqArray.LinqArray.Create( - new Vector2(-0.5f, -0.5f), - new Vector2(-0.5f, 0.5f), - new Vector2(0.5f, 0.5f), - new Vector2(0.5f, -0.5f)).Select(x => x.ToVector3()).QuadMesh(); - - public static readonly IMesh Octahedron - = Square.Vertices.Append(Vector3.UnitZ, -Vector3.UnitZ).Normalize().TriMesh( - LinqArray.LinqArray.Create( - 0, 1, 4, 1, 2, 4, 2, 3, 4, - 3, 2, 5, 2, 1, 5, 1, 0, 5)); + new Vector3(0.0f, -1f, 1f / Sqrt2) + }; + var indices = new[] { 0, 1, 2, 1, 0, 3, 0, 2, 3, 1, 3, 2 }; + return new VimMesh(indices, vertices); + } + public static IMeshCommon CreateSquare() + { + var vertices = new[] + { + new Vector3(-0.5f, -0.5f, 0f), + new Vector3(-0.5f, 0.5f, 0f), + new Vector3(0.5f, 0.5f, 0f), + new Vector3(0.5f, -0.5f, 0f) + }; + + var indices = new[] { 0, 1, 2, 2, 3, 0 }; + + return new VimMesh(indices, vertices); + } // see: https://github.com/mrdoob/three.js/blob/9ef27d1af7809fa4d9943f8d4c4644e365ab6d2d/src/geometries/TorusBufferGeometry.js#L52 public static Vector3 TorusFunction(Vector2 uv, float radius, float tube) @@ -144,7 +92,7 @@ public static Vector3 TorusFunction(Vector2 uv, float radius, float tube) tube * uv.Y.Sin()); } - public static IMesh Torus(float radius, float tubeRadius, int uSegs, int vSegs) + public static IMeshCommon Torus(float radius, float tubeRadius, int uSegs, int vSegs) => QuadMesh(uv => TorusFunction(uv, radius, tubeRadius), uSegs, vSegs); // see: https://github.com/mrdoob/three.js/blob/9ef27d1af7809fa4d9943f8d4c4644e365ab6d2d/src/geometries/SphereBufferGeometry.js#L76 @@ -154,17 +102,9 @@ public static Vector3 SphereFunction(Vector2 uv, float radius) (float)(radius * Math.Cos(uv.Y * Math3d.Constants.Pi)), (float)(radius * Math.Sin(uv.X * Math3d.Constants.TwoPi) * Math.Sin(uv.Y * Math3d.Constants.Pi))); - public static IMesh Sphere(float radius, int uSegs, int vSegs) + public static IMeshCommon Sphere(float radius, int uSegs, int vSegs) => QuadMesh(uv => SphereFunction(uv, radius), uSegs, vSegs); - /// - /// Creates a TriMesh from four points. - /// - public static IMesh TriMeshFromQuad(Vector3 a, Vector3 b, Vector3 c, Vector3 d) - => TriMesh(new[] { a, b, c, c, d, a }.ToIArray()); - - // Icosahedron, Dodecahedron, - /// /// Returns a collection of circular points. /// @@ -316,13 +256,13 @@ public static IArray TriMeshCylinderCapIndices(int numEdgeVertices) /// /// Creates a quad mesh given a mapping from 2 space to 3 space /// - public static IMesh QuadMesh(this Func f, int segs) + public static IMeshCommon QuadMesh(this Func f, int segs) => QuadMesh(f, segs, segs); /// /// Creates a quad mesh given a mapping from 2 space to 3 space /// - public static IMesh QuadMesh(this Func f, int usegs, int vsegs, bool wrapUSegs = false, bool wrapVSegs = false) + public static IMeshCommon QuadMesh(this Func f, int usegs, int vsegs, bool wrapUSegs = false, bool wrapVSegs = false) { var verts = new List(); var maxUSegs = wrapUSegs ? usegs : usegs + 1; @@ -337,14 +277,15 @@ public static IMesh QuadMesh(this Func f, int usegs, int vsegs verts.Add(f(new Vector2(u, v))); } } + var indices = ComputeQuadMeshStripIndices(usegs, vsegs, wrapUSegs, wrapVSegs); - return QuadMesh(verts.ToIArray(), ComputeQuadMeshStripIndices(usegs, vsegs, wrapUSegs, wrapVSegs)); + return VimMesh.FromQuad(indices.ToArray(), verts.ToArray()); } /// /// Creates a revolved face ... note that the last points are on top of the original /// - public static IMesh RevolveAroundAxis(this IArray points, Vector3 axis, int segments = 4) + public static IMeshCommon RevolveAroundAxis(this IArray points, Vector3 axis, int segments = 4) { var verts = new List(); for (var i = 0; i < segments; ++i) @@ -352,8 +293,8 @@ public static IMesh RevolveAroundAxis(this IArray points, Vector3 axis, var angle = Math3d.Constants.TwoPi / segments; points.Rotate(axis, angle).AddTo(verts); } - - return QuadMesh(verts.ToIArray(), ComputeQuadMeshStripIndices(segments - 1, points.Count - 1)); + var indices = ComputeQuadMeshStripIndices(segments - 1, points.Count - 1); + return new VimMesh(indices.ToArray(), verts.ToArray()); } } } diff --git a/src/cs/vim/Vim.Format.Core/Geometry/Validation.cs b/src/cs/vim/Vim.Format.Core/Geometry/Validation.cs index abf23eef..ef12f052 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/Validation.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/Validation.cs @@ -89,7 +89,7 @@ public static void Validate(this Document doc) // TODO: ValidateShapes() to validate VIM files which contain optional 2d data (shapes/overlays). - public static void ValidateIndices(this IMesh mesh) + public static void ValidateIndices(this IMeshCommon mesh) { foreach (var index in mesh.Indices.ToEnumerable()) { @@ -98,7 +98,7 @@ public static void ValidateIndices(this IMesh mesh) } } - public static void Validate(this IMesh mesh) + public static void Validate(this IMeshCommon mesh) { mesh.ValidateIndices(); } diff --git a/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs b/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs index aaac9cf3..25b5414b 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs @@ -62,6 +62,27 @@ public VimMesh( this.submeshIndexCounts = submeshIndexCounts ?? ComputeCounts(this.submeshIndexOffsets, this.indices.Length); } + public G3dVim ToG3d() + { + return new G3dVim( + indices: indices, + positions: vertices, + instanceMeshes: new[] {0}, + instanceTransforms: new[] { Matrix4x4.Identity }, + instanceParents: null, + instanceFlags: null, + meshSubmeshOffsets: new[] { 0 }, + submeshIndexOffsets: new[] { 0 }, + submeshMaterials: new[] { -1 }, + materialColors: null, + materialGlossiness: null, + materialSmoothness: null, + shapeVertices: null, + shapeColors: null, + shapeVertexOffsets: null, + shapeWidths: null); + } + private static int[] ComputeCounts(int[] offsets, int max) { var result = new int[offsets.Length]; @@ -298,6 +319,25 @@ public static (int, List)[] GroupSubmeshesByMaterials(this IMeshCommon mesh return map.Select(kvp => (kvp.Key, kvp.Value)).ToArray(); } + public static Triangle VertexIndicesToTriangle(this IMeshCommon mesh, Int3 indices) + => new Triangle(mesh.Vertices[indices.X], mesh.Vertices[indices.Y], mesh.Vertices[indices.Z]); + + public static bool Planar(this IMeshCommon mesh, float tolerance = Math3d.Constants.Tolerance) + { + if (mesh.NumFaces <= 1) return true; + var normal = mesh.Triangle(0).Normal; + return mesh.ComputedNormals().All(n => n.AlmostEquals(normal, tolerance)); + } + + public static IArray ComputedNormals(this IMeshCommon mesh) + => mesh.Triangles().Select(t => t.Normal); + + public static Triangle Triangle(this IMeshCommon mesh, int face) + => mesh.VertexIndicesToTriangle(mesh.FaceVertexIndices(face)); + + public static IArray Triangles(this IMeshCommon mesh) + => mesh.NumFaces.Select(mesh.Triangle); + public static Vector3 Center(this IMeshCommon mesh) => mesh.BoundingBox().Center; diff --git a/src/cs/vim/Vim.Format.Tests/Geometry/GeometryTests.cs b/src/cs/vim/Vim.Format.Tests/Geometry/GeometryTests.cs index 5eb5ea40..13092f28 100644 --- a/src/cs/vim/Vim.Format.Tests/Geometry/GeometryTests.cs +++ b/src/cs/vim/Vim.Format.Tests/Geometry/GeometryTests.cs @@ -3,6 +3,7 @@ using NUnit.Framework; using Vim.Format.Geometry; using Vim.G3d; +using Vim.G3dNext; using Vim.LinqArray; using Vim.Math3d; @@ -10,26 +11,41 @@ namespace Vim.Format.Tests.Geometry { public static class GeometryTests { - public static IMesh XYTriangle = new[] { new Vector3(0f, 0f, 0f), new Vector3(0f, 1f, 0f), new Vector3(1f, 0f, 0f) }.ToIArray().TriMesh(3.Range()); - public static IMesh XYQuad = new[] { new Vector3(0f, 0f, 0f), new Vector3(0f, 1f, 0f), new Vector3(1f, 1f, 0f), new Vector3(1f, 0f, 0f) }.ToIArray().QuadMesh(4.Range()); - public static IMesh XYQuadFromFunc = Primitives.QuadMesh(uv => uv.ToVector3(), 1, 1); - public static IMesh XYQuad2x2 = Primitives.QuadMesh(uv => uv.ToVector3(), 2, 2); - public static IMesh XYTriangleTwice = XYTriangle.Merge(XYTriangle.Translate(new Vector3(1, 0, 0))); - - public static readonly Vector3[] TestTetrahedronVertices = { Vector3.Zero, Vector3.UnitX, Vector3.UnitY, Vector3.UnitZ }; - public static readonly int[] TestTetrahedronIndices = { 0, 1, 2, 0, 3, 1, 1, 3, 2, 2, 3, 0 }; - - public static IMesh Tetrahedron = - TestTetrahedronVertices.ToIArray().TriMesh(TestTetrahedronIndices.ToIArray()); - - public static IMesh Torus = Primitives.Torus(10, 0.2f, 10, 24); - - static IMesh RevolvedVerticalCylinder(float height, float radius, int verticalSegments, int radialSegments) + public static IMeshCommon XYTriangle = new VimMesh( + new[] { 0, 1, 2 }, new[] { + new Vector3(0f, 0f, 0f), + new Vector3(0f, 1f, 0f), + new Vector3(1f, 0f, 0f) + }); + + public static IMeshCommon XYQuad = VimMesh.FromQuad( + new int[] { 0, 1, 2, 3 }, new[]{ + new Vector3(0f, 0f, 0f), + new Vector3(0f, 1f, 0f), + new Vector3(1f, 1f, 0f), + new Vector3(1f, 0f, 0f) + }); + + public static IMeshCommon XYQuadFromFunc = Primitives.QuadMesh(uv => uv.ToVector3(), 1, 1); + public static IMeshCommon XYQuad2x2 = Primitives.QuadMesh(uv => uv.ToVector3(), 2, 2); + public static IMeshCommon XYTriangleTwice = XYTriangle.Merge2(XYTriangle.Translate(new Vector3(1, 0, 0))); + + public static IMeshCommon Tetrahedron = new VimMesh( + new[] { 0, 1, 2, 0, 3, 1, 1, 3, 2, 2, 3, 0 }, new[] { + Vector3.Zero, + Vector3.UnitX, + Vector3.UnitY, + Vector3.UnitZ + }); + + public static IMeshCommon Torus = Primitives.Torus(10, 0.2f, 10, 24); + + static IMeshCommon RevolvedVerticalCylinder(float height, float radius, int verticalSegments, int radialSegments) => (Vector3.UnitZ * height).ToLine().Interpolate(verticalSegments).Add(-radius.AlongX()).RevolveAroundAxis(Vector3.UnitZ, radialSegments); - public static IMesh Cylinder = RevolvedVerticalCylinder(5, 1, 4, 12); + public static IMeshCommon Cylinder = RevolvedVerticalCylinder(5, 1, 4, 12); - public static IMesh[] AllMeshes = { + public static IMeshCommon[] AllMeshes = { XYTriangle, // 0 XYQuad, // 1 XYQuadFromFunc, // 2 @@ -44,6 +60,7 @@ static IMesh RevolvedVerticalCylinder(float height, float radius, int verticalSe public static void AssertEquals(IMesh g1, IMesh g2) { + Assert.AreEqual(g1.NumFaces, g2.NumFaces); Assert.AreEqual(g1.NumCorners, g2.NumCorners); Assert.AreEqual(g1.NumVertices, g2.NumVertices); @@ -55,65 +72,14 @@ public static void AssertEquals(IMesh g1, IMesh g2) } } - public static void AssertEqualsWithAttributes(IMesh g1, IMesh g2) - { - AssertEquals(g1, g2); - - Assert.AreEqual( - g1.Attributes.Select(attr => attr.Name).ToArray(), - g2.Attributes.Select(attr => attr.Name).ToArray()); - - Assert.AreEqual( - g1.Attributes.Select(attr => attr.ElementCount).ToArray(), - g2.Attributes.Select(attr => attr.ElementCount).ToArray()); - } - - public static void OutputTriangleStats(Triangle t) + public static void GeometryNullOps(IMeshCommon g) { - Console.WriteLine($"Vertices: {t.A} {t.B} {t.C}"); - Console.WriteLine($"Area: {t.Area} Perimeter: {t.Perimeter} Midpoint: {t.MidPoint}"); - Console.WriteLine($"Bounding box: {t.BoundingBox}"); - Console.WriteLine($"Bounding sphere: {t.BoundingSphere}"); - Console.WriteLine($"Normal: {t.Normal}, normal direction {t.NormalDirection}"); - Console.WriteLine($"Lengths: {t.LengthA} {t.LengthB} {t.LengthC}"); + g.GeometryEquals(g); + g.Translate(Vector3.Zero).GeometryEquals(g); + g.Scale(Vector3.Zero).GeometryEquals(g); + g.Transform(Matrix4x4.Identity).GeometryEquals(g); } - public static void OutputTriangleStatsSummary(IMesh g) - { - var triangles = g.Triangles(); - for (var i = 0; i < Math.Min(3, triangles.Count); ++i) - { - Console.WriteLine($"Triangle {i}"); - OutputTriangleStats(triangles[i]); - } - - if (triangles.Count > 3) - { - Console.WriteLine("..."); - Console.WriteLine($"Triangle {triangles.Count - 1}"); - OutputTriangleStats(triangles.Last()); - } - } - - public static void OutputIMeshStats(IMesh g) - { - g.Validate(); - foreach (var attr in g.Attributes.ToEnumerable()) - Console.WriteLine($"{attr.Descriptor} elementCount={attr.ElementCount}"); - } - - public static void GeometryNullOps(IMesh g) - { - AssertEqualsWithAttributes(g, g); - AssertEqualsWithAttributes(g, g.Attributes.ToIMesh()); - AssertEqualsWithAttributes(g, g.Translate(Vector3.Zero)); - AssertEqualsWithAttributes(g, g.Scale(1.0f)); - AssertEqualsWithAttributes(g, g.Transform(Matrix4x4.Identity)); - - AssertEquals(g, g.CopyFaces(0, g.NumFaces).ToIMesh()); - } - - [Test] public static void BasicTests() { @@ -155,7 +121,6 @@ public static void BasicTests() Assert.AreEqual(4, Tetrahedron.NumFaces); Assert.AreEqual(4, Tetrahedron.Vertices.Count); Assert.AreEqual(12, Tetrahedron.Indices.Count); - Assert.AreEqual(TestTetrahedronIndices, Tetrahedron.Indices.ToArray()); Assert.AreEqual(3, XYTriangleTwice.NumCornersPerFace); Assert.AreEqual(2, XYTriangleTwice.NumFaces); @@ -277,40 +242,30 @@ public static void StripIndicesTests() [Test] public static void TriangleSerializationTest() { - // Serialize a triangle g3d to a bfast as bytes and read it back. - var vertices = new[] + //TODO: Check the need for this test. + // Serializing a triangle is that a use case ? + + var mesh = new VimMesh(new [] { 0, 1, 2 }, new[] { new Vector3(0, 0, 0), new Vector3(0, 1, 0), new Vector3(0, 1, 1) - }; - - var indices = new[] { 0, 1, 2 }; - var submeshIndexOffsets = new[] { 0 }; - var submeshMaterials = new[] { 0 }; - - var g3d = new G3DBuilder() - .AddVertices(vertices.ToIArray()) - .AddIndices(indices.ToIArray()) - .Add(submeshIndexOffsets.ToIArray().ToSubmeshIndexOffsetAttribute()) - .Add(submeshMaterials.ToIArray().ToSubmeshMaterialAttribute()) - .ToG3D(); - - var bfast = g3d.ToBFast(); - var readG3d = G3D.Read(bfast); - - Assert.IsNotNull(readG3d); - var mesh = readG3d.ToIMesh(); - mesh.Validate(); - - Assert.AreEqual(3, mesh.NumVertices); - Assert.AreEqual(new Vector3(0, 0, 0), mesh.Vertices[0]); - Assert.AreEqual(new Vector3(0, 1, 0), mesh.Vertices[1]); - Assert.AreEqual(new Vector3(0, 1, 1), mesh.Vertices[2]); - Assert.AreEqual(1, mesh.NumFaces); - Assert.AreEqual(0, mesh.SubmeshIndexOffsets.ToEnumerable().Single()); - Assert.AreEqual(0, mesh.SubmeshMaterials.ToEnumerable().Single()); - Assert.AreEqual(0, mesh.GetFaceMaterials().First()); + }); + + var bfast = mesh.ToG3d().ToBFast(); + var result = VimMesh.FromG3d(new G3dVim(bfast)); + + Assert.IsNotNull(mesh); + result.Validate(); + + Assert.AreEqual(3, result.NumVertices); + Assert.AreEqual(new Vector3(0, 0, 0), result.Vertices[0]); + Assert.AreEqual(new Vector3(0, 1, 0), result.Vertices[1]); + Assert.AreEqual(new Vector3(0, 1, 1), result.Vertices[2]); + Assert.AreEqual(1, result.NumFaces); + Assert.AreEqual(0, result.SubmeshIndexOffsets.ToEnumerable().Single()); + Assert.AreEqual(-1, result.SubmeshMaterials.ToEnumerable().Single()); + Assert.AreEqual(-1, result.GetFaceMaterials().First()); } } } diff --git a/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs b/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs index 23c3d8b0..40ad87bb 100644 --- a/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs +++ b/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs @@ -127,26 +127,6 @@ public static void Merge_ByPair_IsSame() } } - [Test] - public static void QuadToTri_IsSame() - { - var indices = new int[] { 0, 1, 4, 3, 1, 2, 5, 4 }; - var vertices = new Vector3[] - { - new Vector3(1,0,0), - new Vector3(1,1,0), - new Vector3(1,2,0), - new Vector3(0,0,0), - new Vector3(0,1,0), - new Vector3(0,2,0), - }; - - var mesh = Primitives.QuadMesh(vertices.ToIArray(), indices.ToIArray()); - var next = VimMesh.FromQuad(indices, vertices); - - MeshesAreSame(mesh, next); - } - [Test] public static void FromG3d_Equals_ToIMesh() { diff --git a/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs b/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs index 282ad544..dcde1a3b 100644 --- a/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs +++ b/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs @@ -28,15 +28,10 @@ public VimValidationException(string message) : base(message) { } public static void ValidateGeometry(this VimScene vim) { // Validate the packed geometry. - vim.Document.Geometry.ToIMesh().Validate(); + VimMesh.FromG3d(vim.Document.GeometryNext).Validate(); var errors = new List(); G3d.Validation.Validate(vim.Document.Geometry); - - - // Validate the individual meshes. - foreach (var g in vim.MeshesOld.ToEnumerable()) - g.Validate(); } public static void ValidateGeometryNext(this VimScene vim) diff --git a/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs b/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs index b5704969..83f115a8 100644 --- a/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs +++ b/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs @@ -83,14 +83,6 @@ public Vector4 GetMaterialColor(int materialIndex) public Vector4 GetMaterialColorNext(int materialIndex) => _SerializableDocument.GeometryNext.MaterialColors[materialIndex]; - public static IMesh ToIMesh(G3dMesh g3d) - => Primitives.TriMesh( - g3d.Vertices.ToPositionAttribute(), - g3d.Indices.ToIndexAttribute(), - g3d.SubmeshIndexOffsets?.ToSubmeshIndexOffsetAttribute(), - g3d.SubmeshMaterials?.ToSubmeshMaterialAttribute() - ); - private VimScene(SerializableDocument doc) => _SerializableDocument = doc; @@ -198,12 +190,6 @@ private void CreateMeshes(bool inParallel) } var srcGeo = _SerializableDocument.Geometry; - var tmp = srcGeo?.Meshes.Select(ToIMesh); - MeshesOld = (tmp == null) - ? LinqArray.LinqArray.Empty() - : inParallel - ? tmp.EvaluateInParallel() - : tmp.Evaluate(); MeshesNext = VimMesh.GetAllMeshes(_SerializableDocument.GeometryNext).ToArray(); Meshes = srcGeo?.Meshes.Select(m => m as IMeshCommon); } From 10dc6c9218244a2a1ab65ed32fca34000da70a38 Mon Sep 17 00:00:00 2001 From: simon Date: Fri, 5 Apr 2024 17:01:51 -0400 Subject: [PATCH 138/204] added unindex method --- src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs b/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs index 25b5414b..b9dada16 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs @@ -46,6 +46,12 @@ public VimMesh() } + public VimMesh(Vector3[] vertices) + : this(Enumerable.Range(0,vertices.Length).ToArray(), vertices) + { + + } + public VimMesh( int[] indices, Vector3[] vertices, @@ -95,6 +101,7 @@ private static int[] ComputeCounts(int[] offsets, int max) return result; } + public VimMesh(int indexCount, int vertexCount, int submeshCount) { indices = new int[indexCount]; @@ -329,6 +336,12 @@ public static bool Planar(this IMeshCommon mesh, float tolerance = Math3d.Consta return mesh.ComputedNormals().All(n => n.AlmostEquals(normal, tolerance)); } + public static VimMesh Unindex(this IMeshCommon mesh) + { + var vertices = mesh.Indices.Select(i => mesh.Vertices[i]); + return new VimMesh(vertices.ToArray()); + } + public static IArray ComputedNormals(this IMeshCommon mesh) => mesh.Triangles().Select(t => t.Normal); From 24a8ddf28d0b3233e7a3167ad9dc054fc7a2f1b1 Mon Sep 17 00:00:00 2001 From: simon Date: Fri, 5 Apr 2024 17:14:53 -0400 Subject: [PATCH 139/204] removing more imesh --- .../Geometry/MeshExtensions.cs | 26 ++----------------- .../vim/Vim.Format.Core/Geometry/QuadMesh.cs | 21 --------------- .../vim/Vim.Format.Core/Geometry/TriMesh.cs | 20 -------------- .../Geometry/GeometryTests.cs | 14 ---------- .../SerializableDocumentTests.cs | 4 +-- 5 files changed, 4 insertions(+), 81 deletions(-) delete mode 100644 src/cs/vim/Vim.Format.Core/Geometry/QuadMesh.cs delete mode 100644 src/cs/vim/Vim.Format.Core/Geometry/TriMesh.cs diff --git a/src/cs/vim/Vim.Format.Core/Geometry/MeshExtensions.cs b/src/cs/vim/Vim.Format.Core/Geometry/MeshExtensions.cs index deacbe26..56d1dc00 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/MeshExtensions.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/MeshExtensions.cs @@ -10,28 +10,6 @@ namespace Vim.Format.Geometry { public static class MeshExtensions { - #region constructors - public static IMesh ToIMesh(this IArray self) - => self.ToEnumerable().ToIMesh(); - - public static IMesh ToIMesh(this IEnumerable self) - { - var tmp = new GeometryAttributes(self); - switch (tmp.NumCornersPerFace) - { - case 3: - return new TriMesh(tmp.Attributes.ToEnumerable()); - case 4: - return new QuadMesh(tmp.Attributes.ToEnumerable()).ToTriMesh(); - default: - throw new Exception($"Can not convert a geometry with {tmp.NumCornersPerFace} to a triangle mesh: only quad meshes"); - } - } - - public static IMesh ToIMesh(this IGeometryAttributes g) - => g is IMesh m ? m : g is QuadMesh q ? q.ToIMesh() : g.Attributes.ToIMesh(); - #endregion - public static IArray GetFaceMaterials(this IMesh mesh) { // SubmeshIndexOffsets: [0, A, B] @@ -47,7 +25,7 @@ public static IArray GetFaceMaterials(this IMesh mesh) } public static IMesh Merge(this IArray meshes) - => meshes.Select(m => (IGeometryAttributes)m).Merge().ToIMesh(); + => meshes.Select(m => (IGeometryAttributes)m).Merge() as IMesh; public static IMesh Merge(this IEnumerable meshes) => meshes.ToIArray().Merge(); @@ -137,7 +115,7 @@ public static IMesh Merge(this IMesh mesh, params IMesh[] others) .Append(newSubmeshIndexOffsets) .Append(newSubmeshMaterials) .ToGeometryAttributes() - .ToIMesh(); + as IMesh; }); return meshes.Select(m => (material, m)); diff --git a/src/cs/vim/Vim.Format.Core/Geometry/QuadMesh.cs b/src/cs/vim/Vim.Format.Core/Geometry/QuadMesh.cs deleted file mode 100644 index deb3af9f..00000000 --- a/src/cs/vim/Vim.Format.Core/Geometry/QuadMesh.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System.Collections.Generic; -using System.Diagnostics; -using Vim.Util; -using Vim.G3d; - -namespace Vim.Format.Geometry -{ - /// - /// This is a quadrilateral mesh. Note that it does not implement the IMesh interface, - /// but does implement IGeometryAttributes and inherits from a G3D. - /// - public class QuadMesh : G3D, IGeometryAttributes - { - public QuadMesh(IEnumerable attributes) - : base(attributes.Append(new[] { 4 }.ToObjectFaceSizeAttribute())) - => Debug.Assert(NumCornersPerFace == 4); - - public IMesh ToTriMesh() - => this.TriangulateQuadMesh().ToIMesh(); - } -} diff --git a/src/cs/vim/Vim.Format.Core/Geometry/TriMesh.cs b/src/cs/vim/Vim.Format.Core/Geometry/TriMesh.cs deleted file mode 100644 index 17678088..00000000 --- a/src/cs/vim/Vim.Format.Core/Geometry/TriMesh.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System.Collections.Generic; -using System.Diagnostics; -using Vim.G3d; -using Vim.Math3d; - -namespace Vim.Format.Geometry -{ - /// - /// A triangular mesh data structure. - /// - public class TriMesh : G3D, IMesh - { - public TriMesh(IEnumerable attributes) - : base(attributes) - => Debug.Assert(NumCornersPerFace == 3); - - public IMesh Transform(Matrix4x4 mat) - => ((IGeometryAttributes)this).Transform(mat).ToIMesh(); - } -} diff --git a/src/cs/vim/Vim.Format.Tests/Geometry/GeometryTests.cs b/src/cs/vim/Vim.Format.Tests/Geometry/GeometryTests.cs index 13092f28..22945f35 100644 --- a/src/cs/vim/Vim.Format.Tests/Geometry/GeometryTests.cs +++ b/src/cs/vim/Vim.Format.Tests/Geometry/GeometryTests.cs @@ -58,20 +58,6 @@ static IMeshCommon RevolvedVerticalCylinder(float height, float radius, int vert public static double SmallTolerance = 0.0001; - public static void AssertEquals(IMesh g1, IMesh g2) - { - - Assert.AreEqual(g1.NumFaces, g2.NumFaces); - Assert.AreEqual(g1.NumCorners, g2.NumCorners); - Assert.AreEqual(g1.NumVertices, g2.NumVertices); - for (var i = 0; i < g1.Indices.Count; i++) - { - var v1 = g1.Vertices[g1.Indices[i]]; - var v2 = g2.Vertices[g2.Indices[i]]; - Assert.IsTrue(v1.AlmostEquals(v2, (float)SmallTolerance)); - } - } - public static void GeometryNullOps(IMeshCommon g) { g.GeometryEquals(g); diff --git a/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs b/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs index 40ad87bb..bb6ddb11 100644 --- a/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs +++ b/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs @@ -89,7 +89,7 @@ public static void ReverseWindingOrder_IsSame() for (var i = 0; i < scene.GetMeshCount(); i++) { - var mesh = scene.MeshesOld[i].ReverseWindingOrder().ToIMesh(); + var mesh = scene.MeshesOld[i].ReverseWindingOrder() as IMesh; var next = scene.MeshesNext[i].ReverseWindingOrder(); var raw = scene.Meshes[i].ReverseWindingOrder(); MeshesAreSame(mesh, next); @@ -132,7 +132,7 @@ public static void FromG3d_Equals_ToIMesh() { var path = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); var scene = VimScene.LoadVim(path); - var mesh = scene.Document.Geometry.ToIMesh(); + var mesh = scene.Document.Geometry as IMesh; var next = VimMesh.FromG3d(scene.Document.GeometryNext); MeshesAreSame(mesh, next); From f7753a092ff06dca5169cc1fa3b23e5694f573b3 Mon Sep 17 00:00:00 2001 From: simon Date: Tue, 9 Apr 2024 14:54:38 -0400 Subject: [PATCH 140/204] removed imesh --- src/cs/vim/Vim.Format.Core/Geometry/IMesh.cs | 22 -- .../Geometry/MeshExtensions.cs | 178 ----------- .../SerializableDocumentTests.cs | 284 +++++++++--------- .../vim/Vim.Format/SceneBuilder/VimScene.cs | 1 - 4 files changed, 142 insertions(+), 343 deletions(-) delete mode 100644 src/cs/vim/Vim.Format.Core/Geometry/IMesh.cs delete mode 100644 src/cs/vim/Vim.Format.Core/Geometry/MeshExtensions.cs diff --git a/src/cs/vim/Vim.Format.Core/Geometry/IMesh.cs b/src/cs/vim/Vim.Format.Core/Geometry/IMesh.cs deleted file mode 100644 index 4e98afd8..00000000 --- a/src/cs/vim/Vim.Format.Core/Geometry/IMesh.cs +++ /dev/null @@ -1,22 +0,0 @@ -using Vim.G3d; -using Vim.LinqArray; -using Vim.Math3d; - -namespace Vim.Format.Geometry -{ - /// - /// This is the interface for triangle meshes. - /// - public interface IMesh : - IGeometryAttributes, - ITransformable3D - { - IArray Vertices { get; } - IArray Indices { get; } - - IArray SubmeshMaterials { get; } - IArray SubmeshIndexOffsets { get; } - IArray SubmeshIndexCount { get; } - } - -} diff --git a/src/cs/vim/Vim.Format.Core/Geometry/MeshExtensions.cs b/src/cs/vim/Vim.Format.Core/Geometry/MeshExtensions.cs deleted file mode 100644 index 56d1dc00..00000000 --- a/src/cs/vim/Vim.Format.Core/Geometry/MeshExtensions.cs +++ /dev/null @@ -1,178 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Vim.G3d; -using Vim.LinqArray; -using Vim.Math3d; -using Vim.Util; - -namespace Vim.Format.Geometry -{ - public static class MeshExtensions - { - public static IArray GetFaceMaterials(this IMesh mesh) - { - // SubmeshIndexOffsets: [0, A, B] - // SubmeshIndexCount: [X, Y, Z] - // SubmeshMaterials: [L, M, N] - // --- - // FaceMaterials: [...Repeat(L, X / 3), ...Repeat(M, Y / 3), ...Repeat(N, Z / 3)] <-- divide by 3 for the number of corners per Triangular face - var numCornersPerFace = mesh.NumCornersPerFace; - return mesh.SubmeshIndexCount - .ToEnumerable() - .SelectMany((indexCount, i) => Enumerable.Repeat(mesh.SubmeshMaterials[i], indexCount / numCornersPerFace)) - .ToIArray(); - } - - public static IMesh Merge(this IArray meshes) - => meshes.Select(m => (IGeometryAttributes)m).Merge() as IMesh; - - public static IMesh Merge(this IEnumerable meshes) - => meshes.ToIArray().Merge(); - - public static IMesh Merge(this IMesh mesh, params IMesh[] others) - { - var gs = others.ToList(); - gs.Insert(0, mesh); - return gs.Merge(); - } - - public static IEnumerable<(int Material, IMesh Mesh)> SplitByMaterial(this IMesh mesh) - { - var submeshMaterials = mesh.SubmeshMaterials; - if (submeshMaterials == null || submeshMaterials.Count == 0) - { - // Base case: no submesh materials are defined on the mesh. - return new[] { (-1, mesh) }; - } - - var submeshIndexOffets = mesh.SubmeshIndexOffsets; - var submeshIndexCounts = mesh.SubmeshIndexCount; - if (submeshIndexOffets == null || submeshIndexCounts == null || - submeshMaterials.Count <= 1 || submeshIndexOffets.Count <= 1 || submeshIndexCounts.Count <= 1) - { - // Base case: only one submesh material. - return new[] { (submeshMaterials[0], mesh) }; - } - - // Example: - // - // ------------ - // INPUT MESH: - // ------------ - // Vertices [Va, Vb, Vc, Vd, Ve, Vf, Vg] <-- 7 vertices - // Indices [0 (Va), 1 (Vb), 2 (Vc), 1 (Vb), 2 (Vc), 3 (Vd), 4 (Ve), 5 (Vf), 6 (Vg)] <-- 3 triangles referencing the 7 vertices - // SubmeshIndexOffsets [0, 3, 6] - // SubmeshIndexCount [3, 3, 3] (computed) - // SubmeshMaterials [Ma, Mb, Mc] - // - // ------------ - // OUTPUT MESHES - // ------------ - // - MESH FOR MATERIAL Ma - // Vertices: [Va, Vb, Vc] - // Indices: [0, 1, 2] - // SubmeshIndexOffsets: [0] - // SubmeshMaterials: [Ma] - // - //- MESH FOR MATERIAL Mb - // Vertices: [Vb, Vc, Vd] - // Indices: [0, 1, 2] - // SubmeshIndexOffsets: [0] - // SubmeshMaterials: [Mb] - // - //- MESH FOR MATERIAL Mc - // Vertices: [Ve, Vf, Vg] - // Indices: [0, 1, 2] - // SubmeshIndexOffsets: [0] - // SubmeshMaterials: [Mc] - - return mesh.SubmeshMaterials - .Select((submeshMaterial, submeshIndex) => (submeshMaterial, submeshIndex)) - .GroupBy(t => t.submeshMaterial) - .SelectMany(g => - { - var material = g.Key; - var meshes = g.Select((t, _) => - { - var submeshMaterial = t.submeshMaterial; - var submeshStartIndex = submeshIndexOffets[t.submeshIndex]; - var submeshIndexCount = submeshIndexCounts[t.submeshIndex]; - - var indexSlice = mesh.Indices.Slice(submeshStartIndex, submeshStartIndex + submeshIndexCount); - - var newVertexAttributes = mesh.VertexAttributes().Select(attr => attr.Remap(indexSlice)); - var newIndexAttribute = indexSlice.Count.Select(i => i).ToIndexAttribute(); - - var newSubmeshIndexOffsets = 0.Repeat(1).ToSubmeshIndexOffsetAttribute(); - var newSubmeshMaterials = submeshMaterial.Repeat(1).ToSubmeshMaterialAttribute(); - - return newVertexAttributes - .Concat(mesh.NoneAttributes()) - .Concat(mesh.WholeGeometryAttributes()) - // TODO: TECH DEBT - face, edge, and corner attributes are ignored for now. - .Append(newIndexAttribute) - .Append(newSubmeshIndexOffsets) - .Append(newSubmeshMaterials) - .ToGeometryAttributes() - as IMesh; - }); - - return meshes.Select(m => (material, m)); - }); - } - public static bool GeometryEquals(this IMesh mesh, IMesh other, float tolerance = Math3d.Constants.Tolerance) - { - if (mesh.NumFaces != other.NumFaces) - return false; - return mesh.Triangles().Zip(other.Triangles(), (t1, t2) => t1.AlmostEquals(t2, tolerance)).All(x => x); - } - public static IGeometryAttributes ReverseWindingOrder(this IMesh mesh) - { - var n = mesh.Indices.Count; - var r = new int[n]; - for (var i = 0; i < n; i += 3) - { - r[i + 0] = mesh.Indices[i + 2]; - r[i + 1] = mesh.Indices[i + 1]; - r[i + 2] = mesh.Indices[i + 0]; - } - return mesh.SetAttribute(r.ToIArray().ToIndexAttribute()); - } - - - public static AABox BoundingBox(this IMesh mesh) - => AABox.Create(mesh.Vertices.ToEnumerable()); - - - public static Vector3 Center(this IMesh mesh) - => mesh.BoundingBox().Center; - - #region Face operations - - - public static Int3 FaceVertexIndices(this IMesh mesh, int faceIndex) - => new Int3(mesh.Indices[faceIndex * 3], mesh.Indices[faceIndex * 3 + 1], mesh.Indices[faceIndex * 3 + 2]); - - public static Triangle VertexIndicesToTriangle(this IMesh mesh, Int3 indices) - => new Triangle(mesh.Vertices[indices.X], mesh.Vertices[indices.Y], mesh.Vertices[indices.Z]); - - public static Triangle Triangle(this IMesh mesh, int face) - => mesh.VertexIndicesToTriangle(mesh.FaceVertexIndices(face)); - - public static IArray Triangles(this IMesh mesh) - => mesh.NumFaces.Select(mesh.Triangle); - - public static IArray ComputedNormals(this IMesh mesh) - => mesh.Triangles().Select(t => t.Normal); - - public static bool Planar(this IMesh mesh, float tolerance = Math3d.Constants.Tolerance) - { - if (mesh.NumFaces <= 1) return true; - var normal = mesh.Triangle(0).Normal; - return mesh.ComputedNormals().All(n => n.AlmostEquals(normal, tolerance)); - } - - #endregion - } -} diff --git a/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs b/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs index bb6ddb11..b4cd0c6b 100644 --- a/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs +++ b/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs @@ -46,140 +46,140 @@ public static void MaterialColor_IsSame() } } - [Test] - public static void GetMesh_IsSameMesh() - { - var path = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); - var scene = VimScene.LoadVim(path); - for (var i = 0; i < scene.GetMeshCount(); i++) - { - var mesh = scene.MeshesOld[i]; - var next = scene.MeshesNext[i]; - var raw = scene.Meshes[i]; - MeshesAreSame(mesh, next); - MeshesAreSame(mesh, raw); - } - } - - [Test] - public static void GetMesh_Transform_IsSame() - { - var path = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); - var scene = VimScene.LoadVim(path); - for (var i = 0; i < scene.GetMeshCount(); i++) - { - var mat = Matrix4x4.CreateWorld( - new Vector3(1, -2, 3), - new Vector3(0, 0, 1), - new Vector3(0, 1, 0) - ); - var mesh = scene.MeshesOld[i].Transform(mat); - var next = scene.MeshesNext[i].Transform(mat); - var raw = scene.Meshes[i].Transform(mat); - MeshesAreSame(mesh, next); - MeshesAreSame(mesh, raw); - } - } - - [Test] - public static void ReverseWindingOrder_IsSame() - { - var path = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); - var scene = VimScene.LoadVim(path); - for (var i = 0; i < scene.GetMeshCount(); i++) - { - - var mesh = scene.MeshesOld[i].ReverseWindingOrder() as IMesh; - var next = scene.MeshesNext[i].ReverseWindingOrder(); - var raw = scene.Meshes[i].ReverseWindingOrder(); - MeshesAreSame(mesh, next); - MeshesAreSame(mesh, raw); - } - } - - [Test] - public static void FaceMaterial_IsSame() - { - var path = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); - var scene = VimScene.LoadVim(path); - for (var i = 0; i < scene.GetMeshCount(); i++) - { - var mesh = scene.MeshesOld[i].GetFaceMaterials(); - var next = scene.MeshesNext[i].GetFaceMaterials(); - var raw = scene.Meshes[i].GetFaceMaterials(); - Assert.That(mesh.SequenceEquals(next)); - Assert.That(next.SequenceEquals(raw)); - } - } - - [Test] - public static void Merge_ByPair_IsSame() - { - var path = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); - var scene = VimScene.LoadVim(path); - for (var i = 1; i < scene.GetMeshCount(); i++) - { - var mesh = scene.MeshesOld[i].Merge(scene.MeshesOld[i - 1]); - var next = scene.MeshesNext[i].Merge2(scene.MeshesNext[i - 1]); - var raw = scene.Meshes[i].Merge2(scene.Meshes[i - 1]); - MeshesAreSame(mesh, next); - MeshesAreSame(mesh, raw); - } - } - - [Test] - public static void FromG3d_Equals_ToIMesh() - { - var path = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); - var scene = VimScene.LoadVim(path); - var mesh = scene.Document.Geometry as IMesh; - var next = VimMesh.FromG3d(scene.Document.GeometryNext); - MeshesAreSame(mesh, next); - - } - - [Test] - public static void Merge_All_IsSame() - { - var path = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); - var scene = VimScene.LoadVim(path); - - var mesh = scene.MeshesOld[0].Merge(scene.MeshesOld.Skip(1).ToArray()); - var next = scene.MeshesNext[0].Merge2(scene.MeshesNext.Skip(1).ToArray()); - var raw = scene.Meshes[0].Merge2(scene.Meshes.Skip(1).ToArray()); - MeshesAreSame(mesh, next); - MeshesAreSame(mesh, raw); - } - - [Test] - public static void SplitByMaterials_IsSame() - { - var path = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); - var scene = VimScene.LoadVim(path); - for (var i = 0; i < scene.GetMeshCount(); i++) - { - var mesh = scene.MeshesOld[i].SplitByMaterial().ToArray(); - var next = scene.MeshesNext[i].SplitByMaterial(); - var raw = scene.Meshes[i].SplitByMaterial(); - Assert.AreEqual(mesh.Length, next.Length); - Assert.AreEqual(mesh.Length, raw.Length); - - for (var j = 0; j < mesh.Length; j++) - { - MeshesAreSame(mesh[j].Mesh, next[j].mesh); - MeshesAreSame(mesh[j].Mesh, raw[j].mesh); - } - } - } - - private static void Consume(IMesh mesh) - { - mesh.Indices.Sum(); - mesh.Vertices.Sum(v => v.X); - mesh.SubmeshIndexOffsets.Sum(); - mesh.SubmeshIndexCount.Sum(); - mesh.SubmeshMaterials.Sum(); - } + //[Test] + //public static void GetMesh_IsSameMesh() + //{ + // var path = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); + // var scene = VimScene.LoadVim(path); + // for (var i = 0; i < scene.GetMeshCount(); i++) + // { + // var mesh = scene.MeshesOld[i]; + // var next = scene.MeshesNext[i]; + // var raw = scene.Meshes[i]; + // MeshesAreSame(mesh, next); + // MeshesAreSame(mesh, raw); + // } + //} + + //[Test] + //public static void GetMesh_Transform_IsSame() + //{ + // var path = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); + // var scene = VimScene.LoadVim(path); + // for (var i = 0; i < scene.GetMeshCount(); i++) + // { + // var mat = Matrix4x4.CreateWorld( + // new Vector3(1, -2, 3), + // new Vector3(0, 0, 1), + // new Vector3(0, 1, 0) + // ); + // var mesh = scene.MeshesOld[i].Transform(mat); + // var next = scene.MeshesNext[i].Transform(mat); + // var raw = scene.Meshes[i].Transform(mat); + // MeshesAreSame(mesh, next); + // MeshesAreSame(mesh, raw); + // } + //} + + //[Test] + //public static void ReverseWindingOrder_IsSame() + //{ + // var path = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); + // var scene = VimScene.LoadVim(path); + // for (var i = 0; i < scene.GetMeshCount(); i++) + // { + + // var mesh = scene.MeshesOld[i].ReverseWindingOrder() as IMesh; + // var next = scene.MeshesNext[i].ReverseWindingOrder(); + // var raw = scene.Meshes[i].ReverseWindingOrder(); + // MeshesAreSame(mesh, next); + // MeshesAreSame(mesh, raw); + // } + //} + + //[Test] + //public static void FaceMaterial_IsSame() + //{ + // var path = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); + // var scene = VimScene.LoadVim(path); + // for (var i = 0; i < scene.GetMeshCount(); i++) + // { + // var mesh = scene.MeshesOld[i].GetFaceMaterials(); + // var next = scene.MeshesNext[i].GetFaceMaterials(); + // var raw = scene.Meshes[i].GetFaceMaterials(); + // Assert.That(mesh.SequenceEquals(next)); + // Assert.That(next.SequenceEquals(raw)); + // } + //} + + //[Test] + //public static void Merge_ByPair_IsSame() + //{ + // var path = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); + // var scene = VimScene.LoadVim(path); + // for (var i = 1; i < scene.GetMeshCount(); i++) + // { + // var mesh = scene.MeshesOld[i].Merge(scene.MeshesOld[i - 1]); + // var next = scene.MeshesNext[i].Merge2(scene.MeshesNext[i - 1]); + // var raw = scene.Meshes[i].Merge2(scene.Meshes[i - 1]); + // MeshesAreSame(mesh, next); + // MeshesAreSame(mesh, raw); + // } + //} + + //[Test] + //public static void FromG3d_Equals_ToIMesh() + //{ + // var path = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); + // var scene = VimScene.LoadVim(path); + // var mesh = scene.Document.Geometry as IMesh; + // var next = VimMesh.FromG3d(scene.Document.GeometryNext); + // MeshesAreSame(mesh, next); + + //} + + //[Test] + //public static void Merge_All_IsSame() + //{ + // var path = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); + // var scene = VimScene.LoadVim(path); + + // var mesh = scene.MeshesOld[0].Merge(scene.MeshesOld.Skip(1).ToArray()); + // var next = scene.MeshesNext[0].Merge2(scene.MeshesNext.Skip(1).ToArray()); + // var raw = scene.Meshes[0].Merge2(scene.Meshes.Skip(1).ToArray()); + // MeshesAreSame(mesh, next); + // MeshesAreSame(mesh, raw); + //} + + //[Test] + //public static void SplitByMaterials_IsSame() + //{ + // var path = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); + // var scene = VimScene.LoadVim(path); + // for (var i = 0; i < scene.GetMeshCount(); i++) + // { + // var mesh = scene.MeshesOld[i].SplitByMaterial().ToArray(); + // var next = scene.MeshesNext[i].SplitByMaterial(); + // var raw = scene.Meshes[i].SplitByMaterial(); + // Assert.AreEqual(mesh.Length, next.Length); + // Assert.AreEqual(mesh.Length, raw.Length); + + // for (var j = 0; j < mesh.Length; j++) + // { + // MeshesAreSame(mesh[j].Mesh, next[j].mesh); + // MeshesAreSame(mesh[j].Mesh, raw[j].mesh); + // } + // } + //} + + //private static void Consume(IMesh mesh) + //{ + // mesh.Indices.Sum(); + // mesh.Vertices.Sum(v => v.X); + // mesh.SubmeshIndexOffsets.Sum(); + // mesh.SubmeshIndexCount.Sum(); + // mesh.SubmeshMaterials.Sum(); + //} private static void Consume(IMeshCommon mesh) { @@ -191,14 +191,14 @@ private static void Consume(IMeshCommon mesh) } - private static void MeshesAreSame(IMesh mesh, IMeshCommon next) - { - Assert.That(mesh.Indices.SequenceEquals(next.Indices)); - Assert.That(mesh.Vertices.SequenceEquals(next.Vertices)); - Assert.That(mesh.SubmeshIndexOffsets.SequenceEquals(next.SubmeshIndexOffsets)); - Assert.That(mesh.SubmeshMaterials.SequenceEquals(next.SubmeshMaterials)); - Assert.That(mesh.SubmeshIndexCount.SequenceEquals(next.SubmeshIndexCounts)); - } + //private static void MeshesAreSame(IMesh mesh, IMeshCommon next) + //{ + // Assert.That(mesh.Indices.SequenceEquals(next.Indices)); + // Assert.That(mesh.Vertices.SequenceEquals(next.Vertices)); + // Assert.That(mesh.SubmeshIndexOffsets.SequenceEquals(next.SubmeshIndexOffsets)); + // Assert.That(mesh.SubmeshMaterials.SequenceEquals(next.SubmeshMaterials)); + // Assert.That(mesh.SubmeshIndexCount.SequenceEquals(next.SubmeshIndexCounts)); + //} private static void MeshesAreSame(IMeshCommon mesh, IMeshCommon next) { Assert.That(mesh.Indices.SequenceEquals(next.Indices)); diff --git a/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs b/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs index 83f115a8..145975e3 100644 --- a/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs +++ b/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs @@ -59,7 +59,6 @@ public static VimScene LoadVim(Stream stream, IVimSceneProgress progress = null, => LoadVim(stream, new LoadOptions { SkipGeometry = skipGeometry, SkipAssets = skipAssets}, progress, inParallel); public int VimIndex { get; set; } - public IArray MeshesOld { get; private set; } public VimMesh[] MeshesNext { get; private set; } public IArray Meshes { get; private set; } public IArray Nodes { get; private set; } From bd36088de7108dca7a3382a6ad583d4381d03de9 Mon Sep 17 00:00:00 2001 From: simon Date: Tue, 9 Apr 2024 14:54:38 -0400 Subject: [PATCH 141/204] removed imesh --- src/cs/vim/Vim.Format.Core/Geometry/IMesh.cs | 22 -- .../Geometry/MeshExtensions.cs | 178 ----------- .../SerializableDocumentTests.cs | 284 +++++++++--------- .../vim/Vim.Format/SceneBuilder/VimScene.cs | 1 - 4 files changed, 142 insertions(+), 343 deletions(-) delete mode 100644 src/cs/vim/Vim.Format.Core/Geometry/IMesh.cs delete mode 100644 src/cs/vim/Vim.Format.Core/Geometry/MeshExtensions.cs diff --git a/src/cs/vim/Vim.Format.Core/Geometry/IMesh.cs b/src/cs/vim/Vim.Format.Core/Geometry/IMesh.cs deleted file mode 100644 index 4e98afd8..00000000 --- a/src/cs/vim/Vim.Format.Core/Geometry/IMesh.cs +++ /dev/null @@ -1,22 +0,0 @@ -using Vim.G3d; -using Vim.LinqArray; -using Vim.Math3d; - -namespace Vim.Format.Geometry -{ - /// - /// This is the interface for triangle meshes. - /// - public interface IMesh : - IGeometryAttributes, - ITransformable3D - { - IArray Vertices { get; } - IArray Indices { get; } - - IArray SubmeshMaterials { get; } - IArray SubmeshIndexOffsets { get; } - IArray SubmeshIndexCount { get; } - } - -} diff --git a/src/cs/vim/Vim.Format.Core/Geometry/MeshExtensions.cs b/src/cs/vim/Vim.Format.Core/Geometry/MeshExtensions.cs deleted file mode 100644 index 56d1dc00..00000000 --- a/src/cs/vim/Vim.Format.Core/Geometry/MeshExtensions.cs +++ /dev/null @@ -1,178 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Vim.G3d; -using Vim.LinqArray; -using Vim.Math3d; -using Vim.Util; - -namespace Vim.Format.Geometry -{ - public static class MeshExtensions - { - public static IArray GetFaceMaterials(this IMesh mesh) - { - // SubmeshIndexOffsets: [0, A, B] - // SubmeshIndexCount: [X, Y, Z] - // SubmeshMaterials: [L, M, N] - // --- - // FaceMaterials: [...Repeat(L, X / 3), ...Repeat(M, Y / 3), ...Repeat(N, Z / 3)] <-- divide by 3 for the number of corners per Triangular face - var numCornersPerFace = mesh.NumCornersPerFace; - return mesh.SubmeshIndexCount - .ToEnumerable() - .SelectMany((indexCount, i) => Enumerable.Repeat(mesh.SubmeshMaterials[i], indexCount / numCornersPerFace)) - .ToIArray(); - } - - public static IMesh Merge(this IArray meshes) - => meshes.Select(m => (IGeometryAttributes)m).Merge() as IMesh; - - public static IMesh Merge(this IEnumerable meshes) - => meshes.ToIArray().Merge(); - - public static IMesh Merge(this IMesh mesh, params IMesh[] others) - { - var gs = others.ToList(); - gs.Insert(0, mesh); - return gs.Merge(); - } - - public static IEnumerable<(int Material, IMesh Mesh)> SplitByMaterial(this IMesh mesh) - { - var submeshMaterials = mesh.SubmeshMaterials; - if (submeshMaterials == null || submeshMaterials.Count == 0) - { - // Base case: no submesh materials are defined on the mesh. - return new[] { (-1, mesh) }; - } - - var submeshIndexOffets = mesh.SubmeshIndexOffsets; - var submeshIndexCounts = mesh.SubmeshIndexCount; - if (submeshIndexOffets == null || submeshIndexCounts == null || - submeshMaterials.Count <= 1 || submeshIndexOffets.Count <= 1 || submeshIndexCounts.Count <= 1) - { - // Base case: only one submesh material. - return new[] { (submeshMaterials[0], mesh) }; - } - - // Example: - // - // ------------ - // INPUT MESH: - // ------------ - // Vertices [Va, Vb, Vc, Vd, Ve, Vf, Vg] <-- 7 vertices - // Indices [0 (Va), 1 (Vb), 2 (Vc), 1 (Vb), 2 (Vc), 3 (Vd), 4 (Ve), 5 (Vf), 6 (Vg)] <-- 3 triangles referencing the 7 vertices - // SubmeshIndexOffsets [0, 3, 6] - // SubmeshIndexCount [3, 3, 3] (computed) - // SubmeshMaterials [Ma, Mb, Mc] - // - // ------------ - // OUTPUT MESHES - // ------------ - // - MESH FOR MATERIAL Ma - // Vertices: [Va, Vb, Vc] - // Indices: [0, 1, 2] - // SubmeshIndexOffsets: [0] - // SubmeshMaterials: [Ma] - // - //- MESH FOR MATERIAL Mb - // Vertices: [Vb, Vc, Vd] - // Indices: [0, 1, 2] - // SubmeshIndexOffsets: [0] - // SubmeshMaterials: [Mb] - // - //- MESH FOR MATERIAL Mc - // Vertices: [Ve, Vf, Vg] - // Indices: [0, 1, 2] - // SubmeshIndexOffsets: [0] - // SubmeshMaterials: [Mc] - - return mesh.SubmeshMaterials - .Select((submeshMaterial, submeshIndex) => (submeshMaterial, submeshIndex)) - .GroupBy(t => t.submeshMaterial) - .SelectMany(g => - { - var material = g.Key; - var meshes = g.Select((t, _) => - { - var submeshMaterial = t.submeshMaterial; - var submeshStartIndex = submeshIndexOffets[t.submeshIndex]; - var submeshIndexCount = submeshIndexCounts[t.submeshIndex]; - - var indexSlice = mesh.Indices.Slice(submeshStartIndex, submeshStartIndex + submeshIndexCount); - - var newVertexAttributes = mesh.VertexAttributes().Select(attr => attr.Remap(indexSlice)); - var newIndexAttribute = indexSlice.Count.Select(i => i).ToIndexAttribute(); - - var newSubmeshIndexOffsets = 0.Repeat(1).ToSubmeshIndexOffsetAttribute(); - var newSubmeshMaterials = submeshMaterial.Repeat(1).ToSubmeshMaterialAttribute(); - - return newVertexAttributes - .Concat(mesh.NoneAttributes()) - .Concat(mesh.WholeGeometryAttributes()) - // TODO: TECH DEBT - face, edge, and corner attributes are ignored for now. - .Append(newIndexAttribute) - .Append(newSubmeshIndexOffsets) - .Append(newSubmeshMaterials) - .ToGeometryAttributes() - as IMesh; - }); - - return meshes.Select(m => (material, m)); - }); - } - public static bool GeometryEquals(this IMesh mesh, IMesh other, float tolerance = Math3d.Constants.Tolerance) - { - if (mesh.NumFaces != other.NumFaces) - return false; - return mesh.Triangles().Zip(other.Triangles(), (t1, t2) => t1.AlmostEquals(t2, tolerance)).All(x => x); - } - public static IGeometryAttributes ReverseWindingOrder(this IMesh mesh) - { - var n = mesh.Indices.Count; - var r = new int[n]; - for (var i = 0; i < n; i += 3) - { - r[i + 0] = mesh.Indices[i + 2]; - r[i + 1] = mesh.Indices[i + 1]; - r[i + 2] = mesh.Indices[i + 0]; - } - return mesh.SetAttribute(r.ToIArray().ToIndexAttribute()); - } - - - public static AABox BoundingBox(this IMesh mesh) - => AABox.Create(mesh.Vertices.ToEnumerable()); - - - public static Vector3 Center(this IMesh mesh) - => mesh.BoundingBox().Center; - - #region Face operations - - - public static Int3 FaceVertexIndices(this IMesh mesh, int faceIndex) - => new Int3(mesh.Indices[faceIndex * 3], mesh.Indices[faceIndex * 3 + 1], mesh.Indices[faceIndex * 3 + 2]); - - public static Triangle VertexIndicesToTriangle(this IMesh mesh, Int3 indices) - => new Triangle(mesh.Vertices[indices.X], mesh.Vertices[indices.Y], mesh.Vertices[indices.Z]); - - public static Triangle Triangle(this IMesh mesh, int face) - => mesh.VertexIndicesToTriangle(mesh.FaceVertexIndices(face)); - - public static IArray Triangles(this IMesh mesh) - => mesh.NumFaces.Select(mesh.Triangle); - - public static IArray ComputedNormals(this IMesh mesh) - => mesh.Triangles().Select(t => t.Normal); - - public static bool Planar(this IMesh mesh, float tolerance = Math3d.Constants.Tolerance) - { - if (mesh.NumFaces <= 1) return true; - var normal = mesh.Triangle(0).Normal; - return mesh.ComputedNormals().All(n => n.AlmostEquals(normal, tolerance)); - } - - #endregion - } -} diff --git a/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs b/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs index bb6ddb11..b4cd0c6b 100644 --- a/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs +++ b/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs @@ -46,140 +46,140 @@ public static void MaterialColor_IsSame() } } - [Test] - public static void GetMesh_IsSameMesh() - { - var path = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); - var scene = VimScene.LoadVim(path); - for (var i = 0; i < scene.GetMeshCount(); i++) - { - var mesh = scene.MeshesOld[i]; - var next = scene.MeshesNext[i]; - var raw = scene.Meshes[i]; - MeshesAreSame(mesh, next); - MeshesAreSame(mesh, raw); - } - } - - [Test] - public static void GetMesh_Transform_IsSame() - { - var path = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); - var scene = VimScene.LoadVim(path); - for (var i = 0; i < scene.GetMeshCount(); i++) - { - var mat = Matrix4x4.CreateWorld( - new Vector3(1, -2, 3), - new Vector3(0, 0, 1), - new Vector3(0, 1, 0) - ); - var mesh = scene.MeshesOld[i].Transform(mat); - var next = scene.MeshesNext[i].Transform(mat); - var raw = scene.Meshes[i].Transform(mat); - MeshesAreSame(mesh, next); - MeshesAreSame(mesh, raw); - } - } - - [Test] - public static void ReverseWindingOrder_IsSame() - { - var path = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); - var scene = VimScene.LoadVim(path); - for (var i = 0; i < scene.GetMeshCount(); i++) - { - - var mesh = scene.MeshesOld[i].ReverseWindingOrder() as IMesh; - var next = scene.MeshesNext[i].ReverseWindingOrder(); - var raw = scene.Meshes[i].ReverseWindingOrder(); - MeshesAreSame(mesh, next); - MeshesAreSame(mesh, raw); - } - } - - [Test] - public static void FaceMaterial_IsSame() - { - var path = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); - var scene = VimScene.LoadVim(path); - for (var i = 0; i < scene.GetMeshCount(); i++) - { - var mesh = scene.MeshesOld[i].GetFaceMaterials(); - var next = scene.MeshesNext[i].GetFaceMaterials(); - var raw = scene.Meshes[i].GetFaceMaterials(); - Assert.That(mesh.SequenceEquals(next)); - Assert.That(next.SequenceEquals(raw)); - } - } - - [Test] - public static void Merge_ByPair_IsSame() - { - var path = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); - var scene = VimScene.LoadVim(path); - for (var i = 1; i < scene.GetMeshCount(); i++) - { - var mesh = scene.MeshesOld[i].Merge(scene.MeshesOld[i - 1]); - var next = scene.MeshesNext[i].Merge2(scene.MeshesNext[i - 1]); - var raw = scene.Meshes[i].Merge2(scene.Meshes[i - 1]); - MeshesAreSame(mesh, next); - MeshesAreSame(mesh, raw); - } - } - - [Test] - public static void FromG3d_Equals_ToIMesh() - { - var path = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); - var scene = VimScene.LoadVim(path); - var mesh = scene.Document.Geometry as IMesh; - var next = VimMesh.FromG3d(scene.Document.GeometryNext); - MeshesAreSame(mesh, next); - - } - - [Test] - public static void Merge_All_IsSame() - { - var path = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); - var scene = VimScene.LoadVim(path); - - var mesh = scene.MeshesOld[0].Merge(scene.MeshesOld.Skip(1).ToArray()); - var next = scene.MeshesNext[0].Merge2(scene.MeshesNext.Skip(1).ToArray()); - var raw = scene.Meshes[0].Merge2(scene.Meshes.Skip(1).ToArray()); - MeshesAreSame(mesh, next); - MeshesAreSame(mesh, raw); - } - - [Test] - public static void SplitByMaterials_IsSame() - { - var path = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); - var scene = VimScene.LoadVim(path); - for (var i = 0; i < scene.GetMeshCount(); i++) - { - var mesh = scene.MeshesOld[i].SplitByMaterial().ToArray(); - var next = scene.MeshesNext[i].SplitByMaterial(); - var raw = scene.Meshes[i].SplitByMaterial(); - Assert.AreEqual(mesh.Length, next.Length); - Assert.AreEqual(mesh.Length, raw.Length); - - for (var j = 0; j < mesh.Length; j++) - { - MeshesAreSame(mesh[j].Mesh, next[j].mesh); - MeshesAreSame(mesh[j].Mesh, raw[j].mesh); - } - } - } - - private static void Consume(IMesh mesh) - { - mesh.Indices.Sum(); - mesh.Vertices.Sum(v => v.X); - mesh.SubmeshIndexOffsets.Sum(); - mesh.SubmeshIndexCount.Sum(); - mesh.SubmeshMaterials.Sum(); - } + //[Test] + //public static void GetMesh_IsSameMesh() + //{ + // var path = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); + // var scene = VimScene.LoadVim(path); + // for (var i = 0; i < scene.GetMeshCount(); i++) + // { + // var mesh = scene.MeshesOld[i]; + // var next = scene.MeshesNext[i]; + // var raw = scene.Meshes[i]; + // MeshesAreSame(mesh, next); + // MeshesAreSame(mesh, raw); + // } + //} + + //[Test] + //public static void GetMesh_Transform_IsSame() + //{ + // var path = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); + // var scene = VimScene.LoadVim(path); + // for (var i = 0; i < scene.GetMeshCount(); i++) + // { + // var mat = Matrix4x4.CreateWorld( + // new Vector3(1, -2, 3), + // new Vector3(0, 0, 1), + // new Vector3(0, 1, 0) + // ); + // var mesh = scene.MeshesOld[i].Transform(mat); + // var next = scene.MeshesNext[i].Transform(mat); + // var raw = scene.Meshes[i].Transform(mat); + // MeshesAreSame(mesh, next); + // MeshesAreSame(mesh, raw); + // } + //} + + //[Test] + //public static void ReverseWindingOrder_IsSame() + //{ + // var path = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); + // var scene = VimScene.LoadVim(path); + // for (var i = 0; i < scene.GetMeshCount(); i++) + // { + + // var mesh = scene.MeshesOld[i].ReverseWindingOrder() as IMesh; + // var next = scene.MeshesNext[i].ReverseWindingOrder(); + // var raw = scene.Meshes[i].ReverseWindingOrder(); + // MeshesAreSame(mesh, next); + // MeshesAreSame(mesh, raw); + // } + //} + + //[Test] + //public static void FaceMaterial_IsSame() + //{ + // var path = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); + // var scene = VimScene.LoadVim(path); + // for (var i = 0; i < scene.GetMeshCount(); i++) + // { + // var mesh = scene.MeshesOld[i].GetFaceMaterials(); + // var next = scene.MeshesNext[i].GetFaceMaterials(); + // var raw = scene.Meshes[i].GetFaceMaterials(); + // Assert.That(mesh.SequenceEquals(next)); + // Assert.That(next.SequenceEquals(raw)); + // } + //} + + //[Test] + //public static void Merge_ByPair_IsSame() + //{ + // var path = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); + // var scene = VimScene.LoadVim(path); + // for (var i = 1; i < scene.GetMeshCount(); i++) + // { + // var mesh = scene.MeshesOld[i].Merge(scene.MeshesOld[i - 1]); + // var next = scene.MeshesNext[i].Merge2(scene.MeshesNext[i - 1]); + // var raw = scene.Meshes[i].Merge2(scene.Meshes[i - 1]); + // MeshesAreSame(mesh, next); + // MeshesAreSame(mesh, raw); + // } + //} + + //[Test] + //public static void FromG3d_Equals_ToIMesh() + //{ + // var path = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); + // var scene = VimScene.LoadVim(path); + // var mesh = scene.Document.Geometry as IMesh; + // var next = VimMesh.FromG3d(scene.Document.GeometryNext); + // MeshesAreSame(mesh, next); + + //} + + //[Test] + //public static void Merge_All_IsSame() + //{ + // var path = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); + // var scene = VimScene.LoadVim(path); + + // var mesh = scene.MeshesOld[0].Merge(scene.MeshesOld.Skip(1).ToArray()); + // var next = scene.MeshesNext[0].Merge2(scene.MeshesNext.Skip(1).ToArray()); + // var raw = scene.Meshes[0].Merge2(scene.Meshes.Skip(1).ToArray()); + // MeshesAreSame(mesh, next); + // MeshesAreSame(mesh, raw); + //} + + //[Test] + //public static void SplitByMaterials_IsSame() + //{ + // var path = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); + // var scene = VimScene.LoadVim(path); + // for (var i = 0; i < scene.GetMeshCount(); i++) + // { + // var mesh = scene.MeshesOld[i].SplitByMaterial().ToArray(); + // var next = scene.MeshesNext[i].SplitByMaterial(); + // var raw = scene.Meshes[i].SplitByMaterial(); + // Assert.AreEqual(mesh.Length, next.Length); + // Assert.AreEqual(mesh.Length, raw.Length); + + // for (var j = 0; j < mesh.Length; j++) + // { + // MeshesAreSame(mesh[j].Mesh, next[j].mesh); + // MeshesAreSame(mesh[j].Mesh, raw[j].mesh); + // } + // } + //} + + //private static void Consume(IMesh mesh) + //{ + // mesh.Indices.Sum(); + // mesh.Vertices.Sum(v => v.X); + // mesh.SubmeshIndexOffsets.Sum(); + // mesh.SubmeshIndexCount.Sum(); + // mesh.SubmeshMaterials.Sum(); + //} private static void Consume(IMeshCommon mesh) { @@ -191,14 +191,14 @@ private static void Consume(IMeshCommon mesh) } - private static void MeshesAreSame(IMesh mesh, IMeshCommon next) - { - Assert.That(mesh.Indices.SequenceEquals(next.Indices)); - Assert.That(mesh.Vertices.SequenceEquals(next.Vertices)); - Assert.That(mesh.SubmeshIndexOffsets.SequenceEquals(next.SubmeshIndexOffsets)); - Assert.That(mesh.SubmeshMaterials.SequenceEquals(next.SubmeshMaterials)); - Assert.That(mesh.SubmeshIndexCount.SequenceEquals(next.SubmeshIndexCounts)); - } + //private static void MeshesAreSame(IMesh mesh, IMeshCommon next) + //{ + // Assert.That(mesh.Indices.SequenceEquals(next.Indices)); + // Assert.That(mesh.Vertices.SequenceEquals(next.Vertices)); + // Assert.That(mesh.SubmeshIndexOffsets.SequenceEquals(next.SubmeshIndexOffsets)); + // Assert.That(mesh.SubmeshMaterials.SequenceEquals(next.SubmeshMaterials)); + // Assert.That(mesh.SubmeshIndexCount.SequenceEquals(next.SubmeshIndexCounts)); + //} private static void MeshesAreSame(IMeshCommon mesh, IMeshCommon next) { Assert.That(mesh.Indices.SequenceEquals(next.Indices)); diff --git a/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs b/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs index 83f115a8..145975e3 100644 --- a/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs +++ b/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs @@ -59,7 +59,6 @@ public static VimScene LoadVim(Stream stream, IVimSceneProgress progress = null, => LoadVim(stream, new LoadOptions { SkipGeometry = skipGeometry, SkipAssets = skipAssets}, progress, inParallel); public int VimIndex { get; set; } - public IArray MeshesOld { get; private set; } public VimMesh[] MeshesNext { get; private set; } public IArray Meshes { get; private set; } public IArray Nodes { get; private set; } From a7c2e00425e9f25bacd2b265892c451ef44be2be Mon Sep 17 00:00:00 2001 From: simon Date: Wed, 10 Apr 2024 09:36:16 -0400 Subject: [PATCH 142/204] updating vimscene to g3dnext --- src/cs/g3d/Vim.G3dNext/G3dVim.cs | 18 +++++- .../Geometry/VimMaterialNext.cs | 30 +++++++++ .../Vim.Format.Core/Geometry/VimShapeNext.cs | 33 ++++++++++ .../Vim.Format.Core/SerializableDocument.cs | 6 +- .../SerializableDocumentTests.cs | 43 ++++++++++++- .../vim/Vim.Format/SceneBuilder/Validation.cs | 62 ------------------- .../vim/Vim.Format/SceneBuilder/VimScene.cs | 15 ++--- 7 files changed, 131 insertions(+), 76 deletions(-) create mode 100644 src/cs/vim/Vim.Format.Core/Geometry/VimMaterialNext.cs create mode 100644 src/cs/vim/Vim.Format.Core/Geometry/VimShapeNext.cs diff --git a/src/cs/g3d/Vim.G3dNext/G3dVim.cs b/src/cs/g3d/Vim.G3dNext/G3dVim.cs index dd2af2c6..b6447235 100644 --- a/src/cs/g3d/Vim.G3dNext/G3dVim.cs +++ b/src/cs/g3d/Vim.G3dNext/G3dVim.cs @@ -178,9 +178,25 @@ public int GetSubmeshIndexCount(int submesh) /// public int GetShapeCount() => ShapeVertexOffsets?.Length ?? 0; + + public int GetShapeVertexStart(int index) + { + return ShapeVertexOffsets[index]; + } + public int GetShapeVertexEnd(int index) + { + if (index + 1 >= ShapeVertexOffsets.Length) + { + return ShapeVertices.Length; + } + return ShapeVertexOffsets[index + 1]; + } /// /// The total number of shape vertices. /// - public int GetShapeVertexCount() => ShapeVertices?.Length ?? 0; + public int GetShapeVertexCount(int index) + { + return GetShapeVertexEnd(index) - GetShapeVertexStart(index); + } } } diff --git a/src/cs/vim/Vim.Format.Core/Geometry/VimMaterialNext.cs b/src/cs/vim/Vim.Format.Core/Geometry/VimMaterialNext.cs new file mode 100644 index 00000000..f359876e --- /dev/null +++ b/src/cs/vim/Vim.Format.Core/Geometry/VimMaterialNext.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using Vim.G3dNext; +using Vim.Math3d; + +namespace Vim.Format.Geometry +{ + public class VimMaterialNext + { + public G3dVim g3d; + public int index; + + public static IEnumerable FromG3d(G3dVim g3d) + { + for(var i =0; i < g3d.GetMaterialCount(); i++) + { + yield return new VimMaterialNext(g3d, i); + } + } + + public Vector4 Color => g3d.MaterialColors[index]; + public float Smoothness => g3d.MaterialSmoothness[index]; + public float Glossiness => g3d.MaterialGlossiness[index]; + public VimMaterialNext(G3dVim g3d, int index) + { + this.g3d = g3d; + this.index = index; + } + } +} diff --git a/src/cs/vim/Vim.Format.Core/Geometry/VimShapeNext.cs b/src/cs/vim/Vim.Format.Core/Geometry/VimShapeNext.cs new file mode 100644 index 00000000..10dcf2f3 --- /dev/null +++ b/src/cs/vim/Vim.Format.Core/Geometry/VimShapeNext.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using Vim.G3dNext; +using Vim.Math3d; + +namespace Vim.Format.Geometry +{ + public class VimShapeNext + { + public readonly G3dVim g3d; + public readonly int Index; + public readonly ArraySegment Vertices; + + public Vector4 Color => g3d.ShapeColors[Index]; + public float Width => g3d.ShapeWidths[Index]; + + public static IEnumerable FromG3d(G3dVim g3d) + { + for(var i =0; i < g3d.GetShapeCount(); i++) + { + yield return new VimShapeNext(g3d, i); + } + } + + public VimShapeNext(G3dVim g3d, int index) + { + var start = g3d.GetShapeVertexStart(index); + var count = g3d.GetShapeVertexCount(index); + + Vertices = new ArraySegment(g3d.ShapeVertices, start, count); + } + } +} diff --git a/src/cs/vim/Vim.Format.Core/SerializableDocument.cs b/src/cs/vim/Vim.Format.Core/SerializableDocument.cs index 99318a01..31f1772e 100644 --- a/src/cs/vim/Vim.Format.Core/SerializableDocument.cs +++ b/src/cs/vim/Vim.Format.Core/SerializableDocument.cs @@ -96,9 +96,9 @@ public BFast ToBFast() bfast.SetArray(BufferNames.Strings, BFastStrings.Pack(StringTable)); } - if(Geometry != null) + if(GeometryNext != null) { - bfast.SetBFast(BufferNames.Geometry, Geometry?.ToBFast()); + bfast.SetBFast(BufferNames.Geometry, GeometryNext.ToBFast()); } return bfast; @@ -127,8 +127,8 @@ public static SerializableDocument FromBFast(BFast bfast, LoadOptions options = if (!doc.Options.SkipGeometry) { var geo = bfast.GetBFast(BufferNames.Geometry); - doc.Geometry = G3D.Read(geo); doc.GeometryNext = new G3dVim(geo); + doc.Geometry = G3D.Read(geo); } var entities = bfast.GetBFast(BufferNames.Entities); diff --git a/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs b/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs index b4cd0c6b..39198891 100644 --- a/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs +++ b/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs @@ -36,16 +36,39 @@ public static void CanOpenVim() } [Test] - public static void MaterialColor_IsSame() + public static void ShapesAreSame() { var path = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); var scene = VimScene.LoadVim(path); - for (var i = 0; i < scene.GetMaterialCount(); i++) + + var shapes = scene.VimShapes; + var next = scene.VimShapesNext; + Assert.AreEqual(shapes.Count, next.Length); + for (var i = 0; i < shapes.Count; i++) + { + ShapesAreSame(shapes[i], next[i]); + } + } + + + + [Test] + public static void Materials_AreSame() + { + var path = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); + var scene = VimScene.LoadVim(path); + + var mats = scene.Materials; + var next = scene.MaterialsNext; + Assert.AreEqual(mats.Count, next.Length); + for (var i = 0; i < mats.Count; i++) { - Assert.AreEqual(scene.GetMaterialColor(i), scene.GetMaterialColorNext(i)); + MaterialsAreSame(mats[i], next[i]); } + } + //[Test] //public static void GetMesh_IsSameMesh() //{ @@ -208,6 +231,20 @@ private static void MeshesAreSame(IMeshCommon mesh, IMeshCommon next) Assert.That(mesh.SubmeshIndexCounts.SequenceEquals(next.SubmeshIndexCounts)); } + private static void ShapesAreSame(VimShape mesh, VimShapeNext next) + { + Assert.That(mesh.Vertices.ToEnumerable().SequenceEqual(next.Vertices)); + Assert.AreEqual(mesh.Color, next.Color); + Assert.AreEqual(mesh.Width, next.Width); + } + + private static void MaterialsAreSame(IMaterial mesh, VimMaterialNext next) + { + Assert.AreEqual(mesh.Color, next.Color); + Assert.AreEqual(mesh.Glossiness, next.Glossiness); + Assert.AreEqual(mesh.Smoothness, next.Smoothness); + } + diff --git a/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs b/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs index dcde1a3b..d9d81843 100644 --- a/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs +++ b/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs @@ -24,7 +24,6 @@ public class VimValidationException : Exception { public VimValidationException(string message) : base(message) { } } - public static void ValidateGeometry(this VimScene vim) { // Validate the packed geometry. @@ -40,66 +39,6 @@ public static void ValidateGeometryNext(this VimScene vim) vim.Document.GeometryNext.Validate(); } - public static void ValidateDocumentModelToG3dInvariants(this VimScene vim) - { - var g3d = vim._SerializableDocument.Geometry; - var errors = new List(); - - var entityTypesWithG3dReferences = new HashSet<(Type, G3dAttributeReferenceAttribute[])>( - ObjectModelReflection.GetEntityTypes() - .Select(t => ( - type: t, - attrs: t.GetCustomAttributes(typeof(G3dAttributeReferenceAttribute)) - .Select(a => a as G3dAttributeReferenceAttribute) - .ToArray())) - .Where(tuple => tuple.attrs.Length != 0)); - - var dm = vim.DocumentModel; - - foreach (var tuple in entityTypesWithG3dReferences) - { - var (type, attrs) = tuple; - var propertyName = type.Name + "List"; - if (dm.GetPropertyValue(propertyName) is IArray arr) - { - var numEntities = arr.Count; - - foreach (var attr in attrs) - { - var attributeName = attr.AttributeName; - var isOptional = attr.AttributeIsOptional; - - var g3dAttribute = g3d.GetAttribute(attributeName); - - // We don't check the relation if the attribute is optional and absent (null). - if (isOptional && g3dAttribute == null) - continue; - - var g3dElementCount = g3dAttribute?.ElementCount ?? 0; - var mult = attr.AttributeReferenceMultiplicity; - - // Validate one-to-one relationships - if (mult == G3dAttributeReferenceMultiplicity.OneToOne && numEntities != g3dElementCount) - { - errors.Add($"Multiplicity Error ({mult}); the number of entities of type \"{type.Name}\" ({numEntities}) is not equal to the number of elements in the g3d attribute \"{attributeName}\" ({g3dElementCount})"); - } - } - } - else - { - throw new VimValidationException($"DocumentModel.{propertyName} not found"); - } - } - - if (errors.Count > 0) - { - throw new VimValidationException( - $"DocumentModel to G3d invariant error(s):{Environment.NewLine}{string.Join(Environment.NewLine, errors)}"); - } - } - - - public static void ValidateDocumentModelToG3dInvariantsNext(this VimScene vim) { var g3d = vim.Document.GeometryNext; @@ -203,7 +142,6 @@ public static void Validate(this VimScene vim, VimValidationOptions options = nu vim.ValidateGeometry(); vim.ValidateGeometryNext(); - vim.ValidateDocumentModelToG3dInvariants(); vim.ValidateDocumentModelToG3dInvariantsNext(); vim.ValidateNodes(); diff --git a/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs b/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs index 145975e3..40c98e50 100644 --- a/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs +++ b/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs @@ -64,7 +64,9 @@ public static VimScene LoadVim(Stream stream, IVimSceneProgress progress = null, public IArray Nodes { get; private set; } public IArray VimNodes { get; private set; } public IArray VimShapes { get; private set; } + public VimShapeNext[] VimShapesNext { get; private set; } public IArray Materials { get; private set; } + public VimMaterialNext[] MaterialsNext { get; private set; } public SerializableDocument _SerializableDocument { get; } public Document Document { get; private set; } @@ -75,10 +77,7 @@ public string PersistingId public int GetMeshCount() => Meshes.Count; public int GetMaterialCount() => Materials.Count; - - public Vector4 GetMaterialColor(int materialIndex) - => _SerializableDocument.Geometry.MaterialColors[materialIndex]; - + public Vector4 GetMaterialColorNext(int materialIndex) => _SerializableDocument.GeometryNext.MaterialColors[materialIndex]; @@ -183,7 +182,7 @@ private IStep[] GetInitSteps(bool inParallel) private void CreateMeshes(bool inParallel) { - if (_SerializableDocument.Geometry == null) + if (_SerializableDocument.GeometryNext == null) { return; } @@ -195,13 +194,13 @@ private void CreateMeshes(bool inParallel) private void CreateShapes(bool inParallel) { - if (_SerializableDocument.Geometry == null) + if (_SerializableDocument.GeometryNext == null) { return; } - var r = _SerializableDocument.Geometry.Shapes.Select((s, i) => new VimShape(this, i)); VimShapes = inParallel ? r.EvaluateInParallel() : r.Evaluate(); + VimShapesNext = VimShapeNext.FromG3d(_SerializableDocument.GeometryNext).ToArray(); } private void CreateScene(bool inParallel) @@ -224,6 +223,8 @@ private void CreateMaterials(bool inParallel) var query = _SerializableDocument.Geometry.Materials.Select(m => new VimMaterial(m) as IMaterial); Materials = inParallel ? query.EvaluateInParallel() : query.Evaluate(); + MaterialsNext = VimMaterialNext.FromG3d(_SerializableDocument.GeometryNext).ToArray(); + } public static IArray CreateVimSceneNodes(VimScene scene, G3D g3d, bool inParallel) From b6930ee736e6496cd5a9e9ce980ec029075aa243 Mon Sep 17 00:00:00 2001 From: simon Date: Wed, 10 Apr 2024 10:20:58 -0400 Subject: [PATCH 143/204] removing conversions of materials --- src/cs/vim/Vim.Format.Core/DocumentBuilder.cs | 3 ++- src/cs/vim/Vim.Format.Core/DocumentBuilderExtensions.cs | 8 -------- src/cs/vim/Vim.Format.Core/DocumentBuilderTypes.cs | 9 +++++---- src/cs/vim/Vim.Format.Core/G3dBuilder.cs | 5 +++-- 4 files changed, 10 insertions(+), 15 deletions(-) diff --git a/src/cs/vim/Vim.Format.Core/DocumentBuilder.cs b/src/cs/vim/Vim.Format.Core/DocumentBuilder.cs index d90c1d6a..6d408df5 100644 --- a/src/cs/vim/Vim.Format.Core/DocumentBuilder.cs +++ b/src/cs/vim/Vim.Format.Core/DocumentBuilder.cs @@ -6,6 +6,7 @@ using Vim.BFastLib; using System.IO; using Vim.Util; +using Vim.Format.Geometry; namespace Vim.Format { @@ -84,7 +85,7 @@ public DocumentBuilder AddInstance(Matrix4x4 transform, int meshIndex, int paren return this; } - public DocumentBuilder AddMaterials(IEnumerable materials) + public DocumentBuilder AddMaterials(IEnumerable materials) { foreach (var material in materials) { diff --git a/src/cs/vim/Vim.Format.Core/DocumentBuilderExtensions.cs b/src/cs/vim/Vim.Format.Core/DocumentBuilderExtensions.cs index abdfeb48..02ae2464 100644 --- a/src/cs/vim/Vim.Format.Core/DocumentBuilderExtensions.cs +++ b/src/cs/vim/Vim.Format.Core/DocumentBuilderExtensions.cs @@ -10,14 +10,6 @@ namespace Vim.Format { public static class DocumentBuilderExtensions { - public static Material ToDocumentBuilderMaterial(this G3dMaterial g3dMaterial) - => new Material - { - Color = g3dMaterial.Color, - Glossiness = g3dMaterial.Glossiness, - Smoothness = g3dMaterial.Smoothness, - }; - public static SubdividedMesh ToDocumentBuilderSubdividedMesh(this IMeshCommon m) => new SubdividedMesh( m.Indices.ToList(), diff --git a/src/cs/vim/Vim.Format.Core/DocumentBuilderTypes.cs b/src/cs/vim/Vim.Format.Core/DocumentBuilderTypes.cs index 497c4ffa..a93c5543 100644 --- a/src/cs/vim/Vim.Format.Core/DocumentBuilderTypes.cs +++ b/src/cs/vim/Vim.Format.Core/DocumentBuilderTypes.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using Vim.Format.Geometry; using Vim.G3d; using Vim.Math3d; @@ -23,12 +24,12 @@ public class Shape public float Width; } - public class Material + public class Material : IMaterial { //RGBA - public Vector4 Color; - public float Glossiness; - public float Smoothness; + public Vector4 Color { get; private set; } + public float Glossiness { get; private set; } + public float Smoothness { get; private set; } } /// diff --git a/src/cs/vim/Vim.Format.Core/G3dBuilder.cs b/src/cs/vim/Vim.Format.Core/G3dBuilder.cs index 258e1f52..3d4ce2f8 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.BFastLib; using static Vim.Format.DocumentBuilder; using Vim.Math3d; +using Vim.Format.Geometry; namespace Vim.Format { @@ -12,7 +13,7 @@ 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(); + private readonly List _materials = new List(); public void AddMesh(SubdividedMesh mesh) { @@ -29,7 +30,7 @@ public void AddShape(Shape shape) _shapes.Add(shape); } - public void AddMaterial(Material material) + public void AddMaterial(IMaterial material) { _materials.Add(material); } From 293ed9e60fc065ae4ae94315f878ee0da278ec28 Mon Sep 17 00:00:00 2001 From: simon Date: Wed, 10 Apr 2024 10:20:58 -0400 Subject: [PATCH 144/204] removing conversions of materials --- src/cs/vim/Vim.Format.Core/DocumentBuilder.cs | 3 ++- src/cs/vim/Vim.Format.Core/DocumentBuilderExtensions.cs | 8 -------- src/cs/vim/Vim.Format.Core/DocumentBuilderTypes.cs | 9 +++++---- src/cs/vim/Vim.Format.Core/G3dBuilder.cs | 5 +++-- 4 files changed, 10 insertions(+), 15 deletions(-) diff --git a/src/cs/vim/Vim.Format.Core/DocumentBuilder.cs b/src/cs/vim/Vim.Format.Core/DocumentBuilder.cs index d90c1d6a..6d408df5 100644 --- a/src/cs/vim/Vim.Format.Core/DocumentBuilder.cs +++ b/src/cs/vim/Vim.Format.Core/DocumentBuilder.cs @@ -6,6 +6,7 @@ using Vim.BFastLib; using System.IO; using Vim.Util; +using Vim.Format.Geometry; namespace Vim.Format { @@ -84,7 +85,7 @@ public DocumentBuilder AddInstance(Matrix4x4 transform, int meshIndex, int paren return this; } - public DocumentBuilder AddMaterials(IEnumerable materials) + public DocumentBuilder AddMaterials(IEnumerable materials) { foreach (var material in materials) { diff --git a/src/cs/vim/Vim.Format.Core/DocumentBuilderExtensions.cs b/src/cs/vim/Vim.Format.Core/DocumentBuilderExtensions.cs index abdfeb48..02ae2464 100644 --- a/src/cs/vim/Vim.Format.Core/DocumentBuilderExtensions.cs +++ b/src/cs/vim/Vim.Format.Core/DocumentBuilderExtensions.cs @@ -10,14 +10,6 @@ namespace Vim.Format { public static class DocumentBuilderExtensions { - public static Material ToDocumentBuilderMaterial(this G3dMaterial g3dMaterial) - => new Material - { - Color = g3dMaterial.Color, - Glossiness = g3dMaterial.Glossiness, - Smoothness = g3dMaterial.Smoothness, - }; - public static SubdividedMesh ToDocumentBuilderSubdividedMesh(this IMeshCommon m) => new SubdividedMesh( m.Indices.ToList(), diff --git a/src/cs/vim/Vim.Format.Core/DocumentBuilderTypes.cs b/src/cs/vim/Vim.Format.Core/DocumentBuilderTypes.cs index 497c4ffa..a93c5543 100644 --- a/src/cs/vim/Vim.Format.Core/DocumentBuilderTypes.cs +++ b/src/cs/vim/Vim.Format.Core/DocumentBuilderTypes.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using Vim.Format.Geometry; using Vim.G3d; using Vim.Math3d; @@ -23,12 +24,12 @@ public class Shape public float Width; } - public class Material + public class Material : IMaterial { //RGBA - public Vector4 Color; - public float Glossiness; - public float Smoothness; + public Vector4 Color { get; private set; } + public float Glossiness { get; private set; } + public float Smoothness { get; private set; } } /// diff --git a/src/cs/vim/Vim.Format.Core/G3dBuilder.cs b/src/cs/vim/Vim.Format.Core/G3dBuilder.cs index 258e1f52..3d4ce2f8 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.BFastLib; using static Vim.Format.DocumentBuilder; using Vim.Math3d; +using Vim.Format.Geometry; namespace Vim.Format { @@ -12,7 +13,7 @@ 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(); + private readonly List _materials = new List(); public void AddMesh(SubdividedMesh mesh) { @@ -29,7 +30,7 @@ public void AddShape(Shape shape) _shapes.Add(shape); } - public void AddMaterial(Material material) + public void AddMaterial(IMaterial material) { _materials.Add(material); } From b3c63206edae49fdfc18e3c1ef1fda3c364f181d Mon Sep 17 00:00:00 2001 From: simon Date: Wed, 10 Apr 2024 12:54:11 -0400 Subject: [PATCH 145/204] materialnext: imaterial --- src/cs/vim/Vim.Format.Core/Geometry/VimMaterialNext.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cs/vim/Vim.Format.Core/Geometry/VimMaterialNext.cs b/src/cs/vim/Vim.Format.Core/Geometry/VimMaterialNext.cs index f359876e..fd915fc8 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/VimMaterialNext.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/VimMaterialNext.cs @@ -5,7 +5,7 @@ namespace Vim.Format.Geometry { - public class VimMaterialNext + public class VimMaterialNext : IMaterial { public G3dVim g3d; public int index; From 1d19d3b7147ce458a8ec12de3b4559362cd31799 Mon Sep 17 00:00:00 2001 From: simon Date: Wed, 10 Apr 2024 13:01:36 -0400 Subject: [PATCH 146/204] added shape count --- src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs b/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs index 40c98e50..c335462f 100644 --- a/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs +++ b/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs @@ -76,7 +76,9 @@ public string PersistingId => Document.Header.PersistingId; public int GetMeshCount() => Meshes.Count; - public int GetMaterialCount() => Materials.Count; + public int GetMaterialCount() => MaterialsNext.Length; + + public int GetShapeCount() => VimShapesNext.Length; public Vector4 GetMaterialColorNext(int materialIndex) => _SerializableDocument.GeometryNext.MaterialColors[materialIndex]; From e4b04c0e9a942759dd8f9e0b54a18c8b6f0ca77b Mon Sep 17 00:00:00 2001 From: simon Date: Wed, 10 Apr 2024 13:40:11 -0400 Subject: [PATCH 147/204] Renamed shapes and materials to old --- .../SerializableDocumentTests.cs | 8 ++++---- .../vim/Vim.Format/SceneBuilder/Validation.cs | 2 +- .../vim/Vim.Format/SceneBuilder/VimScene.cs | 20 +++++++++---------- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs b/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs index 585d5783..49814ab1 100644 --- a/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs +++ b/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs @@ -37,8 +37,8 @@ public static void ShapesAreSame() var path = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); var scene = VimScene.LoadVim(path); - var shapes = scene.VimShapes; - var next = scene.VimShapesNext; + var shapes = scene.ShapesOld; + var next = scene.Shapes; Assert.AreEqual(shapes.Count, next.Length); for (var i = 0; i < shapes.Count; i++) { @@ -54,8 +54,8 @@ public static void Materials_AreSame() var path = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); var scene = VimScene.LoadVim(path); - var mats = scene.Materials; - var next = scene.MaterialsNext; + var mats = scene.MaterialsOld; + var next = scene.Materials; Assert.AreEqual(mats.Count, next.Length); for (var i = 0; i < mats.Count; i++) { diff --git a/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs b/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs index d9d81843..98d3f658 100644 --- a/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs +++ b/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs @@ -104,7 +104,7 @@ public static void ValidateNodes(this VimScene vim) public static void ValidateShapes(this VimScene vim) { - var shapes = vim.VimShapes; + var shapes = vim.ShapesOld; var numShapes = vim.DocumentModel.NumShape; if (shapes.Count != numShapes) throw new VimValidationException($"The number of {nameof(VimShape)} ({shapes.Count}) does not match the number of shape entities ({numShapes})"); diff --git a/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs b/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs index c335462f..2626bcc9 100644 --- a/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs +++ b/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs @@ -63,10 +63,10 @@ public static VimScene LoadVim(Stream stream, IVimSceneProgress progress = null, public IArray Meshes { get; private set; } public IArray Nodes { get; private set; } public IArray VimNodes { get; private set; } - public IArray VimShapes { get; private set; } - public VimShapeNext[] VimShapesNext { get; private set; } - public IArray Materials { get; private set; } - public VimMaterialNext[] MaterialsNext { get; private set; } + public IArray ShapesOld { get; private set; } + public VimShapeNext[] Shapes { get; private set; } + public IArray MaterialsOld { get; private set; } + public VimMaterialNext[] Materials { get; private set; } public SerializableDocument _SerializableDocument { get; } public Document Document { get; private set; } @@ -76,9 +76,9 @@ public string PersistingId => Document.Header.PersistingId; public int GetMeshCount() => Meshes.Count; - public int GetMaterialCount() => MaterialsNext.Length; + public int GetMaterialCount() => Materials.Length; - public int GetShapeCount() => VimShapesNext.Length; + public int GetShapeCount() => Shapes.Length; public Vector4 GetMaterialColorNext(int materialIndex) => _SerializableDocument.GeometryNext.MaterialColors[materialIndex]; @@ -201,8 +201,8 @@ private void CreateShapes(bool inParallel) return; } var r = _SerializableDocument.Geometry.Shapes.Select((s, i) => new VimShape(this, i)); - VimShapes = inParallel ? r.EvaluateInParallel() : r.Evaluate(); - VimShapesNext = VimShapeNext.FromG3d(_SerializableDocument.GeometryNext).ToArray(); + ShapesOld = inParallel ? r.EvaluateInParallel() : r.Evaluate(); + Shapes = VimShapeNext.FromG3d(_SerializableDocument.GeometryNext).ToArray(); } private void CreateScene(bool inParallel) @@ -224,8 +224,8 @@ private void CreateMaterials(bool inParallel) } var query = _SerializableDocument.Geometry.Materials.Select(m => new VimMaterial(m) as IMaterial); - Materials = inParallel ? query.EvaluateInParallel() : query.Evaluate(); - MaterialsNext = VimMaterialNext.FromG3d(_SerializableDocument.GeometryNext).ToArray(); + MaterialsOld = inParallel ? query.EvaluateInParallel() : query.Evaluate(); + Materials = VimMaterialNext.FromG3d(_SerializableDocument.GeometryNext).ToArray(); } From f54b8416172293804743076680fb8860968eb0de Mon Sep 17 00:00:00 2001 From: simon Date: Wed, 10 Apr 2024 13:49:49 -0400 Subject: [PATCH 148/204] explicit implementation of transform --- .../vim/Vim.Format.Core/Geometry/VimMesh.cs | 19 ++++++++++--------- .../vim/Vim.Format/SceneBuilder/VimScene.cs | 4 ++-- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs b/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs index b9dada16..2a73975f 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs @@ -47,7 +47,7 @@ public VimMesh() } public VimMesh(Vector3[] vertices) - : this(Enumerable.Range(0,vertices.Length).ToArray(), vertices) + : this(Enumerable.Range(0, vertices.Length).ToArray(), vertices) { } @@ -73,7 +73,7 @@ public G3dVim ToG3d() return new G3dVim( indices: indices, positions: vertices, - instanceMeshes: new[] {0}, + instanceMeshes: new[] { 0 }, instanceTransforms: new[] { Matrix4x4.Identity }, instanceParents: null, instanceFlags: null, @@ -123,7 +123,8 @@ public VimMesh Clone() } IMeshCommon IMeshCommon.Clone() => Clone(); - public IMeshCommon Transform(Matrix4x4 mat) + IMeshCommon ITransformable3D.Transform(Matrix4x4 mat) => Transform(mat); + public VimMesh Transform(Matrix4x4 mat) { var mesh = Clone(); @@ -188,7 +189,7 @@ public static VimMesh FromG3d(G3dVim g3d) public static VimMesh FromQuad(int[] indices, Vector3[] vertices) { - if(indices.Length % 4 != 0) + if (indices.Length % 4 != 0) { throw new ArgumentException("Indices count should be a multiple of 4."); } @@ -260,10 +261,10 @@ public static IMeshCommon Merge2(this IMeshCommon mesh, params IMeshCommon[] oth .Append(mesh) .Append(others) .ToArray(); - + return meshes.Merge(); } - + public static IMeshCommon Merge(this IMeshCommon[] meshes) { void Merge(IArray from, int[] to, int offset, int increment) @@ -393,9 +394,9 @@ public static bool GeometryEquals(this IMeshCommon mesh, IMeshCommon other, floa if (mesh.Vertices.Count != other.Vertices.Count) return false; - for(var i = 0; i < mesh.Vertices.Count; i++) + for (var i = 0; i < mesh.Vertices.Count; i++) { - if(!mesh.Vertices[i].AlmostEquals(other.Vertices[i], tolerance)) + if (!mesh.Vertices[i].AlmostEquals(other.Vertices[i], tolerance)) return false; } @@ -413,7 +414,7 @@ public static (int mat, IMeshCommon mesh)[] SplitByMaterial(this IMeshCommon mes return result; } - for (var i =0; i < map.Length; i++) + for (var i = 0; i < map.Length; i++) { var (mat, subs) = map[i]; var pick = mesh.PickSubmeshes(subs); diff --git a/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs b/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs index 2626bcc9..1e30bf3e 100644 --- a/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs +++ b/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs @@ -244,10 +244,10 @@ public void Save(string filePath) public string FileName => _SerializableDocument.FileName; - public void TransformSceneInPlace(Func meshTransform = null, Func nodeTransform = null) + public void TransformSceneInPlace(Func meshTransform = null, Func nodeTransform = null) { if (meshTransform != null) - Meshes = Meshes.Select(meshTransform).EvaluateInParallel(); + MeshesNext = MeshesNext.Select(meshTransform).ToArray(); if (nodeTransform != null) VimNodes = VimNodes.Select(nodeTransform).EvaluateInParallel(); } From a36dcd57bb5beb796c210fdd61b1bd3f14790550 Mon Sep 17 00:00:00 2001 From: simon Date: Wed, 10 Apr 2024 15:03:07 -0400 Subject: [PATCH 149/204] removing builder types --- src/cs/g3d/Vim.G3dNext/Constants.cs | 7 +++ src/cs/vim/Vim.Format.Core/DocumentBuilder.cs | 4 +- .../Vim.Format.Core/DocumentBuilderTypes.cs | 43 ++++++++++++++++--- src/cs/vim/Vim.Format.Core/G3dBuilder.cs | 20 ++++----- src/cs/vim/Vim.Format.Core/Geometry/IScene.cs | 2 +- .../vim/Vim.Format.Core/Geometry/VimMesh.cs | 2 + .../ObjectModel/ObjectModelStore.cs | 8 ---- .../vim/Vim.Format/SceneBuilder/Validation.cs | 25 +++-------- .../vim/Vim.Format/SceneBuilder/VimScene.cs | 19 ++++---- .../Vim.Format/SceneBuilder/VimSceneNode.cs | 3 +- 10 files changed, 77 insertions(+), 56 deletions(-) diff --git a/src/cs/g3d/Vim.G3dNext/Constants.cs b/src/cs/g3d/Vim.G3dNext/Constants.cs index c8cc2282..8442d63a 100644 --- a/src/cs/g3d/Vim.G3dNext/Constants.cs +++ b/src/cs/g3d/Vim.G3dNext/Constants.cs @@ -29,6 +29,13 @@ public static bool SafeEqual(this T[] a, T[] b) } return true; } + + public static T SafeGet(this T[] a, int i) where T : class + { + if (i < 0) return null; + if (i >= a.Length) return null; + return a[i]; + } } public static class Constants diff --git a/src/cs/vim/Vim.Format.Core/DocumentBuilder.cs b/src/cs/vim/Vim.Format.Core/DocumentBuilder.cs index 6d408df5..c5b1e68b 100644 --- a/src/cs/vim/Vim.Format.Core/DocumentBuilder.cs +++ b/src/cs/vim/Vim.Format.Core/DocumentBuilder.cs @@ -49,13 +49,13 @@ public DocumentBuilder AddAsset(string name, byte[] asset) return this; } - public DocumentBuilder AddMesh(SubdividedMesh mesh) + public DocumentBuilder AddMesh(VimMesh mesh) { Geometry.AddMesh(mesh); return this; } - public DocumentBuilder AddMeshes(IEnumerable meshes) + public DocumentBuilder AddMeshes(IEnumerable meshes) { foreach (var m in meshes) { diff --git a/src/cs/vim/Vim.Format.Core/DocumentBuilderTypes.cs b/src/cs/vim/Vim.Format.Core/DocumentBuilderTypes.cs index a93c5543..ca2c4f94 100644 --- a/src/cs/vim/Vim.Format.Core/DocumentBuilderTypes.cs +++ b/src/cs/vim/Vim.Format.Core/DocumentBuilderTypes.cs @@ -4,6 +4,7 @@ using Vim.Format.Geometry; using Vim.G3d; using Vim.Math3d; +using static Vim.Format.DocumentBuilder; namespace Vim.Format { @@ -27,9 +28,9 @@ public class Shape public class Material : IMaterial { //RGBA - public Vector4 Color { get; private set; } - public float Glossiness { get; private set; } - public float Smoothness { get; private set; } + public Vector4 Color { get; set; } + public float Glossiness { get; set; } + public float Smoothness { get; set; } } /// @@ -72,6 +73,7 @@ public Mesh(List vertices = null, List indices = null, List f _uvs = uvs ?? new List(); } + public void SetMeshMaterial(int material) => _faceMaterials = Enumerable.Repeat(material, _indices.Count / 3).ToList(); @@ -101,8 +103,39 @@ public void AppendVertices(IEnumerable vertices) public void AppendUVs(IEnumerable uvs) => _uvs.AddRange(uvs); - public SubdividedMesh Subdivide() - => new SubdividedMesh(this); + public VimMesh Subdivide() + { + if (Indices.Any(i => i < 0 && i >= Vertices.Count)) + throw new Exception($"Invalid mesh. Indices out of vertex range."); + + var facesByMats = FaceMaterials + .Select((face, index) => (face, index)) + .GroupBy(pair => pair.face, pair => pair.index); + + var submeshIndexOffsets = new List(); + var submeshMaterials = new List(); + var indicesRemap = new List(); + + foreach (var group in facesByMats) + { + submeshIndexOffsets.Add(indicesRemap.Count); + submeshMaterials.Add(group.Key); + foreach (var face in group) + { + var f = face * 3; + indicesRemap.Add(Indices[f]); + indicesRemap.Add(Indices[f + 1]); + indicesRemap.Add(Indices[f + 2]); + } + } + return new VimMesh( + indicesRemap.ToArray(), + Vertices.ToArray(), + submeshIndexOffsets.ToArray(), + submeshMaterials.ToArray() + ); + + } } /// diff --git a/src/cs/vim/Vim.Format.Core/G3dBuilder.cs b/src/cs/vim/Vim.Format.Core/G3dBuilder.cs index 3d4ce2f8..76a4304c 100644 --- a/src/cs/vim/Vim.Format.Core/G3dBuilder.cs +++ b/src/cs/vim/Vim.Format.Core/G3dBuilder.cs @@ -10,12 +10,12 @@ namespace Vim.Format { public class G3dBuilder { - private readonly List _meshes = new List(); + 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) + public void AddMesh(VimMesh mesh) { _meshes.Add(mesh); } @@ -40,10 +40,10 @@ public void AddMaterial(IMaterial material) public int MaterialCount => _materials.Count; public int ShapeCount => _shapes.Count; - public SubdividedMesh GetMesh(int index) => _meshes[index]; + public IMeshCommon GetMesh(int index) => _meshes[index]; public AABox GetBox(int meshIndex) { - return AABox.Create(_meshes[meshIndex].Vertices); + return AABox.Create(_meshes[meshIndex].vertices); } public int[] GetVertexCounts() @@ -60,7 +60,7 @@ public int[] GetFaceCounts() public BFast ToBFast() { var bfast = new BFast(); - var totalSubmeshCount = _meshes.Select(s => s.SubmeshesIndexOffset.Count).Sum(); + var totalSubmeshCount = _meshes.Select(s => s.SubmeshCount).Sum(); // Compute the Vertex offsets and index offsets var meshVertexOffsets = new int[_meshes.Count]; @@ -74,14 +74,14 @@ public BFast ToBFast() { 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; + meshSubmeshOffset[i] = meshSubmeshOffset[i - 1] + _meshes[i - 1].SubmeshCount; } var subIndex = 0; var previousIndexCount = 0; foreach (var geo in _meshes) { - foreach (var sub in geo.SubmeshesIndexOffset) + foreach (var sub in geo.submeshIndexOffsets) { submeshIndexOffsets[subIndex++] = sub + previousIndexCount; } @@ -96,11 +96,11 @@ public BFast ToBFast() shapeVertexOffsets[i] = shapeVertexOffsets[i - 1] + _shapes[i - 1].Vertices.Count; } - bfast.SetEnumerable(CommonAttributes.Position, () => _meshes.SelectMany(m => m.Vertices)); - bfast.SetEnumerable(CommonAttributes.Index, () => _meshes.SelectMany(m => m.Indices)); + 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.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)); diff --git a/src/cs/vim/Vim.Format.Core/Geometry/IScene.cs b/src/cs/vim/Vim.Format.Core/Geometry/IScene.cs index 4f7208cd..a618151c 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/IScene.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/IScene.cs @@ -11,7 +11,7 @@ namespace Vim.Format.Geometry public interface IScene { IArray Nodes { get; } - IArray Meshes { get; } + IArray MeshesOld { get; } } /// diff --git a/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs b/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs index 2a73975f..03516d76 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs @@ -19,6 +19,8 @@ public class VimMesh : IMeshCommon public IArray SubmeshIndexOffsets => submeshIndexOffsets.ToIArray(); public IArray SubmeshIndexCounts => submeshIndexCounts.ToIArray(); + public int SubmeshCount => submeshIndexCounts.Length; + public int NumCornersPerFace => 3; public int NumVertices => vertices.Length; diff --git a/src/cs/vim/Vim.Format/ObjectModel/ObjectModelStore.cs b/src/cs/vim/Vim.Format/ObjectModel/ObjectModelStore.cs index b2fa3243..4cb5d0e5 100644 --- a/src/cs/vim/Vim.Format/ObjectModel/ObjectModelStore.cs +++ b/src/cs/vim/Vim.Format/ObjectModel/ObjectModelStore.cs @@ -28,14 +28,6 @@ public DocumentBuilder ToDocumentBuilder(string generator, string versionString) .AddMaterials(CreateMaterialBuilders()); } - private IEnumerable CreateMaterialBuilders() - => ObjectModelBuilder.GetEntities().Select(m => new DocumentBuilder.Material() - { - Color = new Vector4((float) m.Color.X, (float) m.Color.Y, (float) m.Color.Z, (float)(1 - m.Transparency)), - Glossiness = (float) m.Glossiness, - Smoothness = (float) m.Smoothness - }); - /// /// Mutates the Meshes and Instances to remove any meshes which are not referenced by at least one instance. /// diff --git a/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs b/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs index 98d3f658..6fda7aaf 100644 --- a/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs +++ b/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs @@ -104,10 +104,9 @@ public static void ValidateNodes(this VimScene vim) public static void ValidateShapes(this VimScene vim) { - var shapes = vim.ShapesOld; - var numShapes = vim.DocumentModel.NumShape; - if (shapes.Count != numShapes) - throw new VimValidationException($"The number of {nameof(VimShape)} ({shapes.Count}) does not match the number of shape entities ({numShapes})"); + var shapes = vim.Shapes; + if (vim.GetShapeCount() != vim.DocumentModel.NumShape) + throw new VimValidationException($"The number of {nameof(VimShape)} ({vim.GetShapeCount()}) does not match the number of shape entities ({vim.DocumentModel.NumShape})"); void ValidateColorDomain(string label, Vector4 value, Vector4 lowerInclusive, Vector4 upperInclusive, int index) { @@ -124,10 +123,10 @@ void ValidateColorDomain(string label, Vector4 value, Vector4 lowerInclusive, Ve } } - Parallel.For(0, numShapes, shapeIndex => + Parallel.For(0, vim.GetShapeCount(), shapeIndex => { var shape = shapes[shapeIndex]; - if (shape.ElementIndex < 0) + if (vim.DocumentModel.GetShapeElementIndex(shapeIndex) < 0) throw new VimValidationException($"{nameof(Element)} is null for {nameof(VimShape)} {shape.ShapeIndex}"); ValidateColorDomain($"{nameof(VimShape)} color", shape.Color, Vector4.Zero, Vector4.One, shape.ShapeIndex); }); @@ -150,20 +149,6 @@ public static void Validate(this VimScene vim, VimValidationOptions options = nu public static void ValidateEquality(this DocumentBuilder db, VimScene vim) { - // Test the geometry both ways - var vimGeoBuilders = vim.Meshes.Select(g => new DocumentBuilder.SubdividedMesh( - g.Indices.ToList(), - g.Vertices.ToList(), - g.SubmeshIndexOffsets.ToList(), - g.SubmeshMaterials.ToList() - )).ToList(); - - for (var i = 0; i < db.Geometry.MeshCount; ++i) - { - if (!db.Geometry.GetMesh(i).IsEquivalentTo(vimGeoBuilders[i])) - throw new VimValidationException($"{nameof(DocumentBuilder)} mesh {i} is not equivalent to {nameof(VimScene)} mesh {i}"); - } - // Test the assets. var dbAssetDictionary = db.Assets; var vimAssetDictionary = vim._SerializableDocument.Assets.ToDictionary(a => a.Name, a => a.ToBytes()); diff --git a/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs b/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs index 1e30bf3e..fca310d2 100644 --- a/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs +++ b/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs @@ -59,15 +59,17 @@ public static VimScene LoadVim(Stream stream, IVimSceneProgress progress = null, => LoadVim(stream, new LoadOptions { SkipGeometry = skipGeometry, SkipAssets = skipAssets}, progress, inParallel); public int VimIndex { get; set; } - public VimMesh[] MeshesNext { get; private set; } - public IArray Meshes { get; private set; } public IArray Nodes { get; private set; } public IArray VimNodes { get; private set; } - public IArray ShapesOld { get; private set; } + + public VimMesh[] Meshes { get; private set; } public VimShapeNext[] Shapes { get; private set; } - public IArray MaterialsOld { get; private set; } public VimMaterialNext[] Materials { get; private set; } + public IArray ShapesOld { get; private set; } + public IArray MaterialsOld { get; private set; } + public IArray MeshesOld { get; private set; } + public SerializableDocument _SerializableDocument { get; } public Document Document { get; private set; } public DocumentModel DocumentModel { get; private set; } @@ -75,9 +77,8 @@ public static VimScene LoadVim(Stream stream, IVimSceneProgress progress = null, public string PersistingId => Document.Header.PersistingId; - public int GetMeshCount() => Meshes.Count; + public int GetMeshCount() => Meshes.Length; public int GetMaterialCount() => Materials.Length; - public int GetShapeCount() => Shapes.Length; public Vector4 GetMaterialColorNext(int materialIndex) @@ -190,8 +191,8 @@ private void CreateMeshes(bool inParallel) } var srcGeo = _SerializableDocument.Geometry; - MeshesNext = VimMesh.GetAllMeshes(_SerializableDocument.GeometryNext).ToArray(); - Meshes = srcGeo?.Meshes.Select(m => m as IMeshCommon); + Meshes = VimMesh.GetAllMeshes(_SerializableDocument.GeometryNext).ToArray(); + MeshesOld = srcGeo?.Meshes.Select(m => m as IMeshCommon); } private void CreateShapes(bool inParallel) @@ -247,7 +248,7 @@ public void Save(string filePath) public void TransformSceneInPlace(Func meshTransform = null, Func nodeTransform = null) { if (meshTransform != null) - MeshesNext = MeshesNext.Select(meshTransform).ToArray(); + Meshes = Meshes.Select(meshTransform).ToArray(); if (nodeTransform != null) VimNodes = VimNodes.Select(nodeTransform).EvaluateInParallel(); } diff --git a/src/cs/vim/Vim.Format/SceneBuilder/VimSceneNode.cs b/src/cs/vim/Vim.Format/SceneBuilder/VimSceneNode.cs index 9dcf686a..0d90c895 100644 --- a/src/cs/vim/Vim.Format/SceneBuilder/VimSceneNode.cs +++ b/src/cs/vim/Vim.Format/SceneBuilder/VimSceneNode.cs @@ -1,6 +1,7 @@ using Vim.Format.Geometry; using Vim.Format.ObjectModel; using Vim.G3d; +using Vim.G3dNext; using Vim.LinqArray; using Vim.Math3d; @@ -37,7 +38,7 @@ public bool HideByDefault public int NodeIndex { get; } = -1; public IMeshCommon GetMesh() - => _Scene.Meshes.ElementAtOrDefault(MeshIndex); + => _Scene.Meshes.SafeGet(MeshIndex); public int MeshIndex { get; } From e2ae306a4cfd44eda3bd0aa3366794c52512daca Mon Sep 17 00:00:00 2001 From: simon Date: Wed, 10 Apr 2024 15:41:13 -0400 Subject: [PATCH 150/204] meshcommon -> vimmesh --- .../Vim.Format.Core/Geometry/MeshOptimization.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/cs/vim/Vim.Format.Core/Geometry/MeshOptimization.cs b/src/cs/vim/Vim.Format.Core/Geometry/MeshOptimization.cs index fac1c90b..ee3b002a 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/MeshOptimization.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/MeshOptimization.cs @@ -5,7 +5,7 @@ using Vim.Math3d; namespace Vim.Format.Geometry -{ +{ /// /// This class is used to compare quickly two meshes within a lookup table (e.g. Dictionary, HashTable). @@ -15,9 +15,9 @@ namespace Vim.Format.Geometry /// By converting an IMesh to a MeshHash we minimize the amount of comparisons done. It becomes /// possible, but highly unlikely that two different meshes would have the same hash. /// - public class MeshCommonHash + public class MeshHash { - public IMeshCommon Mesh; + public VimMesh Mesh; public float Tolerance; public int NumFaces; public int NumVertices; @@ -31,7 +31,7 @@ public int Round(float f) public Int3 Round(Vector3 v) => new Int3(Round(v.X), Round(v.Y), Round(v.Z)); - public MeshCommonHash(IMeshCommon mesh, float tolerance) + public MeshHash(VimMesh mesh, float tolerance) { Mesh = mesh; Tolerance = tolerance; @@ -44,9 +44,9 @@ public MeshCommonHash(IMeshCommon mesh, float tolerance) } public override bool Equals(object obj) - => obj is MeshCommonHash other && Equals(other); + => obj is MeshHash other && Equals(other); - public bool Equals(MeshCommonHash other) + public bool Equals(MeshHash other) => NumFaces == other.NumFaces && NumVertices == other.NumVertices && BoxMin.Equals(other.BoxMin) @@ -59,7 +59,7 @@ public override int GetHashCode() public static class Optimization { - public static Dictionary> GroupMeshesByHash(this IEnumerable meshes, float tolerance) - => meshes.AsParallel().GroupBy(m => new MeshCommonHash(m, tolerance)).ToDictionary(grp => grp.Key, grp => grp.ToList()); + public static Dictionary> GroupMeshesByHash(this IEnumerable meshes, float tolerance) + => meshes.AsParallel().GroupBy(m => new MeshHash(m, tolerance)).ToDictionary(grp => grp.Key, grp => grp.ToList()); } } From fc7bab61094a113019d0d4e283b775cae07df5c9 Mon Sep 17 00:00:00 2001 From: simon Date: Wed, 10 Apr 2024 15:50:27 -0400 Subject: [PATCH 151/204] renames --- src/cs/vim/Vim.Format/SceneBuilder/Validation.cs | 7 ++++--- src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs b/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs index 6fda7aaf..bba370e1 100644 --- a/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs +++ b/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs @@ -126,9 +126,10 @@ void ValidateColorDomain(string label, Vector4 value, Vector4 lowerInclusive, Ve Parallel.For(0, vim.GetShapeCount(), shapeIndex => { var shape = shapes[shapeIndex]; - if (vim.DocumentModel.GetShapeElementIndex(shapeIndex) < 0) - throw new VimValidationException($"{nameof(Element)} is null for {nameof(VimShape)} {shape.ShapeIndex}"); - ValidateColorDomain($"{nameof(VimShape)} color", shape.Color, Vector4.Zero, Vector4.One, shape.ShapeIndex); + var element = vim.DocumentModel.GetShapeElementIndex(shapeIndex); + if (element < 0) + throw new VimValidationException($"{nameof(Element)} is null for {nameof(VimShape)} {shape.Index}"); + ValidateColorDomain($"{nameof(VimShape)} color", shape.Color, Vector4.Zero, Vector4.One, shape.Index); }); } diff --git a/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs b/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs index fca310d2..4bf943b5 100644 --- a/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs +++ b/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs @@ -81,7 +81,7 @@ public string PersistingId public int GetMaterialCount() => Materials.Length; public int GetShapeCount() => Shapes.Length; - public Vector4 GetMaterialColorNext(int materialIndex) + public Vector4 GetMaterialColor(int materialIndex) => _SerializableDocument.GeometryNext.MaterialColors[materialIndex]; private VimScene(SerializableDocument doc) From d98be27d98e36dd82007fb4c6938aae60e84c954 Mon Sep 17 00:00:00 2001 From: simon Date: Wed, 10 Apr 2024 15:53:46 -0400 Subject: [PATCH 152/204] node.mesh is now vimmesh --- src/cs/vim/Vim.Format.Core/Geometry/IScene.cs | 6 +++--- src/cs/vim/Vim.Format/SceneBuilder/VimSceneNode.cs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/cs/vim/Vim.Format.Core/Geometry/IScene.cs b/src/cs/vim/Vim.Format.Core/Geometry/IScene.cs index a618151c..c4a6cfbf 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/IScene.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/IScene.cs @@ -23,7 +23,7 @@ public interface ISceneNode IScene Scene { get; } Matrix4x4 Transform { get; } int MeshIndex { get; } - IMeshCommon GetMesh(); + VimMesh GetMesh(); ISceneNode Parent { get; } // TODO: DEPRECATE: this needs to be removed, currently only used in Vim.Max.Bridge. @@ -52,7 +52,7 @@ public class NullNode : ISceneNode public int MeshIndex => 0; public ISceneNode Parent => null; public IArray Children => null; - public IMeshCommon GetMesh() => null; + public VimMesh GetMesh() => null; } public class IdNode : ISceneNode @@ -63,6 +63,6 @@ public class IdNode : ISceneNode public int MeshIndex => 0; public ISceneNode Parent => null; public IArray Children => null; - public IMeshCommon GetMesh() => null; + public VimMesh GetMesh() => null; } } diff --git a/src/cs/vim/Vim.Format/SceneBuilder/VimSceneNode.cs b/src/cs/vim/Vim.Format/SceneBuilder/VimSceneNode.cs index 0d90c895..4c4c042b 100644 --- a/src/cs/vim/Vim.Format/SceneBuilder/VimSceneNode.cs +++ b/src/cs/vim/Vim.Format/SceneBuilder/VimSceneNode.cs @@ -37,7 +37,7 @@ public bool HideByDefault public int VimIndex { get; } = -1; public int NodeIndex { get; } = -1; - public IMeshCommon GetMesh() + public VimMesh GetMesh() => _Scene.Meshes.SafeGet(MeshIndex); public int MeshIndex { get; } From 50a2be1a512665f2dfc6f88c73912e3606331733 Mon Sep 17 00:00:00 2001 From: simon Date: Thu, 11 Apr 2024 11:05:45 -0400 Subject: [PATCH 153/204] replaced scene extension with methods --- src/cs/vim/Vim.Format.Core/Geometry/IScene.cs | 2 +- .../Geometry/SceneExtensions.cs | 36 ------------------- .../ObjectModel/ObjectModelStore.cs | 8 +++++ .../vim/Vim.Format/SceneBuilder/VimScene.cs | 15 +++++++- .../Vim.Format/SceneBuilder/VimSceneNode.cs | 21 +++++++++-- 5 files changed, 42 insertions(+), 40 deletions(-) delete mode 100644 src/cs/vim/Vim.Format.Core/Geometry/SceneExtensions.cs diff --git a/src/cs/vim/Vim.Format.Core/Geometry/IScene.cs b/src/cs/vim/Vim.Format.Core/Geometry/IScene.cs index c4a6cfbf..e92a45d1 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/IScene.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/IScene.cs @@ -11,7 +11,7 @@ namespace Vim.Format.Geometry public interface IScene { IArray Nodes { get; } - IArray MeshesOld { get; } + VimMesh[] Meshes { get; } } /// diff --git a/src/cs/vim/Vim.Format.Core/Geometry/SceneExtensions.cs b/src/cs/vim/Vim.Format.Core/Geometry/SceneExtensions.cs deleted file mode 100644 index d59455aa..00000000 --- a/src/cs/vim/Vim.Format.Core/Geometry/SceneExtensions.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using Vim.Util; -using Vim.LinqArray; -using Vim.Math3d; -using Vim.G3d; - -namespace Vim.Format.Geometry -{ - public static class SceneExtensions - { - public static IMeshCommon TransformedMesh(this ISceneNode node) - => node.GetMesh()?.Transform(node.Transform); - - public static IEnumerable TransformedMeshes(this IScene scene) - => scene.Nodes.Where(n => n.GetMesh() != null).Select(TransformedMesh); - - public static IMeshCommon MergedGeometry(this IScene scene) - => scene.Nodes.ToEnumerable().MergedGeometry(); - - public static IMeshCommon MergedGeometry(this IEnumerable nodes) - => nodes.Where(n => n.GetMesh() != null).Select(TransformedMesh).ToArray().Merge(); - - public static IEnumerable AllVertices(this IScene scene) - => scene.TransformedMeshes().SelectMany(g => g.Vertices.ToEnumerable()); - - public static AABox BoundingBox(this IScene scene) - => AABox.Create(scene.AllVertices()); - - public static IArray TransformedVertices(this ISceneNode node) - => node.TransformedMesh()?.Vertices; - - public static AABox TransformedBoundingBox(this ISceneNode node) - => AABox.Create(node.TransformedVertices()?.ToEnumerable()); - } -} diff --git a/src/cs/vim/Vim.Format/ObjectModel/ObjectModelStore.cs b/src/cs/vim/Vim.Format/ObjectModel/ObjectModelStore.cs index 4cb5d0e5..b2fa3243 100644 --- a/src/cs/vim/Vim.Format/ObjectModel/ObjectModelStore.cs +++ b/src/cs/vim/Vim.Format/ObjectModel/ObjectModelStore.cs @@ -28,6 +28,14 @@ public DocumentBuilder ToDocumentBuilder(string generator, string versionString) .AddMaterials(CreateMaterialBuilders()); } + private IEnumerable CreateMaterialBuilders() + => ObjectModelBuilder.GetEntities().Select(m => new DocumentBuilder.Material() + { + Color = new Vector4((float) m.Color.X, (float) m.Color.Y, (float) m.Color.Z, (float)(1 - m.Transparency)), + Glossiness = (float) m.Glossiness, + Smoothness = (float) m.Smoothness + }); + /// /// Mutates the Meshes and Instances to remove any meshes which are not referenced by at least one instance. /// diff --git a/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs b/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs index 4bf943b5..f08a3fc9 100644 --- a/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs +++ b/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs @@ -12,6 +12,7 @@ using IVimSceneProgress = System.IProgress<(string, double)>; using Vim.BFastLib; using Vim.G3dNext; +using System.Collections.Generic; namespace Vim { @@ -80,7 +81,19 @@ public string PersistingId public int GetMeshCount() => Meshes.Length; public int GetMaterialCount() => Materials.Length; public int GetShapeCount() => Shapes.Length; - + + public IEnumerable TransformedMeshes() + => VimNodes.Where(n => n.GetMesh() != null).Select(n => n.TransformedMesh()); + + public IMeshCommon MergedGeometry() + => VimNodes.ToEnumerable().MergedGeometry(); + + public IEnumerable AllVertices() + => TransformedMeshes().SelectMany(g => g.Vertices.ToEnumerable()); + + public AABox BoundingBox() + => AABox.Create(AllVertices()); + public Vector4 GetMaterialColor(int materialIndex) => _SerializableDocument.GeometryNext.MaterialColors[materialIndex]; diff --git a/src/cs/vim/Vim.Format/SceneBuilder/VimSceneNode.cs b/src/cs/vim/Vim.Format/SceneBuilder/VimSceneNode.cs index 4c4c042b..b1fb8704 100644 --- a/src/cs/vim/Vim.Format/SceneBuilder/VimSceneNode.cs +++ b/src/cs/vim/Vim.Format/SceneBuilder/VimSceneNode.cs @@ -1,4 +1,6 @@ -using Vim.Format.Geometry; +using System.Collections.Generic; +using System.Linq; +using Vim.Format.Geometry; using Vim.Format.ObjectModel; using Vim.G3d; using Vim.G3dNext; @@ -37,7 +39,7 @@ public bool HideByDefault public int VimIndex { get; } = -1; public int NodeIndex { get; } = -1; - public VimMesh GetMesh() + public VimMesh GetMesh() => _Scene.Meshes.SafeGet(MeshIndex); public int MeshIndex { get; } @@ -55,5 +57,20 @@ public VimMesh GetMesh() VimSceneNode ITransformable3D.Transform(Matrix4x4 mat) => new VimSceneNode(_Scene, Id, MeshIndex, mat * Transform); + + public IMeshCommon TransformedMesh() + => GetMesh()?.Transform(Transform); + + public IArray TransformedVertices() + => TransformedMesh()?.Vertices; + + public AABox TransformedBoundingBox() + => AABox.Create(TransformedVertices()?.ToEnumerable()); + } + + public static class NodeExtensions + { + public static IMeshCommon MergedGeometry(this IEnumerable nodes) + => nodes.Where(n => n.GetMesh() != null).Select(n => n.TransformedMesh()).ToArray().Merge(); } } From 24e7639bdc8ebd450122488be77d785e51b5d10a Mon Sep 17 00:00:00 2001 From: simon Date: Thu, 11 Apr 2024 14:23:12 -0400 Subject: [PATCH 154/204] concrete types instead of interfaces --- src/cs/vim/Vim.Format/SceneBuilder/IScene.cs | 68 +++++++++++++++++++ .../vim/Vim.Format/SceneBuilder/Validation.cs | 4 +- .../vim/Vim.Format/SceneBuilder/VimScene.cs | 21 +++--- .../Vim.Format/SceneBuilder/VimSceneNode.cs | 22 +++--- 4 files changed, 90 insertions(+), 25 deletions(-) create mode 100644 src/cs/vim/Vim.Format/SceneBuilder/IScene.cs diff --git a/src/cs/vim/Vim.Format/SceneBuilder/IScene.cs b/src/cs/vim/Vim.Format/SceneBuilder/IScene.cs new file mode 100644 index 00000000..6001a574 --- /dev/null +++ b/src/cs/vim/Vim.Format/SceneBuilder/IScene.cs @@ -0,0 +1,68 @@ +using System.Collections.Generic; +using Vim.G3d; +using Vim.LinqArray; +using Vim.Math3d; + +namespace Vim.Format.Geometry +{ + /// + /// An IScene is a generic representation of a 3D scene graph. + /// + public interface IScene + { + VimSceneNode[] Nodes { get; } + VimMesh[] Meshes { get; } + } + + /// + /// A node in a scene graph. + /// + public interface ISceneNode + { + int Id { get; } + VimScene Scene { get; } + Matrix4x4 Transform { get; } + int MeshIndex { get; } + VimMesh GetMesh(); + VimSceneNode Parent { get; } + + // TODO: DEPRECATE: this needs to be removed, currently only used in Vim.Max.Bridge. + VimSceneNode[] Children { get; } + } + + public class SceneNodeComparer : EqualityComparer, IComparer + { + public static readonly SceneNodeComparer Instance = new SceneNodeComparer(); + + public int Compare(VimSceneNode x, VimSceneNode y) + => x.Id - y.Id; + public override bool Equals(VimSceneNode x, VimSceneNode y) + => x.Id == y.Id; + public override int GetHashCode(VimSceneNode obj) + => obj.Id; + } + + public class NullNode : ISceneNode + { + public static NullNode Instance = new NullNode(); + public static List ListInstance = new List() { Instance }; + public int Id => -1; + public VimScene Scene => null; + public Matrix4x4 Transform => Matrix4x4.Identity; + public int MeshIndex => 0; + public VimSceneNode Parent => null; + public VimSceneNode[] Children => null; + public VimMesh GetMesh() => null; + } + + public class IdNode : ISceneNode + { + public int Id { get; set; } + public VimScene Scene => null; + public Matrix4x4 Transform => Matrix4x4.Identity; + public int MeshIndex => 0; + public VimSceneNode Parent => null; + public VimSceneNode[] Children => null; + public VimMesh GetMesh() => null; + } +} diff --git a/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs b/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs index bba370e1..5eaaf8d1 100644 --- a/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs +++ b/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs @@ -98,8 +98,8 @@ public static void ValidateDocumentModelToG3dInvariantsNext(this VimScene vim) public static void ValidateNodes(this VimScene vim) { - if (vim.VimNodes.Count != vim.DocumentModel.NumNode) - throw new VimValidationException($"The number of {nameof(VimSceneNode)} ({vim.VimNodes.Count}) does not match the number of node entities ({vim.DocumentModel.NumNode})"); + if (vim.GetNodeCount() != vim.DocumentModel.NumNode) + throw new VimValidationException($"The number of {nameof(VimSceneNode)} ({vim.GetNodeCount()}) does not match the number of node entities ({vim.DocumentModel.NumNode})"); } public static void ValidateShapes(this VimScene vim) diff --git a/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs b/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs index f08a3fc9..567c8b95 100644 --- a/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs +++ b/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs @@ -60,8 +60,7 @@ public static VimScene LoadVim(Stream stream, IVimSceneProgress progress = null, => LoadVim(stream, new LoadOptions { SkipGeometry = skipGeometry, SkipAssets = skipAssets}, progress, inParallel); public int VimIndex { get; set; } - public IArray Nodes { get; private set; } - public IArray VimNodes { get; private set; } + public VimSceneNode[] Nodes { get; private set; } public VimMesh[] Meshes { get; private set; } public VimShapeNext[] Shapes { get; private set; } @@ -81,12 +80,13 @@ public string PersistingId public int GetMeshCount() => Meshes.Length; public int GetMaterialCount() => Materials.Length; public int GetShapeCount() => Shapes.Length; + public int GetNodeCount() => Nodes.Length; public IEnumerable TransformedMeshes() - => VimNodes.Where(n => n.GetMesh() != null).Select(n => n.TransformedMesh()); + => Nodes.Where(n => n.GetMesh() != null).Select(n => n.TransformedMesh()); public IMeshCommon MergedGeometry() - => VimNodes.ToEnumerable().MergedGeometry(); + => Nodes.MergedGeometry(); public IEnumerable AllVertices() => TransformedMeshes().SelectMany(g => g.Vertices.ToEnumerable()); @@ -226,8 +226,7 @@ private void CreateScene(bool inParallel) return; } - VimNodes = CreateVimSceneNodes(this, _SerializableDocument.Geometry, inParallel); - Nodes = VimNodes.Select(n => n as ISceneNode); + Nodes = CreateVimSceneNodes(this, _SerializableDocument.Geometry, inParallel); } private void CreateMaterials(bool inParallel) @@ -243,14 +242,12 @@ private void CreateMaterials(bool inParallel) } - public static IArray CreateVimSceneNodes(VimScene scene, G3D g3d, bool inParallel) + public static VimSceneNode[] CreateVimSceneNodes(VimScene scene, G3D g3d, bool inParallel) { Matrix4x4 GetMatrix(int i) => i >= 0 ? g3d.InstanceTransforms[i] : Matrix4x4.Identity; - var r = g3d.InstanceTransforms.Select((_, i) => - new VimSceneNode(scene, i, g3d.InstanceMeshes[i], GetMatrix(i))); - - return inParallel ? r.EvaluateInParallel() : r.Evaluate(); + return g3d.InstanceTransforms.Select((_, i) => + new VimSceneNode(scene, i, g3d.InstanceMeshes[i], GetMatrix(i))).ToArray(); } public void Save(string filePath) @@ -263,7 +260,7 @@ public void TransformSceneInPlace(Func meshTransform = null, F if (meshTransform != null) Meshes = Meshes.Select(meshTransform).ToArray(); if (nodeTransform != null) - VimNodes = VimNodes.Select(nodeTransform).EvaluateInParallel(); + Nodes = Nodes.Select(nodeTransform).ToArray(); } public string GetElementName(int elementIndex, string missing = "") diff --git a/src/cs/vim/Vim.Format/SceneBuilder/VimSceneNode.cs b/src/cs/vim/Vim.Format/SceneBuilder/VimSceneNode.cs index b1fb8704..47bed5a6 100644 --- a/src/cs/vim/Vim.Format/SceneBuilder/VimSceneNode.cs +++ b/src/cs/vim/Vim.Format/SceneBuilder/VimSceneNode.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Linq; using Vim.Format.Geometry; using Vim.Format.ObjectModel; @@ -15,15 +16,14 @@ public VimSceneNode(VimScene scene, int nodeIndex, int geometryIndex, Matrix4x4 : base(scene.DocumentModel, scene.DocumentModel.GetNodeElementIndex(nodeIndex)) { VimIndex = scene.VimIndex; - _Scene = scene; + Scene = scene; Transform = transform; MeshIndex = geometryIndex; NodeIndex = nodeIndex; } - public VimScene _Scene { get; } + public VimScene Scene { get; } - public IScene Scene => _Scene; public int Id => NodeIndex; public Matrix4x4 Transform { get; } @@ -31,7 +31,7 @@ public bool HideByDefault { get { - var instanceFlags = (InstanceFlags)_Scene.Document.Geometry.InstanceFlags.ElementAtOrDefault(NodeIndex); + var instanceFlags = (InstanceFlags)Scene.Document.Geometry.InstanceFlags.ElementAtOrDefault(NodeIndex); return (instanceFlags & InstanceFlags.Hidden) == InstanceFlags.Hidden; } } @@ -40,23 +40,23 @@ public bool HideByDefault public int NodeIndex { get; } = -1; public VimMesh GetMesh() - => _Scene.Meshes.SafeGet(MeshIndex); + => Scene.Meshes.SafeGet(MeshIndex); public int MeshIndex { get; } public bool HasMesh => MeshIndex != -1; - public Node NodeModel => _Scene.DocumentModel.GetNode(Id); - public Geometry GeometryModel => _Scene.DocumentModel.GetGeometry(MeshIndex); + public Node NodeModel => Scene.DocumentModel.GetNode(Id); + public Geometry GeometryModel => Scene.DocumentModel.GetGeometry(MeshIndex); // TODO: I think this should be "IEnumerable" in the interface - public ISceneNode Parent => null; - public IArray Children => LinqArray.LinqArray.Empty(); + public VimSceneNode Parent => null; + public VimSceneNode[] Children => Array.Empty(); public string DisciplineName => VimSceneHelpers.GetDisiplineFromCategory(CategoryName); VimSceneNode ITransformable3D.Transform(Matrix4x4 mat) - => new VimSceneNode(_Scene, Id, MeshIndex, mat * Transform); + => new VimSceneNode(Scene, Id, MeshIndex, mat * Transform); public IMeshCommon TransformedMesh() => GetMesh()?.Transform(Transform); From f7ce65b990d9ebc522b77cdfa6a1cc93fe52b668 Mon Sep 17 00:00:00 2001 From: simon Date: Thu, 11 Apr 2024 15:21:17 -0400 Subject: [PATCH 155/204] removing iscene and iscenenode --- src/cs/vim/Vim.Format.Core/Geometry/IScene.cs | 68 ------------------- src/cs/vim/Vim.Format/SceneBuilder/IScene.cs | 68 ------------------- .../vim/Vim.Format/SceneBuilder/VimScene.cs | 2 +- .../Vim.Format/SceneBuilder/VimSceneNode.cs | 2 +- 4 files changed, 2 insertions(+), 138 deletions(-) delete mode 100644 src/cs/vim/Vim.Format.Core/Geometry/IScene.cs delete mode 100644 src/cs/vim/Vim.Format/SceneBuilder/IScene.cs diff --git a/src/cs/vim/Vim.Format.Core/Geometry/IScene.cs b/src/cs/vim/Vim.Format.Core/Geometry/IScene.cs deleted file mode 100644 index e92a45d1..00000000 --- a/src/cs/vim/Vim.Format.Core/Geometry/IScene.cs +++ /dev/null @@ -1,68 +0,0 @@ -using System.Collections.Generic; -using Vim.G3d; -using Vim.LinqArray; -using Vim.Math3d; - -namespace Vim.Format.Geometry -{ - /// - /// An IScene is a generic representation of a 3D scene graph. - /// - public interface IScene - { - IArray Nodes { get; } - VimMesh[] Meshes { get; } - } - - /// - /// A node in a scene graph. - /// - public interface ISceneNode - { - int Id { get; } - IScene Scene { get; } - Matrix4x4 Transform { get; } - int MeshIndex { get; } - VimMesh GetMesh(); - ISceneNode Parent { get; } - - // TODO: DEPRECATE: this needs to be removed, currently only used in Vim.Max.Bridge. - IArray Children { get; } - } - - public class SceneNodeComparer : EqualityComparer, IComparer - { - public static readonly SceneNodeComparer Instance = new SceneNodeComparer(); - - public int Compare(ISceneNode x, ISceneNode y) - => x.Id - y.Id; - public override bool Equals(ISceneNode x, ISceneNode y) - => x.Id == y.Id; - public override int GetHashCode(ISceneNode obj) - => obj.Id; - } - - public class NullNode : ISceneNode - { - public static NullNode Instance = new NullNode(); - public static List ListInstance = new List() { Instance }; - public int Id => -1; - public IScene Scene => null; - public Matrix4x4 Transform => Matrix4x4.Identity; - public int MeshIndex => 0; - public ISceneNode Parent => null; - public IArray Children => null; - public VimMesh GetMesh() => null; - } - - public class IdNode : ISceneNode - { - public int Id { get; set; } - public IScene Scene => null; - public Matrix4x4 Transform => Matrix4x4.Identity; - public int MeshIndex => 0; - public ISceneNode Parent => null; - public IArray Children => null; - public VimMesh GetMesh() => null; - } -} diff --git a/src/cs/vim/Vim.Format/SceneBuilder/IScene.cs b/src/cs/vim/Vim.Format/SceneBuilder/IScene.cs deleted file mode 100644 index 6001a574..00000000 --- a/src/cs/vim/Vim.Format/SceneBuilder/IScene.cs +++ /dev/null @@ -1,68 +0,0 @@ -using System.Collections.Generic; -using Vim.G3d; -using Vim.LinqArray; -using Vim.Math3d; - -namespace Vim.Format.Geometry -{ - /// - /// An IScene is a generic representation of a 3D scene graph. - /// - public interface IScene - { - VimSceneNode[] Nodes { get; } - VimMesh[] Meshes { get; } - } - - /// - /// A node in a scene graph. - /// - public interface ISceneNode - { - int Id { get; } - VimScene Scene { get; } - Matrix4x4 Transform { get; } - int MeshIndex { get; } - VimMesh GetMesh(); - VimSceneNode Parent { get; } - - // TODO: DEPRECATE: this needs to be removed, currently only used in Vim.Max.Bridge. - VimSceneNode[] Children { get; } - } - - public class SceneNodeComparer : EqualityComparer, IComparer - { - public static readonly SceneNodeComparer Instance = new SceneNodeComparer(); - - public int Compare(VimSceneNode x, VimSceneNode y) - => x.Id - y.Id; - public override bool Equals(VimSceneNode x, VimSceneNode y) - => x.Id == y.Id; - public override int GetHashCode(VimSceneNode obj) - => obj.Id; - } - - public class NullNode : ISceneNode - { - public static NullNode Instance = new NullNode(); - public static List ListInstance = new List() { Instance }; - public int Id => -1; - public VimScene Scene => null; - public Matrix4x4 Transform => Matrix4x4.Identity; - public int MeshIndex => 0; - public VimSceneNode Parent => null; - public VimSceneNode[] Children => null; - public VimMesh GetMesh() => null; - } - - public class IdNode : ISceneNode - { - public int Id { get; set; } - public VimScene Scene => null; - public Matrix4x4 Transform => Matrix4x4.Identity; - public int MeshIndex => 0; - public VimSceneNode Parent => null; - public VimSceneNode[] Children => null; - public VimMesh GetMesh() => null; - } -} diff --git a/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs b/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs index 567c8b95..9a890d64 100644 --- a/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs +++ b/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs @@ -21,7 +21,7 @@ namespace Vim /// /// This is the top-level class of a loaded VIM file. /// - public class VimScene : IScene + public class VimScene { /// /// Returns the VIM file's header schema version. Returns null if the Vim has no header. diff --git a/src/cs/vim/Vim.Format/SceneBuilder/VimSceneNode.cs b/src/cs/vim/Vim.Format/SceneBuilder/VimSceneNode.cs index 47bed5a6..9d2eba2b 100644 --- a/src/cs/vim/Vim.Format/SceneBuilder/VimSceneNode.cs +++ b/src/cs/vim/Vim.Format/SceneBuilder/VimSceneNode.cs @@ -10,7 +10,7 @@ namespace Vim { - public sealed class VimSceneNode : ElementInfo, ISceneNode, ITransformable3D + public sealed class VimSceneNode : ElementInfo, ITransformable3D { public VimSceneNode(VimScene scene, int nodeIndex, int geometryIndex, Matrix4x4 transform) : base(scene.DocumentModel, scene.DocumentModel.GetNodeElementIndex(nodeIndex)) From 4f75adb4ab45e17ca3c32613bee026c9530bd5b5 Mon Sep 17 00:00:00 2001 From: simon Date: Thu, 11 Apr 2024 16:19:13 -0400 Subject: [PATCH 156/204] removed assimp project --- .../Vim.G3d.AssimpWrapper/AssimpExtensions.cs | 103 ------------------ .../g3d/Vim.G3d.AssimpWrapper/AssimpLoader.cs | 36 ------ .../Vim.G3d.AssimpWrapper.csproj | 21 ---- src/cs/g3d/Vim.G3d.Tests/Vim.G3d.Tests.csproj | 1 - src/cs/vim-format.sln | 9 +- 5 files changed, 1 insertion(+), 169 deletions(-) delete mode 100644 src/cs/g3d/Vim.G3d.AssimpWrapper/AssimpExtensions.cs delete mode 100644 src/cs/g3d/Vim.G3d.AssimpWrapper/AssimpLoader.cs delete mode 100644 src/cs/g3d/Vim.G3d.AssimpWrapper/Vim.G3d.AssimpWrapper.csproj diff --git a/src/cs/g3d/Vim.G3d.AssimpWrapper/AssimpExtensions.cs b/src/cs/g3d/Vim.G3d.AssimpWrapper/AssimpExtensions.cs deleted file mode 100644 index 80e26239..00000000 --- a/src/cs/g3d/Vim.G3d.AssimpWrapper/AssimpExtensions.cs +++ /dev/null @@ -1,103 +0,0 @@ -using System; -using System.Linq; -using Assimp; -using Vim.LinqArray; -using Vim.Math3d; - -namespace Vim.G3d.AssimpWrapper -{ - public static class AssimpExtensions - { - public static Vector2 ToMath3D(this Vector2D v) - => new Vector2(v.X, v.Y); - - public static Vector3 ToMath3D(this Vector3D v) - => new Vector3(v.X, v.Y, v.Z); - - public static Vector3 ToMath3D(this Color3D v) - => new Vector3(v.R, v.G, v.B); - - public static Vector4 ToMath3D(this Color4D v) - => new Vector4(v.R, v.G, v.B, v.A); - - public static Math3d.Matrix4x4 ToMath3D(this Assimp.Matrix4x4 m) - => new Math3d.Matrix4x4( - m.A1, m.A2, m.A3, m.A4, - m.B1, m.B2, m.B3, m.B4, - m.C1, m.C2, m.C3, m.C4, - m.D1, m.D2, m.D3, m.D4); - - public static bool IsTriangular(this Mesh mesh) - => mesh.Faces.All(f => f.IndexCount == 3); - - public static G3D ToG3d(this Scene scene) - { - var meshes = scene.Meshes.Select(m => m.ToG3D()).ToIArray(); - var nodes = scene.GetNodes().ToIArray(); - if (nodes.Count == 0 || nodes.Count == 1) - return meshes.Count > 0 ? meshes[0] : G3D.Empty; - - var mergedAttributes = meshes.Merge().Attributes.ToList(); - - var subGeoTransforms = nodes.Select(n => n.Transform.ToMath3D()).ToInstanceTransformAttribute(); - mergedAttributes.Add(subGeoTransforms); - - var meshIndices = nodes.Select(n => n.MeshIndex).ToInstanceMeshAttribute(); - mergedAttributes.Add(meshIndices); - - return mergedAttributes.ToG3d(); - } - - public static G3D ToG3D(this Mesh mesh) - { - // The Assimp mesh must be triangulated - if (mesh.FaceCount == 0) - return G3D.Empty; - - var bldr = new G3DBuilder(); - - // Note: should be at most 3 for meses, but could 2 for lines, or 1 for point clouds - var numCornersPerFace = mesh.Faces[0].IndexCount; - if (numCornersPerFace > 3) - throw new Exception("The Assimp mesh must be triangulated as a post-process"); - if (numCornersPerFace <= 0) - throw new Exception("The Assimp mesh has faces without indices"); - foreach (var f in mesh.Faces) - { - if (f.IndexCount != numCornersPerFace) - throw new Exception($"Each face of the assimp mesh must have {numCornersPerFace} corners, but found one with {f.IndexCount}"); - } - bldr.SetObjectFaceSize(numCornersPerFace); - - var indices = mesh.GetIndices(); - if (indices.Length % numCornersPerFace != 0) - throw new Exception($"The mesh index buffer length {indices.Length} is not divisible by {numCornersPerFace}"); - - bldr.AddVertices(mesh.Vertices.ToIArray().Select(ToMath3D)); - bldr.AddIndices(indices); - - if (mesh.HasTangentBasis) - bldr.Add(mesh.BiTangents.ToIArray().Select(ToMath3D).ToVertexBitangentAttribute()); - - if (mesh.HasTangentBasis) - bldr.Add(mesh.Tangents.ToIArray().Select(x => ToMath3D(x).ToVector4()).ToVertexTangentAttribute()); - - if (mesh.HasNormals) - bldr.Add(mesh.Normals.ToIArray().Select(ToMath3D).ToVertexNormalAttribute()); - - for (var i = 0; i < mesh.TextureCoordinateChannelCount; ++i) - { - var uvChannel = mesh.TextureCoordinateChannels[i]; - bldr.Add(uvChannel.ToIArray().Select(ToMath3D).ToVertexUvwAttribute(i)); - } - - for (var i = 0; i < mesh.VertexColorChannelCount; ++i) - { - var vcChannel = mesh.VertexColorChannels[i]; - bldr.Add(vcChannel.ToIArray().Select(ToMath3D).ToVertexColorAttribute(i)); - } - - return bldr.ToG3D(); - } - } -} diff --git a/src/cs/g3d/Vim.G3d.AssimpWrapper/AssimpLoader.cs b/src/cs/g3d/Vim.G3d.AssimpWrapper/AssimpLoader.cs deleted file mode 100644 index bb0387be..00000000 --- a/src/cs/g3d/Vim.G3d.AssimpWrapper/AssimpLoader.cs +++ /dev/null @@ -1,36 +0,0 @@ -using Assimp; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using Vim.LinqArray; - -namespace Vim.G3d.AssimpWrapper -{ - public static class AssimpLoader - { - public static AssimpContext Context = new AssimpContext(); - - public class AssimpNode - { - public int MeshIndex { get; } - public Matrix4x4 Transform { get; } - public AssimpNode(int index, Matrix4x4 transform) - => (MeshIndex, Transform) = (index, transform); - } - - public static IEnumerable GetNodes(this Scene scene) - => scene == null || scene.RootNode == null - ? Enumerable.Empty() - : GetNodes(scene, scene.RootNode, scene.RootNode.Transform); - - public static IEnumerable GetNodes(this Scene scene, Node node, Matrix4x4 transform) - => node.MeshIndices.Select(idx => new AssimpNode(idx, node.Transform)) - .Concat(node.Children.SelectMany(c => GetNodes(scene, c, transform * c.Transform))); - - public static Scene Load(string filePath, bool triangulate = true) - => Context.ImportFile(filePath, triangulate ? PostProcessSteps.Triangulate : PostProcessSteps.None); - - public static bool CanLoad(string filePath) - => Context.IsImportFormatSupported(Path.GetExtension(filePath)); - } -} diff --git a/src/cs/g3d/Vim.G3d.AssimpWrapper/Vim.G3d.AssimpWrapper.csproj b/src/cs/g3d/Vim.G3d.AssimpWrapper/Vim.G3d.AssimpWrapper.csproj deleted file mode 100644 index 3b567b9f..00000000 --- a/src/cs/g3d/Vim.G3d.AssimpWrapper/Vim.G3d.AssimpWrapper.csproj +++ /dev/null @@ -1,21 +0,0 @@ - - - - netstandard2.0 - Vim.G3d.AssimpWrapper - - - - - - - - - - - - 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 ae2d33e9..af8be97d 100644 --- a/src/cs/g3d/Vim.G3d.Tests/Vim.G3d.Tests.csproj +++ b/src/cs/g3d/Vim.G3d.Tests/Vim.G3d.Tests.csproj @@ -12,7 +12,6 @@ - diff --git a/src/cs/vim-format.sln b/src/cs/vim-format.sln index a75b5a5b..d003f17e 100644 --- a/src/cs/vim-format.sln +++ b/src/cs/vim-format.sln @@ -27,8 +27,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vim.G3d.Tests", "g3d\Vim.G3 EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vim.G3d", "g3d\Vim.G3d\Vim.G3d.csproj", "{F1EC1E94-C74C-4C37-961C-305CAE7C4707}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vim.G3d.AssimpWrapper", "g3d\Vim.G3d.AssimpWrapper\Vim.G3d.AssimpWrapper.csproj", "{16DBF49F-3E0C-4CD3-BB6C-1BBAF0D89AC6}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vim.Format.CodeGen", "vim\Vim.Format.CodeGen\Vim.Format.CodeGen.csproj", "{762E8B1A-9182-4C5D-A25C-0C0F6219BA4E}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vim.Format.Tests", "vim\Vim.Format.Tests\Vim.Format.Tests.csproj", "{2CB4CF73-0CA8-4595-910C-EDA244EA5983}" @@ -57,7 +55,7 @@ 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}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vim.G3dNext.Tests", "Vim.G3dNext.Tests\Vim.G3dNext.Tests.csproj", "{AD1A2A9F-18E9-4430-A192-3CD1A17DDA0D}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -93,10 +91,6 @@ Global {F1EC1E94-C74C-4C37-961C-305CAE7C4707}.Debug|Any CPU.Build.0 = Debug|Any CPU {F1EC1E94-C74C-4C37-961C-305CAE7C4707}.Release|Any CPU.ActiveCfg = Release|Any CPU {F1EC1E94-C74C-4C37-961C-305CAE7C4707}.Release|Any CPU.Build.0 = Release|Any CPU - {16DBF49F-3E0C-4CD3-BB6C-1BBAF0D89AC6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {16DBF49F-3E0C-4CD3-BB6C-1BBAF0D89AC6}.Debug|Any CPU.Build.0 = Debug|Any CPU - {16DBF49F-3E0C-4CD3-BB6C-1BBAF0D89AC6}.Release|Any CPU.ActiveCfg = Release|Any CPU - {16DBF49F-3E0C-4CD3-BB6C-1BBAF0D89AC6}.Release|Any CPU.Build.0 = Release|Any CPU {762E8B1A-9182-4C5D-A25C-0C0F6219BA4E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {762E8B1A-9182-4C5D-A25C-0C0F6219BA4E}.Debug|Any CPU.Build.0 = Debug|Any CPU {762E8B1A-9182-4C5D-A25C-0C0F6219BA4E}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -165,7 +159,6 @@ Global {22278D91-27D7-4A84-8170-5FFB77A70C1F} = {D639C635-01D1-48C4-89B5-1FD70F1AFEE9} {DFC8DC5E-377D-4CCC-A498-5894D891A471} = {705B8FB2-D707-4527-91FC-0AADEDBA4D80} {F1EC1E94-C74C-4C37-961C-305CAE7C4707} = {705B8FB2-D707-4527-91FC-0AADEDBA4D80} - {16DBF49F-3E0C-4CD3-BB6C-1BBAF0D89AC6} = {705B8FB2-D707-4527-91FC-0AADEDBA4D80} {762E8B1A-9182-4C5D-A25C-0C0F6219BA4E} = {D639C635-01D1-48C4-89B5-1FD70F1AFEE9} {2CB4CF73-0CA8-4595-910C-EDA244EA5983} = {D639C635-01D1-48C4-89B5-1FD70F1AFEE9} {2C798994-518D-4EA5-8F8A-3EAA30269F9E} = {D639C635-01D1-48C4-89B5-1FD70F1AFEE9} From ede5f3367e33105d7056ffaf1c5ca385854b86ca Mon Sep 17 00:00:00 2001 From: simon Date: Thu, 11 Apr 2024 16:19:26 -0400 Subject: [PATCH 157/204] removed g3dtest project --- src/cs/g3d/Vim.G3d.Tests/G3dTests.cs | 315 ------------------ .../Properties/Resources.Designer.cs | 73 ---- .../Vim.G3d.Tests/Properties/Resources.resx | 124 ------- src/cs/g3d/Vim.G3d.Tests/Resources/.gitignore | 1 - src/cs/g3d/Vim.G3d.Tests/Util.cs | 76 ----- src/cs/g3d/Vim.G3d.Tests/Vim.G3d.Tests.csproj | 44 --- 6 files changed, 633 deletions(-) delete mode 100644 src/cs/g3d/Vim.G3d.Tests/G3dTests.cs delete mode 100644 src/cs/g3d/Vim.G3d.Tests/Properties/Resources.Designer.cs delete mode 100644 src/cs/g3d/Vim.G3d.Tests/Properties/Resources.resx delete mode 100644 src/cs/g3d/Vim.G3d.Tests/Resources/.gitignore delete mode 100644 src/cs/g3d/Vim.G3d.Tests/Util.cs delete mode 100644 src/cs/g3d/Vim.G3d.Tests/Vim.G3d.Tests.csproj diff --git a/src/cs/g3d/Vim.G3d.Tests/G3dTests.cs b/src/cs/g3d/Vim.G3d.Tests/G3dTests.cs deleted file mode 100644 index fa9f38ed..00000000 --- a/src/cs/g3d/Vim.G3d.Tests/G3dTests.cs +++ /dev/null @@ -1,315 +0,0 @@ -using Assimp; -using NUnit.Framework; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using Vim.BFastLib; -using Vim.G3d.AssimpWrapper; -using Vim.LinqArray; -using Vim.Math3d; - -namespace Vim.G3d.Tests -{ - [TestFixture] - public static class G3dTests - { - 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 G3D 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", "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); - - 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(G3D g1, G3D g2) - { - ValidateSame(g1.NumCornersPerFace, g2.NumCornersPerFace, "NumCornersPerFace"); - ValidateSame(g1.NumFaces, g2.NumFaces, "NumFaces"); - ValidateSame(g1.NumCorners, g2.NumCorners, "NumCorners"); - ValidateSame(g1.NumVertices, g2.NumVertices, "NumVertices"); - ValidateSame(g1.NumInstances, g2.NumInstances, "NumInstances"); - ValidateSame(g1.NumMeshes, g2.NumMeshes, "NumMeshes"); - ValidateSame(g1.Attributes.Count, g2.Attributes.Count, "NumAttributes"); - for (var i = 0; i < g1.Attributes.Count; ++i) - { - var attr1 = g1.Attributes[i]; - var attr2 = g2.Attributes[i]; - ValidateSame(attr1.Name, attr2.Name, $"Attribute[{i}].Name"); - ValidateSame(attr1.GetByteSize(), attr2.GetByteSize(), $"Attribute[{i}].ByteSize"); - ValidateSame(attr1.ElementCount, attr2.ElementCount, $"Attribute[{i}].ElementCount"); - } - } - - [Test] - [Platform(Exclude = "Linux,Unix", Reason = "AssimpNet is failing to load its dependency on 'libdl.so'.")] - public static void OpenAndConvertAssimpFiles() - { - 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) = - Util.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 = Util.GetMSecElapsed(() => - f.G3d = f.Scene.ToG3d()); - } - catch (Exception e) - { - f.Error = e; - } - } - - // Save all the G3D scenes - Util.CreateAndClearDirectory(TestOutputFolder); - foreach (var f in files) - { - if (f.G3d == null) continue; - - try - { - var outputFilePath = Path.Combine(TestOutputFolder, f.ShortName + ".g3d"); - f.G3DFile = new FileInfo(outputFilePath); - - f.MSecToSaveG3d = Util.GetMSecElapsed(() => - f.G3d.ToBFast().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 - { - G3D localG3d = null; - - (f.MemoryConsumptionG3d, f.MSecToOpenG3d) = - Util.GetMemoryConsumptionAndMSecElapsed(() => - localG3d = G3D.Read(f.G3DFile.FullName)); - - 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"); - } - - [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 materialIndices = new[] { 5 }; - - var g3d = new G3DBuilder() - .AddVertices(vertices.ToIArray()) - .AddIndices(indices.ToIArray()) - .Add(materialIndices.ToIArray().ToFaceMaterialAttribute()) - .ToG3D(); - - var bfast = g3d.ToBFast(); - var g = G3D.Read(bfast); - - Assert.IsNotNull(g); - - Assert.AreEqual(3, g.NumVertices); - Assert.AreEqual(3, g.NumCorners); - Assert.AreEqual(1, g.NumFaces); - Assert.AreEqual(3, g.NumCornersPerFace); - 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()); - } - - [Test] - public static void UnexpectedAttributes_Are_Ignored() - { - var bfast = new BFast(); - bfast.SetArray("g3d:instance:potato:0:int32:1", new int[] { 5 }); - - 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()); - } - - public static G3D LoadAssimpFile(string filePath) - { - using (var context = new AssimpContext()) - { - var scene = context.ImportFile(filePath); - Assert.AreEqual(1, scene.Meshes.Count); - return scene.Meshes[0].ToG3D(); - } - } - - // NOTE: can't be run as part of NUnit because it requires the GC - public static void BigFileTest() - { - var nVerts = (300 * 1000 * 1000); // 300 * 12 = 3.6 GB - var vertices = nVerts.Select(i => new Vector3(i, i, i)); - var bldr = new G3DBuilder(); - bldr.AddVertices(vertices); - - var expectedG3d = bldr.ToG3D(); - Assert.AreEqual(nVerts, expectedG3d.NumVertices); - var bfast = expectedG3d.ToBFast(); - var resultG3d = G3D.Read(bfast); - - ValidateSameG3D(expectedG3d, resultG3d); - } - - [Test, Explicit] - [Platform(Exclude = "Linux,Unix", Reason = "AssimpNet is failing to load its dependency on 'libdl.so'.")] - public static void TestWriters() - { - var fileName = Path.Combine(TestInputFolder, "PLY", "Wuson.ply"); - - var outputFileName = @"test"; - outputFileName = Path.Combine(TestOutputFolder, 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 g1 = g3d; - var g2 = g3dFromPly; - 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); - } - - // BUG: Assimp ignores the OBJ index buffer. God knows why. - //CompareG3D(g3d, g3dFromObj); - } - } -} diff --git a/src/cs/g3d/Vim.G3d.Tests/Properties/Resources.Designer.cs b/src/cs/g3d/Vim.G3d.Tests/Properties/Resources.Designer.cs deleted file mode 100644 index dba826c3..00000000 --- a/src/cs/g3d/Vim.G3d.Tests/Properties/Resources.Designer.cs +++ /dev/null @@ -1,73 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Vim.G3d.Tests.Properties { - using System; - - - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // 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", "17.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resources { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resources() { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Vim.G3d.Tests.Properties.Resources", typeof(Resources).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - - /// - /// Looks up a localized string similar to C:\Users\Rober\Desktop\Vim\vim-format\src\cs\g3d\Vim.G3d.Tests\ - ///. - /// - internal static string ProjDir { - get { - return ResourceManager.GetString("ProjDir", resourceCulture); - } - } - } -} diff --git a/src/cs/g3d/Vim.G3d.Tests/Properties/Resources.resx b/src/cs/g3d/Vim.G3d.Tests/Properties/Resources.resx deleted file mode 100644 index 579dd3b6..00000000 --- a/src/cs/g3d/Vim.G3d.Tests/Properties/Resources.resx +++ /dev/null @@ -1,124 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - - ..\Resources\ProjDir.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252 - - \ No newline at end of file diff --git a/src/cs/g3d/Vim.G3d.Tests/Resources/.gitignore b/src/cs/g3d/Vim.G3d.Tests/Resources/.gitignore deleted file mode 100644 index d8fff56a..00000000 --- a/src/cs/g3d/Vim.G3d.Tests/Resources/.gitignore +++ /dev/null @@ -1 +0,0 @@ -ProjDir.txt \ No newline at end of file diff --git a/src/cs/g3d/Vim.G3d.Tests/Util.cs b/src/cs/g3d/Vim.G3d.Tests/Util.cs deleted file mode 100644 index 2ff62684..00000000 --- a/src/cs/g3d/Vim.G3d.Tests/Util.cs +++ /dev/null @@ -1,76 +0,0 @@ -using System; -using System.Diagnostics; -using System.IO; -using System.Linq; - -namespace Vim.G3d.Tests -{ - public static class Util - { - 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; - } - } -} \ No newline at end of file diff --git a/src/cs/g3d/Vim.G3d.Tests/Vim.G3d.Tests.csproj b/src/cs/g3d/Vim.G3d.Tests/Vim.G3d.Tests.csproj deleted file mode 100644 index af8be97d..00000000 --- a/src/cs/g3d/Vim.G3d.Tests/Vim.G3d.Tests.csproj +++ /dev/null @@ -1,44 +0,0 @@ - - - - net6.0 - false - - - - - - - - - - - - - - - - - True - True - Resources.resx - - - - - - ResXFileCodeGenerator - Resources.Designer.cs - - - - - - - - - True - - - - From 068c522216a58ef34e8206ba12b1f57327670cb0 Mon Sep 17 00:00:00 2001 From: simon Date: Thu, 11 Apr 2024 16:59:43 -0400 Subject: [PATCH 158/204] removed g3d builder --- src/cs/g3d/Vim.G3d/G3DBuilder.cs | 39 -------------------------------- 1 file changed, 39 deletions(-) delete mode 100644 src/cs/g3d/Vim.G3d/G3DBuilder.cs diff --git a/src/cs/g3d/Vim.G3d/G3DBuilder.cs b/src/cs/g3d/Vim.G3d/G3DBuilder.cs deleted file mode 100644 index 6d68cb99..00000000 --- a/src/cs/g3d/Vim.G3d/G3DBuilder.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System.Collections.Generic; -using Vim.LinqArray; -using Vim.Math3d; - -namespace Vim.G3d -{ - /// - /// This is a helper class for constructing a G3D from individual attributes - /// - public class G3DBuilder - { - public readonly List Attributes = new List(); - - public G3D ToG3D(G3dHeader? header = null) - => new G3D(Attributes, header ?? G3dHeader.Default); - - public G3DBuilder Add(GeometryAttribute attr) - { - Attributes.Add(attr); - return this; - } - - public G3DBuilder AddIndices(int[] indices) - => Add(indices.ToIndexAttribute()); - - public G3DBuilder AddIndices(IArray indices) - => Add(indices.ToIndexAttribute()); - - public G3DBuilder SetObjectFaceSize(int objectFaceSize) - => Add(new[] { objectFaceSize }.ToIArray().ToObjectFaceSizeAttribute()); - - public G3DBuilder AddVertices(IArray vertices) - => Add(vertices.ToPositionAttribute()); - - public IGeometryAttributes ToIGeometryAttributes() - => new GeometryAttributes(Attributes); - } -} - From 621e50e850cfb9d339d66b59da791f579941d01b Mon Sep 17 00:00:00 2001 From: simon Date: Fri, 12 Apr 2024 10:40:10 -0400 Subject: [PATCH 159/204] removed g3d serialization --- src/cs/g3d/Vim.G3d/G3dSerialization.cs | 35 -------------------------- 1 file changed, 35 deletions(-) delete mode 100644 src/cs/g3d/Vim.G3d/G3dSerialization.cs diff --git a/src/cs/g3d/Vim.G3d/G3dSerialization.cs b/src/cs/g3d/Vim.G3d/G3dSerialization.cs deleted file mode 100644 index 4f47b27d..00000000 --- a/src/cs/g3d/Vim.G3d/G3dSerialization.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System; -using System.IO; -using Vim.BFastLib; -using Vim.LinqArray; -using System.Collections.Generic; - -namespace Vim.G3d -{ - public static partial class G3DExtension - { - public static void WriteAttribute(Stream stream, GeometryAttribute attribute, string name, long size) - { - var buffer = attribute.ToBuffer(); - if (buffer.NumBytes() != size) - throw new Exception($"Internal error while writing attribute, expected number of bytes was {size} but instead was {buffer.NumBytes()}"); - if (buffer.Name != name) - throw new Exception($"Internal error while writing attribute, expected name was {name} but instead was {buffer.Name}"); - stream.Write(buffer); - } - - public static BFast ToBFast(this IGeometryAttributes self, G3dHeader? header = null) - { - var bfast = new BFast(); - bfast.SetArray("meta", (header ?? G3dHeader.Default).ToBytes()); - foreach(var attribute in self.Attributes.ToEnumerable()) - { - attribute.AddTo(bfast); - } - return bfast; - } - - - - } -} From f1a31eb11dc09679617a4c207662c0883eaaf72e Mon Sep 17 00:00:00 2001 From: simon Date: Fri, 12 Apr 2024 10:40:10 -0400 Subject: [PATCH 160/204] removed g3d serialization --- src/cs/g3d/Vim.G3d/G3dSerialization.cs | 35 -------------------------- 1 file changed, 35 deletions(-) delete mode 100644 src/cs/g3d/Vim.G3d/G3dSerialization.cs diff --git a/src/cs/g3d/Vim.G3d/G3dSerialization.cs b/src/cs/g3d/Vim.G3d/G3dSerialization.cs deleted file mode 100644 index 4f47b27d..00000000 --- a/src/cs/g3d/Vim.G3d/G3dSerialization.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System; -using System.IO; -using Vim.BFastLib; -using Vim.LinqArray; -using System.Collections.Generic; - -namespace Vim.G3d -{ - public static partial class G3DExtension - { - public static void WriteAttribute(Stream stream, GeometryAttribute attribute, string name, long size) - { - var buffer = attribute.ToBuffer(); - if (buffer.NumBytes() != size) - throw new Exception($"Internal error while writing attribute, expected number of bytes was {size} but instead was {buffer.NumBytes()}"); - if (buffer.Name != name) - throw new Exception($"Internal error while writing attribute, expected name was {name} but instead was {buffer.Name}"); - stream.Write(buffer); - } - - public static BFast ToBFast(this IGeometryAttributes self, G3dHeader? header = null) - { - var bfast = new BFast(); - bfast.SetArray("meta", (header ?? G3dHeader.Default).ToBytes()); - foreach(var attribute in self.Attributes.ToEnumerable()) - { - attribute.AddTo(bfast); - } - return bfast; - } - - - - } -} From 140b12e1ebd0e16efa6397f8b9b6840e14e29868 Mon Sep 17 00:00:00 2001 From: simon Date: Fri, 12 Apr 2024 11:02:39 -0400 Subject: [PATCH 161/204] removed lots of unused attribute code --- src/cs/g3d/Vim.G3d/AttributeExtensions.cs | 24 - .../Vim.G3d/GeometryAttributesExtensions.cs | 494 +----------------- .../vim/Vim.Format.Core/Geometry/VimMesh.cs | 16 - 3 files changed, 1 insertion(+), 533 deletions(-) diff --git a/src/cs/g3d/Vim.G3d/AttributeExtensions.cs b/src/cs/g3d/Vim.G3d/AttributeExtensions.cs index 98fb02fa..aedfed52 100644 --- a/src/cs/g3d/Vim.G3d/AttributeExtensions.cs +++ b/src/cs/g3d/Vim.G3d/AttributeExtensions.cs @@ -9,21 +9,6 @@ namespace Vim.G3d { public static class AttributeExtensions { - public static GeometryAttribute CheckArity(this GeometryAttribute self, int arity) where T : unmanaged - => self?.Descriptor?.DataArity == arity ? self : null; - - public static GeometryAttribute CheckAssociation(this GeometryAttribute self, Association assoc) where T : unmanaged - => self?.Descriptor?.Association == assoc ? self : null; - - public static GeometryAttribute CheckArityAndAssociation(this GeometryAttribute self, int arity, Association assoc) where T : unmanaged - => self?.CheckArity(arity)?.CheckAssociation(assoc); - - public static GeometryAttribute ToAttribute(this IList self, string desc) where T : unmanaged - => self.ToIArray().ToAttribute(desc); - - public static GeometryAttribute ToAttribute(this IList self, AttributeDescriptor desc) where T : unmanaged - => self.ToIArray().ToAttribute(desc); - public static GeometryAttribute ToAttribute(this IArray self, AttributeDescriptor desc) where T : unmanaged => new GeometryAttribute(self, desc); @@ -137,14 +122,5 @@ public static GeometryAttribute ToDefaultAttribute(this AttributeDescriptor desc throw new Exception($"Could not create a default attribute for {desc}"); } - - public static long GetByteSize(this GeometryAttribute attribute) - => (long)attribute.ElementCount * attribute.Descriptor.DataElementSize; - - public static GeometryAttribute Merge(this IEnumerable attributes) - => attributes.FirstOrDefault()?.Merge(attributes.Skip(1)); - - public static GeometryAttribute Merge(this IArray attributes) - => attributes.ToEnumerable().Merge(); } } diff --git a/src/cs/g3d/Vim.G3d/GeometryAttributesExtensions.cs b/src/cs/g3d/Vim.G3d/GeometryAttributesExtensions.cs index 5d7e07d5..a378b94f 100644 --- a/src/cs/g3d/Vim.G3d/GeometryAttributesExtensions.cs +++ b/src/cs/g3d/Vim.G3d/GeometryAttributesExtensions.cs @@ -8,507 +8,15 @@ namespace Vim.G3d { public static class GeometryAttributesExtensions { - public static int ExpectedElementCount(this IGeometryAttributes self, AttributeDescriptor desc) - { - switch (desc.Association) - { - case Association.assoc_all: - return 1; - case Association.assoc_none: - return 0; - case Association.assoc_vertex: - return self.NumVertices; - case Association.assoc_face: - return self.NumFaces; - case Association.assoc_corner: - return self.NumCorners; - case Association.assoc_edge: - return self.NumCorners; - case Association.assoc_mesh: - return self.NumMeshes; - case Association.assoc_instance: - return self.NumInstances; - case Association.assoc_shapevertex: - return self.NumShapeVertices; - case Association.assoc_shape: - return self.NumShapes; - } - return -1; - } - - public static IArray AttributeNames(this IGeometryAttributes g) - => g.Attributes.Select(attr => attr.Name); - public static GeometryAttribute GetAttribute(this IGeometryAttributes g, string attributeName) where T : unmanaged => g.GetAttribute(attributeName)?.AsType(); - public static GeometryAttribute DefaultAttribute(this IGeometryAttributes self, string name) - => self.DefaultAttribute(AttributeDescriptor.Parse(name)); - - public static GeometryAttribute DefaultAttribute(this IGeometryAttributes self, AttributeDescriptor desc) - => desc.ToDefaultAttribute(self.ExpectedElementCount(desc)); - - public static GeometryAttribute GetOrDefaultAttribute(this IGeometryAttributes self, AttributeDescriptor desc) - => self.GetAttribute(desc.ToString()) ?? desc.ToDefaultAttribute(self.ExpectedElementCount(desc)); - - public static IEnumerable NoneAttributes(this IGeometryAttributes g) - => g.Attributes.Where(a => a.Descriptor.Association == Association.assoc_none); - - public static IEnumerable CornerAttributes(this IGeometryAttributes g) - => g.Attributes.Where(a => a.Descriptor.Association == Association.assoc_corner); - - public static IEnumerable EdgeAttributes(this IGeometryAttributes g) - => g.Attributes.Where(a => a.Descriptor.Association == Association.assoc_edge); - - public static IEnumerable FaceAttributes(this IGeometryAttributes g) - => g.Attributes.Where(a => a.Descriptor.Association == Association.assoc_face); - - public static IEnumerable VertexAttributes(this IGeometryAttributes g) - => g.Attributes.Where(a => a.Descriptor.Association == Association.assoc_vertex); - - public static IEnumerable InstanceAttributes(this IGeometryAttributes g) - => g.Attributes.Where(a => a.Descriptor.Association == Association.assoc_instance); - - public static IEnumerable MeshAttributes(this IGeometryAttributes g) - => g.Attributes.Where(a => a.Descriptor.Association == Association.assoc_mesh); - - public static IEnumerable SubMeshAttributes(this IGeometryAttributes g) - => g.Attributes.Where(a => a.Descriptor.Association == Association.assoc_submesh); - - public static IEnumerable WholeGeometryAttributes(this IGeometryAttributes g) - => g.Attributes.Where(a => a.Descriptor.Association == Association.assoc_all); - - public static IEnumerable ShapeVertexAttributes(this IGeometryAttributes g) - => g.Attributes.Where(a => a.Descriptor.Association == Association.assoc_shapevertex); - - public static IEnumerable ShapeAttributes(this IGeometryAttributes g) - => g.Attributes.Where(a => a.Descriptor.Association == Association.assoc_shape); - - public static bool HasSameAttributes(this IGeometryAttributes g1, IGeometryAttributes g2) - => g1.Attributes.Count == g2.Attributes.Count && g1.Attributes.Indices().All(i => g1.Attributes[i].Name == g2.Attributes[i].Name); - - public static int FaceToCorner(this IGeometryAttributes g, int f) - => f * g.NumCornersPerFace; - - /// - /// Given a set of face indices, creates an array of corner indices - /// - public static IArray FaceIndicesToCornerIndices(this IGeometryAttributes g, IArray faceIndices) - => (faceIndices.Count * g.NumCornersPerFace) - .Select(i => g.FaceToCorner(faceIndices[i / g.NumCornersPerFace]) + i % g.NumCornersPerFace); - - /// - /// Given a set of face indices, creates an array of indices of the first corner in each face - /// - public static IArray FaceIndicesToFirstCornerIndices(this IGeometryAttributes g, IArray faceIndices) - => faceIndices.Select(f => f * g.NumCornersPerFace); - - public static int CornerToFace(this IGeometryAttributes g, int c) - => c / g.NumCornersPerFace; - - public static IArray CornersToFaces(this IGeometryAttributes g) - => g.NumCorners.Select(g.CornerToFace); - - public static int CornerNumber(this IGeometryAttributes g, int c) - => c % g.NumCornersPerFace; - public static IGeometryAttributes ToGeometryAttributes(this IEnumerable attributes) => new GeometryAttributes(attributes); - - public static IGeometryAttributes ToGeometryAttributes(this IArray attributes) - => attributes.ToEnumerable().ToGeometryAttributes(); - + public static IGeometryAttributes AddAttributes(this IGeometryAttributes attributes, params GeometryAttribute[] newAttributes) => attributes.Attributes.ToEnumerable().Concat(newAttributes).ToGeometryAttributes(); - public static GeometryAttribute GetAttributeOrDefault(this IGeometryAttributes g, string name) - => g.GetAttribute(name) ?? g.DefaultAttribute(name); - - public static IGeometryAttributes Merge(this IArray gs) - => gs.Select(x => (IGeometryAttributes)x).Merge(); - - public static IGeometryAttributes Merge(this IGeometryAttributes self, params IGeometryAttributes[] gs) - => gs.ToIArray().Prepend(self).Merge(); - - public static IGeometryAttributes Merge(this IArray geometryAttributesArray) - { - if (geometryAttributesArray.Count == 0) - return GeometryAttributes.Empty; - - var first = geometryAttributesArray[0]; - - if (geometryAttributesArray.Count == 1) - return first; - var corners = first.NumCornersPerFace; - if (!geometryAttributesArray.All(g => g.NumCornersPerFace == corners)) - throw new Exception("Cannot merge meshes with different numbers of corners per faces"); - - // Merge all of the attributes of the different geometries - // Except: indices, group indexes, subgeo, and instance attributes - var attributes = first.VertexAttributes() - .Concat(first.CornerAttributes()) - .Concat(first.EdgeAttributes()) - .Concat(first.NoneAttributes()) - .Concat(first.FaceAttributes()) - .Append(first.GetAttributeSubmeshMaterial()) - // Skip the index semantic because things get re-ordered - .Where(attr => attr != null && attr.Descriptor.Semantic != Semantic.Index) - .ToArray(); - - // Merge the non-indexed attributes - var others = geometryAttributesArray.Skip(1).ToEnumerable(); - var attributeList = attributes.Select( - attr => attr.Merge(others.Select(g => g.GetAttributeOrDefault(attr.Name)))).ToList(); - - // Merge the index attribute - // numVertices: [X], [Y], [Z], ... - // valueOffsets: [0], [X], [X+Y], ... - // indices: [A, B, C], [D, E, F], [G, H, I], ... - // mergedIndices: [A, B, C], [X+D, X+E, X+F], [X+Y+G, X+Y+H, X+Y+I], ... - var mergedIndexAttribute = geometryAttributesArray.MergeIndexedAttribute( - ga => ga.GetAttributeIndex(), - ga => ga.NumVertices) - ?.ToIndexAttribute(); - - if (mergedIndexAttribute != null) - attributeList.Add(mergedIndexAttribute); - - // Merge the submesh index offset attribute - // numCorners: [X], [Y], [Z], ... - // valueOffsets: [0] [X], [X+Y], ... - // submeshIndexOffsets: [0, A, B], [0, C, D], [0, E, F], ... - // mergedSubmeshIndexOffsets: [0, A, B], [X, X+C, X+D], [X+Y, X+Y+E, X+Y+F], ... - var mergedSubmeshIndexOffsetAttribute = geometryAttributesArray.MergeIndexedAttribute( - ga => ga.GetAttributeSubmeshIndexOffset(), - ga => ga.NumCorners) - ?.ToSubmeshIndexOffsetAttribute(); - - if (mergedSubmeshIndexOffsetAttribute != null) - attributeList.Add(mergedSubmeshIndexOffsetAttribute); - - return attributeList.ToGeometryAttributes(); - } - - /// - /// Merges the indexed attributes based on the given transformations and returns an array of integers - /// representing the merged and offset values. - /// - public static int[] MergeIndexedAttribute( - this IArray geometryAttributesArray, - Func> getIndexedAttributeFunc, - Func getValueOffsetFunc, - int initialValueOffset = 0) - { - var first = geometryAttributesArray.FirstOrDefault(); - if (first == null) - return null; - - var firstAttribute = getIndexedAttributeFunc(first); - if (firstAttribute == null) - return null; - - return geometryAttributesArray.MergeAttributes( - getIndexedAttributeFunc, - tuples => - { - var valueOffset = initialValueOffset; - var mergedCount = 0; - - var merged = new int[tuples.Sum(t => t.Attribute.Data.Count)]; - - foreach (var (parent, attr) in tuples) - { - var attrData = attr.Data; - var attrDataCount = attr.Data.Count; - - for (var i = 0; i < attrDataCount; ++i) - merged[mergedCount + i] = attrData[i] + valueOffset; - - mergedCount += attrDataCount; - valueOffset += getValueOffsetFunc(parent); - } - - return merged; - }); - } - - /// - /// Merges the attributes based on the given transformations and returns an array of merged values. - /// - public static T[] MergeAttributes( - this IArray geometryAttributesArray, - Func> getAttributeFunc, - Func<(IGeometryAttributes Parent, GeometryAttribute Attribute)[], T[]> mergeFunc) where T : unmanaged - { - var tuples = geometryAttributesArray - .Select(ga => (Parent: ga, GeometryAttribute: getAttributeFunc(ga))) - .Where(tuple => tuple.GeometryAttribute != null) - .ToArray(); - - if (tuples.Length != geometryAttributesArray.Count) - throw new Exception("The geometry attributes array do not all contain the same attribute"); - - return mergeFunc(tuples); - } - - /// - /// Applies a transformation function to position attributes and another to normal attributes. When deforming, we may want to - /// apply a similar deformation to the normals. For example a matrix can change the position, rotation, and scale of a geometry, - /// but the only changes should be to the direction of the normal, not the length. - /// - public static IGeometryAttributes Deform(this IGeometryAttributes g, Func positionTransform, Func normalTransform) - => g.Attributes.Select( - a => - (a.Descriptor.Semantic == Semantic.Position && a is GeometryAttribute p) ? p.Data.Select(positionTransform).ToAttribute(a.Descriptor) : - (a.Descriptor.Semantic == Semantic.Normal && a is GeometryAttribute n) ? n.Data.Select(normalTransform).ToAttribute(a.Descriptor) : - a) - .ToGeometryAttributes(); - - /// - /// Applies a deformation to points, without changing the normals. For some transformation functions this can result in incorrect normals. - /// - public static IGeometryAttributes Deform(this IGeometryAttributes g, Func positionTransform) - => g.Attributes.Select( - a => - (a.Descriptor.Semantic == Semantic.Position && a is GeometryAttribute p) ? p.Data.Select(positionTransform).ToAttribute(a.Descriptor) : - a) - .ToGeometryAttributes(); - - /// - /// Applies a transformation matrix - /// - public static IGeometryAttributes Transform(this IGeometryAttributes g, Matrix4x4 matrix) - => g.Deform(v => v.Transform(matrix), v => v.TransformNormal(matrix)); - - public static IGeometryAttributes SetPosition(this IGeometryAttributes g, IArray points) - => g.SetAttribute(points.ToPositionAttribute()); - - public static IGeometryAttributes SetAttribute(this IGeometryAttributes self, GeometryAttribute attr) - => self.Attributes.Where(a => !a.Descriptor.Equals(attr.Descriptor)).Append(attr).ToGeometryAttributes(); - - public static IGeometryAttributes SetAttribute(this IGeometryAttributes self, IArray values, AttributeDescriptor desc) where ValueT : unmanaged - => self.SetAttribute(values.ToAttribute(desc)); - - /// - /// Leaves the vertex buffer intact and creates a new geometry that remaps all of the group, corner, and face data. - /// The newFaces array is a list of indices into the old face array. - /// Note: meshes are lost. - /// - public static IGeometryAttributes RemapFaces(this IGeometryAttributes g, IArray faceRemap) - => g.RemapFacesAndCorners(faceRemap, g.FaceIndicesToCornerIndices(faceRemap)); - - public static IEnumerable SetFaceSizeAttribute(this IEnumerable attributes, int numCornersPerFaces) - => (numCornersPerFaces <= 0) - ? attributes - : attributes - .Where(attr => attr.Descriptor.Semantic != Semantic.FaceSize) - .Append(new[] { numCornersPerFaces }.ToObjectFaceSizeAttribute()); - - /// - /// Low-level remap function. Maps faces and corners at the same time. - /// In some cases, this is important (e.g. triangulating quads). - /// Note: meshes are lost. - /// - public static IGeometryAttributes RemapFacesAndCorners(this IGeometryAttributes g, IArray faceRemap, IArray cornerRemap, int numCornersPerFace = -1) - => g.VertexAttributes() - .Concat(g.SubMeshAttributes()) - .Concat(g.NoneAttributes()) - .Concat(g.FaceAttributes().Select(attr => attr.Remap(faceRemap))) - .Concat(g.EdgeAttributes().Select(attr => attr.Remap(cornerRemap))) - .Concat(g.CornerAttributes().Select(attr => attr.Remap(cornerRemap))) - .Concat(g.WholeGeometryAttributes()) - .SetFaceSizeAttribute(numCornersPerFace) - .ToGeometryAttributes(); - - /// - /// Converts a quadrilateral mesh into a triangular mesh carrying over all attributes. - /// - public static IGeometryAttributes TriangulateQuadMesh(this IGeometryAttributes g) - { - if (g.NumCornersPerFace != 4) throw new Exception("Not a quad mesh"); - - var cornerRemap = new int[g.NumFaces * 6]; - var faceRemap = new int[g.NumFaces * 2]; - var cur = 0; - for (var i = 0; i < g.NumFaces; ++i) - { - cornerRemap[cur++] = i * 4 + 0; - cornerRemap[cur++] = i * 4 + 1; - cornerRemap[cur++] = i * 4 + 2; - cornerRemap[cur++] = i * 4 + 0; - cornerRemap[cur++] = i * 4 + 2; - cornerRemap[cur++] = i * 4 + 3; - - faceRemap[i * 2 + 0] = i; - faceRemap[i * 2 + 1] = i; - } - - return g.RemapFacesAndCorners(faceRemap.ToIArray(), cornerRemap.ToIArray(), 3); - } - - public static IGeometryAttributes CopyFaces(this IGeometryAttributes g, IArray keep) - => g.CopyFaces(i => keep[i]); - - public static IGeometryAttributes CopyFaces(this IGeometryAttributes g, IArray keep) - => g.RemapFaces(keep); - - public static IGeometryAttributes CopyFaces(this IGeometryAttributes self, Func predicate) - => self.RemapFaces(self.NumFaces.Select(i => i).IndicesWhere(predicate).ToIArray()); - - public static IGeometryAttributes DeleteFaces(this IGeometryAttributes g, Func predicate) - => g.CopyFaces(i => !predicate(i)); - - public static IGeometryAttributes CopyFaces(this IGeometryAttributes g, int from, int count) - => g.CopyFaces(i => i >= from && i < from + count); - - /// - /// Updates the vertex buffer (e.g. after identifying unwanted faces) and the index - /// buffer. Vertices are either re-ordered, removed, or deleted. Does not affect any other - /// - public static IGeometryAttributes RemapVertices(this IGeometryAttributes g, IArray newVertices, IArray newIndices) - => (new[] { newIndices.ToIndexAttribute() } - .Concat( - g.VertexAttributes() - .Select(attr => attr.Remap(newVertices))) - .Concat(g.NoneAttributes()) - .Concat(g.FaceAttributes()) - .Concat(g.EdgeAttributes()) - .Concat(g.CornerAttributes()) - .Concat(g.WholeGeometryAttributes()) - ) - .ToGeometryAttributes(); - - /// - /// The vertRemap is a list of vertices in the new vertex buffer, and where they came from. - /// This could be a reordering of the original vertex buffer, it could even be a repetition. - /// It could also be some vertices were deleted, BUT if those vertices are still referenced - /// then this will throw an exception. - /// The values in the index buffer will change, but it will stay the same length. - /// - public static IGeometryAttributes RemapVertices(this IGeometryAttributes g, IArray vertRemap) - { - var vertLookup = (-1).Repeat(g.NumVertices).ToArray(); - for (var i = 0; i < vertRemap.Count; ++i) - { - var oldVert = vertRemap[i]; - vertLookup[oldVert] = i; - } - - var oldIndices = g.GetAttributeIndex()?.Data ?? g.NumVertices.Range(); - var newIndices = oldIndices.Select(i => vertLookup[i]).Evaluate(); - - if (newIndices.Any(x => x == -1)) - throw new Exception("At least one of the indices references a vertex that no longer exists"); - - return g.RemapVertices(vertRemap, newIndices); - } - - /// - /// For mesh g, create a new mesh from the passed selected faces, - /// discarding un-referenced data and generating new index, vertex & face buffers. - /// - public static IGeometryAttributes SelectFaces(this IGeometryAttributes g, IArray faces) - { - // Early exit, if all selected no need to do anything - if (g.NumFaces == faces.Count) - return g; - - // Early exit, if none selected no need to do anything - if (faces.Count == 0) - return null; - - // First, get all the indices for this array of faces - var oldIndices = g.GetAttributeIndex(); - var oldSelIndices = new int[faces.Count * g.NumCornersPerFace]; - // var oldIndices = faces.SelectMany(f => f.Indices()); - for (var i = 0; i < faces.Count; i++) - { - for (var t = 0; t < 3; t++) - oldSelIndices[i * 3 + t] = oldIndices.Data[faces[i] * g.NumCornersPerFace + t]; - } - - // We need to create list of newIndices, and remapping - // of oldVertices to newVertices - var newIndices = (-1).Repeat(oldSelIndices.Length).ToArray(); - // Each index could potentially be in the new mesh - var indexLookup = (-1).Repeat(oldIndices.ElementCount).ToArray(); - - // Build mapping. For each index, if the vertex it has - // already been referred to has been mapped, use the - // mapped index. Otherwise, remember that we need this vertex - var numUsedVertices = 0; - // remapping from old vert array => new vert array - // Cache built of the old indices of vertices that are used - // should be equivalent to indexLookup.Where(i => i != -1) - var oldVertices = g.GetAttributePosition(); - var usedVertices = (-1).Repeat(oldVertices.ElementCount).ToArray(); - for (var i = 0; i < oldSelIndices.Length; ++i) - { - var oldIndex = oldSelIndices[i]; - var newIndex = indexLookup[oldIndex]; - if (newIndex < 0) - { - // remapping from old vert array => new vert array - usedVertices[numUsedVertices] = oldIndex; - newIndex = indexLookup[oldIndex] = numUsedVertices++; - } - newIndices[i] = newIndex; - } - - //var faceRemapping = faces.Select(f => f.Index); - var vertRemapping = usedVertices.Take(numUsedVertices).ToIArray(); - var cornerRemapping = g.FaceIndicesToCornerIndices(faces); - - return g.VertexAttributes() - .Select(attr => attr.Remap(vertRemapping)) - .Concat(g.NoneAttributes()) - .Concat(g.FaceAttributes().Select(attr => attr.Remap(faces))) - .Concat(g.EdgeAttributes().Select(attr => attr.Remap(cornerRemapping))) - .Concat(g.CornerAttributes().Select(attr => attr.Remap(cornerRemapping))) - .Concat(g.WholeGeometryAttributes()) - .ToGeometryAttributes() - .SetAttribute(newIndices.ToIndexAttribute()); - } - - public static G3D ToG3d(this IEnumerable attributes, G3dHeader? header = null) - => new G3D(attributes, header); - - public static G3D ToG3d(this IArray attributes, G3dHeader? header = null) - => attributes.ToEnumerable().ToG3d(header); - - public static IArray IndexFlippedRemapping(this IGeometryAttributes g) - => g.NumCorners.Select(c => ((c / g.NumCornersPerFace) + 1) * g.NumCornersPerFace - 1 - c % g.NumCornersPerFace); - - public static bool IsNormalAttribute(this GeometryAttribute attr) - => attr.IsType() && attr.Descriptor.Semantic == "normal"; - - public static IEnumerable FlipNormalAttributes(this IEnumerable self) - => self.Select(attr => attr.IsNormalAttribute() - ? attr.AsType().Data.Select(v => v.Inverse()).ToAttribute(attr.Descriptor) - : attr); - - public static IGeometryAttributes FlipWindingOrder(this IGeometryAttributes g) - => g.VertexAttributes() - .Concat(g.NoneAttributes()) - .Concat(g.FaceAttributes()) - .Concat(g.EdgeAttributes().Select(attr => attr.Remap(g.IndexFlippedRemapping()))) - .Concat(g.CornerAttributes().Select(attr => attr.Remap(g.IndexFlippedRemapping()))) - .Concat(g.WholeGeometryAttributes()) - .FlipNormalAttributes() - .ToGeometryAttributes(); - - public static IGeometryAttributes DoubleSided(this IGeometryAttributes g) - => g.Merge(g.FlipWindingOrder()); - - public static IArray DefaultMaterials(this IGeometryAttributes self) - => (-1).Repeat(self.NumFaces); - - public static IArray DefaultColors(this IGeometryAttributes self) - => Vector4.Zero.Repeat(self.NumVertices); - - public static IArray DefaultUvs(this IGeometryAttributes self) - => Vector2.Zero.Repeat(self.NumVertices); - public static IGeometryAttributes Replace(this IGeometryAttributes self, Func selector, GeometryAttribute attribute) => self.Attributes.Where(a => !selector(a.Descriptor)).Append(attribute).ToGeometryAttributes(); diff --git a/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs b/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs index 03516d76..b194b53c 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs @@ -363,22 +363,6 @@ public static AABox BoundingBox(this IMeshCommon mesh) public static Int3 FaceVertexIndices(this IMeshCommon mesh, int faceIndex) => new Int3(mesh.Indices[faceIndex * 3], mesh.Indices[faceIndex * 3 + 1], mesh.Indices[faceIndex * 3 + 2]); - /// - /// Low-level remap function. Maps faces and corners at the same time. - /// In some cases, this is important (e.g. triangulating quads). - /// Note: meshes are lost. - /// - public static IGeometryAttributes RemapFacesAndCorners(this IGeometryAttributes g, IArray faceRemap, IArray cornerRemap, int numCornersPerFace = -1) - => g.VertexAttributes() - .Concat(g.NoneAttributes()) - .Concat(g.FaceAttributes().Select(attr => attr.Remap(faceRemap))) - .Concat(g.EdgeAttributes().Select(attr => attr.Remap(cornerRemap))) - .Concat(g.CornerAttributes().Select(attr => attr.Remap(cornerRemap))) - .Concat(g.WholeGeometryAttributes()) - .SetFaceSizeAttribute(numCornersPerFace) - .ToGeometryAttributes(); - - public static bool GeometryEquals(this IMeshCommon mesh, IMeshCommon other, float tolerance = Math3d.Constants.Tolerance) { if (!mesh.Indices.SequenceEquals(other.Indices)) From f318a8716e9c43e63d3aa4937874b2ac3b01878f Mon Sep 17 00:00:00 2001 From: simon Date: Fri, 12 Apr 2024 11:14:57 -0400 Subject: [PATCH 162/204] removed more --- src/cs/g3d/Vim.G3d/ObjExporter.cs | 59 -------------- src/cs/g3d/Vim.G3d/PlyExporter.cs | 78 ------------------- src/cs/g3d/Vim.G3d/Validation.cs | 76 ------------------ .../Vim.Format.Core/Geometry/Validation.cs | 1 + .../vim/Vim.Format/SceneBuilder/Validation.cs | 20 +---- 5 files changed, 4 insertions(+), 230 deletions(-) delete mode 100644 src/cs/g3d/Vim.G3d/ObjExporter.cs delete mode 100644 src/cs/g3d/Vim.G3d/PlyExporter.cs delete mode 100644 src/cs/g3d/Vim.G3d/Validation.cs diff --git a/src/cs/g3d/Vim.G3d/ObjExporter.cs b/src/cs/g3d/Vim.G3d/ObjExporter.cs deleted file mode 100644 index b76184dd..00000000 --- a/src/cs/g3d/Vim.G3d/ObjExporter.cs +++ /dev/null @@ -1,59 +0,0 @@ -using System.Collections.Generic; -using System.Text; -using System.IO; -using Vim.LinqArray; - -namespace Vim.G3d -{ - /// - /// This is a simple ObjExporter for the purposes of testing. - /// - public static class ObjExporter - { - public static IEnumerable ObjLines(G3D g3d) - { - // Write the vertices - var vertices = g3d.Vertices; - var uvs = g3d.VertexUvs; - foreach (var v in vertices.ToEnumerable()) - yield return ($"v {v.X} {v.Y} {v.Z}"); - if (uvs != null) - { - for (var v = 0; v < uvs.Count; v++) - yield return ($"vt {uvs[v].X} {uvs[v].Y}"); - } - - var indices = g3d.Indices; - var sb = new StringBuilder(); - var i = 0; - var faceSize = g3d.NumCornersPerFace; - while (i < indices.Count) - { - sb.Append("f"); - - if (uvs == null) - { - for (var j = 0; j < faceSize; ++j) - { - var index = g3d.Indices[i++] + 1; - sb.Append(" ").Append(index); - } - } - else - { - for (var j = 0; j < faceSize; ++j) - { - var index = g3d.Indices[i++] + 1; - sb.Append(" ").Append(index).Append("/").Append(index); - } - } - - yield return sb.ToString(); - sb.Clear(); - } - } - - public static void WriteObj(this G3D g3d, string filePath) - => File.WriteAllLines(filePath, ObjLines(g3d)); - } -} diff --git a/src/cs/g3d/Vim.G3d/PlyExporter.cs b/src/cs/g3d/Vim.G3d/PlyExporter.cs deleted file mode 100644 index 1b2f3425..00000000 --- a/src/cs/g3d/Vim.G3d/PlyExporter.cs +++ /dev/null @@ -1,78 +0,0 @@ -using System.Collections.Generic; -using System.Text; -using System.IO; -using Vim.Math3d; - -namespace Vim.G3d -{ - /// - /// A very simple .ply file exporter - /// - public static class PlyExporter - { - public static void WritePly(this G3D g, string filePath) - => File.WriteAllLines(filePath, PlyStrings(g)); - - public static IEnumerable PlyStrings(G3D g) - { - var vertices = g.Vertices; - var indices = g.Indices; - var colors = g.VertexColors; - - //Write the header - yield return "ply"; - yield return "format ascii 1.0"; - yield return "element vertex " + vertices.Count + ""; - yield return "property float x"; - yield return "property float y"; - yield return "property float z"; - if (colors != null) - { - yield return "property uint8 red"; - yield return "property uint8 green"; - yield return "property uint8 blue"; - } - yield return "element face " + g.NumFaces; - yield return "property list uint8 int32 vertex_index"; - yield return "end_header"; - - // Write the vertices - if (colors != null) - { - for (var i = 0; i < vertices.Count; i++) - { - var v = vertices[i]; - var c = (colors[i] * 255f).Clamp(Vector4.Zero, new Vector4(255, 255, 255, 255)); - - yield return - $"{v.X} {v.Y} {v.Z} {(byte)c.X} {(byte)c.Y} {(byte)c.Z}"; - } - } - else - { - for (var i = 0; i < vertices.Count; i++) - { - var v = vertices[i]; - yield return - $"{v.X} {v.Y} {v.Z}"; - } - } - - // Write the face indices - var index = 0; - var sb = new StringBuilder(); - var faceSize = g.NumCornersPerFace; - for (var i = 0; i < g.NumFaces; i++) - { - sb.Append(faceSize); - for (var j = 0; j < faceSize; j++) - { - sb.Append(" ").Append(indices[index++]); - } - - yield return sb.ToString(); - sb.Clear(); - } - } - } -} diff --git a/src/cs/g3d/Vim.G3d/Validation.cs b/src/cs/g3d/Vim.G3d/Validation.cs deleted file mode 100644 index b1fde949..00000000 --- a/src/cs/g3d/Vim.G3d/Validation.cs +++ /dev/null @@ -1,76 +0,0 @@ -using System.Collections.Generic; -using Vim.LinqArray; - -namespace Vim.G3d -{ - public enum G3dErrors - { - NodesCountMismatch, - MaterialsCountMismatch, - IndicesInvalidCount, - IndicesOutOfRange, - - //Submeshes - SubmeshesCountMismatch, - SubmeshesIndesxOffsetInvalidIndex, - SubmeshesIndexOffsetOutOfRange, - SubmeshesNonPositive, - SubmeshesMaterialOutOfRange, - - //Meshes - MeshesSubmeshOffsetOutOfRange, - MeshesSubmeshCountNonPositive, - - // Instances - InstancesCountMismatch, - InstancesParentOutOfRange, - InstancesMeshOutOfRange, - } - - public static class Validation - { - public static IEnumerable Validate(G3D g3d) - { - var errors = new List(); - - void Validate(bool value, G3dErrors error) - { - if (!value) errors.Add(error); - } - - //Indices - Validate(g3d.Indices.Count % 3 == 0, G3dErrors.IndicesInvalidCount); - Validate(g3d.Indices.All(i => i >= 0 && i < g3d.NumVertices), G3dErrors.IndicesOutOfRange); - //Triangle should have 3 distinct vertices - //Assert.That(g3d.Indices.SubArrays(3).Select(face => face.ToEnumerable().Distinct().Count()).All(c => c == 3)); - - //Submeshes - Validate(g3d.NumSubmeshes >= g3d.NumMeshes, G3dErrors.SubmeshesCountMismatch); - Validate(g3d.NumSubmeshes == g3d.SubmeshMaterials.Count, G3dErrors.SubmeshesCountMismatch); - Validate(g3d.NumSubmeshes == g3d.SubmeshIndexOffsets.Count, G3dErrors.SubmeshesCountMismatch); - Validate(g3d.SubmeshIndexOffsets.All(i => i % 3 == 0), G3dErrors.SubmeshesIndesxOffsetInvalidIndex); - Validate(g3d.SubmeshIndexOffsets.All(i => i >= 0 && i < g3d.NumCorners), G3dErrors.SubmeshesIndexOffsetOutOfRange); - Validate(g3d.SubmeshIndexCount.All(i => i > 0), G3dErrors.SubmeshesNonPositive); - Validate(g3d.SubmeshMaterials.All(m => m < g3d.NumMaterials), G3dErrors.SubmeshesMaterialOutOfRange); - - //Mesh - Validate(g3d.MeshSubmeshOffset.All(i => i >= 0 && i < g3d.NumSubmeshes), G3dErrors.MeshesSubmeshOffsetOutOfRange); - Validate(g3d.MeshSubmeshCount.All(i => i > 0), G3dErrors.MeshesSubmeshCountNonPositive); - - //Instances - Validate(g3d.NumInstances == g3d.InstanceParents.Count, G3dErrors.InstancesCountMismatch); - Validate(g3d.NumInstances == g3d.InstanceMeshes.Count, G3dErrors.InstancesCountMismatch); - Validate(g3d.NumInstances == g3d.InstanceTransforms.Count, G3dErrors.InstancesCountMismatch); - Validate(g3d.NumInstances == g3d.InstanceFlags.Count, G3dErrors.InstancesCountMismatch); - Validate(g3d.InstanceParents.All(i => i < g3d.NumInstances), G3dErrors.InstancesParentOutOfRange); - Validate(g3d.InstanceMeshes.All(i => i < g3d.NumMeshes), G3dErrors.InstancesMeshOutOfRange); - - //Materials - Validate(g3d.NumMaterials == g3d.MaterialColors.Count, G3dErrors.MaterialsCountMismatch); - Validate(g3d.NumMaterials == g3d.MaterialGlossiness.Count, G3dErrors.MaterialsCountMismatch); - Validate(g3d.NumMaterials == g3d.MaterialSmoothness.Count, G3dErrors.MaterialsCountMismatch); - - return errors; - } - } -} diff --git a/src/cs/vim/Vim.Format.Core/Geometry/Validation.cs b/src/cs/vim/Vim.Format.Core/Geometry/Validation.cs index ef12f052..79c1c5b5 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/Validation.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/Validation.cs @@ -100,6 +100,7 @@ public static void ValidateIndices(this IMeshCommon mesh) public static void Validate(this IMeshCommon mesh) { + //TODO: Validate better mesh.ValidateIndices(); } } diff --git a/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs b/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs index 5eaaf8d1..eb9cddbb 100644 --- a/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs +++ b/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs @@ -24,21 +24,7 @@ public class VimValidationException : Exception { public VimValidationException(string message) : base(message) { } } - public static void ValidateGeometry(this VimScene vim) - { - // Validate the packed geometry. - VimMesh.FromG3d(vim.Document.GeometryNext).Validate(); - var errors = new List(); - - G3d.Validation.Validate(vim.Document.Geometry); - } - - public static void ValidateGeometryNext(this VimScene vim) - { - //TODO: Sronger validation maybe. - vim.Document.GeometryNext.Validate(); - } - + public static void ValidateDocumentModelToG3dInvariantsNext(this VimScene vim) { var g3d = vim.Document.GeometryNext; @@ -139,8 +125,8 @@ public static void Validate(this VimScene vim, VimValidationOptions options = nu vim.Document.Validate(); vim.DocumentModel.Validate(options.ObjectModelValidationOptions); - vim.ValidateGeometry(); - vim.ValidateGeometryNext(); + + VimMesh.FromG3d(vim.Document.GeometryNext).Validate(); vim.ValidateDocumentModelToG3dInvariantsNext(); From 528f882d94ac293fd6116cc8e80c6deb68d73281 Mon Sep 17 00:00:00 2001 From: simon Date: Fri, 12 Apr 2024 11:49:13 -0400 Subject: [PATCH 163/204] added clone method --- src/cs/g3d/Vim.G3dNext.CodeGen/G3dCodeGen.cs | 5 +++++ src/cs/g3d/Vim.G3dNext/G3dGenerated.g.cs | 20 ++++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/src/cs/g3d/Vim.G3dNext.CodeGen/G3dCodeGen.cs b/src/cs/g3d/Vim.G3dNext.CodeGen/G3dCodeGen.cs index 59cd7b22..7d04fec4 100644 --- a/src/cs/g3d/Vim.G3dNext.CodeGen/G3dCodeGen.cs +++ b/src/cs/g3d/Vim.G3dNext.CodeGen/G3dCodeGen.cs @@ -85,6 +85,11 @@ public BFast ToBFast() return bfast; }} + public {entity.ClassName} Clone() + {{ + return this.MemberwiseClone() as {entity.ClassName}; + }} + public bool Equals({entity.ClassName} other ) {{ return {string.Join(" && \n \t\t\t", entity.Buffers.Select(b => diff --git a/src/cs/g3d/Vim.G3dNext/G3dGenerated.g.cs b/src/cs/g3d/Vim.G3dNext/G3dGenerated.g.cs index 5a2a9801..1a822426 100644 --- a/src/cs/g3d/Vim.G3dNext/G3dGenerated.g.cs +++ b/src/cs/g3d/Vim.G3dNext/G3dGenerated.g.cs @@ -109,6 +109,11 @@ public BFast ToBFast() return bfast; } + public G3dVim Clone() + { + return this.MemberwiseClone() as G3dVim; + } + public bool Equals(G3dVim other ) { return BufferMethods.SafeEquals(Indices, other.Indices) && @@ -245,6 +250,11 @@ public BFast ToBFast() return bfast; } + public G3dChunk Clone() + { + return this.MemberwiseClone() as G3dChunk; + } + public bool Equals(G3dChunk other ) { return BufferMethods.SafeEquals(MeshOpaqueSubmeshCounts, other.MeshOpaqueSubmeshCounts) && @@ -331,6 +341,11 @@ public BFast ToBFast() return bfast; } + public G3dMaterials Clone() + { + return this.MemberwiseClone() as G3dMaterials; + } + public bool Equals(G3dMaterials other ) { return BufferMethods.SafeEquals(MaterialColors, other.MaterialColors) && @@ -462,6 +477,11 @@ public BFast ToBFast() return bfast; } + public G3dScene Clone() + { + return this.MemberwiseClone() as G3dScene; + } + public bool Equals(G3dScene other ) { return BufferMethods.SafeEquals(ChunkCount, other.ChunkCount) && From df1016df5b9c9131606eb3d51cd26be823ae98ed Mon Sep 17 00:00:00 2001 From: simon Date: Fri, 12 Apr 2024 14:45:33 -0400 Subject: [PATCH 164/204] added hasflag --- src/cs/g3d/Vim.G3dNext/G3dVim.cs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/cs/g3d/Vim.G3dNext/G3dVim.cs b/src/cs/g3d/Vim.G3dNext/G3dVim.cs index b6447235..8cd88443 100644 --- a/src/cs/g3d/Vim.G3dNext/G3dVim.cs +++ b/src/cs/g3d/Vim.G3dNext/G3dVim.cs @@ -4,6 +4,21 @@ namespace Vim.G3dNext { + [Flags] + public enum InstanceFlags + { + /// + /// Default - no instance options defined. + /// + None = 0, + + /// + /// When enabled, indicates that the renderer (or the consuming application) should hide + /// the instance by default. + /// + Hidden = 1, + } + public partial class G3dVim { @@ -21,6 +36,11 @@ public int GetApproxSize(int mesh) return GetMeshVertexCount(mesh) * 12 + GetMeshIndexCount(mesh) * 4; } + public bool InstanceHasFlag(int index, InstanceFlags flag) + { + return InstanceFlags[index] == (int)flag; + } + void ISetup.Setup() { MeshVertexOffsets = ComputeMeshVertexOffsets(); From d2bc28696d3d3e9c39a28045def5ae58a1f139c0 Mon Sep 17 00:00:00 2001 From: simon Date: Fri, 12 Apr 2024 15:02:19 -0400 Subject: [PATCH 165/204] added remove shapes --- src/cs/g3d/Vim.G3dNext/G3dVim.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/cs/g3d/Vim.G3dNext/G3dVim.cs b/src/cs/g3d/Vim.G3dNext/G3dVim.cs index 8cd88443..b21fed00 100644 --- a/src/cs/g3d/Vim.G3dNext/G3dVim.cs +++ b/src/cs/g3d/Vim.G3dNext/G3dVim.cs @@ -87,9 +87,14 @@ private List[] ComputeMeshInstances() return result; } - public int GetTriangleCount() + public G3dVim RemoveShapes() { - return GetIndexCount() / 3; + var result = Clone(); + result.ShapeVertexOffsets = null; + result.ShapeWidths = null; + result.ShapeColors = null; + result.ShapeVertices = null; + return result; } /// From f6086450b98237ff1dc7489c75b34d66704adbe9 Mon Sep 17 00:00:00 2001 From: simon Date: Fri, 12 Apr 2024 15:02:32 -0400 Subject: [PATCH 166/204] added test for clone --- src/cs/Vim.G3dNext.Tests/VimG3dNextTests.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/cs/Vim.G3dNext.Tests/VimG3dNextTests.cs b/src/cs/Vim.G3dNext.Tests/VimG3dNextTests.cs index 2d357abd..a8505b66 100644 --- a/src/cs/Vim.G3dNext.Tests/VimG3dNextTests.cs +++ b/src/cs/Vim.G3dNext.Tests/VimG3dNextTests.cs @@ -40,6 +40,8 @@ public static void Can_Write_And_Read() Assert.IsTrue(g3d.Equals(expected)); } + + [Test] public static void Can_Merge_two_g3d() { @@ -66,6 +68,14 @@ public static void Can_Merge_two_g3d() ); Assert.IsTrue(merged.Equals(expected)); } + + + [Test] + public static void Clone_IsEqual() + { + var g3d = G3dNextTestUtils.CreateTestG3d(); + Assert.IsTrue(g3d.Equals(g3d.Clone())); + } } } From d1a31d5f2851542ecc61fe0fd2bdb5aa08b42853 Mon Sep 17 00:00:00 2001 From: simon Date: Fri, 12 Apr 2024 15:02:49 -0400 Subject: [PATCH 167/204] removed geometry usage --- src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs b/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs index 9a890d64..85675c93 100644 --- a/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs +++ b/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs @@ -51,13 +51,13 @@ public static VimScene LoadVim(string f, LoadOptions loadOptions, IVimSceneProgr => 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); + => 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 BFast(stream), loadOptions), 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); + => LoadVim(stream, new LoadOptions { SkipGeometry = skipGeometry, SkipAssets = skipAssets }, progress, inParallel); public int VimIndex { get; set; } public VimSceneNode[] Nodes { get; private set; } @@ -203,9 +203,8 @@ private void CreateMeshes(bool inParallel) return; } - var srcGeo = _SerializableDocument.Geometry; Meshes = VimMesh.GetAllMeshes(_SerializableDocument.GeometryNext).ToArray(); - MeshesOld = srcGeo?.Meshes.Select(m => m as IMeshCommon); + MeshesOld = _SerializableDocument.Geometry?.Meshes.Select(m => m as IMeshCommon); } private void CreateShapes(bool inParallel) @@ -216,12 +215,12 @@ private void CreateShapes(bool inParallel) } var r = _SerializableDocument.Geometry.Shapes.Select((s, i) => new VimShape(this, i)); ShapesOld = inParallel ? r.EvaluateInParallel() : r.Evaluate(); - Shapes = VimShapeNext.FromG3d(_SerializableDocument.GeometryNext).ToArray(); + Shapes = VimShapeNext.FromG3d(_SerializableDocument.GeometryNext).ToArray(); } private void CreateScene(bool inParallel) { - if (_SerializableDocument.Geometry == null) + if (_SerializableDocument.GeometryNext == null) { return; } @@ -231,7 +230,7 @@ private void CreateScene(bool inParallel) private void CreateMaterials(bool inParallel) { - if (_SerializableDocument.Geometry == null) + if (_SerializableDocument.GeometryNext == null) { return; } @@ -245,7 +244,7 @@ private void CreateMaterials(bool inParallel) public static VimSceneNode[] CreateVimSceneNodes(VimScene scene, G3D g3d, bool inParallel) { Matrix4x4 GetMatrix(int i) => i >= 0 ? g3d.InstanceTransforms[i] : Matrix4x4.Identity; - + return g3d.InstanceTransforms.Select((_, i) => new VimSceneNode(scene, i, g3d.InstanceMeshes[i], GetMatrix(i))).ToArray(); } From f1bd33e68e37924adbb17db96d8fa904e4f6d797 Mon Sep 17 00:00:00 2001 From: simon Date: Fri, 12 Apr 2024 15:52:46 -0400 Subject: [PATCH 168/204] removed most imeshcommon --- .../DocumentBuilderExtensions.cs | 2 +- src/cs/vim/Vim.Format.Core/G3dBuilder.cs | 2 +- .../Vim.Format.Core/Geometry/CatmullClark.cs | 14 ++--- .../Geometry/PerimeterProjection.cs | 6 +- .../Vim.Format.Core/Geometry/Primitives.cs | 18 +++--- .../Vim.Format.Core/Geometry/Validation.cs | 18 ------ .../vim/Vim.Format.Core/Geometry/VimMesh.cs | 59 +++++++++++-------- .../Geometry/GeometryTests.cs | 22 +++---- .../SerializableDocumentTests.cs | 26 -------- .../vim/Vim.Format/SceneBuilder/VimScene.cs | 4 +- .../Vim.Format/SceneBuilder/VimSceneNode.cs | 12 +--- 11 files changed, 71 insertions(+), 112 deletions(-) diff --git a/src/cs/vim/Vim.Format.Core/DocumentBuilderExtensions.cs b/src/cs/vim/Vim.Format.Core/DocumentBuilderExtensions.cs index 02ae2464..6ca4fc9b 100644 --- a/src/cs/vim/Vim.Format.Core/DocumentBuilderExtensions.cs +++ b/src/cs/vim/Vim.Format.Core/DocumentBuilderExtensions.cs @@ -10,7 +10,7 @@ namespace Vim.Format { public static class DocumentBuilderExtensions { - public static SubdividedMesh ToDocumentBuilderSubdividedMesh(this IMeshCommon m) + public static SubdividedMesh ToDocumentBuilderSubdividedMesh(this VimMesh m) => new SubdividedMesh( m.Indices.ToList(), m.Vertices.ToList(), diff --git a/src/cs/vim/Vim.Format.Core/G3dBuilder.cs b/src/cs/vim/Vim.Format.Core/G3dBuilder.cs index 76a4304c..082e957f 100644 --- a/src/cs/vim/Vim.Format.Core/G3dBuilder.cs +++ b/src/cs/vim/Vim.Format.Core/G3dBuilder.cs @@ -40,7 +40,7 @@ public void AddMaterial(IMaterial material) public int MaterialCount => _materials.Count; public int ShapeCount => _shapes.Count; - public IMeshCommon GetMesh(int index) => _meshes[index]; + public VimMesh GetMesh(int index) => _meshes[index]; public AABox GetBox(int meshIndex) { return AABox.Create(_meshes[meshIndex].vertices); diff --git a/src/cs/vim/Vim.Format.Core/Geometry/CatmullClark.cs b/src/cs/vim/Vim.Format.Core/Geometry/CatmullClark.cs index 2f0da338..48c2ac77 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/CatmullClark.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/CatmullClark.cs @@ -1,7 +1,5 @@ using System; using System.Collections.Generic; -using Vim.G3d; -using Vim.LinqArray; using Vim.Math3d; namespace Vim.Format.Geometry @@ -40,7 +38,7 @@ public class GeometryEdge public static class CatmullClarkSmoothing { - public static Dictionary CreateEdgeMap(this IMeshCommon geometry) + public static Dictionary CreateEdgeMap(this VimMesh geometry) { var globalEdgeIndex = 0; var edgeMap = new Dictionary(); @@ -69,7 +67,7 @@ public static Dictionary CreateEdgeMap(this IMesh return edgeMap; } - public static IMeshCommon CatmullClark(this IMeshCommon geometry, float smoothing = 0.0f) + public static VimMesh CatmullClark(this VimMesh geometry, float smoothing = 0.0f) { var edgeMap = geometry.CreateEdgeMap(); @@ -130,7 +128,7 @@ public static IMeshCommon CatmullClark(this IMeshCommon geometry, float smoothin return GenerateMesh(geometry, newVertices, newIndices, edgeMap, facePointStartIndex, edgePointStartIndex, numQuads); } - public static void CalculateFaceCentroidPoints(IMeshCommon geometry, Vector3[] outFacePoints, float[] outVertexNumFaces, Vector3[] outVertexFPoints) + public static void CalculateFaceCentroidPoints(VimMesh geometry, Vector3[] outFacePoints, float[] outVertexNumFaces, Vector3[] outVertexFPoints) { var currentVertexIndex = 0; for (var faceIndex = 0; faceIndex < geometry.NumFaces; faceIndex++) @@ -160,7 +158,7 @@ public static void CalculateFaceCentroidPoints(IMeshCommon geometry, Vector3[] o } } - public static void CalculateEdgePoints(IMeshCommon geometry, Dictionary edgeMap, Vector3[] facePoints, float[] outVertexNumEdges, Vector3[] outVertexRPoints, float smoothing) + public static void CalculateEdgePoints(VimMesh geometry, Dictionary edgeMap, Vector3[] facePoints, float[] outVertexNumEdges, Vector3[] outVertexRPoints, float smoothing) { foreach (var edge in edgeMap) { @@ -187,7 +185,7 @@ public static void CalculateEdgePoints(IMeshCommon geometry, Dictionary edgeMap, int facePointStartIndex, int edgePointStartIndex, int numQuads) + public static VimMesh GenerateMesh(VimMesh geometry, Vector3[] newVertices, int[] newIndices, Dictionary edgeMap, int facePointStartIndex, int edgePointStartIndex, int numQuads) { var currentNewVertexIndex = 0; var currentOldVertexIndex = 0; diff --git a/src/cs/vim/Vim.Format.Core/Geometry/PerimeterProjection.cs b/src/cs/vim/Vim.Format.Core/Geometry/PerimeterProjection.cs index d232a460..b6427d01 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/PerimeterProjection.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/PerimeterProjection.cs @@ -11,7 +11,7 @@ namespace Vim.Format.Geometry public static class PerimeterProjection { - public static List> GeneratePerimeter(this IMeshCommon mesh, Vector3 planeNormal, float degenerateSegmentEpsilon = 10.0f, float edgeLoopThreshold = 1e-6f) + public static List> GeneratePerimeter(this VimMesh mesh, Vector3 planeNormal, float degenerateSegmentEpsilon = 10.0f, float edgeLoopThreshold = 1e-6f) { var q = GetClusterRotation(planeNormal.Normalize(), Vector3.UnitZ); @@ -307,7 +307,7 @@ public int GetHashCode(Tuple obj) => obj.Item1.GetHashCode() ^ obj.Item2.GetHashCode(); } - public static Dictionary, int> BuildEdgeDictionary(this IMeshCommon mesh) + public static Dictionary, int> BuildEdgeDictionary(this VimMesh mesh) { var edges = new Dictionary, int>(new EdgeEqualityComparer()); @@ -327,7 +327,7 @@ public static Dictionary, int> BuildEdgeDictionary(this IMeshCom return edges; } - public static List> BuildBoundarySegments(this IMeshCommon mesh, Dictionary, int> edgeDictionary, Func transform) + public static List> BuildBoundarySegments(this VimMesh mesh, Dictionary, int> edgeDictionary, Func transform) { var segments = new List>(); diff --git a/src/cs/vim/Vim.Format.Core/Geometry/Primitives.cs b/src/cs/vim/Vim.Format.Core/Geometry/Primitives.cs index a0c737d8..01b15b0d 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/Primitives.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/Primitives.cs @@ -10,7 +10,7 @@ namespace Vim.Format.Geometry // TODO: plane, cylinder, cone, ruled face, public static class Primitives { - public static IMeshCommon CreateCube() + public static VimMesh CreateCube() { var vertices = new[] { // front @@ -49,13 +49,13 @@ public static IMeshCommon CreateCube() return new VimMesh(indices, vertices); } - public static IMeshCommon CreateCube(AABox box) + public static VimMesh CreateCube(AABox box) { return CreateCube().Scale(box.Extent).Translate(box.Center); } private static float Sqrt2 = 2.0f.Sqrt(); - public static IMeshCommon CreateTetrahedron() + public static VimMesh CreateTetrahedron() { var vertices = new[] { @@ -67,7 +67,7 @@ public static IMeshCommon CreateTetrahedron() var indices = new[] { 0, 1, 2, 1, 0, 3, 0, 2, 3, 1, 3, 2 }; return new VimMesh(indices, vertices); } - public static IMeshCommon CreateSquare() + public static VimMesh CreateSquare() { var vertices = new[] { @@ -92,7 +92,7 @@ public static Vector3 TorusFunction(Vector2 uv, float radius, float tube) tube * uv.Y.Sin()); } - public static IMeshCommon Torus(float radius, float tubeRadius, int uSegs, int vSegs) + public static VimMesh Torus(float radius, float tubeRadius, int uSegs, int vSegs) => QuadMesh(uv => TorusFunction(uv, radius, tubeRadius), uSegs, vSegs); // see: https://github.com/mrdoob/three.js/blob/9ef27d1af7809fa4d9943f8d4c4644e365ab6d2d/src/geometries/SphereBufferGeometry.js#L76 @@ -102,7 +102,7 @@ public static Vector3 SphereFunction(Vector2 uv, float radius) (float)(radius * Math.Cos(uv.Y * Math3d.Constants.Pi)), (float)(radius * Math.Sin(uv.X * Math3d.Constants.TwoPi) * Math.Sin(uv.Y * Math3d.Constants.Pi))); - public static IMeshCommon Sphere(float radius, int uSegs, int vSegs) + public static VimMesh Sphere(float radius, int uSegs, int vSegs) => QuadMesh(uv => SphereFunction(uv, radius), uSegs, vSegs); /// @@ -256,13 +256,13 @@ public static IArray TriMeshCylinderCapIndices(int numEdgeVertices) /// /// Creates a quad mesh given a mapping from 2 space to 3 space /// - public static IMeshCommon QuadMesh(this Func f, int segs) + public static VimMesh QuadMesh(this Func f, int segs) => QuadMesh(f, segs, segs); /// /// Creates a quad mesh given a mapping from 2 space to 3 space /// - public static IMeshCommon QuadMesh(this Func f, int usegs, int vsegs, bool wrapUSegs = false, bool wrapVSegs = false) + public static VimMesh QuadMesh(this Func f, int usegs, int vsegs, bool wrapUSegs = false, bool wrapVSegs = false) { var verts = new List(); var maxUSegs = wrapUSegs ? usegs : usegs + 1; @@ -285,7 +285,7 @@ public static IMeshCommon QuadMesh(this Func f, int usegs, int /// /// Creates a revolved face ... note that the last points are on top of the original /// - public static IMeshCommon RevolveAroundAxis(this IArray points, Vector3 axis, int segments = 4) + public static VimMesh RevolveAroundAxis(this IArray points, Vector3 axis, int segments = 4) { var verts = new List(); for (var i = 0; i < segments; ++i) diff --git a/src/cs/vim/Vim.Format.Core/Geometry/Validation.cs b/src/cs/vim/Vim.Format.Core/Geometry/Validation.cs index 79c1c5b5..88cf5f9f 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/Validation.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/Validation.cs @@ -83,25 +83,7 @@ public static void Validate(this Document doc) { doc.ValidateTableRows(); doc.ValidateIndexColumns(); - doc.ValidateGeometryAttributes(); doc.ValidateAssets(); } - - // TODO: ValidateShapes() to validate VIM files which contain optional 2d data (shapes/overlays). - - public static void ValidateIndices(this IMeshCommon mesh) - { - foreach (var index in mesh.Indices.ToEnumerable()) - { - if (index < 0 || index >= mesh.NumVertices) - throw new Exception($"Invalid mesh index: {index}. Expected a value greater or equal to 0 and less than {mesh.NumVertices}"); - } - } - - public static void Validate(this IMeshCommon mesh) - { - //TODO: Validate better - mesh.ValidateIndices(); - } } } diff --git a/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs b/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs index b194b53c..43ec0313 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs @@ -9,7 +9,7 @@ namespace Vim.Format.Geometry { - public class VimMesh : IMeshCommon + public class VimMesh : ITransformable3D { public IArray Vertices => vertices.ToIArray(); @@ -123,9 +123,6 @@ public VimMesh Clone() ); return mesh; } - IMeshCommon IMeshCommon.Clone() => Clone(); - - IMeshCommon ITransformable3D.Transform(Matrix4x4 mat) => Transform(mat); public VimMesh Transform(Matrix4x4 mat) { var mesh = Clone(); @@ -223,11 +220,25 @@ public void SetIndices(int[] indices) { this.indices = indices; } + + public void Validate() + { + //TODO: Validate better + ValidateIndices(); + } + private void ValidateIndices() + { + foreach (var index in Indices.ToEnumerable()) + { + if (index < 0 || index >= NumVertices) + throw new Exception($"Invalid mesh index: {index}. Expected a value greater or equal to 0 and less than {NumVertices}"); + } + } } public static class MeshCommonExtensions { - public static IMeshCommon ReverseWindingOrder(this IMeshCommon mesh) + public static VimMesh ReverseWindingOrder(this VimMesh mesh) { var result = mesh.Clone(); var count = mesh.Indices.Count; @@ -243,7 +254,7 @@ public static IMeshCommon ReverseWindingOrder(this IMeshCommon mesh) } - public static IArray GetFaceMaterials(this IMeshCommon mesh) + public static IArray GetFaceMaterials(this VimMesh mesh) { // SubmeshIndexOffsets: [0, A, B] // SubmeshIndexCount: [X, Y, Z] @@ -257,9 +268,9 @@ public static IArray GetFaceMaterials(this IMeshCommon mesh) .ToIArray(); } - public static IMeshCommon Merge2(this IMeshCommon mesh, params IMeshCommon[] others) + public static VimMesh Merge2(this VimMesh mesh, params VimMesh[] others) { - var meshes = Enumerable.Empty() + var meshes = Enumerable.Empty() .Append(mesh) .Append(others) .ToArray(); @@ -267,7 +278,7 @@ public static IMeshCommon Merge2(this IMeshCommon mesh, params IMeshCommon[] oth return meshes.Merge(); } - public static IMeshCommon Merge(this IMeshCommon[] meshes) + public static VimMesh Merge(this VimMesh[] meshes) { void Merge(IArray from, int[] to, int offset, int increment) { @@ -305,12 +316,12 @@ void Merge(IArray from, int[] to, int offset, int increment) return result; } - public static VimMesh[] SplitSubmeshes(this IMeshCommon mesh) + public static VimMesh[] SplitSubmeshes(this VimMesh mesh) { return null; } - public static (int, List)[] GroupSubmeshesByMaterials(this IMeshCommon mesh) + public static (int, List)[] GroupSubmeshesByMaterials(this VimMesh mesh) { var submeshCount = mesh.SubmeshIndexOffsets.Count; var map = new Dictionary>(); @@ -329,41 +340,41 @@ public static (int, List)[] GroupSubmeshesByMaterials(this IMeshCommon mesh return map.Select(kvp => (kvp.Key, kvp.Value)).ToArray(); } - public static Triangle VertexIndicesToTriangle(this IMeshCommon mesh, Int3 indices) + public static Triangle VertexIndicesToTriangle(this VimMesh mesh, Int3 indices) => new Triangle(mesh.Vertices[indices.X], mesh.Vertices[indices.Y], mesh.Vertices[indices.Z]); - public static bool Planar(this IMeshCommon mesh, float tolerance = Math3d.Constants.Tolerance) + public static bool Planar(this VimMesh mesh, float tolerance = Math3d.Constants.Tolerance) { if (mesh.NumFaces <= 1) return true; var normal = mesh.Triangle(0).Normal; return mesh.ComputedNormals().All(n => n.AlmostEquals(normal, tolerance)); } - public static VimMesh Unindex(this IMeshCommon mesh) + public static VimMesh Unindex(this VimMesh mesh) { var vertices = mesh.Indices.Select(i => mesh.Vertices[i]); return new VimMesh(vertices.ToArray()); } - public static IArray ComputedNormals(this IMeshCommon mesh) + public static IArray ComputedNormals(this VimMesh mesh) => mesh.Triangles().Select(t => t.Normal); - public static Triangle Triangle(this IMeshCommon mesh, int face) + public static Triangle Triangle(this VimMesh mesh, int face) => mesh.VertexIndicesToTriangle(mesh.FaceVertexIndices(face)); - public static IArray Triangles(this IMeshCommon mesh) + public static IArray Triangles(this VimMesh mesh) => mesh.NumFaces.Select(mesh.Triangle); - public static Vector3 Center(this IMeshCommon mesh) + public static Vector3 Center(this VimMesh mesh) => mesh.BoundingBox().Center; - public static AABox BoundingBox(this IMeshCommon mesh) + public static AABox BoundingBox(this VimMesh mesh) => AABox.Create(mesh.Vertices.ToEnumerable()); - public static Int3 FaceVertexIndices(this IMeshCommon mesh, int faceIndex) + public static Int3 FaceVertexIndices(this VimMesh mesh, int faceIndex) => new Int3(mesh.Indices[faceIndex * 3], mesh.Indices[faceIndex * 3 + 1], mesh.Indices[faceIndex * 3 + 2]); - public static bool GeometryEquals(this IMeshCommon mesh, IMeshCommon other, float tolerance = Math3d.Constants.Tolerance) + public static bool GeometryEquals(this VimMesh mesh, VimMesh other, float tolerance = Math3d.Constants.Tolerance) { if (!mesh.Indices.SequenceEquals(other.Indices)) return false; @@ -389,11 +400,11 @@ public static bool GeometryEquals(this IMeshCommon mesh, IMeshCommon other, floa return true; } - public static (int mat, IMeshCommon mesh)[] SplitByMaterial(this IMeshCommon mesh) + public static (int mat, VimMesh mesh)[] SplitByMaterial(this VimMesh mesh) { var map = mesh.GroupSubmeshesByMaterials(); - var result = new (int, IMeshCommon)[map.Length]; + var result = new (int, VimMesh)[map.Length]; if (map.Length == 1) { result[0] = (mesh.SubmeshMaterials[0], mesh); @@ -409,7 +420,7 @@ public static (int mat, IMeshCommon mesh)[] SplitByMaterial(this IMeshCommon mes return result; } - public static VimMesh PickSubmeshes(this IMeshCommon mesh, IList submeshes) + public static VimMesh PickSubmeshes(this VimMesh mesh, IList submeshes) { var map = mesh.GroupSubmeshesByMaterials(); diff --git a/src/cs/vim/Vim.Format.Tests/Geometry/GeometryTests.cs b/src/cs/vim/Vim.Format.Tests/Geometry/GeometryTests.cs index 22945f35..7863f425 100644 --- a/src/cs/vim/Vim.Format.Tests/Geometry/GeometryTests.cs +++ b/src/cs/vim/Vim.Format.Tests/Geometry/GeometryTests.cs @@ -11,14 +11,14 @@ namespace Vim.Format.Tests.Geometry { public static class GeometryTests { - public static IMeshCommon XYTriangle = new VimMesh( + public static VimMesh XYTriangle = new VimMesh( new[] { 0, 1, 2 }, new[] { new Vector3(0f, 0f, 0f), new Vector3(0f, 1f, 0f), new Vector3(1f, 0f, 0f) }); - public static IMeshCommon XYQuad = VimMesh.FromQuad( + public static VimMesh XYQuad = VimMesh.FromQuad( new int[] { 0, 1, 2, 3 }, new[]{ new Vector3(0f, 0f, 0f), new Vector3(0f, 1f, 0f), @@ -26,11 +26,11 @@ public static class GeometryTests new Vector3(1f, 0f, 0f) }); - public static IMeshCommon XYQuadFromFunc = Primitives.QuadMesh(uv => uv.ToVector3(), 1, 1); - public static IMeshCommon XYQuad2x2 = Primitives.QuadMesh(uv => uv.ToVector3(), 2, 2); - public static IMeshCommon XYTriangleTwice = XYTriangle.Merge2(XYTriangle.Translate(new Vector3(1, 0, 0))); + public static VimMesh XYQuadFromFunc = Primitives.QuadMesh(uv => uv.ToVector3(), 1, 1); + public static VimMesh XYQuad2x2 = Primitives.QuadMesh(uv => uv.ToVector3(), 2, 2); + public static VimMesh XYTriangleTwice = XYTriangle.Merge2(XYTriangle.Translate(new Vector3(1, 0, 0))); - public static IMeshCommon Tetrahedron = new VimMesh( + public static VimMesh Tetrahedron = new VimMesh( new[] { 0, 1, 2, 0, 3, 1, 1, 3, 2, 2, 3, 0 }, new[] { Vector3.Zero, Vector3.UnitX, @@ -38,14 +38,14 @@ public static class GeometryTests Vector3.UnitZ }); - public static IMeshCommon Torus = Primitives.Torus(10, 0.2f, 10, 24); + public static VimMesh Torus = Primitives.Torus(10, 0.2f, 10, 24); - static IMeshCommon RevolvedVerticalCylinder(float height, float radius, int verticalSegments, int radialSegments) + static VimMesh RevolvedVerticalCylinder(float height, float radius, int verticalSegments, int radialSegments) => (Vector3.UnitZ * height).ToLine().Interpolate(verticalSegments).Add(-radius.AlongX()).RevolveAroundAxis(Vector3.UnitZ, radialSegments); - public static IMeshCommon Cylinder = RevolvedVerticalCylinder(5, 1, 4, 12); + public static VimMesh Cylinder = RevolvedVerticalCylinder(5, 1, 4, 12); - public static IMeshCommon[] AllMeshes = { + public static VimMesh[] AllMeshes = { XYTriangle, // 0 XYQuad, // 1 XYQuadFromFunc, // 2 @@ -58,7 +58,7 @@ static IMeshCommon RevolvedVerticalCylinder(float height, float radius, int vert public static double SmallTolerance = 0.0001; - public static void GeometryNullOps(IMeshCommon g) + public static void GeometryNullOps(VimMesh g) { g.GeometryEquals(g); g.Translate(Vector3.Zero).GeometryEquals(g); diff --git a/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs b/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs index 49814ab1..9c09387e 100644 --- a/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs +++ b/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs @@ -200,32 +200,6 @@ public static void Materials_AreSame() // mesh.SubmeshMaterials.Sum(); //} - private static void Consume(IMeshCommon mesh) - { - mesh.Indices.Sum(); - mesh.Vertices.Sum(v => v.X); - mesh.SubmeshIndexOffsets.Sum(); - mesh.SubmeshIndexCounts.Sum(); - mesh.SubmeshMaterials.Sum(); - } - - - //private static void MeshesAreSame(IMesh mesh, IMeshCommon next) - //{ - // Assert.That(mesh.Indices.SequenceEquals(next.Indices)); - // Assert.That(mesh.Vertices.SequenceEquals(next.Vertices)); - // Assert.That(mesh.SubmeshIndexOffsets.SequenceEquals(next.SubmeshIndexOffsets)); - // Assert.That(mesh.SubmeshMaterials.SequenceEquals(next.SubmeshMaterials)); - // Assert.That(mesh.SubmeshIndexCount.SequenceEquals(next.SubmeshIndexCounts)); - //} - private static void MeshesAreSame(IMeshCommon mesh, IMeshCommon next) - { - Assert.That(mesh.Indices.SequenceEquals(next.Indices)); - Assert.That(mesh.Vertices.SequenceEquals(next.Vertices)); - Assert.That(mesh.SubmeshIndexOffsets.SequenceEquals(next.SubmeshIndexOffsets)); - Assert.That(mesh.SubmeshMaterials.SequenceEquals(next.SubmeshMaterials)); - Assert.That(mesh.SubmeshIndexCounts.SequenceEquals(next.SubmeshIndexCounts)); - } private static void ShapesAreSame(VimShape mesh, VimShapeNext next) { diff --git a/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs b/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs index 85675c93..74da76ab 100644 --- a/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs +++ b/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs @@ -82,10 +82,10 @@ public string PersistingId public int GetShapeCount() => Shapes.Length; public int GetNodeCount() => Nodes.Length; - public IEnumerable TransformedMeshes() + public IEnumerable TransformedMeshes() => Nodes.Where(n => n.GetMesh() != null).Select(n => n.TransformedMesh()); - public IMeshCommon MergedGeometry() + public VimMesh MergedGeometry() => Nodes.MergedGeometry(); public IEnumerable AllVertices() diff --git a/src/cs/vim/Vim.Format/SceneBuilder/VimSceneNode.cs b/src/cs/vim/Vim.Format/SceneBuilder/VimSceneNode.cs index 9d2eba2b..28e37b5f 100644 --- a/src/cs/vim/Vim.Format/SceneBuilder/VimSceneNode.cs +++ b/src/cs/vim/Vim.Format/SceneBuilder/VimSceneNode.cs @@ -28,13 +28,7 @@ public VimSceneNode(VimScene scene, int nodeIndex, int geometryIndex, Matrix4x4 public Matrix4x4 Transform { get; } public bool HideByDefault - { - get - { - var instanceFlags = (InstanceFlags)Scene.Document.Geometry.InstanceFlags.ElementAtOrDefault(NodeIndex); - return (instanceFlags & InstanceFlags.Hidden) == InstanceFlags.Hidden; - } - } + => Scene.Document.GeometryNext.InstanceHasFlag(NodeIndex, G3dNext.InstanceFlags.Hidden); public int VimIndex { get; } = -1; public int NodeIndex { get; } = -1; @@ -58,7 +52,7 @@ public VimMesh GetMesh() VimSceneNode ITransformable3D.Transform(Matrix4x4 mat) => new VimSceneNode(Scene, Id, MeshIndex, mat * Transform); - public IMeshCommon TransformedMesh() + public VimMesh TransformedMesh() => GetMesh()?.Transform(Transform); public IArray TransformedVertices() @@ -70,7 +64,7 @@ public AABox TransformedBoundingBox() public static class NodeExtensions { - public static IMeshCommon MergedGeometry(this IEnumerable nodes) + public static VimMesh MergedGeometry(this IEnumerable nodes) => nodes.Where(n => n.GetMesh() != null).Select(n => n.TransformedMesh()).ToArray().Merge(); } } From 29e340172948ab68859c2d9a49baad769a1571ee Mon Sep 17 00:00:00 2001 From: simon Date: Fri, 12 Apr 2024 16:12:02 -0400 Subject: [PATCH 169/204] removing g3d using --- .../DocumentBuilderExtensions.cs | 1 - .../Vim.Format.Core/DocumentBuilderTypes.cs | 3 +- .../Geometry/PerimeterProjection.cs | 1 - .../Vim.Format.Core/Geometry/Primitives.cs | 1 - .../Vim.Format.Core/Geometry/Validation.cs | 30 ------------------- .../vim/Vim.Format.Core/Geometry/VimMesh.cs | 1 - src/cs/vim/Vim.Format.Core/Validation.cs | 30 ------------------- .../Geometry/GeometryTests.cs | 5 ++-- .../SerializableDocumentTests.cs | 11 +++---- .../vim/Vim.Format/SceneBuilder/Validation.cs | 3 +- .../Vim.Format/SceneBuilder/VimSceneNode.cs | 1 - 11 files changed, 8 insertions(+), 79 deletions(-) diff --git a/src/cs/vim/Vim.Format.Core/DocumentBuilderExtensions.cs b/src/cs/vim/Vim.Format.Core/DocumentBuilderExtensions.cs index 6ca4fc9b..27597945 100644 --- a/src/cs/vim/Vim.Format.Core/DocumentBuilderExtensions.cs +++ b/src/cs/vim/Vim.Format.Core/DocumentBuilderExtensions.cs @@ -2,7 +2,6 @@ using System.Linq; using Vim.BFastLib; using Vim.Format.Geometry; -using Vim.G3d; using Vim.LinqArray; using static Vim.Format.DocumentBuilder; diff --git a/src/cs/vim/Vim.Format.Core/DocumentBuilderTypes.cs b/src/cs/vim/Vim.Format.Core/DocumentBuilderTypes.cs index ca2c4f94..7d48f289 100644 --- a/src/cs/vim/Vim.Format.Core/DocumentBuilderTypes.cs +++ b/src/cs/vim/Vim.Format.Core/DocumentBuilderTypes.cs @@ -2,9 +2,8 @@ using System.Collections.Generic; using System.Linq; using Vim.Format.Geometry; -using Vim.G3d; +using Vim.G3dNext; using Vim.Math3d; -using static Vim.Format.DocumentBuilder; namespace Vim.Format { diff --git a/src/cs/vim/Vim.Format.Core/Geometry/PerimeterProjection.cs b/src/cs/vim/Vim.Format.Core/Geometry/PerimeterProjection.cs index b6427d01..d4418352 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/PerimeterProjection.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/PerimeterProjection.cs @@ -4,7 +4,6 @@ using System.Linq; using Vim.LinqArray; using Vim.Math3d; -using Vim.G3d; namespace Vim.Format.Geometry { diff --git a/src/cs/vim/Vim.Format.Core/Geometry/Primitives.cs b/src/cs/vim/Vim.Format.Core/Geometry/Primitives.cs index 01b15b0d..97e09d20 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/Primitives.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/Primitives.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using Vim.G3d; using Vim.LinqArray; 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 88cf5f9f..e987282a 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/Validation.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/Validation.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using Vim.G3d; using Vim.LinqArray; using Vim.BFastLib; @@ -45,34 +43,6 @@ public static void ValidateIndexColumns(this Document doc) } } - public static string[] RequiredAttributeNames => new [] - { - // Vertices - CommonAttributes.Position, - CommonAttributes.Index, - - // Meshes - CommonAttributes.MeshSubmeshOffset, - - // Submeshes - CommonAttributes.SubmeshIndexOffset, - - // Instances - CommonAttributes.InstanceMesh, - CommonAttributes.InstanceTransform, - }; - - public static void ValidateGeometryAttributes(this Document doc) - { - var attributes = doc.Geometry.Attributes; - var attributeNameSet = new HashSet(attributes.Select(a => a.Name).ToEnumerable()); - foreach (var attributeName in RequiredAttributeNames) - { - if (!attributeNameSet.Contains(attributeName)) - throw new Exception($"Required attribute {attributeName} was not found."); - } - } - public static void ValidateAssets(this Document doc) { foreach (var asset in doc.Assets.Values.ToEnumerable()) diff --git a/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs b/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs index 43ec0313..719d9a8f 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using Vim.G3d; using Vim.G3dNext; using Vim.LinqArray; using Vim.Math3d; diff --git a/src/cs/vim/Vim.Format.Core/Validation.cs b/src/cs/vim/Vim.Format.Core/Validation.cs index 5419ef54..e44b2d1c 100644 --- a/src/cs/vim/Vim.Format.Core/Validation.cs +++ b/src/cs/vim/Vim.Format.Core/Validation.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using Vim.BFastLib; -using Vim.G3d; using Vim.LinqArray; namespace Vim.Format @@ -45,34 +44,6 @@ public static void ValidateIndexColumns(this Document doc) } } - public static string[] RequiredAttributeNames => new [] - { - // Vertices - CommonAttributes.Position, - CommonAttributes.Index, - - // Meshes - CommonAttributes.MeshSubmeshOffset, - - // Submeshes - CommonAttributes.SubmeshIndexOffset, - - // Instances - CommonAttributes.InstanceMesh, - CommonAttributes.InstanceTransform, - }; - - public static void ValidateGeometryAttributes(this Document doc) - { - var attributes = doc.Geometry.Attributes; - var attributeNameSet = new HashSet(attributes.Select(a => a.Name).ToEnumerable()); - foreach (var attributeName in RequiredAttributeNames) - { - if (!attributeNameSet.Contains(attributeName)) - throw new Exception($"Required attribute {attributeName} was not found."); - } - } - public static void ValidateAssets(this Document doc) { foreach (var asset in doc.Assets.Values.ToEnumerable()) @@ -83,7 +54,6 @@ public static void Validate(this Document doc) { doc.ValidateTableRows(); doc.ValidateIndexColumns(); - doc.ValidateGeometryAttributes(); doc.ValidateAssets(); } diff --git a/src/cs/vim/Vim.Format.Tests/Geometry/GeometryTests.cs b/src/cs/vim/Vim.Format.Tests/Geometry/GeometryTests.cs index 7863f425..334c882c 100644 --- a/src/cs/vim/Vim.Format.Tests/Geometry/GeometryTests.cs +++ b/src/cs/vim/Vim.Format.Tests/Geometry/GeometryTests.cs @@ -1,8 +1,7 @@ -using System; +using NUnit.Framework; +using System; using System.Linq; -using NUnit.Framework; using Vim.Format.Geometry; -using Vim.G3d; using Vim.G3dNext; using Vim.LinqArray; using Vim.Math3d; diff --git a/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs b/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs index 9c09387e..676a99f0 100644 --- a/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs +++ b/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs @@ -1,13 +1,10 @@ using NUnit.Framework; -using Vim.Util.Tests; -using Vim.Format.SceneBuilder; -using Vim.G3dNext; +using System; +using System.Linq; using Vim.Format.Geometry; +using Vim.Format.SceneBuilder; using Vim.LinqArray; -using Vim.Math3d; -using Vim.G3d; -using System.Linq; -using System; +using Vim.Util.Tests; 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 eb9cddbb..b969efe3 100644 --- a/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs +++ b/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs @@ -6,10 +6,9 @@ using Vim.BFastLib; using Vim.Format.Geometry; using Vim.Format.ObjectModel; -using Vim.Util; using Vim.LinqArray; using Vim.Math3d; -using Vim.G3d; +using Vim.Util; namespace Vim.Format.SceneBuilder { diff --git a/src/cs/vim/Vim.Format/SceneBuilder/VimSceneNode.cs b/src/cs/vim/Vim.Format/SceneBuilder/VimSceneNode.cs index 28e37b5f..28e34077 100644 --- a/src/cs/vim/Vim.Format/SceneBuilder/VimSceneNode.cs +++ b/src/cs/vim/Vim.Format/SceneBuilder/VimSceneNode.cs @@ -3,7 +3,6 @@ using System.Linq; using Vim.Format.Geometry; using Vim.Format.ObjectModel; -using Vim.G3d; using Vim.G3dNext; using Vim.LinqArray; using Vim.Math3d; From 2fa516ff7e69b09a193cf1936ddae862bac1ff66 Mon Sep 17 00:00:00 2001 From: simon Date: Mon, 15 Apr 2024 14:37:20 -0400 Subject: [PATCH 170/204] removed old geometry --- src/cs/vim/Vim.Format.Core/Document.cs | 2 - .../Vim.Format.Core/SerializableDocument.cs | 6 --- .../SerializableDocumentTests.cs | 42 ------------------- .../vim/Vim.Format/SceneBuilder/Validation.cs | 6 +-- .../vim/Vim.Format/SceneBuilder/VimScene.cs | 15 +------ .../vim/Vim.Format/SceneBuilder/VimShape.cs | 25 ----------- 6 files changed, 5 insertions(+), 91 deletions(-) delete mode 100644 src/cs/vim/Vim.Format/SceneBuilder/VimShape.cs diff --git a/src/cs/vim/Vim.Format.Core/Document.cs b/src/cs/vim/Vim.Format.Core/Document.cs index eecebb48..27a4d978 100644 --- a/src/cs/vim/Vim.Format.Core/Document.cs +++ b/src/cs/vim/Vim.Format.Core/Document.cs @@ -11,7 +11,6 @@ public Document(SerializableDocument document) { _Document = document; Header = _Document.Header; - Geometry = _Document.Geometry; GeometryNext = _Document.GeometryNext; StringTable = _Document.StringTable.ToIArray(); EntityTables = _Document.EntityTables.ToLookup( @@ -27,7 +26,6 @@ public Document(SerializableDocument document) public ILookup Assets { get; } public IArray StringTable { get; } public string GetString(int index) => StringTable.ElementAtOrDefault(index); - public G3d.G3D Geometry { get; } public G3dVim GeometryNext { get; } } } diff --git a/src/cs/vim/Vim.Format.Core/SerializableDocument.cs b/src/cs/vim/Vim.Format.Core/SerializableDocument.cs index 31f1772e..94364b97 100644 --- a/src/cs/vim/Vim.Format.Core/SerializableDocument.cs +++ b/src/cs/vim/Vim.Format.Core/SerializableDocument.cs @@ -49,11 +49,6 @@ public class SerializableDocument /// public INamedBuffer[] Assets = Array.Empty(); - /// - /// The uninstanced / untransformed geometry - /// - public G3d.G3D Geometry; - /// /// The uninstanced / untransformed geometry /// @@ -128,7 +123,6 @@ public static SerializableDocument FromBFast(BFast bfast, LoadOptions options = { var geo = bfast.GetBFast(BufferNames.Geometry); doc.GeometryNext = new G3dVim(geo); - doc.Geometry = G3D.Read(geo); } var entities = bfast.GetBFast(BufferNames.Entities); diff --git a/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs b/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs index 676a99f0..409323e5 100644 --- a/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs +++ b/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs @@ -28,40 +28,6 @@ public static void CanOpenVim() scene.Validate(); } - [Test] - public static void ShapesAreSame() - { - var path = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); - var scene = VimScene.LoadVim(path); - - var shapes = scene.ShapesOld; - var next = scene.Shapes; - Assert.AreEqual(shapes.Count, next.Length); - for (var i = 0; i < shapes.Count; i++) - { - ShapesAreSame(shapes[i], next[i]); - } - } - - - - [Test] - public static void Materials_AreSame() - { - var path = VimFormatRepoPaths.GetLatestWolfordResidenceVim(); - var scene = VimScene.LoadVim(path); - - var mats = scene.MaterialsOld; - var next = scene.Materials; - Assert.AreEqual(mats.Count, next.Length); - for (var i = 0; i < mats.Count; i++) - { - MaterialsAreSame(mats[i], next[i]); - } - - } - - //[Test] //public static void GetMesh_IsSameMesh() //{ @@ -197,14 +163,6 @@ public static void Materials_AreSame() // mesh.SubmeshMaterials.Sum(); //} - - private static void ShapesAreSame(VimShape mesh, VimShapeNext next) - { - Assert.That(mesh.Vertices.ToEnumerable().SequenceEqual(next.Vertices)); - Assert.AreEqual(mesh.Color, next.Color); - Assert.AreEqual(mesh.Width, next.Width); - } - private static void MaterialsAreSame(IMaterial mesh, VimMaterialNext next) { Assert.AreEqual(mesh.Color, next.Color); diff --git a/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs b/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs index b969efe3..ceb34e38 100644 --- a/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs +++ b/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs @@ -91,7 +91,7 @@ public static void ValidateShapes(this VimScene vim) { var shapes = vim.Shapes; if (vim.GetShapeCount() != vim.DocumentModel.NumShape) - throw new VimValidationException($"The number of {nameof(VimShape)} ({vim.GetShapeCount()}) does not match the number of shape entities ({vim.DocumentModel.NumShape})"); + throw new VimValidationException($"The number of {nameof(VimShapeNext)} ({vim.GetShapeCount()}) does not match the number of shape entities ({vim.DocumentModel.NumShape})"); void ValidateColorDomain(string label, Vector4 value, Vector4 lowerInclusive, Vector4 upperInclusive, int index) { @@ -113,8 +113,8 @@ void ValidateColorDomain(string label, Vector4 value, Vector4 lowerInclusive, Ve var shape = shapes[shapeIndex]; var element = vim.DocumentModel.GetShapeElementIndex(shapeIndex); if (element < 0) - throw new VimValidationException($"{nameof(Element)} is null for {nameof(VimShape)} {shape.Index}"); - ValidateColorDomain($"{nameof(VimShape)} color", shape.Color, Vector4.Zero, Vector4.One, shape.Index); + throw new VimValidationException($"{nameof(Element)} is null for {nameof(VimShapeNext)} {shape.Index}"); + ValidateColorDomain($"{nameof(VimShapeNext)} color", shape.Color, Vector4.Zero, Vector4.One, shape.Index); }); } diff --git a/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs b/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs index 74da76ab..ec11608c 100644 --- a/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs +++ b/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs @@ -66,10 +66,6 @@ public static VimScene LoadVim(Stream stream, IVimSceneProgress progress = null, public VimShapeNext[] Shapes { get; private set; } public VimMaterialNext[] Materials { get; private set; } - public IArray ShapesOld { get; private set; } - public IArray MaterialsOld { get; private set; } - public IArray MeshesOld { get; private set; } - public SerializableDocument _SerializableDocument { get; } public Document Document { get; private set; } public DocumentModel DocumentModel { get; private set; } @@ -204,7 +200,6 @@ private void CreateMeshes(bool inParallel) } Meshes = VimMesh.GetAllMeshes(_SerializableDocument.GeometryNext).ToArray(); - MeshesOld = _SerializableDocument.Geometry?.Meshes.Select(m => m as IMeshCommon); } private void CreateShapes(bool inParallel) @@ -213,8 +208,6 @@ private void CreateShapes(bool inParallel) { return; } - var r = _SerializableDocument.Geometry.Shapes.Select((s, i) => new VimShape(this, i)); - ShapesOld = inParallel ? r.EvaluateInParallel() : r.Evaluate(); Shapes = VimShapeNext.FromG3d(_SerializableDocument.GeometryNext).ToArray(); } @@ -225,7 +218,7 @@ private void CreateScene(bool inParallel) return; } - Nodes = CreateVimSceneNodes(this, _SerializableDocument.Geometry, inParallel); + Nodes = CreateVimSceneNodes(this, _SerializableDocument.GeometryNext, inParallel); } private void CreateMaterials(bool inParallel) @@ -234,14 +227,10 @@ private void CreateMaterials(bool inParallel) { return; } - - var query = _SerializableDocument.Geometry.Materials.Select(m => new VimMaterial(m) as IMaterial); - MaterialsOld = inParallel ? query.EvaluateInParallel() : query.Evaluate(); Materials = VimMaterialNext.FromG3d(_SerializableDocument.GeometryNext).ToArray(); - } - public static VimSceneNode[] CreateVimSceneNodes(VimScene scene, G3D g3d, bool inParallel) + public static VimSceneNode[] CreateVimSceneNodes(VimScene scene, G3dVim g3d, bool inParallel) { Matrix4x4 GetMatrix(int i) => i >= 0 ? g3d.InstanceTransforms[i] : Matrix4x4.Identity; diff --git a/src/cs/vim/Vim.Format/SceneBuilder/VimShape.cs b/src/cs/vim/Vim.Format/SceneBuilder/VimShape.cs deleted file mode 100644 index 112a6a13..00000000 --- a/src/cs/vim/Vim.Format/SceneBuilder/VimShape.cs +++ /dev/null @@ -1,25 +0,0 @@ -using Vim.Format.ObjectModel; -using Vim.G3d; -using Vim.LinqArray; -using Vim.Math3d; - -namespace Vim -{ - public class VimShape : ElementInfo - { - public readonly VimScene Scene; - public readonly int ShapeIndex; - - public G3dShape G3dShape => Scene.Document.Geometry.Shapes[ShapeIndex]; - public IArray Vertices => G3dShape.Vertices; - public Vector4 Color => G3dShape.Color; - public float Width => G3dShape.Width; - - public VimShape(VimScene scene, int shapeIndex) - : base(scene.DocumentModel, scene.DocumentModel.GetShapeElementIndex(shapeIndex)) - { - Scene = scene; - ShapeIndex = shapeIndex; - } - } -} From 75749ba96ef4d152cd68ec3e07a8ab16776d538a Mon Sep 17 00:00:00 2001 From: simon Date: Mon, 15 Apr 2024 15:03:22 -0400 Subject: [PATCH 171/204] removed g3d --- src/cs/g3d/Vim.G3d/AttributeDescriptor.cs | 158 -------- src/cs/g3d/Vim.G3d/AttributeExtensions.cs | 126 ------- src/cs/g3d/Vim.G3d/CommonAttributes.cs | 231 ------------ src/cs/g3d/Vim.G3d/CommonAttributes.tt | 95 ----- src/cs/g3d/Vim.G3d/Enums.cs | 98 ----- src/cs/g3d/Vim.G3d/G3D.cs | 345 ------------------ src/cs/g3d/Vim.G3d/G3dMaterial.cs | 20 - src/cs/g3d/Vim.G3d/G3dMesh.cs | 120 ------ src/cs/g3d/Vim.G3d/G3dShape.cs | 23 -- src/cs/g3d/Vim.G3d/GeometryAttribute.cs | 245 ------------- src/cs/g3d/Vim.G3d/GeometryAttributes.cs | 164 --------- .../Vim.G3d/GeometryAttributesExtensions.cs | 29 -- src/cs/g3d/Vim.G3d/Header.cs | 81 ---- src/cs/g3d/Vim.G3d/IGeometryAttributes.cs | 22 -- src/cs/g3d/Vim.G3dNext/Constants.cs | 34 +- src/cs/vim-format.sln | 14 - src/cs/vim/Vim.Format.Core/G3dBuilder.cs | 2 +- .../Geometry/MeshOptimization.cs | 1 - .../Vim.Format.Core/Geometry/VimMaterial.cs | 21 -- .../Geometry/VimMaterialNext.cs | 8 + .../Vim.Format.Core/SerializableDocument.cs | 1 - .../Vim.Format.Core/Vim.Format.Core.csproj | 1 - .../vim/Vim.Format/SceneBuilder/VimScene.cs | 9 +- src/cs/vim/Vim.Format/Vim.Format.csproj | 1 - 24 files changed, 46 insertions(+), 1803 deletions(-) delete mode 100644 src/cs/g3d/Vim.G3d/AttributeDescriptor.cs delete mode 100644 src/cs/g3d/Vim.G3d/AttributeExtensions.cs delete mode 100644 src/cs/g3d/Vim.G3d/CommonAttributes.cs delete mode 100644 src/cs/g3d/Vim.G3d/CommonAttributes.tt delete mode 100644 src/cs/g3d/Vim.G3d/Enums.cs delete mode 100644 src/cs/g3d/Vim.G3d/G3D.cs delete mode 100644 src/cs/g3d/Vim.G3d/G3dMaterial.cs delete mode 100644 src/cs/g3d/Vim.G3d/G3dMesh.cs delete mode 100644 src/cs/g3d/Vim.G3d/G3dShape.cs delete mode 100644 src/cs/g3d/Vim.G3d/GeometryAttribute.cs delete mode 100644 src/cs/g3d/Vim.G3d/GeometryAttributes.cs delete mode 100644 src/cs/g3d/Vim.G3d/GeometryAttributesExtensions.cs delete mode 100644 src/cs/g3d/Vim.G3d/Header.cs delete mode 100644 src/cs/g3d/Vim.G3d/IGeometryAttributes.cs delete mode 100644 src/cs/vim/Vim.Format.Core/Geometry/VimMaterial.cs diff --git a/src/cs/g3d/Vim.G3d/AttributeDescriptor.cs b/src/cs/g3d/Vim.G3d/AttributeDescriptor.cs deleted file mode 100644 index a2f48840..00000000 --- a/src/cs/g3d/Vim.G3d/AttributeDescriptor.cs +++ /dev/null @@ -1,158 +0,0 @@ -using System; - -namespace Vim.G3d -{ - /// - /// Provides information about identifying the role and parsing the data within an attribute data buffer. - /// This is encoded using a string in a particular URN form. - /// - public class AttributeDescriptor - { - public Association Association { get; } - public string Semantic { get; } - public DataType DataType { get; } - public int DataArity { get; } - public int Index { get; } - - public int DataElementSize { get; } - public int DataTypeSize { get; } - public string Name { get; } - - public AttributeDescriptor(Association association, string semantic, DataType dataType, int dataArity, int index = 0) - { - Association = association; - if (semantic.Contains(":")) - throw new Exception("The semantic must not contain a semicolon"); - Semantic = semantic; - DataType = dataType; - DataArity = dataArity; - Index = index; - DataTypeSize = GetDataTypeSize(DataType); - DataElementSize = DataTypeSize * DataArity; - Name = $"g3d:{AssociationString}:{Semantic}:{Index}:{DataTypeString}:{DataArity}"; - } - - /// - /// Generates a URN representation of the attribute descriptor - /// - public override string ToString() - => Name; - - /// - /// Returns true if the attribute descriptor has been successfully parsed. - /// - public static bool TryParse(string urn, out AttributeDescriptor attributeDescriptor) - { - attributeDescriptor = null; - try - { - attributeDescriptor = Parse(urn); - } - catch - { - // do nothing. - } - - return attributeDescriptor != null; - } - - /// - /// Parses a URN representation of the attribute descriptor to generate an actual attribute descriptor - /// - public static AttributeDescriptor Parse(string urn) - { - var vals = urn.Split(':'); - if (vals.Length != 6) throw new Exception("Expected 6 parts to the attribute descriptor URN"); - if (vals[0] != "g3d") throw new Exception("First part of URN must be g3d"); - return new AttributeDescriptor( - ParseAssociation(vals[1]), - vals[2], - ParseDataType(vals[4]), - int.Parse(vals[5]), - int.Parse(vals[3]) - ); - } - - public bool Validate() - { - var urn = ToString(); - var tmp = Parse(urn); - if (!Equals(tmp)) - throw new Exception("Invalid attribute descriptor (or internal error in the parsing/string conversion"); - return true; - } - - public bool Equals(AttributeDescriptor other) - => ToString() == other.ToString(); - - public static int GetDataTypeSize(DataType dt) - { - switch (dt) - { - case DataType.dt_uint8: - case DataType.dt_int8: - return 1; - case DataType.dt_uint16: - case DataType.dt_int16: - return 2; - case DataType.dt_uint32: - case DataType.dt_int32: - return 4; - case DataType.dt_uint64: - case DataType.dt_int64: - return 8; - case DataType.dt_float32: - return 4; - case DataType.dt_float64: - return 8; - default: - throw new ArgumentOutOfRangeException(nameof(dt), dt, null); - } - } - - public string AssociationString - => Association.ToString().Substring("assoc_".Length); - - public static Association ParseAssociation(string s) - { - switch (s) - { - case "all": - return Association.assoc_all; - case "corner": - return Association.assoc_corner; - case "edge": - return Association.assoc_edge; - case "face": - return Association.assoc_face; - case "instance": - return Association.assoc_instance; - case "vertex": - return Association.assoc_vertex; - case "shapevertex": - return Association.assoc_shapevertex; - case "shape": - return Association.assoc_shape; - case "material": - return Association.assoc_material; - case "mesh": - return Association.assoc_mesh; - case "submesh": - return Association.assoc_submesh; - - // Anything else we just treat as unknown - default: - return Association.assoc_none; - } - } - - public string DataTypeString - => DataType.ToString()?.Substring("dt_".Length) ?? null; - - public static DataType ParseDataType(string s) - => (DataType)Enum.Parse(typeof(DataType), "dt_" + s); - - public AttributeDescriptor SetIndex(int index) - => new AttributeDescriptor(Association, Semantic, DataType, DataArity, index); - } -} diff --git a/src/cs/g3d/Vim.G3d/AttributeExtensions.cs b/src/cs/g3d/Vim.G3d/AttributeExtensions.cs deleted file mode 100644 index aedfed52..00000000 --- a/src/cs/g3d/Vim.G3d/AttributeExtensions.cs +++ /dev/null @@ -1,126 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using Vim.LinqArray; -using Vim.Math3d; - -namespace Vim.G3d -{ - public static class AttributeExtensions - { - public static GeometryAttribute ToAttribute(this IArray self, AttributeDescriptor desc) where T : unmanaged - => new GeometryAttribute(self, desc); - - public static GeometryAttribute ToAttribute(this IArray self, string desc) where T : unmanaged - => self.ToAttribute(AttributeDescriptor.Parse(desc)); - - public static GeometryAttribute ToAttribute(this IArray self, string desc, int index) where T : unmanaged - => self.ToAttribute(AttributeDescriptor.Parse(desc).SetIndex(index)); - - public static IArray AttributeToColors(this GeometryAttribute attr) - { - var desc = attr.Descriptor; - if (desc.DataType == DataType.dt_float32) - { - if (desc.DataArity == 4) - return attr.AsType().Data; - if (desc.DataArity == 3) - return attr.AsType().Data.Select(vc => new Vector4(vc, 1f)); - if (desc.DataArity == 2) - return attr.AsType().Data.Select(vc => new Vector4(vc.X, vc.Y, 0, 1f)); - if (desc.DataArity == 1) - return attr.AsType().Data.Select(vc => new Vector4(vc, vc, vc, 1f)); - } - if (desc.DataType == DataType.dt_int8) - { - if (desc.DataArity == 4) - return attr.AsType().Data.Select(b => new Vector4(b.X / 255f, b.Y / 255f, b.Z / 255f, b.W / 255f)); - if (desc.DataArity == 3) - return attr.AsType().Data.Select(b => new Vector4(b.X / 255f, b.Y / 255f, b.Z / 255f, 1f)); - if (desc.DataArity == 2) - return attr.AsType().Data.Select(b => new Vector4(b.X / 255f, b.Y / 255f, 0f, 1f)); - if (desc.DataArity == 1) - return attr.AsType().Data.Select(b => new Vector4(b / 255f, b / 255f, b / 255f, 1f)); - } - Debug.WriteLine($"Failed to recongize color format {attr.Descriptor}"); - return null; - } - - public static GeometryAttribute ToDefaultAttribute(this AttributeDescriptor desc, int count) - { - switch (desc.DataType) - { - // TODO: TECH DEBT - Add unsigned tuple objects to Math3d - case DataType.dt_uint8: - if (desc.DataArity == 1) - return default(byte).Repeat(count).ToAttribute(desc); - break; - case DataType.dt_int8: - if (desc.DataArity == 1) - return default(byte).Repeat(count).ToAttribute(desc); - if (desc.DataArity == 2) - return default(Byte2).Repeat(count).ToAttribute(desc); - if (desc.DataArity == 3) - return default(Byte3).Repeat(count).ToAttribute(desc); - if (desc.DataArity == 4) - return default(Byte4).Repeat(count).ToAttribute(desc); - break; - case DataType.dt_uint16: - if (desc.DataArity == 1) - return default(ushort).Repeat(count).ToAttribute(desc); - break; - case DataType.dt_int16: - if (desc.DataArity == 1) - return default(short).Repeat(count).ToAttribute(desc); - break; - case DataType.dt_uint32: - if (desc.DataArity == 1) - return default(uint).Repeat(count).ToAttribute(desc); - break; - case DataType.dt_int32: - if (desc.DataArity == 1) - return default(int).Repeat(count).ToAttribute(desc); - if (desc.DataArity == 2) - return default(Int2).Repeat(count).ToAttribute(desc); - if (desc.DataArity == 3) - return default(Int3).Repeat(count).ToAttribute(desc); - if (desc.DataArity == 4) - return default(Int4).Repeat(count).ToAttribute(desc); - break; - case DataType.dt_uint64: - if (desc.DataArity == 1) - return default(ulong).Repeat(count).ToAttribute(desc); - break; - case DataType.dt_int64: - if (desc.DataArity == 1) - return default(long).Repeat(count).ToAttribute(desc); - break; - case DataType.dt_float32: - if (desc.DataArity == 1) - return default(float).Repeat(count).ToAttribute(desc); - if (desc.DataArity == 2) - return default(Vector2).Repeat(count).ToAttribute(desc); - if (desc.DataArity == 3) - return default(Vector3).Repeat(count).ToAttribute(desc); - if (desc.DataArity == 4) - return default(Vector4).Repeat(count).ToAttribute(desc); - if (desc.DataArity == 16) - return default(Matrix4x4).Repeat(count).ToAttribute(desc); - break; - case DataType.dt_float64: - if (desc.DataArity == 1) - return default(double).Repeat(count).ToAttribute(desc); - if (desc.DataArity == 2) - return default(DVector2).Repeat(count).ToAttribute(desc); - if (desc.DataArity == 3) - return default(DVector3).Repeat(count).ToAttribute(desc); - if (desc.DataArity == 4) - return default(DVector4).Repeat(count).ToAttribute(desc); - break; - } - - throw new Exception($"Could not create a default attribute for {desc}"); - } - } -} diff --git a/src/cs/g3d/Vim.G3d/CommonAttributes.cs b/src/cs/g3d/Vim.G3d/CommonAttributes.cs deleted file mode 100644 index da835913..00000000 --- a/src/cs/g3d/Vim.G3d/CommonAttributes.cs +++ /dev/null @@ -1,231 +0,0 @@ - -// AUTOGENERATED FILE: DO NOT EDIT -// This file is generated from CommonAttributeExtensions.tt - - -using Vim.LinqArray; -using Vim.Math3d; - -namespace Vim.G3d -{ - public static class CommonAttributes - { - - public const string ObjectFaceSize = "g3d:all:facesize:0:int32:1"; - public const string Index = "g3d:corner:index:0:int32:1"; - public const string Position = "g3d:vertex:position:0:float32:3"; - public const string VertexUv = "g3d:vertex:uv:0:float32:2"; - public const string VertexUvw = "g3d:vertex:uv:0:float32:3"; - public const string VertexNormal = "g3d:vertex:normal:0:float32:3"; - public const string VertexColor = "g3d:vertex:color:0:float32:4"; - public const string VertexColor8Bit = "g3d:vertex:color:0:int8:4"; - public const string VertexBitangent = "g3d:vertex:bitangent:0:float32:3"; - public const string VertexTangent = "g3d:vertex:tangent:0:float32:4"; - public const string VertexSelectionWeight = "g3d:vertex:weight:0:float32:1"; - public const string FaceColor = "g3d:face:color:0:float32:4"; - public const string FaceMaterial = "g3d:face:material:0:int32:1"; - public const string FaceNormal = "g3d:face:normal:0:float32:3"; - public const string MeshSubmeshOffset = "g3d:mesh:submeshoffset:0:int32:1"; - public const string InstanceTransform = "g3d:instance:transform:0:float32:16"; - public const string InstanceParent = "g3d:instance:parent:0:int32:1"; - public const string InstanceMesh = "g3d:instance:mesh:0:int32:1"; - public const string InstanceFlags = "g3d:instance:flags:0:uint16:1"; - public const string LineTangentIn = "g3d:vertex:tangent:0:float32:3"; - public const string LineTangentOut = "g3d:vertex:tangent:1:float32:3"; - public const string ShapeVertex = "g3d:shapevertex:position:0:float32:3"; - public const string ShapeVertexOffset = "g3d:shape:vertexoffset:0:int32:1"; - public const string ShapeColor = "g3d:shape:color:0:float32:4"; - public const string ShapeWidth = "g3d:shape:width:0:float32:1"; - public const string MaterialColor = "g3d:material:color:0:float32:4"; - public const string MaterialGlossiness = "g3d:material:glossiness:0:float32:1"; - public const string MaterialSmoothness = "g3d:material:smoothness:0:float32:1"; - public const string SubmeshIndexOffset = "g3d:submesh:indexoffset:0:int32:1"; - public const string SubmeshMaterial = "g3d:submesh:material:0:int32:1"; - } - - public static class CommonAttributeExtensions - { - - public static GeometryAttribute ToObjectFaceSizeAttribute(this IArray xs, int index) => xs.ToAttribute(CommonAttributes.ObjectFaceSize, index); - public static GeometryAttribute ToObjectFaceSizeAttribute(this IArray xs) => xs.ToAttribute(CommonAttributes.ObjectFaceSize); - public static GeometryAttribute ToObjectFaceSizeAttribute(this int[] xs, int index) => xs.ToIArray().ToObjectFaceSizeAttribute(index); - public static GeometryAttribute ToObjectFaceSizeAttribute(this int[] xs) => xs.ToIArray().ToObjectFaceSizeAttribute(); - public static GeometryAttribute GetAttributeObjectFaceSize(this IGeometryAttributes self) => self.GetAttribute(CommonAttributes.ObjectFaceSize); - public static IArray GetAttributeDataObjectFaceSize(this IGeometryAttributes self) => self.GetAttributeObjectFaceSize()?.Data; - public static GeometryAttribute ToIndexAttribute(this IArray xs, int index) => xs.ToAttribute(CommonAttributes.Index, index); - public static GeometryAttribute ToIndexAttribute(this IArray xs) => xs.ToAttribute(CommonAttributes.Index); - public static GeometryAttribute ToIndexAttribute(this int[] xs, int index) => xs.ToIArray().ToIndexAttribute(index); - public static GeometryAttribute ToIndexAttribute(this int[] xs) => xs.ToIArray().ToIndexAttribute(); - public static GeometryAttribute GetAttributeIndex(this IGeometryAttributes self) => self.GetAttribute(CommonAttributes.Index); - public static IArray GetAttributeDataIndex(this IGeometryAttributes self) => self.GetAttributeIndex()?.Data; - public static GeometryAttribute ToPositionAttribute(this IArray xs, int index) => xs.ToAttribute(CommonAttributes.Position, index); - public static GeometryAttribute ToPositionAttribute(this IArray xs) => xs.ToAttribute(CommonAttributes.Position); - public static GeometryAttribute ToPositionAttribute(this Vector3[] xs, int index) => xs.ToIArray().ToPositionAttribute(index); - public static GeometryAttribute ToPositionAttribute(this Vector3[] xs) => xs.ToIArray().ToPositionAttribute(); - public static GeometryAttribute GetAttributePosition(this IGeometryAttributes self) => self.GetAttribute(CommonAttributes.Position); - public static IArray GetAttributeDataPosition(this IGeometryAttributes self) => self.GetAttributePosition()?.Data; - public static GeometryAttribute ToVertexUvAttribute(this IArray xs, int index) => xs.ToAttribute(CommonAttributes.VertexUv, index); - public static GeometryAttribute ToVertexUvAttribute(this IArray xs) => xs.ToAttribute(CommonAttributes.VertexUv); - public static GeometryAttribute ToVertexUvAttribute(this Vector2[] xs, int index) => xs.ToIArray().ToVertexUvAttribute(index); - public static GeometryAttribute ToVertexUvAttribute(this Vector2[] xs) => xs.ToIArray().ToVertexUvAttribute(); - public static GeometryAttribute GetAttributeVertexUv(this IGeometryAttributes self) => self.GetAttribute(CommonAttributes.VertexUv); - public static IArray GetAttributeDataVertexUv(this IGeometryAttributes self) => self.GetAttributeVertexUv()?.Data; - public static GeometryAttribute ToVertexUvwAttribute(this IArray xs, int index) => xs.ToAttribute(CommonAttributes.VertexUvw, index); - public static GeometryAttribute ToVertexUvwAttribute(this IArray xs) => xs.ToAttribute(CommonAttributes.VertexUvw); - public static GeometryAttribute ToVertexUvwAttribute(this Vector3[] xs, int index) => xs.ToIArray().ToVertexUvwAttribute(index); - public static GeometryAttribute ToVertexUvwAttribute(this Vector3[] xs) => xs.ToIArray().ToVertexUvwAttribute(); - public static GeometryAttribute GetAttributeVertexUvw(this IGeometryAttributes self) => self.GetAttribute(CommonAttributes.VertexUvw); - public static IArray GetAttributeDataVertexUvw(this IGeometryAttributes self) => self.GetAttributeVertexUvw()?.Data; - public static GeometryAttribute ToVertexNormalAttribute(this IArray xs, int index) => xs.ToAttribute(CommonAttributes.VertexNormal, index); - public static GeometryAttribute ToVertexNormalAttribute(this IArray xs) => xs.ToAttribute(CommonAttributes.VertexNormal); - public static GeometryAttribute ToVertexNormalAttribute(this Vector3[] xs, int index) => xs.ToIArray().ToVertexNormalAttribute(index); - public static GeometryAttribute ToVertexNormalAttribute(this Vector3[] xs) => xs.ToIArray().ToVertexNormalAttribute(); - public static GeometryAttribute GetAttributeVertexNormal(this IGeometryAttributes self) => self.GetAttribute(CommonAttributes.VertexNormal); - public static IArray GetAttributeDataVertexNormal(this IGeometryAttributes self) => self.GetAttributeVertexNormal()?.Data; - public static GeometryAttribute ToVertexColorAttribute(this IArray xs, int index) => xs.ToAttribute(CommonAttributes.VertexColor, index); - public static GeometryAttribute ToVertexColorAttribute(this IArray xs) => xs.ToAttribute(CommonAttributes.VertexColor); - public static GeometryAttribute ToVertexColorAttribute(this Vector4[] xs, int index) => xs.ToIArray().ToVertexColorAttribute(index); - public static GeometryAttribute ToVertexColorAttribute(this Vector4[] xs) => xs.ToIArray().ToVertexColorAttribute(); - public static GeometryAttribute GetAttributeVertexColor(this IGeometryAttributes self) => self.GetAttribute(CommonAttributes.VertexColor); - public static IArray GetAttributeDataVertexColor(this IGeometryAttributes self) => self.GetAttributeVertexColor()?.Data; - public static GeometryAttribute ToVertexColor8BitAttribute(this IArray xs, int index) => xs.ToAttribute(CommonAttributes.VertexColor8Bit, index); - public static GeometryAttribute ToVertexColor8BitAttribute(this IArray xs) => xs.ToAttribute(CommonAttributes.VertexColor8Bit); - public static GeometryAttribute ToVertexColor8BitAttribute(this Byte4[] xs, int index) => xs.ToIArray().ToVertexColor8BitAttribute(index); - public static GeometryAttribute ToVertexColor8BitAttribute(this Byte4[] xs) => xs.ToIArray().ToVertexColor8BitAttribute(); - public static GeometryAttribute GetAttributeVertexColor8Bit(this IGeometryAttributes self) => self.GetAttribute(CommonAttributes.VertexColor8Bit); - public static IArray GetAttributeDataVertexColor8Bit(this IGeometryAttributes self) => self.GetAttributeVertexColor8Bit()?.Data; - public static GeometryAttribute ToVertexBitangentAttribute(this IArray xs, int index) => xs.ToAttribute(CommonAttributes.VertexBitangent, index); - public static GeometryAttribute ToVertexBitangentAttribute(this IArray xs) => xs.ToAttribute(CommonAttributes.VertexBitangent); - public static GeometryAttribute ToVertexBitangentAttribute(this Vector3[] xs, int index) => xs.ToIArray().ToVertexBitangentAttribute(index); - public static GeometryAttribute ToVertexBitangentAttribute(this Vector3[] xs) => xs.ToIArray().ToVertexBitangentAttribute(); - public static GeometryAttribute GetAttributeVertexBitangent(this IGeometryAttributes self) => self.GetAttribute(CommonAttributes.VertexBitangent); - public static IArray GetAttributeDataVertexBitangent(this IGeometryAttributes self) => self.GetAttributeVertexBitangent()?.Data; - public static GeometryAttribute ToVertexTangentAttribute(this IArray xs, int index) => xs.ToAttribute(CommonAttributes.VertexTangent, index); - public static GeometryAttribute ToVertexTangentAttribute(this IArray xs) => xs.ToAttribute(CommonAttributes.VertexTangent); - public static GeometryAttribute ToVertexTangentAttribute(this Vector4[] xs, int index) => xs.ToIArray().ToVertexTangentAttribute(index); - public static GeometryAttribute ToVertexTangentAttribute(this Vector4[] xs) => xs.ToIArray().ToVertexTangentAttribute(); - public static GeometryAttribute GetAttributeVertexTangent(this IGeometryAttributes self) => self.GetAttribute(CommonAttributes.VertexTangent); - public static IArray GetAttributeDataVertexTangent(this IGeometryAttributes self) => self.GetAttributeVertexTangent()?.Data; - public static GeometryAttribute ToVertexSelectionWeightAttribute(this IArray xs, int index) => xs.ToAttribute(CommonAttributes.VertexSelectionWeight, index); - public static GeometryAttribute ToVertexSelectionWeightAttribute(this IArray xs) => xs.ToAttribute(CommonAttributes.VertexSelectionWeight); - public static GeometryAttribute ToVertexSelectionWeightAttribute(this float[] xs, int index) => xs.ToIArray().ToVertexSelectionWeightAttribute(index); - public static GeometryAttribute ToVertexSelectionWeightAttribute(this float[] xs) => xs.ToIArray().ToVertexSelectionWeightAttribute(); - public static GeometryAttribute GetAttributeVertexSelectionWeight(this IGeometryAttributes self) => self.GetAttribute(CommonAttributes.VertexSelectionWeight); - public static IArray GetAttributeDataVertexSelectionWeight(this IGeometryAttributes self) => self.GetAttributeVertexSelectionWeight()?.Data; - public static GeometryAttribute ToFaceColorAttribute(this IArray xs, int index) => xs.ToAttribute(CommonAttributes.FaceColor, index); - public static GeometryAttribute ToFaceColorAttribute(this IArray xs) => xs.ToAttribute(CommonAttributes.FaceColor); - public static GeometryAttribute ToFaceColorAttribute(this Vector4[] xs, int index) => xs.ToIArray().ToFaceColorAttribute(index); - public static GeometryAttribute ToFaceColorAttribute(this Vector4[] xs) => xs.ToIArray().ToFaceColorAttribute(); - public static GeometryAttribute GetAttributeFaceColor(this IGeometryAttributes self) => self.GetAttribute(CommonAttributes.FaceColor); - public static IArray GetAttributeDataFaceColor(this IGeometryAttributes self) => self.GetAttributeFaceColor()?.Data; - public static GeometryAttribute ToFaceMaterialAttribute(this IArray xs, int index) => xs.ToAttribute(CommonAttributes.FaceMaterial, index); - public static GeometryAttribute ToFaceMaterialAttribute(this IArray xs) => xs.ToAttribute(CommonAttributes.FaceMaterial); - public static GeometryAttribute ToFaceMaterialAttribute(this int[] xs, int index) => xs.ToIArray().ToFaceMaterialAttribute(index); - public static GeometryAttribute ToFaceMaterialAttribute(this int[] xs) => xs.ToIArray().ToFaceMaterialAttribute(); - public static GeometryAttribute GetAttributeFaceMaterial(this IGeometryAttributes self) => self.GetAttribute(CommonAttributes.FaceMaterial); - public static IArray GetAttributeDataFaceMaterial(this IGeometryAttributes self) => self.GetAttributeFaceMaterial()?.Data; - public static GeometryAttribute ToFaceNormalAttribute(this IArray xs, int index) => xs.ToAttribute(CommonAttributes.FaceNormal, index); - public static GeometryAttribute ToFaceNormalAttribute(this IArray xs) => xs.ToAttribute(CommonAttributes.FaceNormal); - public static GeometryAttribute ToFaceNormalAttribute(this Vector3[] xs, int index) => xs.ToIArray().ToFaceNormalAttribute(index); - public static GeometryAttribute ToFaceNormalAttribute(this Vector3[] xs) => xs.ToIArray().ToFaceNormalAttribute(); - public static GeometryAttribute GetAttributeFaceNormal(this IGeometryAttributes self) => self.GetAttribute(CommonAttributes.FaceNormal); - public static IArray GetAttributeDataFaceNormal(this IGeometryAttributes self) => self.GetAttributeFaceNormal()?.Data; - public static GeometryAttribute ToMeshSubmeshOffsetAttribute(this IArray xs, int index) => xs.ToAttribute(CommonAttributes.MeshSubmeshOffset, index); - public static GeometryAttribute ToMeshSubmeshOffsetAttribute(this IArray xs) => xs.ToAttribute(CommonAttributes.MeshSubmeshOffset); - public static GeometryAttribute ToMeshSubmeshOffsetAttribute(this int[] xs, int index) => xs.ToIArray().ToMeshSubmeshOffsetAttribute(index); - public static GeometryAttribute ToMeshSubmeshOffsetAttribute(this int[] xs) => xs.ToIArray().ToMeshSubmeshOffsetAttribute(); - public static GeometryAttribute GetAttributeMeshSubmeshOffset(this IGeometryAttributes self) => self.GetAttribute(CommonAttributes.MeshSubmeshOffset); - public static IArray GetAttributeDataMeshSubmeshOffset(this IGeometryAttributes self) => self.GetAttributeMeshSubmeshOffset()?.Data; - public static GeometryAttribute ToInstanceTransformAttribute(this IArray xs, int index) => xs.ToAttribute(CommonAttributes.InstanceTransform, index); - public static GeometryAttribute ToInstanceTransformAttribute(this IArray xs) => xs.ToAttribute(CommonAttributes.InstanceTransform); - public static GeometryAttribute ToInstanceTransformAttribute(this Matrix4x4[] xs, int index) => xs.ToIArray().ToInstanceTransformAttribute(index); - public static GeometryAttribute ToInstanceTransformAttribute(this Matrix4x4[] xs) => xs.ToIArray().ToInstanceTransformAttribute(); - public static GeometryAttribute GetAttributeInstanceTransform(this IGeometryAttributes self) => self.GetAttribute(CommonAttributes.InstanceTransform); - public static IArray GetAttributeDataInstanceTransform(this IGeometryAttributes self) => self.GetAttributeInstanceTransform()?.Data; - public static GeometryAttribute ToInstanceParentAttribute(this IArray xs, int index) => xs.ToAttribute(CommonAttributes.InstanceParent, index); - public static GeometryAttribute ToInstanceParentAttribute(this IArray xs) => xs.ToAttribute(CommonAttributes.InstanceParent); - public static GeometryAttribute ToInstanceParentAttribute(this int[] xs, int index) => xs.ToIArray().ToInstanceParentAttribute(index); - public static GeometryAttribute ToInstanceParentAttribute(this int[] xs) => xs.ToIArray().ToInstanceParentAttribute(); - public static GeometryAttribute GetAttributeInstanceParent(this IGeometryAttributes self) => self.GetAttribute(CommonAttributes.InstanceParent); - public static IArray GetAttributeDataInstanceParent(this IGeometryAttributes self) => self.GetAttributeInstanceParent()?.Data; - public static GeometryAttribute ToInstanceMeshAttribute(this IArray xs, int index) => xs.ToAttribute(CommonAttributes.InstanceMesh, index); - public static GeometryAttribute ToInstanceMeshAttribute(this IArray xs) => xs.ToAttribute(CommonAttributes.InstanceMesh); - public static GeometryAttribute ToInstanceMeshAttribute(this int[] xs, int index) => xs.ToIArray().ToInstanceMeshAttribute(index); - public static GeometryAttribute ToInstanceMeshAttribute(this int[] xs) => xs.ToIArray().ToInstanceMeshAttribute(); - public static GeometryAttribute GetAttributeInstanceMesh(this IGeometryAttributes self) => self.GetAttribute(CommonAttributes.InstanceMesh); - public static IArray GetAttributeDataInstanceMesh(this IGeometryAttributes self) => self.GetAttributeInstanceMesh()?.Data; - public static GeometryAttribute ToInstanceFlagsAttribute(this IArray xs, int index) => xs.ToAttribute(CommonAttributes.InstanceFlags, index); - public static GeometryAttribute ToInstanceFlagsAttribute(this IArray xs) => xs.ToAttribute(CommonAttributes.InstanceFlags); - public static GeometryAttribute ToInstanceFlagsAttribute(this ushort[] xs, int index) => xs.ToIArray().ToInstanceFlagsAttribute(index); - public static GeometryAttribute ToInstanceFlagsAttribute(this ushort[] xs) => xs.ToIArray().ToInstanceFlagsAttribute(); - public static GeometryAttribute GetAttributeInstanceFlags(this IGeometryAttributes self) => self.GetAttribute(CommonAttributes.InstanceFlags); - public static IArray GetAttributeDataInstanceFlags(this IGeometryAttributes self) => self.GetAttributeInstanceFlags()?.Data; - public static GeometryAttribute ToLineTangentInAttribute(this IArray xs, int index) => xs.ToAttribute(CommonAttributes.LineTangentIn, index); - public static GeometryAttribute ToLineTangentInAttribute(this IArray xs) => xs.ToAttribute(CommonAttributes.LineTangentIn); - public static GeometryAttribute ToLineTangentInAttribute(this Vector3[] xs, int index) => xs.ToIArray().ToLineTangentInAttribute(index); - public static GeometryAttribute ToLineTangentInAttribute(this Vector3[] xs) => xs.ToIArray().ToLineTangentInAttribute(); - public static GeometryAttribute GetAttributeLineTangentIn(this IGeometryAttributes self) => self.GetAttribute(CommonAttributes.LineTangentIn); - public static IArray GetAttributeDataLineTangentIn(this IGeometryAttributes self) => self.GetAttributeLineTangentIn()?.Data; - public static GeometryAttribute ToLineTangentOutAttribute(this IArray xs, int index) => xs.ToAttribute(CommonAttributes.LineTangentOut, index); - public static GeometryAttribute ToLineTangentOutAttribute(this IArray xs) => xs.ToAttribute(CommonAttributes.LineTangentOut); - public static GeometryAttribute ToLineTangentOutAttribute(this Vector3[] xs, int index) => xs.ToIArray().ToLineTangentOutAttribute(index); - public static GeometryAttribute ToLineTangentOutAttribute(this Vector3[] xs) => xs.ToIArray().ToLineTangentOutAttribute(); - public static GeometryAttribute GetAttributeLineTangentOut(this IGeometryAttributes self) => self.GetAttribute(CommonAttributes.LineTangentOut); - public static IArray GetAttributeDataLineTangentOut(this IGeometryAttributes self) => self.GetAttributeLineTangentOut()?.Data; - public static GeometryAttribute ToShapeVertexAttribute(this IArray xs, int index) => xs.ToAttribute(CommonAttributes.ShapeVertex, index); - public static GeometryAttribute ToShapeVertexAttribute(this IArray xs) => xs.ToAttribute(CommonAttributes.ShapeVertex); - public static GeometryAttribute ToShapeVertexAttribute(this Vector3[] xs, int index) => xs.ToIArray().ToShapeVertexAttribute(index); - public static GeometryAttribute ToShapeVertexAttribute(this Vector3[] xs) => xs.ToIArray().ToShapeVertexAttribute(); - public static GeometryAttribute GetAttributeShapeVertex(this IGeometryAttributes self) => self.GetAttribute(CommonAttributes.ShapeVertex); - public static IArray GetAttributeDataShapeVertex(this IGeometryAttributes self) => self.GetAttributeShapeVertex()?.Data; - public static GeometryAttribute ToShapeVertexOffsetAttribute(this IArray xs, int index) => xs.ToAttribute(CommonAttributes.ShapeVertexOffset, index); - public static GeometryAttribute ToShapeVertexOffsetAttribute(this IArray xs) => xs.ToAttribute(CommonAttributes.ShapeVertexOffset); - public static GeometryAttribute ToShapeVertexOffsetAttribute(this int[] xs, int index) => xs.ToIArray().ToShapeVertexOffsetAttribute(index); - public static GeometryAttribute ToShapeVertexOffsetAttribute(this int[] xs) => xs.ToIArray().ToShapeVertexOffsetAttribute(); - public static GeometryAttribute GetAttributeShapeVertexOffset(this IGeometryAttributes self) => self.GetAttribute(CommonAttributes.ShapeVertexOffset); - public static IArray GetAttributeDataShapeVertexOffset(this IGeometryAttributes self) => self.GetAttributeShapeVertexOffset()?.Data; - public static GeometryAttribute ToShapeColorAttribute(this IArray xs, int index) => xs.ToAttribute(CommonAttributes.ShapeColor, index); - public static GeometryAttribute ToShapeColorAttribute(this IArray xs) => xs.ToAttribute(CommonAttributes.ShapeColor); - public static GeometryAttribute ToShapeColorAttribute(this Vector4[] xs, int index) => xs.ToIArray().ToShapeColorAttribute(index); - public static GeometryAttribute ToShapeColorAttribute(this Vector4[] xs) => xs.ToIArray().ToShapeColorAttribute(); - public static GeometryAttribute GetAttributeShapeColor(this IGeometryAttributes self) => self.GetAttribute(CommonAttributes.ShapeColor); - public static IArray GetAttributeDataShapeColor(this IGeometryAttributes self) => self.GetAttributeShapeColor()?.Data; - public static GeometryAttribute ToShapeWidthAttribute(this IArray xs, int index) => xs.ToAttribute(CommonAttributes.ShapeWidth, index); - public static GeometryAttribute ToShapeWidthAttribute(this IArray xs) => xs.ToAttribute(CommonAttributes.ShapeWidth); - public static GeometryAttribute ToShapeWidthAttribute(this float[] xs, int index) => xs.ToIArray().ToShapeWidthAttribute(index); - public static GeometryAttribute ToShapeWidthAttribute(this float[] xs) => xs.ToIArray().ToShapeWidthAttribute(); - public static GeometryAttribute GetAttributeShapeWidth(this IGeometryAttributes self) => self.GetAttribute(CommonAttributes.ShapeWidth); - public static IArray GetAttributeDataShapeWidth(this IGeometryAttributes self) => self.GetAttributeShapeWidth()?.Data; - public static GeometryAttribute ToMaterialColorAttribute(this IArray xs, int index) => xs.ToAttribute(CommonAttributes.MaterialColor, index); - public static GeometryAttribute ToMaterialColorAttribute(this IArray xs) => xs.ToAttribute(CommonAttributes.MaterialColor); - public static GeometryAttribute ToMaterialColorAttribute(this Vector4[] xs, int index) => xs.ToIArray().ToMaterialColorAttribute(index); - public static GeometryAttribute ToMaterialColorAttribute(this Vector4[] xs) => xs.ToIArray().ToMaterialColorAttribute(); - public static GeometryAttribute GetAttributeMaterialColor(this IGeometryAttributes self) => self.GetAttribute(CommonAttributes.MaterialColor); - public static IArray GetAttributeDataMaterialColor(this IGeometryAttributes self) => self.GetAttributeMaterialColor()?.Data; - public static GeometryAttribute ToMaterialGlossinessAttribute(this IArray xs, int index) => xs.ToAttribute(CommonAttributes.MaterialGlossiness, index); - public static GeometryAttribute ToMaterialGlossinessAttribute(this IArray xs) => xs.ToAttribute(CommonAttributes.MaterialGlossiness); - public static GeometryAttribute ToMaterialGlossinessAttribute(this float[] xs, int index) => xs.ToIArray().ToMaterialGlossinessAttribute(index); - public static GeometryAttribute ToMaterialGlossinessAttribute(this float[] xs) => xs.ToIArray().ToMaterialGlossinessAttribute(); - public static GeometryAttribute GetAttributeMaterialGlossiness(this IGeometryAttributes self) => self.GetAttribute(CommonAttributes.MaterialGlossiness); - public static IArray GetAttributeDataMaterialGlossiness(this IGeometryAttributes self) => self.GetAttributeMaterialGlossiness()?.Data; - public static GeometryAttribute ToMaterialSmoothnessAttribute(this IArray xs, int index) => xs.ToAttribute(CommonAttributes.MaterialSmoothness, index); - public static GeometryAttribute ToMaterialSmoothnessAttribute(this IArray xs) => xs.ToAttribute(CommonAttributes.MaterialSmoothness); - public static GeometryAttribute ToMaterialSmoothnessAttribute(this float[] xs, int index) => xs.ToIArray().ToMaterialSmoothnessAttribute(index); - public static GeometryAttribute ToMaterialSmoothnessAttribute(this float[] xs) => xs.ToIArray().ToMaterialSmoothnessAttribute(); - public static GeometryAttribute GetAttributeMaterialSmoothness(this IGeometryAttributes self) => self.GetAttribute(CommonAttributes.MaterialSmoothness); - public static IArray GetAttributeDataMaterialSmoothness(this IGeometryAttributes self) => self.GetAttributeMaterialSmoothness()?.Data; - public static GeometryAttribute ToSubmeshIndexOffsetAttribute(this IArray xs, int index) => xs.ToAttribute(CommonAttributes.SubmeshIndexOffset, index); - public static GeometryAttribute ToSubmeshIndexOffsetAttribute(this IArray xs) => xs.ToAttribute(CommonAttributes.SubmeshIndexOffset); - public static GeometryAttribute ToSubmeshIndexOffsetAttribute(this int[] xs, int index) => xs.ToIArray().ToSubmeshIndexOffsetAttribute(index); - public static GeometryAttribute ToSubmeshIndexOffsetAttribute(this int[] xs) => xs.ToIArray().ToSubmeshIndexOffsetAttribute(); - public static GeometryAttribute GetAttributeSubmeshIndexOffset(this IGeometryAttributes self) => self.GetAttribute(CommonAttributes.SubmeshIndexOffset); - public static IArray GetAttributeDataSubmeshIndexOffset(this IGeometryAttributes self) => self.GetAttributeSubmeshIndexOffset()?.Data; - public static GeometryAttribute ToSubmeshMaterialAttribute(this IArray xs, int index) => xs.ToAttribute(CommonAttributes.SubmeshMaterial, index); - public static GeometryAttribute ToSubmeshMaterialAttribute(this IArray xs) => xs.ToAttribute(CommonAttributes.SubmeshMaterial); - public static GeometryAttribute ToSubmeshMaterialAttribute(this int[] xs, int index) => xs.ToIArray().ToSubmeshMaterialAttribute(index); - public static GeometryAttribute ToSubmeshMaterialAttribute(this int[] xs) => xs.ToIArray().ToSubmeshMaterialAttribute(); - public static GeometryAttribute GetAttributeSubmeshMaterial(this IGeometryAttributes self) => self.GetAttribute(CommonAttributes.SubmeshMaterial); - public static IArray GetAttributeDataSubmeshMaterial(this IGeometryAttributes self) => self.GetAttributeSubmeshMaterial()?.Data; - - } -} diff --git a/src/cs/g3d/Vim.G3d/CommonAttributes.tt b/src/cs/g3d/Vim.G3d/CommonAttributes.tt deleted file mode 100644 index fad9970c..00000000 --- a/src/cs/g3d/Vim.G3d/CommonAttributes.tt +++ /dev/null @@ -1,95 +0,0 @@ -<#@ template language="C#" #> -<#@ output extension=".cs" #> -<#@ assembly name="System.Core" #> -<#@ import namespace="System.Linq" #> -<#@ import namespace="System.Text" #> -<#@ import namespace="System.Collections.Generic" #> - -// AUTOGENERATED FILE: DO NOT EDIT -// This file is generated from CommonAttributeExtensions.tt - -<# -string[] namesDescriptorAndTypes = { - "ObjectFaceSize", "g3d:all:facesize:0:int32:1","int", - "Index", "g3d:corner:index:0:int32:1","int", - "Position", "g3d:vertex:position:0:float32:3","Vector3", - "VertexUv", "g3d:vertex:uv:0:float32:2","Vector2", - "VertexUvw", "g3d:vertex:uv:0:float32:3","Vector3", - "VertexNormal", "g3d:vertex:normal:0:float32:3","Vector3", - "VertexColor", "g3d:vertex:color:0:float32:4","Vector4", - "VertexColor8Bit", "g3d:vertex:color:0:int8:4","Byte4", - "VertexBitangent", "g3d:vertex:bitangent:0:float32:3","Vector3", - "VertexTangent", "g3d:vertex:tangent:0:float32:4","Vector4", - "VertexSelectionWeight", "g3d:vertex:weight:0:float32:1","float", - "FaceColor", "g3d:face:color:0:float32:4","Vector4", - "FaceMaterial", "g3d:face:material:0:int32:1","int", - "FaceNormal", "g3d:face:normal:0:float32:3","Vector3", - - "MeshSubmeshOffset", "g3d:mesh:submeshoffset:0:int32:1", "int", - - "InstanceTransform", "g3d:instance:transform:0:float32:16", "Matrix4x4", - "InstanceParent", "g3d:instance:parent:0:int32:1", "int", - "InstanceMesh", "g3d:instance:mesh:0:int32:1", "int", - "InstanceFlags", "g3d:instance:flags:0:uint16:1", "ushort", - - "LineTangentIn", "g3d:vertex:tangent:0:float32:3","Vector3", - "LineTangentOut", "g3d:vertex:tangent:1:float32:3","Vector3", - "ShapeVertex", "g3d:shapevertex:position:0:float32:3", "Vector3", // We're using a distinct "shapevertex" association here because the "vertex" association is coupled to mesh geometry (there is a lot of logic related to face remapping and merging). - "ShapeVertexOffset", "g3d:shape:vertexoffset:0:int32:1", "int", - "ShapeColor", "g3d:shape:color:0:float32:4", "Vector4", - "ShapeWidth", "g3d:shape:width:0:float32:1", "float", - - "MaterialColor", "g3d:material:color:0:float32:4","Vector4", - "MaterialGlossiness", "g3d:material:glossiness:0:float32:1","float", - "MaterialSmoothness", "g3d:material:smoothness:0:float32:1","float", - - "SubmeshIndexOffset", "g3d:submesh:indexoffset:0:int32:1","int", - "SubmeshMaterial", "g3d:submesh:material:0:int32:1","int", - -}; -#> - -using Vim.LinqArray; -using Vim.Math3d; - -namespace Vim.G3d -{ - public static class CommonAttributes - { - -<# - for (var i=0; i < namesDescriptorAndTypes.Length; i += 3) - { - var name = namesDescriptorAndTypes[i]; - var desc = namesDescriptorAndTypes[i + 1]; - var type = namesDescriptorAndTypes[i + 2]; -#> - public const string <#= name #> = "<#= desc #>"; -<# - } -#> - } - - public static class CommonAttributeExtensions - { - -<# - for (var i=0; i < namesDescriptorAndTypes.Length; i += 3) - { - var name = namesDescriptorAndTypes[i]; - var desc = namesDescriptorAndTypes[i + 1]; - var type = namesDescriptorAndTypes[i + 2]; - var codeName = "CommonAttributes." + name; -#> - public static GeometryAttribute<<#= type #>> To<#= name #>Attribute(this IArray<<#= type #>> xs, int index) => xs.ToAttribute(<#= codeName #>, index); - public static GeometryAttribute<<#= type #>> To<#= name #>Attribute(this IArray<<#= type #>> xs) => xs.ToAttribute(<#= codeName #>); - public static GeometryAttribute<<#= type #>> To<#= name #>Attribute(this <#= type #>[] xs, int index) => xs.ToIArray().To<#= name #>Attribute(index); - public static GeometryAttribute<<#= type #>> To<#= name #>Attribute(this <#= type #>[] xs) => xs.ToIArray().To<#= name #>Attribute(); - public static GeometryAttribute<<#= type #>> GetAttribute<#= name #>(this IGeometryAttributes self) => self.GetAttribute<<#= type #>>(<#= codeName #>); - public static IArray<<#= type #>> GetAttributeData<#= name #>(this IGeometryAttributes self) => self.GetAttribute<#= name #>()?.Data; -<# - } -#> - - } -} diff --git a/src/cs/g3d/Vim.G3d/Enums.cs b/src/cs/g3d/Vim.G3d/Enums.cs deleted file mode 100644 index a3e1db1f..00000000 --- a/src/cs/g3d/Vim.G3d/Enums.cs +++ /dev/null @@ -1,98 +0,0 @@ -using System; - -namespace Vim.G3d -{ - /// - /// The different types of data types that can be used as elements. - /// - public enum DataType - { - dt_uint8, - dt_int8, - dt_uint16, - dt_int16, - dt_uint32, - dt_int32, - dt_uint64, - dt_int64, - dt_float32, - dt_float64, - dt_string, - }; - - /// - /// What element or component of a mesh each attribute is associated with. - /// - public enum Association - { - assoc_all, // associated with all data in G3d - assoc_none, // no association - assoc_vertex, // vertex or point data - assoc_face, // face associated data - assoc_corner, // corner (aka face-vertex) data. A corner is associated with one vertex, but a vertex may be shared between multiple corners - assoc_edge, // half-edge data. Each face consists of n half-edges, one per corner. A half-edge, is a directed edge - assoc_instance, // instance information - assoc_shapevertex, // flattened shape vertex collection. - assoc_shape, // shape instance - assoc_material, // material properties - assoc_mesh, - assoc_submesh - } - - [Flags] - public enum InstanceFlags - { - /// - /// Default - no instance options defined. - /// - None = 0, - - /// - /// When enabled, indicates that the renderer (or the consuming application) should hide - /// the instance by default. - /// - Hidden = 1, - } - - /// - /// Common semantic names. - /// - public static class Semantic - { - public const string Position = "position"; - public const string Index = "index"; - public const string FaceSize = "facesize"; - public const string Uv = "uv"; - public const string Normal = "normal"; - public const string Color = "color"; - public const string Bitangent = "bitangent"; - public const string Tangent = "tangent"; - public const string Weight = "weight"; - public const string Width = "width"; - - // Usually associated with face. - public const string Material = "material"; - - // Usually associated with material. - public const string Glossiness = "glossiness"; - - public const string Smoothness = "smoothness"; - - // Usually associated with meshes and submeshes - public const string IndexOffset = "indexoffset"; - public const string VertexOffset = "vertexoffset"; - - // Usually associated with instances - public const string Subgeometry = "subgeometry"; - public const string Mesh = "mesh"; - public const string Parent = "parent"; - public const string Transform = "transform"; - public const string Flags = "flags"; - - public const string TangentInt = "tangentin"; - public const string TangentOut = "tangentout"; - - public const string SubMeshOffset = "submeshoffset"; - - } -} diff --git a/src/cs/g3d/Vim.G3d/G3D.cs b/src/cs/g3d/Vim.G3d/G3D.cs deleted file mode 100644 index 36e90ca7..00000000 --- a/src/cs/g3d/Vim.G3d/G3D.cs +++ /dev/null @@ -1,345 +0,0 @@ -/* - G3D Geometry Format Library - Copyright 2019, VIMaec LLC. - Copyright 2018, Ara 3D Inc. - Usage licensed under terms of MIT License -*/ - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using Vim.LinqArray; -using Vim.Math3d; -using Vim.BFastLib; -using System.Diagnostics; - -namespace Vim.G3d -{ - /// - /// Represents a basic single-precision G3D in memory, with access to common attributes. - /// The G3D format can be double precision, but this data structure won't provide access to all of the attributes. - /// In the case of G3D formats that are non-conformant to the expected semantics you can use GeometryAttributes. - /// This class is inspired heavily by the structure of FBX and Assimp. - /// - public class G3D : GeometryAttributes - { - public new static G3D Empty = Create(); - - public G3dHeader Header { get; } - - // These are the values of the most common attributes. Some are retrieved directly from data, others are computed on demand, or coerced. - - // Vertex buffer. Usually present. - public IArray Vertices { get; } - - // Index buffer (one index per corner, and per half-edge). Computed if absent. - public IArray Indices { get; } - - // Vertex associated data, provided or null - public List> AllVertexUvs { get; } = new List>(); - public List> AllVertexColors { get; } = new List>(); - public IArray VertexUvs => AllVertexUvs?.ElementAtOrDefault(0); - public IArray VertexColors => AllVertexColors?.ElementAtOrDefault(0); - public IArray VertexNormals { get; } - public IArray VertexTangents { get; } - - // Faces - public IArray FaceMaterials { get; } // Material indices per face, - public IArray FaceNormals { get; } // If not provided, are computed dynamically as the average of all vertex normals, - - // Meshes - public IArray MeshIndexOffsets { get; } // Offset into the index buffer for each Mesh - public IArray MeshVertexOffsets { get; } // Offset into the vertex buffer for each Mesh - public IArray MeshIndexCounts { get; } // Computed - public IArray MeshVertexCounts { get; } // Computed - public IArray MeshSubmeshOffset { get; } - public IArray MeshSubmeshCount { get; } // Computed - public IArray Meshes { get; } - - // Instances - public IArray InstanceParents { get; } // Index of the parent transform - public IArray InstanceTransforms { get; } // A 4x4 matrix in row-column order defining the transormed - public IArray InstanceMeshes { get; } // The SubGeometry associated with the index - public IArray InstanceFlags { get; } // The instance flags associated with the index. - - // Shapes - public IArray ShapeVertices { get; } - public IArray ShapeVertexOffsets { get; } - public IArray ShapeColors { get; } - public IArray ShapeWidths { get; } - public IArray ShapeVertexCounts { get; } // Computed - public IArray Shapes { get; } // Computed - - // Materials - public IArray MaterialColors { get; } // RGBA with transparency. - public IArray MaterialGlossiness { get; } - public IArray MaterialSmoothness { get; } - public IArray Materials { get; } - - - // Submeshes - public IArray SubmeshIndexOffsets { get; } - public IArray SubmeshIndexCount { get; } - public IArray SubmeshMaterials { get; } - - public G3D(IEnumerable attributes, G3dHeader? header = null, int numCornersPerFaceOverride = -1) - : base(attributes, numCornersPerFaceOverride) - { - Header = header ?? new G3dHeader(); - - foreach (var attr in Attributes.ToEnumerable()) - { - var desc = attr.Descriptor; - switch (desc.Semantic) - { - case Semantic.Index: - if (attr.IsTypeAndAssociation(Association.assoc_corner)) - Indices = Indices ?? attr.AsType().Data; - if (attr.IsTypeAndAssociation(Association.assoc_corner)) - Indices = Indices ?? attr.AsType().Data.Select(x => (int)x); - break; - - case Semantic.Position: - if (attr.IsTypeAndAssociation(Association.assoc_vertex)) - Vertices = Vertices ?? attr.AsType().Data; - if (attr.IsTypeAndAssociation(Association.assoc_corner)) - Vertices = Vertices ?? attr.AsType().Data; // TODO: is this used? - if (attr.IsTypeAndAssociation(Association.assoc_shapevertex)) - ShapeVertices = ShapeVertices ?? attr.AsType().Data; - break; - - case Semantic.Tangent: - if (attr.IsTypeAndAssociation(Association.assoc_vertex)) - VertexTangents = VertexTangents ?? attr.AsType().Data.Select(v => v.ToVector4()); - if (attr.IsTypeAndAssociation(Association.assoc_vertex)) - VertexTangents = VertexTangents ?? attr.AsType().Data; - break; - - case Semantic.Uv: - if (attr.IsTypeAndAssociation(Association.assoc_vertex)) - AllVertexUvs.Add(attr.AsType().Data.Select(uv => uv.ToVector2())); - if (attr.IsTypeAndAssociation(Association.assoc_vertex)) - AllVertexUvs.Add(attr.AsType().Data); - break; - - case Semantic.Color: - if (desc.Association == Association.assoc_vertex) - AllVertexColors.Add(attr.AttributeToColors()); - if (desc.Association == Association.assoc_shape) - ShapeColors = ShapeColors ?? attr.AttributeToColors(); - if (desc.Association == Association.assoc_material) - MaterialColors = MaterialColors ?? attr.AttributeToColors(); - break; - - case Semantic.VertexOffset: - if (attr.IsTypeAndAssociation(Association.assoc_mesh)) - MeshVertexOffsets = MeshVertexOffsets ?? attr.AsType().Data; - if (attr.IsTypeAndAssociation(Association.assoc_shape)) - ShapeVertexOffsets = ShapeVertexOffsets ?? attr.AsType().Data; - break; - - case Semantic.IndexOffset: - if (attr.IsTypeAndAssociation(Association.assoc_mesh)) - MeshIndexOffsets = MeshIndexOffsets ?? attr.AsType().Data; - if (attr.IsTypeAndAssociation(Association.assoc_submesh)) - SubmeshIndexOffsets = SubmeshIndexOffsets ?? attr.AsType().Data; - break; - - case Semantic.Normal: - if (attr.IsTypeAndAssociation(Association.assoc_face)) - FaceNormals = FaceNormals ?? attr.AsType().Data; - if (attr.IsTypeAndAssociation(Association.assoc_vertex)) - VertexNormals = VertexNormals ?? attr.AsType().Data; - break; - - case Semantic.Material: - if (attr.IsTypeAndAssociation(Association.assoc_face)) - FaceMaterials = FaceMaterials ?? attr.AsType().Data; - if (attr.IsTypeAndAssociation(Association.assoc_submesh)) - SubmeshMaterials = SubmeshMaterials ?? attr.AsType().Data; - break; - - case Semantic.Parent: - if (attr.IsTypeAndAssociation(Association.assoc_instance)) - InstanceParents = InstanceParents ?? attr.AsType().Data; - break; - - case Semantic.Mesh: - if (attr.IsTypeAndAssociation(Association.assoc_instance)) - InstanceMeshes = InstanceMeshes ?? attr.AsType().Data; - break; - - case Semantic.Transform: - if (attr.IsTypeAndAssociation(Association.assoc_instance)) - InstanceTransforms = InstanceTransforms ?? attr.AsType().Data; - break; - - case Semantic.Width: - if (attr.IsTypeAndAssociation(Association.assoc_shape)) - ShapeWidths = ShapeWidths ?? attr.AsType().Data; - break; - - case Semantic.Glossiness: - if (attr.IsTypeAndAssociation(Association.assoc_material)) - MaterialGlossiness = attr.AsType().Data; - break; - - case Semantic.Smoothness: - if (attr.IsTypeAndAssociation(Association.assoc_material)) - MaterialSmoothness = attr.AsType().Data; - break; - - case Semantic.SubMeshOffset: - if (attr.IsTypeAndAssociation(Association.assoc_mesh)) - MeshSubmeshOffset = attr.AsType().Data; - break; - - case Semantic.Flags: - if (attr.IsTypeAndAssociation(Association.assoc_instance)) - InstanceFlags = attr.AsType().Data; - break; - } - } - - // If no vertices are provided, we are going to generate a list of zero vertices. - if (Vertices == null) - Vertices = Vector3.Zero.Repeat(0); - - // If no indices are provided then we are going to have to treat the index buffer as indices - if (Indices == null) - Indices = Vertices.Indices(); - - // Compute face normals if possible - if (FaceNormals == null && VertexNormals != null) - FaceNormals = NumFaces.Select(ComputeFaceNormal); - - if (NumMeshes > 0) - { - // Mesh offset is the same as the offset of its first submesh. - if(MeshSubmeshOffset != null) - { - MeshIndexOffsets = MeshSubmeshOffset.Select(submesh => SubmeshIndexOffsets[submesh]); - MeshSubmeshCount = GetSubArrayCounts(MeshSubmeshOffset.Count, MeshSubmeshOffset, NumSubmeshes).Evaluate(); - } - - if(MeshIndexOffsets != null) - { - MeshIndexCounts = GetSubArrayCounts(NumMeshes, MeshIndexOffsets, NumCorners); - MeshVertexOffsets = MeshIndexOffsets - .Zip(MeshIndexCounts, (start, count) => (start, count)) - .Select(range => Indices.SubArray(range.start, range.count).Min()); - } - - if (MeshVertexOffsets != null) - MeshVertexCounts = GetSubArrayCounts(NumMeshes, MeshVertexOffsets, NumVertices); - } - else - { - MeshSubmeshCount = Array.Empty().ToIArray(); - } - - if (SubmeshIndexOffsets != null) - SubmeshIndexCount = GetSubArrayCounts(SubmeshIndexOffsets.Count, SubmeshIndexOffsets, NumCorners).Evaluate(); - - // Compute all meshes - Meshes = NumMeshes.Select(i => new G3dMesh(this, i)); - - if (MaterialColors != null) - Materials = MaterialColors.Count.Select(i => new G3dMaterial(this, i)); - - // Process the shape data - if (ShapeVertices == null) - ShapeVertices = Vector3.Zero.Repeat(0); - - if (ShapeVertexOffsets == null) - ShapeVertexOffsets = Array.Empty().ToIArray(); - - if (ShapeColors == null) - ShapeColors = Vector4.Zero.Repeat(0); - - if (ShapeWidths == null) - ShapeWidths = Array.Empty().ToIArray(); - - // Update the instance options - if (InstanceFlags == null) - InstanceFlags = ((ushort) 0).Repeat(NumInstances); - - ShapeVertexCounts = GetSubArrayCounts(NumShapes, ShapeVertexOffsets, ShapeVertices.Count); - ValidateSubArrayCounts(ShapeVertexCounts, nameof(ShapeVertexCounts)); - - Shapes = NumShapes.Select(i => new G3dShape(this, i)); - } - - private static IArray GetSubArrayCounts(int numItems, IArray offsets, int totalCount) - => numItems.Select(i => i < (numItems - 1) - ? offsets[i + 1] - offsets[i] - : totalCount - offsets[i]); - - private static void ValidateSubArrayCounts(IArray subArrayCounts, string memberName) - { - for (var i = 0; i < subArrayCounts.Count; ++i) - { - if (subArrayCounts[i] < 0) - throw new Exception($"{memberName}[{i}] is a negative sub array count."); - } - } - - public static Vector3 Average(IArray xs) - => xs.Aggregate(Vector3.Zero, (a, b) => a + b) / xs.Count; - - public Vector3 ComputeFaceNormal(int nFace) - => Average(NumCornersPerFace.Select(c => VertexNormals[nFace * NumCornersPerFace + c])); - - public static G3D Read(string filePath) - { - using (var stream = File.OpenRead(filePath)) - { - var bfast = new BFast(stream); - return Read(bfast); - } - } - - - public static G3D Read(BFast bfast) - { - 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); - if (attribute == null) continue; - 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)) - { - Debug.WriteLine("G3D Error: Could not parse attribute " + name); - return null; - } - try - { - return attributeDescriptor.ToDefaultAttribute(0); - } - catch - { - Debug.WriteLine("G3D Error: Could not parse attribute " + name); - 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/G3dMaterial.cs b/src/cs/g3d/Vim.G3d/G3dMaterial.cs deleted file mode 100644 index 9dc3b5bf..00000000 --- a/src/cs/g3d/Vim.G3d/G3dMaterial.cs +++ /dev/null @@ -1,20 +0,0 @@ -using Vim.Math3d; - -namespace Vim.G3d -{ - public class G3dMaterial - { - public readonly G3D G3d; - public readonly int Index; - - public G3dMaterial(G3D g3D, int index) - { - G3d = g3D; - Index = index; - } - - public Vector4 Color => G3d.MaterialColors[Index]; - public float Glossiness => G3d?.MaterialGlossiness[Index] ?? 0f; - public float Smoothness => G3d?.MaterialSmoothness[Index] ?? 0f; - } -} diff --git a/src/cs/g3d/Vim.G3d/G3dMesh.cs b/src/cs/g3d/Vim.G3d/G3dMesh.cs deleted file mode 100644 index 837ac11f..00000000 --- a/src/cs/g3d/Vim.G3d/G3dMesh.cs +++ /dev/null @@ -1,120 +0,0 @@ -using System; -using System.Collections.Generic; -using Vim.LinqArray; -using Vim.Math3d; - -namespace Vim.G3d -{ - - public interface IMeshCommon : ITransformable3D - { - IMeshCommon Clone(); - void SetVertices(Vector3[] vertices); - void SetIndices(int[] indices); - - // To be compatible with IMesh - IArray Vertices { get; } - IArray Indices { get; } - - IArray SubmeshMaterials { get; } - IArray SubmeshIndexOffsets { get; } - IArray SubmeshIndexCounts { get; } - - - - // To be compatible with IGeometryAttributes - int NumCornersPerFace { get; } - int NumVertices { get; } - int NumCorners { get; } - int NumFaces { get; } - int NumInstances { get; } - int NumMeshes { get; } - int NumShapeVertices { get; } - int NumShapes { get; } - } - - /// - /// A G3dMesh is a section of the G3D data that defines a mesh. - /// This does not implement IGeometryAttributes for performance reasons. - /// - public class G3dMesh : IMeshCommon - { - public G3D G3D { get; } - public int Index { get; } - - public int VertexOffset => G3D.MeshVertexOffsets[Index]; - public int NumVertices => G3D.MeshVertexCounts[Index]; - public int IndexOffset => G3D.MeshIndexOffsets[Index]; - public int NumCorners => G3D.MeshIndexCounts[Index]; - public int FaceOffset => IndexOffset / NumCornersPerFace; - public int NumFaces => NumCorners / NumCornersPerFace; - public int NumCornersPerFace => G3D.NumCornersPerFace; - - - // Fillers to fullfil IGeometryAttributes for now - public int NumInstances => 0; - public int NumMeshes => 1; - public int NumShapeVertices => 0; - public int NumShapes => 0; - - // Data - public IArray Vertices { get; private set; } - public IArray Indices { get; private set; } - public IArray SubmeshMaterials { get; private set; } - public IArray SubmeshIndexOffsets { get; private set; } - public IArray SubmeshIndexCounts { get; private set; } - - - public G3dMesh(G3D parent, int index) - { - (G3D, Index) = (parent, index); - Vertices = G3D.Vertices?.SubArray(VertexOffset, NumVertices); - var offset = VertexOffset; - Indices = G3D.Indices?.SubArray(IndexOffset, NumCorners).Select(i => i - offset); - - // TODO: Remove need for this. - var submeshArray = (G3D.SubmeshIndexOffsets as ArrayAdapter).Array; - var submeshIndex = Array.BinarySearch(submeshArray, IndexOffset); - var submeshCount = 0; - for(var i = submeshIndex; i < submeshArray.Length; i++) - { - var indexOffset = submeshArray[i]; - if (indexOffset - IndexOffset >= NumCorners) - break; - submeshCount++; - } - SubmeshMaterials = G3D.SubmeshMaterials?.SubArray(submeshIndex, submeshCount).Evaluate(); - SubmeshIndexOffsets = G3D.SubmeshIndexOffsets?.SubArray(submeshIndex, submeshCount).Select(i => i - IndexOffset).Evaluate(); - - var last = NumCorners - SubmeshIndexOffsets.Last(); - SubmeshIndexCounts = SubmeshIndexOffsets.AdjacentDifferences().Append(last).Evaluate(); - } - - public IMeshCommon Transform(Matrix4x4 mat) - { - var mesh = Clone(); - mesh.Vertices = mesh.Vertices.Select(v => v.Transform(mat)).Evaluate(); - return mesh; - } - - public G3dMesh Clone() - { - var mesh = new G3dMesh(G3D, Index); - mesh.Vertices = mesh.Vertices; - mesh.Indices = mesh.Indices; - mesh.SubmeshMaterials = mesh.SubmeshMaterials; - mesh.SubmeshIndexOffsets = mesh.SubmeshIndexOffsets; - mesh.SubmeshIndexCounts = mesh.SubmeshIndexCounts; - return mesh; - } - IMeshCommon IMeshCommon.Clone() => Clone(); - public void SetVertices(Vector3[] vertices) - { - Vertices = vertices.ToIArray(); - } - public void SetIndices(int[] indices) - { - Indices = indices.ToIArray(); - } - } -} diff --git a/src/cs/g3d/Vim.G3d/G3dShape.cs b/src/cs/g3d/Vim.G3d/G3dShape.cs deleted file mode 100644 index 9cd220ad..00000000 --- a/src/cs/g3d/Vim.G3d/G3dShape.cs +++ /dev/null @@ -1,23 +0,0 @@ -using Vim.LinqArray; -using Vim.Math3d; - -namespace Vim.G3d -{ - public class G3dShape - { - public readonly G3D G3D; - public readonly int Index; - public readonly IArray Vertices; - - public int ShapeVertexOffset => G3D.ShapeVertexOffsets[Index]; - public int NumVertices => G3D.ShapeVertexCounts[Index]; - public Vector4 Color => G3D.ShapeColors[Index]; - public float Width => G3D.ShapeWidths[Index]; - - public G3dShape(G3D parent, int index) - { - (G3D, Index) = (parent, index); - Vertices = G3D.ShapeVertices?.SubArray(ShapeVertexOffset, NumVertices); - } - } -} diff --git a/src/cs/g3d/Vim.G3d/GeometryAttribute.cs b/src/cs/g3d/Vim.G3d/GeometryAttribute.cs deleted file mode 100644 index 9b2030f9..00000000 --- a/src/cs/g3d/Vim.G3d/GeometryAttribute.cs +++ /dev/null @@ -1,245 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using Vim.LinqArray; -using Vim.Math3d; -using Vim.BFastLib; -using Vim.BFastLib.Core; - -namespace Vim.G3d -{ - /// - /// A mesh attribute is an array of data associated with some component of a mesh. - /// It could be vertices, corners, faces, face groups, sub-meshes, instances or the entire mesh. - /// This is the base class of a typed MeshAttribute. - /// It provides two core operations we are the foundation for mesh manipulation: - /// 1. concatenation with like-typed attributes - /// 2. remapping - /// - public abstract class GeometryAttribute - { - /// - /// The descriptor contains information about the data contained in the attribute: - /// * the primitive data type - /// * the arity - /// * the association - /// * the semantic - /// - public AttributeDescriptor Descriptor { get; } - - /// - /// A "name" is a string encoding of the attribute descriptor. - /// - public string Name - => Descriptor.Name; - - /// - /// This is the number of data elements in the attribute. This is equal to - /// the number of primitives times the arity. All mesh attributes associated - /// with the same mesh component (e.g. vertices) must have the same element count. - /// - public int ElementCount { get; } - - /// - /// Constructor. - /// - protected GeometryAttribute(AttributeDescriptor descriptor, int count) - => (Descriptor, ElementCount) = (descriptor, count); - - /// - /// Multiple mesh attributes can be merged together if they have the same - /// underlying descriptor and data type. - /// - public abstract GeometryAttribute Merge(IEnumerable others); - - /// - /// A mesh attribute can be remapped, using the given indices. - /// - public abstract GeometryAttribute Remap(IArray indices); - - /// - /// Converted to an INamedBuffer which consists of a name and an array of unmanaged types. - /// - public abstract INamedBuffer ToBuffer(); - - /// - /// Convenience function to check if this object is a mesh attribute of the given type. - /// - public bool IsType() where T : unmanaged - => this is GeometryAttribute; - - /// - /// Convenience function to check if this object is a mesh attribute of the given type, and the association matches. - /// - public bool IsTypeAndAssociation(Association assoc) where T : unmanaged - => Descriptor.Association == assoc && this is GeometryAttribute; - - /// - /// Convenience function to cast this object into a mesh attribute of the given type, throwing an exception if not possible, - /// - public GeometryAttribute AsType() where T : unmanaged - => this as GeometryAttribute ?? throw new Exception($"The type of the attribute is {GetType()} not MeshAttribute<{typeof(T)}>"); - - /// - /// Loads the correct typed data from a Stream. - /// - public abstract GeometryAttribute Read(Stream stream, long byteCount); - - /// - /// Loads the correct typed data from a BFastNext. - /// - public abstract GeometryAttribute Read(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 - /// - public abstract GeometryAttribute SetIndex(int index); - } - - /// - /// This is a typed attribute associated with some part of the mesh. - /// The underlying data is an IArray which means that it can be - /// computed on demand. - /// - public class GeometryAttribute : GeometryAttribute where T : unmanaged - { - public IArray Data; - - public GeometryAttribute(IArray data, AttributeDescriptor descriptor) - : base(descriptor, data.Count) - { - Data = data; - int arity; - DataType dataType; - // TODO: TECH DEBT - Support unsigned tuples in Math3d - if (typeof(T) == typeof(byte)) - (arity, dataType) = (1, DataType.dt_uint8); - else if (typeof(T) == typeof(sbyte)) - (arity, dataType) = (1, DataType.dt_int8); - else if (typeof(T) == typeof(Byte2)) - (arity, dataType) = (2, DataType.dt_int8); - else if (typeof(T) == typeof(Byte3)) - (arity, dataType) = (3, DataType.dt_int8); - else if (typeof(T) == typeof(Byte4)) - (arity, dataType) = (4, DataType.dt_int8); - else if (typeof(T) == typeof(ushort)) - (arity, dataType) = (1, DataType.dt_uint16); - else if (typeof(T) == typeof(short)) - (arity, dataType) = (1, DataType.dt_int16); - else if (typeof(T) == typeof(uint)) - (arity, dataType) = (1, DataType.dt_uint32); - else if (typeof(T) == typeof(int)) - (arity, dataType) = (1, DataType.dt_int32); - else if (typeof(T) == typeof(Int2)) - (arity, dataType) = (2, DataType.dt_int32); - else if (typeof(T) == typeof(Int3)) - (arity, dataType) = (3, DataType.dt_int32); - else if (typeof(T) == typeof(Int4)) - (arity, dataType) = (4, DataType.dt_int32); - else if (typeof(T) == typeof(ulong)) - (arity, dataType) = (1, DataType.dt_uint64); - else if (typeof(T) == typeof(long)) - (arity, dataType) = (1, DataType.dt_int64); - else if (typeof(T) == typeof(float)) - (arity, dataType) = (1, DataType.dt_float32); - else if (typeof(T) == typeof(Vector2)) - (arity, dataType) = (2, DataType.dt_float32); - else if (typeof(T) == typeof(Vector3)) - (arity, dataType) = (3, DataType.dt_float32); - else if (typeof(T) == typeof(Vector4)) - (arity, dataType) = (4, DataType.dt_float32); - else if (typeof(T) == typeof(Matrix4x4)) - (arity, dataType) = (16, DataType.dt_float32); - else if (typeof(T) == typeof(double)) - (arity, dataType) = (1, DataType.dt_float64); - else if (typeof(T) == typeof(DVector2)) - (arity, dataType) = (2, DataType.dt_float64); - else if (typeof(T) == typeof(DVector3)) - (arity, dataType) = (3, DataType.dt_float64); - else if (typeof(T) == typeof(DVector4)) - (arity, dataType) = (4, DataType.dt_float64); - else - throw new Exception($"Unsupported data type {typeof(T)}"); - - // Check that the computed data type is consistent with the descriptor - if (dataType != Descriptor.DataType) - throw new Exception($"DataType was {dataType} but expected {Descriptor.DataType}"); - - // Check that the computed data arity is consistent with the descriptor - if (arity != Descriptor.DataArity) - throw new Exception($"DatArity was {arity} but expected {Descriptor.DataArity}"); - } - - public override GeometryAttribute Merge(IEnumerable others) - { - if (!others.Any()) - return this; - - // Check that all attributes have the same descriptor - if (!others.All(ma => ma.Descriptor.Equals(Descriptor))) - throw new Exception($"All attributes have to have same descriptor {Descriptor} to be concatenated"); - - // Check that all attributes have the same type - if (!others.All(ma => ma is GeometryAttribute)) - throw new Exception($"All attributes have to have the same type {typeof(T)} to be concatenated"); - - // Given multiple attributes associated with "all" or with "nothing", the first one takes precedence - if (Descriptor.Association == Association.assoc_all || Descriptor.Association == Association.assoc_none) - return this; - - // Sub-geometry attributes can't be merged - if (Descriptor.Association == Association.assoc_mesh) - throw new Exception("Can't merge sub-geometry attributes"); - - // Instance attributes can't be merged - if (Descriptor.Association == Association.assoc_instance) - throw new Exception("Can't merge instance attributes"); - - // Index attributes can't be merged - if (Descriptor.Semantic == Semantic.Index) - throw new Exception("Can't merge index attributes"); - - return others - .Select(ma => ma as GeometryAttribute) - .Prepend(this) - .ToIArray() - .Select(attr => attr.Data) - .Flatten() - .ToAttribute(Descriptor); - } - - public override GeometryAttribute Remap(IArray indices) - => Data.SelectByIndex(indices).ToAttribute(Descriptor); - - public override INamedBuffer ToBuffer() - => Data.ToArray().ToNamedBuffer(Name); - - public override GeometryAttribute Read(Stream stream, long byteCount) - { - if (byteCount % Descriptor.DataElementSize != 0) - throw new Exception($"The number of bytes to read {byteCount} does not divide cleanly by the size of the elements {Descriptor.DataElementSize}"); - var nElements = byteCount / Descriptor.DataElementSize; - if (nElements > int.MaxValue) - throw new Exception($"Trying to read {nElements} which is more than the maximum number of elements in a C# array"); - var data = stream.ReadArray((int)nElements); - return new GeometryAttribute(data.ToIArray(), Descriptor); - } - - public override GeometryAttribute Read(BFast bfast) - { - var array = bfast.GetArray(Name); - return new GeometryAttribute(array.ToIArray(), Descriptor); - } - - public override void AddTo(BFast 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/GeometryAttributes.cs b/src/cs/g3d/Vim.G3d/GeometryAttributes.cs deleted file mode 100644 index ac799c07..00000000 --- a/src/cs/g3d/Vim.G3d/GeometryAttributes.cs +++ /dev/null @@ -1,164 +0,0 @@ -/* - G3D Geometry Format Library - Copyright 2019, VIMaec LLC. - Copyright 2018, Ara 3D Inc. - Usage licensed under terms of MIT License -*/ - -using System; -using System.Collections.Generic; -using System.Linq; -using Vim.LinqArray; - -namespace Vim.G3d -{ - /// - /// This is the most generic representation of a G3D, which is a bag of attributes, and the observed size of each component. - /// - public class GeometryAttributes : IGeometryAttributes - { - public int NumCornersPerFace { get; } = -1; - - public int NumVertices { get; } = -1; - public int NumFaces { get; } = -1; - public int NumCorners { get; } = -1; - public int NumMeshes { get; } = -1; - public int NumInstances { get; } = -1; - public int NumMaterials { get; } = -1; - public int NumSubmeshes { get; } = -1; - - public int NumShapeVertices { get; } = -1; - public int NumShapes { get; } = -1; - - public IArray Attributes { get; } - - public GeometryAttribute GetAttribute(string name) - => Lookup.TryGetValue(name, out var val) ? val : null; - - public Dictionary Lookup - = new Dictionary(); - - public int ValidateAttribute(GeometryAttribute attr, int expectedCount) - { - if (expectedCount >= 0 && attr.ElementCount != expectedCount) - throw new Exception($"Attribute {attr.Descriptor.Name} size {attr.ElementCount} not match the expected size {expectedCount}"); - return attr.ElementCount; - } - - public GeometryAttributes(IEnumerable attributes, int numCornersPerFaceOverride = -1) - { - foreach (var attr in attributes) - { - if (attr != null && !Lookup.ContainsKey(attr.Name)) - Lookup.Add(attr.Name, attr); - } - - foreach (var attr in Lookup.Values) - { - var desc = attr.Descriptor; - - switch (desc.Association) - { - case Association.assoc_none: - break; - case Association.assoc_vertex: - NumVertices = ValidateAttribute(attr, NumVertices); - break; - case Association.assoc_edge: - case Association.assoc_corner: - NumCorners = ValidateAttribute(attr, NumCorners); - break; - case Association.assoc_face: - NumFaces = ValidateAttribute(attr, NumFaces); - break; - case Association.assoc_instance: - NumInstances = ValidateAttribute(attr, NumInstances); - break; - case Association.assoc_submesh: - NumSubmeshes = ValidateAttribute(attr, NumSubmeshes); - break; - case Association.assoc_material: - NumMaterials = ValidateAttribute(attr, NumMaterials); - break; - case Association.assoc_mesh: - NumMeshes = ValidateAttribute(attr, NumMeshes); - break; - case Association.assoc_shapevertex: - NumShapeVertices = ValidateAttribute(attr, NumShapeVertices); - break; - case Association.assoc_shape: - NumShapes = ValidateAttribute(attr, NumShapes); - break; - } - - if (desc.Semantic == Semantic.FaceSize) - { - if (desc.Association != Association.assoc_all) - throw new Exception($"The face size semantic has to be associated with entire geometry set, not {desc.Association}"); - if (desc.DataArity != 1) - throw new Exception($"The face size semantic has to have arity of 1, not {desc.DataArity}"); - - if (desc.DataType == DataType.dt_int8) - NumCornersPerFace = attr.AsType().Data[0]; - else if (desc.DataType == DataType.dt_int16) - NumCornersPerFace = attr.AsType().Data[0]; - else if (desc.DataType == DataType.dt_int32) - NumCornersPerFace = attr.AsType().Data[0]; - else - throw new Exception($"The face size semantic has to be an int8, int16, or int32"); - } - } - - if (NumVertices < 0) NumVertices = 0; - - // If the index attribute is missing we will have to add it. - if (!Lookup.ContainsKey(CommonAttributes.Index)) - { - if (NumCorners < 0) NumCorners = NumVertices; - Lookup.Add(CommonAttributes.Index, NumCorners.Range().ToIndexAttribute()); - } - - // Now we create the public ordered list of attributes - Attributes = Lookup.Values.OrderBy(attr => attr.Name).ToIArray(); - - - // If the number of corner and faces are observed, one has to be a multiple of the other - if (NumCorners > 0 && NumFaces > 0) - { - if (NumCorners % NumFaces != 0) - throw new Exception($"The number of corners {NumCorners} to be divisible by the number of faces {NumFaces}"); - } - - // Try to compute the number of corners per face - if (NumCornersPerFace < 0) - { - if (NumCorners > 0 && NumFaces > 0) - { - // We compute the number of corners per face by dividing the observed number of faces by the observed number of corners - NumCornersPerFace = NumCorners / NumFaces; - } - else - { - // By default we assume a triangular mesh - NumCornersPerFace = 3; - } - } - - if (numCornersPerFaceOverride >= 0) - { - NumCornersPerFace = numCornersPerFaceOverride; - } - - if (NumCorners < 0) NumCorners = NumVertices; - if (NumInstances < 0) NumInstances = 0; - if (NumMeshes < 0) NumMeshes = 0; - if (NumFaces < 0) NumFaces = NumCorners / NumCornersPerFace; - - if (NumShapeVertices < 0) NumShapeVertices = 0; - if (NumShapes < 0) NumShapes = 0; - } - - public static GeometryAttributes Empty - => new GeometryAttributes(new GeometryAttribute[] { }); - } -} diff --git a/src/cs/g3d/Vim.G3d/GeometryAttributesExtensions.cs b/src/cs/g3d/Vim.G3d/GeometryAttributesExtensions.cs deleted file mode 100644 index a378b94f..00000000 --- a/src/cs/g3d/Vim.G3d/GeometryAttributesExtensions.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Vim.LinqArray; -using Vim.Math3d; - -namespace Vim.G3d -{ - public static class GeometryAttributesExtensions - { - public static GeometryAttribute GetAttribute(this IGeometryAttributes g, string attributeName) where T : unmanaged - => g.GetAttribute(attributeName)?.AsType(); - - public static IGeometryAttributes ToGeometryAttributes(this IEnumerable attributes) - => new GeometryAttributes(attributes); - - public static IGeometryAttributes AddAttributes(this IGeometryAttributes attributes, params GeometryAttribute[] newAttributes) - => attributes.Attributes.ToEnumerable().Concat(newAttributes).ToGeometryAttributes(); - - public static IGeometryAttributes Replace(this IGeometryAttributes self, Func selector, GeometryAttribute attribute) - => self.Attributes.Where(a => !selector(a.Descriptor)).Append(attribute).ToGeometryAttributes(); - - public static IGeometryAttributes Remove(this IGeometryAttributes self, Func selector) - => self.Attributes.Where(a => !selector(a.Descriptor)).ToGeometryAttributes(); - - public static G3D ToG3d(this IGeometryAttributes self) - => G3D.Create(self.Attributes.ToArray()); - } -} diff --git a/src/cs/g3d/Vim.G3d/Header.cs b/src/cs/g3d/Vim.G3d/Header.cs deleted file mode 100644 index 60d4bb09..00000000 --- a/src/cs/g3d/Vim.G3d/Header.cs +++ /dev/null @@ -1,81 +0,0 @@ -using System; -using System.Text; - -namespace Vim.G3d -{ - // 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 - - // The header is 7 bytes + 1 bytes padding. - public struct G3dHeader - { - public const byte MagicA = 0x63; - public const byte MagicB = 0xD0; - - 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 static G3dHeader FromBytes(byte[] bytes) - => new G3dHeader - { - magicA = bytes[0], - magicB = bytes[1], - unitA = bytes[2], - unitB = bytes[3], - upAxis = bytes[4], - forwardVector = bytes[5], - handedness = bytes[6], - } - .Validate(); - - public static G3dHeader FromBytesOrDefault(byte[] bytes) - { - try - { - return FromBytes(bytes).Validate(); - } - catch (Exception) - { - return Default; - } - } - - public static G3dHeader Default - = new G3dHeader - { - magicA = 0x63, - magicB = 0xD0, - unitA = (byte)'m', - unitB = 0, - upAxis = 2, - forwardVector = 0, - handedness = 0, - padding = 0 - }; - - public static readonly string[] SupportedUnits = { "mm", "cm", "m\0", "km", "in", "ft", "yd", "mi" }; - - public G3dHeader Validate() - { - if (magicA != 0x63) throw new Exception($"First magic number must be 0x63 not {magicA}"); - if (magicB != 0xD0) throw new Exception($"Second magic number must be 0xD0 not {magicB}"); - if (Array.IndexOf(SupportedUnits, Unit) < 0) throw new Exception($"Unit {Unit} is not a supported unit: {string.Join(", ", SupportedUnits)}"); - 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; - } - } -} diff --git a/src/cs/g3d/Vim.G3d/IGeometryAttributes.cs b/src/cs/g3d/Vim.G3d/IGeometryAttributes.cs deleted file mode 100644 index e25da638..00000000 --- a/src/cs/g3d/Vim.G3d/IGeometryAttributes.cs +++ /dev/null @@ -1,22 +0,0 @@ -using Vim.LinqArray; - -namespace Vim.G3d -{ - /// - /// This is a read-only collection of G3D attributes. - /// - public interface IGeometryAttributes - { - int NumCornersPerFace { get; } - int NumVertices { get; } - int NumCorners { get; } - int NumFaces { get; } - int NumInstances { get; } - int NumMeshes { get; } - int NumShapeVertices { get; } - int NumShapes { get; } - - IArray Attributes { get; } - GeometryAttribute GetAttribute(string name); - } -} diff --git a/src/cs/g3d/Vim.G3dNext/Constants.cs b/src/cs/g3d/Vim.G3dNext/Constants.cs index 8442d63a..047a6081 100644 --- a/src/cs/g3d/Vim.G3dNext/Constants.cs +++ b/src/cs/g3d/Vim.G3dNext/Constants.cs @@ -14,7 +14,39 @@ public enum MeshSection Transparent, All } - + public static class CommonAttributes + { + public const string ObjectFaceSize = "g3d:all:facesize:0:int32:1"; + public const string Index = "g3d:corner:index:0:int32:1"; + public const string Position = "g3d:vertex:position:0:float32:3"; + public const string VertexUv = "g3d:vertex:uv:0:float32:2"; + public const string VertexUvw = "g3d:vertex:uv:0:float32:3"; + public const string VertexNormal = "g3d:vertex:normal:0:float32:3"; + public const string VertexColor = "g3d:vertex:color:0:float32:4"; + public const string VertexColor8Bit = "g3d:vertex:color:0:int8:4"; + public const string VertexBitangent = "g3d:vertex:bitangent:0:float32:3"; + public const string VertexTangent = "g3d:vertex:tangent:0:float32:4"; + public const string VertexSelectionWeight = "g3d:vertex:weight:0:float32:1"; + public const string FaceColor = "g3d:face:color:0:float32:4"; + public const string FaceMaterial = "g3d:face:material:0:int32:1"; + public const string FaceNormal = "g3d:face:normal:0:float32:3"; + public const string MeshSubmeshOffset = "g3d:mesh:submeshoffset:0:int32:1"; + public const string InstanceTransform = "g3d:instance:transform:0:float32:16"; + public const string InstanceParent = "g3d:instance:parent:0:int32:1"; + public const string InstanceMesh = "g3d:instance:mesh:0:int32:1"; + public const string InstanceFlags = "g3d:instance:flags:0:uint16:1"; + public const string LineTangentIn = "g3d:vertex:tangent:0:float32:3"; + public const string LineTangentOut = "g3d:vertex:tangent:1:float32:3"; + public const string ShapeVertex = "g3d:shapevertex:position:0:float32:3"; + public const string ShapeVertexOffset = "g3d:shape:vertexoffset:0:int32:1"; + public const string ShapeColor = "g3d:shape:color:0:float32:4"; + public const string ShapeWidth = "g3d:shape:width:0:float32:1"; + public const string MaterialColor = "g3d:material:color:0:float32:4"; + public const string MaterialGlossiness = "g3d:material:glossiness:0:float32:1"; + public const string MaterialSmoothness = "g3d:material:smoothness:0:float32:1"; + public const string SubmeshIndexOffset = "g3d:submesh:indexoffset:0:int32:1"; + public const string SubmeshMaterial = "g3d:submesh:material:0:int32:1"; + } public static class Utils { public static bool SafeEqual(this T[] a, T[] b) diff --git a/src/cs/vim-format.sln b/src/cs/vim-format.sln index d003f17e..6939a1f3 100644 --- a/src/cs/vim-format.sln +++ b/src/cs/vim-format.sln @@ -23,10 +23,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vim.Format", "vim\Vim.Forma EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "g3d", "g3d", "{705B8FB2-D707-4527-91FC-0AADEDBA4D80}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vim.G3d.Tests", "g3d\Vim.G3d.Tests\Vim.G3d.Tests.csproj", "{DFC8DC5E-377D-4CCC-A498-5894D891A471}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vim.G3d", "g3d\Vim.G3d\Vim.G3d.csproj", "{F1EC1E94-C74C-4C37-961C-305CAE7C4707}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vim.Format.CodeGen", "vim\Vim.Format.CodeGen\Vim.Format.CodeGen.csproj", "{762E8B1A-9182-4C5D-A25C-0C0F6219BA4E}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vim.Format.Tests", "vim\Vim.Format.Tests\Vim.Format.Tests.csproj", "{2CB4CF73-0CA8-4595-910C-EDA244EA5983}" @@ -83,14 +79,6 @@ Global {22278D91-27D7-4A84-8170-5FFB77A70C1F}.Debug|Any CPU.Build.0 = Debug|Any CPU {22278D91-27D7-4A84-8170-5FFB77A70C1F}.Release|Any CPU.ActiveCfg = Release|Any CPU {22278D91-27D7-4A84-8170-5FFB77A70C1F}.Release|Any CPU.Build.0 = Release|Any CPU - {DFC8DC5E-377D-4CCC-A498-5894D891A471}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {DFC8DC5E-377D-4CCC-A498-5894D891A471}.Debug|Any CPU.Build.0 = Debug|Any CPU - {DFC8DC5E-377D-4CCC-A498-5894D891A471}.Release|Any CPU.ActiveCfg = Release|Any CPU - {DFC8DC5E-377D-4CCC-A498-5894D891A471}.Release|Any CPU.Build.0 = Release|Any CPU - {F1EC1E94-C74C-4C37-961C-305CAE7C4707}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F1EC1E94-C74C-4C37-961C-305CAE7C4707}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F1EC1E94-C74C-4C37-961C-305CAE7C4707}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F1EC1E94-C74C-4C37-961C-305CAE7C4707}.Release|Any CPU.Build.0 = Release|Any CPU {762E8B1A-9182-4C5D-A25C-0C0F6219BA4E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {762E8B1A-9182-4C5D-A25C-0C0F6219BA4E}.Debug|Any CPU.Build.0 = Debug|Any CPU {762E8B1A-9182-4C5D-A25C-0C0F6219BA4E}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -157,8 +145,6 @@ Global {1086F24E-32C8-4261-9B06-A364EEE71DEF} = {9BD3CC85-97FD-4093-AA11-58FE405B0F65} {1CC20AA4-11F1-4548-9285-FD24D42190FB} = {9BD3CC85-97FD-4093-AA11-58FE405B0F65} {22278D91-27D7-4A84-8170-5FFB77A70C1F} = {D639C635-01D1-48C4-89B5-1FD70F1AFEE9} - {DFC8DC5E-377D-4CCC-A498-5894D891A471} = {705B8FB2-D707-4527-91FC-0AADEDBA4D80} - {F1EC1E94-C74C-4C37-961C-305CAE7C4707} = {705B8FB2-D707-4527-91FC-0AADEDBA4D80} {762E8B1A-9182-4C5D-A25C-0C0F6219BA4E} = {D639C635-01D1-48C4-89B5-1FD70F1AFEE9} {2CB4CF73-0CA8-4595-910C-EDA244EA5983} = {D639C635-01D1-48C4-89B5-1FD70F1AFEE9} {2C798994-518D-4EA5-8F8A-3EAA30269F9E} = {D639C635-01D1-48C4-89B5-1FD70F1AFEE9} diff --git a/src/cs/vim/Vim.Format.Core/G3dBuilder.cs b/src/cs/vim/Vim.Format.Core/G3dBuilder.cs index 082e957f..daca69a3 100644 --- a/src/cs/vim/Vim.Format.Core/G3dBuilder.cs +++ b/src/cs/vim/Vim.Format.Core/G3dBuilder.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; using System.Linq; -using Vim.G3d; +using Vim.G3dNext; using Vim.BFastLib; using static Vim.Format.DocumentBuilder; using Vim.Math3d; diff --git a/src/cs/vim/Vim.Format.Core/Geometry/MeshOptimization.cs b/src/cs/vim/Vim.Format.Core/Geometry/MeshOptimization.cs index ee3b002a..851a93d4 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/MeshOptimization.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/MeshOptimization.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using System.Linq; -using Vim.G3d; using Vim.LinqArray; using Vim.Math3d; diff --git a/src/cs/vim/Vim.Format.Core/Geometry/VimMaterial.cs b/src/cs/vim/Vim.Format.Core/Geometry/VimMaterial.cs deleted file mode 100644 index 4799219f..00000000 --- a/src/cs/vim/Vim.Format.Core/Geometry/VimMaterial.cs +++ /dev/null @@ -1,21 +0,0 @@ -using Vim.G3d; -using Vim.Math3d; - -namespace Vim.Format.Geometry -{ - public interface IMaterial - { - Vector4 Color { get; } - float Smoothness { get; } - float Glossiness { get; } - } - - public class VimMaterial : IMaterial - { - public G3dMaterial Material; - public VimMaterial(G3dMaterial material) => Material = material; - public Vector4 Color => Material.Color; - public float Smoothness => Material.Smoothness; - public float Glossiness => Material.Glossiness; - } -} diff --git a/src/cs/vim/Vim.Format.Core/Geometry/VimMaterialNext.cs b/src/cs/vim/Vim.Format.Core/Geometry/VimMaterialNext.cs index fd915fc8..0d0a1740 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/VimMaterialNext.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/VimMaterialNext.cs @@ -5,6 +5,14 @@ namespace Vim.Format.Geometry { + public interface IMaterial + { + Vector4 Color { get; } + float Smoothness { get; } + float Glossiness { get; } + } + + public class VimMaterialNext : IMaterial { public G3dVim g3d; diff --git a/src/cs/vim/Vim.Format.Core/SerializableDocument.cs b/src/cs/vim/Vim.Format.Core/SerializableDocument.cs index 94364b97..013ce98f 100644 --- a/src/cs/vim/Vim.Format.Core/SerializableDocument.cs +++ b/src/cs/vim/Vim.Format.Core/SerializableDocument.cs @@ -4,7 +4,6 @@ using System.Text; using Vim.BFastLib; using Vim.BFastLib.Core; -using Vim.G3d; 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 f02d4460..00b498be 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/SceneBuilder/VimScene.cs b/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs index ec11608c..6c0ecc96 100644 --- a/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs +++ b/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs @@ -1,18 +1,17 @@ using System; +using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading.Tasks; +using Vim.BFastLib; using Vim.Format; using Vim.Format.Geometry; using Vim.Format.ObjectModel; -using Vim.Util; -using Vim.G3d; +using Vim.G3dNext; using Vim.LinqArray; using Vim.Math3d; +using Vim.Util; using IVimSceneProgress = System.IProgress<(string, double)>; -using Vim.BFastLib; -using Vim.G3dNext; -using System.Collections.Generic; namespace Vim { diff --git a/src/cs/vim/Vim.Format/Vim.Format.csproj b/src/cs/vim/Vim.Format/Vim.Format.csproj index 6f385377..a3ae53d8 100644 --- a/src/cs/vim/Vim.Format/Vim.Format.csproj +++ b/src/cs/vim/Vim.Format/Vim.Format.csproj @@ -18,7 +18,6 @@ - From 48e3459968d5ebd547e296b6d60d744ae9c78aec Mon Sep 17 00:00:00 2001 From: simon Date: Mon, 15 Apr 2024 15:55:53 -0400 Subject: [PATCH 172/204] removed geometry utils --- .../Vim.Format.Core/Geometry/GeometryUtil.cs | 60 +------------------ .../Vim.Format.Core/Geometry/Primitives.cs | 15 ----- .../Geometry/GeometryTests.cs | 8 +-- 3 files changed, 2 insertions(+), 81 deletions(-) diff --git a/src/cs/vim/Vim.Format.Core/Geometry/GeometryUtil.cs b/src/cs/vim/Vim.Format.Core/Geometry/GeometryUtil.cs index db8d33e7..6d6f1b71 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/GeometryUtil.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/GeometryUtil.cs @@ -6,63 +6,5 @@ namespace Vim.Format.Geometry { - // TODO: many of these functions should live in other places - public static class GeometryUtil - { - public static IArray Normalize(this IArray vectors) - => vectors.Select(v => v.Normalize()); - - public static bool SequenceAlmostEquals(this IArray vs1, IArray vs2, float tolerance = Math3d.Constants.Tolerance) - => vs1.Count == vs2.Count && vs1.Indices().All(i => vs1[i].AlmostEquals(vs2[i], tolerance)); - - public static bool AreColinear(this IEnumerable vectors, Vector3 reference, float tolerance = (float)Math3d.Constants.OneTenthOfADegree) - => !reference.IsNaN() && vectors.All(v => v.Colinear(reference, tolerance)); - - public static bool AreColinear(this IEnumerable vectors, float tolerance = (float)Math3d.Constants.OneTenthOfADegree) - => vectors.ToList().AreColinear(tolerance); - - public static bool AreColinear(this IList vectors, float tolerance = (float)Math3d.Constants.OneTenthOfADegree) - => vectors.Count <= 1 || vectors.Skip(1).AreColinear(vectors[0], tolerance); - - public static AABox BoundingBox(this IArray vertices) - => AABox.Create(vertices.ToEnumerable()); - - public static IArray SampleZeroToOneInclusive(this int count) - => (count + 1).Select(i => i / (float)count); - - public static IArray SampleZeroToOneExclusive(this int count) - => count.Select(i => i / (float)count); - - public static IArray InterpolateInclusive(this int count, Func function) - => count.SampleZeroToOneInclusive().Select(function); - - public static IArray Interpolate(this Line self, int count) - => count.InterpolateInclusive(self.Lerp); - - public static IArray Rotate(this IArray self, Vector3 axis, float angle) - => self.Transform(Matrix4x4.CreateFromAxisAngle(axis, angle)); - - public static IArray Transform(this IArray self, Matrix4x4 matrix) - => self.Select(x => x.Transform(matrix)); - - public static Int3 Sort(this Int3 v) - { - if (v.X < v.Y) - { - return (v.Y < v.Z) - ? new Int3(v.X, v.Y, v.Z) - : (v.X < v.Z) - ? new Int3(v.X, v.Z, v.Y) - : new Int3(v.Z, v.X, v.Y); - } - else - { - return (v.X < v.Z) - ? new Int3(v.Y, v.X, v.Z) - : (v.Y < v.Z) - ? new Int3(v.Y, v.Z, v.X) - : new Int3(v.Z, v.Y, v.X); - } - } - } + } diff --git a/src/cs/vim/Vim.Format.Core/Geometry/Primitives.cs b/src/cs/vim/Vim.Format.Core/Geometry/Primitives.cs index 97e09d20..3c97bbfd 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/Primitives.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/Primitives.cs @@ -280,20 +280,5 @@ public static VimMesh QuadMesh(this Func f, int usegs, int vse return VimMesh.FromQuad(indices.ToArray(), verts.ToArray()); } - - /// - /// Creates a revolved face ... note that the last points are on top of the original - /// - public static VimMesh RevolveAroundAxis(this IArray points, Vector3 axis, int segments = 4) - { - var verts = new List(); - for (var i = 0; i < segments; ++i) - { - var angle = Math3d.Constants.TwoPi / segments; - points.Rotate(axis, angle).AddTo(verts); - } - var indices = ComputeQuadMeshStripIndices(segments - 1, points.Count - 1); - return new VimMesh(indices.ToArray(), verts.ToArray()); - } } } diff --git a/src/cs/vim/Vim.Format.Tests/Geometry/GeometryTests.cs b/src/cs/vim/Vim.Format.Tests/Geometry/GeometryTests.cs index 334c882c..4e16f6b5 100644 --- a/src/cs/vim/Vim.Format.Tests/Geometry/GeometryTests.cs +++ b/src/cs/vim/Vim.Format.Tests/Geometry/GeometryTests.cs @@ -38,12 +38,7 @@ public static class GeometryTests }); public static VimMesh Torus = Primitives.Torus(10, 0.2f, 10, 24); - - static VimMesh RevolvedVerticalCylinder(float height, float radius, int verticalSegments, int radialSegments) - => (Vector3.UnitZ * height).ToLine().Interpolate(verticalSegments).Add(-radius.AlongX()).RevolveAroundAxis(Vector3.UnitZ, radialSegments); - - public static VimMesh Cylinder = RevolvedVerticalCylinder(5, 1, 4, 12); - + public static VimMesh[] AllMeshes = { XYTriangle, // 0 XYQuad, // 1 @@ -51,7 +46,6 @@ static VimMesh RevolvedVerticalCylinder(float height, float radius, int vertical XYQuad2x2, // 3 Tetrahedron, // 4 Torus, // 5 - Cylinder, // 6 XYTriangleTwice, // 7 }; From 8a55f41230ce975148000589e4d7c0f4cd7f55b7 Mon Sep 17 00:00:00 2001 From: simon Date: Mon, 15 Apr 2024 16:13:05 -0400 Subject: [PATCH 173/204] removing dead code --- .../Geometry/GeometryCuttingUtils.cs | 46 ------------- .../Vim.Format.Core/Geometry/GeometryUtil.cs | 68 ------------------- .../Vim.Format.Core/Geometry/Primitives.cs | 8 +-- .../Geometry/GeometryTests.cs | 8 +-- 4 files changed, 5 insertions(+), 125 deletions(-) delete mode 100644 src/cs/vim/Vim.Format.Core/Geometry/GeometryUtil.cs diff --git a/src/cs/vim/Vim.Format.Core/Geometry/GeometryCuttingUtils.cs b/src/cs/vim/Vim.Format.Core/Geometry/GeometryCuttingUtils.cs index 338f7776..b35ac47d 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/GeometryCuttingUtils.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/GeometryCuttingUtils.cs @@ -123,51 +123,5 @@ public static float LinePointDistance(Vector2 v, Vector2 w, Vector2 p, out float var closestPoint = v + t * (w - v); // Projection falls on the segment return (p - closestPoint).Length(); } - - - - // Apply a surface function that projects a 2d triangulation in UV space into a 3d triangulation - /* public static IGeometry ApplySurfaceFunction(this List triangulations, Func surfaceFunction) - { - var allIndices = new List(); - var allVertices = new List(); - - foreach (var triangulation in triangulations) - { - var vertices = triangulation.Points.ToList(); - var indices = triangulation.TriangleIndices; - - while (true) - { - List outIndices; - List outVertices; - bool done = SubdivideLargeTriangles(vertices, indices, out outVertices, out outIndices, 0.3f); - - vertices = outVertices; - indices = outIndices; - - if (done) - { - break; - } - } - - // Apply surface function - var vertices3d = vertices.Select(x => surfaceFunction(x.ToVector())); - - // Merge all triangulations - int startIndex = allVertices.Count; - allVertices.AddRange(vertices3d); - allIndices.AddRange(indices.Select(x => x + startIndex)); - } - - var cutGeometry = new G3D( - allVertices.ToIArray().ToVertexAttribute(), - allIndices.ToIArray().ToIndexAttribute(), - new FunctionalArray(allIndices.Count / 3, x => 3).ToFaceSizeAttribute() - ).ToIMesh(); - - return cutGeometry; - }*/ } } diff --git a/src/cs/vim/Vim.Format.Core/Geometry/GeometryUtil.cs b/src/cs/vim/Vim.Format.Core/Geometry/GeometryUtil.cs deleted file mode 100644 index db8d33e7..00000000 --- a/src/cs/vim/Vim.Format.Core/Geometry/GeometryUtil.cs +++ /dev/null @@ -1,68 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Vim.LinqArray; -using Vim.Math3d; - -namespace Vim.Format.Geometry -{ - // TODO: many of these functions should live in other places - public static class GeometryUtil - { - public static IArray Normalize(this IArray vectors) - => vectors.Select(v => v.Normalize()); - - public static bool SequenceAlmostEquals(this IArray vs1, IArray vs2, float tolerance = Math3d.Constants.Tolerance) - => vs1.Count == vs2.Count && vs1.Indices().All(i => vs1[i].AlmostEquals(vs2[i], tolerance)); - - public static bool AreColinear(this IEnumerable vectors, Vector3 reference, float tolerance = (float)Math3d.Constants.OneTenthOfADegree) - => !reference.IsNaN() && vectors.All(v => v.Colinear(reference, tolerance)); - - public static bool AreColinear(this IEnumerable vectors, float tolerance = (float)Math3d.Constants.OneTenthOfADegree) - => vectors.ToList().AreColinear(tolerance); - - public static bool AreColinear(this IList vectors, float tolerance = (float)Math3d.Constants.OneTenthOfADegree) - => vectors.Count <= 1 || vectors.Skip(1).AreColinear(vectors[0], tolerance); - - public static AABox BoundingBox(this IArray vertices) - => AABox.Create(vertices.ToEnumerable()); - - public static IArray SampleZeroToOneInclusive(this int count) - => (count + 1).Select(i => i / (float)count); - - public static IArray SampleZeroToOneExclusive(this int count) - => count.Select(i => i / (float)count); - - public static IArray InterpolateInclusive(this int count, Func function) - => count.SampleZeroToOneInclusive().Select(function); - - public static IArray Interpolate(this Line self, int count) - => count.InterpolateInclusive(self.Lerp); - - public static IArray Rotate(this IArray self, Vector3 axis, float angle) - => self.Transform(Matrix4x4.CreateFromAxisAngle(axis, angle)); - - public static IArray Transform(this IArray self, Matrix4x4 matrix) - => self.Select(x => x.Transform(matrix)); - - public static Int3 Sort(this Int3 v) - { - if (v.X < v.Y) - { - return (v.Y < v.Z) - ? new Int3(v.X, v.Y, v.Z) - : (v.X < v.Z) - ? new Int3(v.X, v.Z, v.Y) - : new Int3(v.Z, v.X, v.Y); - } - else - { - return (v.X < v.Z) - ? new Int3(v.Y, v.X, v.Z) - : (v.Y < v.Z) - ? new Int3(v.Y, v.Z, v.X) - : new Int3(v.Z, v.Y, v.X); - } - } - } -} diff --git a/src/cs/vim/Vim.Format.Core/Geometry/Primitives.cs b/src/cs/vim/Vim.Format.Core/Geometry/Primitives.cs index 97e09d20..24ca7bf3 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/Primitives.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/Primitives.cs @@ -119,7 +119,7 @@ public static Vector2 CirclePoint(int i, int numPoints) /// /// Computes the indices of a quad mesh astrip. /// - public static IArray ComputeQuadMeshStripIndices(int usegs, int vsegs, bool wrapUSegs = false, bool wrapVSegs = false) + public static int[] ComputeQuadMeshStripIndices(int usegs, int vsegs, bool wrapUSegs = false, bool wrapVSegs = false) { var indices = new List(); @@ -143,7 +143,7 @@ public static IArray ComputeQuadMeshStripIndices(int usegs, int vsegs, bool } } - return indices.ToIArray(); + return indices.ToArray(); } /// @@ -278,7 +278,7 @@ public static VimMesh QuadMesh(this Func f, int usegs, int vse } var indices = ComputeQuadMeshStripIndices(usegs, vsegs, wrapUSegs, wrapVSegs); - return VimMesh.FromQuad(indices.ToArray(), verts.ToArray()); + return VimMesh.FromQuad(indices, verts.ToArray()); } /// @@ -293,7 +293,7 @@ public static VimMesh RevolveAroundAxis(this IArray points, Vector3 axi points.Rotate(axis, angle).AddTo(verts); } var indices = ComputeQuadMeshStripIndices(segments - 1, points.Count - 1); - return new VimMesh(indices.ToArray(), verts.ToArray()); + return new VimMesh(indices, verts.ToArray()); } } } diff --git a/src/cs/vim/Vim.Format.Tests/Geometry/GeometryTests.cs b/src/cs/vim/Vim.Format.Tests/Geometry/GeometryTests.cs index 334c882c..26a82403 100644 --- a/src/cs/vim/Vim.Format.Tests/Geometry/GeometryTests.cs +++ b/src/cs/vim/Vim.Format.Tests/Geometry/GeometryTests.cs @@ -39,11 +39,6 @@ public static class GeometryTests public static VimMesh Torus = Primitives.Torus(10, 0.2f, 10, 24); - static VimMesh RevolvedVerticalCylinder(float height, float radius, int verticalSegments, int radialSegments) - => (Vector3.UnitZ * height).ToLine().Interpolate(verticalSegments).Add(-radius.AlongX()).RevolveAroundAxis(Vector3.UnitZ, radialSegments); - - public static VimMesh Cylinder = RevolvedVerticalCylinder(5, 1, 4, 12); - public static VimMesh[] AllMeshes = { XYTriangle, // 0 XYQuad, // 1 @@ -51,7 +46,6 @@ static VimMesh RevolvedVerticalCylinder(float height, float radius, int vertical XYQuad2x2, // 3 Tetrahedron, // 4 Torus, // 5 - Cylinder, // 6 XYTriangleTwice, // 7 }; @@ -230,7 +224,7 @@ public static void TriangleSerializationTest() //TODO: Check the need for this test. // Serializing a triangle is that a use case ? - var mesh = new VimMesh(new [] { 0, 1, 2 }, new[] + var mesh = new VimMesh(new[] { 0, 1, 2 }, new[] { new Vector3(0, 0, 0), new Vector3(0, 1, 0), From dbfcfdd697873b8eb8760229479a2f5dfcc4a02d Mon Sep 17 00:00:00 2001 From: simon Date: Mon, 15 Apr 2024 16:13:21 -0400 Subject: [PATCH 174/204] iarray -> array --- src/cs/vim/Vim.Format/ObjectModel/ElementInfo.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/cs/vim/Vim.Format/ObjectModel/ElementInfo.cs b/src/cs/vim/Vim.Format/ObjectModel/ElementInfo.cs index f8f40bac..df7755cb 100644 --- a/src/cs/vim/Vim.Format/ObjectModel/ElementInfo.cs +++ b/src/cs/vim/Vim.Format/ObjectModel/ElementInfo.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using Vim.LinqArray; namespace Vim.Format.ObjectModel @@ -29,8 +30,8 @@ public int FamilyInstanceIndex } } - private IArray _parameterIndices; - public IArray ParameterIndices + private int[] _parameterIndices; + public int[] ParameterIndices { get { @@ -39,7 +40,7 @@ public IArray ParameterIndices _parameterIndices = (DocumentModel.ElementIndexMaps.ParameterIndicesFromElementIndex .TryGetValue(ElementIndex, out var parameterIndices) ? parameterIndices : new List()) - .ToIArray(); + .ToArray(); return _parameterIndices; } @@ -108,7 +109,7 @@ public bool IsSystem public Family Family => DocumentModel.FamilyList.ElementAtOrDefault(FamilyIndex); public System System => DocumentModel.SystemList.ElementAtOrDefault(SystemIndex); public Element SystemElement => DocumentModel.ElementList.ElementAtOrDefault(SystemElementIndex); - public IEnumerable Parameters => DocumentModel.ParameterList.SelectByIndex(ParameterIndices).ToEnumerable(); + public IEnumerable Parameters => ParameterIndices.Select(i => DocumentModel.ParameterList[i]); [Flags] public enum ParameterScope From 2908d93166c0fcf1a20a61829846179bea68cbd6 Mon Sep 17 00:00:00 2001 From: simon Date: Mon, 15 Apr 2024 16:32:39 -0400 Subject: [PATCH 175/204] iarray -> array --- src/cs/vim/Vim.Format/ObjectModel/Validation.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cs/vim/Vim.Format/ObjectModel/Validation.cs b/src/cs/vim/Vim.Format/ObjectModel/Validation.cs index 24fb6399..1e6167da 100644 --- a/src/cs/vim/Vim.Format/ObjectModel/Validation.cs +++ b/src/cs/vim/Vim.Format/ObjectModel/Validation.cs @@ -265,7 +265,7 @@ void ValidateDVector3Domain(string label, DVector3 value, DVector3 lowerInclusiv } public static Dictionary> GetViewToElementsMap( - this IArray elementInViewList) + this ElementInView[] elementInViewList) => elementInViewList .Select(eiv => (viewIndex: eiv._View?.Index ?? -1, elementIndex: eiv._Element?.Index ?? -1)) .GroupBy(t => t.viewIndex) @@ -275,7 +275,7 @@ public static Dictionary> GetViewToElementsMap( public static void ValidateShapesInView(this DocumentModel dm) { - var viewToElementsMap = dm.ElementInViewList.GetViewToElementsMap(); + var viewToElementsMap = dm.ElementInViewList.ToArray().GetViewToElementsMap(); // Validate that the shapes in view have an element which is also in the same view. foreach (var item in dm.ShapeInViewList.ToEnumerable()) From 169a31a9f5789819bb4574c3cca3fee530b12cbd Mon Sep 17 00:00:00 2001 From: simon Date: Mon, 15 Apr 2024 16:32:48 -0400 Subject: [PATCH 176/204] removed dead code --- src/cs/vim/Vim.Format.Core/Geometry/Primitives.cs | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/src/cs/vim/Vim.Format.Core/Geometry/Primitives.cs b/src/cs/vim/Vim.Format.Core/Geometry/Primitives.cs index 24ca7bf3..6dcc346e 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/Primitives.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/Primitives.cs @@ -280,20 +280,5 @@ public static VimMesh QuadMesh(this Func f, int usegs, int vse return VimMesh.FromQuad(indices, verts.ToArray()); } - - /// - /// Creates a revolved face ... note that the last points are on top of the original - /// - public static VimMesh RevolveAroundAxis(this IArray points, Vector3 axis, int segments = 4) - { - var verts = new List(); - for (var i = 0; i < segments; ++i) - { - var angle = Math3d.Constants.TwoPi / segments; - points.Rotate(axis, angle).AddTo(verts); - } - var indices = ComputeQuadMeshStripIndices(segments - 1, points.Count - 1); - return new VimMesh(indices, verts.ToArray()); - } } } From 6f1f9ff3a28ceb2564d12f2a940e6c84c6da4c16 Mon Sep 17 00:00:00 2001 From: simon Date: Tue, 16 Apr 2024 07:22:06 -0400 Subject: [PATCH 177/204] iarray -> array --- .../DocumentBuilderExtensions.cs | 8 +- src/cs/vim/Vim.Format.Core/G3dBuilder.cs | 10 +- .../Vim.Format.Core/Geometry/CatmullClark.cs | 36 +++--- .../Geometry/MeshOptimization.cs | 2 +- .../Geometry/PerimeterProjection.cs | 10 +- .../Vim.Format.Core/Geometry/Primitives.cs | 16 +-- .../vim/Vim.Format.Core/Geometry/VimMesh.cs | 112 ++++++++---------- .../Geometry/GeometryTests.cs | 76 ++++++------ .../vim/Vim.Format/SceneBuilder/VimScene.cs | 2 +- .../Vim.Format/SceneBuilder/VimSceneNode.cs | 6 +- 10 files changed, 133 insertions(+), 145 deletions(-) diff --git a/src/cs/vim/Vim.Format.Core/DocumentBuilderExtensions.cs b/src/cs/vim/Vim.Format.Core/DocumentBuilderExtensions.cs index 27597945..a8bf6e51 100644 --- a/src/cs/vim/Vim.Format.Core/DocumentBuilderExtensions.cs +++ b/src/cs/vim/Vim.Format.Core/DocumentBuilderExtensions.cs @@ -11,10 +11,10 @@ public static class DocumentBuilderExtensions { public static SubdividedMesh ToDocumentBuilderSubdividedMesh(this VimMesh m) => new SubdividedMesh( - m.Indices.ToList(), - m.Vertices.ToList(), - m.SubmeshIndexOffsets.ToList(), - m.SubmeshMaterials.ToList()); + m.indices, + m.vertices, + m.submeshIndexOffsets, + m.submeshMaterials); public static EntityTableBuilder CreateTableCopy(this DocumentBuilder db, EntityTable table, List nodeIndexRemapping = null) { diff --git a/src/cs/vim/Vim.Format.Core/G3dBuilder.cs b/src/cs/vim/Vim.Format.Core/G3dBuilder.cs index daca69a3..f2cd62d4 100644 --- a/src/cs/vim/Vim.Format.Core/G3dBuilder.cs +++ b/src/cs/vim/Vim.Format.Core/G3dBuilder.cs @@ -48,12 +48,12 @@ public AABox GetBox(int meshIndex) public int[] GetVertexCounts() { - return _meshes.Select(m => m.Vertices.Count).ToArray(); + return _meshes.Select(m => m.vertices.Length).ToArray(); } public int[] GetFaceCounts() { - return _meshes.Select(m => m.Indices.Count / 3).ToArray(); + return _meshes.Select(m => m.NumFaces).ToArray(); } @@ -72,8 +72,8 @@ public BFast ToBFast() 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; + meshVertexOffsets[i] = meshVertexOffsets[i - 1] + _meshes[i - 1].vertices.Length; + meshIndexOffsets[i] = meshIndexOffsets[i - 1] + _meshes[i - 1].indices.Length; meshSubmeshOffset[i] = meshSubmeshOffset[i - 1] + _meshes[i - 1].SubmeshCount; } @@ -85,7 +85,7 @@ public BFast ToBFast() { submeshIndexOffsets[subIndex++] = sub + previousIndexCount; } - previousIndexCount += geo.Indices.Count; + previousIndexCount += geo.indices.Length; } // Compute the shape vertex offsets diff --git a/src/cs/vim/Vim.Format.Core/Geometry/CatmullClark.cs b/src/cs/vim/Vim.Format.Core/Geometry/CatmullClark.cs index 48c2ac77..30142230 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/CatmullClark.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/CatmullClark.cs @@ -48,7 +48,7 @@ public static Dictionary CreateEdgeMap(this VimMe var faceSize = 3; for (var edgeIndex = 0; edgeIndex < faceSize; edgeIndex++) { - var geometryEdgeKey = new GeometryEdgeKey(geometry.Indices[currentIndex + edgeIndex], geometry.Indices[currentIndex + (edgeIndex + 1) % faceSize]); + var geometryEdgeKey = new GeometryEdgeKey(geometry.indices[currentIndex + edgeIndex], geometry.indices[currentIndex + (edgeIndex + 1) % faceSize]); if (edgeMap.ContainsKey(geometryEdgeKey)) { edgeMap[geometryEdgeKey].Face1 = faceIndex; @@ -72,16 +72,16 @@ public static VimMesh CatmullClark(this VimMesh geometry, float smoothing = 0.0f var edgeMap = geometry.CreateEdgeMap(); var numQuads = geometry.NumFaces * 3; - var numVertices = geometry.Vertices.Count + edgeMap.Count + geometry.NumFaces; + var numVertices = geometry.vertices.Length + edgeMap.Count + geometry.NumFaces; var facePoints = new Vector3[geometry.NumFaces]; - var vertexFPoints = new Vector3[geometry.Vertices.Count]; - var vertexRPoints = new Vector3[geometry.Vertices.Count]; - var vertexNumFaces = new float[geometry.Vertices.Count]; - var vertexNumEdges = new float[geometry.Vertices.Count]; + var vertexFPoints = new Vector3[geometry.vertices.Length]; + var vertexRPoints = new Vector3[geometry.vertices.Length]; + var vertexNumFaces = new float[geometry.vertices.Length]; + var vertexNumEdges = new float[geometry.vertices.Length]; var newVertices = new Vector3[numVertices]; var newIndices = new int[numQuads * 4]; - var edgeVertices = new bool[geometry.Vertices.Count]; + var edgeVertices = new bool[geometry.vertices.Length]; foreach (var edge in edgeMap) { @@ -112,7 +112,7 @@ public static VimMesh CatmullClark(this VimMesh geometry, float smoothing = 0.0f CalculateEdgePoints(geometry, edgeMap, facePoints, vertexNumEdges, vertexRPoints, smoothing); CalculateVertexPoints(geometry, vertexNumFaces, vertexFPoints, vertexNumEdges, vertexRPoints, newVertices, edgeVertices, smoothing); - var facePointStartIndex = geometry.Vertices.Count; + var facePointStartIndex = geometry.vertices.Length; var edgePointStartIndex = facePointStartIndex + facePoints.Length; // Copy all points into a single buffer @@ -139,8 +139,8 @@ public static void CalculateFaceCentroidPoints(VimMesh geometry, Vector3[] outFa for (var edgeIndex = 0; edgeIndex < faceSize; edgeIndex++) { - var vertexIndex = geometry.Indices[currentVertexIndex + edgeIndex]; - facePoint += geometry.Vertices[vertexIndex]; + var vertexIndex = geometry.indices[currentVertexIndex + edgeIndex]; + facePoint += geometry.vertices[vertexIndex]; } facePoint /= faceSize; @@ -149,7 +149,7 @@ public static void CalculateFaceCentroidPoints(VimMesh geometry, Vector3[] outFa for (var edgeIndex = 0; edgeIndex < faceSize; edgeIndex++) { - var vertexIndex = geometry.Indices[currentVertexIndex + edgeIndex]; + var vertexIndex = geometry.indices[currentVertexIndex + edgeIndex]; outVertexNumFaces[vertexIndex]++; outVertexFPoints[vertexIndex] += facePoint; } @@ -163,7 +163,7 @@ public static void CalculateEdgePoints(VimMesh geometry, Dictionary= 0 && edge.Value.Face1 >= 0) @@ -187,13 +187,13 @@ public static void CalculateEdgePoints(VimMesh geometry, Dictionary, int> BuildEdgeDictionary(this VimMesh { var edges = new Dictionary, int>(new EdgeEqualityComparer()); - var indices = mesh.Indices; + var indices = mesh.indices; - for (var i = 0; i < indices.Count; i += 3) + for (var i = 0; i < indices.Length; i += 3) { var i0 = indices[i + 0]; var i1 = indices[i + 1]; @@ -330,10 +330,10 @@ public static List> BuildBoundarySegments(this VimMesh mesh, Dicti { var segments = new List>(); - var indices = mesh.Indices; - var vertices = mesh.Vertices; + var indices = mesh.indices; + var vertices = mesh.vertices; - for (var i = 0; i < indices.Count; i += 3) + for (var i = 0; i < indices.Length; i += 3) { var i0 = indices[i + 0]; var i1 = indices[i + 1]; diff --git a/src/cs/vim/Vim.Format.Core/Geometry/Primitives.cs b/src/cs/vim/Vim.Format.Core/Geometry/Primitives.cs index 6dcc346e..efd44cd3 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/Primitives.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/Primitives.cs @@ -107,11 +107,11 @@ public static VimMesh Sphere(float radius, int uSegs, int vSegs) /// /// Returns a collection of circular points. /// - public static IArray CirclePoints(float radius, int numPoints) - => CirclePoints(numPoints).Select(x => x * radius); + public static Vector2[] CirclePoints(float radius, int numPoints) + => CirclePoints(numPoints).Select(x => x * radius).ToArray(); - public static IArray CirclePoints(int numPoints) - => numPoints.Select(i => CirclePoint(i, numPoints)); + public static Vector2[] CirclePoints(int numPoints) + => numPoints.Select(i => CirclePoint(i, numPoints)).ToArray(); public static Vector2 CirclePoint(int i, int numPoints) => new Vector2((i * (Math3d.Constants.TwoPi / numPoints)).Cos(), (i * (Math3d.Constants.TwoPi / numPoints)).Sin()); @@ -150,7 +150,7 @@ public static int[] ComputeQuadMeshStripIndices(int usegs, int vsegs, bool wrapU /// Returns the index buffer of a quad mesh strip. /// Returns an empty array if either numRowPoints or numPointsPerRow is less than 2. /// - public static IArray QuadMeshStripIndicesFromPointRows( + public static int[] QuadMeshStripIndicesFromPointRows( int numPointRows, int numPointsPerRow, bool clockwise = false) @@ -206,10 +206,10 @@ public static IArray QuadMeshStripIndicesFromPointRows( } } - return indices.ToIArray(); + return indices.ToArray(); } - public static IArray TriMeshCylinderCapIndices(int numEdgeVertices) + public static int[] TriMeshCylinderCapIndices(int numEdgeVertices) { // Example cap where numEdgeVertices is 6: // @@ -249,7 +249,7 @@ public static IArray TriMeshCylinderCapIndices(int numEdgeVertices) indices.Add(lastTriangleIndex1); indices.Add(lastTriangleIndex2); - return indices.ToIArray(); + return indices.ToArray(); } /// diff --git a/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs b/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs index 719d9a8f..0f1989a3 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs @@ -10,14 +10,6 @@ namespace Vim.Format.Geometry { public class VimMesh : ITransformable3D { - public IArray Vertices => vertices.ToIArray(); - - public IArray Indices => indices.ToIArray(); - - public IArray SubmeshMaterials => submeshMaterials.ToIArray(); - public IArray SubmeshIndexOffsets => submeshIndexOffsets.ToIArray(); - public IArray SubmeshIndexCounts => submeshIndexCounts.ToIArray(); - public int SubmeshCount => submeshIndexCounts.Length; public int NumCornersPerFace => 3; @@ -28,13 +20,6 @@ public class VimMesh : ITransformable3D public int NumFaces => indices.Length / 3; - public int NumInstances => 0; - - public int NumMeshes => 1; - - public int NumShapeVertices => 0; - - public int NumShapes => 0; public int[] indices; public Vector3[] vertices; @@ -42,6 +27,10 @@ public class VimMesh : ITransformable3D public int[] submeshMaterials; public int[] submeshIndexCounts; + public int GetIndexCount() => indices.Length; + public int GetVertexCount() => vertices.Length; + + public VimMesh() { @@ -227,7 +216,7 @@ public void Validate() } private void ValidateIndices() { - foreach (var index in Indices.ToEnumerable()) + foreach (var index in indices) { if (index < 0 || index >= NumVertices) throw new Exception($"Invalid mesh index: {index}. Expected a value greater or equal to 0 and less than {NumVertices}"); @@ -240,20 +229,20 @@ public static class MeshCommonExtensions public static VimMesh ReverseWindingOrder(this VimMesh mesh) { var result = mesh.Clone(); - var count = mesh.Indices.Count; + var count = mesh.indices.Length; var indices = new int[count]; for (var i = 0; i < count; i += 3) { - indices[i + 0] = mesh.Indices[i + 2]; - indices[i + 1] = mesh.Indices[i + 1]; - indices[i + 2] = mesh.Indices[i + 0]; + indices[i + 0] = mesh.indices[i + 2]; + indices[i + 1] = mesh.indices[i + 1]; + indices[i + 2] = mesh.indices[i + 0]; } result.SetIndices(indices); return result; } - public static IArray GetFaceMaterials(this VimMesh mesh) + public static int[] GetFaceMaterials(this VimMesh mesh) { // SubmeshIndexOffsets: [0, A, B] // SubmeshIndexCount: [X, Y, Z] @@ -261,10 +250,9 @@ public static IArray GetFaceMaterials(this VimMesh mesh) // --- // FaceMaterials: [...Repeat(L, X / 3), ...Repeat(M, Y / 3), ...Repeat(N, Z / 3)] <-- divide by 3 for the number of corners per Triangular face var numCornersPerFace = mesh.NumCornersPerFace; - return mesh.SubmeshIndexCounts - .ToEnumerable() - .SelectMany((indexCount, i) => Enumerable.Repeat(mesh.SubmeshMaterials[i], indexCount / numCornersPerFace)) - .ToIArray(); + return mesh.submeshIndexCounts + .SelectMany((indexCount, i) => Enumerable.Repeat(mesh.submeshMaterials[i], indexCount / numCornersPerFace)) + .ToArray(); } public static VimMesh Merge2(this VimMesh mesh, params VimMesh[] others) @@ -279,18 +267,18 @@ public static VimMesh Merge2(this VimMesh mesh, params VimMesh[] others) public static VimMesh Merge(this VimMesh[] meshes) { - void Merge(IArray from, int[] to, int offset, int increment) + void Merge(int[] from, int[] to, int offset, int increment) { - for (var i = 0; i < from.Count; i++) + for (var i = 0; i < from.Length; i++) { to[i + offset] = from[i] + increment; } } // Init arrays - var indexCount = meshes.Sum(m => m.Indices.Count); - var vertexCount = meshes.Sum(m => m.Vertices.Count); - var submeshCount = meshes.Sum(m => m.SubmeshIndexOffsets.Count); + var indexCount = meshes.Sum(m => m.indices.Length); + var vertexCount = meshes.Sum(m => m.vertices.Length); + var submeshCount = meshes.Sum(m => m.submeshIndexOffsets.Length); var result = new VimMesh(indexCount, vertexCount, submeshCount); var indexOffset = 0; @@ -301,15 +289,15 @@ void Merge(IArray from, int[] to, int offset, int increment) { var mesh = meshes[m]; - Merge(mesh.Indices, result.indices, indexOffset, vertexOffset); - mesh.Vertices.CopyTo(result.vertices, vertexOffset); - mesh.SubmeshMaterials.CopyTo(result.submeshMaterials, submeshOffset); - mesh.SubmeshIndexCounts.CopyTo(result.submeshIndexCounts, submeshOffset); - Merge(mesh.SubmeshIndexOffsets, result.submeshIndexOffsets, submeshOffset, indexOffset); + Merge(mesh.indices, result.indices, indexOffset, vertexOffset); + mesh.vertices.CopyTo(result.vertices, vertexOffset); + mesh.submeshMaterials.CopyTo(result.submeshMaterials, submeshOffset); + mesh.submeshIndexCounts.CopyTo(result.submeshIndexCounts, submeshOffset); + Merge(mesh.submeshIndexOffsets, result.submeshIndexOffsets, submeshOffset, indexOffset); - indexOffset += mesh.Indices.Count; - vertexOffset += mesh.Vertices.Count; - submeshOffset += mesh.SubmeshIndexOffsets.Count; + indexOffset += mesh.indices.Length; + vertexOffset += mesh.vertices.Length; + submeshOffset += mesh.submeshIndexOffsets.Length; } return result; @@ -322,11 +310,11 @@ public static VimMesh[] SplitSubmeshes(this VimMesh mesh) public static (int, List)[] GroupSubmeshesByMaterials(this VimMesh mesh) { - var submeshCount = mesh.SubmeshIndexOffsets.Count; + var submeshCount = mesh.submeshIndexOffsets.Length; var map = new Dictionary>(); for (var i = 0; i < submeshCount; i++) { - var mat = mesh.SubmeshMaterials[i]; + var mat = mesh.submeshMaterials[i]; if (map.ContainsKey(mat)) { map[mat].Add(i); @@ -340,7 +328,7 @@ public static (int, List)[] GroupSubmeshesByMaterials(this VimMesh mesh) } public static Triangle VertexIndicesToTriangle(this VimMesh mesh, Int3 indices) - => new Triangle(mesh.Vertices[indices.X], mesh.Vertices[indices.Y], mesh.Vertices[indices.Z]); + => new Triangle(mesh.vertices[indices.X], mesh.vertices[indices.Y], mesh.vertices[indices.Z]); public static bool Planar(this VimMesh mesh, float tolerance = Math3d.Constants.Tolerance) { @@ -351,48 +339,48 @@ public static bool Planar(this VimMesh mesh, float tolerance = Math3d.Constants. public static VimMesh Unindex(this VimMesh mesh) { - var vertices = mesh.Indices.Select(i => mesh.Vertices[i]); + var vertices = mesh.indices.Select(i => mesh.vertices[i]); return new VimMesh(vertices.ToArray()); } - public static IArray ComputedNormals(this VimMesh mesh) - => mesh.Triangles().Select(t => t.Normal); + public static Vector3[] ComputedNormals(this VimMesh mesh) + => mesh.Triangles().Select(t => t.Normal).ToArray(); public static Triangle Triangle(this VimMesh mesh, int face) => mesh.VertexIndicesToTriangle(mesh.FaceVertexIndices(face)); - public static IArray Triangles(this VimMesh mesh) - => mesh.NumFaces.Select(mesh.Triangle); + public static Triangle[] Triangles(this VimMesh mesh) + => Enumerable.Range(0, mesh.NumFaces).Select(mesh.Triangle).ToArray(); public static Vector3 Center(this VimMesh mesh) => mesh.BoundingBox().Center; public static AABox BoundingBox(this VimMesh mesh) - => AABox.Create(mesh.Vertices.ToEnumerable()); + => AABox.Create(mesh.vertices); public static Int3 FaceVertexIndices(this VimMesh mesh, int faceIndex) - => new Int3(mesh.Indices[faceIndex * 3], mesh.Indices[faceIndex * 3 + 1], mesh.Indices[faceIndex * 3 + 2]); + => new Int3(mesh.indices[faceIndex * 3], mesh.indices[faceIndex * 3 + 1], mesh.indices[faceIndex * 3 + 2]); public static bool GeometryEquals(this VimMesh mesh, VimMesh other, float tolerance = Math3d.Constants.Tolerance) { - if (!mesh.Indices.SequenceEquals(other.Indices)) + if (!mesh.indices.SequenceEqual(other.indices)) return false; - if (!mesh.SubmeshIndexOffsets.SequenceEquals(other.SubmeshIndexOffsets)) + if (!mesh.submeshIndexOffsets.SequenceEqual(other.submeshIndexOffsets)) return false; - if (!mesh.SubmeshMaterials.SequenceEquals(other.SubmeshMaterials)) + if (!mesh.submeshMaterials.SequenceEqual(other.submeshMaterials)) return false; - if (!mesh.SubmeshIndexCounts.SequenceEquals(other.SubmeshIndexCounts)) + if (!mesh.submeshIndexCounts.SequenceEqual(other.submeshIndexCounts)) return false; - if (mesh.Vertices.Count != other.Vertices.Count) + if (mesh.vertices.Length != other.vertices.Length) return false; - for (var i = 0; i < mesh.Vertices.Count; i++) + for (var i = 0; i < mesh.vertices.Length; i++) { - if (!mesh.Vertices[i].AlmostEquals(other.Vertices[i], tolerance)) + if (!mesh.vertices[i].AlmostEquals(other.vertices[i], tolerance)) return false; } @@ -406,7 +394,7 @@ public static (int mat, VimMesh mesh)[] SplitByMaterial(this VimMesh mesh) var result = new (int, VimMesh)[map.Length]; if (map.Length == 1) { - result[0] = (mesh.SubmeshMaterials[0], mesh); + result[0] = (mesh.submeshMaterials[0], mesh); return result; } @@ -424,7 +412,7 @@ public static VimMesh PickSubmeshes(this VimMesh mesh, IList submeshes) var map = mesh.GroupSubmeshesByMaterials(); // Allocate arrays of the final sizes - var indexCount = submeshes.Sum(s => mesh.SubmeshIndexCounts[s]); + var indexCount = submeshes.Sum(s => mesh.submeshIndexCounts[s]); var result = new VimMesh(indexCount, indexCount, submeshes.Count); var indexOffset = 0; @@ -434,18 +422,18 @@ public static VimMesh PickSubmeshes(this VimMesh mesh, IList submeshes) var submesh = submeshes[s]; // copy indices at their new positions - var indexStart = mesh.SubmeshIndexOffsets[submesh]; - var indexEnd = indexStart + mesh.SubmeshIndexCounts[submesh]; + var indexStart = mesh.submeshIndexOffsets[submesh]; + var indexEnd = indexStart + mesh.submeshIndexCounts[submesh]; for (var i = indexStart; i < indexEnd; i++) { result.indices[index] = indexOffset + i - indexStart; - result.vertices[index] = mesh.Vertices[mesh.Indices[i]]; + result.vertices[index] = mesh.vertices[mesh.indices[i]]; index++; } // submesh data is mostly the same - result.submeshIndexCounts[s] = mesh.SubmeshIndexCounts[submesh]; - result.submeshMaterials[s] = mesh.SubmeshMaterials[submesh]; + result.submeshIndexCounts[s] = mesh.submeshIndexCounts[submesh]; + result.submeshMaterials[s] = mesh.submeshMaterials[submesh]; result.submeshIndexOffsets[s] = indexOffset; // Update offset for next submesh diff --git a/src/cs/vim/Vim.Format.Tests/Geometry/GeometryTests.cs b/src/cs/vim/Vim.Format.Tests/Geometry/GeometryTests.cs index 26a82403..7dc3c74a 100644 --- a/src/cs/vim/Vim.Format.Tests/Geometry/GeometryTests.cs +++ b/src/cs/vim/Vim.Format.Tests/Geometry/GeometryTests.cs @@ -72,42 +72,42 @@ public static void BasicTests() Assert.AreEqual(3, XYTriangle.NumCornersPerFace); Assert.AreEqual(1, XYTriangle.NumFaces); - Assert.AreEqual(3, XYTriangle.Vertices.Count); - Assert.AreEqual(3, XYTriangle.Indices.Count); + Assert.AreEqual(3, XYTriangle.vertices.Length); + Assert.AreEqual(3, XYTriangle.indices.Length); Assert.AreEqual(1, XYTriangle.Triangles().Count); Assert.IsTrue(XYTriangle.Planar()); - Assert.AreEqual(new[] { 0, 1, 2 }, XYTriangle.Indices.ToArray()); + Assert.AreEqual(new[] { 0, 1, 2 }, XYTriangle.indices.Length); Assert.AreEqual(3, XYQuad.NumCornersPerFace); Assert.AreEqual(2, XYQuad.NumFaces); - Assert.AreEqual(4, XYQuad.Vertices.Count); - Assert.AreEqual(6, XYQuad.Indices.Count); + Assert.AreEqual(4, XYQuad.vertices.Length); + Assert.AreEqual(6, XYQuad.indices.Length); Assert.IsTrue(XYQuad.Planar()); - Assert.AreEqual(new[] { 0, 1, 2, 0, 2, 3 }, XYQuad.Indices.ToArray()); + Assert.AreEqual(new[] { 0, 1, 2, 0, 2, 3 }, XYQuad.indices.ToArray()); Assert.AreEqual(3, XYQuadFromFunc.NumCornersPerFace); Assert.AreEqual(2, XYQuadFromFunc.NumFaces); - Assert.AreEqual(4, XYQuadFromFunc.Vertices.Count); - Assert.AreEqual(6, XYQuadFromFunc.Indices.Count); + Assert.AreEqual(4, XYQuadFromFunc.vertices.Length); + Assert.AreEqual(6, XYQuadFromFunc.indices.Length); Assert.AreEqual(3, XYQuad2x2.NumCornersPerFace); Assert.AreEqual(8, XYQuad2x2.NumFaces); - Assert.AreEqual(9, XYQuad2x2.Vertices.Count); - Assert.AreEqual(24, XYQuad2x2.Indices.Count); + Assert.AreEqual(9, XYQuad2x2.vertices.Length); + Assert.AreEqual(24, XYQuad2x2.indices.Length); Assert.AreEqual(3, Tetrahedron.NumCornersPerFace); Assert.AreEqual(4, Tetrahedron.NumFaces); - Assert.AreEqual(4, Tetrahedron.Vertices.Count); - Assert.AreEqual(12, Tetrahedron.Indices.Count); + Assert.AreEqual(4, Tetrahedron.vertices.Length); + Assert.AreEqual(12, Tetrahedron.indices.Length); Assert.AreEqual(3, XYTriangleTwice.NumCornersPerFace); Assert.AreEqual(2, XYTriangleTwice.NumFaces); - Assert.AreEqual(6, XYTriangleTwice.Vertices.Count); - Assert.AreEqual(6, XYTriangleTwice.Indices.Count); + Assert.AreEqual(6, XYTriangleTwice.vertices.Length); + Assert.AreEqual(6, XYTriangleTwice.indices.Length); Assert.AreEqual(2, XYTriangleTwice.Triangles().Count); Assert.IsTrue(XYTriangleTwice.Planar()); - Assert.AreEqual(new[] { 0, 1, 2, 3, 4, 5 }, XYTriangleTwice.Indices.ToArray()); + Assert.AreEqual(new[] { 0, 1, 2, 3, 4, 5 }, XYTriangleTwice.indices); } [Test] @@ -124,16 +124,16 @@ public static void OutputGeometryData() foreach (var g in AllMeshes) { Console.WriteLine($"Geometry {n++}"); - for (var i = 0; i < g.Vertices.Count && i < 10; ++i) + for (var i = 0; i < g.vertices.Length && i < 10; ++i) { - Console.WriteLine($"Vertex {i} {g.Vertices[i]}"); + Console.WriteLine($"Vertex {i} {g.vertices[i]}"); } - if (g.Vertices.Count > 10) + if (g.vertices.Length > 10) { - var last = g.Vertices.Count - 1; + var last = g.vertices.Length - 1; Console.WriteLine("..."); - Console.WriteLine($"Vertex {last} {g.Vertices[last]}"); + Console.WriteLine($"Vertex {last} {g.vertices[last]}"); } for (var i = 0; i < g.NumFaces && i < 10; ++i) @@ -141,7 +141,7 @@ public static void OutputGeometryData() Console.WriteLine($"Face {i}: {g.Triangle(i)}"); } - if (g.Vertices.Count > 10) + if (g.vertices.Length > 10) { var last = g.NumFaces - 1; Console.WriteLine("..."); @@ -154,22 +154,22 @@ public static void OutputGeometryData() public static void StripIndicesTests() { var emptyStrip00 = Primitives.QuadMeshStripIndicesFromPointRows(0, 0); - Assert.AreEqual(0, emptyStrip00.Count); + Assert.AreEqual(0, emptyStrip00.Length); var emptyStrip01 = Primitives.QuadMeshStripIndicesFromPointRows(0, 1); - Assert.AreEqual(0, emptyStrip01.Count); + Assert.AreEqual(0, emptyStrip01.Length); var emptyStrip10 = Primitives.QuadMeshStripIndicesFromPointRows(1, 0); - Assert.AreEqual(0, emptyStrip10.Count); + Assert.AreEqual(0, emptyStrip10.Length); var emptyStrip11 = Primitives.QuadMeshStripIndicesFromPointRows(1, 1); - Assert.AreEqual(0, emptyStrip11.Count); + Assert.AreEqual(0, emptyStrip11.Length); var emptyStrip12 = Primitives.QuadMeshStripIndicesFromPointRows(1, 2); - Assert.AreEqual(0, emptyStrip12.Count); + Assert.AreEqual(0, emptyStrip12.Length); var emptyStrip21 = Primitives.QuadMeshStripIndicesFromPointRows(2, 1); - Assert.AreEqual(0, emptyStrip21.Count); + Assert.AreEqual(0, emptyStrip21.Length); // COUNTER-CLOCKWISE TEST (DEFAULT) // 2------3 <--- row 1: [2,3] @@ -177,7 +177,7 @@ public static void StripIndicesTests() // | | // 0------1 <--- row 0: [0,1] var strip22 = Primitives.QuadMeshStripIndicesFromPointRows(2, 2); - Assert.AreEqual(4, strip22.Count); + Assert.AreEqual(4, strip22.Length); Assert.AreEqual(0, strip22[0]); Assert.AreEqual(1, strip22[1]); Assert.AreEqual(3, strip22[2]); @@ -189,13 +189,13 @@ public static void StripIndicesTests() // | | // 0------1 <--- row 0: [0,1] var clockwiseStrip22 = Primitives.QuadMeshStripIndicesFromPointRows(2, 2, true); - Assert.AreEqual(4, clockwiseStrip22.Count); + Assert.AreEqual(4, clockwiseStrip22.Length); Assert.AreEqual(2, clockwiseStrip22[0]); Assert.AreEqual(3, clockwiseStrip22[1]); Assert.AreEqual(1, clockwiseStrip22[2]); Assert.AreEqual(0, clockwiseStrip22[3]); - var reversed22 = clockwiseStrip22.Reverse(); - for (var i = 0; i < strip22.Count; ++i) + var reversed22 = clockwiseStrip22.Reverse().ToArray(); + for (var i = 0; i < strip22.Length; ++i) { Assert.AreEqual(strip22[i], reversed22[i]); } @@ -205,7 +205,7 @@ public static void StripIndicesTests() // | | | // *------*------* var strip23 = Primitives.QuadMeshStripIndicesFromPointRows(2, 3); - Assert.AreEqual(4 * 2, strip23.Count); + Assert.AreEqual(4 * 2, strip23.Length); // *------*------*------* // | | | | @@ -215,7 +215,7 @@ public static void StripIndicesTests() // | | | | // *------*------*------* var strip34 = Primitives.QuadMeshStripIndicesFromPointRows(3, 4); - Assert.AreEqual(4 * 6, strip34.Count); + Assert.AreEqual(4 * 6, strip34.Length); } [Test] @@ -238,12 +238,12 @@ public static void TriangleSerializationTest() result.Validate(); Assert.AreEqual(3, result.NumVertices); - Assert.AreEqual(new Vector3(0, 0, 0), result.Vertices[0]); - Assert.AreEqual(new Vector3(0, 1, 0), result.Vertices[1]); - Assert.AreEqual(new Vector3(0, 1, 1), result.Vertices[2]); + Assert.AreEqual(new Vector3(0, 0, 0), result.vertices[0]); + Assert.AreEqual(new Vector3(0, 1, 0), result.vertices[1]); + Assert.AreEqual(new Vector3(0, 1, 1), result.vertices[2]); Assert.AreEqual(1, result.NumFaces); - Assert.AreEqual(0, result.SubmeshIndexOffsets.ToEnumerable().Single()); - Assert.AreEqual(-1, result.SubmeshMaterials.ToEnumerable().Single()); + Assert.AreEqual(0, result.submeshIndexOffsets.Single()); + Assert.AreEqual(-1, result.submeshMaterials.Single()); Assert.AreEqual(-1, result.GetFaceMaterials().First()); } } diff --git a/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs b/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs index 6c0ecc96..005ea2d6 100644 --- a/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs +++ b/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs @@ -84,7 +84,7 @@ public VimMesh MergedGeometry() => Nodes.MergedGeometry(); public IEnumerable AllVertices() - => TransformedMeshes().SelectMany(g => g.Vertices.ToEnumerable()); + => TransformedMeshes().SelectMany(g => g.vertices); public AABox BoundingBox() => AABox.Create(AllVertices()); diff --git a/src/cs/vim/Vim.Format/SceneBuilder/VimSceneNode.cs b/src/cs/vim/Vim.Format/SceneBuilder/VimSceneNode.cs index 28e34077..76c0e3f4 100644 --- a/src/cs/vim/Vim.Format/SceneBuilder/VimSceneNode.cs +++ b/src/cs/vim/Vim.Format/SceneBuilder/VimSceneNode.cs @@ -54,11 +54,11 @@ VimSceneNode ITransformable3D.Transform(Matrix4x4 mat) public VimMesh TransformedMesh() => GetMesh()?.Transform(Transform); - public IArray TransformedVertices() - => TransformedMesh()?.Vertices; + public Vector3[] TransformedVertices() + => TransformedMesh()?.vertices; public AABox TransformedBoundingBox() - => AABox.Create(TransformedVertices()?.ToEnumerable()); + => AABox.Create(TransformedVertices()); } public static class NodeExtensions From 033a466cf61ce6c1a555eed15cfcf531baaa19b8 Mon Sep 17 00:00:00 2001 From: simon Date: Tue, 16 Apr 2024 08:24:55 -0400 Subject: [PATCH 178/204] iarray -> array --- src/cs/util/Vim.Util/LinqExtensions.cs | 2 +- .../ObjectModelGenerator.cs | 17 +- .../ColumnExtensions.Buffer.cs | 4 +- src/cs/vim/Vim.Format.Core/Document.cs | 5 +- .../vim/Vim.Format.Core/DocumentExtensions.cs | 4 +- src/cs/vim/Vim.Format.Core/EntityTable.cs | 21 +- .../vim/Vim.Format.Core/Geometry/ArrayOps.cs | 1 - .../Geometry/GeometryTests.cs | 4 +- .../ObjectModel/ObjectModelExtensions.cs | 12 +- .../ObjectModel/ObjectModelGenerated.cs | 1625 +++++++++-------- .../vim/Vim.Format/ObjectModel/Validation.cs | 17 +- .../SceneBuilder/VimSceneHelpers.cs | 2 +- 12 files changed, 859 insertions(+), 855 deletions(-) diff --git a/src/cs/util/Vim.Util/LinqExtensions.cs b/src/cs/util/Vim.Util/LinqExtensions.cs index ae41cd0e..56800bb0 100644 --- a/src/cs/util/Vim.Util/LinqExtensions.cs +++ b/src/cs/util/Vim.Util/LinqExtensions.cs @@ -33,7 +33,7 @@ public static T OneOrDefault(this IEnumerable values) public static IEnumerable Append(this IEnumerable xs, params T[] x) => xs.Concat(x); - public static T ElementAtOrDefault(this IReadOnlyList items, int index, T @default) + public static T ElementAtOrDefault(this IReadOnlyList items, int index, T @default = default(T)) => index < 0 || index >= items.Count ? @default : items[index]; /// diff --git a/src/cs/vim/Vim.Format.CodeGen/ObjectModelGenerator.cs b/src/cs/vim/Vim.Format.CodeGen/ObjectModelGenerator.cs index d386e613..49ce077a 100644 --- a/src/cs/vim/Vim.Format.CodeGen/ObjectModelGenerator.cs +++ b/src/cs/vim/Vim.Format.CodeGen/ObjectModelGenerator.cs @@ -71,7 +71,7 @@ private static CodeBuilder WriteDocumentEntityData(Type t, CodeBuilder cb, Entit var dataColumnGetter = $"{t.Name}EntityTable?.{functionName}(\"{eci.SerializedValueColumnName}\")"; if (eci.EntityColumnAttribute.SerializedType != fieldType) { - dataColumnGetter += $"?.Select(v => ({fieldTypeName}) v)"; + dataColumnGetter += $"?.Select(v => ({fieldTypeName}) v).ToArray()"; } return dataColumnGetter; }).ToArray(); @@ -80,9 +80,9 @@ private static CodeBuilder WriteDocumentEntityData(Type t, CodeBuilder cb, Entit ? $"({string.Join(" ?? ", dataColumnGetters)})" : dataColumnGetters[0]; - cb.AppendLine($"public IArray<{fieldTypeName}> {t.Name}{fieldName} {{ get; }}"); + cb.AppendLine($"public {fieldTypeName}[] {t.Name}{fieldName} {{ get; }}"); constructor.ArraysInitializers - .Add($"{t.Name}{fieldName} = {dataColumnGetterString} ?? Array.Empty<{fieldTypeName}>().ToIArray();"); + .Add($"{t.Name}{fieldName} = {dataColumnGetterString} ?? Array.Empty<{fieldTypeName}>();"); // Safe accessor. var defaultValue = baseStrategy == ValueSerializationStrategy.SerializeAsStringColumn ? "\"\"" : "default"; @@ -94,9 +94,9 @@ private static CodeBuilder WriteDocumentEntityData(Type t, CodeBuilder cb, Entit { var (indexColumnName, localFieldName) = fieldInfo.GetIndexColumnInfo(); - cb.AppendLine($"public IArray {t.Name}{localFieldName}Index {{ get; }}"); + cb.AppendLine($"public int[] {t.Name}{localFieldName}Index {{ get; }}"); constructor.RelationalColumns - .Add($"{t.Name}{localFieldName}Index = {t.Name}EntityTable?.GetIndexColumnValues(\"{indexColumnName}\") ?? Array.Empty().ToIArray();"); + .Add($"{t.Name}{localFieldName}Index = {t.Name}EntityTable?.GetIndexColumnValues(\"{indexColumnName}\") ?? Array.Empty();"); cb.AppendLine($"public int Get{t.Name}{localFieldName}Index(int index) => {t.Name}{localFieldName}Index?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None;"); } @@ -105,7 +105,7 @@ private static CodeBuilder WriteDocumentEntityData(Type t, CodeBuilder cb, Entit cb.AppendLine($"public int Num{t.Name} => {t.Name}EntityTable?.NumRows ?? 0;"); // Entity lists - cb.AppendLine($"public IArray<{t.Name}> {t.Name}List {{ get; }}"); + cb.AppendLine($"public {t.Name}[] {t.Name}List {{ get; }}"); // Element getter function cb.AppendLine($"public {t.Name} Get{t.Name}(int n)"); @@ -231,7 +231,7 @@ private static CodeBuilder WriteDocument(CodeBuilder cb = null) cb.AppendLine("// All entity collections"); cb.AppendLine("public Dictionary> AllEntities => new Dictionary>() {"); foreach (var t in entityTypes) - cb.AppendLine($"{{\"{t.GetEntityTableName()}\", {t.Name}List.ToEnumerable()}},"); + cb.AppendLine($"{{\"{t.GetEntityTableName()}\", {t.Name}List}},"); cb.AppendLine("};"); cb.AppendLine(); @@ -265,7 +265,7 @@ private static CodeBuilder WriteDocument(CodeBuilder cb = null) cb.AppendLine("// Initialize entity collections"); foreach (var t in entityTypes) - cb.AppendLine($"{t.Name}List = Num{t.Name}.Select(i => Get{t.Name}(i));"); + cb.AppendLine($"{t.Name}List = Enumerable.Range(0, Num{t.Name}).Select(i => Get{t.Name}(i)).ToArray();"); cb.AppendLine(); cb.AppendLine("// Initialize element index maps"); @@ -352,6 +352,7 @@ public static void WriteDocument(string file) cb.AppendLine("using Vim.Math3d;"); cb.AppendLine("using Vim.LinqArray;"); cb.AppendLine("using Vim.Format.ObjectModel;"); + cb.AppendLine("using Vim.Util;"); cb.AppendLine(); diff --git a/src/cs/vim/Vim.Format.Core/ColumnExtensions.Buffer.cs b/src/cs/vim/Vim.Format.Core/ColumnExtensions.Buffer.cs index 0b213bd8..69133ef5 100644 --- a/src/cs/vim/Vim.Format.Core/ColumnExtensions.Buffer.cs +++ b/src/cs/vim/Vim.Format.Core/ColumnExtensions.Buffer.cs @@ -196,8 +196,8 @@ public static SerializableEntityTable Concat(this SerializableEntityTable thisTa DataColumns = thisTable.DataColumns.ConcatDataColumns(otherTable.DataColumns), }.ValidateColumnRowsAreAligned(); - public static IArray GetColumnValues(this INamedBuffer nb) where T : unmanaged - => nb.AsArray().ToIArray(); + public static T[] GetColumnValues(this INamedBuffer nb) where T : unmanaged + => nb.AsArray(); /// /// Returns a new collection of index columns in which the designated column names have repeated values of VimConstants.NoEntityRelation. diff --git a/src/cs/vim/Vim.Format.Core/Document.cs b/src/cs/vim/Vim.Format.Core/Document.cs index 27a4d978..9a529d6e 100644 --- a/src/cs/vim/Vim.Format.Core/Document.cs +++ b/src/cs/vim/Vim.Format.Core/Document.cs @@ -1,6 +1,7 @@ using Vim.LinqArray; using Vim.BFastLib; using Vim.G3dNext; +using Vim.Util; namespace Vim.Format { @@ -12,7 +13,7 @@ public Document(SerializableDocument document) _Document = document; Header = _Document.Header; GeometryNext = _Document.GeometryNext; - StringTable = _Document.StringTable.ToIArray(); + StringTable = _Document.StringTable; EntityTables = _Document.EntityTables.ToLookup( et => et.Name, et => et.ToEntityTable(this)); @@ -24,7 +25,7 @@ public Document(SerializableDocument document) public SerializableHeader Header { get; } public ILookup EntityTables { get; } public ILookup Assets { get; } - public IArray StringTable { get; } + public string[] StringTable { get; } public string GetString(int index) => StringTable.ElementAtOrDefault(index); public G3dVim GeometryNext { get; } } diff --git a/src/cs/vim/Vim.Format.Core/DocumentExtensions.cs b/src/cs/vim/Vim.Format.Core/DocumentExtensions.cs index 9d7a9cfd..3ab52296 100644 --- a/src/cs/vim/Vim.Format.Core/DocumentExtensions.cs +++ b/src/cs/vim/Vim.Format.Core/DocumentExtensions.cs @@ -13,8 +13,8 @@ public static Document ToDocument(this SerializableDocument document) public static EntityTable ToEntityTable(this SerializableEntityTable entityTable, Document document) => new EntityTable(document, entityTable); - public static IArray GetColumnNames(this EntityTable table) - => table.Columns.Select(b => b.Name); + public static string[] GetColumnNames(this EntityTable table) + => table.Columns.Select(b => b.Name).ToArray(); public static void ValidateRelations(this Document doc) { diff --git a/src/cs/vim/Vim.Format.Core/EntityTable.cs b/src/cs/vim/Vim.Format.Core/EntityTable.cs index d35097cc..51551e09 100644 --- a/src/cs/vim/Vim.Format.Core/EntityTable.cs +++ b/src/cs/vim/Vim.Format.Core/EntityTable.cs @@ -1,6 +1,7 @@ using System; using Vim.LinqArray; using Vim.BFastLib; +using System.Linq; namespace Vim.Format { @@ -17,7 +18,7 @@ public EntityTable(Document document, SerializableEntityTable entityTable) StringColumns = LinqArray.LinqArray.ToLookup(_EntityTable.StringColumns, c => c.Name, c => c); NumRows = Columns.FirstOrDefault()?.NumElements() ?? 0; - Columns.ToEnumerable().ValidateColumnRowsAreAligned(); + Columns.ValidateColumnRowsAreAligned(); } private SerializableEntityTable _EntityTable { get; } @@ -27,20 +28,21 @@ public EntityTable(Document document, SerializableEntityTable entityTable) public LinqArray.ILookup DataColumns { get; } public LinqArray.ILookup> StringColumns { get; } public LinqArray.ILookup> IndexColumns { get; } - public IArray Columns + public INamedBuffer[] Columns => DataColumns.Values .Concatenate(IndexColumns.Values.Select(x => (INamedBuffer)x)) - .Concatenate(StringColumns.Values.Select(x => (INamedBuffer)x)); + .Concatenate(StringColumns.Values.Select(x => (INamedBuffer)x)) + .ToArray(); - public IArray GetIndexColumnValues(string columnName) + public int[] GetIndexColumnValues(string columnName) => IndexColumns.GetOrDefault(columnName)?.GetColumnValues(); - public IArray GetStringColumnValues(string columnName) + public string[] GetStringColumnValues(string columnName) => StringColumns.GetOrDefault(columnName) ?.GetColumnValues() - ?.Select(Document.GetString); + ?.Select(Document.GetString).ToArray(); - public IArray GetDataColumnValues(string columnName) where T : unmanaged + public T[] GetDataColumnValues(string columnName) where T : unmanaged { var type = typeof(T); @@ -52,11 +54,10 @@ public IArray GetDataColumnValues(string columnName) where T : unmanaged return null; if (type == typeof(short)) - return namedBuffer.GetColumnValues().Select(i => (short)i) as IArray; + return namedBuffer.GetColumnValues().Select(i => (short)i) as T[]; if (type == typeof(bool)) - return namedBuffer.GetColumnValues().Select(b => b != 0) as IArray; - + return namedBuffer.GetColumnValues().Select(b => b != 0) as T[]; return namedBuffer.GetColumnValues(); } } diff --git a/src/cs/vim/Vim.Format.Core/Geometry/ArrayOps.cs b/src/cs/vim/Vim.Format.Core/Geometry/ArrayOps.cs index 55bbcedb..d77a7f5a 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/ArrayOps.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/ArrayOps.cs @@ -10,7 +10,6 @@ namespace Vim.Format.Geometry { public static class ArrayOps { - public static IArray< int > Add(this IArray< int > self, IArray< int > other) => self.Zip(other, MathOps.Add); public static IArray< int > Add(this IArray< int > self, int scalar) => self.Select(x => MathOps.Add(x, scalar)); public static IArray< int > Add(this int self, IArray< int > vector) => vector.Select(x => MathOps.Add(self, x)); diff --git a/src/cs/vim/Vim.Format.Tests/Geometry/GeometryTests.cs b/src/cs/vim/Vim.Format.Tests/Geometry/GeometryTests.cs index 7dc3c74a..3850be40 100644 --- a/src/cs/vim/Vim.Format.Tests/Geometry/GeometryTests.cs +++ b/src/cs/vim/Vim.Format.Tests/Geometry/GeometryTests.cs @@ -74,7 +74,7 @@ public static void BasicTests() Assert.AreEqual(1, XYTriangle.NumFaces); Assert.AreEqual(3, XYTriangle.vertices.Length); Assert.AreEqual(3, XYTriangle.indices.Length); - Assert.AreEqual(1, XYTriangle.Triangles().Count); + Assert.AreEqual(1, XYTriangle.Triangles().Length); Assert.IsTrue(XYTriangle.Planar()); Assert.AreEqual(new[] { 0, 1, 2 }, XYTriangle.indices.Length); @@ -105,7 +105,7 @@ public static void BasicTests() Assert.AreEqual(2, XYTriangleTwice.NumFaces); Assert.AreEqual(6, XYTriangleTwice.vertices.Length); Assert.AreEqual(6, XYTriangleTwice.indices.Length); - Assert.AreEqual(2, XYTriangleTwice.Triangles().Count); + Assert.AreEqual(2, XYTriangleTwice.Triangles().Length); Assert.IsTrue(XYTriangleTwice.Planar()); Assert.AreEqual(new[] { 0, 1, 2, 3, 4, 5 }, XYTriangleTwice.indices); } diff --git a/src/cs/vim/Vim.Format/ObjectModel/ObjectModelExtensions.cs b/src/cs/vim/Vim.Format/ObjectModel/ObjectModelExtensions.cs index c66023cf..6174db7f 100644 --- a/src/cs/vim/Vim.Format/ObjectModel/ObjectModelExtensions.cs +++ b/src/cs/vim/Vim.Format/ObjectModel/ObjectModelExtensions.cs @@ -40,22 +40,22 @@ public static DictionaryOfLists GetAssetsInViewOrderedByViewIn public static string GetBimDocumentFileName(this DocumentModel dm, int bimDocumentIndex) => Path.GetFileName(dm.GetBimDocumentPathName(bimDocumentIndex)); - public static IArray GetBimDocumentDisplayUnits(this DocumentModel dm, BimDocument bd) + public static DisplayUnit[] GetBimDocumentDisplayUnits(this DocumentModel dm, BimDocument bd) => dm.DisplayUnitInBimDocumentList .Where(item => item.BimDocument.Index == bd.Index) .Select(item => item.DisplayUnit) - .ToIArray(); + .ToArray(); - public static IArray GetBimDocumentPhases(this DocumentModel dm, BimDocument bd) + public static Phase[] GetBimDocumentPhases(this DocumentModel dm, BimDocument bd) => dm.PhaseOrderInBimDocumentList .Where(item => item.BimDocument.Index == bd.Index) .Select(item => item.Phase) - .ToIArray(); + .ToArray(); public const string LengthSpecLegacyPrefix = "UT_Length"; public const string LengthSpecPrefix = "autodesk.spec.aec:length"; - public static DisplayUnit GetLengthDisplayUnit(this IArray displayUnits) + public static DisplayUnit GetLengthDisplayUnit(this DisplayUnit[] displayUnits) => displayUnits.FirstOrDefault(du => { var spec = du.Spec; @@ -153,7 +153,7 @@ public static DataTable GetScheduleAsDataTable(this DocumentModel dm, int schedu var columnSet = new HashSet(columns.Select(c => c.Index)); - var cellRecords = dm.ScheduleCellScheduleColumnIndex + var cellRecords = dm.ScheduleCellScheduleColumnIndex.ToIArray() .IndicesWhere((colIndex, _) => columnSet.Contains(colIndex)) .Select(cellIndex => new CellData( dm.GetScheduleCellValue(cellIndex), diff --git a/src/cs/vim/Vim.Format/ObjectModel/ObjectModelGenerated.cs b/src/cs/vim/Vim.Format/ObjectModel/ObjectModelGenerated.cs index 1a176ad1..6a5a980d 100644 --- a/src/cs/vim/Vim.Format/ObjectModel/ObjectModelGenerated.cs +++ b/src/cs/vim/Vim.Format/ObjectModel/ObjectModelGenerated.cs @@ -6,6 +6,7 @@ using Vim.Math3d; using Vim.LinqArray; using Vim.Format.ObjectModel; +using Vim.Util; namespace Vim.Format.ObjectModel { // AUTO-GENERATED @@ -1888,10 +1889,10 @@ public partial class DocumentModel public EntityTable AssetEntityTable { get; } - public IArray AssetBufferName { get; } + public String[] AssetBufferName { get; } public String GetAssetBufferName(int index, String defaultValue = "") => AssetBufferName?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; public int NumAsset => AssetEntityTable?.NumRows ?? 0; - public IArray AssetList { get; } + public Asset[] AssetList { get; } public Asset GetAsset(int n) { if (n < 0) return null; @@ -1907,14 +1908,14 @@ public Asset GetAsset(int n) public EntityTable DisplayUnitEntityTable { get; } - public IArray DisplayUnitSpec { get; } + public String[] DisplayUnitSpec { get; } public String GetDisplayUnitSpec(int index, String defaultValue = "") => DisplayUnitSpec?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray DisplayUnitType { get; } + public String[] DisplayUnitType { get; } public String GetDisplayUnitType(int index, String defaultValue = "") => DisplayUnitType?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray DisplayUnitLabel { get; } + public String[] DisplayUnitLabel { get; } public String GetDisplayUnitLabel(int index, String defaultValue = "") => DisplayUnitLabel?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; public int NumDisplayUnit => DisplayUnitEntityTable?.NumRows ?? 0; - public IArray DisplayUnitList { get; } + public DisplayUnit[] DisplayUnitList { get; } public DisplayUnit GetDisplayUnit(int n) { if (n < 0) return null; @@ -1932,26 +1933,26 @@ public DisplayUnit GetDisplayUnit(int n) public EntityTable ParameterDescriptorEntityTable { get; } - public IArray ParameterDescriptorName { get; } + public String[] ParameterDescriptorName { get; } public String GetParameterDescriptorName(int index, String defaultValue = "") => ParameterDescriptorName?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray ParameterDescriptorGroup { get; } + public String[] ParameterDescriptorGroup { get; } public String GetParameterDescriptorGroup(int index, String defaultValue = "") => ParameterDescriptorGroup?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray ParameterDescriptorParameterType { get; } + public String[] ParameterDescriptorParameterType { get; } public String GetParameterDescriptorParameterType(int index, String defaultValue = "") => ParameterDescriptorParameterType?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray ParameterDescriptorIsInstance { get; } + public Boolean[] ParameterDescriptorIsInstance { get; } public Boolean GetParameterDescriptorIsInstance(int index, Boolean defaultValue = default) => ParameterDescriptorIsInstance?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray ParameterDescriptorIsShared { get; } + public Boolean[] ParameterDescriptorIsShared { get; } public Boolean GetParameterDescriptorIsShared(int index, Boolean defaultValue = default) => ParameterDescriptorIsShared?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray ParameterDescriptorIsReadOnly { get; } + public Boolean[] ParameterDescriptorIsReadOnly { get; } public Boolean GetParameterDescriptorIsReadOnly(int index, Boolean defaultValue = default) => ParameterDescriptorIsReadOnly?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray ParameterDescriptorFlags { get; } + public Int32[] ParameterDescriptorFlags { get; } public Int32 GetParameterDescriptorFlags(int index, Int32 defaultValue = default) => ParameterDescriptorFlags?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray ParameterDescriptorGuid { get; } + public String[] ParameterDescriptorGuid { get; } public String GetParameterDescriptorGuid(int index, String defaultValue = "") => ParameterDescriptorGuid?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray ParameterDescriptorDisplayUnitIndex { get; } + public int[] ParameterDescriptorDisplayUnitIndex { get; } public int GetParameterDescriptorDisplayUnitIndex(int index) => ParameterDescriptorDisplayUnitIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; public int NumParameterDescriptor => ParameterDescriptorEntityTable?.NumRows ?? 0; - public IArray ParameterDescriptorList { get; } + public ParameterDescriptor[] ParameterDescriptorList { get; } public ParameterDescriptor GetParameterDescriptor(int n) { if (n < 0) return null; @@ -1975,14 +1976,14 @@ public ParameterDescriptor GetParameterDescriptor(int n) public EntityTable ParameterEntityTable { get; } - public IArray ParameterValue { get; } + public String[] ParameterValue { get; } public String GetParameterValue(int index, String defaultValue = "") => ParameterValue?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray ParameterParameterDescriptorIndex { get; } + public int[] ParameterParameterDescriptorIndex { get; } public int GetParameterParameterDescriptorIndex(int index) => ParameterParameterDescriptorIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; - public IArray ParameterElementIndex { get; } + public int[] ParameterElementIndex { get; } public int GetParameterElementIndex(int index) => ParameterElementIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; public int NumParameter => ParameterEntityTable?.NumRows ?? 0; - public IArray ParameterList { get; } + public Parameter[] ParameterList { get; } public Parameter GetParameter(int n) { if (n < 0) return null; @@ -2000,48 +2001,48 @@ public Parameter GetParameter(int n) public EntityTable ElementEntityTable { get; } - public IArray ElementId { get; } + public Int64[] ElementId { get; } public Int64 GetElementId(int index, Int64 defaultValue = default) => ElementId?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray ElementType { get; } + public String[] ElementType { get; } public String GetElementType(int index, String defaultValue = "") => ElementType?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray ElementName { get; } + public String[] ElementName { get; } public String GetElementName(int index, String defaultValue = "") => ElementName?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray ElementUniqueId { get; } + public String[] ElementUniqueId { get; } public String GetElementUniqueId(int index, String defaultValue = "") => ElementUniqueId?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray ElementLocation_X { get; } + public Single[] ElementLocation_X { get; } public Single GetElementLocation_X(int index, Single defaultValue = default) => ElementLocation_X?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray ElementLocation_Y { get; } + public Single[] ElementLocation_Y { get; } public Single GetElementLocation_Y(int index, Single defaultValue = default) => ElementLocation_Y?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray ElementLocation_Z { get; } + public Single[] ElementLocation_Z { get; } public Single GetElementLocation_Z(int index, Single defaultValue = default) => ElementLocation_Z?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray ElementFamilyName { get; } + public String[] ElementFamilyName { get; } public String GetElementFamilyName(int index, String defaultValue = "") => ElementFamilyName?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray ElementIsPinned { get; } + public Boolean[] ElementIsPinned { get; } public Boolean GetElementIsPinned(int index, Boolean defaultValue = default) => ElementIsPinned?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray ElementLevelIndex { get; } + public int[] ElementLevelIndex { get; } public int GetElementLevelIndex(int index) => ElementLevelIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; - public IArray ElementPhaseCreatedIndex { get; } + public int[] ElementPhaseCreatedIndex { get; } public int GetElementPhaseCreatedIndex(int index) => ElementPhaseCreatedIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; - public IArray ElementPhaseDemolishedIndex { get; } + public int[] ElementPhaseDemolishedIndex { get; } public int GetElementPhaseDemolishedIndex(int index) => ElementPhaseDemolishedIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; - public IArray ElementCategoryIndex { get; } + public int[] ElementCategoryIndex { get; } public int GetElementCategoryIndex(int index) => ElementCategoryIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; - public IArray ElementWorksetIndex { get; } + public int[] ElementWorksetIndex { get; } public int GetElementWorksetIndex(int index) => ElementWorksetIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; - public IArray ElementDesignOptionIndex { get; } + public int[] ElementDesignOptionIndex { get; } public int GetElementDesignOptionIndex(int index) => ElementDesignOptionIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; - public IArray ElementOwnerViewIndex { get; } + public int[] ElementOwnerViewIndex { get; } public int GetElementOwnerViewIndex(int index) => ElementOwnerViewIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; - public IArray ElementGroupIndex { get; } + public int[] ElementGroupIndex { get; } public int GetElementGroupIndex(int index) => ElementGroupIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; - public IArray ElementAssemblyInstanceIndex { get; } + public int[] ElementAssemblyInstanceIndex { get; } public int GetElementAssemblyInstanceIndex(int index) => ElementAssemblyInstanceIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; - public IArray ElementBimDocumentIndex { get; } + public int[] ElementBimDocumentIndex { get; } public int GetElementBimDocumentIndex(int index) => ElementBimDocumentIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; - public IArray ElementRoomIndex { get; } + public int[] ElementRoomIndex { get; } public int GetElementRoomIndex(int index) => ElementRoomIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; public int NumElement => ElementEntityTable?.NumRows ?? 0; - public IArray ElementList { get; } + public Element[] ElementList { get; } public Element GetElement(int n) { if (n < 0) return null; @@ -2076,24 +2077,24 @@ public Element GetElement(int n) public EntityTable WorksetEntityTable { get; } - public IArray WorksetId { get; } + public Int32[] WorksetId { get; } public Int32 GetWorksetId(int index, Int32 defaultValue = default) => WorksetId?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray WorksetName { get; } + public String[] WorksetName { get; } public String GetWorksetName(int index, String defaultValue = "") => WorksetName?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray WorksetKind { get; } + public String[] WorksetKind { get; } public String GetWorksetKind(int index, String defaultValue = "") => WorksetKind?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray WorksetIsOpen { get; } + public Boolean[] WorksetIsOpen { get; } public Boolean GetWorksetIsOpen(int index, Boolean defaultValue = default) => WorksetIsOpen?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray WorksetIsEditable { get; } + public Boolean[] WorksetIsEditable { get; } public Boolean GetWorksetIsEditable(int index, Boolean defaultValue = default) => WorksetIsEditable?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray WorksetOwner { get; } + public String[] WorksetOwner { get; } public String GetWorksetOwner(int index, String defaultValue = "") => WorksetOwner?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray WorksetUniqueId { get; } + public String[] WorksetUniqueId { get; } public String GetWorksetUniqueId(int index, String defaultValue = "") => WorksetUniqueId?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray WorksetBimDocumentIndex { get; } + public int[] WorksetBimDocumentIndex { get; } public int GetWorksetBimDocumentIndex(int index) => WorksetBimDocumentIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; public int NumWorkset => WorksetEntityTable?.NumRows ?? 0; - public IArray WorksetList { get; } + public Workset[] WorksetList { get; } public Workset GetWorkset(int n) { if (n < 0) return null; @@ -2116,18 +2117,18 @@ public Workset GetWorkset(int n) public EntityTable AssemblyInstanceEntityTable { get; } - public IArray AssemblyInstanceAssemblyTypeName { get; } + public String[] AssemblyInstanceAssemblyTypeName { get; } public String GetAssemblyInstanceAssemblyTypeName(int index, String defaultValue = "") => AssemblyInstanceAssemblyTypeName?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray AssemblyInstancePosition_X { get; } + public Single[] AssemblyInstancePosition_X { get; } public Single GetAssemblyInstancePosition_X(int index, Single defaultValue = default) => AssemblyInstancePosition_X?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray AssemblyInstancePosition_Y { get; } + public Single[] AssemblyInstancePosition_Y { get; } public Single GetAssemblyInstancePosition_Y(int index, Single defaultValue = default) => AssemblyInstancePosition_Y?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray AssemblyInstancePosition_Z { get; } + public Single[] AssemblyInstancePosition_Z { get; } public Single GetAssemblyInstancePosition_Z(int index, Single defaultValue = default) => AssemblyInstancePosition_Z?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray AssemblyInstanceElementIndex { get; } + public int[] AssemblyInstanceElementIndex { get; } public int GetAssemblyInstanceElementIndex(int index) => AssemblyInstanceElementIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; public int NumAssemblyInstance => AssemblyInstanceEntityTable?.NumRows ?? 0; - public IArray AssemblyInstanceList { get; } + public AssemblyInstance[] AssemblyInstanceList { get; } public AssemblyInstance GetAssemblyInstance(int n) { if (n < 0) return null; @@ -2147,18 +2148,18 @@ public AssemblyInstance GetAssemblyInstance(int n) public EntityTable GroupEntityTable { get; } - public IArray GroupGroupType { get; } + public String[] GroupGroupType { get; } public String GetGroupGroupType(int index, String defaultValue = "") => GroupGroupType?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray GroupPosition_X { get; } + public Single[] GroupPosition_X { get; } public Single GetGroupPosition_X(int index, Single defaultValue = default) => GroupPosition_X?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray GroupPosition_Y { get; } + public Single[] GroupPosition_Y { get; } public Single GetGroupPosition_Y(int index, Single defaultValue = default) => GroupPosition_Y?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray GroupPosition_Z { get; } + public Single[] GroupPosition_Z { get; } public Single GetGroupPosition_Z(int index, Single defaultValue = default) => GroupPosition_Z?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray GroupElementIndex { get; } + public int[] GroupElementIndex { get; } public int GetGroupElementIndex(int index) => GroupElementIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; public int NumGroup => GroupEntityTable?.NumRows ?? 0; - public IArray GroupList { get; } + public Group[] GroupList { get; } public Group GetGroup(int n) { if (n < 0) return null; @@ -2178,12 +2179,12 @@ public Group GetGroup(int n) public EntityTable DesignOptionEntityTable { get; } - public IArray DesignOptionIsPrimary { get; } + public Boolean[] DesignOptionIsPrimary { get; } public Boolean GetDesignOptionIsPrimary(int index, Boolean defaultValue = default) => DesignOptionIsPrimary?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray DesignOptionElementIndex { get; } + public int[] DesignOptionElementIndex { get; } public int GetDesignOptionElementIndex(int index) => DesignOptionElementIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; public int NumDesignOption => DesignOptionEntityTable?.NumRows ?? 0; - public IArray DesignOptionList { get; } + public DesignOption[] DesignOptionList { get; } public DesignOption GetDesignOption(int n) { if (n < 0) return null; @@ -2200,16 +2201,16 @@ public DesignOption GetDesignOption(int n) public EntityTable LevelEntityTable { get; } - public IArray LevelElevation { get; } + public Double[] LevelElevation { get; } public Double GetLevelElevation(int index, Double defaultValue = default) => LevelElevation?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray LevelFamilyTypeIndex { get; } + public int[] LevelFamilyTypeIndex { get; } public int GetLevelFamilyTypeIndex(int index) => LevelFamilyTypeIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; - public IArray LevelBuildingIndex { get; } + public int[] LevelBuildingIndex { get; } public int GetLevelBuildingIndex(int index) => LevelBuildingIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; - public IArray LevelElementIndex { get; } + public int[] LevelElementIndex { get; } public int GetLevelElementIndex(int index) => LevelElementIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; public int NumLevel => LevelEntityTable?.NumRows ?? 0; - public IArray LevelList { get; } + public Level[] LevelList { get; } public Level GetLevel(int n) { if (n < 0) return null; @@ -2228,10 +2229,10 @@ public Level GetLevel(int n) public EntityTable PhaseEntityTable { get; } - public IArray PhaseElementIndex { get; } + public int[] PhaseElementIndex { get; } public int GetPhaseElementIndex(int index) => PhaseElementIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; public int NumPhase => PhaseEntityTable?.NumRows ?? 0; - public IArray PhaseList { get; } + public Phase[] PhaseList { get; } public Phase GetPhase(int n) { if (n < 0) return null; @@ -2247,26 +2248,26 @@ public Phase GetPhase(int n) public EntityTable RoomEntityTable { get; } - public IArray RoomBaseOffset { get; } + public Double[] RoomBaseOffset { get; } public Double GetRoomBaseOffset(int index, Double defaultValue = default) => RoomBaseOffset?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray RoomLimitOffset { get; } + public Double[] RoomLimitOffset { get; } public Double GetRoomLimitOffset(int index, Double defaultValue = default) => RoomLimitOffset?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray RoomUnboundedHeight { get; } + public Double[] RoomUnboundedHeight { get; } public Double GetRoomUnboundedHeight(int index, Double defaultValue = default) => RoomUnboundedHeight?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray RoomVolume { get; } + public Double[] RoomVolume { get; } public Double GetRoomVolume(int index, Double defaultValue = default) => RoomVolume?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray RoomPerimeter { get; } + public Double[] RoomPerimeter { get; } public Double GetRoomPerimeter(int index, Double defaultValue = default) => RoomPerimeter?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray RoomArea { get; } + public Double[] RoomArea { get; } public Double GetRoomArea(int index, Double defaultValue = default) => RoomArea?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray RoomNumber { get; } + public String[] RoomNumber { get; } public String GetRoomNumber(int index, String defaultValue = "") => RoomNumber?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray RoomUpperLimitIndex { get; } + public int[] RoomUpperLimitIndex { get; } public int GetRoomUpperLimitIndex(int index) => RoomUpperLimitIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; - public IArray RoomElementIndex { get; } + public int[] RoomElementIndex { get; } public int GetRoomElementIndex(int index) => RoomElementIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; public int NumRoom => RoomEntityTable?.NumRows ?? 0; - public IArray RoomList { get; } + public Room[] RoomList { get; } public Room GetRoom(int n) { if (n < 0) return null; @@ -2290,72 +2291,72 @@ public Room GetRoom(int n) public EntityTable BimDocumentEntityTable { get; } - public IArray BimDocumentTitle { get; } + public String[] BimDocumentTitle { get; } public String GetBimDocumentTitle(int index, String defaultValue = "") => BimDocumentTitle?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray BimDocumentIsMetric { get; } + public Boolean[] BimDocumentIsMetric { get; } public Boolean GetBimDocumentIsMetric(int index, Boolean defaultValue = default) => BimDocumentIsMetric?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray BimDocumentGuid { get; } + public String[] BimDocumentGuid { get; } public String GetBimDocumentGuid(int index, String defaultValue = "") => BimDocumentGuid?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray BimDocumentNumSaves { get; } + public Int32[] BimDocumentNumSaves { get; } public Int32 GetBimDocumentNumSaves(int index, Int32 defaultValue = default) => BimDocumentNumSaves?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray BimDocumentIsLinked { get; } + public Boolean[] BimDocumentIsLinked { get; } public Boolean GetBimDocumentIsLinked(int index, Boolean defaultValue = default) => BimDocumentIsLinked?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray BimDocumentIsDetached { get; } + public Boolean[] BimDocumentIsDetached { get; } public Boolean GetBimDocumentIsDetached(int index, Boolean defaultValue = default) => BimDocumentIsDetached?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray BimDocumentIsWorkshared { get; } + public Boolean[] BimDocumentIsWorkshared { get; } public Boolean GetBimDocumentIsWorkshared(int index, Boolean defaultValue = default) => BimDocumentIsWorkshared?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray BimDocumentPathName { get; } + public String[] BimDocumentPathName { get; } public String GetBimDocumentPathName(int index, String defaultValue = "") => BimDocumentPathName?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray BimDocumentLatitude { get; } + public Double[] BimDocumentLatitude { get; } public Double GetBimDocumentLatitude(int index, Double defaultValue = default) => BimDocumentLatitude?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray BimDocumentLongitude { get; } + public Double[] BimDocumentLongitude { get; } public Double GetBimDocumentLongitude(int index, Double defaultValue = default) => BimDocumentLongitude?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray BimDocumentTimeZone { get; } + public Double[] BimDocumentTimeZone { get; } public Double GetBimDocumentTimeZone(int index, Double defaultValue = default) => BimDocumentTimeZone?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray BimDocumentPlaceName { get; } + public String[] BimDocumentPlaceName { get; } public String GetBimDocumentPlaceName(int index, String defaultValue = "") => BimDocumentPlaceName?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray BimDocumentWeatherStationName { get; } + public String[] BimDocumentWeatherStationName { get; } public String GetBimDocumentWeatherStationName(int index, String defaultValue = "") => BimDocumentWeatherStationName?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray BimDocumentElevation { get; } + public Double[] BimDocumentElevation { get; } public Double GetBimDocumentElevation(int index, Double defaultValue = default) => BimDocumentElevation?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray BimDocumentProjectLocation { get; } + public String[] BimDocumentProjectLocation { get; } public String GetBimDocumentProjectLocation(int index, String defaultValue = "") => BimDocumentProjectLocation?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray BimDocumentIssueDate { get; } + public String[] BimDocumentIssueDate { get; } public String GetBimDocumentIssueDate(int index, String defaultValue = "") => BimDocumentIssueDate?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray BimDocumentStatus { get; } + public String[] BimDocumentStatus { get; } public String GetBimDocumentStatus(int index, String defaultValue = "") => BimDocumentStatus?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray BimDocumentClientName { get; } + public String[] BimDocumentClientName { get; } public String GetBimDocumentClientName(int index, String defaultValue = "") => BimDocumentClientName?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray BimDocumentAddress { get; } + public String[] BimDocumentAddress { get; } public String GetBimDocumentAddress(int index, String defaultValue = "") => BimDocumentAddress?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray BimDocumentName { get; } + public String[] BimDocumentName { get; } public String GetBimDocumentName(int index, String defaultValue = "") => BimDocumentName?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray BimDocumentNumber { get; } + public String[] BimDocumentNumber { get; } public String GetBimDocumentNumber(int index, String defaultValue = "") => BimDocumentNumber?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray BimDocumentAuthor { get; } + public String[] BimDocumentAuthor { get; } public String GetBimDocumentAuthor(int index, String defaultValue = "") => BimDocumentAuthor?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray BimDocumentBuildingName { get; } + public String[] BimDocumentBuildingName { get; } public String GetBimDocumentBuildingName(int index, String defaultValue = "") => BimDocumentBuildingName?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray BimDocumentOrganizationName { get; } + public String[] BimDocumentOrganizationName { get; } public String GetBimDocumentOrganizationName(int index, String defaultValue = "") => BimDocumentOrganizationName?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray BimDocumentOrganizationDescription { get; } + public String[] BimDocumentOrganizationDescription { get; } public String GetBimDocumentOrganizationDescription(int index, String defaultValue = "") => BimDocumentOrganizationDescription?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray BimDocumentProduct { get; } + public String[] BimDocumentProduct { get; } public String GetBimDocumentProduct(int index, String defaultValue = "") => BimDocumentProduct?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray BimDocumentVersion { get; } + public String[] BimDocumentVersion { get; } public String GetBimDocumentVersion(int index, String defaultValue = "") => BimDocumentVersion?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray BimDocumentUser { get; } + public String[] BimDocumentUser { get; } public String GetBimDocumentUser(int index, String defaultValue = "") => BimDocumentUser?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray BimDocumentActiveViewIndex { get; } + public int[] BimDocumentActiveViewIndex { get; } public int GetBimDocumentActiveViewIndex(int index) => BimDocumentActiveViewIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; - public IArray BimDocumentOwnerFamilyIndex { get; } + public int[] BimDocumentOwnerFamilyIndex { get; } public int GetBimDocumentOwnerFamilyIndex(int index) => BimDocumentOwnerFamilyIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; - public IArray BimDocumentParentIndex { get; } + public int[] BimDocumentParentIndex { get; } public int GetBimDocumentParentIndex(int index) => BimDocumentParentIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; - public IArray BimDocumentElementIndex { get; } + public int[] BimDocumentElementIndex { get; } public int GetBimDocumentElementIndex(int index) => BimDocumentElementIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; public int NumBimDocument => BimDocumentEntityTable?.NumRows ?? 0; - public IArray BimDocumentList { get; } + public BimDocument[] BimDocumentList { get; } public BimDocument GetBimDocument(int n) { if (n < 0) return null; @@ -2402,12 +2403,12 @@ public BimDocument GetBimDocument(int n) public EntityTable DisplayUnitInBimDocumentEntityTable { get; } - public IArray DisplayUnitInBimDocumentDisplayUnitIndex { get; } + public int[] DisplayUnitInBimDocumentDisplayUnitIndex { get; } public int GetDisplayUnitInBimDocumentDisplayUnitIndex(int index) => DisplayUnitInBimDocumentDisplayUnitIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; - public IArray DisplayUnitInBimDocumentBimDocumentIndex { get; } + public int[] DisplayUnitInBimDocumentBimDocumentIndex { get; } public int GetDisplayUnitInBimDocumentBimDocumentIndex(int index) => DisplayUnitInBimDocumentBimDocumentIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; public int NumDisplayUnitInBimDocument => DisplayUnitInBimDocumentEntityTable?.NumRows ?? 0; - public IArray DisplayUnitInBimDocumentList { get; } + public DisplayUnitInBimDocument[] DisplayUnitInBimDocumentList { get; } public DisplayUnitInBimDocument GetDisplayUnitInBimDocument(int n) { if (n < 0) return null; @@ -2424,14 +2425,14 @@ public DisplayUnitInBimDocument GetDisplayUnitInBimDocument(int n) public EntityTable PhaseOrderInBimDocumentEntityTable { get; } - public IArray PhaseOrderInBimDocumentOrderIndex { get; } + public Int32[] PhaseOrderInBimDocumentOrderIndex { get; } public Int32 GetPhaseOrderInBimDocumentOrderIndex(int index, Int32 defaultValue = default) => PhaseOrderInBimDocumentOrderIndex?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray PhaseOrderInBimDocumentPhaseIndex { get; } + public int[] PhaseOrderInBimDocumentPhaseIndex { get; } public int GetPhaseOrderInBimDocumentPhaseIndex(int index) => PhaseOrderInBimDocumentPhaseIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; - public IArray PhaseOrderInBimDocumentBimDocumentIndex { get; } + public int[] PhaseOrderInBimDocumentBimDocumentIndex { get; } public int GetPhaseOrderInBimDocumentBimDocumentIndex(int index) => PhaseOrderInBimDocumentBimDocumentIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; public int NumPhaseOrderInBimDocument => PhaseOrderInBimDocumentEntityTable?.NumRows ?? 0; - public IArray PhaseOrderInBimDocumentList { get; } + public PhaseOrderInBimDocument[] PhaseOrderInBimDocumentList { get; } public PhaseOrderInBimDocument GetPhaseOrderInBimDocument(int n) { if (n < 0) return null; @@ -2449,26 +2450,26 @@ public PhaseOrderInBimDocument GetPhaseOrderInBimDocument(int n) public EntityTable CategoryEntityTable { get; } - public IArray CategoryName { get; } + public String[] CategoryName { get; } public String GetCategoryName(int index, String defaultValue = "") => CategoryName?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray CategoryId { get; } + public Int64[] CategoryId { get; } public Int64 GetCategoryId(int index, Int64 defaultValue = default) => CategoryId?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray CategoryCategoryType { get; } + public String[] CategoryCategoryType { get; } public String GetCategoryCategoryType(int index, String defaultValue = "") => CategoryCategoryType?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray CategoryLineColor_X { get; } + public Double[] CategoryLineColor_X { get; } public Double GetCategoryLineColor_X(int index, Double defaultValue = default) => CategoryLineColor_X?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray CategoryLineColor_Y { get; } + public Double[] CategoryLineColor_Y { get; } public Double GetCategoryLineColor_Y(int index, Double defaultValue = default) => CategoryLineColor_Y?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray CategoryLineColor_Z { get; } + public Double[] CategoryLineColor_Z { get; } public Double GetCategoryLineColor_Z(int index, Double defaultValue = default) => CategoryLineColor_Z?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray CategoryBuiltInCategory { get; } + public String[] CategoryBuiltInCategory { get; } public String GetCategoryBuiltInCategory(int index, String defaultValue = "") => CategoryBuiltInCategory?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray CategoryParentIndex { get; } + public int[] CategoryParentIndex { get; } public int GetCategoryParentIndex(int index) => CategoryParentIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; - public IArray CategoryMaterialIndex { get; } + public int[] CategoryMaterialIndex { get; } public int GetCategoryMaterialIndex(int index) => CategoryMaterialIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; public int NumCategory => CategoryEntityTable?.NumRows ?? 0; - public IArray CategoryList { get; } + public Category[] CategoryList { get; } public Category GetCategory(int n) { if (n < 0) return null; @@ -2492,20 +2493,20 @@ public Category GetCategory(int n) public EntityTable FamilyEntityTable { get; } - public IArray FamilyStructuralMaterialType { get; } + public String[] FamilyStructuralMaterialType { get; } public String GetFamilyStructuralMaterialType(int index, String defaultValue = "") => FamilyStructuralMaterialType?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray FamilyStructuralSectionShape { get; } + public String[] FamilyStructuralSectionShape { get; } public String GetFamilyStructuralSectionShape(int index, String defaultValue = "") => FamilyStructuralSectionShape?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray FamilyIsSystemFamily { get; } + public Boolean[] FamilyIsSystemFamily { get; } public Boolean GetFamilyIsSystemFamily(int index, Boolean defaultValue = default) => FamilyIsSystemFamily?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray FamilyIsInPlace { get; } + public Boolean[] FamilyIsInPlace { get; } public Boolean GetFamilyIsInPlace(int index, Boolean defaultValue = default) => FamilyIsInPlace?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray FamilyFamilyCategoryIndex { get; } + public int[] FamilyFamilyCategoryIndex { get; } public int GetFamilyFamilyCategoryIndex(int index) => FamilyFamilyCategoryIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; - public IArray FamilyElementIndex { get; } + public int[] FamilyElementIndex { get; } public int GetFamilyElementIndex(int index) => FamilyElementIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; public int NumFamily => FamilyEntityTable?.NumRows ?? 0; - public IArray FamilyList { get; } + public Family[] FamilyList { get; } public Family GetFamily(int n) { if (n < 0) return null; @@ -2526,16 +2527,16 @@ public Family GetFamily(int n) public EntityTable FamilyTypeEntityTable { get; } - public IArray FamilyTypeIsSystemFamilyType { get; } + public Boolean[] FamilyTypeIsSystemFamilyType { get; } public Boolean GetFamilyTypeIsSystemFamilyType(int index, Boolean defaultValue = default) => FamilyTypeIsSystemFamilyType?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray FamilyTypeFamilyIndex { get; } + public int[] FamilyTypeFamilyIndex { get; } public int GetFamilyTypeFamilyIndex(int index) => FamilyTypeFamilyIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; - public IArray FamilyTypeCompoundStructureIndex { get; } + public int[] FamilyTypeCompoundStructureIndex { get; } public int GetFamilyTypeCompoundStructureIndex(int index) => FamilyTypeCompoundStructureIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; - public IArray FamilyTypeElementIndex { get; } + public int[] FamilyTypeElementIndex { get; } public int GetFamilyTypeElementIndex(int index) => FamilyTypeElementIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; public int NumFamilyType => FamilyTypeEntityTable?.NumRows ?? 0; - public IArray FamilyTypeList { get; } + public FamilyType[] FamilyTypeList { get; } public FamilyType GetFamilyType(int n) { if (n < 0) return null; @@ -2554,64 +2555,64 @@ public FamilyType GetFamilyType(int n) public EntityTable FamilyInstanceEntityTable { get; } - public IArray FamilyInstanceFacingFlipped { get; } + public Boolean[] FamilyInstanceFacingFlipped { get; } public Boolean GetFamilyInstanceFacingFlipped(int index, Boolean defaultValue = default) => FamilyInstanceFacingFlipped?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray FamilyInstanceFacingOrientation_X { get; } + public Single[] FamilyInstanceFacingOrientation_X { get; } public Single GetFamilyInstanceFacingOrientation_X(int index, Single defaultValue = default) => FamilyInstanceFacingOrientation_X?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray FamilyInstanceFacingOrientation_Y { get; } + public Single[] FamilyInstanceFacingOrientation_Y { get; } public Single GetFamilyInstanceFacingOrientation_Y(int index, Single defaultValue = default) => FamilyInstanceFacingOrientation_Y?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray FamilyInstanceFacingOrientation_Z { get; } + public Single[] FamilyInstanceFacingOrientation_Z { get; } public Single GetFamilyInstanceFacingOrientation_Z(int index, Single defaultValue = default) => FamilyInstanceFacingOrientation_Z?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray FamilyInstanceHandFlipped { get; } + public Boolean[] FamilyInstanceHandFlipped { get; } public Boolean GetFamilyInstanceHandFlipped(int index, Boolean defaultValue = default) => FamilyInstanceHandFlipped?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray FamilyInstanceMirrored { get; } + public Boolean[] FamilyInstanceMirrored { get; } public Boolean GetFamilyInstanceMirrored(int index, Boolean defaultValue = default) => FamilyInstanceMirrored?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray FamilyInstanceHasModifiedGeometry { get; } + public Boolean[] FamilyInstanceHasModifiedGeometry { get; } public Boolean GetFamilyInstanceHasModifiedGeometry(int index, Boolean defaultValue = default) => FamilyInstanceHasModifiedGeometry?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray FamilyInstanceScale { get; } + public Single[] FamilyInstanceScale { get; } public Single GetFamilyInstanceScale(int index, Single defaultValue = default) => FamilyInstanceScale?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray FamilyInstanceBasisX_X { get; } + public Single[] FamilyInstanceBasisX_X { get; } public Single GetFamilyInstanceBasisX_X(int index, Single defaultValue = default) => FamilyInstanceBasisX_X?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray FamilyInstanceBasisX_Y { get; } + public Single[] FamilyInstanceBasisX_Y { get; } public Single GetFamilyInstanceBasisX_Y(int index, Single defaultValue = default) => FamilyInstanceBasisX_Y?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray FamilyInstanceBasisX_Z { get; } + public Single[] FamilyInstanceBasisX_Z { get; } public Single GetFamilyInstanceBasisX_Z(int index, Single defaultValue = default) => FamilyInstanceBasisX_Z?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray FamilyInstanceBasisY_X { get; } + public Single[] FamilyInstanceBasisY_X { get; } public Single GetFamilyInstanceBasisY_X(int index, Single defaultValue = default) => FamilyInstanceBasisY_X?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray FamilyInstanceBasisY_Y { get; } + public Single[] FamilyInstanceBasisY_Y { get; } public Single GetFamilyInstanceBasisY_Y(int index, Single defaultValue = default) => FamilyInstanceBasisY_Y?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray FamilyInstanceBasisY_Z { get; } + public Single[] FamilyInstanceBasisY_Z { get; } public Single GetFamilyInstanceBasisY_Z(int index, Single defaultValue = default) => FamilyInstanceBasisY_Z?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray FamilyInstanceBasisZ_X { get; } + public Single[] FamilyInstanceBasisZ_X { get; } public Single GetFamilyInstanceBasisZ_X(int index, Single defaultValue = default) => FamilyInstanceBasisZ_X?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray FamilyInstanceBasisZ_Y { get; } + public Single[] FamilyInstanceBasisZ_Y { get; } public Single GetFamilyInstanceBasisZ_Y(int index, Single defaultValue = default) => FamilyInstanceBasisZ_Y?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray FamilyInstanceBasisZ_Z { get; } + public Single[] FamilyInstanceBasisZ_Z { get; } public Single GetFamilyInstanceBasisZ_Z(int index, Single defaultValue = default) => FamilyInstanceBasisZ_Z?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray FamilyInstanceTranslation_X { get; } + public Single[] FamilyInstanceTranslation_X { get; } public Single GetFamilyInstanceTranslation_X(int index, Single defaultValue = default) => FamilyInstanceTranslation_X?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray FamilyInstanceTranslation_Y { get; } + public Single[] FamilyInstanceTranslation_Y { get; } public Single GetFamilyInstanceTranslation_Y(int index, Single defaultValue = default) => FamilyInstanceTranslation_Y?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray FamilyInstanceTranslation_Z { get; } + public Single[] FamilyInstanceTranslation_Z { get; } public Single GetFamilyInstanceTranslation_Z(int index, Single defaultValue = default) => FamilyInstanceTranslation_Z?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray FamilyInstanceHandOrientation_X { get; } + public Single[] FamilyInstanceHandOrientation_X { get; } public Single GetFamilyInstanceHandOrientation_X(int index, Single defaultValue = default) => FamilyInstanceHandOrientation_X?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray FamilyInstanceHandOrientation_Y { get; } + public Single[] FamilyInstanceHandOrientation_Y { get; } public Single GetFamilyInstanceHandOrientation_Y(int index, Single defaultValue = default) => FamilyInstanceHandOrientation_Y?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray FamilyInstanceHandOrientation_Z { get; } + public Single[] FamilyInstanceHandOrientation_Z { get; } public Single GetFamilyInstanceHandOrientation_Z(int index, Single defaultValue = default) => FamilyInstanceHandOrientation_Z?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray FamilyInstanceFamilyTypeIndex { get; } + public int[] FamilyInstanceFamilyTypeIndex { get; } public int GetFamilyInstanceFamilyTypeIndex(int index) => FamilyInstanceFamilyTypeIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; - public IArray FamilyInstanceHostIndex { get; } + public int[] FamilyInstanceHostIndex { get; } public int GetFamilyInstanceHostIndex(int index) => FamilyInstanceHostIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; - public IArray FamilyInstanceFromRoomIndex { get; } + public int[] FamilyInstanceFromRoomIndex { get; } public int GetFamilyInstanceFromRoomIndex(int index) => FamilyInstanceFromRoomIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; - public IArray FamilyInstanceToRoomIndex { get; } + public int[] FamilyInstanceToRoomIndex { get; } public int GetFamilyInstanceToRoomIndex(int index) => FamilyInstanceToRoomIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; - public IArray FamilyInstanceElementIndex { get; } + public int[] FamilyInstanceElementIndex { get; } public int GetFamilyInstanceElementIndex(int index) => FamilyInstanceElementIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; public int NumFamilyInstance => FamilyInstanceEntityTable?.NumRows ?? 0; - public IArray FamilyInstanceList { get; } + public FamilyInstance[] FamilyInstanceList { get; } public FamilyInstance GetFamilyInstance(int n) { if (n < 0) return null; @@ -2654,60 +2655,60 @@ public FamilyInstance GetFamilyInstance(int n) public EntityTable ViewEntityTable { get; } - public IArray ViewTitle { get; } + public String[] ViewTitle { get; } public String GetViewTitle(int index, String defaultValue = "") => ViewTitle?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray ViewViewType { get; } + public String[] ViewViewType { get; } public String GetViewViewType(int index, String defaultValue = "") => ViewViewType?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray ViewUp_X { get; } + public Double[] ViewUp_X { get; } public Double GetViewUp_X(int index, Double defaultValue = default) => ViewUp_X?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray ViewUp_Y { get; } + public Double[] ViewUp_Y { get; } public Double GetViewUp_Y(int index, Double defaultValue = default) => ViewUp_Y?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray ViewUp_Z { get; } + public Double[] ViewUp_Z { get; } public Double GetViewUp_Z(int index, Double defaultValue = default) => ViewUp_Z?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray ViewRight_X { get; } + public Double[] ViewRight_X { get; } public Double GetViewRight_X(int index, Double defaultValue = default) => ViewRight_X?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray ViewRight_Y { get; } + public Double[] ViewRight_Y { get; } public Double GetViewRight_Y(int index, Double defaultValue = default) => ViewRight_Y?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray ViewRight_Z { get; } + public Double[] ViewRight_Z { get; } public Double GetViewRight_Z(int index, Double defaultValue = default) => ViewRight_Z?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray ViewOrigin_X { get; } + public Double[] ViewOrigin_X { get; } public Double GetViewOrigin_X(int index, Double defaultValue = default) => ViewOrigin_X?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray ViewOrigin_Y { get; } + public Double[] ViewOrigin_Y { get; } public Double GetViewOrigin_Y(int index, Double defaultValue = default) => ViewOrigin_Y?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray ViewOrigin_Z { get; } + public Double[] ViewOrigin_Z { get; } public Double GetViewOrigin_Z(int index, Double defaultValue = default) => ViewOrigin_Z?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray ViewViewDirection_X { get; } + public Double[] ViewViewDirection_X { get; } public Double GetViewViewDirection_X(int index, Double defaultValue = default) => ViewViewDirection_X?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray ViewViewDirection_Y { get; } + public Double[] ViewViewDirection_Y { get; } public Double GetViewViewDirection_Y(int index, Double defaultValue = default) => ViewViewDirection_Y?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray ViewViewDirection_Z { get; } + public Double[] ViewViewDirection_Z { get; } public Double GetViewViewDirection_Z(int index, Double defaultValue = default) => ViewViewDirection_Z?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray ViewViewPosition_X { get; } + public Double[] ViewViewPosition_X { get; } public Double GetViewViewPosition_X(int index, Double defaultValue = default) => ViewViewPosition_X?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray ViewViewPosition_Y { get; } + public Double[] ViewViewPosition_Y { get; } public Double GetViewViewPosition_Y(int index, Double defaultValue = default) => ViewViewPosition_Y?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray ViewViewPosition_Z { get; } + public Double[] ViewViewPosition_Z { get; } public Double GetViewViewPosition_Z(int index, Double defaultValue = default) => ViewViewPosition_Z?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray ViewScale { get; } + public Double[] ViewScale { get; } public Double GetViewScale(int index, Double defaultValue = default) => ViewScale?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray ViewOutline_Min_X { get; } + public Double[] ViewOutline_Min_X { get; } public Double GetViewOutline_Min_X(int index, Double defaultValue = default) => ViewOutline_Min_X?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray ViewOutline_Min_Y { get; } + public Double[] ViewOutline_Min_Y { get; } public Double GetViewOutline_Min_Y(int index, Double defaultValue = default) => ViewOutline_Min_Y?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray ViewOutline_Max_X { get; } + public Double[] ViewOutline_Max_X { get; } public Double GetViewOutline_Max_X(int index, Double defaultValue = default) => ViewOutline_Max_X?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray ViewOutline_Max_Y { get; } + public Double[] ViewOutline_Max_Y { get; } public Double GetViewOutline_Max_Y(int index, Double defaultValue = default) => ViewOutline_Max_Y?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray ViewDetailLevel { get; } + public Int32[] ViewDetailLevel { get; } public Int32 GetViewDetailLevel(int index, Int32 defaultValue = default) => ViewDetailLevel?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray ViewCameraIndex { get; } + public int[] ViewCameraIndex { get; } public int GetViewCameraIndex(int index) => ViewCameraIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; - public IArray ViewFamilyTypeIndex { get; } + public int[] ViewFamilyTypeIndex { get; } public int GetViewFamilyTypeIndex(int index) => ViewFamilyTypeIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; - public IArray ViewElementIndex { get; } + public int[] ViewElementIndex { get; } public int GetViewElementIndex(int index) => ViewElementIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; public int NumView => ViewEntityTable?.NumRows ?? 0; - public IArray ViewList { get; } + public View[] ViewList { get; } public View GetView(int n) { if (n < 0) return null; @@ -2748,12 +2749,12 @@ public View GetView(int n) public EntityTable ElementInViewEntityTable { get; } - public IArray ElementInViewViewIndex { get; } + public int[] ElementInViewViewIndex { get; } public int GetElementInViewViewIndex(int index) => ElementInViewViewIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; - public IArray ElementInViewElementIndex { get; } + public int[] ElementInViewElementIndex { get; } public int GetElementInViewElementIndex(int index) => ElementInViewElementIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; public int NumElementInView => ElementInViewEntityTable?.NumRows ?? 0; - public IArray ElementInViewList { get; } + public ElementInView[] ElementInViewList { get; } public ElementInView GetElementInView(int n) { if (n < 0) return null; @@ -2770,12 +2771,12 @@ public ElementInView GetElementInView(int n) public EntityTable ShapeInViewEntityTable { get; } - public IArray ShapeInViewShapeIndex { get; } + public int[] ShapeInViewShapeIndex { get; } public int GetShapeInViewShapeIndex(int index) => ShapeInViewShapeIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; - public IArray ShapeInViewViewIndex { get; } + public int[] ShapeInViewViewIndex { get; } public int GetShapeInViewViewIndex(int index) => ShapeInViewViewIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; public int NumShapeInView => ShapeInViewEntityTable?.NumRows ?? 0; - public IArray ShapeInViewList { get; } + public ShapeInView[] ShapeInViewList { get; } public ShapeInView GetShapeInView(int n) { if (n < 0) return null; @@ -2792,12 +2793,12 @@ public ShapeInView GetShapeInView(int n) public EntityTable AssetInViewEntityTable { get; } - public IArray AssetInViewAssetIndex { get; } + public int[] AssetInViewAssetIndex { get; } public int GetAssetInViewAssetIndex(int index) => AssetInViewAssetIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; - public IArray AssetInViewViewIndex { get; } + public int[] AssetInViewViewIndex { get; } public int GetAssetInViewViewIndex(int index) => AssetInViewViewIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; public int NumAssetInView => AssetInViewEntityTable?.NumRows ?? 0; - public IArray AssetInViewList { get; } + public AssetInView[] AssetInViewList { get; } public AssetInView GetAssetInView(int n) { if (n < 0) return null; @@ -2814,12 +2815,12 @@ public AssetInView GetAssetInView(int n) public EntityTable AssetInViewSheetEntityTable { get; } - public IArray AssetInViewSheetAssetIndex { get; } + public int[] AssetInViewSheetAssetIndex { get; } public int GetAssetInViewSheetAssetIndex(int index) => AssetInViewSheetAssetIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; - public IArray AssetInViewSheetViewSheetIndex { get; } + public int[] AssetInViewSheetViewSheetIndex { get; } public int GetAssetInViewSheetViewSheetIndex(int index) => AssetInViewSheetViewSheetIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; public int NumAssetInViewSheet => AssetInViewSheetEntityTable?.NumRows ?? 0; - public IArray AssetInViewSheetList { get; } + public AssetInViewSheet[] AssetInViewSheetList { get; } public AssetInViewSheet GetAssetInViewSheet(int n) { if (n < 0) return null; @@ -2836,24 +2837,24 @@ public AssetInViewSheet GetAssetInViewSheet(int n) public EntityTable LevelInViewEntityTable { get; } - public IArray LevelInViewExtents_Min_X { get; } + public Double[] LevelInViewExtents_Min_X { get; } public Double GetLevelInViewExtents_Min_X(int index, Double defaultValue = default) => LevelInViewExtents_Min_X?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray LevelInViewExtents_Min_Y { get; } + public Double[] LevelInViewExtents_Min_Y { get; } public Double GetLevelInViewExtents_Min_Y(int index, Double defaultValue = default) => LevelInViewExtents_Min_Y?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray LevelInViewExtents_Min_Z { get; } + public Double[] LevelInViewExtents_Min_Z { get; } public Double GetLevelInViewExtents_Min_Z(int index, Double defaultValue = default) => LevelInViewExtents_Min_Z?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray LevelInViewExtents_Max_X { get; } + public Double[] LevelInViewExtents_Max_X { get; } public Double GetLevelInViewExtents_Max_X(int index, Double defaultValue = default) => LevelInViewExtents_Max_X?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray LevelInViewExtents_Max_Y { get; } + public Double[] LevelInViewExtents_Max_Y { get; } public Double GetLevelInViewExtents_Max_Y(int index, Double defaultValue = default) => LevelInViewExtents_Max_Y?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray LevelInViewExtents_Max_Z { get; } + public Double[] LevelInViewExtents_Max_Z { get; } public Double GetLevelInViewExtents_Max_Z(int index, Double defaultValue = default) => LevelInViewExtents_Max_Z?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray LevelInViewLevelIndex { get; } + public int[] LevelInViewLevelIndex { get; } public int GetLevelInViewLevelIndex(int index) => LevelInViewLevelIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; - public IArray LevelInViewViewIndex { get; } + public int[] LevelInViewViewIndex { get; } public int GetLevelInViewViewIndex(int index) => LevelInViewViewIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; public int NumLevelInView => LevelInViewEntityTable?.NumRows ?? 0; - public IArray LevelInViewList { get; } + public LevelInView[] LevelInViewList { get; } public LevelInView GetLevelInView(int n) { if (n < 0) return null; @@ -2876,26 +2877,26 @@ public LevelInView GetLevelInView(int n) public EntityTable CameraEntityTable { get; } - public IArray CameraId { get; } + public Int32[] CameraId { get; } public Int32 GetCameraId(int index, Int32 defaultValue = default) => CameraId?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray CameraIsPerspective { get; } + public Int32[] CameraIsPerspective { get; } public Int32 GetCameraIsPerspective(int index, Int32 defaultValue = default) => CameraIsPerspective?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray CameraVerticalExtent { get; } + public Double[] CameraVerticalExtent { get; } public Double GetCameraVerticalExtent(int index, Double defaultValue = default) => CameraVerticalExtent?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray CameraHorizontalExtent { get; } + public Double[] CameraHorizontalExtent { get; } public Double GetCameraHorizontalExtent(int index, Double defaultValue = default) => CameraHorizontalExtent?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray CameraFarDistance { get; } + public Double[] CameraFarDistance { get; } public Double GetCameraFarDistance(int index, Double defaultValue = default) => CameraFarDistance?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray CameraNearDistance { get; } + public Double[] CameraNearDistance { get; } public Double GetCameraNearDistance(int index, Double defaultValue = default) => CameraNearDistance?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray CameraTargetDistance { get; } + public Double[] CameraTargetDistance { get; } public Double GetCameraTargetDistance(int index, Double defaultValue = default) => CameraTargetDistance?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray CameraRightOffset { get; } + public Double[] CameraRightOffset { get; } public Double GetCameraRightOffset(int index, Double defaultValue = default) => CameraRightOffset?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray CameraUpOffset { get; } + public Double[] CameraUpOffset { get; } public Double GetCameraUpOffset(int index, Double defaultValue = default) => CameraUpOffset?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; public int NumCamera => CameraEntityTable?.NumRows ?? 0; - public IArray CameraList { get; } + public Camera[] CameraList { get; } public Camera GetCamera(int n) { if (n < 0) return null; @@ -2919,48 +2920,48 @@ public Camera GetCamera(int n) public EntityTable MaterialEntityTable { get; } - public IArray MaterialName { get; } + public String[] MaterialName { get; } public String GetMaterialName(int index, String defaultValue = "") => MaterialName?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray MaterialMaterialCategory { get; } + public String[] MaterialMaterialCategory { get; } public String GetMaterialMaterialCategory(int index, String defaultValue = "") => MaterialMaterialCategory?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray MaterialColor_X { get; } + public Double[] MaterialColor_X { get; } public Double GetMaterialColor_X(int index, Double defaultValue = default) => MaterialColor_X?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray MaterialColor_Y { get; } + public Double[] MaterialColor_Y { get; } public Double GetMaterialColor_Y(int index, Double defaultValue = default) => MaterialColor_Y?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray MaterialColor_Z { get; } + public Double[] MaterialColor_Z { get; } public Double GetMaterialColor_Z(int index, Double defaultValue = default) => MaterialColor_Z?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray MaterialColorUvScaling_X { get; } + public Double[] MaterialColorUvScaling_X { get; } public Double GetMaterialColorUvScaling_X(int index, Double defaultValue = default) => MaterialColorUvScaling_X?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray MaterialColorUvScaling_Y { get; } + public Double[] MaterialColorUvScaling_Y { get; } public Double GetMaterialColorUvScaling_Y(int index, Double defaultValue = default) => MaterialColorUvScaling_Y?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray MaterialColorUvOffset_X { get; } + public Double[] MaterialColorUvOffset_X { get; } public Double GetMaterialColorUvOffset_X(int index, Double defaultValue = default) => MaterialColorUvOffset_X?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray MaterialColorUvOffset_Y { get; } + public Double[] MaterialColorUvOffset_Y { get; } public Double GetMaterialColorUvOffset_Y(int index, Double defaultValue = default) => MaterialColorUvOffset_Y?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray MaterialNormalUvScaling_X { get; } + public Double[] MaterialNormalUvScaling_X { get; } public Double GetMaterialNormalUvScaling_X(int index, Double defaultValue = default) => MaterialNormalUvScaling_X?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray MaterialNormalUvScaling_Y { get; } + public Double[] MaterialNormalUvScaling_Y { get; } public Double GetMaterialNormalUvScaling_Y(int index, Double defaultValue = default) => MaterialNormalUvScaling_Y?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray MaterialNormalUvOffset_X { get; } + public Double[] MaterialNormalUvOffset_X { get; } public Double GetMaterialNormalUvOffset_X(int index, Double defaultValue = default) => MaterialNormalUvOffset_X?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray MaterialNormalUvOffset_Y { get; } + public Double[] MaterialNormalUvOffset_Y { get; } public Double GetMaterialNormalUvOffset_Y(int index, Double defaultValue = default) => MaterialNormalUvOffset_Y?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray MaterialNormalAmount { get; } + public Double[] MaterialNormalAmount { get; } public Double GetMaterialNormalAmount(int index, Double defaultValue = default) => MaterialNormalAmount?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray MaterialGlossiness { get; } + public Double[] MaterialGlossiness { get; } public Double GetMaterialGlossiness(int index, Double defaultValue = default) => MaterialGlossiness?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray MaterialSmoothness { get; } + public Double[] MaterialSmoothness { get; } public Double GetMaterialSmoothness(int index, Double defaultValue = default) => MaterialSmoothness?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray MaterialTransparency { get; } + public Double[] MaterialTransparency { get; } public Double GetMaterialTransparency(int index, Double defaultValue = default) => MaterialTransparency?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray MaterialColorTextureFileIndex { get; } + public int[] MaterialColorTextureFileIndex { get; } public int GetMaterialColorTextureFileIndex(int index) => MaterialColorTextureFileIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; - public IArray MaterialNormalTextureFileIndex { get; } + public int[] MaterialNormalTextureFileIndex { get; } public int GetMaterialNormalTextureFileIndex(int index) => MaterialNormalTextureFileIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; - public IArray MaterialElementIndex { get; } + public int[] MaterialElementIndex { get; } public int GetMaterialElementIndex(int index) => MaterialElementIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; public int NumMaterial => MaterialEntityTable?.NumRows ?? 0; - public IArray MaterialList { get; } + public Material[] MaterialList { get; } public Material GetMaterial(int n) { if (n < 0) return null; @@ -2995,18 +2996,18 @@ public Material GetMaterial(int n) public EntityTable MaterialInElementEntityTable { get; } - public IArray MaterialInElementArea { get; } + public Double[] MaterialInElementArea { get; } public Double GetMaterialInElementArea(int index, Double defaultValue = default) => MaterialInElementArea?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray MaterialInElementVolume { get; } + public Double[] MaterialInElementVolume { get; } public Double GetMaterialInElementVolume(int index, Double defaultValue = default) => MaterialInElementVolume?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray MaterialInElementIsPaint { get; } + public Boolean[] MaterialInElementIsPaint { get; } public Boolean GetMaterialInElementIsPaint(int index, Boolean defaultValue = default) => MaterialInElementIsPaint?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray MaterialInElementMaterialIndex { get; } + public int[] MaterialInElementMaterialIndex { get; } public int GetMaterialInElementMaterialIndex(int index) => MaterialInElementMaterialIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; - public IArray MaterialInElementElementIndex { get; } + public int[] MaterialInElementElementIndex { get; } public int GetMaterialInElementElementIndex(int index) => MaterialInElementElementIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; public int NumMaterialInElement => MaterialInElementEntityTable?.NumRows ?? 0; - public IArray MaterialInElementList { get; } + public MaterialInElement[] MaterialInElementList { get; } public MaterialInElement GetMaterialInElement(int n) { if (n < 0) return null; @@ -3026,18 +3027,18 @@ public MaterialInElement GetMaterialInElement(int n) public EntityTable CompoundStructureLayerEntityTable { get; } - public IArray CompoundStructureLayerOrderIndex { get; } + public Int32[] CompoundStructureLayerOrderIndex { get; } public Int32 GetCompoundStructureLayerOrderIndex(int index, Int32 defaultValue = default) => CompoundStructureLayerOrderIndex?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray CompoundStructureLayerWidth { get; } + public Double[] CompoundStructureLayerWidth { get; } public Double GetCompoundStructureLayerWidth(int index, Double defaultValue = default) => CompoundStructureLayerWidth?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray CompoundStructureLayerMaterialFunctionAssignment { get; } + public String[] CompoundStructureLayerMaterialFunctionAssignment { get; } public String GetCompoundStructureLayerMaterialFunctionAssignment(int index, String defaultValue = "") => CompoundStructureLayerMaterialFunctionAssignment?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray CompoundStructureLayerMaterialIndex { get; } + public int[] CompoundStructureLayerMaterialIndex { get; } public int GetCompoundStructureLayerMaterialIndex(int index) => CompoundStructureLayerMaterialIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; - public IArray CompoundStructureLayerCompoundStructureIndex { get; } + public int[] CompoundStructureLayerCompoundStructureIndex { get; } public int GetCompoundStructureLayerCompoundStructureIndex(int index) => CompoundStructureLayerCompoundStructureIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; public int NumCompoundStructureLayer => CompoundStructureLayerEntityTable?.NumRows ?? 0; - public IArray CompoundStructureLayerList { get; } + public CompoundStructureLayer[] CompoundStructureLayerList { get; } public CompoundStructureLayer GetCompoundStructureLayer(int n) { if (n < 0) return null; @@ -3057,12 +3058,12 @@ public CompoundStructureLayer GetCompoundStructureLayer(int n) public EntityTable CompoundStructureEntityTable { get; } - public IArray CompoundStructureWidth { get; } + public Double[] CompoundStructureWidth { get; } public Double GetCompoundStructureWidth(int index, Double defaultValue = default) => CompoundStructureWidth?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray CompoundStructureStructuralLayerIndex { get; } + public int[] CompoundStructureStructuralLayerIndex { get; } public int GetCompoundStructureStructuralLayerIndex(int index) => CompoundStructureStructuralLayerIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; public int NumCompoundStructure => CompoundStructureEntityTable?.NumRows ?? 0; - public IArray CompoundStructureList { get; } + public CompoundStructure[] CompoundStructureList { get; } public CompoundStructure GetCompoundStructure(int n) { if (n < 0) return null; @@ -3079,10 +3080,10 @@ public CompoundStructure GetCompoundStructure(int n) public EntityTable NodeEntityTable { get; } - public IArray NodeElementIndex { get; } + public int[] NodeElementIndex { get; } public int GetNodeElementIndex(int index) => NodeElementIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; public int NumNode => NodeEntityTable?.NumRows ?? 0; - public IArray NodeList { get; } + public Node[] NodeList { get; } public Node GetNode(int n) { if (n < 0) return null; @@ -3098,24 +3099,24 @@ public Node GetNode(int n) public EntityTable GeometryEntityTable { get; } - public IArray GeometryBox_Min_X { get; } + public Single[] GeometryBox_Min_X { get; } public Single GetGeometryBox_Min_X(int index, Single defaultValue = default) => GeometryBox_Min_X?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray GeometryBox_Min_Y { get; } + public Single[] GeometryBox_Min_Y { get; } public Single GetGeometryBox_Min_Y(int index, Single defaultValue = default) => GeometryBox_Min_Y?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray GeometryBox_Min_Z { get; } + public Single[] GeometryBox_Min_Z { get; } public Single GetGeometryBox_Min_Z(int index, Single defaultValue = default) => GeometryBox_Min_Z?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray GeometryBox_Max_X { get; } + public Single[] GeometryBox_Max_X { get; } public Single GetGeometryBox_Max_X(int index, Single defaultValue = default) => GeometryBox_Max_X?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray GeometryBox_Max_Y { get; } + public Single[] GeometryBox_Max_Y { get; } public Single GetGeometryBox_Max_Y(int index, Single defaultValue = default) => GeometryBox_Max_Y?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray GeometryBox_Max_Z { get; } + public Single[] GeometryBox_Max_Z { get; } public Single GetGeometryBox_Max_Z(int index, Single defaultValue = default) => GeometryBox_Max_Z?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray GeometryVertexCount { get; } + public Int32[] GeometryVertexCount { get; } public Int32 GetGeometryVertexCount(int index, Int32 defaultValue = default) => GeometryVertexCount?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray GeometryFaceCount { get; } + public Int32[] GeometryFaceCount { get; } public Int32 GetGeometryFaceCount(int index, Int32 defaultValue = default) => GeometryFaceCount?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; public int NumGeometry => GeometryEntityTable?.NumRows ?? 0; - public IArray GeometryList { get; } + public Geometry[] GeometryList { get; } public Geometry GetGeometry(int n) { if (n < 0) return null; @@ -3138,10 +3139,10 @@ public Geometry GetGeometry(int n) public EntityTable ShapeEntityTable { get; } - public IArray ShapeElementIndex { get; } + public int[] ShapeElementIndex { get; } public int GetShapeElementIndex(int index) => ShapeElementIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; public int NumShape => ShapeEntityTable?.NumRows ?? 0; - public IArray ShapeList { get; } + public Shape[] ShapeList { get; } public Shape GetShape(int n) { if (n < 0) return null; @@ -3157,10 +3158,10 @@ public Shape GetShape(int n) public EntityTable ShapeCollectionEntityTable { get; } - public IArray ShapeCollectionElementIndex { get; } + public int[] ShapeCollectionElementIndex { get; } public int GetShapeCollectionElementIndex(int index) => ShapeCollectionElementIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; public int NumShapeCollection => ShapeCollectionEntityTable?.NumRows ?? 0; - public IArray ShapeCollectionList { get; } + public ShapeCollection[] ShapeCollectionList { get; } public ShapeCollection GetShapeCollection(int n) { if (n < 0) return null; @@ -3176,12 +3177,12 @@ public ShapeCollection GetShapeCollection(int n) public EntityTable ShapeInShapeCollectionEntityTable { get; } - public IArray ShapeInShapeCollectionShapeIndex { get; } + public int[] ShapeInShapeCollectionShapeIndex { get; } public int GetShapeInShapeCollectionShapeIndex(int index) => ShapeInShapeCollectionShapeIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; - public IArray ShapeInShapeCollectionShapeCollectionIndex { get; } + public int[] ShapeInShapeCollectionShapeCollectionIndex { get; } public int GetShapeInShapeCollectionShapeCollectionIndex(int index) => ShapeInShapeCollectionShapeCollectionIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; public int NumShapeInShapeCollection => ShapeInShapeCollectionEntityTable?.NumRows ?? 0; - public IArray ShapeInShapeCollectionList { get; } + public ShapeInShapeCollection[] ShapeInShapeCollectionList { get; } public ShapeInShapeCollection GetShapeInShapeCollection(int n) { if (n < 0) return null; @@ -3198,14 +3199,14 @@ public ShapeInShapeCollection GetShapeInShapeCollection(int n) public EntityTable SystemEntityTable { get; } - public IArray SystemSystemType { get; } + public Int32[] SystemSystemType { get; } public Int32 GetSystemSystemType(int index, Int32 defaultValue = default) => SystemSystemType?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray SystemFamilyTypeIndex { get; } + public int[] SystemFamilyTypeIndex { get; } public int GetSystemFamilyTypeIndex(int index) => SystemFamilyTypeIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; - public IArray SystemElementIndex { get; } + public int[] SystemElementIndex { get; } public int GetSystemElementIndex(int index) => SystemElementIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; public int NumSystem => SystemEntityTable?.NumRows ?? 0; - public IArray SystemList { get; } + public System[] SystemList { get; } public System GetSystem(int n) { if (n < 0) return null; @@ -3223,14 +3224,14 @@ public System GetSystem(int n) public EntityTable ElementInSystemEntityTable { get; } - public IArray ElementInSystemRoles { get; } + public Int32[] ElementInSystemRoles { get; } public Int32 GetElementInSystemRoles(int index, Int32 defaultValue = default) => ElementInSystemRoles?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray ElementInSystemSystemIndex { get; } + public int[] ElementInSystemSystemIndex { get; } public int GetElementInSystemSystemIndex(int index) => ElementInSystemSystemIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; - public IArray ElementInSystemElementIndex { get; } + public int[] ElementInSystemElementIndex { get; } public int GetElementInSystemElementIndex(int index) => ElementInSystemElementIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; public int NumElementInSystem => ElementInSystemEntityTable?.NumRows ?? 0; - public IArray ElementInSystemList { get; } + public ElementInSystem[] ElementInSystemList { get; } public ElementInSystem GetElementInSystem(int n) { if (n < 0) return null; @@ -3248,16 +3249,16 @@ public ElementInSystem GetElementInSystem(int n) public EntityTable WarningEntityTable { get; } - public IArray WarningGuid { get; } + public String[] WarningGuid { get; } public String GetWarningGuid(int index, String defaultValue = "") => WarningGuid?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray WarningSeverity { get; } + public String[] WarningSeverity { get; } public String GetWarningSeverity(int index, String defaultValue = "") => WarningSeverity?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray WarningDescription { get; } + public String[] WarningDescription { get; } public String GetWarningDescription(int index, String defaultValue = "") => WarningDescription?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray WarningBimDocumentIndex { get; } + public int[] WarningBimDocumentIndex { get; } public int GetWarningBimDocumentIndex(int index) => WarningBimDocumentIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; public int NumWarning => WarningEntityTable?.NumRows ?? 0; - public IArray WarningList { get; } + public Warning[] WarningList { get; } public Warning GetWarning(int n) { if (n < 0) return null; @@ -3276,12 +3277,12 @@ public Warning GetWarning(int n) public EntityTable ElementInWarningEntityTable { get; } - public IArray ElementInWarningWarningIndex { get; } + public int[] ElementInWarningWarningIndex { get; } public int GetElementInWarningWarningIndex(int index) => ElementInWarningWarningIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; - public IArray ElementInWarningElementIndex { get; } + public int[] ElementInWarningElementIndex { get; } public int GetElementInWarningElementIndex(int index) => ElementInWarningElementIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; public int NumElementInWarning => ElementInWarningEntityTable?.NumRows ?? 0; - public IArray ElementInWarningList { get; } + public ElementInWarning[] ElementInWarningList { get; } public ElementInWarning GetElementInWarning(int n) { if (n < 0) return null; @@ -3298,24 +3299,24 @@ public ElementInWarning GetElementInWarning(int n) public EntityTable BasePointEntityTable { get; } - public IArray BasePointIsSurveyPoint { get; } + public Boolean[] BasePointIsSurveyPoint { get; } public Boolean GetBasePointIsSurveyPoint(int index, Boolean defaultValue = default) => BasePointIsSurveyPoint?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray BasePointPosition_X { get; } + public Double[] BasePointPosition_X { get; } public Double GetBasePointPosition_X(int index, Double defaultValue = default) => BasePointPosition_X?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray BasePointPosition_Y { get; } + public Double[] BasePointPosition_Y { get; } public Double GetBasePointPosition_Y(int index, Double defaultValue = default) => BasePointPosition_Y?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray BasePointPosition_Z { get; } + public Double[] BasePointPosition_Z { get; } public Double GetBasePointPosition_Z(int index, Double defaultValue = default) => BasePointPosition_Z?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray BasePointSharedPosition_X { get; } + public Double[] BasePointSharedPosition_X { get; } public Double GetBasePointSharedPosition_X(int index, Double defaultValue = default) => BasePointSharedPosition_X?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray BasePointSharedPosition_Y { get; } + public Double[] BasePointSharedPosition_Y { get; } public Double GetBasePointSharedPosition_Y(int index, Double defaultValue = default) => BasePointSharedPosition_Y?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray BasePointSharedPosition_Z { get; } + public Double[] BasePointSharedPosition_Z { get; } public Double GetBasePointSharedPosition_Z(int index, Double defaultValue = default) => BasePointSharedPosition_Z?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray BasePointElementIndex { get; } + public int[] BasePointElementIndex { get; } public int GetBasePointElementIndex(int index) => BasePointElementIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; public int NumBasePoint => BasePointEntityTable?.NumRows ?? 0; - public IArray BasePointList { get; } + public BasePoint[] BasePointList { get; } public BasePoint GetBasePoint(int n) { if (n < 0) return null; @@ -3338,18 +3339,18 @@ public BasePoint GetBasePoint(int n) public EntityTable PhaseFilterEntityTable { get; } - public IArray PhaseFilterNew { get; } + public Int32[] PhaseFilterNew { get; } public Int32 GetPhaseFilterNew(int index, Int32 defaultValue = default) => PhaseFilterNew?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray PhaseFilterExisting { get; } + public Int32[] PhaseFilterExisting { get; } public Int32 GetPhaseFilterExisting(int index, Int32 defaultValue = default) => PhaseFilterExisting?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray PhaseFilterDemolished { get; } + public Int32[] PhaseFilterDemolished { get; } public Int32 GetPhaseFilterDemolished(int index, Int32 defaultValue = default) => PhaseFilterDemolished?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray PhaseFilterTemporary { get; } + public Int32[] PhaseFilterTemporary { get; } public Int32 GetPhaseFilterTemporary(int index, Int32 defaultValue = default) => PhaseFilterTemporary?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray PhaseFilterElementIndex { get; } + public int[] PhaseFilterElementIndex { get; } public int GetPhaseFilterElementIndex(int index) => PhaseFilterElementIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; public int NumPhaseFilter => PhaseFilterEntityTable?.NumRows ?? 0; - public IArray PhaseFilterList { get; } + public PhaseFilter[] PhaseFilterList { get; } public PhaseFilter GetPhaseFilter(int n) { if (n < 0) return null; @@ -3369,38 +3370,38 @@ public PhaseFilter GetPhaseFilter(int n) public EntityTable GridEntityTable { get; } - public IArray GridStartPoint_X { get; } + public Double[] GridStartPoint_X { get; } public Double GetGridStartPoint_X(int index, Double defaultValue = default) => GridStartPoint_X?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray GridStartPoint_Y { get; } + public Double[] GridStartPoint_Y { get; } public Double GetGridStartPoint_Y(int index, Double defaultValue = default) => GridStartPoint_Y?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray GridStartPoint_Z { get; } + public Double[] GridStartPoint_Z { get; } public Double GetGridStartPoint_Z(int index, Double defaultValue = default) => GridStartPoint_Z?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray GridEndPoint_X { get; } + public Double[] GridEndPoint_X { get; } public Double GetGridEndPoint_X(int index, Double defaultValue = default) => GridEndPoint_X?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray GridEndPoint_Y { get; } + public Double[] GridEndPoint_Y { get; } public Double GetGridEndPoint_Y(int index, Double defaultValue = default) => GridEndPoint_Y?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray GridEndPoint_Z { get; } + public Double[] GridEndPoint_Z { get; } public Double GetGridEndPoint_Z(int index, Double defaultValue = default) => GridEndPoint_Z?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray GridIsCurved { get; } + public Boolean[] GridIsCurved { get; } public Boolean GetGridIsCurved(int index, Boolean defaultValue = default) => GridIsCurved?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray GridExtents_Min_X { get; } + public Double[] GridExtents_Min_X { get; } public Double GetGridExtents_Min_X(int index, Double defaultValue = default) => GridExtents_Min_X?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray GridExtents_Min_Y { get; } + public Double[] GridExtents_Min_Y { get; } public Double GetGridExtents_Min_Y(int index, Double defaultValue = default) => GridExtents_Min_Y?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray GridExtents_Min_Z { get; } + public Double[] GridExtents_Min_Z { get; } public Double GetGridExtents_Min_Z(int index, Double defaultValue = default) => GridExtents_Min_Z?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray GridExtents_Max_X { get; } + public Double[] GridExtents_Max_X { get; } public Double GetGridExtents_Max_X(int index, Double defaultValue = default) => GridExtents_Max_X?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray GridExtents_Max_Y { get; } + public Double[] GridExtents_Max_Y { get; } public Double GetGridExtents_Max_Y(int index, Double defaultValue = default) => GridExtents_Max_Y?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray GridExtents_Max_Z { get; } + public Double[] GridExtents_Max_Z { get; } public Double GetGridExtents_Max_Z(int index, Double defaultValue = default) => GridExtents_Max_Z?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray GridFamilyTypeIndex { get; } + public int[] GridFamilyTypeIndex { get; } public int GetGridFamilyTypeIndex(int index) => GridFamilyTypeIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; - public IArray GridElementIndex { get; } + public int[] GridElementIndex { get; } public int GetGridElementIndex(int index) => GridElementIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; public int NumGrid => GridEntityTable?.NumRows ?? 0; - public IArray GridList { get; } + public Grid[] GridList { get; } public Grid GetGrid(int n) { if (n < 0) return null; @@ -3430,20 +3431,20 @@ public Grid GetGrid(int n) public EntityTable AreaEntityTable { get; } - public IArray AreaValue { get; } + public Double[] AreaValue { get; } public Double GetAreaValue(int index, Double defaultValue = default) => AreaValue?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray AreaPerimeter { get; } + public Double[] AreaPerimeter { get; } public Double GetAreaPerimeter(int index, Double defaultValue = default) => AreaPerimeter?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray AreaNumber { get; } + public String[] AreaNumber { get; } public String GetAreaNumber(int index, String defaultValue = "") => AreaNumber?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray AreaIsGrossInterior { get; } + public Boolean[] AreaIsGrossInterior { get; } public Boolean GetAreaIsGrossInterior(int index, Boolean defaultValue = default) => AreaIsGrossInterior?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray AreaAreaSchemeIndex { get; } + public int[] AreaAreaSchemeIndex { get; } public int GetAreaAreaSchemeIndex(int index) => AreaAreaSchemeIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; - public IArray AreaElementIndex { get; } + public int[] AreaElementIndex { get; } public int GetAreaElementIndex(int index) => AreaElementIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; public int NumArea => AreaEntityTable?.NumRows ?? 0; - public IArray AreaList { get; } + public Area[] AreaList { get; } public Area GetArea(int n) { if (n < 0) return null; @@ -3464,12 +3465,12 @@ public Area GetArea(int n) public EntityTable AreaSchemeEntityTable { get; } - public IArray AreaSchemeIsGrossBuildingArea { get; } + public Boolean[] AreaSchemeIsGrossBuildingArea { get; } public Boolean GetAreaSchemeIsGrossBuildingArea(int index, Boolean defaultValue = default) => AreaSchemeIsGrossBuildingArea?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray AreaSchemeElementIndex { get; } + public int[] AreaSchemeElementIndex { get; } public int GetAreaSchemeElementIndex(int index) => AreaSchemeElementIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; public int NumAreaScheme => AreaSchemeEntityTable?.NumRows ?? 0; - public IArray AreaSchemeList { get; } + public AreaScheme[] AreaSchemeList { get; } public AreaScheme GetAreaScheme(int n) { if (n < 0) return null; @@ -3486,10 +3487,10 @@ public AreaScheme GetAreaScheme(int n) public EntityTable ScheduleEntityTable { get; } - public IArray ScheduleElementIndex { get; } + public int[] ScheduleElementIndex { get; } public int GetScheduleElementIndex(int index) => ScheduleElementIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; public int NumSchedule => ScheduleEntityTable?.NumRows ?? 0; - public IArray ScheduleList { get; } + public Schedule[] ScheduleList { get; } public Schedule GetSchedule(int n) { if (n < 0) return null; @@ -3505,14 +3506,14 @@ public Schedule GetSchedule(int n) public EntityTable ScheduleColumnEntityTable { get; } - public IArray ScheduleColumnName { get; } + public String[] ScheduleColumnName { get; } public String GetScheduleColumnName(int index, String defaultValue = "") => ScheduleColumnName?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray ScheduleColumnColumnIndex { get; } + public Int32[] ScheduleColumnColumnIndex { get; } public Int32 GetScheduleColumnColumnIndex(int index, Int32 defaultValue = default) => ScheduleColumnColumnIndex?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray ScheduleColumnScheduleIndex { get; } + public int[] ScheduleColumnScheduleIndex { get; } public int GetScheduleColumnScheduleIndex(int index) => ScheduleColumnScheduleIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; public int NumScheduleColumn => ScheduleColumnEntityTable?.NumRows ?? 0; - public IArray ScheduleColumnList { get; } + public ScheduleColumn[] ScheduleColumnList { get; } public ScheduleColumn GetScheduleColumn(int n) { if (n < 0) return null; @@ -3530,14 +3531,14 @@ public ScheduleColumn GetScheduleColumn(int n) public EntityTable ScheduleCellEntityTable { get; } - public IArray ScheduleCellValue { get; } + public String[] ScheduleCellValue { get; } public String GetScheduleCellValue(int index, String defaultValue = "") => ScheduleCellValue?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray ScheduleCellRowIndex { get; } + public Int32[] ScheduleCellRowIndex { get; } public Int32 GetScheduleCellRowIndex(int index, Int32 defaultValue = default) => ScheduleCellRowIndex?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray ScheduleCellScheduleColumnIndex { get; } + public int[] ScheduleCellScheduleColumnIndex { get; } public int GetScheduleCellScheduleColumnIndex(int index) => ScheduleCellScheduleColumnIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; public int NumScheduleCell => ScheduleCellEntityTable?.NumRows ?? 0; - public IArray ScheduleCellList { get; } + public ScheduleCell[] ScheduleCellList { get; } public ScheduleCell GetScheduleCell(int n) { if (n < 0) return null; @@ -3555,10 +3556,10 @@ public ScheduleCell GetScheduleCell(int n) public EntityTable ViewSheetSetEntityTable { get; } - public IArray ViewSheetSetElementIndex { get; } + public int[] ViewSheetSetElementIndex { get; } public int GetViewSheetSetElementIndex(int index) => ViewSheetSetElementIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; public int NumViewSheetSet => ViewSheetSetEntityTable?.NumRows ?? 0; - public IArray ViewSheetSetList { get; } + public ViewSheetSet[] ViewSheetSetList { get; } public ViewSheetSet GetViewSheetSet(int n) { if (n < 0) return null; @@ -3574,12 +3575,12 @@ public ViewSheetSet GetViewSheetSet(int n) public EntityTable ViewSheetEntityTable { get; } - public IArray ViewSheetFamilyTypeIndex { get; } + public int[] ViewSheetFamilyTypeIndex { get; } public int GetViewSheetFamilyTypeIndex(int index) => ViewSheetFamilyTypeIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; - public IArray ViewSheetElementIndex { get; } + public int[] ViewSheetElementIndex { get; } public int GetViewSheetElementIndex(int index) => ViewSheetElementIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; public int NumViewSheet => ViewSheetEntityTable?.NumRows ?? 0; - public IArray ViewSheetList { get; } + public ViewSheet[] ViewSheetList { get; } public ViewSheet GetViewSheet(int n) { if (n < 0) return null; @@ -3596,12 +3597,12 @@ public ViewSheet GetViewSheet(int n) public EntityTable ViewSheetInViewSheetSetEntityTable { get; } - public IArray ViewSheetInViewSheetSetViewSheetIndex { get; } + public int[] ViewSheetInViewSheetSetViewSheetIndex { get; } public int GetViewSheetInViewSheetSetViewSheetIndex(int index) => ViewSheetInViewSheetSetViewSheetIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; - public IArray ViewSheetInViewSheetSetViewSheetSetIndex { get; } + public int[] ViewSheetInViewSheetSetViewSheetSetIndex { get; } public int GetViewSheetInViewSheetSetViewSheetSetIndex(int index) => ViewSheetInViewSheetSetViewSheetSetIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; public int NumViewSheetInViewSheetSet => ViewSheetInViewSheetSetEntityTable?.NumRows ?? 0; - public IArray ViewSheetInViewSheetSetList { get; } + public ViewSheetInViewSheetSet[] ViewSheetInViewSheetSetList { get; } public ViewSheetInViewSheetSet GetViewSheetInViewSheetSet(int n) { if (n < 0) return null; @@ -3618,12 +3619,12 @@ public ViewSheetInViewSheetSet GetViewSheetInViewSheetSet(int n) public EntityTable ViewInViewSheetSetEntityTable { get; } - public IArray ViewInViewSheetSetViewIndex { get; } + public int[] ViewInViewSheetSetViewIndex { get; } public int GetViewInViewSheetSetViewIndex(int index) => ViewInViewSheetSetViewIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; - public IArray ViewInViewSheetSetViewSheetSetIndex { get; } + public int[] ViewInViewSheetSetViewSheetSetIndex { get; } public int GetViewInViewSheetSetViewSheetSetIndex(int index) => ViewInViewSheetSetViewSheetSetIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; public int NumViewInViewSheetSet => ViewInViewSheetSetEntityTable?.NumRows ?? 0; - public IArray ViewInViewSheetSetList { get; } + public ViewInViewSheetSet[] ViewInViewSheetSetList { get; } public ViewInViewSheetSet GetViewInViewSheetSet(int n) { if (n < 0) return null; @@ -3640,12 +3641,12 @@ public ViewInViewSheetSet GetViewInViewSheetSet(int n) public EntityTable ViewInViewSheetEntityTable { get; } - public IArray ViewInViewSheetViewIndex { get; } + public int[] ViewInViewSheetViewIndex { get; } public int GetViewInViewSheetViewIndex(int index) => ViewInViewSheetViewIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; - public IArray ViewInViewSheetViewSheetIndex { get; } + public int[] ViewInViewSheetViewSheetIndex { get; } public int GetViewInViewSheetViewSheetIndex(int index) => ViewInViewSheetViewSheetIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; public int NumViewInViewSheet => ViewInViewSheetEntityTable?.NumRows ?? 0; - public IArray ViewInViewSheetList { get; } + public ViewInViewSheet[] ViewInViewSheetList { get; } public ViewInViewSheet GetViewInViewSheet(int n) { if (n < 0) return null; @@ -3662,20 +3663,20 @@ public ViewInViewSheet GetViewInViewSheet(int n) public EntityTable SiteEntityTable { get; } - public IArray SiteLatitude { get; } + public Double[] SiteLatitude { get; } public Double GetSiteLatitude(int index, Double defaultValue = default) => SiteLatitude?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray SiteLongitude { get; } + public Double[] SiteLongitude { get; } public Double GetSiteLongitude(int index, Double defaultValue = default) => SiteLongitude?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray SiteAddress { get; } + public String[] SiteAddress { get; } public String GetSiteAddress(int index, String defaultValue = "") => SiteAddress?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray SiteElevation { get; } + public Double[] SiteElevation { get; } public Double GetSiteElevation(int index, Double defaultValue = default) => SiteElevation?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray SiteNumber { get; } + public String[] SiteNumber { get; } public String GetSiteNumber(int index, String defaultValue = "") => SiteNumber?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray SiteElementIndex { get; } + public int[] SiteElementIndex { get; } public int GetSiteElementIndex(int index) => SiteElementIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; public int NumSite => SiteEntityTable?.NumRows ?? 0; - public IArray SiteList { get; } + public Site[] SiteList { get; } public Site GetSite(int n) { if (n < 0) return null; @@ -3696,18 +3697,18 @@ public Site GetSite(int n) public EntityTable BuildingEntityTable { get; } - public IArray BuildingElevation { get; } + public Double[] BuildingElevation { get; } public Double GetBuildingElevation(int index, Double defaultValue = default) => BuildingElevation?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray BuildingTerrainElevation { get; } + public Double[] BuildingTerrainElevation { get; } public Double GetBuildingTerrainElevation(int index, Double defaultValue = default) => BuildingTerrainElevation?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray BuildingAddress { get; } + public String[] BuildingAddress { get; } public String GetBuildingAddress(int index, String defaultValue = "") => BuildingAddress?.ElementAtOrDefault(index, defaultValue) ?? defaultValue; - public IArray BuildingSiteIndex { get; } + public int[] BuildingSiteIndex { get; } public int GetBuildingSiteIndex(int index) => BuildingSiteIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; - public IArray BuildingElementIndex { get; } + public int[] BuildingElementIndex { get; } public int GetBuildingElementIndex(int index) => BuildingElementIndex?.ElementAtOrDefault(index, EntityRelation.None) ?? EntityRelation.None; public int NumBuilding => BuildingEntityTable?.NumRows ?? 0; - public IArray BuildingList { get; } + public Building[] BuildingList { get; } public Building GetBuilding(int n) { if (n < 0) return null; @@ -3724,60 +3725,60 @@ public Building GetBuilding(int n) // All entity collections public Dictionary> AllEntities => new Dictionary>() { - {"Vim.Asset", AssetList.ToEnumerable()}, - {"Vim.DisplayUnit", DisplayUnitList.ToEnumerable()}, - {"Vim.ParameterDescriptor", ParameterDescriptorList.ToEnumerable()}, - {"Vim.Parameter", ParameterList.ToEnumerable()}, - {"Vim.Element", ElementList.ToEnumerable()}, - {"Vim.Workset", WorksetList.ToEnumerable()}, - {"Vim.AssemblyInstance", AssemblyInstanceList.ToEnumerable()}, - {"Vim.Group", GroupList.ToEnumerable()}, - {"Vim.DesignOption", DesignOptionList.ToEnumerable()}, - {"Vim.Level", LevelList.ToEnumerable()}, - {"Vim.Phase", PhaseList.ToEnumerable()}, - {"Vim.Room", RoomList.ToEnumerable()}, - {"Vim.BimDocument", BimDocumentList.ToEnumerable()}, - {"Vim.DisplayUnitInBimDocument", DisplayUnitInBimDocumentList.ToEnumerable()}, - {"Vim.PhaseOrderInBimDocument", PhaseOrderInBimDocumentList.ToEnumerable()}, - {"Vim.Category", CategoryList.ToEnumerable()}, - {"Vim.Family", FamilyList.ToEnumerable()}, - {"Vim.FamilyType", FamilyTypeList.ToEnumerable()}, - {"Vim.FamilyInstance", FamilyInstanceList.ToEnumerable()}, - {"Vim.View", ViewList.ToEnumerable()}, - {"Vim.ElementInView", ElementInViewList.ToEnumerable()}, - {"Vim.ShapeInView", ShapeInViewList.ToEnumerable()}, - {"Vim.AssetInView", AssetInViewList.ToEnumerable()}, - {"Vim.AssetInViewSheet", AssetInViewSheetList.ToEnumerable()}, - {"Vim.LevelInView", LevelInViewList.ToEnumerable()}, - {"Vim.Camera", CameraList.ToEnumerable()}, - {"Vim.Material", MaterialList.ToEnumerable()}, - {"Vim.MaterialInElement", MaterialInElementList.ToEnumerable()}, - {"Vim.CompoundStructureLayer", CompoundStructureLayerList.ToEnumerable()}, - {"Vim.CompoundStructure", CompoundStructureList.ToEnumerable()}, - {"Vim.Node", NodeList.ToEnumerable()}, - {"Vim.Geometry", GeometryList.ToEnumerable()}, - {"Vim.Shape", ShapeList.ToEnumerable()}, - {"Vim.ShapeCollection", ShapeCollectionList.ToEnumerable()}, - {"Vim.ShapeInShapeCollection", ShapeInShapeCollectionList.ToEnumerable()}, - {"Vim.System", SystemList.ToEnumerable()}, - {"Vim.ElementInSystem", ElementInSystemList.ToEnumerable()}, - {"Vim.Warning", WarningList.ToEnumerable()}, - {"Vim.ElementInWarning", ElementInWarningList.ToEnumerable()}, - {"Vim.BasePoint", BasePointList.ToEnumerable()}, - {"Vim.PhaseFilter", PhaseFilterList.ToEnumerable()}, - {"Vim.Grid", GridList.ToEnumerable()}, - {"Vim.Area", AreaList.ToEnumerable()}, - {"Vim.AreaScheme", AreaSchemeList.ToEnumerable()}, - {"Vim.Schedule", ScheduleList.ToEnumerable()}, - {"Vim.ScheduleColumn", ScheduleColumnList.ToEnumerable()}, - {"Vim.ScheduleCell", ScheduleCellList.ToEnumerable()}, - {"Vim.ViewSheetSet", ViewSheetSetList.ToEnumerable()}, - {"Vim.ViewSheet", ViewSheetList.ToEnumerable()}, - {"Vim.ViewSheetInViewSheetSet", ViewSheetInViewSheetSetList.ToEnumerable()}, - {"Vim.ViewInViewSheetSet", ViewInViewSheetSetList.ToEnumerable()}, - {"Vim.ViewInViewSheet", ViewInViewSheetList.ToEnumerable()}, - {"Vim.Site", SiteList.ToEnumerable()}, - {"Vim.Building", BuildingList.ToEnumerable()}, + {"Vim.Asset", AssetList}, + {"Vim.DisplayUnit", DisplayUnitList}, + {"Vim.ParameterDescriptor", ParameterDescriptorList}, + {"Vim.Parameter", ParameterList}, + {"Vim.Element", ElementList}, + {"Vim.Workset", WorksetList}, + {"Vim.AssemblyInstance", AssemblyInstanceList}, + {"Vim.Group", GroupList}, + {"Vim.DesignOption", DesignOptionList}, + {"Vim.Level", LevelList}, + {"Vim.Phase", PhaseList}, + {"Vim.Room", RoomList}, + {"Vim.BimDocument", BimDocumentList}, + {"Vim.DisplayUnitInBimDocument", DisplayUnitInBimDocumentList}, + {"Vim.PhaseOrderInBimDocument", PhaseOrderInBimDocumentList}, + {"Vim.Category", CategoryList}, + {"Vim.Family", FamilyList}, + {"Vim.FamilyType", FamilyTypeList}, + {"Vim.FamilyInstance", FamilyInstanceList}, + {"Vim.View", ViewList}, + {"Vim.ElementInView", ElementInViewList}, + {"Vim.ShapeInView", ShapeInViewList}, + {"Vim.AssetInView", AssetInViewList}, + {"Vim.AssetInViewSheet", AssetInViewSheetList}, + {"Vim.LevelInView", LevelInViewList}, + {"Vim.Camera", CameraList}, + {"Vim.Material", MaterialList}, + {"Vim.MaterialInElement", MaterialInElementList}, + {"Vim.CompoundStructureLayer", CompoundStructureLayerList}, + {"Vim.CompoundStructure", CompoundStructureList}, + {"Vim.Node", NodeList}, + {"Vim.Geometry", GeometryList}, + {"Vim.Shape", ShapeList}, + {"Vim.ShapeCollection", ShapeCollectionList}, + {"Vim.ShapeInShapeCollection", ShapeInShapeCollectionList}, + {"Vim.System", SystemList}, + {"Vim.ElementInSystem", ElementInSystemList}, + {"Vim.Warning", WarningList}, + {"Vim.ElementInWarning", ElementInWarningList}, + {"Vim.BasePoint", BasePointList}, + {"Vim.PhaseFilter", PhaseFilterList}, + {"Vim.Grid", GridList}, + {"Vim.Area", AreaList}, + {"Vim.AreaScheme", AreaSchemeList}, + {"Vim.Schedule", ScheduleList}, + {"Vim.ScheduleColumn", ScheduleColumnList}, + {"Vim.ScheduleCell", ScheduleCellList}, + {"Vim.ViewSheetSet", ViewSheetSetList}, + {"Vim.ViewSheet", ViewSheetList}, + {"Vim.ViewSheetInViewSheetSet", ViewSheetInViewSheetSetList}, + {"Vim.ViewInViewSheetSet", ViewInViewSheetSetList}, + {"Vim.ViewInViewSheet", ViewInViewSheetList}, + {"Vim.Site", SiteList}, + {"Vim.Building", BuildingList}, }; // Entity types from table names @@ -3898,389 +3899,389 @@ public DocumentModel(Document d, bool inParallel = true) BuildingEntityTable = Document.GetTable("Vim.Building"); // Initialize entity arrays - AssetBufferName = AssetEntityTable?.GetStringColumnValues("string:BufferName") ?? Array.Empty().ToIArray(); - DisplayUnitSpec = DisplayUnitEntityTable?.GetStringColumnValues("string:Spec") ?? Array.Empty().ToIArray(); - DisplayUnitType = DisplayUnitEntityTable?.GetStringColumnValues("string:Type") ?? Array.Empty().ToIArray(); - DisplayUnitLabel = DisplayUnitEntityTable?.GetStringColumnValues("string:Label") ?? Array.Empty().ToIArray(); - ParameterDescriptorName = ParameterDescriptorEntityTable?.GetStringColumnValues("string:Name") ?? Array.Empty().ToIArray(); - ParameterDescriptorGroup = ParameterDescriptorEntityTable?.GetStringColumnValues("string:Group") ?? Array.Empty().ToIArray(); - ParameterDescriptorParameterType = ParameterDescriptorEntityTable?.GetStringColumnValues("string:ParameterType") ?? Array.Empty().ToIArray(); - ParameterDescriptorIsInstance = ParameterDescriptorEntityTable?.GetDataColumnValues("byte:IsInstance") ?? Array.Empty().ToIArray(); - ParameterDescriptorIsShared = ParameterDescriptorEntityTable?.GetDataColumnValues("byte:IsShared") ?? Array.Empty().ToIArray(); - ParameterDescriptorIsReadOnly = ParameterDescriptorEntityTable?.GetDataColumnValues("byte:IsReadOnly") ?? Array.Empty().ToIArray(); - ParameterDescriptorFlags = ParameterDescriptorEntityTable?.GetDataColumnValues("int:Flags") ?? Array.Empty().ToIArray(); - ParameterDescriptorGuid = ParameterDescriptorEntityTable?.GetStringColumnValues("string:Guid") ?? Array.Empty().ToIArray(); - ParameterValue = ParameterEntityTable?.GetStringColumnValues("string:Value") ?? Array.Empty().ToIArray(); - ElementId = (ElementEntityTable?.GetDataColumnValues("long:Id") ?? ElementEntityTable?.GetDataColumnValues("int:Id")?.Select(v => (Int64) v)) ?? Array.Empty().ToIArray(); - ElementType = ElementEntityTable?.GetStringColumnValues("string:Type") ?? Array.Empty().ToIArray(); - ElementName = ElementEntityTable?.GetStringColumnValues("string:Name") ?? Array.Empty().ToIArray(); - ElementUniqueId = ElementEntityTable?.GetStringColumnValues("string:UniqueId") ?? Array.Empty().ToIArray(); - ElementLocation_X = ElementEntityTable?.GetDataColumnValues("float:Location.X") ?? Array.Empty().ToIArray(); - ElementLocation_Y = ElementEntityTable?.GetDataColumnValues("float:Location.Y") ?? Array.Empty().ToIArray(); - ElementLocation_Z = ElementEntityTable?.GetDataColumnValues("float:Location.Z") ?? Array.Empty().ToIArray(); - ElementFamilyName = ElementEntityTable?.GetStringColumnValues("string:FamilyName") ?? Array.Empty().ToIArray(); - ElementIsPinned = ElementEntityTable?.GetDataColumnValues("byte:IsPinned") ?? Array.Empty().ToIArray(); - WorksetId = WorksetEntityTable?.GetDataColumnValues("int:Id") ?? Array.Empty().ToIArray(); - WorksetName = WorksetEntityTable?.GetStringColumnValues("string:Name") ?? Array.Empty().ToIArray(); - WorksetKind = WorksetEntityTable?.GetStringColumnValues("string:Kind") ?? Array.Empty().ToIArray(); - WorksetIsOpen = WorksetEntityTable?.GetDataColumnValues("byte:IsOpen") ?? Array.Empty().ToIArray(); - WorksetIsEditable = WorksetEntityTable?.GetDataColumnValues("byte:IsEditable") ?? Array.Empty().ToIArray(); - WorksetOwner = WorksetEntityTable?.GetStringColumnValues("string:Owner") ?? Array.Empty().ToIArray(); - WorksetUniqueId = WorksetEntityTable?.GetStringColumnValues("string:UniqueId") ?? Array.Empty().ToIArray(); - AssemblyInstanceAssemblyTypeName = AssemblyInstanceEntityTable?.GetStringColumnValues("string:AssemblyTypeName") ?? Array.Empty().ToIArray(); - AssemblyInstancePosition_X = AssemblyInstanceEntityTable?.GetDataColumnValues("float:Position.X") ?? Array.Empty().ToIArray(); - AssemblyInstancePosition_Y = AssemblyInstanceEntityTable?.GetDataColumnValues("float:Position.Y") ?? Array.Empty().ToIArray(); - AssemblyInstancePosition_Z = AssemblyInstanceEntityTable?.GetDataColumnValues("float:Position.Z") ?? Array.Empty().ToIArray(); - GroupGroupType = GroupEntityTable?.GetStringColumnValues("string:GroupType") ?? Array.Empty().ToIArray(); - GroupPosition_X = GroupEntityTable?.GetDataColumnValues("float:Position.X") ?? Array.Empty().ToIArray(); - GroupPosition_Y = GroupEntityTable?.GetDataColumnValues("float:Position.Y") ?? Array.Empty().ToIArray(); - GroupPosition_Z = GroupEntityTable?.GetDataColumnValues("float:Position.Z") ?? Array.Empty().ToIArray(); - DesignOptionIsPrimary = DesignOptionEntityTable?.GetDataColumnValues("byte:IsPrimary") ?? Array.Empty().ToIArray(); - LevelElevation = LevelEntityTable?.GetDataColumnValues("double:Elevation") ?? Array.Empty().ToIArray(); - RoomBaseOffset = RoomEntityTable?.GetDataColumnValues("double:BaseOffset") ?? Array.Empty().ToIArray(); - RoomLimitOffset = RoomEntityTable?.GetDataColumnValues("double:LimitOffset") ?? Array.Empty().ToIArray(); - RoomUnboundedHeight = RoomEntityTable?.GetDataColumnValues("double:UnboundedHeight") ?? Array.Empty().ToIArray(); - RoomVolume = RoomEntityTable?.GetDataColumnValues("double:Volume") ?? Array.Empty().ToIArray(); - RoomPerimeter = RoomEntityTable?.GetDataColumnValues("double:Perimeter") ?? Array.Empty().ToIArray(); - RoomArea = RoomEntityTable?.GetDataColumnValues("double:Area") ?? Array.Empty().ToIArray(); - RoomNumber = RoomEntityTable?.GetStringColumnValues("string:Number") ?? Array.Empty().ToIArray(); - BimDocumentTitle = BimDocumentEntityTable?.GetStringColumnValues("string:Title") ?? Array.Empty().ToIArray(); - BimDocumentIsMetric = BimDocumentEntityTable?.GetDataColumnValues("byte:IsMetric") ?? Array.Empty().ToIArray(); - BimDocumentGuid = BimDocumentEntityTable?.GetStringColumnValues("string:Guid") ?? Array.Empty().ToIArray(); - BimDocumentNumSaves = BimDocumentEntityTable?.GetDataColumnValues("int:NumSaves") ?? Array.Empty().ToIArray(); - BimDocumentIsLinked = BimDocumentEntityTable?.GetDataColumnValues("byte:IsLinked") ?? Array.Empty().ToIArray(); - BimDocumentIsDetached = BimDocumentEntityTable?.GetDataColumnValues("byte:IsDetached") ?? Array.Empty().ToIArray(); - BimDocumentIsWorkshared = BimDocumentEntityTable?.GetDataColumnValues("byte:IsWorkshared") ?? Array.Empty().ToIArray(); - BimDocumentPathName = BimDocumentEntityTable?.GetStringColumnValues("string:PathName") ?? Array.Empty().ToIArray(); - BimDocumentLatitude = BimDocumentEntityTable?.GetDataColumnValues("double:Latitude") ?? Array.Empty().ToIArray(); - BimDocumentLongitude = BimDocumentEntityTable?.GetDataColumnValues("double:Longitude") ?? Array.Empty().ToIArray(); - BimDocumentTimeZone = BimDocumentEntityTable?.GetDataColumnValues("double:TimeZone") ?? Array.Empty().ToIArray(); - BimDocumentPlaceName = BimDocumentEntityTable?.GetStringColumnValues("string:PlaceName") ?? Array.Empty().ToIArray(); - BimDocumentWeatherStationName = BimDocumentEntityTable?.GetStringColumnValues("string:WeatherStationName") ?? Array.Empty().ToIArray(); - BimDocumentElevation = BimDocumentEntityTable?.GetDataColumnValues("double:Elevation") ?? Array.Empty().ToIArray(); - BimDocumentProjectLocation = BimDocumentEntityTable?.GetStringColumnValues("string:ProjectLocation") ?? Array.Empty().ToIArray(); - BimDocumentIssueDate = BimDocumentEntityTable?.GetStringColumnValues("string:IssueDate") ?? Array.Empty().ToIArray(); - BimDocumentStatus = BimDocumentEntityTable?.GetStringColumnValues("string:Status") ?? Array.Empty().ToIArray(); - BimDocumentClientName = BimDocumentEntityTable?.GetStringColumnValues("string:ClientName") ?? Array.Empty().ToIArray(); - BimDocumentAddress = BimDocumentEntityTable?.GetStringColumnValues("string:Address") ?? Array.Empty().ToIArray(); - BimDocumentName = BimDocumentEntityTable?.GetStringColumnValues("string:Name") ?? Array.Empty().ToIArray(); - BimDocumentNumber = BimDocumentEntityTable?.GetStringColumnValues("string:Number") ?? Array.Empty().ToIArray(); - BimDocumentAuthor = BimDocumentEntityTable?.GetStringColumnValues("string:Author") ?? Array.Empty().ToIArray(); - BimDocumentBuildingName = BimDocumentEntityTable?.GetStringColumnValues("string:BuildingName") ?? Array.Empty().ToIArray(); - BimDocumentOrganizationName = BimDocumentEntityTable?.GetStringColumnValues("string:OrganizationName") ?? Array.Empty().ToIArray(); - BimDocumentOrganizationDescription = BimDocumentEntityTable?.GetStringColumnValues("string:OrganizationDescription") ?? Array.Empty().ToIArray(); - BimDocumentProduct = BimDocumentEntityTable?.GetStringColumnValues("string:Product") ?? Array.Empty().ToIArray(); - BimDocumentVersion = BimDocumentEntityTable?.GetStringColumnValues("string:Version") ?? Array.Empty().ToIArray(); - BimDocumentUser = BimDocumentEntityTable?.GetStringColumnValues("string:User") ?? Array.Empty().ToIArray(); - PhaseOrderInBimDocumentOrderIndex = PhaseOrderInBimDocumentEntityTable?.GetDataColumnValues("int:OrderIndex") ?? Array.Empty().ToIArray(); - CategoryName = CategoryEntityTable?.GetStringColumnValues("string:Name") ?? Array.Empty().ToIArray(); - CategoryId = (CategoryEntityTable?.GetDataColumnValues("long:Id") ?? CategoryEntityTable?.GetDataColumnValues("int:Id")?.Select(v => (Int64) v)) ?? Array.Empty().ToIArray(); - CategoryCategoryType = CategoryEntityTable?.GetStringColumnValues("string:CategoryType") ?? Array.Empty().ToIArray(); - CategoryLineColor_X = CategoryEntityTable?.GetDataColumnValues("double:LineColor.X") ?? Array.Empty().ToIArray(); - CategoryLineColor_Y = CategoryEntityTable?.GetDataColumnValues("double:LineColor.Y") ?? Array.Empty().ToIArray(); - CategoryLineColor_Z = CategoryEntityTable?.GetDataColumnValues("double:LineColor.Z") ?? Array.Empty().ToIArray(); - CategoryBuiltInCategory = CategoryEntityTable?.GetStringColumnValues("string:BuiltInCategory") ?? Array.Empty().ToIArray(); - FamilyStructuralMaterialType = FamilyEntityTable?.GetStringColumnValues("string:StructuralMaterialType") ?? Array.Empty().ToIArray(); - FamilyStructuralSectionShape = FamilyEntityTable?.GetStringColumnValues("string:StructuralSectionShape") ?? Array.Empty().ToIArray(); - FamilyIsSystemFamily = FamilyEntityTable?.GetDataColumnValues("byte:IsSystemFamily") ?? Array.Empty().ToIArray(); - FamilyIsInPlace = FamilyEntityTable?.GetDataColumnValues("byte:IsInPlace") ?? Array.Empty().ToIArray(); - FamilyTypeIsSystemFamilyType = FamilyTypeEntityTable?.GetDataColumnValues("byte:IsSystemFamilyType") ?? Array.Empty().ToIArray(); - FamilyInstanceFacingFlipped = FamilyInstanceEntityTable?.GetDataColumnValues("byte:FacingFlipped") ?? Array.Empty().ToIArray(); - FamilyInstanceFacingOrientation_X = FamilyInstanceEntityTable?.GetDataColumnValues("float:FacingOrientation.X") ?? Array.Empty().ToIArray(); - FamilyInstanceFacingOrientation_Y = FamilyInstanceEntityTable?.GetDataColumnValues("float:FacingOrientation.Y") ?? Array.Empty().ToIArray(); - FamilyInstanceFacingOrientation_Z = FamilyInstanceEntityTable?.GetDataColumnValues("float:FacingOrientation.Z") ?? Array.Empty().ToIArray(); - FamilyInstanceHandFlipped = FamilyInstanceEntityTable?.GetDataColumnValues("byte:HandFlipped") ?? Array.Empty().ToIArray(); - FamilyInstanceMirrored = FamilyInstanceEntityTable?.GetDataColumnValues("byte:Mirrored") ?? Array.Empty().ToIArray(); - FamilyInstanceHasModifiedGeometry = FamilyInstanceEntityTable?.GetDataColumnValues("byte:HasModifiedGeometry") ?? Array.Empty().ToIArray(); - FamilyInstanceScale = FamilyInstanceEntityTable?.GetDataColumnValues("float:Scale") ?? Array.Empty().ToIArray(); - FamilyInstanceBasisX_X = FamilyInstanceEntityTable?.GetDataColumnValues("float:BasisX.X") ?? Array.Empty().ToIArray(); - FamilyInstanceBasisX_Y = FamilyInstanceEntityTable?.GetDataColumnValues("float:BasisX.Y") ?? Array.Empty().ToIArray(); - FamilyInstanceBasisX_Z = FamilyInstanceEntityTable?.GetDataColumnValues("float:BasisX.Z") ?? Array.Empty().ToIArray(); - FamilyInstanceBasisY_X = FamilyInstanceEntityTable?.GetDataColumnValues("float:BasisY.X") ?? Array.Empty().ToIArray(); - FamilyInstanceBasisY_Y = FamilyInstanceEntityTable?.GetDataColumnValues("float:BasisY.Y") ?? Array.Empty().ToIArray(); - FamilyInstanceBasisY_Z = FamilyInstanceEntityTable?.GetDataColumnValues("float:BasisY.Z") ?? Array.Empty().ToIArray(); - FamilyInstanceBasisZ_X = FamilyInstanceEntityTable?.GetDataColumnValues("float:BasisZ.X") ?? Array.Empty().ToIArray(); - FamilyInstanceBasisZ_Y = FamilyInstanceEntityTable?.GetDataColumnValues("float:BasisZ.Y") ?? Array.Empty().ToIArray(); - FamilyInstanceBasisZ_Z = FamilyInstanceEntityTable?.GetDataColumnValues("float:BasisZ.Z") ?? Array.Empty().ToIArray(); - FamilyInstanceTranslation_X = FamilyInstanceEntityTable?.GetDataColumnValues("float:Translation.X") ?? Array.Empty().ToIArray(); - FamilyInstanceTranslation_Y = FamilyInstanceEntityTable?.GetDataColumnValues("float:Translation.Y") ?? Array.Empty().ToIArray(); - FamilyInstanceTranslation_Z = FamilyInstanceEntityTable?.GetDataColumnValues("float:Translation.Z") ?? Array.Empty().ToIArray(); - FamilyInstanceHandOrientation_X = FamilyInstanceEntityTable?.GetDataColumnValues("float:HandOrientation.X") ?? Array.Empty().ToIArray(); - FamilyInstanceHandOrientation_Y = FamilyInstanceEntityTable?.GetDataColumnValues("float:HandOrientation.Y") ?? Array.Empty().ToIArray(); - FamilyInstanceHandOrientation_Z = FamilyInstanceEntityTable?.GetDataColumnValues("float:HandOrientation.Z") ?? Array.Empty().ToIArray(); - ViewTitle = ViewEntityTable?.GetStringColumnValues("string:Title") ?? Array.Empty().ToIArray(); - ViewViewType = ViewEntityTable?.GetStringColumnValues("string:ViewType") ?? Array.Empty().ToIArray(); - ViewUp_X = ViewEntityTable?.GetDataColumnValues("double:Up.X") ?? Array.Empty().ToIArray(); - ViewUp_Y = ViewEntityTable?.GetDataColumnValues("double:Up.Y") ?? Array.Empty().ToIArray(); - ViewUp_Z = ViewEntityTable?.GetDataColumnValues("double:Up.Z") ?? Array.Empty().ToIArray(); - ViewRight_X = ViewEntityTable?.GetDataColumnValues("double:Right.X") ?? Array.Empty().ToIArray(); - ViewRight_Y = ViewEntityTable?.GetDataColumnValues("double:Right.Y") ?? Array.Empty().ToIArray(); - ViewRight_Z = ViewEntityTable?.GetDataColumnValues("double:Right.Z") ?? Array.Empty().ToIArray(); - ViewOrigin_X = ViewEntityTable?.GetDataColumnValues("double:Origin.X") ?? Array.Empty().ToIArray(); - ViewOrigin_Y = ViewEntityTable?.GetDataColumnValues("double:Origin.Y") ?? Array.Empty().ToIArray(); - ViewOrigin_Z = ViewEntityTable?.GetDataColumnValues("double:Origin.Z") ?? Array.Empty().ToIArray(); - ViewViewDirection_X = ViewEntityTable?.GetDataColumnValues("double:ViewDirection.X") ?? Array.Empty().ToIArray(); - ViewViewDirection_Y = ViewEntityTable?.GetDataColumnValues("double:ViewDirection.Y") ?? Array.Empty().ToIArray(); - ViewViewDirection_Z = ViewEntityTable?.GetDataColumnValues("double:ViewDirection.Z") ?? Array.Empty().ToIArray(); - ViewViewPosition_X = ViewEntityTable?.GetDataColumnValues("double:ViewPosition.X") ?? Array.Empty().ToIArray(); - ViewViewPosition_Y = ViewEntityTable?.GetDataColumnValues("double:ViewPosition.Y") ?? Array.Empty().ToIArray(); - ViewViewPosition_Z = ViewEntityTable?.GetDataColumnValues("double:ViewPosition.Z") ?? Array.Empty().ToIArray(); - ViewScale = ViewEntityTable?.GetDataColumnValues("double:Scale") ?? Array.Empty().ToIArray(); - ViewOutline_Min_X = ViewEntityTable?.GetDataColumnValues("double:Outline.Min.X") ?? Array.Empty().ToIArray(); - ViewOutline_Min_Y = ViewEntityTable?.GetDataColumnValues("double:Outline.Min.Y") ?? Array.Empty().ToIArray(); - ViewOutline_Max_X = ViewEntityTable?.GetDataColumnValues("double:Outline.Max.X") ?? Array.Empty().ToIArray(); - ViewOutline_Max_Y = ViewEntityTable?.GetDataColumnValues("double:Outline.Max.Y") ?? Array.Empty().ToIArray(); - ViewDetailLevel = ViewEntityTable?.GetDataColumnValues("int:DetailLevel") ?? Array.Empty().ToIArray(); - LevelInViewExtents_Min_X = LevelInViewEntityTable?.GetDataColumnValues("double:Extents.Min.X") ?? Array.Empty().ToIArray(); - LevelInViewExtents_Min_Y = LevelInViewEntityTable?.GetDataColumnValues("double:Extents.Min.Y") ?? Array.Empty().ToIArray(); - LevelInViewExtents_Min_Z = LevelInViewEntityTable?.GetDataColumnValues("double:Extents.Min.Z") ?? Array.Empty().ToIArray(); - LevelInViewExtents_Max_X = LevelInViewEntityTable?.GetDataColumnValues("double:Extents.Max.X") ?? Array.Empty().ToIArray(); - LevelInViewExtents_Max_Y = LevelInViewEntityTable?.GetDataColumnValues("double:Extents.Max.Y") ?? Array.Empty().ToIArray(); - LevelInViewExtents_Max_Z = LevelInViewEntityTable?.GetDataColumnValues("double:Extents.Max.Z") ?? Array.Empty().ToIArray(); - CameraId = CameraEntityTable?.GetDataColumnValues("int:Id") ?? Array.Empty().ToIArray(); - CameraIsPerspective = CameraEntityTable?.GetDataColumnValues("int:IsPerspective") ?? Array.Empty().ToIArray(); - CameraVerticalExtent = CameraEntityTable?.GetDataColumnValues("double:VerticalExtent") ?? Array.Empty().ToIArray(); - CameraHorizontalExtent = CameraEntityTable?.GetDataColumnValues("double:HorizontalExtent") ?? Array.Empty().ToIArray(); - CameraFarDistance = CameraEntityTable?.GetDataColumnValues("double:FarDistance") ?? Array.Empty().ToIArray(); - CameraNearDistance = CameraEntityTable?.GetDataColumnValues("double:NearDistance") ?? Array.Empty().ToIArray(); - CameraTargetDistance = CameraEntityTable?.GetDataColumnValues("double:TargetDistance") ?? Array.Empty().ToIArray(); - CameraRightOffset = CameraEntityTable?.GetDataColumnValues("double:RightOffset") ?? Array.Empty().ToIArray(); - CameraUpOffset = CameraEntityTable?.GetDataColumnValues("double:UpOffset") ?? Array.Empty().ToIArray(); - MaterialName = MaterialEntityTable?.GetStringColumnValues("string:Name") ?? Array.Empty().ToIArray(); - MaterialMaterialCategory = MaterialEntityTable?.GetStringColumnValues("string:MaterialCategory") ?? Array.Empty().ToIArray(); - MaterialColor_X = MaterialEntityTable?.GetDataColumnValues("double:Color.X") ?? Array.Empty().ToIArray(); - MaterialColor_Y = MaterialEntityTable?.GetDataColumnValues("double:Color.Y") ?? Array.Empty().ToIArray(); - MaterialColor_Z = MaterialEntityTable?.GetDataColumnValues("double:Color.Z") ?? Array.Empty().ToIArray(); - MaterialColorUvScaling_X = MaterialEntityTable?.GetDataColumnValues("double:ColorUvScaling.X") ?? Array.Empty().ToIArray(); - MaterialColorUvScaling_Y = MaterialEntityTable?.GetDataColumnValues("double:ColorUvScaling.Y") ?? Array.Empty().ToIArray(); - MaterialColorUvOffset_X = MaterialEntityTable?.GetDataColumnValues("double:ColorUvOffset.X") ?? Array.Empty().ToIArray(); - MaterialColorUvOffset_Y = MaterialEntityTable?.GetDataColumnValues("double:ColorUvOffset.Y") ?? Array.Empty().ToIArray(); - MaterialNormalUvScaling_X = MaterialEntityTable?.GetDataColumnValues("double:NormalUvScaling.X") ?? Array.Empty().ToIArray(); - MaterialNormalUvScaling_Y = MaterialEntityTable?.GetDataColumnValues("double:NormalUvScaling.Y") ?? Array.Empty().ToIArray(); - MaterialNormalUvOffset_X = MaterialEntityTable?.GetDataColumnValues("double:NormalUvOffset.X") ?? Array.Empty().ToIArray(); - MaterialNormalUvOffset_Y = MaterialEntityTable?.GetDataColumnValues("double:NormalUvOffset.Y") ?? Array.Empty().ToIArray(); - MaterialNormalAmount = MaterialEntityTable?.GetDataColumnValues("double:NormalAmount") ?? Array.Empty().ToIArray(); - MaterialGlossiness = MaterialEntityTable?.GetDataColumnValues("double:Glossiness") ?? Array.Empty().ToIArray(); - MaterialSmoothness = MaterialEntityTable?.GetDataColumnValues("double:Smoothness") ?? Array.Empty().ToIArray(); - MaterialTransparency = MaterialEntityTable?.GetDataColumnValues("double:Transparency") ?? Array.Empty().ToIArray(); - MaterialInElementArea = MaterialInElementEntityTable?.GetDataColumnValues("double:Area") ?? Array.Empty().ToIArray(); - MaterialInElementVolume = MaterialInElementEntityTable?.GetDataColumnValues("double:Volume") ?? Array.Empty().ToIArray(); - MaterialInElementIsPaint = MaterialInElementEntityTable?.GetDataColumnValues("byte:IsPaint") ?? Array.Empty().ToIArray(); - CompoundStructureLayerOrderIndex = CompoundStructureLayerEntityTable?.GetDataColumnValues("int:OrderIndex") ?? Array.Empty().ToIArray(); - CompoundStructureLayerWidth = CompoundStructureLayerEntityTable?.GetDataColumnValues("double:Width") ?? Array.Empty().ToIArray(); - CompoundStructureLayerMaterialFunctionAssignment = CompoundStructureLayerEntityTable?.GetStringColumnValues("string:MaterialFunctionAssignment") ?? Array.Empty().ToIArray(); - CompoundStructureWidth = CompoundStructureEntityTable?.GetDataColumnValues("double:Width") ?? Array.Empty().ToIArray(); - GeometryBox_Min_X = GeometryEntityTable?.GetDataColumnValues("float:Box.Min.X") ?? Array.Empty().ToIArray(); - GeometryBox_Min_Y = GeometryEntityTable?.GetDataColumnValues("float:Box.Min.Y") ?? Array.Empty().ToIArray(); - GeometryBox_Min_Z = GeometryEntityTable?.GetDataColumnValues("float:Box.Min.Z") ?? Array.Empty().ToIArray(); - GeometryBox_Max_X = GeometryEntityTable?.GetDataColumnValues("float:Box.Max.X") ?? Array.Empty().ToIArray(); - GeometryBox_Max_Y = GeometryEntityTable?.GetDataColumnValues("float:Box.Max.Y") ?? Array.Empty().ToIArray(); - GeometryBox_Max_Z = GeometryEntityTable?.GetDataColumnValues("float:Box.Max.Z") ?? Array.Empty().ToIArray(); - GeometryVertexCount = GeometryEntityTable?.GetDataColumnValues("int:VertexCount") ?? Array.Empty().ToIArray(); - GeometryFaceCount = GeometryEntityTable?.GetDataColumnValues("int:FaceCount") ?? Array.Empty().ToIArray(); - SystemSystemType = SystemEntityTable?.GetDataColumnValues("int:SystemType") ?? Array.Empty().ToIArray(); - ElementInSystemRoles = ElementInSystemEntityTable?.GetDataColumnValues("int:Roles") ?? Array.Empty().ToIArray(); - WarningGuid = WarningEntityTable?.GetStringColumnValues("string:Guid") ?? Array.Empty().ToIArray(); - WarningSeverity = WarningEntityTable?.GetStringColumnValues("string:Severity") ?? Array.Empty().ToIArray(); - WarningDescription = WarningEntityTable?.GetStringColumnValues("string:Description") ?? Array.Empty().ToIArray(); - BasePointIsSurveyPoint = BasePointEntityTable?.GetDataColumnValues("byte:IsSurveyPoint") ?? Array.Empty().ToIArray(); - BasePointPosition_X = BasePointEntityTable?.GetDataColumnValues("double:Position.X") ?? Array.Empty().ToIArray(); - BasePointPosition_Y = BasePointEntityTable?.GetDataColumnValues("double:Position.Y") ?? Array.Empty().ToIArray(); - BasePointPosition_Z = BasePointEntityTable?.GetDataColumnValues("double:Position.Z") ?? Array.Empty().ToIArray(); - BasePointSharedPosition_X = BasePointEntityTable?.GetDataColumnValues("double:SharedPosition.X") ?? Array.Empty().ToIArray(); - BasePointSharedPosition_Y = BasePointEntityTable?.GetDataColumnValues("double:SharedPosition.Y") ?? Array.Empty().ToIArray(); - BasePointSharedPosition_Z = BasePointEntityTable?.GetDataColumnValues("double:SharedPosition.Z") ?? Array.Empty().ToIArray(); - PhaseFilterNew = PhaseFilterEntityTable?.GetDataColumnValues("int:New") ?? Array.Empty().ToIArray(); - PhaseFilterExisting = PhaseFilterEntityTable?.GetDataColumnValues("int:Existing") ?? Array.Empty().ToIArray(); - PhaseFilterDemolished = PhaseFilterEntityTable?.GetDataColumnValues("int:Demolished") ?? Array.Empty().ToIArray(); - PhaseFilterTemporary = PhaseFilterEntityTable?.GetDataColumnValues("int:Temporary") ?? Array.Empty().ToIArray(); - GridStartPoint_X = GridEntityTable?.GetDataColumnValues("double:StartPoint.X") ?? Array.Empty().ToIArray(); - GridStartPoint_Y = GridEntityTable?.GetDataColumnValues("double:StartPoint.Y") ?? Array.Empty().ToIArray(); - GridStartPoint_Z = GridEntityTable?.GetDataColumnValues("double:StartPoint.Z") ?? Array.Empty().ToIArray(); - GridEndPoint_X = GridEntityTable?.GetDataColumnValues("double:EndPoint.X") ?? Array.Empty().ToIArray(); - GridEndPoint_Y = GridEntityTable?.GetDataColumnValues("double:EndPoint.Y") ?? Array.Empty().ToIArray(); - GridEndPoint_Z = GridEntityTable?.GetDataColumnValues("double:EndPoint.Z") ?? Array.Empty().ToIArray(); - GridIsCurved = GridEntityTable?.GetDataColumnValues("byte:IsCurved") ?? Array.Empty().ToIArray(); - GridExtents_Min_X = GridEntityTable?.GetDataColumnValues("double:Extents.Min.X") ?? Array.Empty().ToIArray(); - GridExtents_Min_Y = GridEntityTable?.GetDataColumnValues("double:Extents.Min.Y") ?? Array.Empty().ToIArray(); - GridExtents_Min_Z = GridEntityTable?.GetDataColumnValues("double:Extents.Min.Z") ?? Array.Empty().ToIArray(); - GridExtents_Max_X = GridEntityTable?.GetDataColumnValues("double:Extents.Max.X") ?? Array.Empty().ToIArray(); - GridExtents_Max_Y = GridEntityTable?.GetDataColumnValues("double:Extents.Max.Y") ?? Array.Empty().ToIArray(); - GridExtents_Max_Z = GridEntityTable?.GetDataColumnValues("double:Extents.Max.Z") ?? Array.Empty().ToIArray(); - AreaValue = AreaEntityTable?.GetDataColumnValues("double:Value") ?? Array.Empty().ToIArray(); - AreaPerimeter = AreaEntityTable?.GetDataColumnValues("double:Perimeter") ?? Array.Empty().ToIArray(); - AreaNumber = AreaEntityTable?.GetStringColumnValues("string:Number") ?? Array.Empty().ToIArray(); - AreaIsGrossInterior = AreaEntityTable?.GetDataColumnValues("byte:IsGrossInterior") ?? Array.Empty().ToIArray(); - AreaSchemeIsGrossBuildingArea = AreaSchemeEntityTable?.GetDataColumnValues("byte:IsGrossBuildingArea") ?? Array.Empty().ToIArray(); - ScheduleColumnName = ScheduleColumnEntityTable?.GetStringColumnValues("string:Name") ?? Array.Empty().ToIArray(); - ScheduleColumnColumnIndex = ScheduleColumnEntityTable?.GetDataColumnValues("int:ColumnIndex") ?? Array.Empty().ToIArray(); - ScheduleCellValue = ScheduleCellEntityTable?.GetStringColumnValues("string:Value") ?? Array.Empty().ToIArray(); - ScheduleCellRowIndex = ScheduleCellEntityTable?.GetDataColumnValues("int:RowIndex") ?? Array.Empty().ToIArray(); - SiteLatitude = SiteEntityTable?.GetDataColumnValues("double:Latitude") ?? Array.Empty().ToIArray(); - SiteLongitude = SiteEntityTable?.GetDataColumnValues("double:Longitude") ?? Array.Empty().ToIArray(); - SiteAddress = SiteEntityTable?.GetStringColumnValues("string:Address") ?? Array.Empty().ToIArray(); - SiteElevation = SiteEntityTable?.GetDataColumnValues("double:Elevation") ?? Array.Empty().ToIArray(); - SiteNumber = SiteEntityTable?.GetStringColumnValues("string:Number") ?? Array.Empty().ToIArray(); - BuildingElevation = BuildingEntityTable?.GetDataColumnValues("double:Elevation") ?? Array.Empty().ToIArray(); - BuildingTerrainElevation = BuildingEntityTable?.GetDataColumnValues("double:TerrainElevation") ?? Array.Empty().ToIArray(); - BuildingAddress = BuildingEntityTable?.GetStringColumnValues("string:Address") ?? Array.Empty().ToIArray(); + AssetBufferName = AssetEntityTable?.GetStringColumnValues("string:BufferName") ?? Array.Empty(); + DisplayUnitSpec = DisplayUnitEntityTable?.GetStringColumnValues("string:Spec") ?? Array.Empty(); + DisplayUnitType = DisplayUnitEntityTable?.GetStringColumnValues("string:Type") ?? Array.Empty(); + DisplayUnitLabel = DisplayUnitEntityTable?.GetStringColumnValues("string:Label") ?? Array.Empty(); + ParameterDescriptorName = ParameterDescriptorEntityTable?.GetStringColumnValues("string:Name") ?? Array.Empty(); + ParameterDescriptorGroup = ParameterDescriptorEntityTable?.GetStringColumnValues("string:Group") ?? Array.Empty(); + ParameterDescriptorParameterType = ParameterDescriptorEntityTable?.GetStringColumnValues("string:ParameterType") ?? Array.Empty(); + ParameterDescriptorIsInstance = ParameterDescriptorEntityTable?.GetDataColumnValues("byte:IsInstance") ?? Array.Empty(); + ParameterDescriptorIsShared = ParameterDescriptorEntityTable?.GetDataColumnValues("byte:IsShared") ?? Array.Empty(); + ParameterDescriptorIsReadOnly = ParameterDescriptorEntityTable?.GetDataColumnValues("byte:IsReadOnly") ?? Array.Empty(); + ParameterDescriptorFlags = ParameterDescriptorEntityTable?.GetDataColumnValues("int:Flags") ?? Array.Empty(); + ParameterDescriptorGuid = ParameterDescriptorEntityTable?.GetStringColumnValues("string:Guid") ?? Array.Empty(); + ParameterValue = ParameterEntityTable?.GetStringColumnValues("string:Value") ?? Array.Empty(); + ElementId = (ElementEntityTable?.GetDataColumnValues("long:Id") ?? ElementEntityTable?.GetDataColumnValues("int:Id")?.Select(v => (Int64) v).ToArray()) ?? Array.Empty(); + ElementType = ElementEntityTable?.GetStringColumnValues("string:Type") ?? Array.Empty(); + ElementName = ElementEntityTable?.GetStringColumnValues("string:Name") ?? Array.Empty(); + ElementUniqueId = ElementEntityTable?.GetStringColumnValues("string:UniqueId") ?? Array.Empty(); + ElementLocation_X = ElementEntityTable?.GetDataColumnValues("float:Location.X") ?? Array.Empty(); + ElementLocation_Y = ElementEntityTable?.GetDataColumnValues("float:Location.Y") ?? Array.Empty(); + ElementLocation_Z = ElementEntityTable?.GetDataColumnValues("float:Location.Z") ?? Array.Empty(); + ElementFamilyName = ElementEntityTable?.GetStringColumnValues("string:FamilyName") ?? Array.Empty(); + ElementIsPinned = ElementEntityTable?.GetDataColumnValues("byte:IsPinned") ?? Array.Empty(); + WorksetId = WorksetEntityTable?.GetDataColumnValues("int:Id") ?? Array.Empty(); + WorksetName = WorksetEntityTable?.GetStringColumnValues("string:Name") ?? Array.Empty(); + WorksetKind = WorksetEntityTable?.GetStringColumnValues("string:Kind") ?? Array.Empty(); + WorksetIsOpen = WorksetEntityTable?.GetDataColumnValues("byte:IsOpen") ?? Array.Empty(); + WorksetIsEditable = WorksetEntityTable?.GetDataColumnValues("byte:IsEditable") ?? Array.Empty(); + WorksetOwner = WorksetEntityTable?.GetStringColumnValues("string:Owner") ?? Array.Empty(); + WorksetUniqueId = WorksetEntityTable?.GetStringColumnValues("string:UniqueId") ?? Array.Empty(); + AssemblyInstanceAssemblyTypeName = AssemblyInstanceEntityTable?.GetStringColumnValues("string:AssemblyTypeName") ?? Array.Empty(); + AssemblyInstancePosition_X = AssemblyInstanceEntityTable?.GetDataColumnValues("float:Position.X") ?? Array.Empty(); + AssemblyInstancePosition_Y = AssemblyInstanceEntityTable?.GetDataColumnValues("float:Position.Y") ?? Array.Empty(); + AssemblyInstancePosition_Z = AssemblyInstanceEntityTable?.GetDataColumnValues("float:Position.Z") ?? Array.Empty(); + GroupGroupType = GroupEntityTable?.GetStringColumnValues("string:GroupType") ?? Array.Empty(); + GroupPosition_X = GroupEntityTable?.GetDataColumnValues("float:Position.X") ?? Array.Empty(); + GroupPosition_Y = GroupEntityTable?.GetDataColumnValues("float:Position.Y") ?? Array.Empty(); + GroupPosition_Z = GroupEntityTable?.GetDataColumnValues("float:Position.Z") ?? Array.Empty(); + DesignOptionIsPrimary = DesignOptionEntityTable?.GetDataColumnValues("byte:IsPrimary") ?? Array.Empty(); + LevelElevation = LevelEntityTable?.GetDataColumnValues("double:Elevation") ?? Array.Empty(); + RoomBaseOffset = RoomEntityTable?.GetDataColumnValues("double:BaseOffset") ?? Array.Empty(); + RoomLimitOffset = RoomEntityTable?.GetDataColumnValues("double:LimitOffset") ?? Array.Empty(); + RoomUnboundedHeight = RoomEntityTable?.GetDataColumnValues("double:UnboundedHeight") ?? Array.Empty(); + RoomVolume = RoomEntityTable?.GetDataColumnValues("double:Volume") ?? Array.Empty(); + RoomPerimeter = RoomEntityTable?.GetDataColumnValues("double:Perimeter") ?? Array.Empty(); + RoomArea = RoomEntityTable?.GetDataColumnValues("double:Area") ?? Array.Empty(); + RoomNumber = RoomEntityTable?.GetStringColumnValues("string:Number") ?? Array.Empty(); + BimDocumentTitle = BimDocumentEntityTable?.GetStringColumnValues("string:Title") ?? Array.Empty(); + BimDocumentIsMetric = BimDocumentEntityTable?.GetDataColumnValues("byte:IsMetric") ?? Array.Empty(); + BimDocumentGuid = BimDocumentEntityTable?.GetStringColumnValues("string:Guid") ?? Array.Empty(); + BimDocumentNumSaves = BimDocumentEntityTable?.GetDataColumnValues("int:NumSaves") ?? Array.Empty(); + BimDocumentIsLinked = BimDocumentEntityTable?.GetDataColumnValues("byte:IsLinked") ?? Array.Empty(); + BimDocumentIsDetached = BimDocumentEntityTable?.GetDataColumnValues("byte:IsDetached") ?? Array.Empty(); + BimDocumentIsWorkshared = BimDocumentEntityTable?.GetDataColumnValues("byte:IsWorkshared") ?? Array.Empty(); + BimDocumentPathName = BimDocumentEntityTable?.GetStringColumnValues("string:PathName") ?? Array.Empty(); + BimDocumentLatitude = BimDocumentEntityTable?.GetDataColumnValues("double:Latitude") ?? Array.Empty(); + BimDocumentLongitude = BimDocumentEntityTable?.GetDataColumnValues("double:Longitude") ?? Array.Empty(); + BimDocumentTimeZone = BimDocumentEntityTable?.GetDataColumnValues("double:TimeZone") ?? Array.Empty(); + BimDocumentPlaceName = BimDocumentEntityTable?.GetStringColumnValues("string:PlaceName") ?? Array.Empty(); + BimDocumentWeatherStationName = BimDocumentEntityTable?.GetStringColumnValues("string:WeatherStationName") ?? Array.Empty(); + BimDocumentElevation = BimDocumentEntityTable?.GetDataColumnValues("double:Elevation") ?? Array.Empty(); + BimDocumentProjectLocation = BimDocumentEntityTable?.GetStringColumnValues("string:ProjectLocation") ?? Array.Empty(); + BimDocumentIssueDate = BimDocumentEntityTable?.GetStringColumnValues("string:IssueDate") ?? Array.Empty(); + BimDocumentStatus = BimDocumentEntityTable?.GetStringColumnValues("string:Status") ?? Array.Empty(); + BimDocumentClientName = BimDocumentEntityTable?.GetStringColumnValues("string:ClientName") ?? Array.Empty(); + BimDocumentAddress = BimDocumentEntityTable?.GetStringColumnValues("string:Address") ?? Array.Empty(); + BimDocumentName = BimDocumentEntityTable?.GetStringColumnValues("string:Name") ?? Array.Empty(); + BimDocumentNumber = BimDocumentEntityTable?.GetStringColumnValues("string:Number") ?? Array.Empty(); + BimDocumentAuthor = BimDocumentEntityTable?.GetStringColumnValues("string:Author") ?? Array.Empty(); + BimDocumentBuildingName = BimDocumentEntityTable?.GetStringColumnValues("string:BuildingName") ?? Array.Empty(); + BimDocumentOrganizationName = BimDocumentEntityTable?.GetStringColumnValues("string:OrganizationName") ?? Array.Empty(); + BimDocumentOrganizationDescription = BimDocumentEntityTable?.GetStringColumnValues("string:OrganizationDescription") ?? Array.Empty(); + BimDocumentProduct = BimDocumentEntityTable?.GetStringColumnValues("string:Product") ?? Array.Empty(); + BimDocumentVersion = BimDocumentEntityTable?.GetStringColumnValues("string:Version") ?? Array.Empty(); + BimDocumentUser = BimDocumentEntityTable?.GetStringColumnValues("string:User") ?? Array.Empty(); + PhaseOrderInBimDocumentOrderIndex = PhaseOrderInBimDocumentEntityTable?.GetDataColumnValues("int:OrderIndex") ?? Array.Empty(); + CategoryName = CategoryEntityTable?.GetStringColumnValues("string:Name") ?? Array.Empty(); + CategoryId = (CategoryEntityTable?.GetDataColumnValues("long:Id") ?? CategoryEntityTable?.GetDataColumnValues("int:Id")?.Select(v => (Int64) v).ToArray()) ?? Array.Empty(); + CategoryCategoryType = CategoryEntityTable?.GetStringColumnValues("string:CategoryType") ?? Array.Empty(); + CategoryLineColor_X = CategoryEntityTable?.GetDataColumnValues("double:LineColor.X") ?? Array.Empty(); + CategoryLineColor_Y = CategoryEntityTable?.GetDataColumnValues("double:LineColor.Y") ?? Array.Empty(); + CategoryLineColor_Z = CategoryEntityTable?.GetDataColumnValues("double:LineColor.Z") ?? Array.Empty(); + CategoryBuiltInCategory = CategoryEntityTable?.GetStringColumnValues("string:BuiltInCategory") ?? Array.Empty(); + FamilyStructuralMaterialType = FamilyEntityTable?.GetStringColumnValues("string:StructuralMaterialType") ?? Array.Empty(); + FamilyStructuralSectionShape = FamilyEntityTable?.GetStringColumnValues("string:StructuralSectionShape") ?? Array.Empty(); + FamilyIsSystemFamily = FamilyEntityTable?.GetDataColumnValues("byte:IsSystemFamily") ?? Array.Empty(); + FamilyIsInPlace = FamilyEntityTable?.GetDataColumnValues("byte:IsInPlace") ?? Array.Empty(); + FamilyTypeIsSystemFamilyType = FamilyTypeEntityTable?.GetDataColumnValues("byte:IsSystemFamilyType") ?? Array.Empty(); + FamilyInstanceFacingFlipped = FamilyInstanceEntityTable?.GetDataColumnValues("byte:FacingFlipped") ?? Array.Empty(); + FamilyInstanceFacingOrientation_X = FamilyInstanceEntityTable?.GetDataColumnValues("float:FacingOrientation.X") ?? Array.Empty(); + FamilyInstanceFacingOrientation_Y = FamilyInstanceEntityTable?.GetDataColumnValues("float:FacingOrientation.Y") ?? Array.Empty(); + FamilyInstanceFacingOrientation_Z = FamilyInstanceEntityTable?.GetDataColumnValues("float:FacingOrientation.Z") ?? Array.Empty(); + FamilyInstanceHandFlipped = FamilyInstanceEntityTable?.GetDataColumnValues("byte:HandFlipped") ?? Array.Empty(); + FamilyInstanceMirrored = FamilyInstanceEntityTable?.GetDataColumnValues("byte:Mirrored") ?? Array.Empty(); + FamilyInstanceHasModifiedGeometry = FamilyInstanceEntityTable?.GetDataColumnValues("byte:HasModifiedGeometry") ?? Array.Empty(); + FamilyInstanceScale = FamilyInstanceEntityTable?.GetDataColumnValues("float:Scale") ?? Array.Empty(); + FamilyInstanceBasisX_X = FamilyInstanceEntityTable?.GetDataColumnValues("float:BasisX.X") ?? Array.Empty(); + FamilyInstanceBasisX_Y = FamilyInstanceEntityTable?.GetDataColumnValues("float:BasisX.Y") ?? Array.Empty(); + FamilyInstanceBasisX_Z = FamilyInstanceEntityTable?.GetDataColumnValues("float:BasisX.Z") ?? Array.Empty(); + FamilyInstanceBasisY_X = FamilyInstanceEntityTable?.GetDataColumnValues("float:BasisY.X") ?? Array.Empty(); + FamilyInstanceBasisY_Y = FamilyInstanceEntityTable?.GetDataColumnValues("float:BasisY.Y") ?? Array.Empty(); + FamilyInstanceBasisY_Z = FamilyInstanceEntityTable?.GetDataColumnValues("float:BasisY.Z") ?? Array.Empty(); + FamilyInstanceBasisZ_X = FamilyInstanceEntityTable?.GetDataColumnValues("float:BasisZ.X") ?? Array.Empty(); + FamilyInstanceBasisZ_Y = FamilyInstanceEntityTable?.GetDataColumnValues("float:BasisZ.Y") ?? Array.Empty(); + FamilyInstanceBasisZ_Z = FamilyInstanceEntityTable?.GetDataColumnValues("float:BasisZ.Z") ?? Array.Empty(); + FamilyInstanceTranslation_X = FamilyInstanceEntityTable?.GetDataColumnValues("float:Translation.X") ?? Array.Empty(); + FamilyInstanceTranslation_Y = FamilyInstanceEntityTable?.GetDataColumnValues("float:Translation.Y") ?? Array.Empty(); + FamilyInstanceTranslation_Z = FamilyInstanceEntityTable?.GetDataColumnValues("float:Translation.Z") ?? Array.Empty(); + FamilyInstanceHandOrientation_X = FamilyInstanceEntityTable?.GetDataColumnValues("float:HandOrientation.X") ?? Array.Empty(); + FamilyInstanceHandOrientation_Y = FamilyInstanceEntityTable?.GetDataColumnValues("float:HandOrientation.Y") ?? Array.Empty(); + FamilyInstanceHandOrientation_Z = FamilyInstanceEntityTable?.GetDataColumnValues("float:HandOrientation.Z") ?? Array.Empty(); + ViewTitle = ViewEntityTable?.GetStringColumnValues("string:Title") ?? Array.Empty(); + ViewViewType = ViewEntityTable?.GetStringColumnValues("string:ViewType") ?? Array.Empty(); + ViewUp_X = ViewEntityTable?.GetDataColumnValues("double:Up.X") ?? Array.Empty(); + ViewUp_Y = ViewEntityTable?.GetDataColumnValues("double:Up.Y") ?? Array.Empty(); + ViewUp_Z = ViewEntityTable?.GetDataColumnValues("double:Up.Z") ?? Array.Empty(); + ViewRight_X = ViewEntityTable?.GetDataColumnValues("double:Right.X") ?? Array.Empty(); + ViewRight_Y = ViewEntityTable?.GetDataColumnValues("double:Right.Y") ?? Array.Empty(); + ViewRight_Z = ViewEntityTable?.GetDataColumnValues("double:Right.Z") ?? Array.Empty(); + ViewOrigin_X = ViewEntityTable?.GetDataColumnValues("double:Origin.X") ?? Array.Empty(); + ViewOrigin_Y = ViewEntityTable?.GetDataColumnValues("double:Origin.Y") ?? Array.Empty(); + ViewOrigin_Z = ViewEntityTable?.GetDataColumnValues("double:Origin.Z") ?? Array.Empty(); + ViewViewDirection_X = ViewEntityTable?.GetDataColumnValues("double:ViewDirection.X") ?? Array.Empty(); + ViewViewDirection_Y = ViewEntityTable?.GetDataColumnValues("double:ViewDirection.Y") ?? Array.Empty(); + ViewViewDirection_Z = ViewEntityTable?.GetDataColumnValues("double:ViewDirection.Z") ?? Array.Empty(); + ViewViewPosition_X = ViewEntityTable?.GetDataColumnValues("double:ViewPosition.X") ?? Array.Empty(); + ViewViewPosition_Y = ViewEntityTable?.GetDataColumnValues("double:ViewPosition.Y") ?? Array.Empty(); + ViewViewPosition_Z = ViewEntityTable?.GetDataColumnValues("double:ViewPosition.Z") ?? Array.Empty(); + ViewScale = ViewEntityTable?.GetDataColumnValues("double:Scale") ?? Array.Empty(); + ViewOutline_Min_X = ViewEntityTable?.GetDataColumnValues("double:Outline.Min.X") ?? Array.Empty(); + ViewOutline_Min_Y = ViewEntityTable?.GetDataColumnValues("double:Outline.Min.Y") ?? Array.Empty(); + ViewOutline_Max_X = ViewEntityTable?.GetDataColumnValues("double:Outline.Max.X") ?? Array.Empty(); + ViewOutline_Max_Y = ViewEntityTable?.GetDataColumnValues("double:Outline.Max.Y") ?? Array.Empty(); + ViewDetailLevel = ViewEntityTable?.GetDataColumnValues("int:DetailLevel") ?? Array.Empty(); + LevelInViewExtents_Min_X = LevelInViewEntityTable?.GetDataColumnValues("double:Extents.Min.X") ?? Array.Empty(); + LevelInViewExtents_Min_Y = LevelInViewEntityTable?.GetDataColumnValues("double:Extents.Min.Y") ?? Array.Empty(); + LevelInViewExtents_Min_Z = LevelInViewEntityTable?.GetDataColumnValues("double:Extents.Min.Z") ?? Array.Empty(); + LevelInViewExtents_Max_X = LevelInViewEntityTable?.GetDataColumnValues("double:Extents.Max.X") ?? Array.Empty(); + LevelInViewExtents_Max_Y = LevelInViewEntityTable?.GetDataColumnValues("double:Extents.Max.Y") ?? Array.Empty(); + LevelInViewExtents_Max_Z = LevelInViewEntityTable?.GetDataColumnValues("double:Extents.Max.Z") ?? Array.Empty(); + CameraId = CameraEntityTable?.GetDataColumnValues("int:Id") ?? Array.Empty(); + CameraIsPerspective = CameraEntityTable?.GetDataColumnValues("int:IsPerspective") ?? Array.Empty(); + CameraVerticalExtent = CameraEntityTable?.GetDataColumnValues("double:VerticalExtent") ?? Array.Empty(); + CameraHorizontalExtent = CameraEntityTable?.GetDataColumnValues("double:HorizontalExtent") ?? Array.Empty(); + CameraFarDistance = CameraEntityTable?.GetDataColumnValues("double:FarDistance") ?? Array.Empty(); + CameraNearDistance = CameraEntityTable?.GetDataColumnValues("double:NearDistance") ?? Array.Empty(); + CameraTargetDistance = CameraEntityTable?.GetDataColumnValues("double:TargetDistance") ?? Array.Empty(); + CameraRightOffset = CameraEntityTable?.GetDataColumnValues("double:RightOffset") ?? Array.Empty(); + CameraUpOffset = CameraEntityTable?.GetDataColumnValues("double:UpOffset") ?? Array.Empty(); + MaterialName = MaterialEntityTable?.GetStringColumnValues("string:Name") ?? Array.Empty(); + MaterialMaterialCategory = MaterialEntityTable?.GetStringColumnValues("string:MaterialCategory") ?? Array.Empty(); + MaterialColor_X = MaterialEntityTable?.GetDataColumnValues("double:Color.X") ?? Array.Empty(); + MaterialColor_Y = MaterialEntityTable?.GetDataColumnValues("double:Color.Y") ?? Array.Empty(); + MaterialColor_Z = MaterialEntityTable?.GetDataColumnValues("double:Color.Z") ?? Array.Empty(); + MaterialColorUvScaling_X = MaterialEntityTable?.GetDataColumnValues("double:ColorUvScaling.X") ?? Array.Empty(); + MaterialColorUvScaling_Y = MaterialEntityTable?.GetDataColumnValues("double:ColorUvScaling.Y") ?? Array.Empty(); + MaterialColorUvOffset_X = MaterialEntityTable?.GetDataColumnValues("double:ColorUvOffset.X") ?? Array.Empty(); + MaterialColorUvOffset_Y = MaterialEntityTable?.GetDataColumnValues("double:ColorUvOffset.Y") ?? Array.Empty(); + MaterialNormalUvScaling_X = MaterialEntityTable?.GetDataColumnValues("double:NormalUvScaling.X") ?? Array.Empty(); + MaterialNormalUvScaling_Y = MaterialEntityTable?.GetDataColumnValues("double:NormalUvScaling.Y") ?? Array.Empty(); + MaterialNormalUvOffset_X = MaterialEntityTable?.GetDataColumnValues("double:NormalUvOffset.X") ?? Array.Empty(); + MaterialNormalUvOffset_Y = MaterialEntityTable?.GetDataColumnValues("double:NormalUvOffset.Y") ?? Array.Empty(); + MaterialNormalAmount = MaterialEntityTable?.GetDataColumnValues("double:NormalAmount") ?? Array.Empty(); + MaterialGlossiness = MaterialEntityTable?.GetDataColumnValues("double:Glossiness") ?? Array.Empty(); + MaterialSmoothness = MaterialEntityTable?.GetDataColumnValues("double:Smoothness") ?? Array.Empty(); + MaterialTransparency = MaterialEntityTable?.GetDataColumnValues("double:Transparency") ?? Array.Empty(); + MaterialInElementArea = MaterialInElementEntityTable?.GetDataColumnValues("double:Area") ?? Array.Empty(); + MaterialInElementVolume = MaterialInElementEntityTable?.GetDataColumnValues("double:Volume") ?? Array.Empty(); + MaterialInElementIsPaint = MaterialInElementEntityTable?.GetDataColumnValues("byte:IsPaint") ?? Array.Empty(); + CompoundStructureLayerOrderIndex = CompoundStructureLayerEntityTable?.GetDataColumnValues("int:OrderIndex") ?? Array.Empty(); + CompoundStructureLayerWidth = CompoundStructureLayerEntityTable?.GetDataColumnValues("double:Width") ?? Array.Empty(); + CompoundStructureLayerMaterialFunctionAssignment = CompoundStructureLayerEntityTable?.GetStringColumnValues("string:MaterialFunctionAssignment") ?? Array.Empty(); + CompoundStructureWidth = CompoundStructureEntityTable?.GetDataColumnValues("double:Width") ?? Array.Empty(); + GeometryBox_Min_X = GeometryEntityTable?.GetDataColumnValues("float:Box.Min.X") ?? Array.Empty(); + GeometryBox_Min_Y = GeometryEntityTable?.GetDataColumnValues("float:Box.Min.Y") ?? Array.Empty(); + GeometryBox_Min_Z = GeometryEntityTable?.GetDataColumnValues("float:Box.Min.Z") ?? Array.Empty(); + GeometryBox_Max_X = GeometryEntityTable?.GetDataColumnValues("float:Box.Max.X") ?? Array.Empty(); + GeometryBox_Max_Y = GeometryEntityTable?.GetDataColumnValues("float:Box.Max.Y") ?? Array.Empty(); + GeometryBox_Max_Z = GeometryEntityTable?.GetDataColumnValues("float:Box.Max.Z") ?? Array.Empty(); + GeometryVertexCount = GeometryEntityTable?.GetDataColumnValues("int:VertexCount") ?? Array.Empty(); + GeometryFaceCount = GeometryEntityTable?.GetDataColumnValues("int:FaceCount") ?? Array.Empty(); + SystemSystemType = SystemEntityTable?.GetDataColumnValues("int:SystemType") ?? Array.Empty(); + ElementInSystemRoles = ElementInSystemEntityTable?.GetDataColumnValues("int:Roles") ?? Array.Empty(); + WarningGuid = WarningEntityTable?.GetStringColumnValues("string:Guid") ?? Array.Empty(); + WarningSeverity = WarningEntityTable?.GetStringColumnValues("string:Severity") ?? Array.Empty(); + WarningDescription = WarningEntityTable?.GetStringColumnValues("string:Description") ?? Array.Empty(); + BasePointIsSurveyPoint = BasePointEntityTable?.GetDataColumnValues("byte:IsSurveyPoint") ?? Array.Empty(); + BasePointPosition_X = BasePointEntityTable?.GetDataColumnValues("double:Position.X") ?? Array.Empty(); + BasePointPosition_Y = BasePointEntityTable?.GetDataColumnValues("double:Position.Y") ?? Array.Empty(); + BasePointPosition_Z = BasePointEntityTable?.GetDataColumnValues("double:Position.Z") ?? Array.Empty(); + BasePointSharedPosition_X = BasePointEntityTable?.GetDataColumnValues("double:SharedPosition.X") ?? Array.Empty(); + BasePointSharedPosition_Y = BasePointEntityTable?.GetDataColumnValues("double:SharedPosition.Y") ?? Array.Empty(); + BasePointSharedPosition_Z = BasePointEntityTable?.GetDataColumnValues("double:SharedPosition.Z") ?? Array.Empty(); + PhaseFilterNew = PhaseFilterEntityTable?.GetDataColumnValues("int:New") ?? Array.Empty(); + PhaseFilterExisting = PhaseFilterEntityTable?.GetDataColumnValues("int:Existing") ?? Array.Empty(); + PhaseFilterDemolished = PhaseFilterEntityTable?.GetDataColumnValues("int:Demolished") ?? Array.Empty(); + PhaseFilterTemporary = PhaseFilterEntityTable?.GetDataColumnValues("int:Temporary") ?? Array.Empty(); + GridStartPoint_X = GridEntityTable?.GetDataColumnValues("double:StartPoint.X") ?? Array.Empty(); + GridStartPoint_Y = GridEntityTable?.GetDataColumnValues("double:StartPoint.Y") ?? Array.Empty(); + GridStartPoint_Z = GridEntityTable?.GetDataColumnValues("double:StartPoint.Z") ?? Array.Empty(); + GridEndPoint_X = GridEntityTable?.GetDataColumnValues("double:EndPoint.X") ?? Array.Empty(); + GridEndPoint_Y = GridEntityTable?.GetDataColumnValues("double:EndPoint.Y") ?? Array.Empty(); + GridEndPoint_Z = GridEntityTable?.GetDataColumnValues("double:EndPoint.Z") ?? Array.Empty(); + GridIsCurved = GridEntityTable?.GetDataColumnValues("byte:IsCurved") ?? Array.Empty(); + GridExtents_Min_X = GridEntityTable?.GetDataColumnValues("double:Extents.Min.X") ?? Array.Empty(); + GridExtents_Min_Y = GridEntityTable?.GetDataColumnValues("double:Extents.Min.Y") ?? Array.Empty(); + GridExtents_Min_Z = GridEntityTable?.GetDataColumnValues("double:Extents.Min.Z") ?? Array.Empty(); + GridExtents_Max_X = GridEntityTable?.GetDataColumnValues("double:Extents.Max.X") ?? Array.Empty(); + GridExtents_Max_Y = GridEntityTable?.GetDataColumnValues("double:Extents.Max.Y") ?? Array.Empty(); + GridExtents_Max_Z = GridEntityTable?.GetDataColumnValues("double:Extents.Max.Z") ?? Array.Empty(); + AreaValue = AreaEntityTable?.GetDataColumnValues("double:Value") ?? Array.Empty(); + AreaPerimeter = AreaEntityTable?.GetDataColumnValues("double:Perimeter") ?? Array.Empty(); + AreaNumber = AreaEntityTable?.GetStringColumnValues("string:Number") ?? Array.Empty(); + AreaIsGrossInterior = AreaEntityTable?.GetDataColumnValues("byte:IsGrossInterior") ?? Array.Empty(); + AreaSchemeIsGrossBuildingArea = AreaSchemeEntityTable?.GetDataColumnValues("byte:IsGrossBuildingArea") ?? Array.Empty(); + ScheduleColumnName = ScheduleColumnEntityTable?.GetStringColumnValues("string:Name") ?? Array.Empty(); + ScheduleColumnColumnIndex = ScheduleColumnEntityTable?.GetDataColumnValues("int:ColumnIndex") ?? Array.Empty(); + ScheduleCellValue = ScheduleCellEntityTable?.GetStringColumnValues("string:Value") ?? Array.Empty(); + ScheduleCellRowIndex = ScheduleCellEntityTable?.GetDataColumnValues("int:RowIndex") ?? Array.Empty(); + SiteLatitude = SiteEntityTable?.GetDataColumnValues("double:Latitude") ?? Array.Empty(); + SiteLongitude = SiteEntityTable?.GetDataColumnValues("double:Longitude") ?? Array.Empty(); + SiteAddress = SiteEntityTable?.GetStringColumnValues("string:Address") ?? Array.Empty(); + SiteElevation = SiteEntityTable?.GetDataColumnValues("double:Elevation") ?? Array.Empty(); + SiteNumber = SiteEntityTable?.GetStringColumnValues("string:Number") ?? Array.Empty(); + BuildingElevation = BuildingEntityTable?.GetDataColumnValues("double:Elevation") ?? Array.Empty(); + BuildingTerrainElevation = BuildingEntityTable?.GetDataColumnValues("double:TerrainElevation") ?? Array.Empty(); + BuildingAddress = BuildingEntityTable?.GetStringColumnValues("string:Address") ?? Array.Empty(); // Initialize entity relational columns - ParameterDescriptorDisplayUnitIndex = ParameterDescriptorEntityTable?.GetIndexColumnValues("index:Vim.DisplayUnit:DisplayUnit") ?? Array.Empty().ToIArray(); - ParameterParameterDescriptorIndex = ParameterEntityTable?.GetIndexColumnValues("index:Vim.ParameterDescriptor:ParameterDescriptor") ?? Array.Empty().ToIArray(); - ParameterElementIndex = ParameterEntityTable?.GetIndexColumnValues("index:Vim.Element:Element") ?? Array.Empty().ToIArray(); - ElementLevelIndex = ElementEntityTable?.GetIndexColumnValues("index:Vim.Level:Level") ?? Array.Empty().ToIArray(); - ElementPhaseCreatedIndex = ElementEntityTable?.GetIndexColumnValues("index:Vim.Phase:PhaseCreated") ?? Array.Empty().ToIArray(); - ElementPhaseDemolishedIndex = ElementEntityTable?.GetIndexColumnValues("index:Vim.Phase:PhaseDemolished") ?? Array.Empty().ToIArray(); - ElementCategoryIndex = ElementEntityTable?.GetIndexColumnValues("index:Vim.Category:Category") ?? Array.Empty().ToIArray(); - ElementWorksetIndex = ElementEntityTable?.GetIndexColumnValues("index:Vim.Workset:Workset") ?? Array.Empty().ToIArray(); - ElementDesignOptionIndex = ElementEntityTable?.GetIndexColumnValues("index:Vim.DesignOption:DesignOption") ?? Array.Empty().ToIArray(); - ElementOwnerViewIndex = ElementEntityTable?.GetIndexColumnValues("index:Vim.View:OwnerView") ?? Array.Empty().ToIArray(); - ElementGroupIndex = ElementEntityTable?.GetIndexColumnValues("index:Vim.Group:Group") ?? Array.Empty().ToIArray(); - ElementAssemblyInstanceIndex = ElementEntityTable?.GetIndexColumnValues("index:Vim.AssemblyInstance:AssemblyInstance") ?? Array.Empty().ToIArray(); - ElementBimDocumentIndex = ElementEntityTable?.GetIndexColumnValues("index:Vim.BimDocument:BimDocument") ?? Array.Empty().ToIArray(); - ElementRoomIndex = ElementEntityTable?.GetIndexColumnValues("index:Vim.Room:Room") ?? Array.Empty().ToIArray(); - WorksetBimDocumentIndex = WorksetEntityTable?.GetIndexColumnValues("index:Vim.BimDocument:BimDocument") ?? Array.Empty().ToIArray(); - AssemblyInstanceElementIndex = AssemblyInstanceEntityTable?.GetIndexColumnValues("index:Vim.Element:Element") ?? Array.Empty().ToIArray(); - GroupElementIndex = GroupEntityTable?.GetIndexColumnValues("index:Vim.Element:Element") ?? Array.Empty().ToIArray(); - DesignOptionElementIndex = DesignOptionEntityTable?.GetIndexColumnValues("index:Vim.Element:Element") ?? Array.Empty().ToIArray(); - LevelFamilyTypeIndex = LevelEntityTable?.GetIndexColumnValues("index:Vim.FamilyType:FamilyType") ?? Array.Empty().ToIArray(); - LevelBuildingIndex = LevelEntityTable?.GetIndexColumnValues("index:Vim.Building:Building") ?? Array.Empty().ToIArray(); - LevelElementIndex = LevelEntityTable?.GetIndexColumnValues("index:Vim.Element:Element") ?? Array.Empty().ToIArray(); - PhaseElementIndex = PhaseEntityTable?.GetIndexColumnValues("index:Vim.Element:Element") ?? Array.Empty().ToIArray(); - RoomUpperLimitIndex = RoomEntityTable?.GetIndexColumnValues("index:Vim.Level:UpperLimit") ?? Array.Empty().ToIArray(); - RoomElementIndex = RoomEntityTable?.GetIndexColumnValues("index:Vim.Element:Element") ?? Array.Empty().ToIArray(); - BimDocumentActiveViewIndex = BimDocumentEntityTable?.GetIndexColumnValues("index:Vim.View:ActiveView") ?? Array.Empty().ToIArray(); - BimDocumentOwnerFamilyIndex = BimDocumentEntityTable?.GetIndexColumnValues("index:Vim.Family:OwnerFamily") ?? Array.Empty().ToIArray(); - BimDocumentParentIndex = BimDocumentEntityTable?.GetIndexColumnValues("index:Vim.BimDocument:Parent") ?? Array.Empty().ToIArray(); - BimDocumentElementIndex = BimDocumentEntityTable?.GetIndexColumnValues("index:Vim.Element:Element") ?? Array.Empty().ToIArray(); - DisplayUnitInBimDocumentDisplayUnitIndex = DisplayUnitInBimDocumentEntityTable?.GetIndexColumnValues("index:Vim.DisplayUnit:DisplayUnit") ?? Array.Empty().ToIArray(); - DisplayUnitInBimDocumentBimDocumentIndex = DisplayUnitInBimDocumentEntityTable?.GetIndexColumnValues("index:Vim.BimDocument:BimDocument") ?? Array.Empty().ToIArray(); - PhaseOrderInBimDocumentPhaseIndex = PhaseOrderInBimDocumentEntityTable?.GetIndexColumnValues("index:Vim.Phase:Phase") ?? Array.Empty().ToIArray(); - PhaseOrderInBimDocumentBimDocumentIndex = PhaseOrderInBimDocumentEntityTable?.GetIndexColumnValues("index:Vim.BimDocument:BimDocument") ?? Array.Empty().ToIArray(); - CategoryParentIndex = CategoryEntityTable?.GetIndexColumnValues("index:Vim.Category:Parent") ?? Array.Empty().ToIArray(); - CategoryMaterialIndex = CategoryEntityTable?.GetIndexColumnValues("index:Vim.Material:Material") ?? Array.Empty().ToIArray(); - FamilyFamilyCategoryIndex = FamilyEntityTable?.GetIndexColumnValues("index:Vim.Category:FamilyCategory") ?? Array.Empty().ToIArray(); - FamilyElementIndex = FamilyEntityTable?.GetIndexColumnValues("index:Vim.Element:Element") ?? Array.Empty().ToIArray(); - FamilyTypeFamilyIndex = FamilyTypeEntityTable?.GetIndexColumnValues("index:Vim.Family:Family") ?? Array.Empty().ToIArray(); - FamilyTypeCompoundStructureIndex = FamilyTypeEntityTable?.GetIndexColumnValues("index:Vim.CompoundStructure:CompoundStructure") ?? Array.Empty().ToIArray(); - FamilyTypeElementIndex = FamilyTypeEntityTable?.GetIndexColumnValues("index:Vim.Element:Element") ?? Array.Empty().ToIArray(); - FamilyInstanceFamilyTypeIndex = FamilyInstanceEntityTable?.GetIndexColumnValues("index:Vim.FamilyType:FamilyType") ?? Array.Empty().ToIArray(); - FamilyInstanceHostIndex = FamilyInstanceEntityTable?.GetIndexColumnValues("index:Vim.Element:Host") ?? Array.Empty().ToIArray(); - FamilyInstanceFromRoomIndex = FamilyInstanceEntityTable?.GetIndexColumnValues("index:Vim.Room:FromRoom") ?? Array.Empty().ToIArray(); - FamilyInstanceToRoomIndex = FamilyInstanceEntityTable?.GetIndexColumnValues("index:Vim.Room:ToRoom") ?? Array.Empty().ToIArray(); - FamilyInstanceElementIndex = FamilyInstanceEntityTable?.GetIndexColumnValues("index:Vim.Element:Element") ?? Array.Empty().ToIArray(); - ViewCameraIndex = ViewEntityTable?.GetIndexColumnValues("index:Vim.Camera:Camera") ?? Array.Empty().ToIArray(); - ViewFamilyTypeIndex = ViewEntityTable?.GetIndexColumnValues("index:Vim.FamilyType:FamilyType") ?? Array.Empty().ToIArray(); - ViewElementIndex = ViewEntityTable?.GetIndexColumnValues("index:Vim.Element:Element") ?? Array.Empty().ToIArray(); - ElementInViewViewIndex = ElementInViewEntityTable?.GetIndexColumnValues("index:Vim.View:View") ?? Array.Empty().ToIArray(); - ElementInViewElementIndex = ElementInViewEntityTable?.GetIndexColumnValues("index:Vim.Element:Element") ?? Array.Empty().ToIArray(); - ShapeInViewShapeIndex = ShapeInViewEntityTable?.GetIndexColumnValues("index:Vim.Shape:Shape") ?? Array.Empty().ToIArray(); - ShapeInViewViewIndex = ShapeInViewEntityTable?.GetIndexColumnValues("index:Vim.View:View") ?? Array.Empty().ToIArray(); - AssetInViewAssetIndex = AssetInViewEntityTable?.GetIndexColumnValues("index:Vim.Asset:Asset") ?? Array.Empty().ToIArray(); - AssetInViewViewIndex = AssetInViewEntityTable?.GetIndexColumnValues("index:Vim.View:View") ?? Array.Empty().ToIArray(); - AssetInViewSheetAssetIndex = AssetInViewSheetEntityTable?.GetIndexColumnValues("index:Vim.Asset:Asset") ?? Array.Empty().ToIArray(); - AssetInViewSheetViewSheetIndex = AssetInViewSheetEntityTable?.GetIndexColumnValues("index:Vim.ViewSheet:ViewSheet") ?? Array.Empty().ToIArray(); - LevelInViewLevelIndex = LevelInViewEntityTable?.GetIndexColumnValues("index:Vim.Level:Level") ?? Array.Empty().ToIArray(); - LevelInViewViewIndex = LevelInViewEntityTable?.GetIndexColumnValues("index:Vim.View:View") ?? Array.Empty().ToIArray(); - MaterialColorTextureFileIndex = MaterialEntityTable?.GetIndexColumnValues("index:Vim.Asset:ColorTextureFile") ?? Array.Empty().ToIArray(); - MaterialNormalTextureFileIndex = MaterialEntityTable?.GetIndexColumnValues("index:Vim.Asset:NormalTextureFile") ?? Array.Empty().ToIArray(); - MaterialElementIndex = MaterialEntityTable?.GetIndexColumnValues("index:Vim.Element:Element") ?? Array.Empty().ToIArray(); - MaterialInElementMaterialIndex = MaterialInElementEntityTable?.GetIndexColumnValues("index:Vim.Material:Material") ?? Array.Empty().ToIArray(); - MaterialInElementElementIndex = MaterialInElementEntityTable?.GetIndexColumnValues("index:Vim.Element:Element") ?? Array.Empty().ToIArray(); - CompoundStructureLayerMaterialIndex = CompoundStructureLayerEntityTable?.GetIndexColumnValues("index:Vim.Material:Material") ?? Array.Empty().ToIArray(); - CompoundStructureLayerCompoundStructureIndex = CompoundStructureLayerEntityTable?.GetIndexColumnValues("index:Vim.CompoundStructure:CompoundStructure") ?? Array.Empty().ToIArray(); - CompoundStructureStructuralLayerIndex = CompoundStructureEntityTable?.GetIndexColumnValues("index:Vim.CompoundStructureLayer:StructuralLayer") ?? Array.Empty().ToIArray(); - NodeElementIndex = NodeEntityTable?.GetIndexColumnValues("index:Vim.Element:Element") ?? Array.Empty().ToIArray(); - ShapeElementIndex = ShapeEntityTable?.GetIndexColumnValues("index:Vim.Element:Element") ?? Array.Empty().ToIArray(); - ShapeCollectionElementIndex = ShapeCollectionEntityTable?.GetIndexColumnValues("index:Vim.Element:Element") ?? Array.Empty().ToIArray(); - ShapeInShapeCollectionShapeIndex = ShapeInShapeCollectionEntityTable?.GetIndexColumnValues("index:Vim.Shape:Shape") ?? Array.Empty().ToIArray(); - ShapeInShapeCollectionShapeCollectionIndex = ShapeInShapeCollectionEntityTable?.GetIndexColumnValues("index:Vim.ShapeCollection:ShapeCollection") ?? Array.Empty().ToIArray(); - SystemFamilyTypeIndex = SystemEntityTable?.GetIndexColumnValues("index:Vim.FamilyType:FamilyType") ?? Array.Empty().ToIArray(); - SystemElementIndex = SystemEntityTable?.GetIndexColumnValues("index:Vim.Element:Element") ?? Array.Empty().ToIArray(); - ElementInSystemSystemIndex = ElementInSystemEntityTable?.GetIndexColumnValues("index:Vim.System:System") ?? Array.Empty().ToIArray(); - ElementInSystemElementIndex = ElementInSystemEntityTable?.GetIndexColumnValues("index:Vim.Element:Element") ?? Array.Empty().ToIArray(); - WarningBimDocumentIndex = WarningEntityTable?.GetIndexColumnValues("index:Vim.BimDocument:BimDocument") ?? Array.Empty().ToIArray(); - ElementInWarningWarningIndex = ElementInWarningEntityTable?.GetIndexColumnValues("index:Vim.Warning:Warning") ?? Array.Empty().ToIArray(); - ElementInWarningElementIndex = ElementInWarningEntityTable?.GetIndexColumnValues("index:Vim.Element:Element") ?? Array.Empty().ToIArray(); - BasePointElementIndex = BasePointEntityTable?.GetIndexColumnValues("index:Vim.Element:Element") ?? Array.Empty().ToIArray(); - PhaseFilterElementIndex = PhaseFilterEntityTable?.GetIndexColumnValues("index:Vim.Element:Element") ?? Array.Empty().ToIArray(); - GridFamilyTypeIndex = GridEntityTable?.GetIndexColumnValues("index:Vim.FamilyType:FamilyType") ?? Array.Empty().ToIArray(); - GridElementIndex = GridEntityTable?.GetIndexColumnValues("index:Vim.Element:Element") ?? Array.Empty().ToIArray(); - AreaAreaSchemeIndex = AreaEntityTable?.GetIndexColumnValues("index:Vim.AreaScheme:AreaScheme") ?? Array.Empty().ToIArray(); - AreaElementIndex = AreaEntityTable?.GetIndexColumnValues("index:Vim.Element:Element") ?? Array.Empty().ToIArray(); - AreaSchemeElementIndex = AreaSchemeEntityTable?.GetIndexColumnValues("index:Vim.Element:Element") ?? Array.Empty().ToIArray(); - ScheduleElementIndex = ScheduleEntityTable?.GetIndexColumnValues("index:Vim.Element:Element") ?? Array.Empty().ToIArray(); - ScheduleColumnScheduleIndex = ScheduleColumnEntityTable?.GetIndexColumnValues("index:Vim.Schedule:Schedule") ?? Array.Empty().ToIArray(); - ScheduleCellScheduleColumnIndex = ScheduleCellEntityTable?.GetIndexColumnValues("index:Vim.ScheduleColumn:ScheduleColumn") ?? Array.Empty().ToIArray(); - ViewSheetSetElementIndex = ViewSheetSetEntityTable?.GetIndexColumnValues("index:Vim.Element:Element") ?? Array.Empty().ToIArray(); - ViewSheetFamilyTypeIndex = ViewSheetEntityTable?.GetIndexColumnValues("index:Vim.FamilyType:FamilyType") ?? Array.Empty().ToIArray(); - ViewSheetElementIndex = ViewSheetEntityTable?.GetIndexColumnValues("index:Vim.Element:Element") ?? Array.Empty().ToIArray(); - ViewSheetInViewSheetSetViewSheetIndex = ViewSheetInViewSheetSetEntityTable?.GetIndexColumnValues("index:Vim.ViewSheet:ViewSheet") ?? Array.Empty().ToIArray(); - ViewSheetInViewSheetSetViewSheetSetIndex = ViewSheetInViewSheetSetEntityTable?.GetIndexColumnValues("index:Vim.ViewSheetSet:ViewSheetSet") ?? Array.Empty().ToIArray(); - ViewInViewSheetSetViewIndex = ViewInViewSheetSetEntityTable?.GetIndexColumnValues("index:Vim.View:View") ?? Array.Empty().ToIArray(); - ViewInViewSheetSetViewSheetSetIndex = ViewInViewSheetSetEntityTable?.GetIndexColumnValues("index:Vim.ViewSheetSet:ViewSheetSet") ?? Array.Empty().ToIArray(); - ViewInViewSheetViewIndex = ViewInViewSheetEntityTable?.GetIndexColumnValues("index:Vim.View:View") ?? Array.Empty().ToIArray(); - ViewInViewSheetViewSheetIndex = ViewInViewSheetEntityTable?.GetIndexColumnValues("index:Vim.ViewSheet:ViewSheet") ?? Array.Empty().ToIArray(); - SiteElementIndex = SiteEntityTable?.GetIndexColumnValues("index:Vim.Element:Element") ?? Array.Empty().ToIArray(); - BuildingSiteIndex = BuildingEntityTable?.GetIndexColumnValues("index:Vim.Site:Site") ?? Array.Empty().ToIArray(); - BuildingElementIndex = BuildingEntityTable?.GetIndexColumnValues("index:Vim.Element:Element") ?? Array.Empty().ToIArray(); + ParameterDescriptorDisplayUnitIndex = ParameterDescriptorEntityTable?.GetIndexColumnValues("index:Vim.DisplayUnit:DisplayUnit") ?? Array.Empty(); + ParameterParameterDescriptorIndex = ParameterEntityTable?.GetIndexColumnValues("index:Vim.ParameterDescriptor:ParameterDescriptor") ?? Array.Empty(); + ParameterElementIndex = ParameterEntityTable?.GetIndexColumnValues("index:Vim.Element:Element") ?? Array.Empty(); + ElementLevelIndex = ElementEntityTable?.GetIndexColumnValues("index:Vim.Level:Level") ?? Array.Empty(); + ElementPhaseCreatedIndex = ElementEntityTable?.GetIndexColumnValues("index:Vim.Phase:PhaseCreated") ?? Array.Empty(); + ElementPhaseDemolishedIndex = ElementEntityTable?.GetIndexColumnValues("index:Vim.Phase:PhaseDemolished") ?? Array.Empty(); + ElementCategoryIndex = ElementEntityTable?.GetIndexColumnValues("index:Vim.Category:Category") ?? Array.Empty(); + ElementWorksetIndex = ElementEntityTable?.GetIndexColumnValues("index:Vim.Workset:Workset") ?? Array.Empty(); + ElementDesignOptionIndex = ElementEntityTable?.GetIndexColumnValues("index:Vim.DesignOption:DesignOption") ?? Array.Empty(); + ElementOwnerViewIndex = ElementEntityTable?.GetIndexColumnValues("index:Vim.View:OwnerView") ?? Array.Empty(); + ElementGroupIndex = ElementEntityTable?.GetIndexColumnValues("index:Vim.Group:Group") ?? Array.Empty(); + ElementAssemblyInstanceIndex = ElementEntityTable?.GetIndexColumnValues("index:Vim.AssemblyInstance:AssemblyInstance") ?? Array.Empty(); + ElementBimDocumentIndex = ElementEntityTable?.GetIndexColumnValues("index:Vim.BimDocument:BimDocument") ?? Array.Empty(); + ElementRoomIndex = ElementEntityTable?.GetIndexColumnValues("index:Vim.Room:Room") ?? Array.Empty(); + WorksetBimDocumentIndex = WorksetEntityTable?.GetIndexColumnValues("index:Vim.BimDocument:BimDocument") ?? Array.Empty(); + AssemblyInstanceElementIndex = AssemblyInstanceEntityTable?.GetIndexColumnValues("index:Vim.Element:Element") ?? Array.Empty(); + GroupElementIndex = GroupEntityTable?.GetIndexColumnValues("index:Vim.Element:Element") ?? Array.Empty(); + DesignOptionElementIndex = DesignOptionEntityTable?.GetIndexColumnValues("index:Vim.Element:Element") ?? Array.Empty(); + LevelFamilyTypeIndex = LevelEntityTable?.GetIndexColumnValues("index:Vim.FamilyType:FamilyType") ?? Array.Empty(); + LevelBuildingIndex = LevelEntityTable?.GetIndexColumnValues("index:Vim.Building:Building") ?? Array.Empty(); + LevelElementIndex = LevelEntityTable?.GetIndexColumnValues("index:Vim.Element:Element") ?? Array.Empty(); + PhaseElementIndex = PhaseEntityTable?.GetIndexColumnValues("index:Vim.Element:Element") ?? Array.Empty(); + RoomUpperLimitIndex = RoomEntityTable?.GetIndexColumnValues("index:Vim.Level:UpperLimit") ?? Array.Empty(); + RoomElementIndex = RoomEntityTable?.GetIndexColumnValues("index:Vim.Element:Element") ?? Array.Empty(); + BimDocumentActiveViewIndex = BimDocumentEntityTable?.GetIndexColumnValues("index:Vim.View:ActiveView") ?? Array.Empty(); + BimDocumentOwnerFamilyIndex = BimDocumentEntityTable?.GetIndexColumnValues("index:Vim.Family:OwnerFamily") ?? Array.Empty(); + BimDocumentParentIndex = BimDocumentEntityTable?.GetIndexColumnValues("index:Vim.BimDocument:Parent") ?? Array.Empty(); + BimDocumentElementIndex = BimDocumentEntityTable?.GetIndexColumnValues("index:Vim.Element:Element") ?? Array.Empty(); + DisplayUnitInBimDocumentDisplayUnitIndex = DisplayUnitInBimDocumentEntityTable?.GetIndexColumnValues("index:Vim.DisplayUnit:DisplayUnit") ?? Array.Empty(); + DisplayUnitInBimDocumentBimDocumentIndex = DisplayUnitInBimDocumentEntityTable?.GetIndexColumnValues("index:Vim.BimDocument:BimDocument") ?? Array.Empty(); + PhaseOrderInBimDocumentPhaseIndex = PhaseOrderInBimDocumentEntityTable?.GetIndexColumnValues("index:Vim.Phase:Phase") ?? Array.Empty(); + PhaseOrderInBimDocumentBimDocumentIndex = PhaseOrderInBimDocumentEntityTable?.GetIndexColumnValues("index:Vim.BimDocument:BimDocument") ?? Array.Empty(); + CategoryParentIndex = CategoryEntityTable?.GetIndexColumnValues("index:Vim.Category:Parent") ?? Array.Empty(); + CategoryMaterialIndex = CategoryEntityTable?.GetIndexColumnValues("index:Vim.Material:Material") ?? Array.Empty(); + FamilyFamilyCategoryIndex = FamilyEntityTable?.GetIndexColumnValues("index:Vim.Category:FamilyCategory") ?? Array.Empty(); + FamilyElementIndex = FamilyEntityTable?.GetIndexColumnValues("index:Vim.Element:Element") ?? Array.Empty(); + FamilyTypeFamilyIndex = FamilyTypeEntityTable?.GetIndexColumnValues("index:Vim.Family:Family") ?? Array.Empty(); + FamilyTypeCompoundStructureIndex = FamilyTypeEntityTable?.GetIndexColumnValues("index:Vim.CompoundStructure:CompoundStructure") ?? Array.Empty(); + FamilyTypeElementIndex = FamilyTypeEntityTable?.GetIndexColumnValues("index:Vim.Element:Element") ?? Array.Empty(); + FamilyInstanceFamilyTypeIndex = FamilyInstanceEntityTable?.GetIndexColumnValues("index:Vim.FamilyType:FamilyType") ?? Array.Empty(); + FamilyInstanceHostIndex = FamilyInstanceEntityTable?.GetIndexColumnValues("index:Vim.Element:Host") ?? Array.Empty(); + FamilyInstanceFromRoomIndex = FamilyInstanceEntityTable?.GetIndexColumnValues("index:Vim.Room:FromRoom") ?? Array.Empty(); + FamilyInstanceToRoomIndex = FamilyInstanceEntityTable?.GetIndexColumnValues("index:Vim.Room:ToRoom") ?? Array.Empty(); + FamilyInstanceElementIndex = FamilyInstanceEntityTable?.GetIndexColumnValues("index:Vim.Element:Element") ?? Array.Empty(); + ViewCameraIndex = ViewEntityTable?.GetIndexColumnValues("index:Vim.Camera:Camera") ?? Array.Empty(); + ViewFamilyTypeIndex = ViewEntityTable?.GetIndexColumnValues("index:Vim.FamilyType:FamilyType") ?? Array.Empty(); + ViewElementIndex = ViewEntityTable?.GetIndexColumnValues("index:Vim.Element:Element") ?? Array.Empty(); + ElementInViewViewIndex = ElementInViewEntityTable?.GetIndexColumnValues("index:Vim.View:View") ?? Array.Empty(); + ElementInViewElementIndex = ElementInViewEntityTable?.GetIndexColumnValues("index:Vim.Element:Element") ?? Array.Empty(); + ShapeInViewShapeIndex = ShapeInViewEntityTable?.GetIndexColumnValues("index:Vim.Shape:Shape") ?? Array.Empty(); + ShapeInViewViewIndex = ShapeInViewEntityTable?.GetIndexColumnValues("index:Vim.View:View") ?? Array.Empty(); + AssetInViewAssetIndex = AssetInViewEntityTable?.GetIndexColumnValues("index:Vim.Asset:Asset") ?? Array.Empty(); + AssetInViewViewIndex = AssetInViewEntityTable?.GetIndexColumnValues("index:Vim.View:View") ?? Array.Empty(); + AssetInViewSheetAssetIndex = AssetInViewSheetEntityTable?.GetIndexColumnValues("index:Vim.Asset:Asset") ?? Array.Empty(); + AssetInViewSheetViewSheetIndex = AssetInViewSheetEntityTable?.GetIndexColumnValues("index:Vim.ViewSheet:ViewSheet") ?? Array.Empty(); + LevelInViewLevelIndex = LevelInViewEntityTable?.GetIndexColumnValues("index:Vim.Level:Level") ?? Array.Empty(); + LevelInViewViewIndex = LevelInViewEntityTable?.GetIndexColumnValues("index:Vim.View:View") ?? Array.Empty(); + MaterialColorTextureFileIndex = MaterialEntityTable?.GetIndexColumnValues("index:Vim.Asset:ColorTextureFile") ?? Array.Empty(); + MaterialNormalTextureFileIndex = MaterialEntityTable?.GetIndexColumnValues("index:Vim.Asset:NormalTextureFile") ?? Array.Empty(); + MaterialElementIndex = MaterialEntityTable?.GetIndexColumnValues("index:Vim.Element:Element") ?? Array.Empty(); + MaterialInElementMaterialIndex = MaterialInElementEntityTable?.GetIndexColumnValues("index:Vim.Material:Material") ?? Array.Empty(); + MaterialInElementElementIndex = MaterialInElementEntityTable?.GetIndexColumnValues("index:Vim.Element:Element") ?? Array.Empty(); + CompoundStructureLayerMaterialIndex = CompoundStructureLayerEntityTable?.GetIndexColumnValues("index:Vim.Material:Material") ?? Array.Empty(); + CompoundStructureLayerCompoundStructureIndex = CompoundStructureLayerEntityTable?.GetIndexColumnValues("index:Vim.CompoundStructure:CompoundStructure") ?? Array.Empty(); + CompoundStructureStructuralLayerIndex = CompoundStructureEntityTable?.GetIndexColumnValues("index:Vim.CompoundStructureLayer:StructuralLayer") ?? Array.Empty(); + NodeElementIndex = NodeEntityTable?.GetIndexColumnValues("index:Vim.Element:Element") ?? Array.Empty(); + ShapeElementIndex = ShapeEntityTable?.GetIndexColumnValues("index:Vim.Element:Element") ?? Array.Empty(); + ShapeCollectionElementIndex = ShapeCollectionEntityTable?.GetIndexColumnValues("index:Vim.Element:Element") ?? Array.Empty(); + ShapeInShapeCollectionShapeIndex = ShapeInShapeCollectionEntityTable?.GetIndexColumnValues("index:Vim.Shape:Shape") ?? Array.Empty(); + ShapeInShapeCollectionShapeCollectionIndex = ShapeInShapeCollectionEntityTable?.GetIndexColumnValues("index:Vim.ShapeCollection:ShapeCollection") ?? Array.Empty(); + SystemFamilyTypeIndex = SystemEntityTable?.GetIndexColumnValues("index:Vim.FamilyType:FamilyType") ?? Array.Empty(); + SystemElementIndex = SystemEntityTable?.GetIndexColumnValues("index:Vim.Element:Element") ?? Array.Empty(); + ElementInSystemSystemIndex = ElementInSystemEntityTable?.GetIndexColumnValues("index:Vim.System:System") ?? Array.Empty(); + ElementInSystemElementIndex = ElementInSystemEntityTable?.GetIndexColumnValues("index:Vim.Element:Element") ?? Array.Empty(); + WarningBimDocumentIndex = WarningEntityTable?.GetIndexColumnValues("index:Vim.BimDocument:BimDocument") ?? Array.Empty(); + ElementInWarningWarningIndex = ElementInWarningEntityTable?.GetIndexColumnValues("index:Vim.Warning:Warning") ?? Array.Empty(); + ElementInWarningElementIndex = ElementInWarningEntityTable?.GetIndexColumnValues("index:Vim.Element:Element") ?? Array.Empty(); + BasePointElementIndex = BasePointEntityTable?.GetIndexColumnValues("index:Vim.Element:Element") ?? Array.Empty(); + PhaseFilterElementIndex = PhaseFilterEntityTable?.GetIndexColumnValues("index:Vim.Element:Element") ?? Array.Empty(); + GridFamilyTypeIndex = GridEntityTable?.GetIndexColumnValues("index:Vim.FamilyType:FamilyType") ?? Array.Empty(); + GridElementIndex = GridEntityTable?.GetIndexColumnValues("index:Vim.Element:Element") ?? Array.Empty(); + AreaAreaSchemeIndex = AreaEntityTable?.GetIndexColumnValues("index:Vim.AreaScheme:AreaScheme") ?? Array.Empty(); + AreaElementIndex = AreaEntityTable?.GetIndexColumnValues("index:Vim.Element:Element") ?? Array.Empty(); + AreaSchemeElementIndex = AreaSchemeEntityTable?.GetIndexColumnValues("index:Vim.Element:Element") ?? Array.Empty(); + ScheduleElementIndex = ScheduleEntityTable?.GetIndexColumnValues("index:Vim.Element:Element") ?? Array.Empty(); + ScheduleColumnScheduleIndex = ScheduleColumnEntityTable?.GetIndexColumnValues("index:Vim.Schedule:Schedule") ?? Array.Empty(); + ScheduleCellScheduleColumnIndex = ScheduleCellEntityTable?.GetIndexColumnValues("index:Vim.ScheduleColumn:ScheduleColumn") ?? Array.Empty(); + ViewSheetSetElementIndex = ViewSheetSetEntityTable?.GetIndexColumnValues("index:Vim.Element:Element") ?? Array.Empty(); + ViewSheetFamilyTypeIndex = ViewSheetEntityTable?.GetIndexColumnValues("index:Vim.FamilyType:FamilyType") ?? Array.Empty(); + ViewSheetElementIndex = ViewSheetEntityTable?.GetIndexColumnValues("index:Vim.Element:Element") ?? Array.Empty(); + ViewSheetInViewSheetSetViewSheetIndex = ViewSheetInViewSheetSetEntityTable?.GetIndexColumnValues("index:Vim.ViewSheet:ViewSheet") ?? Array.Empty(); + ViewSheetInViewSheetSetViewSheetSetIndex = ViewSheetInViewSheetSetEntityTable?.GetIndexColumnValues("index:Vim.ViewSheetSet:ViewSheetSet") ?? Array.Empty(); + ViewInViewSheetSetViewIndex = ViewInViewSheetSetEntityTable?.GetIndexColumnValues("index:Vim.View:View") ?? Array.Empty(); + ViewInViewSheetSetViewSheetSetIndex = ViewInViewSheetSetEntityTable?.GetIndexColumnValues("index:Vim.ViewSheetSet:ViewSheetSet") ?? Array.Empty(); + ViewInViewSheetViewIndex = ViewInViewSheetEntityTable?.GetIndexColumnValues("index:Vim.View:View") ?? Array.Empty(); + ViewInViewSheetViewSheetIndex = ViewInViewSheetEntityTable?.GetIndexColumnValues("index:Vim.ViewSheet:ViewSheet") ?? Array.Empty(); + SiteElementIndex = SiteEntityTable?.GetIndexColumnValues("index:Vim.Element:Element") ?? Array.Empty(); + BuildingSiteIndex = BuildingEntityTable?.GetIndexColumnValues("index:Vim.Site:Site") ?? Array.Empty(); + BuildingElementIndex = BuildingEntityTable?.GetIndexColumnValues("index:Vim.Element:Element") ?? Array.Empty(); // Initialize entity collections - AssetList = NumAsset.Select(i => GetAsset(i)); - DisplayUnitList = NumDisplayUnit.Select(i => GetDisplayUnit(i)); - ParameterDescriptorList = NumParameterDescriptor.Select(i => GetParameterDescriptor(i)); - ParameterList = NumParameter.Select(i => GetParameter(i)); - ElementList = NumElement.Select(i => GetElement(i)); - WorksetList = NumWorkset.Select(i => GetWorkset(i)); - AssemblyInstanceList = NumAssemblyInstance.Select(i => GetAssemblyInstance(i)); - GroupList = NumGroup.Select(i => GetGroup(i)); - DesignOptionList = NumDesignOption.Select(i => GetDesignOption(i)); - LevelList = NumLevel.Select(i => GetLevel(i)); - PhaseList = NumPhase.Select(i => GetPhase(i)); - RoomList = NumRoom.Select(i => GetRoom(i)); - BimDocumentList = NumBimDocument.Select(i => GetBimDocument(i)); - DisplayUnitInBimDocumentList = NumDisplayUnitInBimDocument.Select(i => GetDisplayUnitInBimDocument(i)); - PhaseOrderInBimDocumentList = NumPhaseOrderInBimDocument.Select(i => GetPhaseOrderInBimDocument(i)); - CategoryList = NumCategory.Select(i => GetCategory(i)); - FamilyList = NumFamily.Select(i => GetFamily(i)); - FamilyTypeList = NumFamilyType.Select(i => GetFamilyType(i)); - FamilyInstanceList = NumFamilyInstance.Select(i => GetFamilyInstance(i)); - ViewList = NumView.Select(i => GetView(i)); - ElementInViewList = NumElementInView.Select(i => GetElementInView(i)); - ShapeInViewList = NumShapeInView.Select(i => GetShapeInView(i)); - AssetInViewList = NumAssetInView.Select(i => GetAssetInView(i)); - AssetInViewSheetList = NumAssetInViewSheet.Select(i => GetAssetInViewSheet(i)); - LevelInViewList = NumLevelInView.Select(i => GetLevelInView(i)); - CameraList = NumCamera.Select(i => GetCamera(i)); - MaterialList = NumMaterial.Select(i => GetMaterial(i)); - MaterialInElementList = NumMaterialInElement.Select(i => GetMaterialInElement(i)); - CompoundStructureLayerList = NumCompoundStructureLayer.Select(i => GetCompoundStructureLayer(i)); - CompoundStructureList = NumCompoundStructure.Select(i => GetCompoundStructure(i)); - NodeList = NumNode.Select(i => GetNode(i)); - GeometryList = NumGeometry.Select(i => GetGeometry(i)); - ShapeList = NumShape.Select(i => GetShape(i)); - ShapeCollectionList = NumShapeCollection.Select(i => GetShapeCollection(i)); - ShapeInShapeCollectionList = NumShapeInShapeCollection.Select(i => GetShapeInShapeCollection(i)); - SystemList = NumSystem.Select(i => GetSystem(i)); - ElementInSystemList = NumElementInSystem.Select(i => GetElementInSystem(i)); - WarningList = NumWarning.Select(i => GetWarning(i)); - ElementInWarningList = NumElementInWarning.Select(i => GetElementInWarning(i)); - BasePointList = NumBasePoint.Select(i => GetBasePoint(i)); - PhaseFilterList = NumPhaseFilter.Select(i => GetPhaseFilter(i)); - GridList = NumGrid.Select(i => GetGrid(i)); - AreaList = NumArea.Select(i => GetArea(i)); - AreaSchemeList = NumAreaScheme.Select(i => GetAreaScheme(i)); - ScheduleList = NumSchedule.Select(i => GetSchedule(i)); - ScheduleColumnList = NumScheduleColumn.Select(i => GetScheduleColumn(i)); - ScheduleCellList = NumScheduleCell.Select(i => GetScheduleCell(i)); - ViewSheetSetList = NumViewSheetSet.Select(i => GetViewSheetSet(i)); - ViewSheetList = NumViewSheet.Select(i => GetViewSheet(i)); - ViewSheetInViewSheetSetList = NumViewSheetInViewSheetSet.Select(i => GetViewSheetInViewSheetSet(i)); - ViewInViewSheetSetList = NumViewInViewSheetSet.Select(i => GetViewInViewSheetSet(i)); - ViewInViewSheetList = NumViewInViewSheet.Select(i => GetViewInViewSheet(i)); - SiteList = NumSite.Select(i => GetSite(i)); - BuildingList = NumBuilding.Select(i => GetBuilding(i)); + AssetList = Enumerable.Range(0, NumAsset).Select(i => GetAsset(i)).ToArray(); + DisplayUnitList = Enumerable.Range(0, NumDisplayUnit).Select(i => GetDisplayUnit(i)).ToArray(); + ParameterDescriptorList = Enumerable.Range(0, NumParameterDescriptor).Select(i => GetParameterDescriptor(i)).ToArray(); + ParameterList = Enumerable.Range(0, NumParameter).Select(i => GetParameter(i)).ToArray(); + ElementList = Enumerable.Range(0, NumElement).Select(i => GetElement(i)).ToArray(); + WorksetList = Enumerable.Range(0, NumWorkset).Select(i => GetWorkset(i)).ToArray(); + AssemblyInstanceList = Enumerable.Range(0, NumAssemblyInstance).Select(i => GetAssemblyInstance(i)).ToArray(); + GroupList = Enumerable.Range(0, NumGroup).Select(i => GetGroup(i)).ToArray(); + DesignOptionList = Enumerable.Range(0, NumDesignOption).Select(i => GetDesignOption(i)).ToArray(); + LevelList = Enumerable.Range(0, NumLevel).Select(i => GetLevel(i)).ToArray(); + PhaseList = Enumerable.Range(0, NumPhase).Select(i => GetPhase(i)).ToArray(); + RoomList = Enumerable.Range(0, NumRoom).Select(i => GetRoom(i)).ToArray(); + BimDocumentList = Enumerable.Range(0, NumBimDocument).Select(i => GetBimDocument(i)).ToArray(); + DisplayUnitInBimDocumentList = Enumerable.Range(0, NumDisplayUnitInBimDocument).Select(i => GetDisplayUnitInBimDocument(i)).ToArray(); + PhaseOrderInBimDocumentList = Enumerable.Range(0, NumPhaseOrderInBimDocument).Select(i => GetPhaseOrderInBimDocument(i)).ToArray(); + CategoryList = Enumerable.Range(0, NumCategory).Select(i => GetCategory(i)).ToArray(); + FamilyList = Enumerable.Range(0, NumFamily).Select(i => GetFamily(i)).ToArray(); + FamilyTypeList = Enumerable.Range(0, NumFamilyType).Select(i => GetFamilyType(i)).ToArray(); + FamilyInstanceList = Enumerable.Range(0, NumFamilyInstance).Select(i => GetFamilyInstance(i)).ToArray(); + ViewList = Enumerable.Range(0, NumView).Select(i => GetView(i)).ToArray(); + ElementInViewList = Enumerable.Range(0, NumElementInView).Select(i => GetElementInView(i)).ToArray(); + ShapeInViewList = Enumerable.Range(0, NumShapeInView).Select(i => GetShapeInView(i)).ToArray(); + AssetInViewList = Enumerable.Range(0, NumAssetInView).Select(i => GetAssetInView(i)).ToArray(); + AssetInViewSheetList = Enumerable.Range(0, NumAssetInViewSheet).Select(i => GetAssetInViewSheet(i)).ToArray(); + LevelInViewList = Enumerable.Range(0, NumLevelInView).Select(i => GetLevelInView(i)).ToArray(); + CameraList = Enumerable.Range(0, NumCamera).Select(i => GetCamera(i)).ToArray(); + MaterialList = Enumerable.Range(0, NumMaterial).Select(i => GetMaterial(i)).ToArray(); + MaterialInElementList = Enumerable.Range(0, NumMaterialInElement).Select(i => GetMaterialInElement(i)).ToArray(); + CompoundStructureLayerList = Enumerable.Range(0, NumCompoundStructureLayer).Select(i => GetCompoundStructureLayer(i)).ToArray(); + CompoundStructureList = Enumerable.Range(0, NumCompoundStructure).Select(i => GetCompoundStructure(i)).ToArray(); + NodeList = Enumerable.Range(0, NumNode).Select(i => GetNode(i)).ToArray(); + GeometryList = Enumerable.Range(0, NumGeometry).Select(i => GetGeometry(i)).ToArray(); + ShapeList = Enumerable.Range(0, NumShape).Select(i => GetShape(i)).ToArray(); + ShapeCollectionList = Enumerable.Range(0, NumShapeCollection).Select(i => GetShapeCollection(i)).ToArray(); + ShapeInShapeCollectionList = Enumerable.Range(0, NumShapeInShapeCollection).Select(i => GetShapeInShapeCollection(i)).ToArray(); + SystemList = Enumerable.Range(0, NumSystem).Select(i => GetSystem(i)).ToArray(); + ElementInSystemList = Enumerable.Range(0, NumElementInSystem).Select(i => GetElementInSystem(i)).ToArray(); + WarningList = Enumerable.Range(0, NumWarning).Select(i => GetWarning(i)).ToArray(); + ElementInWarningList = Enumerable.Range(0, NumElementInWarning).Select(i => GetElementInWarning(i)).ToArray(); + BasePointList = Enumerable.Range(0, NumBasePoint).Select(i => GetBasePoint(i)).ToArray(); + PhaseFilterList = Enumerable.Range(0, NumPhaseFilter).Select(i => GetPhaseFilter(i)).ToArray(); + GridList = Enumerable.Range(0, NumGrid).Select(i => GetGrid(i)).ToArray(); + AreaList = Enumerable.Range(0, NumArea).Select(i => GetArea(i)).ToArray(); + AreaSchemeList = Enumerable.Range(0, NumAreaScheme).Select(i => GetAreaScheme(i)).ToArray(); + ScheduleList = Enumerable.Range(0, NumSchedule).Select(i => GetSchedule(i)).ToArray(); + ScheduleColumnList = Enumerable.Range(0, NumScheduleColumn).Select(i => GetScheduleColumn(i)).ToArray(); + ScheduleCellList = Enumerable.Range(0, NumScheduleCell).Select(i => GetScheduleCell(i)).ToArray(); + ViewSheetSetList = Enumerable.Range(0, NumViewSheetSet).Select(i => GetViewSheetSet(i)).ToArray(); + ViewSheetList = Enumerable.Range(0, NumViewSheet).Select(i => GetViewSheet(i)).ToArray(); + ViewSheetInViewSheetSetList = Enumerable.Range(0, NumViewSheetInViewSheetSet).Select(i => GetViewSheetInViewSheetSet(i)).ToArray(); + ViewInViewSheetSetList = Enumerable.Range(0, NumViewInViewSheetSet).Select(i => GetViewInViewSheetSet(i)).ToArray(); + ViewInViewSheetList = Enumerable.Range(0, NumViewInViewSheet).Select(i => GetViewInViewSheet(i)).ToArray(); + SiteList = Enumerable.Range(0, NumSite).Select(i => GetSite(i)).ToArray(); + BuildingList = Enumerable.Range(0, NumBuilding).Select(i => GetBuilding(i)).ToArray(); // Initialize element index maps ElementIndexMaps = new ElementIndexMaps(this, inParallel); diff --git a/src/cs/vim/Vim.Format/ObjectModel/Validation.cs b/src/cs/vim/Vim.Format/ObjectModel/Validation.cs index 1e6167da..7869186e 100644 --- a/src/cs/vim/Vim.Format/ObjectModel/Validation.cs +++ b/src/cs/vim/Vim.Format/ObjectModel/Validation.cs @@ -5,6 +5,7 @@ using System.Threading.Tasks; using Vim.LinqArray; using Vim.Math3d; +using Vim.Util; namespace Vim.Format.ObjectModel { @@ -58,7 +59,7 @@ public static void ValidateBimDocument(this DocumentModel dm, ObjectModelValidat if (dm.NumBimDocument == 0 && validationOptions.BimDocumentMustExist) throw new ObjectModelValidationException($"No {nameof(BimDocument)} found."); - foreach (var bd in dm.BimDocumentList.ToEnumerable()) + foreach (var bd in dm.BimDocumentList) { var bdElement = bd.Element; if (bdElement == null) @@ -150,7 +151,7 @@ public static void ValidateAssets(this DocumentModel dm) public static void ValidateParameters(this DocumentModel dm) { - Parallel.ForEach(dm.ParameterList.ToEnumerable(), p => + Parallel.ForEach(dm.ParameterList, p => { // Each parameter must be associated to an element. if (p._Element.Index == EntityRelation.None) @@ -162,7 +163,7 @@ public static void ValidateParameters(this DocumentModel dm) }); // Validate the parameter descriptors. - foreach (var pd in dm.ParameterDescriptorList.ToEnumerable()) + foreach (var pd in dm.ParameterDescriptorList) { if (pd.DisplayUnit == null) throw new ObjectModelValidationException($"{nameof(DisplayUnit)} is null for {nameof(ParameterDescriptor)} {pd.Index}"); @@ -198,7 +199,7 @@ public static void ValidatePhases(this DocumentModel dm) } // Validate that the phase order information covers the set of phases. - var phaseIndexSet = new HashSet(dm.PhaseList.Select(p => p.Index).ToEnumerable()); + var phaseIndexSet = new HashSet(dm.PhaseList.Select(p => p.Index)); phaseIndexSet.ExceptWith(poArray.Select(po => po.Index)); if (phaseIndexSet.Count != 0) throw new ObjectModelValidationException($"{nameof(Phase)} index coverage is incomplete among {nameof(PhaseOrderInBimDocument)}"); @@ -253,7 +254,7 @@ void ValidateDVector3Domain(string label, DVector3 value, DVector3 lowerInclusiv } } - foreach (var material in dm.MaterialList.ToEnumerable()) + foreach (var material in dm.MaterialList) { var index = material.Index; ValidateDVector3Domain(nameof(material.Color), material.Color, DVector3.Zero, DVector3.One, index); @@ -278,7 +279,7 @@ public static void ValidateShapesInView(this DocumentModel dm) var viewToElementsMap = dm.ElementInViewList.ToArray().GetViewToElementsMap(); // Validate that the shapes in view have an element which is also in the same view. - foreach (var item in dm.ShapeInViewList.ToEnumerable()) + foreach (var item in dm.ShapeInViewList) { var viewIndex = item._View.Index; var shape = item.Shape; @@ -302,7 +303,7 @@ public static void ValidateEntitiesWithElement(this DocumentModel dm) Parallel.ForEach(entityWithElementTypes, entityWithElementType => { - var elementIndices = ((IArray)dm.GetPropertyValue(entityWithElementType.Name + "ElementIndex")).ToArray(); + var elementIndices = ((int[])dm.GetPropertyValue(entityWithElementType.Name + "ElementIndex")).ToArray(); for (var i = 0; i < elementIndices.Length; ++i) { var elementIndex = elementIndices[i]; @@ -316,7 +317,7 @@ public static void ValidateEntitiesWithElement(this DocumentModel dm) public static void ValidateElementInSystem(this DocumentModel dm) { - foreach (var eis in dm.ElementInSystemList.ToEnumerable()) + foreach (var eis in dm.ElementInSystemList) { if (eis.System == null) throw new ObjectModelValidationException($"{nameof(ElementInSystem)} @ {eis.Index} has a null {nameof(ElementInSystem.System)}"); diff --git a/src/cs/vim/Vim.Format/SceneBuilder/VimSceneHelpers.cs b/src/cs/vim/Vim.Format/SceneBuilder/VimSceneHelpers.cs index 025a2c6c..cf7ed5cc 100644 --- a/src/cs/vim/Vim.Format/SceneBuilder/VimSceneHelpers.cs +++ b/src/cs/vim/Vim.Format/SceneBuilder/VimSceneHelpers.cs @@ -156,7 +156,7 @@ public static Vector4 GetDiffuseColor(this Material m) public static Vector4 ToDiffuseColor(this DVector3 v, double transparency) => new Vector4((float)v.X, (float)v.Y, (float)v.Z, 1.0f - (float)transparency); - public static IArray MaterialColors(this VimScene scene) => scene.DocumentModel.MaterialList.Select(GetDiffuseColor); + public static Vector4[] MaterialColors(this VimScene scene) => scene.DocumentModel.MaterialList.Select(GetDiffuseColor).ToArray(); public static Vector4 DefaultColor = new Vector4(0.5f, 0.5f, 0.5f, 1); From 5bfe828deb5efde9d0f245429e73b9bc28f52449 Mon Sep 17 00:00:00 2001 From: simon Date: Tue, 16 Apr 2024 08:50:58 -0400 Subject: [PATCH 179/204] lookup with enumerables --- src/cs/linqarray/Vim.LinqArray/ILookup.cs | 22 ++++++++----------- .../DocumentBuilderExtensions.cs | 9 ++++---- .../vim/Vim.Format.Core/DocumentExtensions.cs | 10 +++++---- src/cs/vim/Vim.Format.Core/EntityTable.cs | 8 +++---- .../Vim.Format.Core/Geometry/Validation.cs | 14 ++++++------ src/cs/vim/Vim.Format.Core/Validation.cs | 14 ++++++------ .../vim/Vim.Format/SceneBuilder/Validation.cs | 2 +- 7 files changed, 39 insertions(+), 40 deletions(-) diff --git a/src/cs/linqarray/Vim.LinqArray/ILookup.cs b/src/cs/linqarray/Vim.LinqArray/ILookup.cs index 4bf6dc81..a4eb5b8b 100644 --- a/src/cs/linqarray/Vim.LinqArray/ILookup.cs +++ b/src/cs/linqarray/Vim.LinqArray/ILookup.cs @@ -13,16 +13,16 @@ namespace Vim.LinqArray /// public interface ILookup { - IArray Keys { get; } - IArray Values { get; } + IEnumerable Keys { get; } + IEnumerable Values { get; } bool Contains(TKey key); TValue this[TKey key] { get; } } public class EmptyLookup : ILookup { - public IArray Keys => LinqArray.Empty(); - public IArray Values => LinqArray.Empty(); + public IEnumerable Keys => Enumerable.Empty(); + public IEnumerable Values => Enumerable.Empty(); public bool Contains(TKey key) => false; public TValue this[TKey key] => default; } @@ -37,12 +37,10 @@ public LookupFromDictionary(IDictionary d = null, TValue defaultVa Dictionary = d ?? new Dictionary(); // TODO: sort? _default = defaultValue; - Keys = d.Keys.ToIArray(); - Values = d.Values.ToIArray(); } - public IArray Keys { get; } - public IArray Values { get; } + public IEnumerable Keys => Dictionary.Keys; + public IEnumerable Values => Dictionary.Values; public TValue this[TKey key] => Contains(key) ? Dictionary[key] : _default; public bool Contains(TKey key) => Dictionary.ContainsKey(key); } @@ -54,12 +52,10 @@ public class LookupFromArray : ILookup public LookupFromArray(IArray xs) { array = xs; - Keys = array.Indices(); - Values = array; } - public IArray Keys { get; } - public IArray Values { get; } + public IEnumerable Keys => array.Indices().ToEnumerable(); + public IEnumerable Values => array.ToEnumerable(); public TValue this[int key] => array[key]; public bool Contains(int key) => key >= 0 && key <= array.Count; } @@ -73,6 +69,6 @@ public static TValue GetOrDefault(this ILookup looku => lookup.Contains(key) ? lookup[key] : default; public static IEnumerable GetValues(this ILookup lookup) - => lookup.Keys.ToEnumerable().Select(k => lookup[k]); + => lookup.Keys.Select(k => lookup[k]); } } diff --git a/src/cs/vim/Vim.Format.Core/DocumentBuilderExtensions.cs b/src/cs/vim/Vim.Format.Core/DocumentBuilderExtensions.cs index a8bf6e51..a73fe17b 100644 --- a/src/cs/vim/Vim.Format.Core/DocumentBuilderExtensions.cs +++ b/src/cs/vim/Vim.Format.Core/DocumentBuilderExtensions.cs @@ -3,6 +3,7 @@ using Vim.BFastLib; using Vim.Format.Geometry; using Vim.LinqArray; +using Vim.Util; using static Vim.Format.DocumentBuilder; namespace Vim.Format @@ -21,17 +22,17 @@ public static EntityTableBuilder CreateTableCopy(this DocumentBuilder db, Entity var name = table.Name; var tb = db.CreateTableBuilder(name); - foreach (var col in table.IndexColumns.Values.ToEnumerable()) + foreach (var col in table.IndexColumns.Values) { tb.AddIndexColumn(col.Name, col.GetTypedData().RemapData(nodeIndexRemapping)); } - foreach (var col in table.DataColumns.Values.ToEnumerable()) + foreach (var col in table.DataColumns.Values) { tb.AddDataColumn(col.Name, col.CopyDataColumn(nodeIndexRemapping)); } - foreach (var col in table.StringColumns.Values.ToEnumerable()) + foreach (var col in table.StringColumns.Values) { var strings = col.GetTypedData().Select(i => table.Document.StringTable.ElementAtOrDefault(i, null)); tb.AddStringColumn(col.Name, strings.ToArray().RemapData(nodeIndexRemapping)); @@ -42,7 +43,7 @@ public static EntityTableBuilder CreateTableCopy(this DocumentBuilder db, Entity public static DocumentBuilder CopyTablesFrom(this DocumentBuilder db, Document doc, List nodeIndexRemapping = null) { - foreach (var table in doc.EntityTables.Values.ToEnumerable()) + foreach (var table in doc.EntityTables.Values) { var name = table.Name; diff --git a/src/cs/vim/Vim.Format.Core/DocumentExtensions.cs b/src/cs/vim/Vim.Format.Core/DocumentExtensions.cs index 3ab52296..3ed5c589 100644 --- a/src/cs/vim/Vim.Format.Core/DocumentExtensions.cs +++ b/src/cs/vim/Vim.Format.Core/DocumentExtensions.cs @@ -2,6 +2,8 @@ using System.Text.RegularExpressions; using Vim.LinqArray; using Vim.BFastLib; +using System.Collections.Generic; +using System.Linq; namespace Vim.Format { @@ -13,14 +15,14 @@ public static Document ToDocument(this SerializableDocument document) public static EntityTable ToEntityTable(this SerializableEntityTable entityTable, Document document) => new EntityTable(document, entityTable); - public static string[] GetColumnNames(this EntityTable table) - => table.Columns.Select(b => b.Name).ToArray(); + public static IEnumerable GetColumnNames(this EntityTable table) + => table.Columns.Select(c => c.Name); public static void ValidateRelations(this Document doc) { - foreach (var et in doc.EntityTables.Values.ToEnumerable()) + foreach (var et in doc.EntityTables.Values) { - foreach (var ic in et.IndexColumns.Values.ToEnumerable()) + foreach (var ic in et.IndexColumns.Values) { var relatedTable = ic.GetRelatedTable(doc); var maxValue = relatedTable.NumRows; diff --git a/src/cs/vim/Vim.Format.Core/EntityTable.cs b/src/cs/vim/Vim.Format.Core/EntityTable.cs index 51551e09..42c7b967 100644 --- a/src/cs/vim/Vim.Format.Core/EntityTable.cs +++ b/src/cs/vim/Vim.Format.Core/EntityTable.cs @@ -2,6 +2,7 @@ using Vim.LinqArray; using Vim.BFastLib; using System.Linq; +using System.Collections.Generic; namespace Vim.Format { @@ -28,11 +29,10 @@ public EntityTable(Document document, SerializableEntityTable entityTable) public LinqArray.ILookup DataColumns { get; } public LinqArray.ILookup> StringColumns { get; } public LinqArray.ILookup> IndexColumns { get; } - public INamedBuffer[] Columns + public IEnumerable Columns => DataColumns.Values - .Concatenate(IndexColumns.Values.Select(x => (INamedBuffer)x)) - .Concatenate(StringColumns.Values.Select(x => (INamedBuffer)x)) - .ToArray(); + .Concat(IndexColumns.Values.Select(x => (INamedBuffer)x)) + .Concat(StringColumns.Values.Select(x => (INamedBuffer)x)); public int[] GetIndexColumnValues(string columnName) => IndexColumns.GetOrDefault(columnName)?.GetColumnValues(); diff --git a/src/cs/vim/Vim.Format.Core/Geometry/Validation.cs b/src/cs/vim/Vim.Format.Core/Geometry/Validation.cs index e987282a..474b340a 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/Validation.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/Validation.cs @@ -8,21 +8,21 @@ public static class Validation { public static void ValidateTableRows(this Document doc) { - foreach (var et in doc.EntityTables.Values.ToArray()) + foreach (var et in doc.EntityTables.Values) { - foreach (var c in et.IndexColumns.Values.ToArray()) + foreach (var c in et.IndexColumns.Values) { if (c.Array.Length != et.NumRows) throw new Exception($"Expected array length {c.Array.Length} of column {c.Name} to be the same as number of rows {et.NumRows}"); } - foreach (var c in et.DataColumns.Values.ToArray()) + foreach (var c in et.DataColumns.Values) { if (c.NumElements() != et.NumRows) throw new Exception($"Expected array length {c.NumElements()} of column {c.Name} to be the same as number of rows {et.NumRows}"); } - foreach (var c in et.StringColumns.Values.ToArray()) + foreach (var c in et.StringColumns.Values) { if (c.Array.Length != et.NumRows) throw new Exception($"Expected array length {c.Array.Length} of column {c.Name} to be the same as number of rows {et.NumRows}"); @@ -32,9 +32,9 @@ public static void ValidateTableRows(this Document doc) public static void ValidateIndexColumns(this Document doc) { - foreach (var et in doc.EntityTables.Values.ToArray()) + foreach (var et in doc.EntityTables.Values) { - foreach (var ic in et.IndexColumns.Values.ToEnumerable()) + foreach (var ic in et.IndexColumns.Values) { var table = ic.GetRelatedTable(doc); if (table == null) @@ -45,7 +45,7 @@ public static void ValidateIndexColumns(this Document doc) public static void ValidateAssets(this Document doc) { - foreach (var asset in doc.Assets.Values.ToEnumerable()) + foreach (var asset in doc.Assets.Values) AssetInfo.Parse(asset.Name); // This will throw if it fails to parse. } diff --git a/src/cs/vim/Vim.Format.Core/Validation.cs b/src/cs/vim/Vim.Format.Core/Validation.cs index e44b2d1c..6d596db8 100644 --- a/src/cs/vim/Vim.Format.Core/Validation.cs +++ b/src/cs/vim/Vim.Format.Core/Validation.cs @@ -9,21 +9,21 @@ public static class Validation { public static void ValidateTableRows(this Document doc) { - foreach (var et in doc.EntityTables.Values.ToArray()) + foreach (var et in doc.EntityTables.Values) { - foreach (var c in et.IndexColumns.Values.ToArray()) + foreach (var c in et.IndexColumns.Values) { if (c.Array.Length != et.NumRows) throw new Exception($"Expected array length {c.Array.Length} of column {c.Name} to be the same as number of rows {et.NumRows}"); } - foreach (var c in et.DataColumns.Values.ToArray()) + foreach (var c in et.DataColumns.Values) { if (c.NumElements() != et.NumRows) throw new Exception($"Expected array length {c.NumElements()} of column {c.Name} to be the same as number of rows {et.NumRows}"); } - foreach (var c in et.StringColumns.Values.ToArray()) + foreach (var c in et.StringColumns.Values) { if (c.Array.Length != et.NumRows) throw new Exception($"Expected array length {c.Array.Length} of column {c.Name} to be the same as number of rows {et.NumRows}"); @@ -33,9 +33,9 @@ public static void ValidateTableRows(this Document doc) public static void ValidateIndexColumns(this Document doc) { - foreach (var et in doc.EntityTables.Values.ToArray()) + foreach (var et in doc.EntityTables.Values) { - foreach (var ic in et.IndexColumns.Values.ToEnumerable()) + foreach (var ic in et.IndexColumns.Values) { var table = ic.GetRelatedTable(doc); if (table == null) @@ -46,7 +46,7 @@ public static void ValidateIndexColumns(this Document doc) public static void ValidateAssets(this Document doc) { - foreach (var asset in doc.Assets.Values.ToEnumerable()) + foreach (var asset in doc.Assets.Values) AssetInfo.Parse(asset.Name); // This will throw if it fails to parse. } diff --git a/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs b/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs index ceb34e38..0f7f2107 100644 --- a/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs +++ b/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs @@ -143,7 +143,7 @@ public static void ValidateEquality(this DocumentBuilder db, VimScene vim) // Test the entity tables. var tableNames = new HashSet(db.Tables.Values.Select(t => t.Name)); - foreach (var et in vim.Document.EntityTables.Keys.ToEnumerable()) + foreach (var et in vim.Document.EntityTables.Keys) { if (!tableNames.Contains(et)) throw new VimValidationException($"{nameof(DocumentBuilder)} does not contain table name {et} from {nameof(VimScene)}"); From ec747ebea11ebb7def0947239c7fe570c62e568e Mon Sep 17 00:00:00 2001 From: simon Date: Tue, 16 Apr 2024 09:01:52 -0400 Subject: [PATCH 180/204] iarray -> array --- src/cs/vim/Vim.Format.Core/AssetInfo.cs | 3 ++- src/cs/vim/Vim.Format.Core/VimSchema.cs | 4 ++-- src/cs/vim/Vim.Format.Tests/FormatTests.cs | 24 +++++++++---------- .../Vim.Format.Vimx.Conversion/Ordering.cs | 6 ++--- .../VimxConverter.cs | 13 +++++----- 5 files changed, 25 insertions(+), 25 deletions(-) diff --git a/src/cs/vim/Vim.Format.Core/AssetInfo.cs b/src/cs/vim/Vim.Format.Core/AssetInfo.cs index 009d7d37..53c3ef73 100644 --- a/src/cs/vim/Vim.Format.Core/AssetInfo.cs +++ b/src/cs/vim/Vim.Format.Core/AssetInfo.cs @@ -4,6 +4,7 @@ using Vim.Util; using Vim.LinqArray; using Vim.BFastLib; +using System.Linq; namespace Vim.Format { @@ -123,7 +124,7 @@ public static FileInfo ExtractAsset(this Document doc, string assetBufferName, F public static IEnumerable<(string assetBufferName, FileInfo assetFileInfo)> ExtractAssets(this Document doc, DirectoryInfo directoryInfo) { var result = new List<(string assetBufferName, FileInfo assetFileInfo)>(); - foreach (var assetBuffer in doc.Assets.Values.ToEnumerable()) + foreach (var assetBuffer in doc.Assets.Values) { var assetBufferName = assetBuffer.Name; var assetFilePath = assetBuffer.ExtractAsset(directoryInfo); diff --git a/src/cs/vim/Vim.Format.Core/VimSchema.cs b/src/cs/vim/Vim.Format.Core/VimSchema.cs index 70b9e025..8195c39a 100644 --- a/src/cs/vim/Vim.Format.Core/VimSchema.cs +++ b/src/cs/vim/Vim.Format.Core/VimSchema.cs @@ -53,12 +53,12 @@ public static VimSchema Create(SerializableDocument doc) private static VimSchema Create(Document doc) { var vimSchema = new VimSchema(doc.Header); - foreach (var entityTable in doc.EntityTables.Values.ToEnumerable()) + foreach (var entityTable in doc.EntityTables.Values) { var ets = vimSchema.AddEntityTableSchema(entityTable.Name); // Collect all the column names in the entity table and sort them alphabetically. - foreach (var columnName in entityTable.Columns.Select(nb => nb.Name).ToEnumerable().OrderBy(n => n)) + foreach (var columnName in entityTable.Columns.Select(nb => nb.Name).OrderBy(n => n)) ets.AddColumn(columnName); } return vimSchema; diff --git a/src/cs/vim/Vim.Format.Tests/FormatTests.cs b/src/cs/vim/Vim.Format.Tests/FormatTests.cs index 544469ff..b243c570 100644 --- a/src/cs/vim/Vim.Format.Tests/FormatTests.cs +++ b/src/cs/vim/Vim.Format.Tests/FormatTests.cs @@ -68,12 +68,12 @@ public static void AssertEquals(SerializableDocument d1, SerializableDocument d2 public static void AssertEquals(EntityTable et1, EntityTable et2) { Assert.AreEqual(et1.Name, et2.Name); - Assert.AreEqual(et1.DataColumns.Keys.ToEnumerable().OrderBy(n => n).ToArray(), et2.DataColumns.Keys.ToEnumerable().OrderBy(n => n).ToArray()); - Assert.AreEqual(et1.IndexColumns.Keys.ToEnumerable().OrderBy(n => n).ToArray(), et2.IndexColumns.Keys.ToEnumerable().OrderBy(n => n).ToArray()); - Assert.AreEqual(et1.StringColumns.Keys.ToEnumerable().OrderBy(n => n).ToArray(), et2.StringColumns.Keys.ToEnumerable().OrderBy(n => n).ToArray()); + Assert.AreEqual(et1.DataColumns.Keys.OrderBy(n => n).ToArray(), et2.DataColumns.Keys.OrderBy(n => n).ToArray()); + Assert.AreEqual(et1.IndexColumns.Keys.OrderBy(n => n).ToArray(), et2.IndexColumns.Keys.OrderBy(n => n).ToArray()); + Assert.AreEqual(et1.StringColumns.Keys.OrderBy(n => n).ToArray(), et2.StringColumns.Keys.OrderBy(n => n).ToArray()); - var columns1 = et1.Columns.ToEnumerable().OrderBy(c => c.Name).ToArray(); - var columns2 = et2.Columns.ToEnumerable().OrderBy(c => c.Name).ToArray(); + var columns1 = et1.Columns.OrderBy(c => c.Name).ToArray(); + var columns2 = et2.Columns.OrderBy(c => c.Name).ToArray(); Assert.AreEqual( columns1.Select(ec => ec.Name).ToArray(), @@ -104,9 +104,9 @@ public static bool IsSupersetOf(IEnumerable a, IEnumerable b) public static void AssertIsSupersetOf(EntityTable et1, EntityTable et2) { Assert.AreEqual(et1.Name, et2.Name); - Assert.IsTrue(IsSupersetOf(et1.DataColumns.Keys.ToEnumerable(), et2.DataColumns.Keys.ToEnumerable())); - Assert.IsTrue(IsSupersetOf(et1.IndexColumns.Keys.ToEnumerable(), et2.IndexColumns.Keys.ToEnumerable())); - Assert.IsTrue(IsSupersetOf(et1.StringColumns.Keys.ToEnumerable(), et2.StringColumns.Keys.ToEnumerable())); + Assert.IsTrue(IsSupersetOf(et1.DataColumns.Keys, et2.DataColumns.Keys)); + Assert.IsTrue(IsSupersetOf(et1.IndexColumns.Keys, et2.IndexColumns.Keys)); + Assert.IsTrue(IsSupersetOf(et1.StringColumns.Keys, et2.StringColumns.Keys)); var columns1 = et1.Columns.ToArray(); var columns2 = et2.Columns.ToArray(); @@ -137,9 +137,9 @@ public static void AssertIsSuperSetOf(Document d1, Document d2, bool skipGeometr var etKeys1 = d1.EntityTables.Keys; var etKeys2 = d2.EntityTables.Keys; - Assert.IsTrue(IsSupersetOf(etKeys1.ToEnumerable(), etKeys2.ToEnumerable())); + Assert.IsTrue(IsSupersetOf(etKeys1, etKeys2)); - foreach (var key in etKeys2.ToEnumerable()) + foreach (var key in etKeys2) { if (skipGeometryAndNodes && key.ToLowerInvariant().Contains("geometry")) continue; @@ -158,8 +158,8 @@ public static void AssertEquals(Document d1, Document d2, bool skipGeometryAndNo var schema2 = VimSchema.Create(d2._Document); Assert.IsTrue(VimSchema.IsSame(schema1, schema2)); - var entityTables1 = d1.EntityTables.Keys.ToEnumerable().OrderBy(n => n).ToArray(); - var entityTables2 = d2.EntityTables.Keys.ToEnumerable().OrderBy(n => n).ToArray(); + var entityTables1 = d1.EntityTables.Keys.OrderBy(n => n).ToArray(); + var entityTables2 = d2.EntityTables.Keys.OrderBy(n => n).ToArray(); Assert.AreEqual(entityTables1, entityTables2); foreach (var k in entityTables1) diff --git a/src/cs/vim/Vim.Format.Vimx.Conversion/Ordering.cs b/src/cs/vim/Vim.Format.Vimx.Conversion/Ordering.cs index d079bf0b..2424185b 100644 --- a/src/cs/vim/Vim.Format.Vimx.Conversion/Ordering.cs +++ b/src/cs/vim/Vim.Format.Vimx.Conversion/Ordering.cs @@ -40,13 +40,13 @@ static string GetMeshName(G3dVim g3d, DocumentModel bim, int mesh) { var node = g3d.GetMeshInstances(mesh)[0]; - if (node < 0 || node >= bim.NodeElementIndex.Count) return ""; + if (node < 0 || node >= bim.NodeElementIndex.Length) return ""; var element = bim.NodeElementIndex[node]; - if (element < 0 || element >= bim.ElementCategoryIndex.Count) return ""; + if (element < 0 || element >= bim.ElementCategoryIndex.Length) return ""; var category = bim.ElementCategoryIndex[element]; - if (category < 0 || category >= bim.CategoryName.Count) return ""; + if (category < 0 || category >= bim.CategoryName.Length) return ""; var name = bim.CategoryName[category]; return name; diff --git a/src/cs/vim/Vim.Format.Vimx.Conversion/VimxConverter.cs b/src/cs/vim/Vim.Format.Vimx.Conversion/VimxConverter.cs index 31d3e45f..804635ae 100644 --- a/src/cs/vim/Vim.Format.Vimx.Conversion/VimxConverter.cs +++ b/src/cs/vim/Vim.Format.Vimx.Conversion/VimxConverter.cs @@ -1,13 +1,12 @@ -using System.Linq; -using Vim.LinqArray; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; using Vim.BFastLib; -using Vim.G3dNext; using Vim.Format.ObjectModel; using Vim.G3dNext; -using System.Collections.Generic; +using Vim.LinqArray; using Vim.Math3d; -using System.Diagnostics; -using System; +using Vim.Util; namespace Vim.Format.VimxLib.Conversion { @@ -106,7 +105,7 @@ public static G3dScene CreateScene(VimChunks chunks, DocumentModel bim) // bim instanceNodes[instance] = node; instanceGroups[instance] = element; - instanceTags[instance] = bim.ElementId.SafeGet(element, -1); + instanceTags[instance] = bim.ElementId.ElementAtOrDefault(element, -1); instance++; } From 90e3a2f8c2be79e1a63a2bf61c044bdcc0f2f4c3 Mon Sep 17 00:00:00 2001 From: simon Date: Tue, 16 Apr 2024 09:50:09 -0400 Subject: [PATCH 181/204] addind missing functions --- src/cs/util/Vim.Util/LinqExtensions.cs | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/cs/util/Vim.Util/LinqExtensions.cs b/src/cs/util/Vim.Util/LinqExtensions.cs index 56800bb0..ac6b9410 100644 --- a/src/cs/util/Vim.Util/LinqExtensions.cs +++ b/src/cs/util/Vim.Util/LinqExtensions.cs @@ -8,6 +8,32 @@ namespace Vim.Util { public static class LinqExtensions { + /// + /// Returns the index of the first element matching the given item. + /// + public static int IndexOf(this IList self, Func predicate) + { + for (var i = 0; i < self.Count; ++i) + { + if (predicate(self[i])) + return i; + } + return -1; + } + + /// + /// Returns an IEnumerable containing only indices of the array for which the function satisfies a specific predicate. + /// An IArray is not created automatically because it is an expensive operation that is potentially unneeded. + /// + public static IEnumerable IndicesWhere(this IList self, Func predicate) + { + for (var i = 0; i < self.Count; ++i) + { + if (predicate(self[i])) + yield return i; + } + } + /// /// Returns the top of a stack, or the default T value if none is present. /// From deb6a22fd94cd8710ddb81fb7560ccf94e6b561e Mon Sep 17 00:00:00 2001 From: simon Date: Tue, 16 Apr 2024 09:54:09 -0400 Subject: [PATCH 182/204] more extensions --- src/cs/util/Vim.Util/LinqExtensions.cs | 28 ++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/src/cs/util/Vim.Util/LinqExtensions.cs b/src/cs/util/Vim.Util/LinqExtensions.cs index ac6b9410..8a6c0b0a 100644 --- a/src/cs/util/Vim.Util/LinqExtensions.cs +++ b/src/cs/util/Vim.Util/LinqExtensions.cs @@ -9,7 +9,7 @@ namespace Vim.Util public static class LinqExtensions { /// - /// Returns the index of the first element matching the given item. + /// Returns the index of the first element matching the given predicate. /// public static int IndexOf(this IList self, Func predicate) { @@ -21,9 +21,21 @@ public static int IndexOf(this IList self, Func predicate) return -1; } + /// + /// Returns the index of the first element matching the given item. + /// + public static int IndexOf(this IList self, T value) where T:IEquatable + { + for (var i = 0; i < self.Count; ++i) + { + if (self[i].Equals(value)) + return i; + } + return -1; + } + /// /// Returns an IEnumerable containing only indices of the array for which the function satisfies a specific predicate. - /// An IArray is not created automatically because it is an expensive operation that is potentially unneeded. /// public static IEnumerable IndicesWhere(this IList self, Func predicate) { @@ -34,6 +46,18 @@ public static IEnumerable IndicesWhere(this IList self, Func } } + /// + /// Returns an IEnumerable containing only indices of the array for which the function satisfies a specific predicate. + /// + public static IEnumerable IndicesWhere(this IList self, Func predicate) + { + for (var i = 0; i < self.Count; ++i) + { + if (predicate(self[i], i)) + yield return i; + } + } + /// /// Returns the top of a stack, or the default T value if none is present. /// From 5a1f66600877ee100232240aa2b7108ade721825 Mon Sep 17 00:00:00 2001 From: simon Date: Tue, 16 Apr 2024 09:57:38 -0400 Subject: [PATCH 183/204] removed conflicting method --- src/cs/util/Vim.Util/LinqExtensions.cs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/cs/util/Vim.Util/LinqExtensions.cs b/src/cs/util/Vim.Util/LinqExtensions.cs index 8a6c0b0a..0f82d4a9 100644 --- a/src/cs/util/Vim.Util/LinqExtensions.cs +++ b/src/cs/util/Vim.Util/LinqExtensions.cs @@ -77,12 +77,6 @@ public static T OneOrDefault(this IEnumerable values) return items?.Count == 1 ? items[0] : default; } - /// - /// A helper function for append one or more items to an IEnumerable. - /// - public static IEnumerable Append(this IEnumerable xs, params T[] x) - => xs.Concat(x); - public static T ElementAtOrDefault(this IReadOnlyList items, int index, T @default = default(T)) => index < 0 || index >= items.Count ? @default : items[index]; From 298324d0a1d30fe73b5161ad7e4335bcd25f497d Mon Sep 17 00:00:00 2001 From: simon Date: Tue, 16 Apr 2024 14:17:29 -0400 Subject: [PATCH 184/204] added array methods --- src/cs/util/Vim.Util/LinqExtensions.cs | 15 ++++++++++++++- src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs | 2 +- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/cs/util/Vim.Util/LinqExtensions.cs b/src/cs/util/Vim.Util/LinqExtensions.cs index 0f82d4a9..775fc40e 100644 --- a/src/cs/util/Vim.Util/LinqExtensions.cs +++ b/src/cs/util/Vim.Util/LinqExtensions.cs @@ -24,7 +24,7 @@ public static int IndexOf(this IList self, Func predicate) /// /// Returns the index of the first element matching the given item. /// - public static int IndexOf(this IList self, T value) where T:IEquatable + public static int IndexOf(this IList self, T value) where T : IEquatable { for (var i = 0; i < self.Count; ++i) { @@ -34,6 +34,19 @@ public static int IndexOf(this IList self, T value) where T:IEquatable return -1; } + /// + /// [a, b, c ..] => [0, a, a+b, a+b+c ...] + /// + public static int[] OffsetsFromCounts(this IList self) + { + var result = new int[self.Count]; + for (var i = 1; i < self.Count; ++i) + { + result[i] = result[i - 1] + self[i-1]; + } + return result; + } + /// /// Returns an IEnumerable containing only indices of the array for which the function satisfies a specific predicate. /// diff --git a/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs b/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs index 0f1989a3..a199e5a4 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs @@ -259,7 +259,7 @@ public static VimMesh Merge2(this VimMesh mesh, params VimMesh[] others) { var meshes = Enumerable.Empty() .Append(mesh) - .Append(others) + .Concat(others) .ToArray(); return meshes.Merge(); From df716a3eec45fc2740f3354f7b531012f47d84f1 Mon Sep 17 00:00:00 2001 From: simon Date: Tue, 16 Apr 2024 14:35:46 -0400 Subject: [PATCH 185/204] Remove array ops --- .../vim/Vim.Format.Core/Geometry/ArrayOps.cs | 259 ------------------ .../vim/Vim.Format.Core/Geometry/ArrayOps.tt | 96 ------- .../Vim.Format.Core/Vim.Format.Core.csproj | 15 - 3 files changed, 370 deletions(-) delete mode 100644 src/cs/vim/Vim.Format.Core/Geometry/ArrayOps.cs delete mode 100644 src/cs/vim/Vim.Format.Core/Geometry/ArrayOps.tt diff --git a/src/cs/vim/Vim.Format.Core/Geometry/ArrayOps.cs b/src/cs/vim/Vim.Format.Core/Geometry/ArrayOps.cs deleted file mode 100644 index d77a7f5a..00000000 --- a/src/cs/vim/Vim.Format.Core/Geometry/ArrayOps.cs +++ /dev/null @@ -1,259 +0,0 @@ - -// AUTOGENERATED FILE: DO NOT EDIT -// This file is generated from ArrayOps.tt - - -using Vim.LinqArray; -using Vim.Math3d; - -namespace Vim.Format.Geometry -{ - public static class ArrayOps - { - public static IArray< int > Add(this IArray< int > self, IArray< int > other) => self.Zip(other, MathOps.Add); - public static IArray< int > Add(this IArray< int > self, int scalar) => self.Select(x => MathOps.Add(x, scalar)); - public static IArray< int > Add(this int self, IArray< int > vector) => vector.Select(x => MathOps.Add(self, x)); - public static IArray< int > Multiply(this IArray< int > self, IArray< int > other) => self.Zip(other, MathOps.Multiply); - public static IArray< int > Multiply(this IArray< int > self, int scalar) => self.Select(x => MathOps.Multiply(x, scalar)); - public static IArray< int > Multiply(this int self, IArray< int > vector) => vector.Select(x => MathOps.Multiply(self, x)); - public static IArray< int > Subtract(this IArray< int > self, IArray< int > other) => self.Zip(other, MathOps.Subtract); - public static IArray< int > Subtract(this IArray< int > self, int scalar) => self.Select(x => MathOps.Subtract(x, scalar)); - public static IArray< int > Subtract(this int self, IArray< int > vector) => vector.Select(x => MathOps.Subtract(self, x)); - public static IArray< int > Divide(this IArray< int > self, IArray< int > other) => self.Zip(other, MathOps.Divide); - public static IArray< int > Divide(this IArray< int > self, int scalar) => self.Select(x => MathOps.Divide(x, scalar)); - public static IArray< int > Divide(this int self, IArray< int > vector) => vector.Select(x => MathOps.Divide(self, x)); - public static IArray< long > Add(this IArray< long > self, IArray< long > other) => self.Zip(other, MathOps.Add); - public static IArray< long > Add(this IArray< long > self, long scalar) => self.Select(x => MathOps.Add(x, scalar)); - public static IArray< long > Add(this long self, IArray< long > vector) => vector.Select(x => MathOps.Add(self, x)); - public static IArray< long > Multiply(this IArray< long > self, IArray< long > other) => self.Zip(other, MathOps.Multiply); - public static IArray< long > Multiply(this IArray< long > self, long scalar) => self.Select(x => MathOps.Multiply(x, scalar)); - public static IArray< long > Multiply(this long self, IArray< long > vector) => vector.Select(x => MathOps.Multiply(self, x)); - public static IArray< long > Subtract(this IArray< long > self, IArray< long > other) => self.Zip(other, MathOps.Subtract); - public static IArray< long > Subtract(this IArray< long > self, long scalar) => self.Select(x => MathOps.Subtract(x, scalar)); - public static IArray< long > Subtract(this long self, IArray< long > vector) => vector.Select(x => MathOps.Subtract(self, x)); - public static IArray< long > Divide(this IArray< long > self, IArray< long > other) => self.Zip(other, MathOps.Divide); - public static IArray< long > Divide(this IArray< long > self, long scalar) => self.Select(x => MathOps.Divide(x, scalar)); - public static IArray< long > Divide(this long self, IArray< long > vector) => vector.Select(x => MathOps.Divide(self, x)); - public static IArray< float > Add(this IArray< float > self, IArray< float > other) => self.Zip(other, MathOps.Add); - public static IArray< float > Add(this IArray< float > self, float scalar) => self.Select(x => MathOps.Add(x, scalar)); - public static IArray< float > Add(this float self, IArray< float > vector) => vector.Select(x => MathOps.Add(self, x)); - public static IArray< float > Multiply(this IArray< float > self, IArray< float > other) => self.Zip(other, MathOps.Multiply); - public static IArray< float > Multiply(this IArray< float > self, float scalar) => self.Select(x => MathOps.Multiply(x, scalar)); - public static IArray< float > Multiply(this float self, IArray< float > vector) => vector.Select(x => MathOps.Multiply(self, x)); - public static IArray< float > Subtract(this IArray< float > self, IArray< float > other) => self.Zip(other, MathOps.Subtract); - public static IArray< float > Subtract(this IArray< float > self, float scalar) => self.Select(x => MathOps.Subtract(x, scalar)); - public static IArray< float > Subtract(this float self, IArray< float > vector) => vector.Select(x => MathOps.Subtract(self, x)); - public static IArray< float > Divide(this IArray< float > self, IArray< float > other) => self.Zip(other, MathOps.Divide); - public static IArray< float > Divide(this IArray< float > self, float scalar) => self.Select(x => MathOps.Divide(x, scalar)); - public static IArray< float > Divide(this float self, IArray< float > vector) => vector.Select(x => MathOps.Divide(self, x)); - public static IArray< double > Add(this IArray< double > self, IArray< double > other) => self.Zip(other, MathOps.Add); - public static IArray< double > Add(this IArray< double > self, double scalar) => self.Select(x => MathOps.Add(x, scalar)); - public static IArray< double > Add(this double self, IArray< double > vector) => vector.Select(x => MathOps.Add(self, x)); - public static IArray< double > Multiply(this IArray< double > self, IArray< double > other) => self.Zip(other, MathOps.Multiply); - public static IArray< double > Multiply(this IArray< double > self, double scalar) => self.Select(x => MathOps.Multiply(x, scalar)); - public static IArray< double > Multiply(this double self, IArray< double > vector) => vector.Select(x => MathOps.Multiply(self, x)); - public static IArray< double > Subtract(this IArray< double > self, IArray< double > other) => self.Zip(other, MathOps.Subtract); - public static IArray< double > Subtract(this IArray< double > self, double scalar) => self.Select(x => MathOps.Subtract(x, scalar)); - public static IArray< double > Subtract(this double self, IArray< double > vector) => vector.Select(x => MathOps.Subtract(self, x)); - public static IArray< double > Divide(this IArray< double > self, IArray< double > other) => self.Zip(other, MathOps.Divide); - public static IArray< double > Divide(this IArray< double > self, double scalar) => self.Select(x => MathOps.Divide(x, scalar)); - public static IArray< double > Divide(this double self, IArray< double > vector) => vector.Select(x => MathOps.Divide(self, x)); - public static IArray< Vector2 > Add(this IArray< Vector2 > self, IArray< Vector2 > other) => self.Zip(other, MathOps.Add); - public static IArray< Vector2 > Add(this IArray< Vector2 > self, Vector2 scalar) => self.Select(x => MathOps.Add(x, scalar)); - public static IArray< Vector2 > Add(this Vector2 self, IArray< Vector2 > vector) => vector.Select(x => MathOps.Add(self, x)); - public static IArray< Vector2 > Multiply(this IArray< Vector2 > self, IArray< Vector2 > other) => self.Zip(other, MathOps.Multiply); - public static IArray< Vector2 > Multiply(this IArray< Vector2 > self, Vector2 scalar) => self.Select(x => MathOps.Multiply(x, scalar)); - public static IArray< Vector2 > Multiply(this Vector2 self, IArray< Vector2 > vector) => vector.Select(x => MathOps.Multiply(self, x)); - public static IArray< Vector2 > Subtract(this IArray< Vector2 > self, IArray< Vector2 > other) => self.Zip(other, MathOps.Subtract); - public static IArray< Vector2 > Subtract(this IArray< Vector2 > self, Vector2 scalar) => self.Select(x => MathOps.Subtract(x, scalar)); - public static IArray< Vector2 > Subtract(this Vector2 self, IArray< Vector2 > vector) => vector.Select(x => MathOps.Subtract(self, x)); - public static IArray< Vector2 > Divide(this IArray< Vector2 > self, IArray< Vector2 > other) => self.Zip(other, MathOps.Divide); - public static IArray< Vector2 > Divide(this IArray< Vector2 > self, Vector2 scalar) => self.Select(x => MathOps.Divide(x, scalar)); - public static IArray< Vector2 > Divide(this Vector2 self, IArray< Vector2 > vector) => vector.Select(x => MathOps.Divide(self, x)); - public static IArray< Vector3 > Add(this IArray< Vector3 > self, IArray< Vector3 > other) => self.Zip(other, MathOps.Add); - public static IArray< Vector3 > Add(this IArray< Vector3 > self, Vector3 scalar) => self.Select(x => MathOps.Add(x, scalar)); - public static IArray< Vector3 > Add(this Vector3 self, IArray< Vector3 > vector) => vector.Select(x => MathOps.Add(self, x)); - public static IArray< Vector3 > Multiply(this IArray< Vector3 > self, IArray< Vector3 > other) => self.Zip(other, MathOps.Multiply); - public static IArray< Vector3 > Multiply(this IArray< Vector3 > self, Vector3 scalar) => self.Select(x => MathOps.Multiply(x, scalar)); - public static IArray< Vector3 > Multiply(this Vector3 self, IArray< Vector3 > vector) => vector.Select(x => MathOps.Multiply(self, x)); - public static IArray< Vector3 > Subtract(this IArray< Vector3 > self, IArray< Vector3 > other) => self.Zip(other, MathOps.Subtract); - public static IArray< Vector3 > Subtract(this IArray< Vector3 > self, Vector3 scalar) => self.Select(x => MathOps.Subtract(x, scalar)); - public static IArray< Vector3 > Subtract(this Vector3 self, IArray< Vector3 > vector) => vector.Select(x => MathOps.Subtract(self, x)); - public static IArray< Vector3 > Divide(this IArray< Vector3 > self, IArray< Vector3 > other) => self.Zip(other, MathOps.Divide); - public static IArray< Vector3 > Divide(this IArray< Vector3 > self, Vector3 scalar) => self.Select(x => MathOps.Divide(x, scalar)); - public static IArray< Vector3 > Divide(this Vector3 self, IArray< Vector3 > vector) => vector.Select(x => MathOps.Divide(self, x)); - public static IArray< Vector4 > Add(this IArray< Vector4 > self, IArray< Vector4 > other) => self.Zip(other, MathOps.Add); - public static IArray< Vector4 > Add(this IArray< Vector4 > self, Vector4 scalar) => self.Select(x => MathOps.Add(x, scalar)); - public static IArray< Vector4 > Add(this Vector4 self, IArray< Vector4 > vector) => vector.Select(x => MathOps.Add(self, x)); - public static IArray< Vector4 > Multiply(this IArray< Vector4 > self, IArray< Vector4 > other) => self.Zip(other, MathOps.Multiply); - public static IArray< Vector4 > Multiply(this IArray< Vector4 > self, Vector4 scalar) => self.Select(x => MathOps.Multiply(x, scalar)); - public static IArray< Vector4 > Multiply(this Vector4 self, IArray< Vector4 > vector) => vector.Select(x => MathOps.Multiply(self, x)); - public static IArray< Vector4 > Subtract(this IArray< Vector4 > self, IArray< Vector4 > other) => self.Zip(other, MathOps.Subtract); - public static IArray< Vector4 > Subtract(this IArray< Vector4 > self, Vector4 scalar) => self.Select(x => MathOps.Subtract(x, scalar)); - public static IArray< Vector4 > Subtract(this Vector4 self, IArray< Vector4 > vector) => vector.Select(x => MathOps.Subtract(self, x)); - public static IArray< Vector4 > Divide(this IArray< Vector4 > self, IArray< Vector4 > other) => self.Zip(other, MathOps.Divide); - public static IArray< Vector4 > Divide(this IArray< Vector4 > self, Vector4 scalar) => self.Select(x => MathOps.Divide(x, scalar)); - public static IArray< Vector4 > Divide(this Vector4 self, IArray< Vector4 > vector) => vector.Select(x => MathOps.Divide(self, x)); - - public static IArray Abs (this IArray< double > self) => self.Select(MathOps.Abs); - public static IArray Abs (this IArray< float > self) => self.Select(MathOps.Abs); - public static IArray Abs (this IArray< Vector2 > self) => self.Select(MathOps.Abs); - public static IArray Abs (this IArray< Vector3 > self) => self.Select(MathOps.Abs); - public static IArray Abs (this IArray< Vector4 > self) => self.Select(MathOps.Abs); - - public static IArray Acos (this IArray< double > self) => self.Select(MathOps.Acos); - public static IArray Acos (this IArray< float > self) => self.Select(MathOps.Acos); - public static IArray Acos (this IArray< Vector2 > self) => self.Select(MathOps.Acos); - public static IArray Acos (this IArray< Vector3 > self) => self.Select(MathOps.Acos); - public static IArray Acos (this IArray< Vector4 > self) => self.Select(MathOps.Acos); - - public static IArray Asin (this IArray< double > self) => self.Select(MathOps.Asin); - public static IArray Asin (this IArray< float > self) => self.Select(MathOps.Asin); - public static IArray Asin (this IArray< Vector2 > self) => self.Select(MathOps.Asin); - public static IArray Asin (this IArray< Vector3 > self) => self.Select(MathOps.Asin); - public static IArray Asin (this IArray< Vector4 > self) => self.Select(MathOps.Asin); - - public static IArray Atan (this IArray< double > self) => self.Select(MathOps.Atan); - public static IArray Atan (this IArray< float > self) => self.Select(MathOps.Atan); - public static IArray Atan (this IArray< Vector2 > self) => self.Select(MathOps.Atan); - public static IArray Atan (this IArray< Vector3 > self) => self.Select(MathOps.Atan); - public static IArray Atan (this IArray< Vector4 > self) => self.Select(MathOps.Atan); - - public static IArray Cos (this IArray< double > self) => self.Select(MathOps.Cos); - public static IArray Cos (this IArray< float > self) => self.Select(MathOps.Cos); - public static IArray Cos (this IArray< Vector2 > self) => self.Select(MathOps.Cos); - public static IArray Cos (this IArray< Vector3 > self) => self.Select(MathOps.Cos); - public static IArray Cos (this IArray< Vector4 > self) => self.Select(MathOps.Cos); - - public static IArray Cosh (this IArray< double > self) => self.Select(MathOps.Cosh); - public static IArray Cosh (this IArray< float > self) => self.Select(MathOps.Cosh); - public static IArray Cosh (this IArray< Vector2 > self) => self.Select(MathOps.Cosh); - public static IArray Cosh (this IArray< Vector3 > self) => self.Select(MathOps.Cosh); - public static IArray Cosh (this IArray< Vector4 > self) => self.Select(MathOps.Cosh); - - public static IArray Exp (this IArray< double > self) => self.Select(MathOps.Exp); - public static IArray Exp (this IArray< float > self) => self.Select(MathOps.Exp); - public static IArray Exp (this IArray< Vector2 > self) => self.Select(MathOps.Exp); - public static IArray Exp (this IArray< Vector3 > self) => self.Select(MathOps.Exp); - public static IArray Exp (this IArray< Vector4 > self) => self.Select(MathOps.Exp); - - public static IArray Log (this IArray< double > self) => self.Select(MathOps.Log); - public static IArray Log (this IArray< float > self) => self.Select(MathOps.Log); - public static IArray Log (this IArray< Vector2 > self) => self.Select(MathOps.Log); - public static IArray Log (this IArray< Vector3 > self) => self.Select(MathOps.Log); - public static IArray Log (this IArray< Vector4 > self) => self.Select(MathOps.Log); - - public static IArray Log10 (this IArray< double > self) => self.Select(MathOps.Log10); - public static IArray Log10 (this IArray< float > self) => self.Select(MathOps.Log10); - public static IArray Log10 (this IArray< Vector2 > self) => self.Select(MathOps.Log10); - public static IArray Log10 (this IArray< Vector3 > self) => self.Select(MathOps.Log10); - public static IArray Log10 (this IArray< Vector4 > self) => self.Select(MathOps.Log10); - - public static IArray Sin (this IArray< double > self) => self.Select(MathOps.Sin); - public static IArray Sin (this IArray< float > self) => self.Select(MathOps.Sin); - public static IArray Sin (this IArray< Vector2 > self) => self.Select(MathOps.Sin); - public static IArray Sin (this IArray< Vector3 > self) => self.Select(MathOps.Sin); - public static IArray Sin (this IArray< Vector4 > self) => self.Select(MathOps.Sin); - - public static IArray Sinh (this IArray< double > self) => self.Select(MathOps.Sinh); - public static IArray Sinh (this IArray< float > self) => self.Select(MathOps.Sinh); - public static IArray Sinh (this IArray< Vector2 > self) => self.Select(MathOps.Sinh); - public static IArray Sinh (this IArray< Vector3 > self) => self.Select(MathOps.Sinh); - public static IArray Sinh (this IArray< Vector4 > self) => self.Select(MathOps.Sinh); - - public static IArray Sqrt (this IArray< double > self) => self.Select(MathOps.Sqrt); - public static IArray Sqrt (this IArray< float > self) => self.Select(MathOps.Sqrt); - public static IArray Sqrt (this IArray< Vector2 > self) => self.Select(MathOps.Sqrt); - public static IArray Sqrt (this IArray< Vector3 > self) => self.Select(MathOps.Sqrt); - public static IArray Sqrt (this IArray< Vector4 > self) => self.Select(MathOps.Sqrt); - - public static IArray Tan (this IArray< double > self) => self.Select(MathOps.Tan); - public static IArray Tan (this IArray< float > self) => self.Select(MathOps.Tan); - public static IArray Tan (this IArray< Vector2 > self) => self.Select(MathOps.Tan); - public static IArray Tan (this IArray< Vector3 > self) => self.Select(MathOps.Tan); - public static IArray Tan (this IArray< Vector4 > self) => self.Select(MathOps.Tan); - - public static IArray Tanh (this IArray< double > self) => self.Select(MathOps.Tanh); - public static IArray Tanh (this IArray< float > self) => self.Select(MathOps.Tanh); - public static IArray Tanh (this IArray< Vector2 > self) => self.Select(MathOps.Tanh); - public static IArray Tanh (this IArray< Vector3 > self) => self.Select(MathOps.Tanh); - public static IArray Tanh (this IArray< Vector4 > self) => self.Select(MathOps.Tanh); - - public static IArray Sqr (this IArray< double > self) => self.Select(MathOps.Sqr); - public static IArray Sqr (this IArray< float > self) => self.Select(MathOps.Sqr); - public static IArray Sqr (this IArray< Vector2 > self) => self.Select(MathOps.Sqr); - public static IArray Sqr (this IArray< Vector3 > self) => self.Select(MathOps.Sqr); - public static IArray Sqr (this IArray< Vector4 > self) => self.Select(MathOps.Sqr); - - public static IArray Inverse (this IArray< double > self) => self.Select(MathOps.Inverse); - public static IArray Inverse (this IArray< float > self) => self.Select(MathOps.Inverse); - public static IArray Inverse (this IArray< Vector2 > self) => self.Select(MathOps.Inverse); - public static IArray Inverse (this IArray< Vector3 > self) => self.Select(MathOps.Inverse); - public static IArray Inverse (this IArray< Vector4 > self) => self.Select(MathOps.Inverse); - - public static IArray Ceiling (this IArray< double > self) => self.Select(MathOps.Ceiling); - public static IArray Ceiling (this IArray< float > self) => self.Select(MathOps.Ceiling); - public static IArray Ceiling (this IArray< Vector2 > self) => self.Select(MathOps.Ceiling); - public static IArray Ceiling (this IArray< Vector3 > self) => self.Select(MathOps.Ceiling); - public static IArray Ceiling (this IArray< Vector4 > self) => self.Select(MathOps.Ceiling); - - public static IArray Floor (this IArray< double > self) => self.Select(MathOps.Floor); - public static IArray Floor (this IArray< float > self) => self.Select(MathOps.Floor); - public static IArray Floor (this IArray< Vector2 > self) => self.Select(MathOps.Floor); - public static IArray Floor (this IArray< Vector3 > self) => self.Select(MathOps.Floor); - public static IArray Floor (this IArray< Vector4 > self) => self.Select(MathOps.Floor); - - public static IArray Round (this IArray< double > self) => self.Select(MathOps.Round); - public static IArray Round (this IArray< float > self) => self.Select(MathOps.Round); - public static IArray Round (this IArray< Vector2 > self) => self.Select(MathOps.Round); - public static IArray Round (this IArray< Vector3 > self) => self.Select(MathOps.Round); - public static IArray Round (this IArray< Vector4 > self) => self.Select(MathOps.Round); - - public static IArray Truncate (this IArray< double > self) => self.Select(MathOps.Truncate); - public static IArray Truncate (this IArray< float > self) => self.Select(MathOps.Truncate); - public static IArray Truncate (this IArray< Vector2 > self) => self.Select(MathOps.Truncate); - public static IArray Truncate (this IArray< Vector3 > self) => self.Select(MathOps.Truncate); - public static IArray Truncate (this IArray< Vector4 > self) => self.Select(MathOps.Truncate); - // TODO: do this over all over the numerical types - public static long Sum(this IArray self) => self.Aggregate(0L, (x, y) => x + y); - public static long Sum(this IArray self) => self.Aggregate(0L, (x, y) => x + y); - public static double Sum(this IArray self) => self.Aggregate(0.0, (x, y) => x + y); - public static double Sum(this IArray self) => self.Aggregate(0.0, (x, y) => x + y); - public static Vector2 Sum(this IArray self) => self.Aggregate(Vector2.Zero, (x, y) => x + y); - public static Vector3 Sum(this IArray self) => self.Aggregate(Vector3.Zero, (x, y) => x + y); - public static Vector4 Sum(this IArray self) => self.Aggregate(Vector4.Zero, (x, y) => x + y); - - public static double Average(this IArray self) => self.Sum() / self.Count; - public static double Average(this IArray self) => self.Sum() / self.Count; - public static double Average(this IArray self) => self.Sum() / self.Count; - public static double Average(this IArray self) => self.Sum() / self.Count; - public static Vector2 Average(this IArray self) => self.Sum() / self.Count; - public static Vector3 Average(this IArray self) => self.Sum() / self.Count; - public static Vector4 Average(this IArray self) => self.Sum() / self.Count; - - public static double Variance(this IArray self) { var mean = self.Average(); return self.Select(x => MathOps.Sqr(x - mean)).Average(); } - public static double Variance(this IArray self) { var mean = self.Average(); return self.Select(x => MathOps.Sqr(x - mean)).Average(); } - public static double Variance(this IArray self) { var mean = self.Average(); return self.Select(x => MathOps.Sqr(x - mean)).Average(); } - public static double Variance(this IArray self) { var mean = self.Average(); return self.Select(x => MathOps.Sqr(x - mean)).Average(); } - public static Vector2 Variance(this IArray self) { var mean = self.Average(); return self.Select(x => MathOps.Sqr(x - mean)).Average(); } - public static Vector3 Variance(this IArray self) { var mean = self.Average(); return self.Select(x => MathOps.Sqr(x - mean)).Average(); } - public static Vector4 Variance(this IArray self) { var mean = self.Average(); return self.Select(x => MathOps.Sqr(x - mean)).Average(); } - - public static double StdDev(this IArray self) => self.Variance().Sqrt(); - public static double StdDev(this IArray self) => self.Variance().Sqrt(); - public static double StdDev(this IArray self) => self.Variance().Sqrt(); - public static double StdDev(this IArray self) => self.Variance().Sqrt(); - public static Vector2 StdDev(this IArray self) => self.Variance().Sqrt(); - public static Vector3 StdDev(this IArray self) => self.Variance().Sqrt(); - public static Vector4 StdDev(this IArray self) => self.Variance().Sqrt(); - - public static IArray PartialSums(this IArray self) => self.PostAccumulate((x, y) => x + y); - public static IArray PartialSums(this IArray self) => self.PostAccumulate((x, y) => x + y); - public static IArray PartialSums(this IArray self) => self.PostAccumulate((x, y) => x + y); - public static IArray PartialSums(this IArray self) => self.PostAccumulate((x, y) => x + y); - public static IArray PartialSums(this IArray self) => self.PostAccumulate((x, y) => x + y); - public static IArray PartialSums(this IArray self) => self.PostAccumulate((x, y) => x + y); - public static IArray PartialSums(this IArray self) => self.PostAccumulate((x, y) => x + y); - - } -} diff --git a/src/cs/vim/Vim.Format.Core/Geometry/ArrayOps.tt b/src/cs/vim/Vim.Format.Core/Geometry/ArrayOps.tt deleted file mode 100644 index 2858a417..00000000 --- a/src/cs/vim/Vim.Format.Core/Geometry/ArrayOps.tt +++ /dev/null @@ -1,96 +0,0 @@ -<#@ template language="C#" #> -<#@ output extension=".cs" #> -<#@ assembly name="System.Core" #> -<#@ import namespace="System" #> -<#@ import namespace="System.IO" #> -<#@ import namespace="System.Diagnostics" #> -<#@ import namespace="System.Linq" #> - -// AUTOGENERATED FILE: DO NOT EDIT -// This file is generated from ArrayOps.tt - -<# -var nonVectorTypes = new[] { "int", "long", "float", "double" }; -var vectorTypes = new[] { "Vector2", "Vector3", "Vector4" }; -var types = nonVectorTypes.Concat(vectorTypes); -var intTypes = new[] { "int", "long" }; -var araBinaryOps = new[] { "Add", "Sub", "Mul", "Div" }; -var araCompOps = new[] { "Gt", "Lt", "GtEq", "LtEq", "Eq", "NEq" }; -var sysUnaryOps = new[] { "Abs", "Acos", "Asin", "Atan", "Cos", "Cosh", "Exp", "Log", "Log10", "Sin", "Sinh", "Sqrt", "Tan", "Tanh" }; -var araUnaryOps = new[] { "Sqr", "Inverse", "Ceiling", "Floor", "Round", "Truncate" }; -var allUnaryOps = sysUnaryOps.Concat(araUnaryOps); -#> - -using Vim.LinqArray; -using Vim.Math3d; - -namespace Vim.Format.Geometry -{ - public static class ArrayOps - { - -<# -foreach (var t in types) { -foreach (var op in new[] { "Add", "Multiply", "Subtract", "Divide" }) -{ -#> - public static IArray< <#= t #> > <#= op #>(this IArray< <#= t #> > self, IArray< <#= t #> > other) => self.Zip(other, MathOps.<#= op #>); - public static IArray< <#= t #> > <#= op #>(this IArray< <#= t #> > self, <#= t #> scalar) => self.Select(x => MathOps.<#= op #>(x, scalar)); - public static IArray< <#= t #> > <#= op #>(this <#= t #> self, IArray< <#= t #> > vector) => vector.Select(x => MathOps.<#= op #>(self, x)); -<# -} -} -foreach (var op in allUnaryOps) { -#> - - public static IArray <#= op #> (this IArray< double > self) => self.Select(MathOps.<#= op #>); - public static IArray <#= op #> (this IArray< float > self) => self.Select(MathOps.<#= op #>); - public static IArray <#= op #> (this IArray< Vector2 > self) => self.Select(MathOps.<#= op #>); - public static IArray <#= op #> (this IArray< Vector3 > self) => self.Select(MathOps.<#= op #>); - public static IArray <#= op #> (this IArray< Vector4 > self) => self.Select(MathOps.<#= op #>); -<# -} -#> - // TODO: do this over all over the numerical types - public static long Sum(this IArray self) => self.Aggregate(0L, (x, y) => x + y); - public static long Sum(this IArray self) => self.Aggregate(0L, (x, y) => x + y); - public static double Sum(this IArray self) => self.Aggregate(0.0, (x, y) => x + y); - public static double Sum(this IArray self) => self.Aggregate(0.0, (x, y) => x + y); - public static Vector2 Sum(this IArray self) => self.Aggregate(Vector2.Zero, (x, y) => x + y); - public static Vector3 Sum(this IArray self) => self.Aggregate(Vector3.Zero, (x, y) => x + y); - public static Vector4 Sum(this IArray self) => self.Aggregate(Vector4.Zero, (x, y) => x + y); - - public static double Average(this IArray self) => self.Sum() / self.Count; - public static double Average(this IArray self) => self.Sum() / self.Count; - public static double Average(this IArray self) => self.Sum() / self.Count; - public static double Average(this IArray self) => self.Sum() / self.Count; - public static Vector2 Average(this IArray self) => self.Sum() / self.Count; - public static Vector3 Average(this IArray self) => self.Sum() / self.Count; - public static Vector4 Average(this IArray self) => self.Sum() / self.Count; - - public static double Variance(this IArray self) { var mean = self.Average(); return self.Select(x => MathOps.Sqr(x - mean)).Average(); } - public static double Variance(this IArray self) { var mean = self.Average(); return self.Select(x => MathOps.Sqr(x - mean)).Average(); } - public static double Variance(this IArray self) { var mean = self.Average(); return self.Select(x => MathOps.Sqr(x - mean)).Average(); } - public static double Variance(this IArray self) { var mean = self.Average(); return self.Select(x => MathOps.Sqr(x - mean)).Average(); } - public static Vector2 Variance(this IArray self) { var mean = self.Average(); return self.Select(x => MathOps.Sqr(x - mean)).Average(); } - public static Vector3 Variance(this IArray self) { var mean = self.Average(); return self.Select(x => MathOps.Sqr(x - mean)).Average(); } - public static Vector4 Variance(this IArray self) { var mean = self.Average(); return self.Select(x => MathOps.Sqr(x - mean)).Average(); } - - public static double StdDev(this IArray self) => self.Variance().Sqrt(); - public static double StdDev(this IArray self) => self.Variance().Sqrt(); - public static double StdDev(this IArray self) => self.Variance().Sqrt(); - public static double StdDev(this IArray self) => self.Variance().Sqrt(); - public static Vector2 StdDev(this IArray self) => self.Variance().Sqrt(); - public static Vector3 StdDev(this IArray self) => self.Variance().Sqrt(); - public static Vector4 StdDev(this IArray self) => self.Variance().Sqrt(); - - public static IArray PartialSums(this IArray self) => self.PostAccumulate((x, y) => x + y); - public static IArray PartialSums(this IArray self) => self.PostAccumulate((x, y) => x + y); - public static IArray PartialSums(this IArray self) => self.PostAccumulate((x, y) => x + y); - public static IArray PartialSums(this IArray self) => self.PostAccumulate((x, y) => x + y); - public static IArray PartialSums(this IArray self) => self.PostAccumulate((x, y) => x + y); - public static IArray PartialSums(this IArray self) => self.PostAccumulate((x, y) => x + y); - public static IArray PartialSums(this IArray self) => self.PostAccumulate((x, y) => x + y); - - } -} 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 00b498be..f2908353 100644 --- a/src/cs/vim/Vim.Format.Core/Vim.Format.Core.csproj +++ b/src/cs/vim/Vim.Format.Core/Vim.Format.Core.csproj @@ -23,21 +23,6 @@ - - - - TextTemplatingFileGenerator - ArrayOps.cs - - - - - - True - True - ArrayOps.tt - - True From 6422ca555270117e8c9c649bf27f7be7f3d7bc2a Mon Sep 17 00:00:00 2001 From: simon Date: Tue, 16 Apr 2024 14:37:25 -0400 Subject: [PATCH 186/204] removed array ops renamed linqextensions ->collectionextensions --- ...qExtensions.cs => CollectionExtensions.cs} | 43 +-- .../vim/Vim.Format.Core/Geometry/ArrayOps.cs | 259 ------------------ .../vim/Vim.Format.Core/Geometry/ArrayOps.tt | 96 ------- .../SerializableDocumentTests.cs | 1 + 4 files changed, 3 insertions(+), 396 deletions(-) rename src/cs/util/Vim.Util/{LinqExtensions.cs => CollectionExtensions.cs} (85%) delete mode 100644 src/cs/vim/Vim.Format.Core/Geometry/ArrayOps.cs delete mode 100644 src/cs/vim/Vim.Format.Core/Geometry/ArrayOps.tt diff --git a/src/cs/util/Vim.Util/LinqExtensions.cs b/src/cs/util/Vim.Util/CollectionExtensions.cs similarity index 85% rename from src/cs/util/Vim.Util/LinqExtensions.cs rename to src/cs/util/Vim.Util/CollectionExtensions.cs index 775fc40e..cadcfa54 100644 --- a/src/cs/util/Vim.Util/LinqExtensions.cs +++ b/src/cs/util/Vim.Util/CollectionExtensions.cs @@ -2,51 +2,12 @@ using System.Collections; using System.Collections.Generic; using System.Linq; -using System.Text; namespace Vim.Util { - public static class LinqExtensions + public static class CollectionExtensions { - /// - /// Returns the index of the first element matching the given predicate. - /// - public static int IndexOf(this IList self, Func predicate) - { - for (var i = 0; i < self.Count; ++i) - { - if (predicate(self[i])) - return i; - } - return -1; - } - - /// - /// Returns the index of the first element matching the given item. - /// - public static int IndexOf(this IList self, T value) where T : IEquatable - { - for (var i = 0; i < self.Count; ++i) - { - if (self[i].Equals(value)) - return i; - } - return -1; - } - - /// - /// [a, b, c ..] => [0, a, a+b, a+b+c ...] - /// - public static int[] OffsetsFromCounts(this IList self) - { - var result = new int[self.Count]; - for (var i = 1; i < self.Count; ++i) - { - result[i] = result[i - 1] + self[i-1]; - } - return result; - } - + /// /// Returns an IEnumerable containing only indices of the array for which the function satisfies a specific predicate. /// diff --git a/src/cs/vim/Vim.Format.Core/Geometry/ArrayOps.cs b/src/cs/vim/Vim.Format.Core/Geometry/ArrayOps.cs deleted file mode 100644 index d77a7f5a..00000000 --- a/src/cs/vim/Vim.Format.Core/Geometry/ArrayOps.cs +++ /dev/null @@ -1,259 +0,0 @@ - -// AUTOGENERATED FILE: DO NOT EDIT -// This file is generated from ArrayOps.tt - - -using Vim.LinqArray; -using Vim.Math3d; - -namespace Vim.Format.Geometry -{ - public static class ArrayOps - { - public static IArray< int > Add(this IArray< int > self, IArray< int > other) => self.Zip(other, MathOps.Add); - public static IArray< int > Add(this IArray< int > self, int scalar) => self.Select(x => MathOps.Add(x, scalar)); - public static IArray< int > Add(this int self, IArray< int > vector) => vector.Select(x => MathOps.Add(self, x)); - public static IArray< int > Multiply(this IArray< int > self, IArray< int > other) => self.Zip(other, MathOps.Multiply); - public static IArray< int > Multiply(this IArray< int > self, int scalar) => self.Select(x => MathOps.Multiply(x, scalar)); - public static IArray< int > Multiply(this int self, IArray< int > vector) => vector.Select(x => MathOps.Multiply(self, x)); - public static IArray< int > Subtract(this IArray< int > self, IArray< int > other) => self.Zip(other, MathOps.Subtract); - public static IArray< int > Subtract(this IArray< int > self, int scalar) => self.Select(x => MathOps.Subtract(x, scalar)); - public static IArray< int > Subtract(this int self, IArray< int > vector) => vector.Select(x => MathOps.Subtract(self, x)); - public static IArray< int > Divide(this IArray< int > self, IArray< int > other) => self.Zip(other, MathOps.Divide); - public static IArray< int > Divide(this IArray< int > self, int scalar) => self.Select(x => MathOps.Divide(x, scalar)); - public static IArray< int > Divide(this int self, IArray< int > vector) => vector.Select(x => MathOps.Divide(self, x)); - public static IArray< long > Add(this IArray< long > self, IArray< long > other) => self.Zip(other, MathOps.Add); - public static IArray< long > Add(this IArray< long > self, long scalar) => self.Select(x => MathOps.Add(x, scalar)); - public static IArray< long > Add(this long self, IArray< long > vector) => vector.Select(x => MathOps.Add(self, x)); - public static IArray< long > Multiply(this IArray< long > self, IArray< long > other) => self.Zip(other, MathOps.Multiply); - public static IArray< long > Multiply(this IArray< long > self, long scalar) => self.Select(x => MathOps.Multiply(x, scalar)); - public static IArray< long > Multiply(this long self, IArray< long > vector) => vector.Select(x => MathOps.Multiply(self, x)); - public static IArray< long > Subtract(this IArray< long > self, IArray< long > other) => self.Zip(other, MathOps.Subtract); - public static IArray< long > Subtract(this IArray< long > self, long scalar) => self.Select(x => MathOps.Subtract(x, scalar)); - public static IArray< long > Subtract(this long self, IArray< long > vector) => vector.Select(x => MathOps.Subtract(self, x)); - public static IArray< long > Divide(this IArray< long > self, IArray< long > other) => self.Zip(other, MathOps.Divide); - public static IArray< long > Divide(this IArray< long > self, long scalar) => self.Select(x => MathOps.Divide(x, scalar)); - public static IArray< long > Divide(this long self, IArray< long > vector) => vector.Select(x => MathOps.Divide(self, x)); - public static IArray< float > Add(this IArray< float > self, IArray< float > other) => self.Zip(other, MathOps.Add); - public static IArray< float > Add(this IArray< float > self, float scalar) => self.Select(x => MathOps.Add(x, scalar)); - public static IArray< float > Add(this float self, IArray< float > vector) => vector.Select(x => MathOps.Add(self, x)); - public static IArray< float > Multiply(this IArray< float > self, IArray< float > other) => self.Zip(other, MathOps.Multiply); - public static IArray< float > Multiply(this IArray< float > self, float scalar) => self.Select(x => MathOps.Multiply(x, scalar)); - public static IArray< float > Multiply(this float self, IArray< float > vector) => vector.Select(x => MathOps.Multiply(self, x)); - public static IArray< float > Subtract(this IArray< float > self, IArray< float > other) => self.Zip(other, MathOps.Subtract); - public static IArray< float > Subtract(this IArray< float > self, float scalar) => self.Select(x => MathOps.Subtract(x, scalar)); - public static IArray< float > Subtract(this float self, IArray< float > vector) => vector.Select(x => MathOps.Subtract(self, x)); - public static IArray< float > Divide(this IArray< float > self, IArray< float > other) => self.Zip(other, MathOps.Divide); - public static IArray< float > Divide(this IArray< float > self, float scalar) => self.Select(x => MathOps.Divide(x, scalar)); - public static IArray< float > Divide(this float self, IArray< float > vector) => vector.Select(x => MathOps.Divide(self, x)); - public static IArray< double > Add(this IArray< double > self, IArray< double > other) => self.Zip(other, MathOps.Add); - public static IArray< double > Add(this IArray< double > self, double scalar) => self.Select(x => MathOps.Add(x, scalar)); - public static IArray< double > Add(this double self, IArray< double > vector) => vector.Select(x => MathOps.Add(self, x)); - public static IArray< double > Multiply(this IArray< double > self, IArray< double > other) => self.Zip(other, MathOps.Multiply); - public static IArray< double > Multiply(this IArray< double > self, double scalar) => self.Select(x => MathOps.Multiply(x, scalar)); - public static IArray< double > Multiply(this double self, IArray< double > vector) => vector.Select(x => MathOps.Multiply(self, x)); - public static IArray< double > Subtract(this IArray< double > self, IArray< double > other) => self.Zip(other, MathOps.Subtract); - public static IArray< double > Subtract(this IArray< double > self, double scalar) => self.Select(x => MathOps.Subtract(x, scalar)); - public static IArray< double > Subtract(this double self, IArray< double > vector) => vector.Select(x => MathOps.Subtract(self, x)); - public static IArray< double > Divide(this IArray< double > self, IArray< double > other) => self.Zip(other, MathOps.Divide); - public static IArray< double > Divide(this IArray< double > self, double scalar) => self.Select(x => MathOps.Divide(x, scalar)); - public static IArray< double > Divide(this double self, IArray< double > vector) => vector.Select(x => MathOps.Divide(self, x)); - public static IArray< Vector2 > Add(this IArray< Vector2 > self, IArray< Vector2 > other) => self.Zip(other, MathOps.Add); - public static IArray< Vector2 > Add(this IArray< Vector2 > self, Vector2 scalar) => self.Select(x => MathOps.Add(x, scalar)); - public static IArray< Vector2 > Add(this Vector2 self, IArray< Vector2 > vector) => vector.Select(x => MathOps.Add(self, x)); - public static IArray< Vector2 > Multiply(this IArray< Vector2 > self, IArray< Vector2 > other) => self.Zip(other, MathOps.Multiply); - public static IArray< Vector2 > Multiply(this IArray< Vector2 > self, Vector2 scalar) => self.Select(x => MathOps.Multiply(x, scalar)); - public static IArray< Vector2 > Multiply(this Vector2 self, IArray< Vector2 > vector) => vector.Select(x => MathOps.Multiply(self, x)); - public static IArray< Vector2 > Subtract(this IArray< Vector2 > self, IArray< Vector2 > other) => self.Zip(other, MathOps.Subtract); - public static IArray< Vector2 > Subtract(this IArray< Vector2 > self, Vector2 scalar) => self.Select(x => MathOps.Subtract(x, scalar)); - public static IArray< Vector2 > Subtract(this Vector2 self, IArray< Vector2 > vector) => vector.Select(x => MathOps.Subtract(self, x)); - public static IArray< Vector2 > Divide(this IArray< Vector2 > self, IArray< Vector2 > other) => self.Zip(other, MathOps.Divide); - public static IArray< Vector2 > Divide(this IArray< Vector2 > self, Vector2 scalar) => self.Select(x => MathOps.Divide(x, scalar)); - public static IArray< Vector2 > Divide(this Vector2 self, IArray< Vector2 > vector) => vector.Select(x => MathOps.Divide(self, x)); - public static IArray< Vector3 > Add(this IArray< Vector3 > self, IArray< Vector3 > other) => self.Zip(other, MathOps.Add); - public static IArray< Vector3 > Add(this IArray< Vector3 > self, Vector3 scalar) => self.Select(x => MathOps.Add(x, scalar)); - public static IArray< Vector3 > Add(this Vector3 self, IArray< Vector3 > vector) => vector.Select(x => MathOps.Add(self, x)); - public static IArray< Vector3 > Multiply(this IArray< Vector3 > self, IArray< Vector3 > other) => self.Zip(other, MathOps.Multiply); - public static IArray< Vector3 > Multiply(this IArray< Vector3 > self, Vector3 scalar) => self.Select(x => MathOps.Multiply(x, scalar)); - public static IArray< Vector3 > Multiply(this Vector3 self, IArray< Vector3 > vector) => vector.Select(x => MathOps.Multiply(self, x)); - public static IArray< Vector3 > Subtract(this IArray< Vector3 > self, IArray< Vector3 > other) => self.Zip(other, MathOps.Subtract); - public static IArray< Vector3 > Subtract(this IArray< Vector3 > self, Vector3 scalar) => self.Select(x => MathOps.Subtract(x, scalar)); - public static IArray< Vector3 > Subtract(this Vector3 self, IArray< Vector3 > vector) => vector.Select(x => MathOps.Subtract(self, x)); - public static IArray< Vector3 > Divide(this IArray< Vector3 > self, IArray< Vector3 > other) => self.Zip(other, MathOps.Divide); - public static IArray< Vector3 > Divide(this IArray< Vector3 > self, Vector3 scalar) => self.Select(x => MathOps.Divide(x, scalar)); - public static IArray< Vector3 > Divide(this Vector3 self, IArray< Vector3 > vector) => vector.Select(x => MathOps.Divide(self, x)); - public static IArray< Vector4 > Add(this IArray< Vector4 > self, IArray< Vector4 > other) => self.Zip(other, MathOps.Add); - public static IArray< Vector4 > Add(this IArray< Vector4 > self, Vector4 scalar) => self.Select(x => MathOps.Add(x, scalar)); - public static IArray< Vector4 > Add(this Vector4 self, IArray< Vector4 > vector) => vector.Select(x => MathOps.Add(self, x)); - public static IArray< Vector4 > Multiply(this IArray< Vector4 > self, IArray< Vector4 > other) => self.Zip(other, MathOps.Multiply); - public static IArray< Vector4 > Multiply(this IArray< Vector4 > self, Vector4 scalar) => self.Select(x => MathOps.Multiply(x, scalar)); - public static IArray< Vector4 > Multiply(this Vector4 self, IArray< Vector4 > vector) => vector.Select(x => MathOps.Multiply(self, x)); - public static IArray< Vector4 > Subtract(this IArray< Vector4 > self, IArray< Vector4 > other) => self.Zip(other, MathOps.Subtract); - public static IArray< Vector4 > Subtract(this IArray< Vector4 > self, Vector4 scalar) => self.Select(x => MathOps.Subtract(x, scalar)); - public static IArray< Vector4 > Subtract(this Vector4 self, IArray< Vector4 > vector) => vector.Select(x => MathOps.Subtract(self, x)); - public static IArray< Vector4 > Divide(this IArray< Vector4 > self, IArray< Vector4 > other) => self.Zip(other, MathOps.Divide); - public static IArray< Vector4 > Divide(this IArray< Vector4 > self, Vector4 scalar) => self.Select(x => MathOps.Divide(x, scalar)); - public static IArray< Vector4 > Divide(this Vector4 self, IArray< Vector4 > vector) => vector.Select(x => MathOps.Divide(self, x)); - - public static IArray Abs (this IArray< double > self) => self.Select(MathOps.Abs); - public static IArray Abs (this IArray< float > self) => self.Select(MathOps.Abs); - public static IArray Abs (this IArray< Vector2 > self) => self.Select(MathOps.Abs); - public static IArray Abs (this IArray< Vector3 > self) => self.Select(MathOps.Abs); - public static IArray Abs (this IArray< Vector4 > self) => self.Select(MathOps.Abs); - - public static IArray Acos (this IArray< double > self) => self.Select(MathOps.Acos); - public static IArray Acos (this IArray< float > self) => self.Select(MathOps.Acos); - public static IArray Acos (this IArray< Vector2 > self) => self.Select(MathOps.Acos); - public static IArray Acos (this IArray< Vector3 > self) => self.Select(MathOps.Acos); - public static IArray Acos (this IArray< Vector4 > self) => self.Select(MathOps.Acos); - - public static IArray Asin (this IArray< double > self) => self.Select(MathOps.Asin); - public static IArray Asin (this IArray< float > self) => self.Select(MathOps.Asin); - public static IArray Asin (this IArray< Vector2 > self) => self.Select(MathOps.Asin); - public static IArray Asin (this IArray< Vector3 > self) => self.Select(MathOps.Asin); - public static IArray Asin (this IArray< Vector4 > self) => self.Select(MathOps.Asin); - - public static IArray Atan (this IArray< double > self) => self.Select(MathOps.Atan); - public static IArray Atan (this IArray< float > self) => self.Select(MathOps.Atan); - public static IArray Atan (this IArray< Vector2 > self) => self.Select(MathOps.Atan); - public static IArray Atan (this IArray< Vector3 > self) => self.Select(MathOps.Atan); - public static IArray Atan (this IArray< Vector4 > self) => self.Select(MathOps.Atan); - - public static IArray Cos (this IArray< double > self) => self.Select(MathOps.Cos); - public static IArray Cos (this IArray< float > self) => self.Select(MathOps.Cos); - public static IArray Cos (this IArray< Vector2 > self) => self.Select(MathOps.Cos); - public static IArray Cos (this IArray< Vector3 > self) => self.Select(MathOps.Cos); - public static IArray Cos (this IArray< Vector4 > self) => self.Select(MathOps.Cos); - - public static IArray Cosh (this IArray< double > self) => self.Select(MathOps.Cosh); - public static IArray Cosh (this IArray< float > self) => self.Select(MathOps.Cosh); - public static IArray Cosh (this IArray< Vector2 > self) => self.Select(MathOps.Cosh); - public static IArray Cosh (this IArray< Vector3 > self) => self.Select(MathOps.Cosh); - public static IArray Cosh (this IArray< Vector4 > self) => self.Select(MathOps.Cosh); - - public static IArray Exp (this IArray< double > self) => self.Select(MathOps.Exp); - public static IArray Exp (this IArray< float > self) => self.Select(MathOps.Exp); - public static IArray Exp (this IArray< Vector2 > self) => self.Select(MathOps.Exp); - public static IArray Exp (this IArray< Vector3 > self) => self.Select(MathOps.Exp); - public static IArray Exp (this IArray< Vector4 > self) => self.Select(MathOps.Exp); - - public static IArray Log (this IArray< double > self) => self.Select(MathOps.Log); - public static IArray Log (this IArray< float > self) => self.Select(MathOps.Log); - public static IArray Log (this IArray< Vector2 > self) => self.Select(MathOps.Log); - public static IArray Log (this IArray< Vector3 > self) => self.Select(MathOps.Log); - public static IArray Log (this IArray< Vector4 > self) => self.Select(MathOps.Log); - - public static IArray Log10 (this IArray< double > self) => self.Select(MathOps.Log10); - public static IArray Log10 (this IArray< float > self) => self.Select(MathOps.Log10); - public static IArray Log10 (this IArray< Vector2 > self) => self.Select(MathOps.Log10); - public static IArray Log10 (this IArray< Vector3 > self) => self.Select(MathOps.Log10); - public static IArray Log10 (this IArray< Vector4 > self) => self.Select(MathOps.Log10); - - public static IArray Sin (this IArray< double > self) => self.Select(MathOps.Sin); - public static IArray Sin (this IArray< float > self) => self.Select(MathOps.Sin); - public static IArray Sin (this IArray< Vector2 > self) => self.Select(MathOps.Sin); - public static IArray Sin (this IArray< Vector3 > self) => self.Select(MathOps.Sin); - public static IArray Sin (this IArray< Vector4 > self) => self.Select(MathOps.Sin); - - public static IArray Sinh (this IArray< double > self) => self.Select(MathOps.Sinh); - public static IArray Sinh (this IArray< float > self) => self.Select(MathOps.Sinh); - public static IArray Sinh (this IArray< Vector2 > self) => self.Select(MathOps.Sinh); - public static IArray Sinh (this IArray< Vector3 > self) => self.Select(MathOps.Sinh); - public static IArray Sinh (this IArray< Vector4 > self) => self.Select(MathOps.Sinh); - - public static IArray Sqrt (this IArray< double > self) => self.Select(MathOps.Sqrt); - public static IArray Sqrt (this IArray< float > self) => self.Select(MathOps.Sqrt); - public static IArray Sqrt (this IArray< Vector2 > self) => self.Select(MathOps.Sqrt); - public static IArray Sqrt (this IArray< Vector3 > self) => self.Select(MathOps.Sqrt); - public static IArray Sqrt (this IArray< Vector4 > self) => self.Select(MathOps.Sqrt); - - public static IArray Tan (this IArray< double > self) => self.Select(MathOps.Tan); - public static IArray Tan (this IArray< float > self) => self.Select(MathOps.Tan); - public static IArray Tan (this IArray< Vector2 > self) => self.Select(MathOps.Tan); - public static IArray Tan (this IArray< Vector3 > self) => self.Select(MathOps.Tan); - public static IArray Tan (this IArray< Vector4 > self) => self.Select(MathOps.Tan); - - public static IArray Tanh (this IArray< double > self) => self.Select(MathOps.Tanh); - public static IArray Tanh (this IArray< float > self) => self.Select(MathOps.Tanh); - public static IArray Tanh (this IArray< Vector2 > self) => self.Select(MathOps.Tanh); - public static IArray Tanh (this IArray< Vector3 > self) => self.Select(MathOps.Tanh); - public static IArray Tanh (this IArray< Vector4 > self) => self.Select(MathOps.Tanh); - - public static IArray Sqr (this IArray< double > self) => self.Select(MathOps.Sqr); - public static IArray Sqr (this IArray< float > self) => self.Select(MathOps.Sqr); - public static IArray Sqr (this IArray< Vector2 > self) => self.Select(MathOps.Sqr); - public static IArray Sqr (this IArray< Vector3 > self) => self.Select(MathOps.Sqr); - public static IArray Sqr (this IArray< Vector4 > self) => self.Select(MathOps.Sqr); - - public static IArray Inverse (this IArray< double > self) => self.Select(MathOps.Inverse); - public static IArray Inverse (this IArray< float > self) => self.Select(MathOps.Inverse); - public static IArray Inverse (this IArray< Vector2 > self) => self.Select(MathOps.Inverse); - public static IArray Inverse (this IArray< Vector3 > self) => self.Select(MathOps.Inverse); - public static IArray Inverse (this IArray< Vector4 > self) => self.Select(MathOps.Inverse); - - public static IArray Ceiling (this IArray< double > self) => self.Select(MathOps.Ceiling); - public static IArray Ceiling (this IArray< float > self) => self.Select(MathOps.Ceiling); - public static IArray Ceiling (this IArray< Vector2 > self) => self.Select(MathOps.Ceiling); - public static IArray Ceiling (this IArray< Vector3 > self) => self.Select(MathOps.Ceiling); - public static IArray Ceiling (this IArray< Vector4 > self) => self.Select(MathOps.Ceiling); - - public static IArray Floor (this IArray< double > self) => self.Select(MathOps.Floor); - public static IArray Floor (this IArray< float > self) => self.Select(MathOps.Floor); - public static IArray Floor (this IArray< Vector2 > self) => self.Select(MathOps.Floor); - public static IArray Floor (this IArray< Vector3 > self) => self.Select(MathOps.Floor); - public static IArray Floor (this IArray< Vector4 > self) => self.Select(MathOps.Floor); - - public static IArray Round (this IArray< double > self) => self.Select(MathOps.Round); - public static IArray Round (this IArray< float > self) => self.Select(MathOps.Round); - public static IArray Round (this IArray< Vector2 > self) => self.Select(MathOps.Round); - public static IArray Round (this IArray< Vector3 > self) => self.Select(MathOps.Round); - public static IArray Round (this IArray< Vector4 > self) => self.Select(MathOps.Round); - - public static IArray Truncate (this IArray< double > self) => self.Select(MathOps.Truncate); - public static IArray Truncate (this IArray< float > self) => self.Select(MathOps.Truncate); - public static IArray Truncate (this IArray< Vector2 > self) => self.Select(MathOps.Truncate); - public static IArray Truncate (this IArray< Vector3 > self) => self.Select(MathOps.Truncate); - public static IArray Truncate (this IArray< Vector4 > self) => self.Select(MathOps.Truncate); - // TODO: do this over all over the numerical types - public static long Sum(this IArray self) => self.Aggregate(0L, (x, y) => x + y); - public static long Sum(this IArray self) => self.Aggregate(0L, (x, y) => x + y); - public static double Sum(this IArray self) => self.Aggregate(0.0, (x, y) => x + y); - public static double Sum(this IArray self) => self.Aggregate(0.0, (x, y) => x + y); - public static Vector2 Sum(this IArray self) => self.Aggregate(Vector2.Zero, (x, y) => x + y); - public static Vector3 Sum(this IArray self) => self.Aggregate(Vector3.Zero, (x, y) => x + y); - public static Vector4 Sum(this IArray self) => self.Aggregate(Vector4.Zero, (x, y) => x + y); - - public static double Average(this IArray self) => self.Sum() / self.Count; - public static double Average(this IArray self) => self.Sum() / self.Count; - public static double Average(this IArray self) => self.Sum() / self.Count; - public static double Average(this IArray self) => self.Sum() / self.Count; - public static Vector2 Average(this IArray self) => self.Sum() / self.Count; - public static Vector3 Average(this IArray self) => self.Sum() / self.Count; - public static Vector4 Average(this IArray self) => self.Sum() / self.Count; - - public static double Variance(this IArray self) { var mean = self.Average(); return self.Select(x => MathOps.Sqr(x - mean)).Average(); } - public static double Variance(this IArray self) { var mean = self.Average(); return self.Select(x => MathOps.Sqr(x - mean)).Average(); } - public static double Variance(this IArray self) { var mean = self.Average(); return self.Select(x => MathOps.Sqr(x - mean)).Average(); } - public static double Variance(this IArray self) { var mean = self.Average(); return self.Select(x => MathOps.Sqr(x - mean)).Average(); } - public static Vector2 Variance(this IArray self) { var mean = self.Average(); return self.Select(x => MathOps.Sqr(x - mean)).Average(); } - public static Vector3 Variance(this IArray self) { var mean = self.Average(); return self.Select(x => MathOps.Sqr(x - mean)).Average(); } - public static Vector4 Variance(this IArray self) { var mean = self.Average(); return self.Select(x => MathOps.Sqr(x - mean)).Average(); } - - public static double StdDev(this IArray self) => self.Variance().Sqrt(); - public static double StdDev(this IArray self) => self.Variance().Sqrt(); - public static double StdDev(this IArray self) => self.Variance().Sqrt(); - public static double StdDev(this IArray self) => self.Variance().Sqrt(); - public static Vector2 StdDev(this IArray self) => self.Variance().Sqrt(); - public static Vector3 StdDev(this IArray self) => self.Variance().Sqrt(); - public static Vector4 StdDev(this IArray self) => self.Variance().Sqrt(); - - public static IArray PartialSums(this IArray self) => self.PostAccumulate((x, y) => x + y); - public static IArray PartialSums(this IArray self) => self.PostAccumulate((x, y) => x + y); - public static IArray PartialSums(this IArray self) => self.PostAccumulate((x, y) => x + y); - public static IArray PartialSums(this IArray self) => self.PostAccumulate((x, y) => x + y); - public static IArray PartialSums(this IArray self) => self.PostAccumulate((x, y) => x + y); - public static IArray PartialSums(this IArray self) => self.PostAccumulate((x, y) => x + y); - public static IArray PartialSums(this IArray self) => self.PostAccumulate((x, y) => x + y); - - } -} diff --git a/src/cs/vim/Vim.Format.Core/Geometry/ArrayOps.tt b/src/cs/vim/Vim.Format.Core/Geometry/ArrayOps.tt deleted file mode 100644 index 2858a417..00000000 --- a/src/cs/vim/Vim.Format.Core/Geometry/ArrayOps.tt +++ /dev/null @@ -1,96 +0,0 @@ -<#@ template language="C#" #> -<#@ output extension=".cs" #> -<#@ assembly name="System.Core" #> -<#@ import namespace="System" #> -<#@ import namespace="System.IO" #> -<#@ import namespace="System.Diagnostics" #> -<#@ import namespace="System.Linq" #> - -// AUTOGENERATED FILE: DO NOT EDIT -// This file is generated from ArrayOps.tt - -<# -var nonVectorTypes = new[] { "int", "long", "float", "double" }; -var vectorTypes = new[] { "Vector2", "Vector3", "Vector4" }; -var types = nonVectorTypes.Concat(vectorTypes); -var intTypes = new[] { "int", "long" }; -var araBinaryOps = new[] { "Add", "Sub", "Mul", "Div" }; -var araCompOps = new[] { "Gt", "Lt", "GtEq", "LtEq", "Eq", "NEq" }; -var sysUnaryOps = new[] { "Abs", "Acos", "Asin", "Atan", "Cos", "Cosh", "Exp", "Log", "Log10", "Sin", "Sinh", "Sqrt", "Tan", "Tanh" }; -var araUnaryOps = new[] { "Sqr", "Inverse", "Ceiling", "Floor", "Round", "Truncate" }; -var allUnaryOps = sysUnaryOps.Concat(araUnaryOps); -#> - -using Vim.LinqArray; -using Vim.Math3d; - -namespace Vim.Format.Geometry -{ - public static class ArrayOps - { - -<# -foreach (var t in types) { -foreach (var op in new[] { "Add", "Multiply", "Subtract", "Divide" }) -{ -#> - public static IArray< <#= t #> > <#= op #>(this IArray< <#= t #> > self, IArray< <#= t #> > other) => self.Zip(other, MathOps.<#= op #>); - public static IArray< <#= t #> > <#= op #>(this IArray< <#= t #> > self, <#= t #> scalar) => self.Select(x => MathOps.<#= op #>(x, scalar)); - public static IArray< <#= t #> > <#= op #>(this <#= t #> self, IArray< <#= t #> > vector) => vector.Select(x => MathOps.<#= op #>(self, x)); -<# -} -} -foreach (var op in allUnaryOps) { -#> - - public static IArray <#= op #> (this IArray< double > self) => self.Select(MathOps.<#= op #>); - public static IArray <#= op #> (this IArray< float > self) => self.Select(MathOps.<#= op #>); - public static IArray <#= op #> (this IArray< Vector2 > self) => self.Select(MathOps.<#= op #>); - public static IArray <#= op #> (this IArray< Vector3 > self) => self.Select(MathOps.<#= op #>); - public static IArray <#= op #> (this IArray< Vector4 > self) => self.Select(MathOps.<#= op #>); -<# -} -#> - // TODO: do this over all over the numerical types - public static long Sum(this IArray self) => self.Aggregate(0L, (x, y) => x + y); - public static long Sum(this IArray self) => self.Aggregate(0L, (x, y) => x + y); - public static double Sum(this IArray self) => self.Aggregate(0.0, (x, y) => x + y); - public static double Sum(this IArray self) => self.Aggregate(0.0, (x, y) => x + y); - public static Vector2 Sum(this IArray self) => self.Aggregate(Vector2.Zero, (x, y) => x + y); - public static Vector3 Sum(this IArray self) => self.Aggregate(Vector3.Zero, (x, y) => x + y); - public static Vector4 Sum(this IArray self) => self.Aggregate(Vector4.Zero, (x, y) => x + y); - - public static double Average(this IArray self) => self.Sum() / self.Count; - public static double Average(this IArray self) => self.Sum() / self.Count; - public static double Average(this IArray self) => self.Sum() / self.Count; - public static double Average(this IArray self) => self.Sum() / self.Count; - public static Vector2 Average(this IArray self) => self.Sum() / self.Count; - public static Vector3 Average(this IArray self) => self.Sum() / self.Count; - public static Vector4 Average(this IArray self) => self.Sum() / self.Count; - - public static double Variance(this IArray self) { var mean = self.Average(); return self.Select(x => MathOps.Sqr(x - mean)).Average(); } - public static double Variance(this IArray self) { var mean = self.Average(); return self.Select(x => MathOps.Sqr(x - mean)).Average(); } - public static double Variance(this IArray self) { var mean = self.Average(); return self.Select(x => MathOps.Sqr(x - mean)).Average(); } - public static double Variance(this IArray self) { var mean = self.Average(); return self.Select(x => MathOps.Sqr(x - mean)).Average(); } - public static Vector2 Variance(this IArray self) { var mean = self.Average(); return self.Select(x => MathOps.Sqr(x - mean)).Average(); } - public static Vector3 Variance(this IArray self) { var mean = self.Average(); return self.Select(x => MathOps.Sqr(x - mean)).Average(); } - public static Vector4 Variance(this IArray self) { var mean = self.Average(); return self.Select(x => MathOps.Sqr(x - mean)).Average(); } - - public static double StdDev(this IArray self) => self.Variance().Sqrt(); - public static double StdDev(this IArray self) => self.Variance().Sqrt(); - public static double StdDev(this IArray self) => self.Variance().Sqrt(); - public static double StdDev(this IArray self) => self.Variance().Sqrt(); - public static Vector2 StdDev(this IArray self) => self.Variance().Sqrt(); - public static Vector3 StdDev(this IArray self) => self.Variance().Sqrt(); - public static Vector4 StdDev(this IArray self) => self.Variance().Sqrt(); - - public static IArray PartialSums(this IArray self) => self.PostAccumulate((x, y) => x + y); - public static IArray PartialSums(this IArray self) => self.PostAccumulate((x, y) => x + y); - public static IArray PartialSums(this IArray self) => self.PostAccumulate((x, y) => x + y); - public static IArray PartialSums(this IArray self) => self.PostAccumulate((x, y) => x + y); - public static IArray PartialSums(this IArray self) => self.PostAccumulate((x, y) => x + y); - public static IArray PartialSums(this IArray self) => self.PostAccumulate((x, y) => x + y); - public static IArray PartialSums(this IArray self) => self.PostAccumulate((x, y) => x + y); - - } -} diff --git a/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs b/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs index 409323e5..acf01b1b 100644 --- a/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs +++ b/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs @@ -5,6 +5,7 @@ using Vim.Format.SceneBuilder; using Vim.LinqArray; using Vim.Util.Tests; +using Vim.Util; namespace Vim.Format.Tests; From 181976bbc209f2824824627b298c3b55feeac5f5 Mon Sep 17 00:00:00 2001 From: simon Date: Tue, 16 Apr 2024 15:37:55 -0400 Subject: [PATCH 187/204] removing linq array --- src/cs/linqarray/Vim.LinqArray/LinqArray.cs | 6 ++---- src/cs/util/Vim.Util/CollectionExtensions.cs | 11 ++++++++++- .../Vim.LinqArray => util/Vim.Util}/ILookup.cs | 12 ++++++------ .../vim/Vim.Format.CodeGen/ObjectModelGenerator.cs | 1 - src/cs/vim/Vim.Format.Core/AssetInfo.cs | 1 - .../vim/Vim.Format.Core/ColumnExtensions.Buffer.cs | 3 +-- src/cs/vim/Vim.Format.Core/Document.cs | 7 +++---- .../Vim.Format.Core/DocumentBuilderExtensions.cs | 1 - src/cs/vim/Vim.Format.Core/DocumentExtensions.cs | 2 +- src/cs/vim/Vim.Format.Core/EntityTable.cs | 14 +++++++------- .../Vim.Format.Core/Geometry/MeshOptimization.cs | 1 - .../Geometry/PerimeterProjection.cs | 1 - src/cs/vim/Vim.Format.Core/Geometry/Primitives.cs | 3 +-- src/cs/vim/Vim.Format.Core/Geometry/Validation.cs | 1 - src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs | 2 -- src/cs/vim/Vim.Format.Core/Validation.cs | 2 -- src/cs/vim/Vim.Format.Core/VimSchema.cs | 1 - src/cs/vim/Vim.Format.Tests/FormatTests.cs | 13 +------------ .../vim/Vim.Format.Tests/Geometry/GeometryTests.cs | 1 - .../Vim.Format.Tests/SerializableDocumentTests.cs | 4 ---- src/cs/vim/Vim.Format.Vimx.Conversion/Chunking.cs | 1 - .../Vim.Format.Vimx.Conversion/VimxConverter.cs | 1 - src/cs/vim/Vim.Format/ObjectModel/ElementInfo.cs | 1 - .../ObjectModel/ObjectModelExtensions.cs | 3 +-- .../Vim.Format/ObjectModel/ObjectModelGenerated.cs | 1 - src/cs/vim/Vim.Format/ObjectModel/Validation.cs | 1 - src/cs/vim/Vim.Format/SceneBuilder/Validation.cs | 5 ++--- src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs | 1 - .../vim/Vim.Format/SceneBuilder/VimSceneHelpers.cs | 1 - src/cs/vim/Vim.Format/SceneBuilder/VimSceneNode.cs | 1 - 30 files changed, 35 insertions(+), 68 deletions(-) rename src/cs/{linqarray/Vim.LinqArray => util/Vim.Util}/ILookup.cs (90%) diff --git a/src/cs/linqarray/Vim.LinqArray/LinqArray.cs b/src/cs/linqarray/Vim.LinqArray/LinqArray.cs index cf646593..3e392e0e 100644 --- a/src/cs/linqarray/Vim.LinqArray/LinqArray.cs +++ b/src/cs/linqarray/Vim.LinqArray/LinqArray.cs @@ -943,14 +943,12 @@ public static IArray Cast(this IArray xs) where T : U public static bool Contains(this IArray xs, T value) => xs.Any(x => x.Equals(value)); - public static ILookup ToLookup(this IEnumerable input, Func keyFunc, Func valueFunc) - => input.ToDictionary(keyFunc, valueFunc).ToLookup(); + + public static ILookup ToLookup(this IArray input, Func keyFunc, Func valueFunc) => input.ToEnumerable().ToLookup(keyFunc, valueFunc); - public static ILookup ToLookup(this IEnumerable input, Func keyFunc) - => input.ToDictionary(keyFunc, x => x).ToLookup(); public static ILookup ToLookup(this IArray input, Func keyFunc) => input.ToEnumerable().ToLookup(keyFunc, x => x); diff --git a/src/cs/util/Vim.Util/CollectionExtensions.cs b/src/cs/util/Vim.Util/CollectionExtensions.cs index cadcfa54..9982620a 100644 --- a/src/cs/util/Vim.Util/CollectionExtensions.cs +++ b/src/cs/util/Vim.Util/CollectionExtensions.cs @@ -7,7 +7,16 @@ namespace Vim.Util { public static class CollectionExtensions { - + public static TValue GetOrDefault(this ILookup lookup, TKey key, TValue @default = default(TValue)) + => lookup.Contains(key) ? lookup[key] : @default; + + public static ILookup ToVimLookup(this IEnumerable input, Func keyFunc, Func valueFunc) + => input.ToDictionary(keyFunc, valueFunc).ToLookup(); + + public static ILookup ToVimLookup(this IEnumerable input, Func keyFunc) + => input.ToDictionary(keyFunc, x => x).ToLookup(); + + /// /// Returns an IEnumerable containing only indices of the array for which the function satisfies a specific predicate. /// diff --git a/src/cs/linqarray/Vim.LinqArray/ILookup.cs b/src/cs/util/Vim.Util/ILookup.cs similarity index 90% rename from src/cs/linqarray/Vim.LinqArray/ILookup.cs rename to src/cs/util/Vim.Util/ILookup.cs index a4eb5b8b..b1c8257f 100644 --- a/src/cs/linqarray/Vim.LinqArray/ILookup.cs +++ b/src/cs/util/Vim.Util/ILookup.cs @@ -6,7 +6,7 @@ using System.Collections.Generic; using System.Linq; -namespace Vim.LinqArray +namespace Vim.Util { /// /// Lookup table: mapping from a key to some value. @@ -47,17 +47,17 @@ public LookupFromDictionary(IDictionary d = null, TValue defaultVa public class LookupFromArray : ILookup { - private IArray array; + private TValue[] array; - public LookupFromArray(IArray xs) + public LookupFromArray(TValue[] xs) { array = xs; } - public IEnumerable Keys => array.Indices().ToEnumerable(); - public IEnumerable Values => array.ToEnumerable(); + public IEnumerable Keys => Enumerable.Range(0, array.Length); + public IEnumerable Values => array; public TValue this[int key] => array[key]; - public bool Contains(int key) => key >= 0 && key <= array.Count; + public bool Contains(int key) => key >= 0 && key <= array.Length; } public static class LookupExtensions diff --git a/src/cs/vim/Vim.Format.CodeGen/ObjectModelGenerator.cs b/src/cs/vim/Vim.Format.CodeGen/ObjectModelGenerator.cs index 49ce077a..6b6fcbba 100644 --- a/src/cs/vim/Vim.Format.CodeGen/ObjectModelGenerator.cs +++ b/src/cs/vim/Vim.Format.CodeGen/ObjectModelGenerator.cs @@ -350,7 +350,6 @@ public static void WriteDocument(string file) cb.AppendLine("using System.Collections.Generic;"); cb.AppendLine("using System.Linq;"); cb.AppendLine("using Vim.Math3d;"); - cb.AppendLine("using Vim.LinqArray;"); cb.AppendLine("using Vim.Format.ObjectModel;"); cb.AppendLine("using Vim.Util;"); diff --git a/src/cs/vim/Vim.Format.Core/AssetInfo.cs b/src/cs/vim/Vim.Format.Core/AssetInfo.cs index 53c3ef73..dd3329e7 100644 --- a/src/cs/vim/Vim.Format.Core/AssetInfo.cs +++ b/src/cs/vim/Vim.Format.Core/AssetInfo.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.IO; using Vim.Util; -using Vim.LinqArray; using Vim.BFastLib; using System.Linq; diff --git a/src/cs/vim/Vim.Format.Core/ColumnExtensions.Buffer.cs b/src/cs/vim/Vim.Format.Core/ColumnExtensions.Buffer.cs index 69133ef5..e1246fe2 100644 --- a/src/cs/vim/Vim.Format.Core/ColumnExtensions.Buffer.cs +++ b/src/cs/vim/Vim.Format.Core/ColumnExtensions.Buffer.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; -using Vim.LinqArray; using Vim.BFastLib; namespace Vim.Format @@ -206,7 +205,7 @@ public static IEnumerable> NoneIndexColumnRelations( this IEnumerable> indexColumns, params string[] indexColumnNames) => indexColumns.Select(ic => indexColumnNames.Contains(ic.Name) - ? new NamedBuffer(VimConstants.NoEntityRelation.Repeat(ic.Data.Length).ToArray(), ic.Name) + ? new NamedBuffer(Enumerable.Repeat(VimConstants.NoEntityRelation, ic.Data.Length).ToArray(), ic.Name) : ic); /// diff --git a/src/cs/vim/Vim.Format.Core/Document.cs b/src/cs/vim/Vim.Format.Core/Document.cs index 9a529d6e..4257d38d 100644 --- a/src/cs/vim/Vim.Format.Core/Document.cs +++ b/src/cs/vim/Vim.Format.Core/Document.cs @@ -1,5 +1,4 @@ -using Vim.LinqArray; -using Vim.BFastLib; +using Vim.BFastLib; using Vim.G3dNext; using Vim.Util; @@ -14,10 +13,10 @@ public Document(SerializableDocument document) Header = _Document.Header; GeometryNext = _Document.GeometryNext; StringTable = _Document.StringTable; - EntityTables = _Document.EntityTables.ToLookup( + EntityTables = _Document.EntityTables.ToVimLookup( et => et.Name, et => et.ToEntityTable(this)); - Assets = _Document.Assets.ToLookup(et => et.Name, et => et); + Assets = _Document.Assets.ToVimLookup(et => et.Name, et => et); } public string FileName => _Document.FileName; diff --git a/src/cs/vim/Vim.Format.Core/DocumentBuilderExtensions.cs b/src/cs/vim/Vim.Format.Core/DocumentBuilderExtensions.cs index a73fe17b..c5b4e636 100644 --- a/src/cs/vim/Vim.Format.Core/DocumentBuilderExtensions.cs +++ b/src/cs/vim/Vim.Format.Core/DocumentBuilderExtensions.cs @@ -2,7 +2,6 @@ using System.Linq; using Vim.BFastLib; using Vim.Format.Geometry; -using Vim.LinqArray; using Vim.Util; using static Vim.Format.DocumentBuilder; diff --git a/src/cs/vim/Vim.Format.Core/DocumentExtensions.cs b/src/cs/vim/Vim.Format.Core/DocumentExtensions.cs index 3ed5c589..366cf46b 100644 --- a/src/cs/vim/Vim.Format.Core/DocumentExtensions.cs +++ b/src/cs/vim/Vim.Format.Core/DocumentExtensions.cs @@ -1,9 +1,9 @@ using System; using System.Text.RegularExpressions; -using Vim.LinqArray; using Vim.BFastLib; using System.Collections.Generic; using System.Linq; +using Vim.Util; namespace Vim.Format { diff --git a/src/cs/vim/Vim.Format.Core/EntityTable.cs b/src/cs/vim/Vim.Format.Core/EntityTable.cs index 42c7b967..e4b317e4 100644 --- a/src/cs/vim/Vim.Format.Core/EntityTable.cs +++ b/src/cs/vim/Vim.Format.Core/EntityTable.cs @@ -1,8 +1,8 @@ using System; -using Vim.LinqArray; using Vim.BFastLib; using System.Linq; using System.Collections.Generic; +using Vim.Util; namespace Vim.Format { @@ -14,9 +14,9 @@ public EntityTable(Document document, SerializableEntityTable entityTable) _EntityTable = entityTable; Name = _EntityTable.Name; - DataColumns = LinqArray.LinqArray.ToLookup(_EntityTable.DataColumns, c => c.Name, c => c); - IndexColumns = LinqArray.LinqArray.ToLookup(_EntityTable.IndexColumns, c => c.Name, c => c); - StringColumns = LinqArray.LinqArray.ToLookup(_EntityTable.StringColumns, c => c.Name, c => c); + DataColumns = _EntityTable.DataColumns.ToVimLookup( c => c.Name, c => c); + IndexColumns = _EntityTable.IndexColumns.ToVimLookup(c => c.Name, c => c); + StringColumns = _EntityTable.StringColumns.ToVimLookup(c => c.Name, c => c); NumRows = Columns.FirstOrDefault()?.NumElements() ?? 0; Columns.ValidateColumnRowsAreAligned(); @@ -26,9 +26,9 @@ public EntityTable(Document document, SerializableEntityTable entityTable) public Document Document { get; } public string Name { get; } public int NumRows { get; } - public LinqArray.ILookup DataColumns { get; } - public LinqArray.ILookup> StringColumns { get; } - public LinqArray.ILookup> IndexColumns { get; } + public Vim.Util.ILookup DataColumns { get; } + public Vim.Util.ILookup> StringColumns { get; } + public Vim.Util.ILookup> IndexColumns { get; } public IEnumerable Columns => DataColumns.Values .Concat(IndexColumns.Values.Select(x => (INamedBuffer)x)) diff --git a/src/cs/vim/Vim.Format.Core/Geometry/MeshOptimization.cs b/src/cs/vim/Vim.Format.Core/Geometry/MeshOptimization.cs index 94dc91fc..e0a7199b 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/MeshOptimization.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/MeshOptimization.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using System.Linq; -using Vim.LinqArray; using Vim.Math3d; namespace Vim.Format.Geometry diff --git a/src/cs/vim/Vim.Format.Core/Geometry/PerimeterProjection.cs b/src/cs/vim/Vim.Format.Core/Geometry/PerimeterProjection.cs index e502b3f8..6acbe6b1 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/PerimeterProjection.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/PerimeterProjection.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; -using Vim.LinqArray; using Vim.Math3d; namespace Vim.Format.Geometry diff --git a/src/cs/vim/Vim.Format.Core/Geometry/Primitives.cs b/src/cs/vim/Vim.Format.Core/Geometry/Primitives.cs index efd44cd3..ae24622f 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/Primitives.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/Primitives.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using Vim.LinqArray; using Vim.Math3d; namespace Vim.Format.Geometry @@ -111,7 +110,7 @@ public static Vector2[] CirclePoints(float radius, int numPoints) => CirclePoints(numPoints).Select(x => x * radius).ToArray(); public static Vector2[] CirclePoints(int numPoints) - => numPoints.Select(i => CirclePoint(i, numPoints)).ToArray(); + => Enumerable.Range(0, numPoints).Select(i => CirclePoint(i, numPoints)).ToArray(); public static Vector2 CirclePoint(int i, int numPoints) => new Vector2((i * (Math3d.Constants.TwoPi / numPoints)).Cos(), (i * (Math3d.Constants.TwoPi / numPoints)).Sin()); diff --git a/src/cs/vim/Vim.Format.Core/Geometry/Validation.cs b/src/cs/vim/Vim.Format.Core/Geometry/Validation.cs index 474b340a..897ba16d 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/Validation.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/Validation.cs @@ -1,5 +1,4 @@ using System; -using Vim.LinqArray; using Vim.BFastLib; namespace Vim.Format.Geometry diff --git a/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs b/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs index a199e5a4..e5cffc94 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs @@ -2,9 +2,7 @@ using System.Collections.Generic; using System.Linq; using Vim.G3dNext; -using Vim.LinqArray; using Vim.Math3d; -using Vim.Util; namespace Vim.Format.Geometry { diff --git a/src/cs/vim/Vim.Format.Core/Validation.cs b/src/cs/vim/Vim.Format.Core/Validation.cs index 6d596db8..6275bf17 100644 --- a/src/cs/vim/Vim.Format.Core/Validation.cs +++ b/src/cs/vim/Vim.Format.Core/Validation.cs @@ -1,7 +1,5 @@ using System; -using System.Collections.Generic; using Vim.BFastLib; -using Vim.LinqArray; namespace Vim.Format { diff --git a/src/cs/vim/Vim.Format.Core/VimSchema.cs b/src/cs/vim/Vim.Format.Core/VimSchema.cs index 8195c39a..cc262a08 100644 --- a/src/cs/vim/Vim.Format.Core/VimSchema.cs +++ b/src/cs/vim/Vim.Format.Core/VimSchema.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Linq; using Vim.Util; -using Vim.LinqArray; namespace Vim.Format { diff --git a/src/cs/vim/Vim.Format.Tests/FormatTests.cs b/src/cs/vim/Vim.Format.Tests/FormatTests.cs index b243c570..2ea981a3 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.LinqArray; using Vim.BFastLib; +using Vim.Util; namespace Vim.Format.Tests { @@ -29,17 +29,6 @@ public static void AssertNameAndSizesAreEqual(SerializableEntityTable t1, Serial Assert.AreEqual(t1.StringColumns.Count, t2.StringColumns.Count); for (var i = 0; i < t1.StringColumns.Count; ++i) AssertNameAndSizesAreEqual(t1.StringColumns[i], t2.StringColumns[i]); - - /* Can't expect the numerical values to be precise, because of non-determinism of parallelism when generating string table. - for (var i=0; i < t1.Properties.Length; ++i) - { - var p1 = t1.Properties[i]; - var p2 = t2.Properties[i]; - Assert.AreEqual(p1.EntityId, p2.EntityId); - Assert.AreEqual(p1.Name, p2.Name); - Assert.AreEqual(p1.Value, p2.Value); - } - */ } public static void AssertEquals(SerializableDocument d1, SerializableDocument d2, bool compareStringTables = true) diff --git a/src/cs/vim/Vim.Format.Tests/Geometry/GeometryTests.cs b/src/cs/vim/Vim.Format.Tests/Geometry/GeometryTests.cs index 3850be40..6218cd8f 100644 --- a/src/cs/vim/Vim.Format.Tests/Geometry/GeometryTests.cs +++ b/src/cs/vim/Vim.Format.Tests/Geometry/GeometryTests.cs @@ -3,7 +3,6 @@ using System.Linq; using Vim.Format.Geometry; using Vim.G3dNext; -using Vim.LinqArray; using Vim.Math3d; namespace Vim.Format.Tests.Geometry diff --git a/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs b/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs index acf01b1b..cf8fe183 100644 --- a/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs +++ b/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs @@ -1,11 +1,7 @@ using NUnit.Framework; -using System; -using System.Linq; using Vim.Format.Geometry; using Vim.Format.SceneBuilder; -using Vim.LinqArray; using Vim.Util.Tests; -using Vim.Util; namespace Vim.Format.Tests; diff --git a/src/cs/vim/Vim.Format.Vimx.Conversion/Chunking.cs b/src/cs/vim/Vim.Format.Vimx.Conversion/Chunking.cs index 2e42bc8d..0318eb23 100644 --- a/src/cs/vim/Vim.Format.Vimx.Conversion/Chunking.cs +++ b/src/cs/vim/Vim.Format.Vimx.Conversion/Chunking.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using System.Linq; -using Vim.LinqArray; using Vim.Math3d; using Vim.G3dNext; diff --git a/src/cs/vim/Vim.Format.Vimx.Conversion/VimxConverter.cs b/src/cs/vim/Vim.Format.Vimx.Conversion/VimxConverter.cs index 804635ae..77749be7 100644 --- a/src/cs/vim/Vim.Format.Vimx.Conversion/VimxConverter.cs +++ b/src/cs/vim/Vim.Format.Vimx.Conversion/VimxConverter.cs @@ -4,7 +4,6 @@ using Vim.BFastLib; using Vim.Format.ObjectModel; using Vim.G3dNext; -using Vim.LinqArray; using Vim.Math3d; using Vim.Util; diff --git a/src/cs/vim/Vim.Format/ObjectModel/ElementInfo.cs b/src/cs/vim/Vim.Format/ObjectModel/ElementInfo.cs index df7755cb..cc896bb6 100644 --- a/src/cs/vim/Vim.Format/ObjectModel/ElementInfo.cs +++ b/src/cs/vim/Vim.Format/ObjectModel/ElementInfo.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using Vim.LinqArray; namespace Vim.Format.ObjectModel { diff --git a/src/cs/vim/Vim.Format/ObjectModel/ObjectModelExtensions.cs b/src/cs/vim/Vim.Format/ObjectModel/ObjectModelExtensions.cs index 6174db7f..7b45e3ff 100644 --- a/src/cs/vim/Vim.Format/ObjectModel/ObjectModelExtensions.cs +++ b/src/cs/vim/Vim.Format/ObjectModel/ObjectModelExtensions.cs @@ -4,7 +4,6 @@ using System.IO; using System.Linq; using Vim.Util; -using Vim.LinqArray; namespace Vim.Format.ObjectModel { @@ -153,7 +152,7 @@ public static DataTable GetScheduleAsDataTable(this DocumentModel dm, int schedu var columnSet = new HashSet(columns.Select(c => c.Index)); - var cellRecords = dm.ScheduleCellScheduleColumnIndex.ToIArray() + var cellRecords = dm.ScheduleCellScheduleColumnIndex .IndicesWhere((colIndex, _) => columnSet.Contains(colIndex)) .Select(cellIndex => new CellData( dm.GetScheduleCellValue(cellIndex), diff --git a/src/cs/vim/Vim.Format/ObjectModel/ObjectModelGenerated.cs b/src/cs/vim/Vim.Format/ObjectModel/ObjectModelGenerated.cs index 6a5a980d..23c723df 100644 --- a/src/cs/vim/Vim.Format/ObjectModel/ObjectModelGenerated.cs +++ b/src/cs/vim/Vim.Format/ObjectModel/ObjectModelGenerated.cs @@ -4,7 +4,6 @@ using System.Collections.Generic; using System.Linq; using Vim.Math3d; -using Vim.LinqArray; using Vim.Format.ObjectModel; using Vim.Util; diff --git a/src/cs/vim/Vim.Format/ObjectModel/Validation.cs b/src/cs/vim/Vim.Format/ObjectModel/Validation.cs index 7869186e..fd795670 100644 --- a/src/cs/vim/Vim.Format/ObjectModel/Validation.cs +++ b/src/cs/vim/Vim.Format/ObjectModel/Validation.cs @@ -3,7 +3,6 @@ using System.Linq; using System.Reflection; using System.Threading.Tasks; -using Vim.LinqArray; using Vim.Math3d; using Vim.Util; diff --git a/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs b/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs index 0f7f2107..8cc998e4 100644 --- a/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs +++ b/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs @@ -6,7 +6,6 @@ using Vim.BFastLib; using Vim.Format.Geometry; using Vim.Format.ObjectModel; -using Vim.LinqArray; using Vim.Math3d; using Vim.Util; @@ -44,9 +43,9 @@ public static void ValidateDocumentModelToG3dInvariantsNext(this VimScene vim) { var (type, attrs) = tuple; var propertyName = type.Name + "List"; - if (dm.GetPropertyValue(propertyName) is IArray arr) + if (dm.GetPropertyValue(propertyName) is Array arr) { - var numEntities = arr.Count; + var numEntities = arr.Length; foreach (var attr in attrs) { diff --git a/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs b/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs index 005ea2d6..48a652d2 100644 --- a/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs +++ b/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs @@ -8,7 +8,6 @@ using Vim.Format.Geometry; using Vim.Format.ObjectModel; using Vim.G3dNext; -using Vim.LinqArray; using Vim.Math3d; using Vim.Util; using IVimSceneProgress = System.IProgress<(string, double)>; diff --git a/src/cs/vim/Vim.Format/SceneBuilder/VimSceneHelpers.cs b/src/cs/vim/Vim.Format/SceneBuilder/VimSceneHelpers.cs index cf7ed5cc..962916a6 100644 --- a/src/cs/vim/Vim.Format/SceneBuilder/VimSceneHelpers.cs +++ b/src/cs/vim/Vim.Format/SceneBuilder/VimSceneHelpers.cs @@ -4,7 +4,6 @@ using Vim.Format; using Vim.Format.ObjectModel; using Vim.Util; -using Vim.LinqArray; using Vim.Math3d; namespace Vim diff --git a/src/cs/vim/Vim.Format/SceneBuilder/VimSceneNode.cs b/src/cs/vim/Vim.Format/SceneBuilder/VimSceneNode.cs index 76c0e3f4..9e7c5425 100644 --- a/src/cs/vim/Vim.Format/SceneBuilder/VimSceneNode.cs +++ b/src/cs/vim/Vim.Format/SceneBuilder/VimSceneNode.cs @@ -4,7 +4,6 @@ using Vim.Format.Geometry; using Vim.Format.ObjectModel; using Vim.G3dNext; -using Vim.LinqArray; using Vim.Math3d; namespace Vim From 3fae7ec78a2ef96174fddb0120c6c9ff7d309243 Mon Sep 17 00:00:00 2001 From: simon Date: Tue, 16 Apr 2024 15:37:55 -0400 Subject: [PATCH 188/204] removing linq array --- src/cs/linqarray/Vim.LinqArray/LinqArray.cs | 6 ++---- src/cs/util/Vim.Util/CollectionExtensions.cs | 11 ++++++++++- .../Vim.LinqArray => util/Vim.Util}/ILookup.cs | 12 ++++++------ .../vim/Vim.Format.CodeGen/ObjectModelGenerator.cs | 1 - src/cs/vim/Vim.Format.Core/AssetInfo.cs | 1 - .../vim/Vim.Format.Core/ColumnExtensions.Buffer.cs | 3 +-- src/cs/vim/Vim.Format.Core/Document.cs | 7 +++---- .../Vim.Format.Core/DocumentBuilderExtensions.cs | 1 - src/cs/vim/Vim.Format.Core/DocumentExtensions.cs | 2 +- src/cs/vim/Vim.Format.Core/EntityTable.cs | 14 +++++++------- .../Vim.Format.Core/Geometry/MeshOptimization.cs | 1 - .../Geometry/PerimeterProjection.cs | 1 - src/cs/vim/Vim.Format.Core/Geometry/Primitives.cs | 3 +-- src/cs/vim/Vim.Format.Core/Geometry/Validation.cs | 1 - src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs | 2 -- src/cs/vim/Vim.Format.Core/Validation.cs | 2 -- src/cs/vim/Vim.Format.Core/VimSchema.cs | 1 - src/cs/vim/Vim.Format.Tests/FormatTests.cs | 13 +------------ .../vim/Vim.Format.Tests/Geometry/GeometryTests.cs | 1 - .../Vim.Format.Tests/SerializableDocumentTests.cs | 4 ---- src/cs/vim/Vim.Format.Vimx.Conversion/Chunking.cs | 1 - .../Vim.Format.Vimx.Conversion/VimxConverter.cs | 1 - src/cs/vim/Vim.Format/ObjectModel/ElementInfo.cs | 1 - .../ObjectModel/ObjectModelExtensions.cs | 3 +-- .../Vim.Format/ObjectModel/ObjectModelGenerated.cs | 1 - src/cs/vim/Vim.Format/ObjectModel/Validation.cs | 1 - src/cs/vim/Vim.Format/SceneBuilder/Validation.cs | 5 ++--- src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs | 1 - .../vim/Vim.Format/SceneBuilder/VimSceneHelpers.cs | 1 - src/cs/vim/Vim.Format/SceneBuilder/VimSceneNode.cs | 1 - 30 files changed, 35 insertions(+), 68 deletions(-) rename src/cs/{linqarray/Vim.LinqArray => util/Vim.Util}/ILookup.cs (90%) diff --git a/src/cs/linqarray/Vim.LinqArray/LinqArray.cs b/src/cs/linqarray/Vim.LinqArray/LinqArray.cs index cf646593..3e392e0e 100644 --- a/src/cs/linqarray/Vim.LinqArray/LinqArray.cs +++ b/src/cs/linqarray/Vim.LinqArray/LinqArray.cs @@ -943,14 +943,12 @@ public static IArray Cast(this IArray xs) where T : U public static bool Contains(this IArray xs, T value) => xs.Any(x => x.Equals(value)); - public static ILookup ToLookup(this IEnumerable input, Func keyFunc, Func valueFunc) - => input.ToDictionary(keyFunc, valueFunc).ToLookup(); + + public static ILookup ToLookup(this IArray input, Func keyFunc, Func valueFunc) => input.ToEnumerable().ToLookup(keyFunc, valueFunc); - public static ILookup ToLookup(this IEnumerable input, Func keyFunc) - => input.ToDictionary(keyFunc, x => x).ToLookup(); public static ILookup ToLookup(this IArray input, Func keyFunc) => input.ToEnumerable().ToLookup(keyFunc, x => x); diff --git a/src/cs/util/Vim.Util/CollectionExtensions.cs b/src/cs/util/Vim.Util/CollectionExtensions.cs index cadcfa54..9982620a 100644 --- a/src/cs/util/Vim.Util/CollectionExtensions.cs +++ b/src/cs/util/Vim.Util/CollectionExtensions.cs @@ -7,7 +7,16 @@ namespace Vim.Util { public static class CollectionExtensions { - + public static TValue GetOrDefault(this ILookup lookup, TKey key, TValue @default = default(TValue)) + => lookup.Contains(key) ? lookup[key] : @default; + + public static ILookup ToVimLookup(this IEnumerable input, Func keyFunc, Func valueFunc) + => input.ToDictionary(keyFunc, valueFunc).ToLookup(); + + public static ILookup ToVimLookup(this IEnumerable input, Func keyFunc) + => input.ToDictionary(keyFunc, x => x).ToLookup(); + + /// /// Returns an IEnumerable containing only indices of the array for which the function satisfies a specific predicate. /// diff --git a/src/cs/linqarray/Vim.LinqArray/ILookup.cs b/src/cs/util/Vim.Util/ILookup.cs similarity index 90% rename from src/cs/linqarray/Vim.LinqArray/ILookup.cs rename to src/cs/util/Vim.Util/ILookup.cs index a4eb5b8b..b1c8257f 100644 --- a/src/cs/linqarray/Vim.LinqArray/ILookup.cs +++ b/src/cs/util/Vim.Util/ILookup.cs @@ -6,7 +6,7 @@ using System.Collections.Generic; using System.Linq; -namespace Vim.LinqArray +namespace Vim.Util { /// /// Lookup table: mapping from a key to some value. @@ -47,17 +47,17 @@ public LookupFromDictionary(IDictionary d = null, TValue defaultVa public class LookupFromArray : ILookup { - private IArray array; + private TValue[] array; - public LookupFromArray(IArray xs) + public LookupFromArray(TValue[] xs) { array = xs; } - public IEnumerable Keys => array.Indices().ToEnumerable(); - public IEnumerable Values => array.ToEnumerable(); + public IEnumerable Keys => Enumerable.Range(0, array.Length); + public IEnumerable Values => array; public TValue this[int key] => array[key]; - public bool Contains(int key) => key >= 0 && key <= array.Count; + public bool Contains(int key) => key >= 0 && key <= array.Length; } public static class LookupExtensions diff --git a/src/cs/vim/Vim.Format.CodeGen/ObjectModelGenerator.cs b/src/cs/vim/Vim.Format.CodeGen/ObjectModelGenerator.cs index 49ce077a..6b6fcbba 100644 --- a/src/cs/vim/Vim.Format.CodeGen/ObjectModelGenerator.cs +++ b/src/cs/vim/Vim.Format.CodeGen/ObjectModelGenerator.cs @@ -350,7 +350,6 @@ public static void WriteDocument(string file) cb.AppendLine("using System.Collections.Generic;"); cb.AppendLine("using System.Linq;"); cb.AppendLine("using Vim.Math3d;"); - cb.AppendLine("using Vim.LinqArray;"); cb.AppendLine("using Vim.Format.ObjectModel;"); cb.AppendLine("using Vim.Util;"); diff --git a/src/cs/vim/Vim.Format.Core/AssetInfo.cs b/src/cs/vim/Vim.Format.Core/AssetInfo.cs index 53c3ef73..dd3329e7 100644 --- a/src/cs/vim/Vim.Format.Core/AssetInfo.cs +++ b/src/cs/vim/Vim.Format.Core/AssetInfo.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.IO; using Vim.Util; -using Vim.LinqArray; using Vim.BFastLib; using System.Linq; diff --git a/src/cs/vim/Vim.Format.Core/ColumnExtensions.Buffer.cs b/src/cs/vim/Vim.Format.Core/ColumnExtensions.Buffer.cs index 69133ef5..e1246fe2 100644 --- a/src/cs/vim/Vim.Format.Core/ColumnExtensions.Buffer.cs +++ b/src/cs/vim/Vim.Format.Core/ColumnExtensions.Buffer.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; -using Vim.LinqArray; using Vim.BFastLib; namespace Vim.Format @@ -206,7 +205,7 @@ public static IEnumerable> NoneIndexColumnRelations( this IEnumerable> indexColumns, params string[] indexColumnNames) => indexColumns.Select(ic => indexColumnNames.Contains(ic.Name) - ? new NamedBuffer(VimConstants.NoEntityRelation.Repeat(ic.Data.Length).ToArray(), ic.Name) + ? new NamedBuffer(Enumerable.Repeat(VimConstants.NoEntityRelation, ic.Data.Length).ToArray(), ic.Name) : ic); /// diff --git a/src/cs/vim/Vim.Format.Core/Document.cs b/src/cs/vim/Vim.Format.Core/Document.cs index 9a529d6e..4257d38d 100644 --- a/src/cs/vim/Vim.Format.Core/Document.cs +++ b/src/cs/vim/Vim.Format.Core/Document.cs @@ -1,5 +1,4 @@ -using Vim.LinqArray; -using Vim.BFastLib; +using Vim.BFastLib; using Vim.G3dNext; using Vim.Util; @@ -14,10 +13,10 @@ public Document(SerializableDocument document) Header = _Document.Header; GeometryNext = _Document.GeometryNext; StringTable = _Document.StringTable; - EntityTables = _Document.EntityTables.ToLookup( + EntityTables = _Document.EntityTables.ToVimLookup( et => et.Name, et => et.ToEntityTable(this)); - Assets = _Document.Assets.ToLookup(et => et.Name, et => et); + Assets = _Document.Assets.ToVimLookup(et => et.Name, et => et); } public string FileName => _Document.FileName; diff --git a/src/cs/vim/Vim.Format.Core/DocumentBuilderExtensions.cs b/src/cs/vim/Vim.Format.Core/DocumentBuilderExtensions.cs index a73fe17b..c5b4e636 100644 --- a/src/cs/vim/Vim.Format.Core/DocumentBuilderExtensions.cs +++ b/src/cs/vim/Vim.Format.Core/DocumentBuilderExtensions.cs @@ -2,7 +2,6 @@ using System.Linq; using Vim.BFastLib; using Vim.Format.Geometry; -using Vim.LinqArray; using Vim.Util; using static Vim.Format.DocumentBuilder; diff --git a/src/cs/vim/Vim.Format.Core/DocumentExtensions.cs b/src/cs/vim/Vim.Format.Core/DocumentExtensions.cs index 3ed5c589..366cf46b 100644 --- a/src/cs/vim/Vim.Format.Core/DocumentExtensions.cs +++ b/src/cs/vim/Vim.Format.Core/DocumentExtensions.cs @@ -1,9 +1,9 @@ using System; using System.Text.RegularExpressions; -using Vim.LinqArray; using Vim.BFastLib; using System.Collections.Generic; using System.Linq; +using Vim.Util; namespace Vim.Format { diff --git a/src/cs/vim/Vim.Format.Core/EntityTable.cs b/src/cs/vim/Vim.Format.Core/EntityTable.cs index 42c7b967..e4b317e4 100644 --- a/src/cs/vim/Vim.Format.Core/EntityTable.cs +++ b/src/cs/vim/Vim.Format.Core/EntityTable.cs @@ -1,8 +1,8 @@ using System; -using Vim.LinqArray; using Vim.BFastLib; using System.Linq; using System.Collections.Generic; +using Vim.Util; namespace Vim.Format { @@ -14,9 +14,9 @@ public EntityTable(Document document, SerializableEntityTable entityTable) _EntityTable = entityTable; Name = _EntityTable.Name; - DataColumns = LinqArray.LinqArray.ToLookup(_EntityTable.DataColumns, c => c.Name, c => c); - IndexColumns = LinqArray.LinqArray.ToLookup(_EntityTable.IndexColumns, c => c.Name, c => c); - StringColumns = LinqArray.LinqArray.ToLookup(_EntityTable.StringColumns, c => c.Name, c => c); + DataColumns = _EntityTable.DataColumns.ToVimLookup( c => c.Name, c => c); + IndexColumns = _EntityTable.IndexColumns.ToVimLookup(c => c.Name, c => c); + StringColumns = _EntityTable.StringColumns.ToVimLookup(c => c.Name, c => c); NumRows = Columns.FirstOrDefault()?.NumElements() ?? 0; Columns.ValidateColumnRowsAreAligned(); @@ -26,9 +26,9 @@ public EntityTable(Document document, SerializableEntityTable entityTable) public Document Document { get; } public string Name { get; } public int NumRows { get; } - public LinqArray.ILookup DataColumns { get; } - public LinqArray.ILookup> StringColumns { get; } - public LinqArray.ILookup> IndexColumns { get; } + public Vim.Util.ILookup DataColumns { get; } + public Vim.Util.ILookup> StringColumns { get; } + public Vim.Util.ILookup> IndexColumns { get; } public IEnumerable Columns => DataColumns.Values .Concat(IndexColumns.Values.Select(x => (INamedBuffer)x)) diff --git a/src/cs/vim/Vim.Format.Core/Geometry/MeshOptimization.cs b/src/cs/vim/Vim.Format.Core/Geometry/MeshOptimization.cs index 94dc91fc..e0a7199b 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/MeshOptimization.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/MeshOptimization.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using System.Linq; -using Vim.LinqArray; using Vim.Math3d; namespace Vim.Format.Geometry diff --git a/src/cs/vim/Vim.Format.Core/Geometry/PerimeterProjection.cs b/src/cs/vim/Vim.Format.Core/Geometry/PerimeterProjection.cs index e502b3f8..6acbe6b1 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/PerimeterProjection.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/PerimeterProjection.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; -using Vim.LinqArray; using Vim.Math3d; namespace Vim.Format.Geometry diff --git a/src/cs/vim/Vim.Format.Core/Geometry/Primitives.cs b/src/cs/vim/Vim.Format.Core/Geometry/Primitives.cs index efd44cd3..ae24622f 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/Primitives.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/Primitives.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using Vim.LinqArray; using Vim.Math3d; namespace Vim.Format.Geometry @@ -111,7 +110,7 @@ public static Vector2[] CirclePoints(float radius, int numPoints) => CirclePoints(numPoints).Select(x => x * radius).ToArray(); public static Vector2[] CirclePoints(int numPoints) - => numPoints.Select(i => CirclePoint(i, numPoints)).ToArray(); + => Enumerable.Range(0, numPoints).Select(i => CirclePoint(i, numPoints)).ToArray(); public static Vector2 CirclePoint(int i, int numPoints) => new Vector2((i * (Math3d.Constants.TwoPi / numPoints)).Cos(), (i * (Math3d.Constants.TwoPi / numPoints)).Sin()); diff --git a/src/cs/vim/Vim.Format.Core/Geometry/Validation.cs b/src/cs/vim/Vim.Format.Core/Geometry/Validation.cs index 474b340a..897ba16d 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/Validation.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/Validation.cs @@ -1,5 +1,4 @@ using System; -using Vim.LinqArray; using Vim.BFastLib; namespace Vim.Format.Geometry diff --git a/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs b/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs index a199e5a4..e5cffc94 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs @@ -2,9 +2,7 @@ using System.Collections.Generic; using System.Linq; using Vim.G3dNext; -using Vim.LinqArray; using Vim.Math3d; -using Vim.Util; namespace Vim.Format.Geometry { diff --git a/src/cs/vim/Vim.Format.Core/Validation.cs b/src/cs/vim/Vim.Format.Core/Validation.cs index 6d596db8..6275bf17 100644 --- a/src/cs/vim/Vim.Format.Core/Validation.cs +++ b/src/cs/vim/Vim.Format.Core/Validation.cs @@ -1,7 +1,5 @@ using System; -using System.Collections.Generic; using Vim.BFastLib; -using Vim.LinqArray; namespace Vim.Format { diff --git a/src/cs/vim/Vim.Format.Core/VimSchema.cs b/src/cs/vim/Vim.Format.Core/VimSchema.cs index 8195c39a..cc262a08 100644 --- a/src/cs/vim/Vim.Format.Core/VimSchema.cs +++ b/src/cs/vim/Vim.Format.Core/VimSchema.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Linq; using Vim.Util; -using Vim.LinqArray; namespace Vim.Format { diff --git a/src/cs/vim/Vim.Format.Tests/FormatTests.cs b/src/cs/vim/Vim.Format.Tests/FormatTests.cs index b243c570..2ea981a3 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.LinqArray; using Vim.BFastLib; +using Vim.Util; namespace Vim.Format.Tests { @@ -29,17 +29,6 @@ public static void AssertNameAndSizesAreEqual(SerializableEntityTable t1, Serial Assert.AreEqual(t1.StringColumns.Count, t2.StringColumns.Count); for (var i = 0; i < t1.StringColumns.Count; ++i) AssertNameAndSizesAreEqual(t1.StringColumns[i], t2.StringColumns[i]); - - /* Can't expect the numerical values to be precise, because of non-determinism of parallelism when generating string table. - for (var i=0; i < t1.Properties.Length; ++i) - { - var p1 = t1.Properties[i]; - var p2 = t2.Properties[i]; - Assert.AreEqual(p1.EntityId, p2.EntityId); - Assert.AreEqual(p1.Name, p2.Name); - Assert.AreEqual(p1.Value, p2.Value); - } - */ } public static void AssertEquals(SerializableDocument d1, SerializableDocument d2, bool compareStringTables = true) diff --git a/src/cs/vim/Vim.Format.Tests/Geometry/GeometryTests.cs b/src/cs/vim/Vim.Format.Tests/Geometry/GeometryTests.cs index 3850be40..6218cd8f 100644 --- a/src/cs/vim/Vim.Format.Tests/Geometry/GeometryTests.cs +++ b/src/cs/vim/Vim.Format.Tests/Geometry/GeometryTests.cs @@ -3,7 +3,6 @@ using System.Linq; using Vim.Format.Geometry; using Vim.G3dNext; -using Vim.LinqArray; using Vim.Math3d; namespace Vim.Format.Tests.Geometry diff --git a/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs b/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs index acf01b1b..cf8fe183 100644 --- a/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs +++ b/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs @@ -1,11 +1,7 @@ using NUnit.Framework; -using System; -using System.Linq; using Vim.Format.Geometry; using Vim.Format.SceneBuilder; -using Vim.LinqArray; using Vim.Util.Tests; -using Vim.Util; namespace Vim.Format.Tests; diff --git a/src/cs/vim/Vim.Format.Vimx.Conversion/Chunking.cs b/src/cs/vim/Vim.Format.Vimx.Conversion/Chunking.cs index 2e42bc8d..0318eb23 100644 --- a/src/cs/vim/Vim.Format.Vimx.Conversion/Chunking.cs +++ b/src/cs/vim/Vim.Format.Vimx.Conversion/Chunking.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using System.Linq; -using Vim.LinqArray; using Vim.Math3d; using Vim.G3dNext; diff --git a/src/cs/vim/Vim.Format.Vimx.Conversion/VimxConverter.cs b/src/cs/vim/Vim.Format.Vimx.Conversion/VimxConverter.cs index 804635ae..77749be7 100644 --- a/src/cs/vim/Vim.Format.Vimx.Conversion/VimxConverter.cs +++ b/src/cs/vim/Vim.Format.Vimx.Conversion/VimxConverter.cs @@ -4,7 +4,6 @@ using Vim.BFastLib; using Vim.Format.ObjectModel; using Vim.G3dNext; -using Vim.LinqArray; using Vim.Math3d; using Vim.Util; diff --git a/src/cs/vim/Vim.Format/ObjectModel/ElementInfo.cs b/src/cs/vim/Vim.Format/ObjectModel/ElementInfo.cs index df7755cb..cc896bb6 100644 --- a/src/cs/vim/Vim.Format/ObjectModel/ElementInfo.cs +++ b/src/cs/vim/Vim.Format/ObjectModel/ElementInfo.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using Vim.LinqArray; namespace Vim.Format.ObjectModel { diff --git a/src/cs/vim/Vim.Format/ObjectModel/ObjectModelExtensions.cs b/src/cs/vim/Vim.Format/ObjectModel/ObjectModelExtensions.cs index 6174db7f..7b45e3ff 100644 --- a/src/cs/vim/Vim.Format/ObjectModel/ObjectModelExtensions.cs +++ b/src/cs/vim/Vim.Format/ObjectModel/ObjectModelExtensions.cs @@ -4,7 +4,6 @@ using System.IO; using System.Linq; using Vim.Util; -using Vim.LinqArray; namespace Vim.Format.ObjectModel { @@ -153,7 +152,7 @@ public static DataTable GetScheduleAsDataTable(this DocumentModel dm, int schedu var columnSet = new HashSet(columns.Select(c => c.Index)); - var cellRecords = dm.ScheduleCellScheduleColumnIndex.ToIArray() + var cellRecords = dm.ScheduleCellScheduleColumnIndex .IndicesWhere((colIndex, _) => columnSet.Contains(colIndex)) .Select(cellIndex => new CellData( dm.GetScheduleCellValue(cellIndex), diff --git a/src/cs/vim/Vim.Format/ObjectModel/ObjectModelGenerated.cs b/src/cs/vim/Vim.Format/ObjectModel/ObjectModelGenerated.cs index 6a5a980d..23c723df 100644 --- a/src/cs/vim/Vim.Format/ObjectModel/ObjectModelGenerated.cs +++ b/src/cs/vim/Vim.Format/ObjectModel/ObjectModelGenerated.cs @@ -4,7 +4,6 @@ using System.Collections.Generic; using System.Linq; using Vim.Math3d; -using Vim.LinqArray; using Vim.Format.ObjectModel; using Vim.Util; diff --git a/src/cs/vim/Vim.Format/ObjectModel/Validation.cs b/src/cs/vim/Vim.Format/ObjectModel/Validation.cs index 7869186e..fd795670 100644 --- a/src/cs/vim/Vim.Format/ObjectModel/Validation.cs +++ b/src/cs/vim/Vim.Format/ObjectModel/Validation.cs @@ -3,7 +3,6 @@ using System.Linq; using System.Reflection; using System.Threading.Tasks; -using Vim.LinqArray; using Vim.Math3d; using Vim.Util; diff --git a/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs b/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs index 0f7f2107..8cc998e4 100644 --- a/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs +++ b/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs @@ -6,7 +6,6 @@ using Vim.BFastLib; using Vim.Format.Geometry; using Vim.Format.ObjectModel; -using Vim.LinqArray; using Vim.Math3d; using Vim.Util; @@ -44,9 +43,9 @@ public static void ValidateDocumentModelToG3dInvariantsNext(this VimScene vim) { var (type, attrs) = tuple; var propertyName = type.Name + "List"; - if (dm.GetPropertyValue(propertyName) is IArray arr) + if (dm.GetPropertyValue(propertyName) is Array arr) { - var numEntities = arr.Count; + var numEntities = arr.Length; foreach (var attr in attrs) { diff --git a/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs b/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs index 005ea2d6..48a652d2 100644 --- a/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs +++ b/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs @@ -8,7 +8,6 @@ using Vim.Format.Geometry; using Vim.Format.ObjectModel; using Vim.G3dNext; -using Vim.LinqArray; using Vim.Math3d; using Vim.Util; using IVimSceneProgress = System.IProgress<(string, double)>; diff --git a/src/cs/vim/Vim.Format/SceneBuilder/VimSceneHelpers.cs b/src/cs/vim/Vim.Format/SceneBuilder/VimSceneHelpers.cs index cf7ed5cc..962916a6 100644 --- a/src/cs/vim/Vim.Format/SceneBuilder/VimSceneHelpers.cs +++ b/src/cs/vim/Vim.Format/SceneBuilder/VimSceneHelpers.cs @@ -4,7 +4,6 @@ using Vim.Format; using Vim.Format.ObjectModel; using Vim.Util; -using Vim.LinqArray; using Vim.Math3d; namespace Vim diff --git a/src/cs/vim/Vim.Format/SceneBuilder/VimSceneNode.cs b/src/cs/vim/Vim.Format/SceneBuilder/VimSceneNode.cs index 76c0e3f4..9e7c5425 100644 --- a/src/cs/vim/Vim.Format/SceneBuilder/VimSceneNode.cs +++ b/src/cs/vim/Vim.Format/SceneBuilder/VimSceneNode.cs @@ -4,7 +4,6 @@ using Vim.Format.Geometry; using Vim.Format.ObjectModel; using Vim.G3dNext; -using Vim.LinqArray; using Vim.Math3d; namespace Vim From 43cb01fa7209d0f349a8f62912916a99da90c9d1 Mon Sep 17 00:00:00 2001 From: simon Date: Tue, 16 Apr 2024 15:44:27 -0400 Subject: [PATCH 189/204] restored method --- src/cs/util/Vim.Util/CollectionExtensions.cs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/cs/util/Vim.Util/CollectionExtensions.cs b/src/cs/util/Vim.Util/CollectionExtensions.cs index 9982620a..79712ba0 100644 --- a/src/cs/util/Vim.Util/CollectionExtensions.cs +++ b/src/cs/util/Vim.Util/CollectionExtensions.cs @@ -41,6 +41,19 @@ public static IEnumerable IndicesWhere(this IList self, Func + /// [a, b, c ..] => [0, a, a+b, a+b+c ...] + /// + public static int[] OffsetsFromCounts(this IList self) + { + var result = new int[self.Count]; + for (var i = 1; i < self.Count; ++i) + { + result[i] = result[i - 1] + self[i - 1]; + } + return result; + } + /// /// Returns the top of a stack, or the default T value if none is present. /// From 463a07af4aac1892d97892eec40702608c93164f Mon Sep 17 00:00:00 2001 From: simon Date: Tue, 16 Apr 2024 16:00:49 -0400 Subject: [PATCH 190/204] index of methods --- src/cs/util/Vim.Util/CollectionExtensions.cs | 22 ++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/cs/util/Vim.Util/CollectionExtensions.cs b/src/cs/util/Vim.Util/CollectionExtensions.cs index 79712ba0..87339b07 100644 --- a/src/cs/util/Vim.Util/CollectionExtensions.cs +++ b/src/cs/util/Vim.Util/CollectionExtensions.cs @@ -17,6 +17,28 @@ public static ILookup ToVimLookup(this IEnumerable => input.ToDictionary(keyFunc, x => x).ToLookup(); + /// + /// Returns the index of the first element matching the given item. + /// + public static int IndexOf(this IArray self, T item) where T : IEquatable + => self.IndexOf(x => x.Equals(item)); + + /// + /// Returns the index of the first element matching the given item. + /// + public static int IndexOf(this IArray self, Func predicate) + { + for (var i = 0; i < self.Count; ++i) + { + if (predicate(self[i])) + return i; + } + + return -1; + } + + + /// /// Returns an IEnumerable containing only indices of the array for which the function satisfies a specific predicate. /// From d6db1d9564ca4c248310fefd4ac5822b28cc4082 Mon Sep 17 00:00:00 2001 From: simon Date: Tue, 16 Apr 2024 16:02:27 -0400 Subject: [PATCH 191/204] fix --- src/cs/util/Vim.Util/CollectionExtensions.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cs/util/Vim.Util/CollectionExtensions.cs b/src/cs/util/Vim.Util/CollectionExtensions.cs index 87339b07..92404f98 100644 --- a/src/cs/util/Vim.Util/CollectionExtensions.cs +++ b/src/cs/util/Vim.Util/CollectionExtensions.cs @@ -20,15 +20,15 @@ public static ILookup ToVimLookup(this IEnumerable /// /// Returns the index of the first element matching the given item. /// - public static int IndexOf(this IArray self, T item) where T : IEquatable + public static int IndexOf(this T[] self, T item) where T : IEquatable => self.IndexOf(x => x.Equals(item)); /// /// 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 T[] self, Func predicate) { - for (var i = 0; i < self.Count; ++i) + for (var i = 0; i < self.Length; ++i) { if (predicate(self[i])) return i; From a5a9b43032a174a23f7da54a9e6b82125f4a7752 Mon Sep 17 00:00:00 2001 From: simon Date: Wed, 17 Apr 2024 07:58:31 -0400 Subject: [PATCH 192/204] removed linqarray --- .../Vim.LinqArray.Tests/LinqArrayTests.cs | 72 -- src/cs/linqarray/Vim.LinqArray/LinqArray.cs | 1021 ----------------- .../Vim.Math3D/{LinqUtil.cs => AABoxUtil.cs} | 6 +- src/cs/vim-format.sln | 16 - .../Vim.Format.Core/Vim.Format.Core.csproj | 1 - .../Vim.Format.Vimx.Conversion.csproj | 3 +- src/cs/vim/Vim.Format/Vim.Format.csproj | 1 - 7 files changed, 3 insertions(+), 1117 deletions(-) delete mode 100644 src/cs/linqarray/Vim.LinqArray.Tests/LinqArrayTests.cs delete mode 100644 src/cs/linqarray/Vim.LinqArray/LinqArray.cs rename src/cs/math3d/Vim.Math3D/{LinqUtil.cs => AABoxUtil.cs} (57%) diff --git a/src/cs/linqarray/Vim.LinqArray.Tests/LinqArrayTests.cs b/src/cs/linqarray/Vim.LinqArray.Tests/LinqArrayTests.cs deleted file mode 100644 index 4f85ca04..00000000 --- a/src/cs/linqarray/Vim.LinqArray.Tests/LinqArrayTests.cs +++ /dev/null @@ -1,72 +0,0 @@ -using NUnit.Framework; -using System; - -namespace Vim.LinqArray.Tests -{ - public class LinqArrayTests - { - public static int[] ArrayToTen = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; - public static IArray RangeToTen = 10.Range(); - public static IArray BuildToTen = LinqArray.Build(0, x => x + 1, x => x < 10); - - public static object[] TensData = { ArrayToTen.ToIArray(), RangeToTen, BuildToTen }; - - [TestCaseSource(nameof(TensData))] - public void CheckTens(IArray tens) - { - Assert.IsTrue(tens.SequenceEquals(ArrayToTen.ToIArray())); - Assert.AreEqual(0, tens.First()); - Assert.AreEqual(9, tens.Last()); - Assert.AreEqual(45, tens.Aggregate(0, (a, b) => a + b)); - Assert.AreEqual(10, tens.Count); - Assert.AreEqual(5, tens[5]); - Assert.AreEqual(5, tens.ElementAt(5)); - - var ones = 1.Repeat(9); - var diffs = tens.ZipEachWithNext((x, y) => y - x); - Assert.IsTrue(ones.SequenceEquals(diffs)); - Assert.IsFalse(ones.SequenceEquals(tens)); - - var indices = tens.Indices(); - Assert.IsTrue(tens.SequenceEquals(indices)); - Assert.IsTrue(tens.SequenceEquals(tens.SelectByIndex(indices))); - Assert.IsTrue(tens.Reverse().SequenceEquals(tens.SelectByIndex(indices.Reverse()))); - - var sum = 0; - foreach (var x in tens.ToEnumerable()) - { - sum += x; - } - foreach (var x in tens.ToEnumerable()) - { - Console.WriteLine(x.ToString()); - } - Assert.AreEqual(45, sum); - Assert.AreEqual(0, tens.First()); - Assert.True(tens.All(x => x < 10)); - Assert.True(tens.Any(x => x < 5)); - Assert.AreEqual(5, tens.CountWhere(x => x % 2 == 0)); - Assert.AreEqual(0, tens.Reverse().Last()); - Assert.AreEqual(0, tens.Reverse().Reverse().First()); - var split = tens.Split(LinqArray.Create(3, 6)); - Assert.AreEqual(3, split.Count); - - var batch = tens.SubArrays(3); - Assert.AreEqual(4, batch.Count); - Assert.True(batch[0].SequenceEquals(LinqArray.Create(0, 1, 2))); - Assert.True(batch[3].SequenceEquals(LinqArray.Create(9))); - - var batch2 = tens.Take(9).SubArrays(3); - Assert.AreEqual(3, batch2.Count); - - var counts = split.Select(x => x.Count); - Assert.True(counts.SequenceEquals(LinqArray.Create(3, 3, 4))); - var indices2 = counts.Accumulate((x, y) => x + y); - Assert.True(indices2.SequenceEquals(LinqArray.Create(3, 6, 10))); - var indices3 = counts.PostAccumulate((x, y) => x + y); - Assert.True(indices3.SequenceEquals(LinqArray.Create(0, 3, 6, 10))); - var flattened = split.Flatten(); - Assert.True(flattened.SequenceEquals(tens)); - } - } -} diff --git a/src/cs/linqarray/Vim.LinqArray/LinqArray.cs b/src/cs/linqarray/Vim.LinqArray/LinqArray.cs deleted file mode 100644 index 3e392e0e..00000000 --- a/src/cs/linqarray/Vim.LinqArray/LinqArray.cs +++ /dev/null @@ -1,1021 +0,0 @@ -// MIT License - Copyright 2019 (C) VIMaec, LLC. -// MIT License - Copyright (C) Ara 3D, Inc. -// This file is subject to the terms and conditions defined in -// file 'LICENSE.txt', which is part of this source code package. -// -// LinqArray.cs -// A library for working with pure functional arrays, using LINQ style extension functions. -// Based on code that originally appeared in https://www.codeproject.com/Articles/140138/Immutable-Array-for-NET - -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.CompilerServices; -using System.Text; -using System.Threading; -using System.Threading.Tasks; - -namespace Vim.LinqArray -{ - /// - /// Represents an immutable array with expected O(1) complexity when - /// retrieving the number of items. - /// - public interface IArray - { - int Count { get; } - } - - /// - /// Represents an immutable array with expected O(1) complexity when - /// retrieving the number of items and random element access. - /// - public interface IArray : IArray - { - T this[int n] { get; } - } - - /// - /// Implements an IArray via a function and a count. - /// - public class FunctionalArray : IArray - { - public readonly Func Function; - - public int Count - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get; - } - - public T this[int n] - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => Function(n); - } - public FunctionalArray(int count, Func function) - => (Count, Function) = (count, function); - } - - /// - /// Implements an IArray from a System.Array. - /// - public class ArrayAdapter : IArray - { - public readonly T[] Array; - - public int Count - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get; - } - - public T this[int n] - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => Array[n]; - } - public ArrayAdapter(T[] xs) { Count = xs.Length; Array = xs; } - } - - /// - /// Extension functions for working on any object implementing IArray. This overrides - /// many of the Linq functions providing better performance. - /// - public static class LinqArray - { - /// - /// Helper function for creating an IArray from the arguments. - /// - public static IArray Create(params T[] self) - => self.ToIArray(); - - /// - /// A helper function to enable IArray to support IEnumerable - /// - public static IEnumerable ToEnumerable(this IArray self) - => Enumerable.Range(0, self.Count).Select(self.ElementAt); - - public static IArray ForEach(this IArray xs, Action f) - { - for (var i = 0; i < xs.Count; ++i) - f(xs[i]); - return xs; - } - - /// - /// Creates an IArray with the given number of items, - /// and uses the function to return items. - /// - public static IArray Select(this int count, Func f) - => new FunctionalArray(count, f); - - /// - /// Converts any implementation of IList (e.g. Array/List) to an IArray. - /// - public static IArray ToIArray(this IList self) - => self.Count.Select(i => self[i]); - - /// - /// Converts any implementation of IList (e.g. Array/List) to an IArray. - /// - public static IArray ToIArray(this T[] self) - => new ArrayAdapter(self); - - /// - /// Converts any implementation of IEnumerable to an IArray - /// - public static IArray ToIArray(this IEnumerable self) - => self is IList xs ? xs.ToIArray() : self.ToArray().ToIArray(); - - /// - /// Creates an IArray by repeating the given item a number of times. - /// - public static IArray Repeat(this T self, int count) - => Select(count, i => self); - - /// - /// Creates an IArray by repeating each item in the source a number of times. - /// - public static IArray RepeatElements(this IArray self, int count) - => Select(count, i => self[i / count]); - - /// - /// Creates an IArray starting with a seed value, and applying a function - /// to each individual member of the array. This is eagerly evaluated. - /// - public static IArray Generate(this T init, int count, Func f) - { - var r = new T[count]; - for (var i = 0; i < count; ++i) - { - r[i] = init; - init = f(init); - } - return r.ToIArray(); - } - - /// - /// Creates an IArray of integers from zero up to one less than the given number. - /// - public static IArray Range(this int self) - => Select(self, i => i); - - /// - /// Returns the first item in the array. - /// - public static T First(this IArray self, T @default = default) - => self.IsEmpty() ? @default : self[0]; - - /// - /// Returns the last item in the array - /// - public static T Last(this IArray self, T @default = default) - => self.IsEmpty() ? @default : self[self.Count - 1]; - - /// - /// Returns true if and only if the argument is a valid index into the array. - /// - public static bool InRange(this IArray self, int n) - => n >= 0 && n < self.Count; - - /// - /// A mnemonic for "Any()" that returns false if the count is greater than zero - /// - public static bool IsEmpty(this IArray self) - => !self.Any(); - - /// - /// Returns true if there are any elements in the array. - /// - public static bool Any(this IArray self) - => self.Count != 0; - - /// - /// Converts the IArray into a system array. - /// - public static T[] ToArray(this IArray self) - => self.CopyTo(new T[self.Count]); - - /// - /// Converts the IArray into a system List. - /// - public static List ToList(this IArray self) - => self.ToEnumerable().ToList(); - - /// - /// Converts the array into a function that returns values from an integer, returning a default value if out of range. - /// - public static Func ToFunction(this IArray self, T def = default) - => i => self.InRange(i) ? self[i] : def; - - /// - /// Converts the array into a predicate (a function that returns true or false) based on the truth of the given value. - /// - public static Func ToPredicate(this IArray self) - => self.ToFunction(); - - /// - /// Adds all elements of the array to the target collection. - /// - public static U AddTo(this IArray self, U other) where U : ICollection - { - self.ForEach(other.Add); - return other; - } - - /// - /// Copies all elements of the array to the target list or array, starting at the provided index. - /// - public static U CopyTo(this IArray self, U other, int destIndex = 0) where U : IList - { - for (var i = 0; i < self.Count; ++i) - other[i + destIndex] = self[i]; - return other; - } - - /// - /// Returns an array generated by applying a function to each element. - /// - public static IArray Select(this IArray self, Func f) - => Select(self.Count, i => f(self[i])); - - /// - /// Returns an array generated by applying a function to each element. - /// - public static IArray Select(this IArray self, Func f) - => Select(self.Count, i => f(self[i], i)); - - /// - /// Returns an array generated by applying a function to each element. - /// - public static IArray SelectIndices(this IArray self, Func f) - => self.Count.Select(f); - - /// - /// Converts an array of array into a flattened array. Each array is assumed to be of size n. - /// - public static IArray Flatten(this IArray> self, int n) - => Select(self.Count * n, i => self[i / n][i % n]); - - /// - /// Converts an array of array into a flattened array. - /// - public static IArray Flatten(this IArray> self) - { - var counts = self.Select(x => x.Count).PostAccumulate((x, y) => x + y); - var r = new T[counts.Last()]; - var i = 0; - foreach (var xs in self.ToEnumerable()) - xs.CopyTo(r, counts[i++]); - return r.ToIArray(); - } - - /// - /// Returns an array of tuple where each element of the initial array is paired with its index. - /// - public static IArray<(T value, int index)> ZipWithIndex(this IArray self) - => self.Select((v, i) => (v, i)); - - /// - /// Returns an array from an array of arrays, where the number of sub-elements is the same for reach array and is known. - /// - public static IArray SelectMany(this IArray> self, int count) - => Select(self.Count, i => self[i / count][i % count]); - - /// - /// Returns an array given a function that generates an IArray from each member. Eager evaluation. - /// - public static IArray SelectMany(this IArray self, Func> func) - { - var xs = new List(); - for (var i = 0; i < self.Count; ++i) - func(self[i]).AddTo(xs); - return xs.ToIArray(); - } - - /// - /// Returns an array given a function that generates an IArray from each member. Eager evaluation. - /// - public static IArray SelectMany(this IArray self, Func> func) - { - var xs = new List(); - for (var i = 0; i < self.Count; ++i) - func(self[i], i).AddTo(xs); - return xs.ToIArray(); - } - - /// - /// Returns an array given a function that generates a tuple from each member. Eager evaluation. - /// - public static IArray SelectMany(this IArray self, Func> func) - { - var r = new U[self.Count * 2]; - for (var i = 0; i < self.Count; ++i) - { - var tmp = func(self[i]); - r[i * 2] = tmp.Item1; - r[i * 2 + 1] = tmp.Item2; - } - - return r.ToIArray(); - } - - /// - /// Returns an array given a function that generates a tuple from each member. Eager evaluation. - /// - public static IArray SelectMany(this IArray self, Func> func) - { - var r = new U[self.Count * 3]; - for (var i = 0; i < self.Count; ++i) - { - var tmp = func(self[i]); - r[i * 3] = tmp.Item1; - r[i * 3 + 1] = tmp.Item2; - r[i * 3 + 2] = tmp.Item3; - } - return r.ToIArray(); - } - - /// - /// Returns an array given a function that generates a tuple from each member. Eager evaluation. - /// - public static IArray SelectMany(this IArray self, Func> func) - { - var r = new U[self.Count * 4]; - for (var i = 0; i < self.Count; ++i) - { - var tmp = func(self[i]); - r[i * 4] = tmp.Item1; - r[i * 4 + 1] = tmp.Item2; - r[i * 4 + 2] = tmp.Item3; - r[i * 4 + 3] = tmp.Item4; - } - return r.ToIArray(); - } - - /// - /// Returns an array generated by applying a function to corresponding pairs of elements in both arrays. - /// - public static IArray Zip(this IArray self, IArray other, Func f) - => Select(Math.Min(self.Count, other.Count), i => f(self[i], other[i])); - - /// - /// Returns an array generated by applying a function to corresponding pairs of elements in both arrays. - /// - public static IArray Zip(this IArray self, IArray other, Func f) - => Select(Math.Min(self.Count, other.Count), i => f(self[i], other[i], i)); - - /// - /// Returns an array generated by applying a function to corresponding pairs of elements in both arrays. - /// - public static IArray Zip(this IArray self, IArray other, IArray other2, Func f) - => Select(Math.Min(Math.Min(self.Count, other.Count), other2.Count), i => f(self[i], other[i], other2[i])); - - /// - /// Returns an array generated by applying a function to corresponding pairs of elements in both arrays. - /// - public static IArray Zip(this IArray self, IArray other, IArray other2, Func f) - => Select(Math.Min(Math.Min(self.Count, other.Count), other2.Count), i => f(self[i], other[i], other2[i], i)); - - /// - /// Returns an array generated by applying a function to corresponding pairs of elements in both arrays. - /// - public static IArray Zip(this IArray self, IArray other, IArray other2, IArray other3, Func f) - => Select(Math.Min(Math.Min(self.Count, other.Count), Math.Min(other2.Count, other3.Count)), i => f(self[i], other[i], other2[i], other3[i])); - - /// - /// Returns an array generated by applying a function to corresponding pairs of elements in both arrays. - /// - public static IArray Zip(this IArray self, IArray other, IArray other2, IArray other3, Func f) - => Select(Math.Min(Math.Min(self.Count, other.Count), Math.Min(other2.Count, other3.Count)), i => f(self[i], other[i], other2[i], other3[i], i)); - - /// - /// Applies a function to each element in the list paired with the next one. - /// Used to implement adjacent differences for example. - /// - public static IArray ZipEachWithNext(this IArray self, Func f) - => self.Zip(self.Skip(), f); - - /// - /// Returns an IEnumerable containing only elements of the array for which the function returns true on the index. - /// An IArray is not created automatically because it is an expensive operation that is potentially unneeded. - /// - public static IEnumerable WhereIndices(this IArray self, Func f) - => self.Where((x, i) => f(i)); - - /// - /// Returns an IEnumerable containing only elements of the array for which the corresponding mask is true. - /// An IArray is not created automatically because it is an expensive operation that is potentially unneeded. - /// - public static IEnumerable Where(this IArray self, IArray mask) - => self.WhereIndices(mask.ToPredicate()); - - /// - /// Returns an IEnumerable containing only elements of the array for which the corresponding predicate is true. - /// - public static IEnumerable Where(this IArray self, Func predicate) - => self.ToEnumerable().Where(predicate); - - /// - /// Returns an IEnumerable containing only elements of the array for which the corresponding predicate is true. - /// - public static IEnumerable Where(this IArray self, Func predicate) - => self.ToEnumerable().Where(predicate); - - /// - /// Returns an IEnumerable containing only indices of the array for which the function satisfies a specific predicate. - /// An IArray is not created automatically because it is an expensive operation that is potentially unneeded. - /// - public static IEnumerable IndicesWhere(this IArray self, Func f) - => self.Indices().Where(i => f(self[i])); - - /// - /// Returns an IEnumerable containing only indices of the array for which the function satisfies a specific predicate. - /// An IArray is not created automatically because it is an expensive operation that is potentially unneeded. - /// - public static IEnumerable IndicesWhere(this IArray self, Func f) - => self.IndicesWhere(i => f(self[i], i)); - - /// - /// Returns an IEnumerable containing only indices of the array for which the function satisfies a specific predicate. - /// An IArray is not created automatically because it is an expensive operation that is potentially unneeded. - /// - public static IEnumerable IndicesWhere(this IArray self, Func f) - => self.Indices().Where(i => f(i)); - - /// - /// Returns an IEnumerable containing only indices of the array for which booleans in the mask are true. - /// An IArray is not created automatically because it is an expensive operation that is potentially unneeded. - /// - public static IEnumerable IndicesWhere(this IArray self, IArray mask) - => self.IndicesWhere(mask.ToPredicate()); - - /// - /// Shortcut for ToEnumerable.Aggregate() - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static U Aggregate(this IArray self, U init, Func func) - { - for (var i = 0; i < self.Count; ++i) - init = func(init, self[i]); - return init; - } - - /// - /// Shortcut for ToEnumerable.Aggregate() - /// - public static U Aggregate(this IArray self, Func func) - => Aggregate(self, default, func); - - /// - /// Shortcut for ToEnumerable.Aggregate() - /// - public static U Aggregate(this IArray self, U init, Func func) - { - for (var i = 0; i < self.Count; ++i) - init = func(init, self[i], i); - return init; - } - - /// - /// Shortcut for ToEnumerable.Aggregate() - /// - public static U Aggregate(this IArray self, Func func) - => Aggregate(self, default, func); - - /// - /// Returns a new array containing the elements in the range of from to to. - /// - public static IArray Slice(this IArray self, int from, int to) - => Select(to - from, i => self[i + from]); - - /// - /// Returns an array of SubArrays of size "size" - /// the last items that cannot fill an arrat if size "size" will be ignored - /// - public static IArray> SubArraysFixed(this IArray self, int size) - => (self.Count / size).Select(i => self.SubArray(i, size)); - - - /// Returns an array of SubArrays of size "size" plus extras - /// The extra array is of size count % size if present - public static IArray> SubArrays(this IArray self, int size) - => self.Count % size == 0 - ? self.SubArraysFixed(size) - : self.SubArraysFixed(size).Append(self.TakeLast(self.Count % size)); - - /// - /// Returns n elements of the list starting from a given index. - /// - public static IArray SubArray(this IArray self, int from, int count) - => self.Slice(from, count + from); - - /// - /// Returns elements of the array between from and skipping every stride element. - /// - public static IArray Slice(this IArray self, int from, int to, int stride) - => Select(to - from / stride, i => self[i * stride + from]); - - /// - /// Returns a new array containing the elements by taking every nth item. - /// - public static IArray Stride(this IArray self, int n) - => Select(self.Count / n, i => self[i * n % self.Count]); - - /// - /// Returns a new array containing just the first n items. - /// - public static IArray Take(this IArray self, int n) - => self.Slice(0, n); - - /// - /// Returns a new array containing just at most n items. - /// - public static IArray TakeAtMost(this IArray self, int n) - => self.Count > n ? self.Slice(0, n) : self; - - /// - /// Returns a new array containing the elements after the first n elements. - /// - public static IArray Skip(this IArray self, int n = 1) - => self.Slice(n, self.Count); - - /// - /// Returns a new array containing the last n elements. - /// - public static IArray TakeLast(this IArray self, int n = 1) - => self.Skip(self.Count - n); - - /// - /// Returns a new array containing all elements excluding the last n elements. - /// - public static IArray DropLast(this IArray self, int n = 1) - => self.Count > n ? self.Take(self.Count - n) : self.Empty(); - - /// - /// Returns a new array by remapping indices - /// - public static IArray MapIndices(this IArray self, Func f) - => self.Count.Select(i => self[f(i)]); - - /// - /// Returns a new array that reverses the order of elements - /// - public static IArray Reverse(this IArray self) - => self.MapIndices(i => self.Count - 1 - i); - - /// - /// Uses the provided indices to select elements from the array. - /// - public static IArray SelectByIndex(this IArray self, IArray indices) - => indices.Select(i => self[i]); - - /// - /// Uses the array as indices to select elements from the other array. - /// - public static IArray Choose(this IArray indices, IArray values) - => values.SelectByIndex(indices); - - /// - /// Given indices of sub-arrays groups, this will convert it to arrays of indices (e.g. [0, 2] with a group size of 3 becomes [0, 1, 2, 6, 7, 8]) - /// - public static IArray GroupIndicesToIndices(this IArray indices, int groupSize) - => groupSize == 1 - ? indices : (indices.Count * groupSize).Select(i => indices[i / groupSize] * groupSize + i % groupSize); - - /// - /// Return the array separated into a series of groups (similar to DictionaryOfLists) - /// based on keys created by the given keySelector - /// - public static IEnumerable> GroupBy(this IArray self, Func keySelector) - => self.ToEnumerable().GroupBy(keySelector); - - /// - /// Return the array separated into a series of groups (similar to DictionaryOfLists) - /// based on keys created by the given keySelector and elements chosen by the element selector - /// - public static IEnumerable> GroupBy(this IArray self, Func keySelector, Func elementSelector) - => self.ToEnumerable().GroupBy(keySelector, elementSelector); - - /// - /// Uses the provided indices to select groups of contiguous elements from the array. - /// This is equivalent to self.SubArrays(groupSize).SelectByIndex(indices).SelectMany(); - /// - public static IArray SelectGroupsByIndex(this IArray self, int groupSize, IArray indices) - => self.SelectByIndex(indices.GroupIndicesToIndices(groupSize)); - - /// - /// Similar to take, if count is less than the number of items in the array, otherwise uses a modulo operation. - /// - public static IArray Resize(this IArray self, int count) - => Select(count, i => self[i % self.Count]); - - /// - /// Returns an array of the same type with no elements. - /// - public static IArray Empty(this IArray self) - => self.Take(0); - - /// - /// Returns an array of the same type with no elements. - /// - public static IArray Empty() - => default(T).Repeat(0); - - /// - /// Returns a sequence of integers from 0 to 1 less than the number of items in the array, representing indicies of the array. - /// - public static IArray Indices(this IArray self) - => self.Count.Range(); - - /// - /// Converts an array of elements into a string representation - /// - public static string Join(this IArray self, string sep = " ") - => self.Aggregate(new StringBuilder(), (sb, x) => sb.Append(x).Append(sep)).ToString(); - - /// - /// Concatenates the contents of one array with another. - /// - public static IArray Concatenate(this IArray self, IArray other) - => Select(self.Count + other.Count, i => i < self.Count ? self[i] : other[i - self.Count]); - - /// - /// Returns the index of the first element matching the given item. - /// - public static int IndexOf(this IArray self, T item) where T : IEquatable - => self.IndexOf(x => x.Equals(item)); - - /// - /// Returns the index of the first element matching the given item. - /// - public static int IndexOf(this IArray self, Func predicate) - { - for (var i = 0; i < self.Count; ++i) - { - if (predicate(self[i])) - return i; - } - - return -1; - } - - /// - /// Returns the index of the last element matching the given item. - /// - public static int LastIndexOf(this IArray self, T item) where T : IEquatable - { - var n = self.Reverse().IndexOf(item); - return n < 0 ? n : self.Count - 1 - n; - } - - /// - /// Returns an array that is one element shorter that subtracts each element from its previous one. - /// - public static IArray AdjacentDifferences(this IArray self) - => self.ZipEachWithNext((a, b) => b - a); - - /// - /// Creates a new array that concatenates a unit item list of one item after it. - /// Repeatedly calling Append would result in significant performance degradation. - /// - public static IArray Append(this IArray self, T x) - => (self.Count + 1).Select(i => i < self.Count ? self[i] : x); - - /// - /// Creates a new array that concatenates the given items to itself. - /// - public static IArray Append(this IArray self, params T[] x) - => self.Concatenate(x.ToIArray()); - - /// - /// Creates a new array that concatenates a unit item list of one item before it - /// Repeatedly calling Prepend would result in significant performance degradation. - /// - public static IArray Prepend(this IArray self, T x) - => (self.Count + 1).Select(i => i == 0 ? x : self[i - 1]); - - /// - /// Returns the element at the nth position, where n is modulo the number of items in the arrays. - /// - public static T ElementAt(this IArray self, int n) - => self[n]; - - /// - /// Returns the element at the nth position, where n is modulo the number of items in the arrays. - /// - public static T ElementAtModulo(this IArray self, int n) - => self.ElementAt(n % self.Count); - - /// - /// Returns the Nth element of the array, or a default value if out of range/ - /// - public static T ElementAtOrDefault(this IArray xs, int n, T defaultValue = default) - => xs != null && n >= 0 && n < xs.Count ? xs[n] : defaultValue; - - /// - /// Counts all elements in an array that satisfy a predicate - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int CountWhere(this IArray self, Func p) - => self.Aggregate(0, (n, x) => n + (p(x) ? 1 : 0)); - - /// - /// Counts all elements in an array that are equal to true - /// - public static int CountWhere(this IArray self) - => self.CountWhere(x => x); - - /// - /// Counts all elements in an array that are equal to a value - /// - public static int CountWhere(this IArray self, T val) where T : IEquatable - => self.CountWhere(x => x.Equals(val)); - - /// - /// Returns the minimum element in the list - /// - public static T Min(this IArray self) where T : IComparable - { - if (self.Count == 0) throw new ArgumentOutOfRangeException(); - return self.Aggregate(self[0], (a, b) => a.CompareTo(b) < 0 ? a : b); - } - - /// - /// Returns the maximum element in the list - /// - public static T Max(this IArray self) where T : IComparable - { - if (self.Count == 0) throw new ArgumentOutOfRangeException(); - return self.Aggregate(self[0], (a, b) => a.CompareTo(b) > 0 ? a : b); - } - - /// - /// Applies a function (like "+") to each element in the series to create an effect similar to partial sums. - /// - public static IArray Accumulate(this IArray self, Func f) - { - var n = self.Count; - var r = new T[n]; - if (n == 0) return r.ToIArray(); - var prev = r[0] = self[0]; - for (var i = 1; i < n; ++i) - { - prev = r[i] = f(prev, self[i]); - } - return r.ToIArray(); - } - - /// - /// Applies a function (like "+") to each element in the series to create an effect similar to partial sums. - /// The first value in the array will be zero. - /// - public static IArray PostAccumulate(this IArray self, Func f, T init = default) - { - var n = self.Count; - var r = new T[n + 1]; - var prev = r[0] = init; - if (n == 0) return r.ToIArray(); - for (var i = 0; i < n; ++i) - { - prev = r[i + 1] = f(prev, self[i]); - } - return r.ToIArray(); - } - - /// - /// Returns true if the two lists are the same length, and the elements are the same. - /// - public static bool SequenceEquals(this IArray self, IArray other) where T : IEquatable - => self == other || (self.Count == other.Count && self.Zip(other, (x, y) => x?.Equals(y) ?? y == null).All(x => x)); - - /// - /// Creates a readonly array from a seed value, by applying a function - /// - public static IArray Build(T init, Func next, Func hasNext) - { - var r = new List(); - while (hasNext(init)) - { - r.Add(init); - init = next(init); - } - return r.ToIArray(); - } - - /// - /// Creates a readonly array from a seed value, by applying a function - /// - public static IArray Build(T init, Func next, Func hasNext) - { - var i = 0; - var r = new List(); - while (hasNext(init, i)) - { - r.Add(init); - init = next(init, ++i); - } - return r.ToIArray(); - } - - /// - /// Creates an array of arrays, split at the given indices - /// - public static IArray> Split(this IArray self, IArray indices) - => indices.Prepend(0).Zip(indices.Append(self.Count), (x, y) => self.Slice(x, y)); - - /// - /// Creates an array of arrays, split at the given index. - /// - public static IArray> Split(this IArray self, int index) - => Create(self.Take(index), self.Skip(index)); - - /// - /// Splits an array of tuples into a tuple of array - /// - public static (IArray, IArray) Unzip(this IArray<(T1, T2)> self) - => (self.Select(pair => pair.Item1), self.Select(pair => pair.Item2)); - - - /// - /// Returns true if the predicate is true for all of the elements in the array - /// - public static bool All(this IArray self, Func predicate) - => self.ToEnumerable().All(predicate); - - /// - /// Returns true if the predicate is true for any of the elements in the array - /// - public static bool Any(this IArray self, Func predicate) - => self.ToEnumerable().Any(predicate); - - /// - /// Sums items in an array using a selector function that returns integers. - /// - public static long Sum(this IArray self, Func func) - => self.Aggregate(0L, (init, x) => init + func(x)); - - /// - /// Sums items in an array using a selector function that returns doubles. - /// - public static double Sum(this IArray self, Func func) - => self.Aggregate(0.0, (init, x) => init + func(x)); - - /// - /// Forces evaluation (aka reification) of the array by creating a copy in memory. - /// This is useful as a performance optimization, or to force the objects to exist permanently. - /// - public static IArray Evaluate(this IArray x) - => (x is ArrayAdapter) ? x : x.ToArray().ToIArray(); - - /// - /// Forces evaluation (aka reification) of the array in parallel. - /// - public static IArray EvaluateInParallel(this IArray x) - => (x is ArrayAdapter) ? x : x.ToArrayInParallel().ToIArray(); - - /// - /// Converts to a regular array in paralle; - /// - /// - /// - /// - public static T[] ToArrayInParallel(this IArray xs) - { - if (xs.Count == 0) - return Array.Empty(); - - if (xs.Count < Environment.ProcessorCount) - return xs.ToArray(); - - var r = new T[xs.Count]; - var partitioner = Partitioner.Create(0, xs.Count, xs.Count / Environment.ProcessorCount); - - Parallel.ForEach(partitioner, (range, state) => - { - for (var i = range.Item1; i < range.Item2; ++i) - r[i] = xs[i]; - }); - return r; - } - - /// - /// Maps pairs of elements to a new array. - /// - public static IArray SelectPairs(this IArray xs, Func f) - => (xs.Count / 2).Select(i => f(xs[i * 2], xs[i * 2 + 1])); - - /// - /// Maps every 3 elements to a new array. - /// - public static IArray SelectTriplets(this IArray xs, Func f) - => (xs.Count / 3).Select(i => f(xs[i * 3], xs[i * 3 + 1], xs[i * 3 + 2])); - - /// - /// Maps every 4 elements to a new array. - /// - public static IArray SelectQuartets(this IArray xs, Func f) - => (xs.Count / 4).Select(i => f(xs[i * 4], xs[i * 4 + 1], xs[i * 4 + 2], xs[i * 4 + 3])); - - /// - /// Returns the number of unique instances of elements in the array. - /// - public static int CountUnique(this IArray xs) - => xs.ToEnumerable().Distinct().Count(); - - /// - /// Returns elements in order. - /// - public static IArray Sort(this IArray xs) where T : IComparable - => xs.ToEnumerable().OrderBy(x => x).ToIArray(); - - /// - /// Given an array of elements of type T casts them to a U - /// - public static IArray Cast(this IArray xs) where T : U - => xs.Select(x => (U)x); - - /// - /// Returns true if the value is present in the array. - /// - public static bool Contains(this IArray xs, T value) - => xs.Any(x => x.Equals(value)); - - - - - public static ILookup ToLookup(this IArray input, Func keyFunc, Func valueFunc) - => input.ToEnumerable().ToLookup(keyFunc, valueFunc); - - - public static ILookup ToLookup(this IArray input, Func keyFunc) - => input.ToEnumerable().ToLookup(keyFunc, x => x); - - public static T FirstOrDefault(this IArray xs) - => xs.Count > 0 ? xs[0] : default; - - public static T FirstOrDefault(this IArray xs, T @default) - => xs.Count > 0 ? xs[0] : @default; - - public static T FirstOrDefault(this IArray xs, Func predicate) - => xs.Where(predicate).FirstOrDefault(); - - public static IArray ToLongs(this IArray xs) - => xs.Select(x => (long)x); - - public static IArray PrefixSums(this IArray self) - => self.ToLongs().PrefixSums(); - - public static IArray PrefixSums(this IArray self) - => self.Scan(0f, (a, b) => a + b); - - 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) - { - if (self.Count == 0) - return Empty(); - var r = new U[self.Count]; - for (var i = 0; i < self.Count; ++i) - init = r[i] = scanFunc(init, self[i]); - return r.ToIArray(); - } - - public static IArray PrefixSums(this IArray counts) - => counts.Scan(0L, (a, b) => a + b); - - // Similar to prefix sums, but starts at zero. - // r[i] = Sum(count[0 to i]) - public static IArray CountsToOffsets(this IArray counts) - { - var r = new int[counts.Count]; - for (var i = 1; i < counts.Count; ++i) - r[i] = r[i - 1] + counts[i - 1]; - return r.ToIArray(); - } - - public static IArray OffsetsToCounts(this IArray offsets, int last) - => offsets.Indices().Select(i => i < offsets.Count - 1 ? offsets[i + 1] - offsets[i] : last - offsets[i]); - - public static IArray SetElementAt(this IArray self, int index, T value) - => self.SelectIndices(i => i == index ? value : self[i]); - - public static IArray SetFirstElementWhere(this IArray self, Func predicate, T value) - { - var index = self.IndexOf(predicate); - if (index < 0) - return self; - return self.SetElementAt(index, value); - } - - public static T SafeGet(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/math3d/Vim.Math3D/LinqUtil.cs b/src/cs/math3d/Vim.Math3D/AABoxUtil.cs similarity index 57% rename from src/cs/math3d/Vim.Math3D/LinqUtil.cs rename to src/cs/math3d/Vim.Math3D/AABoxUtil.cs index c105f6e4..e5d3b854 100644 --- a/src/cs/math3d/Vim.Math3D/LinqUtil.cs +++ b/src/cs/math3d/Vim.Math3D/AABoxUtil.cs @@ -1,10 +1,8 @@ -using System; -using System.Collections.Generic; -using System.Text; +using System.Collections.Generic; namespace Vim.Math3d { - public static class LinqUtil + public static class AABoxUtil { public static AABox ToAABox(this IEnumerable self) => AABox.Create(self); diff --git a/src/cs/vim-format.sln b/src/cs/vim-format.sln index 6939a1f3..97edf442 100644 --- a/src/cs/vim-format.sln +++ b/src/cs/vim-format.sln @@ -5,12 +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("{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}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vim.LinqArray.Tests", "linqarray\Vim.LinqArray.Tests\Vim.LinqArray.Tests.csproj", "{461788B0-072C-485F-82C0-F83CCC86F95D}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "math3d", "math3d", "{9BD3CC85-97FD-4093-AA11-58FE405B0F65}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vim.Math3D", "math3d\Vim.Math3D\Vim.Math3D.csproj", "{1086F24E-32C8-4261-9B06-A364EEE71DEF}" @@ -59,14 +53,6 @@ Global Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {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 - {07CA1F46-21DA-4C22-A8CB-52D526D51C94}.Release|Any CPU.Build.0 = Release|Any CPU - {461788B0-072C-485F-82C0-F83CCC86F95D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {461788B0-072C-485F-82C0-F83CCC86F95D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {461788B0-072C-485F-82C0-F83CCC86F95D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {461788B0-072C-485F-82C0-F83CCC86F95D}.Release|Any CPU.Build.0 = Release|Any CPU {1086F24E-32C8-4261-9B06-A364EEE71DEF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {1086F24E-32C8-4261-9B06-A364EEE71DEF}.Debug|Any CPU.Build.0 = Debug|Any CPU {1086F24E-32C8-4261-9B06-A364EEE71DEF}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -140,8 +126,6 @@ Global HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution - {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} {1CC20AA4-11F1-4548-9285-FD24D42190FB} = {9BD3CC85-97FD-4093-AA11-58FE405B0F65} {22278D91-27D7-4A84-8170-5FFB77A70C1F} = {D639C635-01D1-48C4-89B5-1FD70F1AFEE9} 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 f2908353..951143a3 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/Vim.Format.Vimx.Conversion.csproj b/src/cs/vim/Vim.Format.Vimx.Conversion/Vim.Format.Vimx.Conversion.csproj index 4e1f53c1..05a0161b 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 @@ -1,11 +1,10 @@ - + netstandard2.0 - diff --git a/src/cs/vim/Vim.Format/Vim.Format.csproj b/src/cs/vim/Vim.Format/Vim.Format.csproj index a3ae53d8..5f433ac3 100644 --- a/src/cs/vim/Vim.Format/Vim.Format.csproj +++ b/src/cs/vim/Vim.Format/Vim.Format.csproj @@ -18,7 +18,6 @@ - From c9af93b18551e36adbde6e2d6c5d3615ae4499fb Mon Sep 17 00:00:00 2001 From: simon Date: Wed, 17 Apr 2024 08:25:37 -0400 Subject: [PATCH 193/204] renamed g3dnext -> g3d --- src/cs/Vim.G3dNext.Tests/{G3dNextTestUtils.cs => G3dTestUtils.cs} | 0 src/cs/Vim.G3dNext.Tests/{VimG3dNextTests.cs => G3dTests.cs} | 0 .../{Vim.G3dNext.Tests.csproj => Vim.G3d.Tests.csproj} | 0 src/cs/g3d/Vim.G3dNext/{Vim.G3dNext.csproj => Vim.G3d.csproj} | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename src/cs/Vim.G3dNext.Tests/{G3dNextTestUtils.cs => G3dTestUtils.cs} (100%) rename src/cs/Vim.G3dNext.Tests/{VimG3dNextTests.cs => G3dTests.cs} (100%) rename src/cs/Vim.G3dNext.Tests/{Vim.G3dNext.Tests.csproj => Vim.G3d.Tests.csproj} (100%) rename src/cs/g3d/Vim.G3dNext/{Vim.G3dNext.csproj => Vim.G3d.csproj} (100%) diff --git a/src/cs/Vim.G3dNext.Tests/G3dNextTestUtils.cs b/src/cs/Vim.G3dNext.Tests/G3dTestUtils.cs similarity index 100% rename from src/cs/Vim.G3dNext.Tests/G3dNextTestUtils.cs rename to src/cs/Vim.G3dNext.Tests/G3dTestUtils.cs diff --git a/src/cs/Vim.G3dNext.Tests/VimG3dNextTests.cs b/src/cs/Vim.G3dNext.Tests/G3dTests.cs similarity index 100% rename from src/cs/Vim.G3dNext.Tests/VimG3dNextTests.cs rename to src/cs/Vim.G3dNext.Tests/G3dTests.cs diff --git a/src/cs/Vim.G3dNext.Tests/Vim.G3dNext.Tests.csproj b/src/cs/Vim.G3dNext.Tests/Vim.G3d.Tests.csproj similarity index 100% rename from src/cs/Vim.G3dNext.Tests/Vim.G3dNext.Tests.csproj rename to src/cs/Vim.G3dNext.Tests/Vim.G3d.Tests.csproj diff --git a/src/cs/g3d/Vim.G3dNext/Vim.G3dNext.csproj b/src/cs/g3d/Vim.G3dNext/Vim.G3d.csproj similarity index 100% rename from src/cs/g3d/Vim.G3dNext/Vim.G3dNext.csproj rename to src/cs/g3d/Vim.G3dNext/Vim.G3d.csproj From c5277817b998a6eea80ce69adb834c40e4a3bd21 Mon Sep 17 00:00:00 2001 From: simon Date: Wed, 17 Apr 2024 08:28:39 -0400 Subject: [PATCH 194/204] rename --- .../{Vim.G3dNext.CodeGen.csproj => Vim.G3d.CodeGen.csproj} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/cs/g3d/Vim.G3dNext.CodeGen/{Vim.G3dNext.CodeGen.csproj => Vim.G3d.CodeGen.csproj} (100%) diff --git a/src/cs/g3d/Vim.G3dNext.CodeGen/Vim.G3dNext.CodeGen.csproj b/src/cs/g3d/Vim.G3dNext.CodeGen/Vim.G3d.CodeGen.csproj similarity index 100% rename from src/cs/g3d/Vim.G3dNext.CodeGen/Vim.G3dNext.CodeGen.csproj rename to src/cs/g3d/Vim.G3dNext.CodeGen/Vim.G3d.CodeGen.csproj From ba112a440c67d944ab3c3832662deea191414fce Mon Sep 17 00:00:00 2001 From: simon Date: Wed, 17 Apr 2024 08:51:09 -0400 Subject: [PATCH 195/204] g3dnext -> g3d --- .../CodeBuilder.cs | 2 +- .../Definitions.cs | 2 +- .../G3dBuffer.cs | 2 +- .../G3dCodeGen.cs | 4 +- .../G3dEntity.cs | 2 +- .../Program.cs | 2 +- .../Vim.G3d.CodeGen.csproj | 4 +- .../Vim.G3d.Tests}/G3dTestUtils.cs | 2 +- .../Vim.G3d.Tests}/G3dTests.cs | 2 +- .../Vim.G3d.Tests}/Vim.G3d.Tests.csproj | 7 +- .../{Vim.G3dNext => Vim.G3d}/BufferMethods.cs | 2 +- .../g3d/{Vim.G3dNext => Vim.G3d}/Constants.cs | 2 +- .../g3d/{Vim.G3dNext => Vim.G3d}/G3dChunk.cs | 2 +- .../G3dGenerated.g.cs | 2 +- .../{Vim.G3dNext => Vim.G3d}/G3dMaterials.cs | 2 +- .../g3d/{Vim.G3dNext => Vim.G3d}/G3dScene.cs | 2 +- src/cs/g3d/{Vim.G3dNext => Vim.G3d}/G3dVim.cs | 2 +- .../{Vim.G3dNext => Vim.G3d}/MetaHeader.cs | 2 +- src/cs/g3d/Vim.G3d/README.md | 109 ------------------ src/cs/g3d/Vim.G3d/Vim.G3d.csproj | 49 ++------ .../Vim.G3dNext.Tests.csproj | 37 ------ src/cs/g3d/Vim.G3dNext/Vim.G3d.csproj | 22 ---- src/cs/vim-format.sln | 40 +++---- src/cs/vim/Vim.Format.Core/Document.cs | 2 +- .../Vim.Format.Core/DocumentBuilderTypes.cs | 2 +- src/cs/vim/Vim.Format.Core/G3dBuilder.cs | 2 +- .../Geometry/VimMaterialNext.cs | 2 +- .../vim/Vim.Format.Core/Geometry/VimMesh.cs | 2 +- .../Vim.Format.Core/Geometry/VimShapeNext.cs | 2 +- .../Vim.Format.Core/SerializableDocument.cs | 2 +- .../Vim.Format.Core/Vim.Format.Core.csproj | 2 +- .../Geometry/GeometryTests.cs | 2 +- .../Vim.Format.Vimx.Conversion/Chunking.cs | 2 +- .../Vim.Format.Vimx.Conversion/Ordering.cs | 2 +- .../VimxConverter.cs | 2 +- .../Vim.Format.Vimx/Vim.Format.Vimx.csproj | 1 - src/cs/vim/Vim.Format.Vimx/Vimx.cs | 2 +- .../vim/Vim.Format/SceneBuilder/VimScene.cs | 2 +- .../Vim.Format/SceneBuilder/VimSceneNode.cs | 4 +- src/cs/vim/Vim.Format/Vim.Format.csproj | 1 - 40 files changed, 65 insertions(+), 271 deletions(-) rename src/cs/g3d/{Vim.G3dNext.CodeGen => Vim.G3d.CodeGen}/CodeBuilder.cs (98%) rename src/cs/g3d/{Vim.G3dNext.CodeGen => Vim.G3d.CodeGen}/Definitions.cs (99%) rename src/cs/g3d/{Vim.G3dNext.CodeGen => Vim.G3d.CodeGen}/G3dBuffer.cs (97%) rename src/cs/g3d/{Vim.G3dNext.CodeGen => Vim.G3d.CodeGen}/G3dCodeGen.cs (98%) rename src/cs/g3d/{Vim.G3dNext.CodeGen => Vim.G3d.CodeGen}/G3dEntity.cs (96%) rename src/cs/g3d/{Vim.G3dNext.CodeGen => Vim.G3d.CodeGen}/Program.cs (85%) rename src/cs/g3d/{Vim.G3dNext.CodeGen => Vim.G3d.CodeGen}/Vim.G3d.CodeGen.csproj (79%) rename src/cs/{Vim.G3dNext.Tests => g3d/Vim.G3d.Tests}/G3dTestUtils.cs (97%) rename src/cs/{Vim.G3dNext.Tests => g3d/Vim.G3d.Tests}/G3dTests.cs (99%) rename src/cs/{Vim.G3dNext.Tests => g3d/Vim.G3d.Tests}/Vim.G3d.Tests.csproj (71%) rename src/cs/g3d/{Vim.G3dNext => Vim.G3d}/BufferMethods.cs (98%) rename src/cs/g3d/{Vim.G3dNext => Vim.G3d}/Constants.cs (99%) rename src/cs/g3d/{Vim.G3dNext => Vim.G3d}/G3dChunk.cs (99%) rename src/cs/g3d/{Vim.G3dNext => Vim.G3d}/G3dGenerated.g.cs (99%) rename src/cs/g3d/{Vim.G3dNext => Vim.G3d}/G3dMaterials.cs (94%) rename src/cs/g3d/{Vim.G3dNext => Vim.G3d}/G3dScene.cs (90%) rename src/cs/g3d/{Vim.G3dNext => Vim.G3d}/G3dVim.cs (99%) rename src/cs/g3d/{Vim.G3dNext => Vim.G3d}/MetaHeader.cs (99%) delete mode 100644 src/cs/g3d/Vim.G3d/README.md delete mode 100644 src/cs/g3d/Vim.G3dNext.Tests/Vim.G3dNext.Tests.csproj delete mode 100644 src/cs/g3d/Vim.G3dNext/Vim.G3d.csproj diff --git a/src/cs/g3d/Vim.G3dNext.CodeGen/CodeBuilder.cs b/src/cs/g3d/Vim.G3d.CodeGen/CodeBuilder.cs similarity index 98% rename from src/cs/g3d/Vim.G3dNext.CodeGen/CodeBuilder.cs rename to src/cs/g3d/Vim.G3d.CodeGen/CodeBuilder.cs index 8dd3283a..41013d8f 100644 --- a/src/cs/g3d/Vim.G3dNext.CodeGen/CodeBuilder.cs +++ b/src/cs/g3d/Vim.G3d.CodeGen/CodeBuilder.cs @@ -2,7 +2,7 @@ using System.Linq; using System.Text; -namespace Vim.G3dNext.CodeGen +namespace Vim.G3d.CodeGen { public class CodeBuilder { diff --git a/src/cs/g3d/Vim.G3dNext.CodeGen/Definitions.cs b/src/cs/g3d/Vim.G3d.CodeGen/Definitions.cs similarity index 99% rename from src/cs/g3d/Vim.G3dNext.CodeGen/Definitions.cs rename to src/cs/g3d/Vim.G3d.CodeGen/Definitions.cs index 9eb47307..8d53e40b 100644 --- a/src/cs/g3d/Vim.G3dNext.CodeGen/Definitions.cs +++ b/src/cs/g3d/Vim.G3d.CodeGen/Definitions.cs @@ -1,6 +1,6 @@ using Vim.Math3d; -namespace Vim.G3dNext.CodeGen +namespace Vim.G3d.CodeGen { internal class Definitions { diff --git a/src/cs/g3d/Vim.G3dNext.CodeGen/G3dBuffer.cs b/src/cs/g3d/Vim.G3d.CodeGen/G3dBuffer.cs similarity index 97% rename from src/cs/g3d/Vim.G3dNext.CodeGen/G3dBuffer.cs rename to src/cs/g3d/Vim.G3d.CodeGen/G3dBuffer.cs index 97cf4ce1..e3763042 100644 --- a/src/cs/g3d/Vim.G3dNext.CodeGen/G3dBuffer.cs +++ b/src/cs/g3d/Vim.G3d.CodeGen/G3dBuffer.cs @@ -1,7 +1,7 @@ using System; using System.Diagnostics; -namespace Vim.G3dNext.CodeGen +namespace Vim.G3d.CodeGen { public enum BufferType { diff --git a/src/cs/g3d/Vim.G3dNext.CodeGen/G3dCodeGen.cs b/src/cs/g3d/Vim.G3d.CodeGen/G3dCodeGen.cs similarity index 98% rename from src/cs/g3d/Vim.G3dNext.CodeGen/G3dCodeGen.cs rename to src/cs/g3d/Vim.G3d.CodeGen/G3dCodeGen.cs index 7d04fec4..773342cc 100644 --- a/src/cs/g3d/Vim.G3dNext.CodeGen/G3dCodeGen.cs +++ b/src/cs/g3d/Vim.G3d.CodeGen/G3dCodeGen.cs @@ -2,7 +2,7 @@ using System.IO; using System.Linq; -namespace Vim.G3dNext.CodeGen +namespace Vim.G3d.CodeGen { public static class G3dCodeGen { @@ -16,7 +16,7 @@ public static void WriteDocument(string filePath) cb.AppendLine("// ReSharper disable All"); cb.AppendLine("using Vim.BFastLib;"); cb.AppendLine(); - cb.AppendLine("namespace Vim.G3dNext"); + cb.AppendLine("namespace Vim.G3d"); cb.AppendLine("{"); WriteEntities(cb); cb.AppendLine("}"); diff --git a/src/cs/g3d/Vim.G3dNext.CodeGen/G3dEntity.cs b/src/cs/g3d/Vim.G3d.CodeGen/G3dEntity.cs similarity index 96% rename from src/cs/g3d/Vim.G3dNext.CodeGen/G3dEntity.cs rename to src/cs/g3d/Vim.G3d.CodeGen/G3dEntity.cs index 2be5f9e7..5c224c31 100644 --- a/src/cs/g3d/Vim.G3dNext.CodeGen/G3dEntity.cs +++ b/src/cs/g3d/Vim.G3d.CodeGen/G3dEntity.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; -namespace Vim.G3dNext.CodeGen +namespace Vim.G3d.CodeGen { /// /// Holds the data to generate the code for a g3d entity. diff --git a/src/cs/g3d/Vim.G3dNext.CodeGen/Program.cs b/src/cs/g3d/Vim.G3d.CodeGen/Program.cs similarity index 85% rename from src/cs/g3d/Vim.G3dNext.CodeGen/Program.cs rename to src/cs/g3d/Vim.G3d.CodeGen/Program.cs index 5470fb2f..6bf7d644 100644 --- a/src/cs/g3d/Vim.G3dNext.CodeGen/Program.cs +++ b/src/cs/g3d/Vim.G3d.CodeGen/Program.cs @@ -1,4 +1,4 @@ -namespace Vim.G3dNext.CodeGen +namespace Vim.G3d.CodeGen { public static class Program { diff --git a/src/cs/g3d/Vim.G3dNext.CodeGen/Vim.G3d.CodeGen.csproj b/src/cs/g3d/Vim.G3d.CodeGen/Vim.G3d.CodeGen.csproj similarity index 79% rename from src/cs/g3d/Vim.G3dNext.CodeGen/Vim.G3d.CodeGen.csproj rename to src/cs/g3d/Vim.G3d.CodeGen/Vim.G3d.CodeGen.csproj index 41239fb1..74a5126c 100644 --- a/src/cs/g3d/Vim.G3dNext.CodeGen/Vim.G3d.CodeGen.csproj +++ b/src/cs/g3d/Vim.G3d.CodeGen/Vim.G3d.CodeGen.csproj @@ -7,7 +7,7 @@ Exe - Vim.G3dNext.CodeGen.Program + Vim.G3d.CodeGen.Program @@ -15,7 +15,7 @@ - + diff --git a/src/cs/Vim.G3dNext.Tests/G3dTestUtils.cs b/src/cs/g3d/Vim.G3d.Tests/G3dTestUtils.cs similarity index 97% rename from src/cs/Vim.G3dNext.Tests/G3dTestUtils.cs rename to src/cs/g3d/Vim.G3d.Tests/G3dTestUtils.cs index 118167fb..d179edd9 100644 --- a/src/cs/Vim.G3dNext.Tests/G3dTestUtils.cs +++ b/src/cs/g3d/Vim.G3d.Tests/G3dTestUtils.cs @@ -1,6 +1,6 @@ using Vim.Math3d; -namespace Vim.G3dNext.Tests +namespace Vim.G3d.Tests { public static class G3dNextTestUtils { diff --git a/src/cs/Vim.G3dNext.Tests/G3dTests.cs b/src/cs/g3d/Vim.G3d.Tests/G3dTests.cs similarity index 99% rename from src/cs/Vim.G3dNext.Tests/G3dTests.cs rename to src/cs/g3d/Vim.G3d.Tests/G3dTests.cs index a8505b66..1539c1f1 100644 --- a/src/cs/Vim.G3dNext.Tests/G3dTests.cs +++ b/src/cs/g3d/Vim.G3d.Tests/G3dTests.cs @@ -3,7 +3,7 @@ using Vim.BFastLib; using Vim.Util.Tests; -namespace Vim.G3dNext.Tests +namespace Vim.G3d.Tests { [TestFixture] public static class VimG3dNextTests diff --git a/src/cs/Vim.G3dNext.Tests/Vim.G3d.Tests.csproj b/src/cs/g3d/Vim.G3d.Tests/Vim.G3d.Tests.csproj similarity index 71% rename from src/cs/Vim.G3dNext.Tests/Vim.G3d.Tests.csproj rename to src/cs/g3d/Vim.G3d.Tests/Vim.G3d.Tests.csproj index 032e77f2..e56190a6 100644 --- a/src/cs/Vim.G3dNext.Tests/Vim.G3d.Tests.csproj +++ b/src/cs/g3d/Vim.G3d.Tests/Vim.G3d.Tests.csproj @@ -1,4 +1,4 @@ - + net6.0 @@ -16,9 +16,8 @@ - - - + + diff --git a/src/cs/g3d/Vim.G3dNext/BufferMethods.cs b/src/cs/g3d/Vim.G3d/BufferMethods.cs similarity index 98% rename from src/cs/g3d/Vim.G3dNext/BufferMethods.cs rename to src/cs/g3d/Vim.G3d/BufferMethods.cs index e4f74d70..c7330f7e 100644 --- a/src/cs/g3d/Vim.G3dNext/BufferMethods.cs +++ b/src/cs/g3d/Vim.G3d/BufferMethods.cs @@ -2,7 +2,7 @@ using System.IO; using System.Linq; -namespace Vim.G3dNext +namespace Vim.G3d { public static class BufferMethods { diff --git a/src/cs/g3d/Vim.G3dNext/Constants.cs b/src/cs/g3d/Vim.G3d/Constants.cs similarity index 99% rename from src/cs/g3d/Vim.G3dNext/Constants.cs rename to src/cs/g3d/Vim.G3d/Constants.cs index 047a6081..d22e623b 100644 --- a/src/cs/g3d/Vim.G3dNext/Constants.cs +++ b/src/cs/g3d/Vim.G3d/Constants.cs @@ -1,4 +1,4 @@ -namespace Vim.G3dNext +namespace Vim.G3d { /// /// Defines method for additionnal setup after constructors in generated G3d classes. diff --git a/src/cs/g3d/Vim.G3dNext/G3dChunk.cs b/src/cs/g3d/Vim.G3d/G3dChunk.cs similarity index 99% rename from src/cs/g3d/Vim.G3dNext/G3dChunk.cs rename to src/cs/g3d/Vim.G3d/G3dChunk.cs index b89414dd..c85d9bc9 100644 --- a/src/cs/g3d/Vim.G3dNext/G3dChunk.cs +++ b/src/cs/g3d/Vim.G3d/G3dChunk.cs @@ -2,7 +2,7 @@ using System.Linq; using Vim.Math3d; -namespace Vim.G3dNext +namespace Vim.G3d { diff --git a/src/cs/g3d/Vim.G3dNext/G3dGenerated.g.cs b/src/cs/g3d/Vim.G3d/G3dGenerated.g.cs similarity index 99% rename from src/cs/g3d/Vim.G3dNext/G3dGenerated.g.cs rename to src/cs/g3d/Vim.G3d/G3dGenerated.g.cs index 1a822426..21c085f8 100644 --- a/src/cs/g3d/Vim.G3dNext/G3dGenerated.g.cs +++ b/src/cs/g3d/Vim.G3d/G3dGenerated.g.cs @@ -2,7 +2,7 @@ // ReSharper disable All using Vim.BFastLib; -namespace Vim.G3dNext +namespace Vim.G3d { // Please provide an explicit implementation in another partial class file. public partial class G3dVim : ISetup diff --git a/src/cs/g3d/Vim.G3dNext/G3dMaterials.cs b/src/cs/g3d/Vim.G3d/G3dMaterials.cs similarity index 94% rename from src/cs/g3d/Vim.G3dNext/G3dMaterials.cs rename to src/cs/g3d/Vim.G3d/G3dMaterials.cs index 18c3138a..28888a7e 100644 --- a/src/cs/g3d/Vim.G3dNext/G3dMaterials.cs +++ b/src/cs/g3d/Vim.G3d/G3dMaterials.cs @@ -1,5 +1,5 @@  -namespace Vim.G3dNext +namespace Vim.G3d { public partial class G3dMaterials { diff --git a/src/cs/g3d/Vim.G3dNext/G3dScene.cs b/src/cs/g3d/Vim.G3d/G3dScene.cs similarity index 90% rename from src/cs/g3d/Vim.G3dNext/G3dScene.cs rename to src/cs/g3d/Vim.G3d/G3dScene.cs index 4d6adb03..1fe8d9e2 100644 --- a/src/cs/g3d/Vim.G3dNext/G3dScene.cs +++ b/src/cs/g3d/Vim.G3d/G3dScene.cs @@ -1,4 +1,4 @@ -namespace Vim.G3dNext +namespace Vim.G3d { public partial class G3dScene { diff --git a/src/cs/g3d/Vim.G3dNext/G3dVim.cs b/src/cs/g3d/Vim.G3d/G3dVim.cs similarity index 99% rename from src/cs/g3d/Vim.G3dNext/G3dVim.cs rename to src/cs/g3d/Vim.G3d/G3dVim.cs index b21fed00..78ab447b 100644 --- a/src/cs/g3d/Vim.G3dNext/G3dVim.cs +++ b/src/cs/g3d/Vim.G3d/G3dVim.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using Vim.BFastLib; -namespace Vim.G3dNext +namespace Vim.G3d { [Flags] public enum InstanceFlags diff --git a/src/cs/g3d/Vim.G3dNext/MetaHeader.cs b/src/cs/g3d/Vim.G3d/MetaHeader.cs similarity index 99% rename from src/cs/g3d/Vim.G3dNext/MetaHeader.cs rename to src/cs/g3d/Vim.G3d/MetaHeader.cs index a58a3a6f..b79db7ea 100644 --- a/src/cs/g3d/Vim.G3dNext/MetaHeader.cs +++ b/src/cs/g3d/Vim.G3d/MetaHeader.cs @@ -1,7 +1,7 @@ using System; using System.Text; -namespace Vim.G3dNext +namespace Vim.G3d { // 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 diff --git a/src/cs/g3d/Vim.G3d/README.md b/src/cs/g3d/Vim.G3d/README.md deleted file mode 100644 index fd8f0ebe..00000000 --- a/src/cs/g3d/Vim.G3d/README.md +++ /dev/null @@ -1,109 +0,0 @@ -# G3D - -[](https://www.nuget.org/packages/Vim.G3d) - -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. - -The G3D format can contain a superset of geometry attributes found in most common geometry formats, -including formats such as FBX, glTF, OBJ, PLY, and in memory data structures used in popular 3D APIs, like -Unity, Three.JS, Assimp, and 3dsMax. - -BFAST is maintained by [VIMaec LLC](https://vimaec.com) and is licensed under the terms of the MIT License. - -# Format - -## BFAST Container - -The underlying binary layout of a G3D file conforms to the [BFAST serialization format](https://github.com/vimaec/bfast), which is a simple and efficient binary format for serializing -collections of byte arrays. BFAST provides an interface that allows named arrays of binary data to be serialized and deserialized quickly and easily. - -The first named buffer in the BFAST container is reserved for meta-information about the file encoded in JSON format. It has the name "meta". -Each subsequent buffer uses the attribute descriptor string as a name. - -## Meta-Information - -The first buffer of a G3D file is named "meta" and is represented by the G3D - -## Attributes - -G3D is organized as a collection of attribute buffers. Each attributes describe what part of the incoming geometry they are associated with: - -* point // vertex data -* corner // face-vertex data -* face // per polygon data -* edge // per half-edge data -* group // face group. Face groups are identified by a face data buffer -* SubGeometry // a contiguous section of the vertex-buffer, and index-buffer -* material // data associated with a material, materials are usually associated with groups, a -* instance // instance data, usually an instance has an index to a SubGeometry -* all // whole object data - for example face-size of 4 with whole object indicates a quad mesh -* none // no association - -Attributes also have a "semantic" which is used to identify what role the attribute has when parsing. These map roughly to FBX layer elements, or Three.JS buffer attributes. -There are a number of predefined semantic values with reserved names, but applications are free to define custom semantic values. The only required semantic in a G3D file is -"position". Here is a list of some of the predefined semantics: - -* unknown, // no known attribute type -* position, // vertex buffer -* index, // index buffer -* indexoffset, // an offset into the index buffer (used with Subgeometries) -* vertexoffset, // the offset into the vertex buffer (used only with Subgeometries) -* normal, // computed normal information (per face, group, corner, or vertex) -* binormal, // computed binormal information -* tangent, // computed tangent information -* material, // material index -* visibility, // visibility data (e.g. -* size, // number of indices per face or group -* uv, // UV (sometimes more than 1, e.g. Unity supports up to 8) -* color, // usually vertex color, but could be edge color as well -* smoothing, // identifies smoothing groups (e.g. ala 3ds Max and OBJ files) -* weight, // in 3ds Max this is called selection -* mapchannel, // 3ds Max map channel (assoc of none => map verts, assoc of corner => map faces) -* id, // used to identify what object each face part came from -* joint, // used to identify what a joint a skin is associated with -* boxes, // used to identify bounding boxes -* spheres, // used to identify bounding spheres -* user, // identifies user specific data (in 3ds Max this could be "per-vertex-data") - -Attributes are stored in 512-byte aligned data-buffers arranged as arrays of scalars or fixed width vectors. The individual data values can be integers, or floating point values of various widths from 1 to 8 bytes. The data-types are: - -* int8 -* int16 -* int32 -* int64 -* float32 -* float64 - -The number of primitives per data element is called the "arity" and can be any integer value greater than zero. For example UV might have an arity of 2, while position data -frequently has an arity of 3. - -## Encoding Strings - -While there is no explicit string type, one could encode string data by using a data-type uint8 with an arity of a fixed value (say 255) to store short strings. - -## Attribute Descriptor String - -Every attribute descriptor has a one to one mapping to a string representation similar to a URN: - - `g3d::::` - -This attribute descriptor string is the name of the buffer. - -# Recommended reading: - -* [VIM AEC blog post about using G3D with Unity](https://www.vimaec.com/the-g3d-geometry-exchange-format/) -* [Hackernoon article about BFast](https://hackernoon.com/bfast-a-data-format-for-serializing-named-binary-buffers-243p130uw) -* http://assimp.sourceforge.net/lib_html/structai_mesh.html -* http://help.autodesk.com/view/FBX/2017/ENU/?guid=__files_GUID_5EDC0280_E000_4B0B_88DF_5D215A589D5E_htm -* https://help.autodesk.com/cloudhelp/2017/ENU/Max-SDK/cpp_ref/class_mesh.html -* https://help.autodesk.com/view/3DSMAX/2016/ENU/?guid=__files_GUID_CBBA20AD_F7D5_46BC_9F5E_5EDA109F9CF4_htm -* http://paulbourke.net/dataformats/ -* http://paulbourke.net/dataformats/obj/ -* http://paulbourke.net/dataformats/ply/ -* http://paulbourke.net/dataformats/3ds/ -* https://github.com/KhronosGroup/gltf -* http://help.autodesk.com/view/FBX/2017/ENU/?guid=__cpp_ref_class_fbx_layer_element_html diff --git a/src/cs/g3d/Vim.G3d/Vim.G3d.csproj b/src/cs/g3d/Vim.G3d/Vim.G3d.csproj index f3bb78c2..b0086596 100644 --- a/src/cs/g3d/Vim.G3d/Vim.G3d.csproj +++ b/src/cs/g3d/Vim.G3d/Vim.G3d.csproj @@ -1,57 +1,22 @@  - - 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. - true - true - snupkg - - - - true - - - - true + netstandard2.0 - - - True - - - - + - - - - - - CommonAttributes.tt - True - True - + + - - - CommonAttributes.cs - TextTemplatingFileGenerator + + True + - - - - - - diff --git a/src/cs/g3d/Vim.G3dNext.Tests/Vim.G3dNext.Tests.csproj b/src/cs/g3d/Vim.G3dNext.Tests/Vim.G3dNext.Tests.csproj deleted file mode 100644 index 158c815b..00000000 --- a/src/cs/g3d/Vim.G3dNext.Tests/Vim.G3dNext.Tests.csproj +++ /dev/null @@ -1,37 +0,0 @@ - - - netstandard2.0 - false - - - - - - - - - - - - - - - - - True - True - Resources.resx - - - - - - ResXFileCodeGenerator - Resources.Designer.cs - - - - - - - diff --git a/src/cs/g3d/Vim.G3dNext/Vim.G3d.csproj b/src/cs/g3d/Vim.G3dNext/Vim.G3d.csproj deleted file mode 100644 index b0086596..00000000 --- a/src/cs/g3d/Vim.G3dNext/Vim.G3d.csproj +++ /dev/null @@ -1,22 +0,0 @@ - - - netstandard2.0 - - - - - - - - - - - - - - True - - - - - diff --git a/src/cs/vim-format.sln b/src/cs/vim-format.sln index 97edf442..dca052d8 100644 --- a/src/cs/vim-format.sln +++ b/src/cs/vim-format.sln @@ -31,10 +31,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "util", "util", "{A279C2F9-3 EndProject 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.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}" @@ -45,7 +41,11 @@ 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("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vim.G3dNext.Tests", "Vim.G3dNext.Tests\Vim.G3dNext.Tests.csproj", "{AD1A2A9F-18E9-4430-A192-3CD1A17DDA0D}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vim.G3d", "g3d\Vim.G3d\Vim.G3d.csproj", "{4D3789CE-5C2F-4B4E-8E9F-EC0D171E520E}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vim.G3d.CodeGen", "g3d\Vim.G3d.CodeGen\Vim.G3d.CodeGen.csproj", "{DC267698-FA79-40E2-9322-14F346ABAD85}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vim.G3d.Tests", "g3d\Vim.G3d.Tests\Vim.G3d.Tests.csproj", "{059CAAF3-0B7C-46B0-A939-BF96DC6DB394}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -89,14 +89,6 @@ 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 - {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 @@ -117,10 +109,18 @@ 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 + {4D3789CE-5C2F-4B4E-8E9F-EC0D171E520E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4D3789CE-5C2F-4B4E-8E9F-EC0D171E520E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4D3789CE-5C2F-4B4E-8E9F-EC0D171E520E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4D3789CE-5C2F-4B4E-8E9F-EC0D171E520E}.Release|Any CPU.Build.0 = Release|Any CPU + {DC267698-FA79-40E2-9322-14F346ABAD85}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DC267698-FA79-40E2-9322-14F346ABAD85}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DC267698-FA79-40E2-9322-14F346ABAD85}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DC267698-FA79-40E2-9322-14F346ABAD85}.Release|Any CPU.Build.0 = Release|Any CPU + {059CAAF3-0B7C-46B0-A939-BF96DC6DB394}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {059CAAF3-0B7C-46B0-A939-BF96DC6DB394}.Debug|Any CPU.Build.0 = Debug|Any CPU + {059CAAF3-0B7C-46B0-A939-BF96DC6DB394}.Release|Any CPU.ActiveCfg = Release|Any CPU + {059CAAF3-0B7C-46B0-A939-BF96DC6DB394}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -135,14 +135,14 @@ 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} - {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} + {4D3789CE-5C2F-4B4E-8E9F-EC0D171E520E} = {705B8FB2-D707-4527-91FC-0AADEDBA4D80} + {DC267698-FA79-40E2-9322-14F346ABAD85} = {705B8FB2-D707-4527-91FC-0AADEDBA4D80} + {059CAAF3-0B7C-46B0-A939-BF96DC6DB394} = {705B8FB2-D707-4527-91FC-0AADEDBA4D80} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {7D1BF641-26E8-4809-B638-029241C51BE2} diff --git a/src/cs/vim/Vim.Format.Core/Document.cs b/src/cs/vim/Vim.Format.Core/Document.cs index 4257d38d..6532197f 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.BFastLib; -using Vim.G3dNext; +using Vim.G3d; using Vim.Util; namespace Vim.Format diff --git a/src/cs/vim/Vim.Format.Core/DocumentBuilderTypes.cs b/src/cs/vim/Vim.Format.Core/DocumentBuilderTypes.cs index 7d48f289..3d4b276f 100644 --- a/src/cs/vim/Vim.Format.Core/DocumentBuilderTypes.cs +++ b/src/cs/vim/Vim.Format.Core/DocumentBuilderTypes.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Linq; using Vim.Format.Geometry; -using Vim.G3dNext; +using Vim.G3d; using Vim.Math3d; namespace Vim.Format diff --git a/src/cs/vim/Vim.Format.Core/G3dBuilder.cs b/src/cs/vim/Vim.Format.Core/G3dBuilder.cs index f2cd62d4..8cbdbd45 100644 --- a/src/cs/vim/Vim.Format.Core/G3dBuilder.cs +++ b/src/cs/vim/Vim.Format.Core/G3dBuilder.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; using System.Linq; -using Vim.G3dNext; +using Vim.G3d; using Vim.BFastLib; using static Vim.Format.DocumentBuilder; using Vim.Math3d; diff --git a/src/cs/vim/Vim.Format.Core/Geometry/VimMaterialNext.cs b/src/cs/vim/Vim.Format.Core/Geometry/VimMaterialNext.cs index 0d0a1740..07ee1f2e 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/VimMaterialNext.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/VimMaterialNext.cs @@ -1,6 +1,6 @@ using System; using System.Collections.Generic; -using Vim.G3dNext; +using Vim.G3d; using Vim.Math3d; namespace Vim.Format.Geometry diff --git a/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs b/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs index e5cffc94..b80c1a0f 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; -using Vim.G3dNext; +using Vim.G3d; using Vim.Math3d; namespace Vim.Format.Geometry diff --git a/src/cs/vim/Vim.Format.Core/Geometry/VimShapeNext.cs b/src/cs/vim/Vim.Format.Core/Geometry/VimShapeNext.cs index 10dcf2f3..7c63bdd1 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/VimShapeNext.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/VimShapeNext.cs @@ -1,6 +1,6 @@ using System; using System.Collections.Generic; -using Vim.G3dNext; +using Vim.G3d; using Vim.Math3d; 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 013ce98f..6acaa935 100644 --- a/src/cs/vim/Vim.Format.Core/SerializableDocument.cs +++ b/src/cs/vim/Vim.Format.Core/SerializableDocument.cs @@ -4,7 +4,7 @@ using System.Text; using Vim.BFastLib; using Vim.BFastLib.Core; -using Vim.G3dNext; +using Vim.G3d; 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 951143a3..a291acd7 100644 --- a/src/cs/vim/Vim.Format.Core/Vim.Format.Core.csproj +++ b/src/cs/vim/Vim.Format.Core/Vim.Format.Core.csproj @@ -10,7 +10,7 @@ - + diff --git a/src/cs/vim/Vim.Format.Tests/Geometry/GeometryTests.cs b/src/cs/vim/Vim.Format.Tests/Geometry/GeometryTests.cs index 6218cd8f..13fde2f6 100644 --- a/src/cs/vim/Vim.Format.Tests/Geometry/GeometryTests.cs +++ b/src/cs/vim/Vim.Format.Tests/Geometry/GeometryTests.cs @@ -2,7 +2,7 @@ using System; using System.Linq; using Vim.Format.Geometry; -using Vim.G3dNext; +using Vim.G3d; using Vim.Math3d; namespace Vim.Format.Tests.Geometry diff --git a/src/cs/vim/Vim.Format.Vimx.Conversion/Chunking.cs b/src/cs/vim/Vim.Format.Vimx.Conversion/Chunking.cs index 0318eb23..8ddf6187 100644 --- a/src/cs/vim/Vim.Format.Vimx.Conversion/Chunking.cs +++ b/src/cs/vim/Vim.Format.Vimx.Conversion/Chunking.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; using System.Linq; using Vim.Math3d; -using Vim.G3dNext; +using Vim.G3d; namespace Vim.Format.VimxLib.Conversion { diff --git a/src/cs/vim/Vim.Format.Vimx.Conversion/Ordering.cs b/src/cs/vim/Vim.Format.Vimx.Conversion/Ordering.cs index 2424185b..587bac7e 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; +using Vim.G3d; namespace Vim.Format.VimxLib.Conversion { diff --git a/src/cs/vim/Vim.Format.Vimx.Conversion/VimxConverter.cs b/src/cs/vim/Vim.Format.Vimx.Conversion/VimxConverter.cs index 77749be7..62663db9 100644 --- a/src/cs/vim/Vim.Format.Vimx.Conversion/VimxConverter.cs +++ b/src/cs/vim/Vim.Format.Vimx.Conversion/VimxConverter.cs @@ -3,7 +3,7 @@ using System.Linq; using Vim.BFastLib; using Vim.Format.ObjectModel; -using Vim.G3dNext; +using Vim.G3d; using Vim.Math3d; using Vim.Util; 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 78fe3dbf..b9896ad8 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 db973d04..31c3c20e 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.Linq; using Vim.BFastLib; -using Vim.G3dNext; +using Vim.G3d; namespace Vim.Format.VimxLib { diff --git a/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs b/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs index 48a652d2..ce5a7cbb 100644 --- a/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs +++ b/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs @@ -7,7 +7,7 @@ using Vim.Format; using Vim.Format.Geometry; using Vim.Format.ObjectModel; -using Vim.G3dNext; +using Vim.G3d; using Vim.Math3d; using Vim.Util; using IVimSceneProgress = System.IProgress<(string, double)>; diff --git a/src/cs/vim/Vim.Format/SceneBuilder/VimSceneNode.cs b/src/cs/vim/Vim.Format/SceneBuilder/VimSceneNode.cs index 9e7c5425..488f1adb 100644 --- a/src/cs/vim/Vim.Format/SceneBuilder/VimSceneNode.cs +++ b/src/cs/vim/Vim.Format/SceneBuilder/VimSceneNode.cs @@ -3,7 +3,7 @@ using System.Linq; using Vim.Format.Geometry; using Vim.Format.ObjectModel; -using Vim.G3dNext; +using Vim.G3d; using Vim.Math3d; namespace Vim @@ -26,7 +26,7 @@ public VimSceneNode(VimScene scene, int nodeIndex, int geometryIndex, Matrix4x4 public Matrix4x4 Transform { get; } public bool HideByDefault - => Scene.Document.GeometryNext.InstanceHasFlag(NodeIndex, G3dNext.InstanceFlags.Hidden); + => Scene.Document.GeometryNext.InstanceHasFlag(NodeIndex, InstanceFlags.Hidden); public int VimIndex { get; } = -1; public int NodeIndex { get; } = -1; diff --git a/src/cs/vim/Vim.Format/Vim.Format.csproj b/src/cs/vim/Vim.Format/Vim.Format.csproj index 5f433ac3..db3e19f8 100644 --- a/src/cs/vim/Vim.Format/Vim.Format.csproj +++ b/src/cs/vim/Vim.Format/Vim.Format.csproj @@ -33,7 +33,6 @@ true true - From faab3f8d732154fe65458c31336f608a4a79ce86 Mon Sep 17 00:00:00 2001 From: simon Date: Wed, 17 Apr 2024 09:00:59 -0400 Subject: [PATCH 196/204] g3dnext -> g3d --- src/cs/g3d/Vim.G3d.Tests/G3dTestUtils.cs | 2 +- src/cs/g3d/Vim.G3d.Tests/G3dTests.cs | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/cs/g3d/Vim.G3d.Tests/G3dTestUtils.cs b/src/cs/g3d/Vim.G3d.Tests/G3dTestUtils.cs index d179edd9..9bd3b033 100644 --- a/src/cs/g3d/Vim.G3d.Tests/G3dTestUtils.cs +++ b/src/cs/g3d/Vim.G3d.Tests/G3dTestUtils.cs @@ -2,7 +2,7 @@ namespace Vim.G3d.Tests { - public static class G3dNextTestUtils + public static class G3dTestUtils { public static G3dVim CreateTestG3d() { diff --git a/src/cs/g3d/Vim.G3d.Tests/G3dTests.cs b/src/cs/g3d/Vim.G3d.Tests/G3dTests.cs index 1539c1f1..c23b45e0 100644 --- a/src/cs/g3d/Vim.G3d.Tests/G3dTests.cs +++ b/src/cs/g3d/Vim.G3d.Tests/G3dTests.cs @@ -6,7 +6,7 @@ namespace Vim.G3d.Tests { [TestFixture] - public static class VimG3dNextTests + public static class VimG3dTests { [Test] public static void Can_Read_G3d_From_Vim() @@ -23,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 = G3dNextTestUtils.CreateTestG3d(); + var g3d = G3dTestUtils.CreateTestG3d(); var g3dMats = new G3dMaterials(g3d.ToBFast()); Assert.IsNotNull(g3dMats); @@ -35,7 +35,7 @@ public static void Can_Ignore_Extra_Attributes() [Test] public static void Can_Write_And_Read() { - var expected = G3dNextTestUtils.CreateTestG3d(); + var expected = G3dTestUtils.CreateTestG3d(); var g3d = new G3dVim(expected.ToBFast()); Assert.IsTrue(g3d.Equals(expected)); } @@ -45,7 +45,7 @@ public static void Can_Write_And_Read() [Test] public static void Can_Merge_two_g3d() { - var g3d = G3dNextTestUtils.CreateTestG3d(); + var g3d = G3dTestUtils.CreateTestG3d(); var merged = g3d.Merge(g3d); var expected = new G3dVim( @@ -73,7 +73,7 @@ public static void Can_Merge_two_g3d() [Test] public static void Clone_IsEqual() { - var g3d = G3dNextTestUtils.CreateTestG3d(); + var g3d = G3dTestUtils.CreateTestG3d(); Assert.IsTrue(g3d.Equals(g3d.Clone())); } } From 9affe332523cd6e70696654d1482db6c795ab7bd Mon Sep 17 00:00:00 2001 From: simon Date: Wed, 17 Apr 2024 10:43:30 -0400 Subject: [PATCH 197/204] extracting loading code --- .../Vim.Format/SceneBuilder/ILoadingStep.cs | 21 ++++++++++++++++ .../SceneBuilder/LoadingProgress.cs | 22 +++++++++++++++++ .../SceneBuilder/LoadingSequence.cs | 22 +++++++++++++++++ .../Vim.Format/SceneBuilder/LoadingStep.cs | 24 +++++++++++++++++++ 4 files changed, 89 insertions(+) create mode 100644 src/cs/vim/Vim.Format/SceneBuilder/ILoadingStep.cs create mode 100644 src/cs/vim/Vim.Format/SceneBuilder/LoadingProgress.cs create mode 100644 src/cs/vim/Vim.Format/SceneBuilder/LoadingSequence.cs create mode 100644 src/cs/vim/Vim.Format/SceneBuilder/LoadingStep.cs diff --git a/src/cs/vim/Vim.Format/SceneBuilder/ILoadingStep.cs b/src/cs/vim/Vim.Format/SceneBuilder/ILoadingStep.cs new file mode 100644 index 00000000..6fd58731 --- /dev/null +++ b/src/cs/vim/Vim.Format/SceneBuilder/ILoadingStep.cs @@ -0,0 +1,21 @@ +namespace Vim.Format.SceneBuilder +{ + using System; + + public class LoadingProgress: Progress<(string, double)>, ILoadingProgress + { + public LoadingProgress(Action<(string, double)> handler) : base(handler) + { + } + } + + public interface ILoadingProgress : IProgress<(string, double)> + { + } + + public interface ILoadingStep + { + void Run(ILoadingProgress progress); + float Effort { get; } + } +} diff --git a/src/cs/vim/Vim.Format/SceneBuilder/LoadingProgress.cs b/src/cs/vim/Vim.Format/SceneBuilder/LoadingProgress.cs new file mode 100644 index 00000000..f5847bd6 --- /dev/null +++ b/src/cs/vim/Vim.Format/SceneBuilder/LoadingProgress.cs @@ -0,0 +1,22 @@ +namespace Vim.Format.SceneBuilder +{ + public class CumulativeProgressDecorator : ILoadingProgress + { + private readonly double _total; + private double _current; + + private readonly ILoadingProgress _progress; + + private CumulativeProgressDecorator(ILoadingProgress progress, float total) + => (_progress, _total) = (progress, total); + + public static CumulativeProgressDecorator Decorate(ILoadingProgress logger, float total) + => logger != null ? new CumulativeProgressDecorator(logger, total) : null; + + public void Report((string, double) value) + { + _current += value.Item2; + _progress.Report((value.Item1, _current / _total)); + } + } +} diff --git a/src/cs/vim/Vim.Format/SceneBuilder/LoadingSequence.cs b/src/cs/vim/Vim.Format/SceneBuilder/LoadingSequence.cs new file mode 100644 index 00000000..d864c8f3 --- /dev/null +++ b/src/cs/vim/Vim.Format/SceneBuilder/LoadingSequence.cs @@ -0,0 +1,22 @@ +using System.Linq; + +namespace Vim.Format.SceneBuilder +{ + public class LoadingSequence : ILoadingStep + { + private readonly LoadingStep[] _steps; + public float Effort { get; } + + public LoadingSequence(params LoadingStep[] steps) + { + _steps = steps; + Effort = _steps.Sum(s => s.Effort); + } + + public void Run(ILoadingProgress progress) + { + foreach (var step in _steps) + step.Run(progress); + } + } +} diff --git a/src/cs/vim/Vim.Format/SceneBuilder/LoadingStep.cs b/src/cs/vim/Vim.Format/SceneBuilder/LoadingStep.cs new file mode 100644 index 00000000..d8bbe47d --- /dev/null +++ b/src/cs/vim/Vim.Format/SceneBuilder/LoadingStep.cs @@ -0,0 +1,24 @@ +using System; + +namespace Vim.Format.SceneBuilder +{ + public class LoadingStep : ILoadingStep + { + private readonly Action _action; + private readonly string _name; + public float Effort { get; } + + public LoadingStep(Action action, string name, float effort = 1f) + { + _action = action; + _name = name; + Effort = effort; + } + + public void Run(ILoadingProgress progress) + { + progress?.Report((_name, Effort)); + _action(); + } + } +} From c80823a5f131d5982c6d418d5fd00c62d07fc644 Mon Sep 17 00:00:00 2001 From: simon Date: Wed, 17 Apr 2024 10:48:12 -0400 Subject: [PATCH 198/204] ilookup -> dictionnary --- src/cs/vim/Vim.Format.Core/Document.cs | 12 +++++++----- src/cs/vim/Vim.Format.Core/EntityTable.cs | 12 ++++++------ 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/cs/vim/Vim.Format.Core/Document.cs b/src/cs/vim/Vim.Format.Core/Document.cs index 6532197f..b83ae7ee 100644 --- a/src/cs/vim/Vim.Format.Core/Document.cs +++ b/src/cs/vim/Vim.Format.Core/Document.cs @@ -1,4 +1,6 @@ -using Vim.BFastLib; +using System.Collections.Generic; +using System.Linq; +using Vim.BFastLib; using Vim.G3d; using Vim.Util; @@ -13,17 +15,17 @@ public Document(SerializableDocument document) Header = _Document.Header; GeometryNext = _Document.GeometryNext; StringTable = _Document.StringTable; - EntityTables = _Document.EntityTables.ToVimLookup( + EntityTables = _Document.EntityTables.ToDictionary( et => et.Name, et => et.ToEntityTable(this)); - Assets = _Document.Assets.ToVimLookup(et => et.Name, et => et); + Assets = _Document.Assets.ToDictionary(et => et.Name, et => et); } public string FileName => _Document.FileName; public SerializableDocument _Document { get; } public SerializableHeader Header { get; } - public ILookup EntityTables { get; } - public ILookup Assets { get; } + public Dictionary EntityTables { get; } + public Dictionary Assets { get; } public string[] StringTable { get; } public string GetString(int index) => StringTable.ElementAtOrDefault(index); public G3dVim GeometryNext { get; } diff --git a/src/cs/vim/Vim.Format.Core/EntityTable.cs b/src/cs/vim/Vim.Format.Core/EntityTable.cs index e4b317e4..edc40e26 100644 --- a/src/cs/vim/Vim.Format.Core/EntityTable.cs +++ b/src/cs/vim/Vim.Format.Core/EntityTable.cs @@ -14,9 +14,9 @@ public EntityTable(Document document, SerializableEntityTable entityTable) _EntityTable = entityTable; Name = _EntityTable.Name; - DataColumns = _EntityTable.DataColumns.ToVimLookup( c => c.Name, c => c); - IndexColumns = _EntityTable.IndexColumns.ToVimLookup(c => c.Name, c => c); - StringColumns = _EntityTable.StringColumns.ToVimLookup(c => c.Name, c => c); + DataColumns = _EntityTable.DataColumns.ToDictionary( c => c.Name, c => c); + IndexColumns = _EntityTable.IndexColumns.ToDictionary(c => c.Name, c => c); + StringColumns = _EntityTable.StringColumns.ToDictionary(c => c.Name, c => c); NumRows = Columns.FirstOrDefault()?.NumElements() ?? 0; Columns.ValidateColumnRowsAreAligned(); @@ -26,9 +26,9 @@ public EntityTable(Document document, SerializableEntityTable entityTable) public Document Document { get; } public string Name { get; } public int NumRows { get; } - public Vim.Util.ILookup DataColumns { get; } - public Vim.Util.ILookup> StringColumns { get; } - public Vim.Util.ILookup> IndexColumns { get; } + public Dictionary DataColumns { get; } + public Dictionary> StringColumns { get; } + public Dictionary> IndexColumns { get; } public IEnumerable Columns => DataColumns.Values .Concat(IndexColumns.Values.Select(x => (INamedBuffer)x)) From 1b6042d6a065337166090c8f20d57101d8e3a60a Mon Sep 17 00:00:00 2001 From: simon Date: Wed, 17 Apr 2024 10:52:17 -0400 Subject: [PATCH 199/204] removed ilookup --- src/cs/util/Vim.Util/CollectionExtensions.cs | 10 --- src/cs/util/Vim.Util/ILookup.cs | 74 ------------------- .../vim/Vim.Format/ObjectModel/Validation.cs | 2 +- 3 files changed, 1 insertion(+), 85 deletions(-) delete mode 100644 src/cs/util/Vim.Util/ILookup.cs diff --git a/src/cs/util/Vim.Util/CollectionExtensions.cs b/src/cs/util/Vim.Util/CollectionExtensions.cs index 92404f98..7039b7de 100644 --- a/src/cs/util/Vim.Util/CollectionExtensions.cs +++ b/src/cs/util/Vim.Util/CollectionExtensions.cs @@ -7,16 +7,6 @@ namespace Vim.Util { public static class CollectionExtensions { - public static TValue GetOrDefault(this ILookup lookup, TKey key, TValue @default = default(TValue)) - => lookup.Contains(key) ? lookup[key] : @default; - - public static ILookup ToVimLookup(this IEnumerable input, Func keyFunc, Func valueFunc) - => input.ToDictionary(keyFunc, valueFunc).ToLookup(); - - public static ILookup ToVimLookup(this IEnumerable input, Func keyFunc) - => input.ToDictionary(keyFunc, x => x).ToLookup(); - - /// /// Returns the index of the first element matching the given item. /// diff --git a/src/cs/util/Vim.Util/ILookup.cs b/src/cs/util/Vim.Util/ILookup.cs deleted file mode 100644 index b1c8257f..00000000 --- a/src/cs/util/Vim.Util/ILookup.cs +++ /dev/null @@ -1,74 +0,0 @@ -// MIT License - Copyright 2019 (C) VIMaec, LLC. -// MIT License - Copyright 2018 (C) Ara 3D, Inc. -// This file is subject to the terms and conditions defined in -// file 'LICENSE.txt', which is part of this source code package. - -using System.Collections.Generic; -using System.Linq; - -namespace Vim.Util -{ - /// - /// Lookup table: mapping from a key to some value. - /// - public interface ILookup - { - IEnumerable Keys { get; } - IEnumerable Values { get; } - bool Contains(TKey key); - TValue this[TKey key] { get; } - } - - public class EmptyLookup : ILookup - { - public IEnumerable Keys => Enumerable.Empty(); - public IEnumerable Values => Enumerable.Empty(); - public bool Contains(TKey key) => false; - public TValue this[TKey key] => default; - } - - public class LookupFromDictionary : ILookup - { - public IDictionary Dictionary; - private TValue _default; - - public LookupFromDictionary(IDictionary d = null, TValue defaultValue = default) - { - Dictionary = d ?? new Dictionary(); - // TODO: sort? - _default = defaultValue; - } - - public IEnumerable Keys => Dictionary.Keys; - public IEnumerable Values => Dictionary.Values; - public TValue this[TKey key] => Contains(key) ? Dictionary[key] : _default; - public bool Contains(TKey key) => Dictionary.ContainsKey(key); - } - - public class LookupFromArray : ILookup - { - private TValue[] array; - - public LookupFromArray(TValue[] xs) - { - array = xs; - } - - public IEnumerable Keys => Enumerable.Range(0, array.Length); - public IEnumerable Values => array; - public TValue this[int key] => array[key]; - public bool Contains(int key) => key >= 0 && key <= array.Length; - } - - public static class LookupExtensions - { - public static ILookup ToLookup(this IDictionary d, TValue defaultValue = default) - => new LookupFromDictionary(d, defaultValue); - - public static TValue GetOrDefault(this ILookup lookup, TKey key) - => lookup.Contains(key) ? lookup[key] : default; - - public static IEnumerable GetValues(this ILookup lookup) - => lookup.Keys.Select(k => lookup[k]); - } -} diff --git a/src/cs/vim/Vim.Format/ObjectModel/Validation.cs b/src/cs/vim/Vim.Format/ObjectModel/Validation.cs index fd795670..14d5d24c 100644 --- a/src/cs/vim/Vim.Format/ObjectModel/Validation.cs +++ b/src/cs/vim/Vim.Format/ObjectModel/Validation.cs @@ -143,7 +143,7 @@ public static void ValidateAssets(this DocumentModel dm) var assetEntities = dm.AssetList.ToArray(); foreach (var asset in assetEntities) { - if (!assetBuffers.Contains(asset.BufferName)) + if (!assetBuffers.ContainsKey(asset.BufferName)) throw new ObjectModelValidationException($"No matching asset buffer found for asset entity {asset.Index} with {nameof(asset.BufferName)} '{asset.BufferName}'"); } } From ac1a599c6739586d0052888e80277bd984d205cc Mon Sep 17 00:00:00 2001 From: simon Date: Thu, 18 Apr 2024 09:45:28 -0400 Subject: [PATCH 200/204] removed unused code --- .../ColumnExtensions.Buffer.cs | 12 ------ .../ColumnExtensions.Reflection.cs | 3 -- .../vim/Vim.Format.Core/ColumnExtensions.cs | 3 -- .../DocumentBuilderExtensions.cs | 7 ---- .../vim/Vim.Format.Core/DocumentExtensions.cs | 37 +------------------ 5 files changed, 1 insertion(+), 61 deletions(-) diff --git a/src/cs/vim/Vim.Format.Core/ColumnExtensions.Buffer.cs b/src/cs/vim/Vim.Format.Core/ColumnExtensions.Buffer.cs index e1246fe2..4522b7d0 100644 --- a/src/cs/vim/Vim.Format.Core/ColumnExtensions.Buffer.cs +++ b/src/cs/vim/Vim.Format.Core/ColumnExtensions.Buffer.cs @@ -183,18 +183,6 @@ public static List> ConcatIntColumns(this IReadOnlyList thisColumnList.ConcatColumns(otherColumnList, (a, b) => new NamedBuffer(a.GetTypedData().Concat(b.GetTypedData()).ToArray(), a.Name)); - /// - /// Returns a concatenated SerializableEntityTable based on the column names of thisTable. - /// - public static SerializableEntityTable Concat(this SerializableEntityTable thisTable, SerializableEntityTable otherTable) - => new SerializableEntityTable - { - Name = thisTable.Name, - IndexColumns = thisTable.IndexColumns.ConcatIntColumns(otherTable.IndexColumns), - StringColumns = thisTable.StringColumns.ConcatIntColumns(otherTable.StringColumns), - DataColumns = thisTable.DataColumns.ConcatDataColumns(otherTable.DataColumns), - }.ValidateColumnRowsAreAligned(); - public static T[] GetColumnValues(this INamedBuffer nb) where T : unmanaged => nb.AsArray(); diff --git a/src/cs/vim/Vim.Format.Core/ColumnExtensions.Reflection.cs b/src/cs/vim/Vim.Format.Core/ColumnExtensions.Reflection.cs index d7cedece..81f3efe3 100644 --- a/src/cs/vim/Vim.Format.Core/ColumnExtensions.Reflection.cs +++ b/src/cs/vim/Vim.Format.Core/ColumnExtensions.Reflection.cs @@ -60,9 +60,6 @@ public static string GetSerializedValueColumnName(this FieldInfo fieldInfo) return $"{typePrefix}{fieldInfo.GetSerializedValueName()}"; } - public static string GetSerializedIndexName(this FieldInfo fieldInfo) - => fieldInfo.Name.Trim('_'); - public static bool IsRelationType(this Type t) => t.Name == "Relation`1"; diff --git a/src/cs/vim/Vim.Format.Core/ColumnExtensions.cs b/src/cs/vim/Vim.Format.Core/ColumnExtensions.cs index 0d826c14..531e3619 100644 --- a/src/cs/vim/Vim.Format.Core/ColumnExtensions.cs +++ b/src/cs/vim/Vim.Format.Core/ColumnExtensions.cs @@ -19,9 +19,6 @@ public static readonly IReadOnlyCollection AllColumnInfos new ColumnInfo(ColumnType.DataColumn, VimConstants.FloatColumnNameTypePrefix, typeof(float)), }; - public static readonly IReadOnlyDictionary TypePrefixToColumnTypeMap - = AllColumnInfos.ToDictionary(t => t.TypePrefix, t => t.ColumnType); - public static readonly IReadOnlyDictionary DataColumnTypeToPrefixMap = AllColumnInfos .Where(t => t.ColumnType == ColumnType.DataColumn) diff --git a/src/cs/vim/Vim.Format.Core/DocumentBuilderExtensions.cs b/src/cs/vim/Vim.Format.Core/DocumentBuilderExtensions.cs index c5b4e636..da62d335 100644 --- a/src/cs/vim/Vim.Format.Core/DocumentBuilderExtensions.cs +++ b/src/cs/vim/Vim.Format.Core/DocumentBuilderExtensions.cs @@ -9,13 +9,6 @@ namespace Vim.Format { public static class DocumentBuilderExtensions { - public static SubdividedMesh ToDocumentBuilderSubdividedMesh(this VimMesh m) - => new SubdividedMesh( - m.indices, - m.vertices, - m.submeshIndexOffsets, - m.submeshMaterials); - public static EntityTableBuilder CreateTableCopy(this DocumentBuilder db, EntityTable table, List nodeIndexRemapping = null) { var name = table.Name; diff --git a/src/cs/vim/Vim.Format.Core/DocumentExtensions.cs b/src/cs/vim/Vim.Format.Core/DocumentExtensions.cs index 366cf46b..dfa6a02d 100644 --- a/src/cs/vim/Vim.Format.Core/DocumentExtensions.cs +++ b/src/cs/vim/Vim.Format.Core/DocumentExtensions.cs @@ -15,30 +15,6 @@ public static Document ToDocument(this SerializableDocument document) public static EntityTable ToEntityTable(this SerializableEntityTable entityTable, Document document) => new EntityTable(document, entityTable); - public static IEnumerable GetColumnNames(this EntityTable table) - => table.Columns.Select(c => c.Name); - - public static void ValidateRelations(this Document doc) - { - foreach (var et in doc.EntityTables.Values) - { - foreach (var ic in et.IndexColumns.Values) - { - var relatedTable = ic.GetRelatedTable(doc); - var maxValue = relatedTable.NumRows; - var data = ic.GetTypedData(); - for (var i = 0; i < data.Length; ++i) - { - var v = data[i]; - if (v < -1 || v > maxValue) - { - throw new Exception($"Invalid relation {v} out of range of -1 to {maxValue}"); - } - } - } - } - } - public static readonly Regex IndexColumnNameComponentsRegex = new Regex(@"(\w+:)((?:\w|\.)+):(.+)"); public class IndexColumnNameComponents @@ -65,12 +41,6 @@ public static IndexColumnNameComponents SplitIndexColumnName(string name) public static string GetRelatedTableNameFromColumnName(string name) => SplitIndexColumnName(name).TableName; - public static string GetFieldNameFromColumnName(string name) - => SplitIndexColumnName(name).FieldName; - - public static string GetFieldName(this INamedBuffer ic) - => GetFieldNameFromColumnName(ic.Name); - public static string GetRelatedTableName(this INamedBuffer ic) => GetRelatedTableNameFromColumnName(ic.Name); @@ -79,11 +49,6 @@ public static EntityTable GetRelatedTable(this INamedBuffer ic, Document do public static EntityTable GetTable(this Document doc, string name) => doc.EntityTables.GetOrDefault(name); - - public static SerializableDocument SetFileName(this SerializableDocument doc, string fileName) - { - doc.FileName = fileName; - return doc; - } + } } From 90858edbeddfefd84ed44fa683a02f7df69ea327 Mon Sep 17 00:00:00 2001 From: simon Date: Thu, 18 Apr 2024 10:29:04 -0400 Subject: [PATCH 201/204] removed uneeded extender --- src/cs/vim/Vim.Format.Core/ColumnExtensions.Buffer.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/cs/vim/Vim.Format.Core/ColumnExtensions.Buffer.cs b/src/cs/vim/Vim.Format.Core/ColumnExtensions.Buffer.cs index 4522b7d0..333323fd 100644 --- a/src/cs/vim/Vim.Format.Core/ColumnExtensions.Buffer.cs +++ b/src/cs/vim/Vim.Format.Core/ColumnExtensions.Buffer.cs @@ -8,9 +8,6 @@ namespace Vim.Format { public static partial class ColumnExtensions { - public static IEnumerable GetAllColumns(this SerializableEntityTable et) - => et.DataColumns.Concat(et.IndexColumns).Concat(et.StringColumns).ToList(); - public static void ValidateColumnRowsAreAligned(this IEnumerable columns) { var numRows = columns.FirstOrDefault()?.NumElements() ?? 0; @@ -28,7 +25,7 @@ public static void ValidateColumnRowsAreAligned(this IEnumerable c public static SerializableEntityTable ValidateColumnRowsAreAligned(this SerializableEntityTable et) { - et.GetAllColumns().ValidateColumnRowsAreAligned(); + et.AllColumns.ValidateColumnRowsAreAligned(); return et; } From bb738ce4f990a03018728b5c94526751926fc95a Mon Sep 17 00:00:00 2001 From: simon Date: Fri, 19 Apr 2024 11:30:29 -0400 Subject: [PATCH 202/204] fixed test --- src/cs/vim/Vim.Format.Tests/Geometry/GeometryTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cs/vim/Vim.Format.Tests/Geometry/GeometryTests.cs b/src/cs/vim/Vim.Format.Tests/Geometry/GeometryTests.cs index 13fde2f6..2394e627 100644 --- a/src/cs/vim/Vim.Format.Tests/Geometry/GeometryTests.cs +++ b/src/cs/vim/Vim.Format.Tests/Geometry/GeometryTests.cs @@ -75,7 +75,7 @@ public static void BasicTests() Assert.AreEqual(3, XYTriangle.indices.Length); Assert.AreEqual(1, XYTriangle.Triangles().Length); Assert.IsTrue(XYTriangle.Planar()); - Assert.AreEqual(new[] { 0, 1, 2 }, XYTriangle.indices.Length); + Assert.AreEqual(new[] { 0, 1, 2 }, XYTriangle.indices); Assert.AreEqual(3, XYQuad.NumCornersPerFace); Assert.AreEqual(2, XYQuad.NumFaces); From 89e907492ab48bd85646717d4d1a3b60d7df8e78 Mon Sep 17 00:00:00 2001 From: vim-sroberge Date: Thu, 10 Oct 2024 14:11:09 -0400 Subject: [PATCH 203/204] added check for local files in bfast --- src/ts/src/bfast.ts | 13 ++++++++++--- src/ts/src/http/remoteBuffer.ts | 4 ++++ 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/ts/src/bfast.ts b/src/ts/src/bfast.ts index 4d611695..1cde4f8c 100644 --- a/src/ts/src/bfast.ts +++ b/src/ts/src/bfast.ts @@ -5,6 +5,7 @@ import { RemoteValue } from './http/remoteValue' import { RemoteBuffer } from './http/remoteBuffer' import * as pako from 'pako' +import { isLocalResource } from './utils' type NumericArrayConstructor = | Int8ArrayConstructor @@ -210,9 +211,15 @@ export function parseName(name: string): [number, NumericArrayConstructor]{ offset: number = 0, name: string = '' ) { - this.source = typeof source === 'string' - ? new RemoteBuffer(source) - : source + if(typeof source === 'string'){ + if(isLocalResource(source)){ + throw new Error(`Local resources are not supported: ${source}`) + } + this.source = new RemoteBuffer(source) + } + else{ + this.source = source + } this.offset = offset this.name = name ?? "root" diff --git a/src/ts/src/http/remoteBuffer.ts b/src/ts/src/http/remoteBuffer.ts index 67d87713..78e636c8 100644 --- a/src/ts/src/http/remoteBuffer.ts +++ b/src/ts/src/http/remoteBuffer.ts @@ -7,6 +7,7 @@ import { RemoteValue } from './remoteValue' import {IProgressLogs, RequestTracker} from './requestTracker' import { Logger, NoLog} from './logging' import { RetriableRequest } from './retriableRequest' +import { isLocalResource } from '../utils' let RemoteBufferMaxConcurency = 10 export function setRemoteBufferMaxConcurency(value: number){ @@ -27,6 +28,9 @@ export class RemoteBuffer { private _active: Set = new Set() constructor (url: string) { + if(isLocalResource(url)){ + throw new Error(`Local resources are not supported: ${url}`) + } this.url = url this.logs = new NoLog() this._tracker = new RequestTracker(url, this.logs) From af640ebf6530e047b567fd640c0e6a8d93394240 Mon Sep 17 00:00:00 2001 From: vim-sroberge Date: Thu, 10 Oct 2024 14:11:38 -0400 Subject: [PATCH 204/204] dump --- src/cs/bfast/Vim.BFast.Tests/BFastTests.cs | 1 + .../Vim.Format.Core/Geometry/CatmullClark.cs | 2 +- .../{VimMaterialNext.cs => VimMaterial.cs} | 9 +- .../vim/Vim.Format.Core/Geometry/VimMesh.cs | 188 +++++++------ .../Geometry/{VimShapeNext.cs => VimShape.cs} | 8 +- .../Geometry/GeometryTests.cs | 249 ------------------ .../Geometry/MeshStripsTest.cs | 119 +++++++++ .../Vim.Format.Tests/Geometry/TestShapes.cs | 114 ++++++++ .../Geometry/TestTransformations.cs | 49 ++++ .../Vim.Format.Tests/Geometry/VimMeshTests.cs | 16 ++ .../SerializableDocumentTests.cs | 2 +- .../vim/Vim.Format/SceneBuilder/Validation.cs | 6 +- .../vim/Vim.Format/SceneBuilder/VimScene.cs | 8 +- 13 files changed, 421 insertions(+), 350 deletions(-) rename src/cs/vim/Vim.Format.Core/Geometry/{VimMaterialNext.cs => VimMaterial.cs} (75%) rename src/cs/vim/Vim.Format.Core/Geometry/{VimShapeNext.cs => VimShape.cs} (77%) delete mode 100644 src/cs/vim/Vim.Format.Tests/Geometry/GeometryTests.cs create mode 100644 src/cs/vim/Vim.Format.Tests/Geometry/MeshStripsTest.cs create mode 100644 src/cs/vim/Vim.Format.Tests/Geometry/TestShapes.cs create mode 100644 src/cs/vim/Vim.Format.Tests/Geometry/TestTransformations.cs create mode 100644 src/cs/vim/Vim.Format.Tests/Geometry/VimMeshTests.cs diff --git a/src/cs/bfast/Vim.BFast.Tests/BFastTests.cs b/src/cs/bfast/Vim.BFast.Tests/BFastTests.cs index 7e4a9742..fb2ee1a5 100644 --- a/src/cs/bfast/Vim.BFast.Tests/BFastTests.cs +++ b/src/cs/bfast/Vim.BFast.Tests/BFastTests.cs @@ -6,6 +6,7 @@ namespace Vim.BFastLib.Tests { + [TestFixture] public class BFastTests { public static string ResultPath = Path.Combine(VimFormatRepoPaths.OutDir, "input.bfast"); diff --git a/src/cs/vim/Vim.Format.Core/Geometry/CatmullClark.cs b/src/cs/vim/Vim.Format.Core/Geometry/CatmullClark.cs index 30142230..60bd68bd 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/CatmullClark.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/CatmullClark.cs @@ -137,7 +137,7 @@ public static void CalculateFaceCentroidPoints(VimMesh geometry, Vector3[] outFa var facePoint = new Vector3(); - for (var edgeIndex = 0; edgeIndex < faceSize; edgeIndex++) + for (var edgeIndex = 0; edgeIndex < 3; edgeIndex++) { var vertexIndex = geometry.indices[currentVertexIndex + edgeIndex]; facePoint += geometry.vertices[vertexIndex]; diff --git a/src/cs/vim/Vim.Format.Core/Geometry/VimMaterialNext.cs b/src/cs/vim/Vim.Format.Core/Geometry/VimMaterial.cs similarity index 75% rename from src/cs/vim/Vim.Format.Core/Geometry/VimMaterialNext.cs rename to src/cs/vim/Vim.Format.Core/Geometry/VimMaterial.cs index 07ee1f2e..f2fc1ba8 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/VimMaterialNext.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/VimMaterial.cs @@ -12,24 +12,23 @@ public interface IMaterial float Glossiness { get; } } - - public class VimMaterialNext : IMaterial + public class VimMaterial : IMaterial { public G3dVim g3d; public int index; - public static IEnumerable FromG3d(G3dVim g3d) + public static IEnumerable FromG3d(G3dVim g3d) { for(var i =0; i < g3d.GetMaterialCount(); i++) { - yield return new VimMaterialNext(g3d, i); + yield return new VimMaterial(g3d, i); } } public Vector4 Color => g3d.MaterialColors[index]; public float Smoothness => g3d.MaterialSmoothness[index]; public float Glossiness => g3d.MaterialGlossiness[index]; - public VimMaterialNext(G3dVim g3d, int index) + public VimMaterial(G3dVim g3d, int index) { this.g3d = g3d; this.index = index; diff --git a/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs b/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs index b80c1a0f..57830276 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/VimMesh.cs @@ -3,6 +3,7 @@ using System.Linq; using Vim.G3d; using Vim.Math3d; +using static Vim.Format.DocumentBuilder; namespace Vim.Format.Geometry { @@ -66,8 +67,8 @@ public G3dVim ToG3d() instanceParents: null, instanceFlags: null, meshSubmeshOffsets: new[] { 0 }, - submeshIndexOffsets: new[] { 0 }, - submeshMaterials: new[] { -1 }, + submeshIndexOffsets: submeshIndexOffsets, + submeshMaterials: submeshMaterials, materialColors: null, materialGlossiness: null, materialSmoothness: null, @@ -89,7 +90,6 @@ private static int[] ComputeCounts(int[] offsets, int max) return result; } - public VimMesh(int indexCount, int vertexCount, int submeshCount) { indices = new int[indexCount]; @@ -99,7 +99,7 @@ public VimMesh(int indexCount, int vertexCount, int submeshCount) submeshIndexCounts = new int[submeshCount]; } - public VimMesh Clone() + public VimMesh CloneShallow() { var mesh = new VimMesh( indices, @@ -109,9 +109,21 @@ public VimMesh Clone() ); return mesh; } + + public VimMesh CloneDeep() + { + var mesh = new VimMesh( + indices.ToArray(), + vertices.ToArray(), + submeshIndexOffsets.ToArray(), + submeshMaterials.ToArray() + ); + return mesh; + } + public VimMesh Transform(Matrix4x4 mat) { - var mesh = Clone(); + var mesh = CloneShallow(); for (var i = 0; i < vertices.Length; i++) { @@ -193,77 +205,100 @@ public static VimMesh FromQuad(int[] indices, Vector3[] vertices) return new VimMesh(triIndices, vertices); } - public static IEnumerable GetAllMeshes(G3dVim g3d) + /// + /// Return true if this mesh indices are sequence equal to the given mesh. + /// + public static bool GeometryEquals(this VimMesh mesh, VimMesh other, float tolerance = Math3d.Constants.Tolerance) { - return Enumerable.Range(0, g3d.GetMeshCount()).Select(i => FromG3d(g3d, i)); - } + if (!mesh.indices.SequenceEqual(other.indices)) + return false; - public void SetVertices(Vector3[] vertices) - { - this.vertices = vertices; - } - public void SetIndices(int[] indices) - { - this.indices = indices; + if (!mesh.submeshIndexOffsets.SequenceEqual(other.submeshIndexOffsets)) + return false; + + if (!mesh.submeshMaterials.SequenceEqual(other.submeshMaterials)) + return false; + + if (!mesh.submeshIndexCounts.SequenceEqual(other.submeshIndexCounts)) + return false; + + if (mesh.vertices.Length != other.vertices.Length) + return false; + + for (var i = 0; i < mesh.vertices.Length; i++) + { + if (!mesh.vertices[i].AlmostEquals(other.vertices[i], tolerance)) + return false; + } + + return true; } + public void Validate() { //TODO: Validate better - ValidateIndices(); - } - private void ValidateIndices() - { foreach (var index in indices) { if (index < 0 || index >= NumVertices) throw new Exception($"Invalid mesh index: {index}. Expected a value greater or equal to 0 and less than {NumVertices}"); } } - } - - public static class MeshCommonExtensions - { - public static VimMesh ReverseWindingOrder(this VimMesh mesh) + + /// + /// Reverses triangle winding order of this mesh. + /// + public void ReverseWindingOrder() { - var result = mesh.Clone(); - var count = mesh.indices.Length; - var indices = new int[count]; - for (var i = 0; i < count; i += 3) + for (var i = 0; i < indices.Length; i += 3) { - indices[i + 0] = mesh.indices[i + 2]; - indices[i + 1] = mesh.indices[i + 1]; - indices[i + 2] = mesh.indices[i + 0]; + var tmp = indices[i + 2]; + indices[i + 2] = indices[i]; + indices[i] = tmp; + // indices[i + 1] stays the same } - result.SetIndices(indices); - return result; } - public static int[] GetFaceMaterials(this VimMesh mesh) + public int[] GetFaceMaterials() { // SubmeshIndexOffsets: [0, A, B] // SubmeshIndexCount: [X, Y, Z] // SubmeshMaterials: [L, M, N] // --- // FaceMaterials: [...Repeat(L, X / 3), ...Repeat(M, Y / 3), ...Repeat(N, Z / 3)] <-- divide by 3 for the number of corners per Triangular face - var numCornersPerFace = mesh.NumCornersPerFace; - return mesh.submeshIndexCounts - .SelectMany((indexCount, i) => Enumerable.Repeat(mesh.submeshMaterials[i], indexCount / numCornersPerFace)) - .ToArray(); + + var j = 0; + var result = new int[indices.Length / 3]; + for (var s = 0; s < SubmeshCount; s++) + { + var count = submeshIndexCounts[s] / 3; + var mat = submeshMaterials[s]; + for (var i = 0; i < count; i++) + { + result[j++] = mat; + } + } + return result; } - public static VimMesh Merge2(this VimMesh mesh, params VimMesh[] others) + /// + /// Merges this mesh and all provided meshes as a new mesh. + /// + public VimMesh Merge(params VimMesh[] others) { var meshes = Enumerable.Empty() - .Append(mesh) + .Append(this) .Concat(others) .ToArray(); - return meshes.Merge(); + return MergeAll(meshes); } - public static VimMesh Merge(this VimMesh[] meshes) + /// + /// Merges all provided meshes as one new mesh. + /// + public static VimMesh MergeAll(VimMesh[] meshes) { void Merge(int[] from, int[] to, int offset, int increment) { @@ -301,28 +336,24 @@ void Merge(int[] from, int[] to, int offset, int increment) return result; } - public static VimMesh[] SplitSubmeshes(this VimMesh mesh) + public VimMesh Unindex() { - return null; + var v = indices.Select(i => vertices[i]); + return new VimMesh(v.ToArray()); } - public static (int, List)[] GroupSubmeshesByMaterials(this VimMesh mesh) + } + + public static class MeshExtensions + { + public static IEnumerable GetAllMeshes(this G3dVim g3d) { - var submeshCount = mesh.submeshIndexOffsets.Length; - var map = new Dictionary>(); - for (var i = 0; i < submeshCount; i++) - { - var mat = mesh.submeshMaterials[i]; - if (map.ContainsKey(mat)) - { - map[mat].Add(i); - } - else - { - map.Add(mat, new List() { i }); - } - } - return map.Select(kvp => (kvp.Key, kvp.Value)).ToArray(); + return Enumerable.Range(0, g3d.GetMeshCount()).Select(i => VimMesh.FromG3d(g3d, i)); + } + + public static VimMesh GetMesh(this G3dVim g3d, int index) + { + return VimMesh.FromG3d(g3d, index); } public static Triangle VertexIndicesToTriangle(this VimMesh mesh, Int3 indices) @@ -359,30 +390,23 @@ public static AABox BoundingBox(this VimMesh mesh) public static Int3 FaceVertexIndices(this VimMesh mesh, int faceIndex) => new Int3(mesh.indices[faceIndex * 3], mesh.indices[faceIndex * 3 + 1], mesh.indices[faceIndex * 3 + 2]); - public static bool GeometryEquals(this VimMesh mesh, VimMesh other, float tolerance = Math3d.Constants.Tolerance) + public static (int, List)[] GroupSubmeshesByMaterials(this VimMesh mesh) { - if (!mesh.indices.SequenceEqual(other.indices)) - return false; - - if (!mesh.submeshIndexOffsets.SequenceEqual(other.submeshIndexOffsets)) - return false; - - if (!mesh.submeshMaterials.SequenceEqual(other.submeshMaterials)) - return false; - - if (!mesh.submeshIndexCounts.SequenceEqual(other.submeshIndexCounts)) - return false; - - if (mesh.vertices.Length != other.vertices.Length) - return false; - - for (var i = 0; i < mesh.vertices.Length; i++) + var submeshCount = mesh.submeshIndexOffsets.Length; + var map = new Dictionary>(); + for (var i = 0; i < submeshCount; i++) { - if (!mesh.vertices[i].AlmostEquals(other.vertices[i], tolerance)) - return false; + var mat = mesh.submeshMaterials[i]; + if (map.ContainsKey(mat)) + { + map[mat].Add(i); + } + else + { + map.Add(mat, new List() { i }); + } } - - return true; + return map.Select(kvp => (kvp.Key, kvp.Value)).ToArray(); } public static (int mat, VimMesh mesh)[] SplitByMaterial(this VimMesh mesh) @@ -407,8 +431,6 @@ public static (int mat, VimMesh mesh)[] SplitByMaterial(this VimMesh mesh) public static VimMesh PickSubmeshes(this VimMesh mesh, IList submeshes) { - var map = mesh.GroupSubmeshesByMaterials(); - // Allocate arrays of the final sizes var indexCount = submeshes.Sum(s => mesh.submeshIndexCounts[s]); var result = new VimMesh(indexCount, indexCount, submeshes.Count); diff --git a/src/cs/vim/Vim.Format.Core/Geometry/VimShapeNext.cs b/src/cs/vim/Vim.Format.Core/Geometry/VimShape.cs similarity index 77% rename from src/cs/vim/Vim.Format.Core/Geometry/VimShapeNext.cs rename to src/cs/vim/Vim.Format.Core/Geometry/VimShape.cs index 7c63bdd1..f789981e 100644 --- a/src/cs/vim/Vim.Format.Core/Geometry/VimShapeNext.cs +++ b/src/cs/vim/Vim.Format.Core/Geometry/VimShape.cs @@ -5,7 +5,7 @@ namespace Vim.Format.Geometry { - public class VimShapeNext + public class VimShape { public readonly G3dVim g3d; public readonly int Index; @@ -14,15 +14,15 @@ public class VimShapeNext public Vector4 Color => g3d.ShapeColors[Index]; public float Width => g3d.ShapeWidths[Index]; - public static IEnumerable FromG3d(G3dVim g3d) + public static IEnumerable FromG3d(G3dVim g3d) { for(var i =0; i < g3d.GetShapeCount(); i++) { - yield return new VimShapeNext(g3d, i); + yield return new VimShape(g3d, i); } } - public VimShapeNext(G3dVim g3d, int index) + public VimShape(G3dVim g3d, int index) { var start = g3d.GetShapeVertexStart(index); var count = g3d.GetShapeVertexCount(index); diff --git a/src/cs/vim/Vim.Format.Tests/Geometry/GeometryTests.cs b/src/cs/vim/Vim.Format.Tests/Geometry/GeometryTests.cs deleted file mode 100644 index 2394e627..00000000 --- a/src/cs/vim/Vim.Format.Tests/Geometry/GeometryTests.cs +++ /dev/null @@ -1,249 +0,0 @@ -using NUnit.Framework; -using System; -using System.Linq; -using Vim.Format.Geometry; -using Vim.G3d; -using Vim.Math3d; - -namespace Vim.Format.Tests.Geometry -{ - public static class GeometryTests - { - public static VimMesh XYTriangle = new VimMesh( - new[] { 0, 1, 2 }, new[] { - new Vector3(0f, 0f, 0f), - new Vector3(0f, 1f, 0f), - new Vector3(1f, 0f, 0f) - }); - - public static VimMesh XYQuad = VimMesh.FromQuad( - new int[] { 0, 1, 2, 3 }, new[]{ - new Vector3(0f, 0f, 0f), - new Vector3(0f, 1f, 0f), - new Vector3(1f, 1f, 0f), - new Vector3(1f, 0f, 0f) - }); - - public static VimMesh XYQuadFromFunc = Primitives.QuadMesh(uv => uv.ToVector3(), 1, 1); - public static VimMesh XYQuad2x2 = Primitives.QuadMesh(uv => uv.ToVector3(), 2, 2); - public static VimMesh XYTriangleTwice = XYTriangle.Merge2(XYTriangle.Translate(new Vector3(1, 0, 0))); - - public static VimMesh Tetrahedron = new VimMesh( - new[] { 0, 1, 2, 0, 3, 1, 1, 3, 2, 2, 3, 0 }, new[] { - Vector3.Zero, - Vector3.UnitX, - Vector3.UnitY, - Vector3.UnitZ - }); - - public static VimMesh Torus = Primitives.Torus(10, 0.2f, 10, 24); - - public static VimMesh[] AllMeshes = { - XYTriangle, // 0 - XYQuad, // 1 - XYQuadFromFunc, // 2 - XYQuad2x2, // 3 - Tetrahedron, // 4 - Torus, // 5 - XYTriangleTwice, // 7 - }; - - public static double SmallTolerance = 0.0001; - - public static void GeometryNullOps(VimMesh g) - { - g.GeometryEquals(g); - g.Translate(Vector3.Zero).GeometryEquals(g); - g.Scale(Vector3.Zero).GeometryEquals(g); - g.Transform(Matrix4x4.Identity).GeometryEquals(g); - } - - [Test] - public static void BasicTests() - { - var nMesh = 0; - foreach (var g in AllMeshes) - { - Console.WriteLine($"Testing mesh {nMesh++}"); - g.Validate(); - //ValidateGeometry(g.ToTriMesh()); - } - - Assert.AreEqual(3, XYTriangle.NumCornersPerFace); - Assert.AreEqual(1, XYTriangle.NumFaces); - Assert.AreEqual(3, XYTriangle.vertices.Length); - Assert.AreEqual(3, XYTriangle.indices.Length); - Assert.AreEqual(1, XYTriangle.Triangles().Length); - Assert.IsTrue(XYTriangle.Planar()); - Assert.AreEqual(new[] { 0, 1, 2 }, XYTriangle.indices); - - Assert.AreEqual(3, XYQuad.NumCornersPerFace); - Assert.AreEqual(2, XYQuad.NumFaces); - Assert.AreEqual(4, XYQuad.vertices.Length); - Assert.AreEqual(6, XYQuad.indices.Length); - - Assert.IsTrue(XYQuad.Planar()); - Assert.AreEqual(new[] { 0, 1, 2, 0, 2, 3 }, XYQuad.indices.ToArray()); - - Assert.AreEqual(3, XYQuadFromFunc.NumCornersPerFace); - Assert.AreEqual(2, XYQuadFromFunc.NumFaces); - Assert.AreEqual(4, XYQuadFromFunc.vertices.Length); - Assert.AreEqual(6, XYQuadFromFunc.indices.Length); - - Assert.AreEqual(3, XYQuad2x2.NumCornersPerFace); - Assert.AreEqual(8, XYQuad2x2.NumFaces); - Assert.AreEqual(9, XYQuad2x2.vertices.Length); - Assert.AreEqual(24, XYQuad2x2.indices.Length); - - Assert.AreEqual(3, Tetrahedron.NumCornersPerFace); - Assert.AreEqual(4, Tetrahedron.NumFaces); - Assert.AreEqual(4, Tetrahedron.vertices.Length); - Assert.AreEqual(12, Tetrahedron.indices.Length); - - Assert.AreEqual(3, XYTriangleTwice.NumCornersPerFace); - Assert.AreEqual(2, XYTriangleTwice.NumFaces); - Assert.AreEqual(6, XYTriangleTwice.vertices.Length); - Assert.AreEqual(6, XYTriangleTwice.indices.Length); - Assert.AreEqual(2, XYTriangleTwice.Triangles().Length); - Assert.IsTrue(XYTriangleTwice.Planar()); - Assert.AreEqual(new[] { 0, 1, 2, 3, 4, 5 }, XYTriangleTwice.indices); - } - - [Test] - public static void BasicManipulationTests() - { - foreach (var g in AllMeshes) - GeometryNullOps(g); - } - - [Test] - public static void OutputGeometryData() - { - var n = 0; - foreach (var g in AllMeshes) - { - Console.WriteLine($"Geometry {n++}"); - for (var i = 0; i < g.vertices.Length && i < 10; ++i) - { - Console.WriteLine($"Vertex {i} {g.vertices[i]}"); - } - - if (g.vertices.Length > 10) - { - var last = g.vertices.Length - 1; - Console.WriteLine("..."); - Console.WriteLine($"Vertex {last} {g.vertices[last]}"); - } - - for (var i = 0; i < g.NumFaces && i < 10; ++i) - { - Console.WriteLine($"Face {i}: {g.Triangle(i)}"); - } - - if (g.vertices.Length > 10) - { - var last = g.NumFaces - 1; - Console.WriteLine("..."); - Console.WriteLine($"Face {last}: {g.Triangle(last)}"); - } - } - } - - [Test] - public static void StripIndicesTests() - { - var emptyStrip00 = Primitives.QuadMeshStripIndicesFromPointRows(0, 0); - Assert.AreEqual(0, emptyStrip00.Length); - - var emptyStrip01 = Primitives.QuadMeshStripIndicesFromPointRows(0, 1); - Assert.AreEqual(0, emptyStrip01.Length); - - var emptyStrip10 = Primitives.QuadMeshStripIndicesFromPointRows(1, 0); - Assert.AreEqual(0, emptyStrip10.Length); - - var emptyStrip11 = Primitives.QuadMeshStripIndicesFromPointRows(1, 1); - Assert.AreEqual(0, emptyStrip11.Length); - - var emptyStrip12 = Primitives.QuadMeshStripIndicesFromPointRows(1, 2); - Assert.AreEqual(0, emptyStrip12.Length); - - var emptyStrip21 = Primitives.QuadMeshStripIndicesFromPointRows(2, 1); - Assert.AreEqual(0, emptyStrip21.Length); - - // COUNTER-CLOCKWISE TEST (DEFAULT) - // 2------3 <--- row 1: [2,3] - // | | => counter-clockwise quad: (0,1,3,2) - // | | - // 0------1 <--- row 0: [0,1] - var strip22 = Primitives.QuadMeshStripIndicesFromPointRows(2, 2); - Assert.AreEqual(4, strip22.Length); - Assert.AreEqual(0, strip22[0]); - Assert.AreEqual(1, strip22[1]); - Assert.AreEqual(3, strip22[2]); - Assert.AreEqual(2, strip22[3]); - - // CLOCKWISE TEST - // 2------3 <--- row 1: [2,3] - // | | => clockwise quad: (2,3,1,0) - // | | - // 0------1 <--- row 0: [0,1] - var clockwiseStrip22 = Primitives.QuadMeshStripIndicesFromPointRows(2, 2, true); - Assert.AreEqual(4, clockwiseStrip22.Length); - Assert.AreEqual(2, clockwiseStrip22[0]); - Assert.AreEqual(3, clockwiseStrip22[1]); - Assert.AreEqual(1, clockwiseStrip22[2]); - Assert.AreEqual(0, clockwiseStrip22[3]); - var reversed22 = clockwiseStrip22.Reverse().ToArray(); - for (var i = 0; i < strip22.Length; ++i) - { - Assert.AreEqual(strip22[i], reversed22[i]); - } - - // *------*------* - // | | | - // | | | - // *------*------* - var strip23 = Primitives.QuadMeshStripIndicesFromPointRows(2, 3); - Assert.AreEqual(4 * 2, strip23.Length); - - // *------*------*------* - // | | | | - // | | | | - // *------*------*------* - // | | | | - // | | | | - // *------*------*------* - var strip34 = Primitives.QuadMeshStripIndicesFromPointRows(3, 4); - Assert.AreEqual(4 * 6, strip34.Length); - } - - [Test] - public static void TriangleSerializationTest() - { - //TODO: Check the need for this test. - // Serializing a triangle is that a use case ? - - var mesh = new VimMesh(new[] { 0, 1, 2 }, new[] - { - new Vector3(0, 0, 0), - new Vector3(0, 1, 0), - new Vector3(0, 1, 1) - }); - - var bfast = mesh.ToG3d().ToBFast(); - var result = VimMesh.FromG3d(new G3dVim(bfast)); - - Assert.IsNotNull(mesh); - result.Validate(); - - Assert.AreEqual(3, result.NumVertices); - Assert.AreEqual(new Vector3(0, 0, 0), result.vertices[0]); - Assert.AreEqual(new Vector3(0, 1, 0), result.vertices[1]); - Assert.AreEqual(new Vector3(0, 1, 1), result.vertices[2]); - Assert.AreEqual(1, result.NumFaces); - Assert.AreEqual(0, result.submeshIndexOffsets.Single()); - Assert.AreEqual(-1, result.submeshMaterials.Single()); - Assert.AreEqual(-1, result.GetFaceMaterials().First()); - } - } -} diff --git a/src/cs/vim/Vim.Format.Tests/Geometry/MeshStripsTest.cs b/src/cs/vim/Vim.Format.Tests/Geometry/MeshStripsTest.cs new file mode 100644 index 00000000..bd8b0a0f --- /dev/null +++ b/src/cs/vim/Vim.Format.Tests/Geometry/MeshStripsTest.cs @@ -0,0 +1,119 @@ +using NUnit.Framework; +using System; +using System.Linq; +using Vim.Format.Geometry; + +namespace Vim.Format.Tests.Geometry +{ + internal class MeshStripsTest + { + [Test] + public static void Strip_0_0() + { + var emptyStrip00 = Primitives.QuadMeshStripIndicesFromPointRows(0, 0); + Assert.AreEqual(0, emptyStrip00.Length); + } + + [Test] + public static void Strip_0_1() + { + var emptyStrip01 = Primitives.QuadMeshStripIndicesFromPointRows(0, 1); + Assert.AreEqual(0, emptyStrip01.Length); + } + + [Test] + public static void Strip_1_0() + { + var emptyStrip10 = Primitives.QuadMeshStripIndicesFromPointRows(1, 0); + Assert.AreEqual(0, emptyStrip10.Length); + } + + [Test] + public static void Strip_1_1() + { + var emptyStrip11 = Primitives.QuadMeshStripIndicesFromPointRows(1, 1); + Assert.AreEqual(0, emptyStrip11.Length); + } + + [Test] + public static void Strip_1_2() + { + var emptyStrip12 = Primitives.QuadMeshStripIndicesFromPointRows(1, 2); + Assert.AreEqual(0, emptyStrip12.Length); + } + + [Test] + public static void Strip_2_1() + { + var emptyStrip21 = Primitives.QuadMeshStripIndicesFromPointRows(2, 1); + Assert.AreEqual(0, emptyStrip21.Length); + } + + [Test] + public static void Strip_2_2_CounterClockwise() + { + // COUNTER-CLOCKWISE TEST (DEFAULT) + // 2------3 <--- row 1: [2,3] + // | | => counter-clockwise quad: (0,1,3,2) + // | | + // 0------1 <--- row 0: [0,1] + var strip22 = Primitives.QuadMeshStripIndicesFromPointRows(2, 2); + Assert.AreEqual(4, strip22.Length); + Assert.AreEqual(0, strip22[0]); + Assert.AreEqual(1, strip22[1]); + Assert.AreEqual(3, strip22[2]); + Assert.AreEqual(2, strip22[3]); + } + + [Test] + public static void Strip_2_2_Clockwise() + { + // CLOCKWISE TEST + // 2------3 <--- row 1: [2,3] + // | | => clockwise quad: (2,3,1,0) + // | | + // 0------1 <--- row 0: [0,1] + var clockwiseStrip22 = Primitives.QuadMeshStripIndicesFromPointRows(2, 2, true); + Assert.AreEqual(4, clockwiseStrip22.Length); + Assert.AreEqual(2, clockwiseStrip22[0]); + Assert.AreEqual(3, clockwiseStrip22[1]); + Assert.AreEqual(1, clockwiseStrip22[2]); + Assert.AreEqual(0, clockwiseStrip22[3]); + clockwiseStrip22.Reverse(); + } + + [Test] + public static void Strip_2_2_Reverse() + { + var clockwiseStrip22 = Primitives.QuadMeshStripIndicesFromPointRows(2, 2, true); + var strip22 = Primitives.QuadMeshStripIndicesFromPointRows(2, 2); + + Assert.IsTrue(clockwiseStrip22.Reverse().SequenceEqual(strip22)); + } + + [Test] + public static void Strip_2_3() + { + // *------*------* + // | | | + // | | | + // *------*------* + var strip23 = Primitives.QuadMeshStripIndicesFromPointRows(2, 3); + Assert.AreEqual(4 * 2, strip23.Length); + } + + [Test] + public static void Strip_3_4() + { + // *------*------*------* + // | | | | + // | | | | + // *------*------*------* + // | | | | + // | | | | + // *------*------*------* + var strip34 = Primitives.QuadMeshStripIndicesFromPointRows(3, 4); + Assert.AreEqual(4 * 6, strip34.Length); + } + } +} diff --git a/src/cs/vim/Vim.Format.Tests/Geometry/TestShapes.cs b/src/cs/vim/Vim.Format.Tests/Geometry/TestShapes.cs new file mode 100644 index 00000000..2a1f4d9d --- /dev/null +++ b/src/cs/vim/Vim.Format.Tests/Geometry/TestShapes.cs @@ -0,0 +1,114 @@ +using NUnit.Framework; +using System.Linq; +using System; +using Vim.Format.Geometry; +using Vim.Math3d; + +namespace Vim.Format.Tests.Geometry +{ + public class TestShapes + { + public static VimMesh XYTriangle => new VimMesh( + new[] { 0, 1, 2 }, new[] { + new Vector3(0f, 0f, 0f), + new Vector3(0f, 1f, 0f), + new Vector3(1f, 0f, 0f) + }); + + public static VimMesh XYQuad => VimMesh.FromQuad( + new int[] { 0, 1, 2, 3 }, new[]{ + new Vector3(0f, 0f, 0f), + new Vector3(0f, 1f, 0f), + new Vector3(1f, 1f, 0f), + new Vector3(1f, 0f, 0f) + }); + + public static VimMesh XYQuadFromFunc => Primitives.QuadMesh(uv => uv.ToVector3(), 1, 1); + public static VimMesh XYQuad2x2 => Primitives.QuadMesh(uv => uv.ToVector3(), 2, 2); + public static VimMesh XYTriangleTwice => XYTriangle.Merge(XYTriangle.Translate(new Vector3(1, 0, 0))); + public static VimMesh Tetrahedron => new VimMesh( + new[] { 0, 1, 2, 0, 3, 1, 1, 3, 2, 2, 3, 0 }, new[] { + Vector3.Zero, + Vector3.UnitX, + Vector3.UnitY, + Vector3.UnitZ + }); + + public static VimMesh Torus => Primitives.Torus(10, 0.2f, 10, 24); + + public static VimMesh[] AllMeshes = { + XYTriangle, // 0 + XYQuad, // 1 + XYQuadFromFunc, // 2 + XYQuad2x2, // 3 + Tetrahedron, // 4 + Torus, // 5 + XYTriangleTwice, // 7 + }; + + public static float SmallTolerance = 0.0001f; + + [Test] + public void Test_Triangle() + { + Assert.AreEqual(3, XYTriangle.NumCornersPerFace); + Assert.AreEqual(1, XYTriangle.NumFaces); + Assert.AreEqual(3, XYTriangle.vertices.Length); + Assert.AreEqual(3, XYTriangle.indices.Length); + Assert.AreEqual(1, XYTriangle.Triangles().Length); + Assert.IsTrue(XYTriangle.Planar(SmallTolerance)); + Assert.AreEqual(new[] { 0, 1, 2 }, XYTriangle.indices); + } + + [Test] + public void Test_Quad() + { + Assert.AreEqual(3, XYQuad.NumCornersPerFace); + Assert.AreEqual(2, XYQuad.NumFaces); + Assert.AreEqual(4, XYQuad.vertices.Length); + Assert.AreEqual(6, XYQuad.indices.Length); + Assert.IsTrue(TestShapes.XYQuad.Planar(SmallTolerance)); + Assert.AreEqual(new[] { 0, 1, 2, 0, 2, 3 }, XYQuad.indices); + } + + [Test] + public void Test_QuadFromFunc() + { + Assert.AreEqual(3, XYQuadFromFunc.NumCornersPerFace); + Assert.AreEqual(2, XYQuadFromFunc.NumFaces); + Assert.AreEqual(4, XYQuadFromFunc.vertices.Length); + Assert.AreEqual(6, XYQuadFromFunc.indices.Length); + } + + [Test] + public void Test_Quad2x2() + { + Assert.AreEqual(3, XYQuad2x2.NumCornersPerFace); + Assert.AreEqual(8, XYQuad2x2.NumFaces); + Assert.AreEqual(9, XYQuad2x2.vertices.Length); + Assert.AreEqual(24, XYQuad2x2.indices.Length); + } + + + [Test] + public void Test_Tetrahedron() + { + Assert.AreEqual(3, Tetrahedron.NumCornersPerFace); + Assert.AreEqual(4, Tetrahedron.NumFaces); + Assert.AreEqual(4, Tetrahedron.vertices.Length); + Assert.AreEqual(12, Tetrahedron.indices.Length); + } + + [Test] + public void Test_TriangleTwice() + { + Assert.AreEqual(3, XYTriangleTwice.NumCornersPerFace); + Assert.AreEqual(2, XYTriangleTwice.NumFaces); + Assert.AreEqual(6, XYTriangleTwice.vertices.Length); + Assert.AreEqual(6, XYTriangleTwice.indices.Length); + Assert.AreEqual(2, XYTriangleTwice.Triangles().Length); + Assert.IsTrue(XYTriangleTwice.Planar()); + Assert.AreEqual(new[] { 0, 1, 2, 3, 4, 5 }, XYTriangleTwice.indices); + } + } +} diff --git a/src/cs/vim/Vim.Format.Tests/Geometry/TestTransformations.cs b/src/cs/vim/Vim.Format.Tests/Geometry/TestTransformations.cs new file mode 100644 index 00000000..bd93e37e --- /dev/null +++ b/src/cs/vim/Vim.Format.Tests/Geometry/TestTransformations.cs @@ -0,0 +1,49 @@ +using NUnit.Framework; +using System; +using System.Linq; +using Vim.Format.Geometry; +using Vim.G3d; +using Vim.Math3d; + +namespace Vim.Format.Tests.Geometry +{ + public static class TestTransformations + { + [Test] + public static void IdentityOperations() + { + foreach (var g in TestShapes.AllMeshes) + { + g.GeometryEquals(g); + g.Translate(Vector3.Zero).GeometryEquals(g); + g.Scale(Vector3.Zero).GeometryEquals(g); + g.Transform(Matrix4x4.Identity).GeometryEquals(g); + } + } + + [Test] + public static void ReverseWindingOrder_InvertsTriangle() + { + var t1 = TestShapes.XYTriangle; + var t2 = TestShapes.XYTriangle; + t1.ReverseWindingOrder(); + Assert.That(t1.indices.SequenceEqual(t2.indices.Reverse())); + } + + [Test] + public static void SaveLoad_AllMeshes() + { + foreach (var g in TestShapes.AllMeshes) + { + var g3d = g.ToG3d(); + var bfast = g3d.ToBFast(); + var g3d2 = new G3dVim(bfast); + var result = VimMesh.FromG3d(g3d2); + Assert.IsTrue(g.GeometryEquals(result)); + } + } + + + + } +} diff --git a/src/cs/vim/Vim.Format.Tests/Geometry/VimMeshTests.cs b/src/cs/vim/Vim.Format.Tests/Geometry/VimMeshTests.cs new file mode 100644 index 00000000..16286fb4 --- /dev/null +++ b/src/cs/vim/Vim.Format.Tests/Geometry/VimMeshTests.cs @@ -0,0 +1,16 @@ +using NUnit.Framework; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Vim.Format.Tests.Geometry +{ + [TestFixture] + internal class VimMeshTests + { + + + } +} diff --git a/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs b/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs index cf8fe183..075c41e5 100644 --- a/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs +++ b/src/cs/vim/Vim.Format.Tests/SerializableDocumentTests.cs @@ -160,7 +160,7 @@ public static void CanOpenVim() // mesh.SubmeshMaterials.Sum(); //} - private static void MaterialsAreSame(IMaterial mesh, VimMaterialNext next) + private static void MaterialsAreSame(IMaterial mesh, VimMaterial next) { Assert.AreEqual(mesh.Color, next.Color); Assert.AreEqual(mesh.Glossiness, next.Glossiness); diff --git a/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs b/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs index 8cc998e4..d7ce8e52 100644 --- a/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs +++ b/src/cs/vim/Vim.Format/SceneBuilder/Validation.cs @@ -90,7 +90,7 @@ public static void ValidateShapes(this VimScene vim) { var shapes = vim.Shapes; if (vim.GetShapeCount() != vim.DocumentModel.NumShape) - throw new VimValidationException($"The number of {nameof(VimShapeNext)} ({vim.GetShapeCount()}) does not match the number of shape entities ({vim.DocumentModel.NumShape})"); + throw new VimValidationException($"The number of {nameof(VimShape)} ({vim.GetShapeCount()}) does not match the number of shape entities ({vim.DocumentModel.NumShape})"); void ValidateColorDomain(string label, Vector4 value, Vector4 lowerInclusive, Vector4 upperInclusive, int index) { @@ -112,8 +112,8 @@ void ValidateColorDomain(string label, Vector4 value, Vector4 lowerInclusive, Ve var shape = shapes[shapeIndex]; var element = vim.DocumentModel.GetShapeElementIndex(shapeIndex); if (element < 0) - throw new VimValidationException($"{nameof(Element)} is null for {nameof(VimShapeNext)} {shape.Index}"); - ValidateColorDomain($"{nameof(VimShapeNext)} color", shape.Color, Vector4.Zero, Vector4.One, shape.Index); + throw new VimValidationException($"{nameof(Element)} is null for {nameof(VimShape)} {shape.Index}"); + ValidateColorDomain($"{nameof(VimShape)} color", shape.Color, Vector4.Zero, Vector4.One, shape.Index); }); } diff --git a/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs b/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs index ce5a7cbb..bcafb031 100644 --- a/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs +++ b/src/cs/vim/Vim.Format/SceneBuilder/VimScene.cs @@ -61,8 +61,8 @@ public static VimScene LoadVim(Stream stream, IVimSceneProgress progress = null, public VimSceneNode[] Nodes { get; private set; } public VimMesh[] Meshes { get; private set; } - public VimShapeNext[] Shapes { get; private set; } - public VimMaterialNext[] Materials { get; private set; } + public VimShape[] Shapes { get; private set; } + public VimMaterial[] Materials { get; private set; } public SerializableDocument _SerializableDocument { get; } public Document Document { get; private set; } @@ -206,7 +206,7 @@ private void CreateShapes(bool inParallel) { return; } - Shapes = VimShapeNext.FromG3d(_SerializableDocument.GeometryNext).ToArray(); + Shapes = VimShape.FromG3d(_SerializableDocument.GeometryNext).ToArray(); } private void CreateScene(bool inParallel) @@ -225,7 +225,7 @@ private void CreateMaterials(bool inParallel) { return; } - Materials = VimMaterialNext.FromG3d(_SerializableDocument.GeometryNext).ToArray(); + Materials = VimMaterial.FromG3d(_SerializableDocument.GeometryNext).ToArray(); } public static VimSceneNode[] CreateVimSceneNodes(VimScene scene, G3dVim g3d, bool inParallel)