Jump to content

Some issues about createCylinder function


celian-garcia
 Share

Recommended Posts

Hello !

I made a createSubdividedCylinder() function and I am relatively proud of me ^^ Here is the result :

 

post-8511-0-70547200-1404302564.jpeg

 

But making it, I found some issues :

 

  • firstly, the diameterTop, and diameterBottom are inversed ! For example : when I write it
// My function var myVertexData = createSubdividedCylinder(1, 1, 0.5, 16);var myCylinder = new BABYLON.Mesh("myCylinder", scene);myVertexData.applyToMesh(myCylinder);myCylinder.position.x = -2;// Babylon functionvar babylonVertexData = new BABYLON.VertexData.CreateCylinder(1, 1, 0.5, 16);var babylonCylinder = new BABYLON.Mesh("babylonCylinder", scene);babylonVertexData.applyToMesh(babylonCylinder);babylonCylinder.position.x = 2;

post-8511-0-61889700-1404303395.jpeg

 

We do not obtain the same result whereas both functions have the same header :

var createSubdividedCylinder = function (height, diameterTop, diameterBottom, tessellation, subdivisions) {...};VertexData.CreateCylinder = function (height, diameterTop, diameterBottom, tessellation) {...};
  • Secondly, when we do not have the same diameterBottom & diameterTop, normals are not really the good ones.

- The first picture shows us what we want

- second one shows what we have currently.

Of course blue arrows materializes normals and gray trapeze is the cylinder

 

post-8511-0-19263200-1404304688.png

 

I fixed the first bug but the second is harder to fix so I prefered make a "BABYLON.VertexData.ComputeNormals" after creation to have the good normals.

Link to comment
Share on other sites

In fact I could try to resolve the second bug (about normals) and prepare a pull request.

It would add at the same time the possibility to create subdivided cylinder too. I precise than the function would have exactly the same behaviour than yours but with an additionnal and optionnal parameter : subdivisions, by default equal to 1.

Link to comment
Share on other sites

I surrender ! In fact I had nice values for the normals but these normals was coming from vertices and not faces. And I saw in the computeNormals function that normals have to be computed for faces. So my results are very closed to computeNormals ones but not exactly sames. 

 

It is not really surrending cause I'll make a simple call to the magical computeNormals function at the end like it has be done for the torusknot ^^. 

 

So the new CreateCylinder function is coming soon !

 

 

Here is a comparison in pictures : 

With old function CreateCylinder :

post-8511-0-79380900-1404728169.jpeg

 

With the new function (trying to compute normals)

post-8511-0-39079800-1404728169.jpeg

 

With the new function and computeNormals function (the one I'll make finally)

post-8511-0-87018400-1404728168.jpeg

Link to comment
Share on other sites

Here is the code of the new function CreateCylinder if somebody want :

VertexData.CreateCylinder = function (height, diameterTop, diameterBottom, tessellation, subdivisions) {    var radiusTop = diameterTop / 2;    var radiusBottom = diameterBottom / 2;    var indices = [];    var positions = [];    var normals = [];    var uvs = [];    height          = height || 1;    diameterTop     = diameterTop || 0.5;    diameterBottom  = diameterBottom || 1;    tessellation    = tessellation || 16;    subdivisions    = subdivisions || 1;    subdivisions    = (subdivisions < 1) ? 1 : subdivisions;    var getCircleVector = function (i) {        var angle = (i * 2.0 * Math.PI / tessellation);        var dx = Math.cos(angle);        var dz = Math.sin(angle);        return new BABYLON.Vector3(dx, 0, dz);    };    var createCylinderCap = function (isTop) {        var radius = isTop ? radiusTop : radiusBottom;        if (radius == 0) {            return;        }        var vbase = positions.length / 3;        var offset = new BABYLON.Vector3(0, height / 2, 0);        var textureScale = new BABYLON.Vector2(0.5, 0.5);        if (!isTop) {            offset.scaleInPlace(-1);            textureScale.x = -textureScale.x;        }        // Positions, normals & uvs        for (i = 0; i < tessellation; i++) {            var circleVector = getCircleVector(i);            var position = circleVector.scale(radius).add(offset);            var textureCoordinate = new BABYLON.Vector2(                circleVector.x * textureScale.x + 0.5,                circleVector.z * textureScale.y + 0.5            );            positions.push(position.x, position.y, position.z);            uvs.push(textureCoordinate.x, textureCoordinate.y);        }        // Indices        for (var i = 0; i < tessellation - 2; i++) {            if (!isTop) {                indices.push(vbase);                indices.push(vbase + (i + 2) % tessellation);                indices.push(vbase + (i + 1) % tessellation);            } else {                indices.push(vbase);                indices.push(vbase + (i + 1) % tessellation);                indices.push(vbase + (i + 2) % tessellation);            }        }    };    var base    = new BABYLON.Vector3(0, -1, 0).scale(height / 2);    var offset  = new BABYLON.Vector3(0, 1, 0).scale(height / subdivisions);    var stride  = tessellation + 1;    // Positions, normals & uvs    for (var i = 0; i <= tessellation; i++) {        var circleVector = getCircleVector(i);        var textureCoordinate = new BABYLON.Vector2(i / tessellation, 0);        var position, radius = radiusBottom;        for (var s = 0; s <= subdivisions; s++) {            // Update variables            position = circleVector.scale(radius);            position.addInPlace(base.add(offset.scale(s)));            textureCoordinate.y += 1 / subdivisions;            radius += (radiusTop - radiusBottom)/subdivisions;            // Push in arrays            positions.push(position.x, position.y, position.z);            uvs.push(textureCoordinate.x, textureCoordinate.y);        }    }    subdivisions += 1;    // Indices    for (var s = 0; s < subdivisions - 1; s++) {        for (var i = 0; i <= tessellation; i++) {            indices.push( i * subdivisions + s);            indices.push((i * subdivisions + (s + subdivisions)) % (stride * subdivisions));            indices.push( i * subdivisions + (s + 1));            indices.push( i * subdivisions + (s + 1));            indices.push((i * subdivisions + (s + subdivisions)) % (stride * subdivisions));            indices.push((i * subdivisions + (s + subdivisions + 1)) % (stride * subdivisions));        }    }    // Create flat triangle fan caps to seal the top and bottom.    createCylinderCap(true);    createCylinderCap(false);    // Normals    BABYLON.VertexData.ComputeNormals(positions, indices, normals);    // Result    var vertexData = new BABYLON.VertexData();    vertexData.indices = indices;    vertexData.positions = positions;    vertexData.normals = normals;    vertexData.uvs = uvs;    return vertexData;};
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...