Custom attribute kinds for setVerticesData() and getVerticesData()

setVerticesData() and getVerticesData() don’t allow any attributes to be set/get other than the limited, built-in kinds.

The typical solution I’ve seen on playgrounds is to make use of an unused kind, for example color, to set attributes that have nothing to do with color, making both the javascript and shader code less legible and more error prone IMO.

So here’s the javascript override code that I’ve been using in my projects, to allow creating new attributes that work with setVerticesData() and getVerticesData(), so that I’m not limited to the built in attribute kinds, for example when making a custom shader with ShaderMaterial.

Let me know if making a patch based on this solution or something similar sounds good and I’ll make a PR for it. For example, how about making _CustomStrides a private static member of VertexBuffer and making a static method called RegisterKind that accepts params kind and stride and uses them to set VertexBuffer._CustomStrides[kind] = stride, which would be used in a typescript version of the below DeduceStride function?

VertexBuffer.CustomStrides = {};
VertexBuffer.DeduceStride = function (kind) {
    if (VertexBuffer.CustomStrides[kind]) {
        return VertexBuffer.CustomStrides[kind];
    }

    // NOTE: BELOW IS THE EXACT SAME AS THE EXISTING METHOD
    switch (kind) {
        case VertexBuffer.UVKind:
        case VertexBuffer.UV2Kind:
        case VertexBuffer.UV3Kind:
        case VertexBuffer.UV4Kind:
        case VertexBuffer.UV5Kind:
        case VertexBuffer.UV6Kind:
            return 2;
        case VertexBuffer.NormalKind:
        case VertexBuffer.PositionKind:
            return 3;
        case VertexBuffer.ColorKind:
        case VertexBuffer.MatricesIndicesKind:
        case VertexBuffer.MatricesIndicesExtraKind:
        case VertexBuffer.MatricesWeightsKind:
        case VertexBuffer.MatricesWeightsExtraKind:
        case VertexBuffer.TangentKind:
            return 4;
        default:
            throw new Error("Invalid kind '" + kind + "'");
    }
};

I am not sure this is something we want here as there are quite a few other places in VertexData with the same logic.

The good news is that the buffer can have a stride defined through the Buffer constructor and it is possible to also rely on Geometry directly to create custom attributes.

@Deltakosh, any thoughts ?

1 Like

Ooh, I didn’t know this could be done already. :+1:

Do you know of an example, in the docs or in a playground, that shows an attribute being defined and its values being set for an existing geometry’s vertices so I can learn how to do it please? :slightly_smiling_face:

Or, for instance, if I create a box mesh with the MeshBuilder and create a shader with ShaderMaterial that has an attribute named level, of type vec2, then how do I set the values for this attribute? The way I’ve been doing it is by calling boxMesh.setVerticesData() like below:

VertexBuffer.CustomStrides[“level”] = 2;
boxMesh.setVerticesData(“level”, levels);

Edit: OMG, setVerticesData has param stride. LOL, never mind then, it’s just:

boxMesh.setVerticesData(“level”, levels, false, 2);

LOL I assumed there wasn’t a way to specify the stride because of all the playgrounds I’d seen using the color kind for setting attributes named color that have nothing to do with color LOL. That’s what I get for not reading the api doc for setVerticesData in the first place LOL :laughing:

2 Likes