How to correctly parse collada files for WebGL ? (example included)
Asked Answered
M

1

6

This is my current result:

incorrect collada model parsing

As you can see the models have a bunch of gaps in them. My guess, why this happens would be, that I somehow need to include the <vcount> data in the <polylist> element, which is supposed to determine the vertex count for each plane(?). Since WebGL can only draw 3 sided polygons, this can't seem to work. If my assumption so far is correct, I'd need to slice all the quadrilaterals into two triangles each.

I've already done a lot of research on collada parsing with WebGL, but almost every site redirected me to several WebGL libraries which have such functionality already implemented (so please don't do the same). I always start out by writing all the core functionality myself to get a better grasp on how things internally work.

Here is my parse function:

function load_collada(gl, program, path) {
    var request = new XMLHttpRequest(),

        buffers = {
            vbo: gl.createBuffer(),
            nbo: gl.createBuffer(),
            ibo: gl.createBuffer(),

            aVertex: gl.getAttribLocation(program, "aVertex"),
            aNormal: gl.getAttribLocation(program, "aNormal")
        },

        mesh,
        vertices,
        indicesList,
        normals = [],
        indices = [];

    request.open("GET", path, false);
    request.overrideMimeType("text/xml");
    request.send();

    mesh = request.responseXML.querySelector("mesh");

    vertices = mesh.querySelectorAll("float_array")[0].textContent.split(" ");
    normals = mesh.querySelectorAll("float_array")[1].textContent.split(" ");
    indicesList = mesh.querySelectorAll("polylist p")[0].textContent.split(" ");

    for (i=0 ; i < indicesList.length; i+=2) { indices.push(indicesList[i]); }

    buffers.vbo.count = parseInt(mesh.querySelectorAll("float_array")[0].getAttribute("count"), 10); 
    buffers.nbo.count = normals.length;
    buffers.ibo.count = indices.length;

    gl.bindBuffer(gl.ARRAY_BUFFER, buffers.vbo);
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
    gl.vertexAttribPointer(buffers.aVertex, 3, gl.FLOAT, true, 0, 0);
    gl.enableVertexAttribArray(buffers.aVertex);

    gl.bindBuffer(gl.ARRAY_BUFFER, buffers.nbo);
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(normals), gl.STATIC_DRAW);
    gl.vertexAttribPointer(buffers.aNormal, 3, gl.FLOAT, true, 0, 0);
    gl.enableVertexAttribArray(buffers.aNormal);

    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, buffers.ibo);
    gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);

    return buffers;
}

I'm also not quite sure why the normals have indices aswell, but I'm ignoring them by adding only each second value from the indicesList.

My draw routine is simply gl.drawElements(gl.TRIANGLE_STRIP, program.models[i].ibo.count, gl.UNSIGNED_SHORT, 0);.

I'd greatly appriciate any solutions or advices on this problem.


Update: After playing around with this parser again, I noticed, that the parse function above (even with correctly exported models) won't won't display the normals correctly. You'd have to alter the data so that the vertices are defined per face and not per unique position.

Magnetometer answered 14/2, 2013 at 19:17 Comment(5)
Even if you don't use, say, three.js, why not just look to see what they did? It's all right there and nicely structured, so it's straightforward to read. See if it fits with your understanding of the COLLADA polys.Putrefaction
You image looks like you are drawing two triangles per quad, but for a quad with verts ABCD, you are drawing ABC and DBC -- not ABC and CDAPutrefaction
@Putrefaction Well good luck finding the solution in this 4k lines script: github.com/arcanis/issue.three.js.collada/blob/master/… I don't really need to parse scenes and animations right now though, just want to get the mesh parsed correctly.Magnetometer
try coloring triangles randomly, or every-other red-blue ... see if my second comment is correct.Are you saying that you can't be bothered looking at correctly-working code, but you want others to expand, install, and debug your broken code, of possibly simialr size?Putrefaction
My entire code isn't nearly as large as this single file. I just provided it for others to see the potential changes they make to the parsing function I pasted above. I simply don't understand what's happening in this plugin, especially since I don't know three.js yet. Also I can't just colour the "black" triangles, since I'd have to split the quads first (or rather extend them). Not sure how easy this is, but I'll try that now if my aussumption is indeed correct.Magnetometer
M
0

Found a potential solution. Before you export your model in blender, you need to add a decimate modifier. Check triangulate and set the ratio to 0.9900 (one click on the left arrow).

Edit: There is actually a triangulate modifier, so use this one instead.

So in the end your sphere mesh for example would look like this:

enter image description here

Magnetometer answered 15/2, 2013 at 8:26 Comment(1)
New in Blender 2.68a - the Collada exporter automatically triangulates the mesh during export without altering the mesh itself. This avoids needing to do that step manually. More usefully, it retains the quads (eg, 6 quads for cube) in the mesh. So you can model as desired and let the exporter triangulate it "invisibly and magically" during the export operation.Business

© 2022 - 2024 — McMap. All rights reserved.