Skip to content

Commit

Permalink
Generally seems to be working but something is off with the scaling i…
Browse files Browse the repository at this point in the history
…n the animSkin function, causing the whale to be very droopy and elongated
  • Loading branch information
cmhhelgeson committed Jan 29, 2024
1 parent 615932b commit a808cbe
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 23 deletions.
28 changes: 22 additions & 6 deletions src/sample/skinnedMesh/glbUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,18 @@ import { Mat4, Vec3, mat4 } from 'wgpu-matrix';

//NOTE: GLTF code is not generally extensible

// Determines the topology of our pipeline
enum GLTFRenderMode {
POINTS = 0,
LINE = 1,
LINE_LOOP = 2,
LINE_STRIP = 3,
TRIANGLES = 4,
TRIANGLE_STRIP = 5,
// Note= fans are not supported in WebGPU, use should be
// an error or converted into a list/strip
TRIANGLE_FAN = 6,
}

// Determines how to interpret each element of the structure that is accessed from our accessor
enum GLTFDataComponentType {
BYTE = 5120,
UNSIGNED_BYTE = 5121,
Expand All @@ -27,6 +27,7 @@ enum GLTFDataComponentType {
DOUBLE = 5130,
}

// Determines how to interpret the structure of the values accessed by an accessor
enum GLTFDataStructureType {
SCALAR = 0,
VEC2 = 1,
Expand Down Expand Up @@ -550,11 +551,13 @@ export class GLTFNode {
} else {
mat4.copy(this.localMatrix, this.worldMatrix);
}
const worldMatrix = this.worldMatrix;
const worldMatrix = this.worldMatrix as Float32Array;
device.queue.writeBuffer(
this.nodeTransformGPUBuffer,
0,
worldMatrix as Float32Array
worldMatrix.buffer,
worldMatrix.byteOffset,
worldMatrix.byteLength
);
for (const child of this.children) {
child.updateWorldMatrix(device, worldMatrix);
Expand Down Expand Up @@ -632,12 +635,18 @@ export class GLTFScene {
}

export class GLTFSkin {
// Inverse bind matrices parsed from the accessor
inverseBindMatrices: Float32Array;
inverseBindMatricesUniformBuffer: GPUBuffer;
// Nodes of the skin's joints
// [5, 2, 3] means our joint info is at nodes 5, 2, and 3
joints: number[];
jointGPUBuffer: GPUBuffer;
// Bind Group for this skin's uniform buffer
skinBindGroup: GPUBindGroup;
// Static bindGroupLayout shared across all skins
// In a larger shader with more properties, certain bind groups
// would likely have to be combined due to device limitations in the number of bind groups
// allowed within a shader
static skinBindGroupLayout: GPUBindGroupLayout;
private jointMatrices: Mat4[];

Expand Down Expand Up @@ -685,6 +694,7 @@ export class GLTFSkin {
inverseBindMatricesAccessor.view.view.byteOffset,
inverseBindMatricesAccessor.view.view.byteLength / 4
);
console.log(this.inverseBindMatrices);
this.joints = joints;
this.inverseBindMatricesUniformBuffer = device.createBuffer({
size: Float32Array.BYTES_PER_ELEMENT * 16 * joints.length,
Expand Down Expand Up @@ -712,7 +722,7 @@ export class GLTFSkin {
mat4.multiply(globalWorldInverse, nodes[joint].worldMatrix, dstMatrix);
const startMatrixAccess = j * 16;
const endMatrixAccess = startMatrixAccess + 16;
const inverseBindMatrix: Mat4 = this.inverseBindMatrices.subarray(
const inverseBindMatrix: Mat4 = this.inverseBindMatrices.slice(
startMatrixAccess,
endMatrixAccess
);
Expand Down Expand Up @@ -849,6 +859,11 @@ export const convertGLBToJSONAndBinary = async (
for (const attr in prim['attributes']) {
const accessor = accessors[prim['attributes'][attr]];
primitiveAttributeMap[attr] = accessor;
if (accessor.structureType > 3) {
throw Error(
'Vertex attribute accessor accessed an unsupported data type for vertex attribute'
);
}
attributes.push(attr);
}
meshPrimitives.push(
Expand Down Expand Up @@ -886,6 +901,7 @@ export const convertGLBToJSONAndBinary = async (
const nodes: GLTFNode[] = [];

console.log(jsonChunk.skins);
console.log(skins);

// Access each node. If node references a mesh, add mesh to that node
const nodeUniformsBindGroupLayout = device.createBindGroupLayout({
Expand Down
4 changes: 1 addition & 3 deletions src/sample/skinnedMesh/gltf.ts
Original file line number Diff line number Diff line change
Expand Up @@ -256,9 +256,7 @@ export interface Sampler {
extras?: any;
[k: string]: any;
}
/**
* The root nodes of a scene.
*/

export interface Scene {
nodes?: GlTfId[];
name?: any;
Expand Down
15 changes: 11 additions & 4 deletions src/sample/skinnedMesh/gltf.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,16 @@ struct VertexOutput {
struct CameraUniforms {
projMatrix: mat4x4f,
viewMatrix: mat4x4f,
modelMatrix: mat4x4f,
model_matrix: mat4x4f,
}

struct GeneralUniforms {
render_mode: u32
render_mode: u32,
skin_mode: u32,
}

struct NodeUniforms {
worldMatrix: mat4x4f,
world_matrix: mat4x4f,
}

@group(0) @binding(0) var<uniform> camera_uniforms: CameraUniforms;
Expand All @@ -43,7 +44,13 @@ fn vertexMain(input: VertexInput) -> VertexOutput {
joint_matrices[input.joints[1]] * input.weights[1] +
joint_matrices[input.joints[2]] * input.weights[2] +
joint_matrices[input.joints[3]] * input.weights[3];
output.Position = camera_uniforms.projMatrix * camera_uniforms.viewMatrix * camera_uniforms.modelMatrix * vec4<f32>(input.position.x, input.position.y, input.position.z, 1.0);
let world_position = vec4<f32>(input.position.x, input.position.y, input.position.z, 1.0);
let skinned_position = select(
camera_uniforms.model_matrix * world_position,
camera_uniforms.model_matrix * skin_matrix * node_uniforms.world_matrix * world_position,
general_uniforms.skin_mode == 0
);
output.Position = camera_uniforms.projMatrix * camera_uniforms.viewMatrix * skinned_position;
output.normal = input.normal;
output.joints = vec4<f32>(f32(input.joints[0]), f32(input.joints[1]), f32(input.joints[2]), f32(input.joints[3]));
// Convert to f32 to avoid flat interpolation error
Expand Down
14 changes: 7 additions & 7 deletions src/sample/skinnedMesh/grid.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ struct CameraUniforms {

struct GeneralUniforms {
render_mode: u32,
skin_mode: u32,
}

struct BoneUniforms {
Expand All @@ -41,17 +42,16 @@ fn vertexMain(input: VertexInput) -> VertexOutput {
let bone2 = bone_uniforms.bones[u32(input.bone_index[2])];
let bone3 = bone_uniforms.bones[u32(input.bone_index[3])];
// Bone transformed mesh
output.Position =
camera_uniforms.projMatrix *
camera_uniforms.viewMatrix *
camera_uniforms.modelMatrix *
output.Position = select(
camera_uniforms.projMatrix * camera_uniforms.viewMatrix * camera_uniforms.modelMatrix * position,
camera_uniforms.projMatrix * camera_uniforms.viewMatrix * camera_uniforms.modelMatrix *
(bone0 * position * input.bone_weight[0] +
bone1 * position * input.bone_weight[1] +
bone2 * position * input.bone_weight[2] +
bone3 * position * input.bone_weight[3]);
bone3 * position * input.bone_weight[3]),
general_uniforms.skin_mode == 0
);

// Normal, unaffected mesh
//output.Position = camera_uniforms.projMatrix * camera_uniforms.viewMatrix * camera_uniforms.modelMatrix * position;
//Get unadjusted world coordinates
output.world_pos = position.xyz;
output.bone_index = input.bone_index;
Expand Down
17 changes: 14 additions & 3 deletions src/sample/skinnedMesh/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ enum RenderMode {
WEIGHTS,
}

enum SkinMode {
ON,
OFF
}

const getRotation = (mat: Mat4): Quat => {

Check failure on line 32 in src/sample/skinnedMesh/main.ts

View workflow job for this annotation

GitHub Actions / build

'getRotation' is assigned a value but never used
const out = [0, 0, 0, 0];
const scaling = mat4.getScaling(mat);
Expand Down Expand Up @@ -105,6 +110,7 @@ const init: SampleInit = async ({
speed: 10,
object: 'Whale',
renderMode: 'NORMAL',
skinMode: 'ON',
};

gui.add(settings, 'object', ['Whale', 'Skinned Grid']).onChange(() => {
Expand All @@ -122,6 +128,9 @@ const init: SampleInit = async ({
gui.add(settings, 'renderMode', ['NORMAL', 'JOINTS', 'WEIGHTS']).onChange(() => {
device.queue.writeBuffer(generalUniformsBuffer, 0, new Uint32Array([RenderMode[settings.renderMode]]));
});
gui.add(settings, 'skinMode', ['ON', 'OFF']).onChange(() => {
device.queue.writeBuffer(generalUniformsBuffer, 4, new Uint32Array([SkinMode[settings.skinMode]]));
})
const cameraFolder = gui.addFolder('Camera Settings');
const cameraXController = cameraFolder.add(settings, 'cameraX', -10, 10).step(0.1);
const cameraYController = cameraFolder.add(settings, 'cameraY', -10, 10).step(0.1);
Expand All @@ -131,7 +140,6 @@ const init: SampleInit = async ({
animFolder.add(settings, 'angle', 0.1, 1.0).step(0.1);
animFolder.add(settings, 'speed', 10, 100).step(10);

// Create global resources
const depthTexture = device.createTexture({
size: [canvas.width, canvas.height],
format: 'depth24plus',
Expand All @@ -154,7 +162,7 @@ const init: SampleInit = async ({
);

const generalUniformsBuffer = device.createBuffer({
size: Uint32Array.BYTES_PER_ELEMENT,
size: Uint32Array.BYTES_PER_ELEMENT * 2,
usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
});

Expand Down Expand Up @@ -348,12 +356,14 @@ const init: SampleInit = async ({
const origMatrix = origMatrices.get(joint);
const m = mat4.rotateX(origMatrix, angle);
whaleScene.nodes[joint].source.position = mat4.getTranslation(m);
// Something wrong with scaling
whaleScene.nodes[joint].source.position = mat4.getScaling(m);
whaleScene.nodes[joint].source.rotation = getRotation(m);

}
}

console.log(whaleScene.nodes)

function frame() {
// Sample is no longer the active page.
if (!pageState.active) return;
Expand Down Expand Up @@ -420,6 +430,7 @@ const init: SampleInit = async ({

// Updates skins (we index into skins in the renderer, which is not the best approach but hey)
animSkin(whaleScene.skins[0], Math.sin(t) * .5)
// Node 6 should be the only node with a drawable mesh so hopefully this works fine
whaleScene.skins[0].update(device, whaleScene.nodes[6], whaleScene.nodes)


Expand Down

0 comments on commit a808cbe

Please sign in to comment.