It'd be great to explore a method for laying out the data of components in a 'linear' manner, as seen in the sparse set ECS approach. I originally had ideas about using Typed Arrays for all primitives in components, because I have some understanding of how to get them to all share the same ArrayBuffer, but as @MaxGraey points out in PR #1 this is less than ideal due to the extra layer of abstraction.
I would love to learn how this can be achieved in AssemblyScript, I suppose the ideal solution would have the following:
Reserve a chunk of memory for an array of components
Specify a location/offset when a class is allocated
Provide a way to pass this to the javascript WebGL API
Allow the underlying chunk to be resized/reallocated?
Here's an example to hopefully clarify the problem that I'm having:
class MyComponent{
valA: f32
valB: Vector3
static byteStride: u16 = 32 // could this be auto generated?
}
const initialComponentCount = 10
//this is my imaginary alternative to ArrayBuffer
const componentPool = new MemoryAllocation(MyComponent.byteStride * initialComponentCount)
function addComponentToPool(index: u16){
//somehow the new instance is assigned to that location in memory
componentPool.set(new MyComponent(), MyComponent.byteStride * index)
}
function getComponentAtIndex(index:u16):MyComponent{
return componentPool.get(MyComponent.byteStride * index)
}
function doJavascriptWebGLThingWithComponent(index:u16){
// it may be better to do this cast in JS, so that we dont need to copy the data across on each usage
const poolAsBufferView = Uint8Array.from(componentPool)
const byteOffset = MyComponent.byteStride * index
gl.bufferData(gl.ArrayBuffer,poolAsBufferView,gl.STATIC_DRAW,byteOffset,MyComponent.stride)
}
note: it looks like according to this stack overflow, passing in a Uint8Array as a view for data that may actually be floats etc is ok
Edit: Just discovered the following functions, perhaps some combination may do the trick:
export declare function load<T>(ptr: usize, immOffset?: usize, immAlign?: usize): T;
export declare function store<T>(ptr: usize, value: auto, immOffset?: usize, immAlign?: usize): void;
export declare function sizeof<T>(): usize; // | u32 / u64
export declare function alignof<T>(): usize; // | u32 / u64
export declare function offsetof<T>(fieldName?: string): usize; // | u32 / u64
export declare function changetype<T>(value: auto): T;
It'd be great to explore a method for laying out the data of components in a 'linear' manner, as seen in the sparse set ECS approach. I originally had ideas about using Typed Arrays for all primitives in components, because I have some understanding of how to get them to all share the same ArrayBuffer, but as @MaxGraey points out in PR #1 this is less than ideal due to the extra layer of abstraction.
I would love to learn how this can be achieved in AssemblyScript, I suppose the ideal solution would have the following:
Here's an example to hopefully clarify the problem that I'm having:
Edit: Just discovered the following functions, perhaps some combination may do the trick: