logunov Posted October 25, 2018 Share Posted October 25, 2018 Good day everyone. I am now works on my own huge project, which uses a lot of mathematical models. So, the problem is ,I have mathematical model of hexasphere from there https://github.com/arscan/hexasphere.js/blob/master/src/face.js And I need to create meshes from vertex data of this model. I'm using this: //hexaSphere - is object, created with library upper for (let i = 0; i < hexaSphere.tiles.length; i++) { let centerpoint = data.centerPoint; let x = centerpoint.x; let y = centerpoint.y; let z = centerpoint.z; let spawnVec = new BABYLON.Vector3(x, y, z); //here I should instantiace center of vector let buildPoints = []; for (let j = 0; j<data.boundary.length; j++){ let x = data.boundary[j].x; let y = data.boundary[j].y; let z = data.boundary[j].z; let point = new BABYLON.Vector3(parseFloat(x), parseFloat(y), parseFloat(z)); buildPoints.push(point); } let polygonalMesh = new BABYLON.MeshBuilder.CreatePolygon(""+i, {shape:buildPoints}, scene); } So, the result of this is (please, do not look on colored spheres and sticks, It was hard to remove from my project because of bad architecture, they are do not touching this part of code, it is isolated): It is not 3D, but 2D projections of each hexagon or pentagon to the XoZ BABYLON plane. I started to think about position, as "How to" said, but polygonalMesh.position = spawnVec; give me that result: How can I create meshes from vertices data in 3D space? I just can not test rotation, because if it's correct, it can be visible to match each other borders of morphed meshes. There is no way to use loaded mesh, because each of hexagon is different. This mathematical model do not use right hexagons, because it is hard co connect (mathematical theorem). And I am sure this library is correct, because I tested it with right hexagon (imported mesh with babylon-loaders.js, created it on blender) and tried to match each other rotation, so I got next result (green dots is rotation co-surface normales, do not look on them): And everything with math was fine: blue dots is 2 of 6 or 5 border points, red is centerPoints. I do not have right now screen of whole sphere, but it was sphere, not was MeshBuilder created. I just putted a copy of IMPORTED model on each center and rotated it with some linear algebra to check everything, before post here. So, my question is: how can I create polygonal mesh in 3D space, not his 2D projection, using BABYLON.MeshBuilder (or other BABYLON solution), because displacement of right hexagons and this mathematical model is too huge for acceptance (impossible to play, looks ugle and other), so I need dynamical creation. p.s There is impossible to create lovely playground example, because of library, but http://playground.babylonjs.com/#4G18GY#67 have the same problem. In arguments of array have all 3D spaces, but it is creating just 2D projection. Quote Link to comment Share on other sites More sharing options...
JohnK Posted October 25, 2018 Share Posted October 25, 2018 Hi @logunov and welcome to the forum. Strictly speaking a polygon is always 2D and so if passing data to create a polygon using a 3D vector then x, y and z must be in the same plane. As it states in the docs for createPolygon https://doc.babylonjs.com/how_to/parametric_shapes#non-regular-polygon All vectors for shape and holes are Vector3 and should be in the XoZ plane, ie of the form BABYLON.Vector3(x, 0, z) and in counter clockwise order; The 3D equivalent is a polyhedron (plural polyhedra). You may find this page of the docs useful https://doc.babylonjs.com/how_to/polyhedra_shapes or if you are working from a particular data set this page https://doc.babylonjs.com/how_to/custom logunov and ssaket 2 Quote Link to comment Share on other sites More sharing options...
jerome Posted October 26, 2018 Share Posted October 26, 2018 a double sided hexa builf from the disc shape in one line : http://playground.babylonjs.com/#4G18GY#68 ssaket and JohnK 2 Quote Link to comment Share on other sites More sharing options...
JohnK Posted October 26, 2018 Share Posted October 26, 2018 4 hours ago, jerome said: a double sided hexa builf from the disc shape I believe that logunov wants this 3D shape http://geek-mag.com/posts/248214/ EDIT from the site lugonuv mentions it is built from an icosphere unfortunately I am too busy at the moment to do any more with it. Quote Link to comment Share on other sites More sharing options...
logunov Posted October 26, 2018 Author Share Posted October 26, 2018 Thx for the help, I am trying to test solution presented by @JohnK (create custom Polyhedra) He is right, I need exactly the same sphere (but with pentagons, ofcourse, and with independed pentagons and meshes, not as single object), but arscan hexasphere library produce not regular hexagons, but irregular. It is not visible by eye, but if I trying to use this with regular (right) hexagon imported model, it is making huge displacement, so I need to dynamically create meshes from array of points, because there is 77 variants of irregular displaced hexagons, which creating hexasphere in arscan hexasphere library, so that is the reason why @jerome method not works for me (it is creating right (regular) hexagon, but I need irregular one, but if it is irregular one, it is not guarantee to me, that it will match mathematical). Now, I am trying something like this (part from my code): for (let i = 0; i < hexaSphere.tiles.length; i++) { let data = hexaSphere.tiles[i]; let centerpoint = data.centerPoint; let x = centerpoint.x; let y = centerpoint.y; let z = centerpoint.z; let spawnVec = new BABYLON.Vector3(x, y, z); let buildPoints = []; for (let j = 0; j<data.boundary.length; j++){ let x = data.boundary[j].x; let y = data.boundary[j].y; let z = data.boundary[j].z; let point = new BABYLON.Vector3(parseFloat(x), parseFloat(y), parseFloat(z)); buildPoints.push(point); } let faceIndexPoints = []; for (let k = 0; k<hexaSphere.tiles[i].faces.length; k++){ faceIndexPoints.push(k); } let irregularHexagon = { "name": "irregularHexagon", "category": ["Hexagon"], "vertex": buildPoints, //aray of points, which represent like [x,y,z] array "face": faceIndexPoints, //array of indices of vertex vector, each of array in array represent face; }; let customHex = BABYLON.MeshBuilder.CreatePolyhedron("", {custom: irregularHexagon}, scene); but for now it have no result (nothing created). Now it's time to check is the points of face object in hexasphere object sorted or not, to push them counter-clockwise, like @JohnK and "How to" said. (Ofcourse I will do it by my own, I just talks my ideas). I do not need this hexaSphere as monoObject (single mesh), but independent hexes, which forms the sphere, there is a reason, why I am trying to morph it from mathematical data, and the reason, why I do not used imported model is written upper by me. In other words I need to create 77 irregular hexagons, different from each other, as independent meshes and put them on hexaSphere surface from mathematical library (not builded with MeshBuilder, because this is not what I need, it will create huge displacement and wrong rotations). The whole idea is put mathematical hexasphere surface net of dots in BABYLON space, create meshes, which will match the mathematical model, and works with mathematical model in whole code. My big thanks for advices and notes, I will try to create my idea and will post any result, if it will succeed. I will be grateful for any other notes and tips. btw, I forget to say: on the third screen of first post you can see white and grey hexagons. The grey ones is imported regular (right) hexagons from blender, the white ones is rendered object from arscan library >whole< hexasphere (it can't render each hexagon independent), so you can see the displacement between imported and mathematical objects visually. Ofcourse, that is the third reason, why I need morph function of BABYLON, because it is impossible to create 77 irregular types of hexagons (I calculated that by surface formula and sorted by set in javascript to know that amount in 6 level of subdivision), and impossible to find and match each other easily to match this. And the problem not in the size, but in the rotation displacement between borders and planes, created with dots of hexagon, it is impossible to match grey ones for white ones, cuz they are much more different. upd: In examples of create custom polyhedra I saw that vertices is array of arrays, am I correct if I need only one face, so I need just make one array in array which contains points? I checked both: "face": [faceIndexPoints] "face": faceIndexPoints And everything gave me empty scene as result.I will post news, when I will done my tests. Quote Link to comment Share on other sites More sharing options...
ssaket Posted October 26, 2018 Share Posted October 26, 2018 Few weeks back, I was trying to do something similar but slightly different, I was trying to delete a vertex and then re-calculate the indices using delaunay's 3d triangulation but none of the available js algorithms give the correct result (whether mapbox or any other), This one gives a 3d tetrahedron (https://github.com/mikolalysenko/delaunay-triangulate)... Moreover, now I think my problem can be solved by hole filling algorithm..... have to work on the implementation..... Coming back to generating the indices from the verdata, you can check CGAL's 3d triangulation algorithm.(https://doc.cgal.org/latest/Triangulation_3/index.html). and can use it as a REST API using crow (https://github.com/ssaket/cgal-crow) , but again not sure whether this will work ! logunov 1 Quote Link to comment Share on other sites More sharing options...
logunov Posted October 27, 2018 Author Share Posted October 27, 2018 Posting news of my tries here, so, after tests I got this result (do not look at any grey sphere, it is from isolated part of code): The code, to reproduce this is: for (let i = 0; i < hexaSphere.tiles.length; i++) { let data = hexaSphere.tiles[i]; let centerpoint = data.centerPoint; let x = centerpoint.x; let y = centerpoint.y; let z = centerpoint.z; let spawnVec = new BABYLON.Vector3(x, y, z); let createIrregularHexagon = function(name,scene, vertices, indices, normals){ let verData = new BABYLON.VertexData(); BABYLON.VertexData.ComputeNormals(vertices, indices, normals); verData.positions = vertices; verData.indices = indices; verData.normals = normals; let polygon = new BABYLON.Mesh(name,scene); verData.applyToMesh(polygon); polygon.convertToFlatShadedMesh(); //what is it doing? return polygon; }; let positions = []; let indices = []; let normals = []; console.log(hexaSphere.tiles[i].faces.length); for (let j = 0; j<hexaSphere.tiles[i].faces.length; j++){ for(let k = 0; k<hexaSphere.tiles[i].faces[j].points.length; k++){ let x = hexaSphere.tiles[i].faces[j].points[k].x; let y = hexaSphere.tiles[i].faces[j].points[k].y; let z = hexaSphere.tiles[i].faces[j].points[k].z; positions.push(x,y,z); indices.push(indices.length); } } let u = 0; while (u<positions.length){ let x1 = positions[u]; let y1 = positions[u+1]; let z1 = positions[u+2]; let x2 = positions[u+3]; let y2 = positions[u+4]; let z2 = positions[u+5]; u+=6; let v1 = new BABYLON.Vector3(x1,y1,z1); let v2 = new BABYLON.Vector3(x2,y2,z2); let result = BABYLON.Vector3.Cross(v1,v2); normals.push(result.x, result.y, result.z); } let poly = createIrregularHexagon("1",scene,positions,indices,normals); let myMaterial = new BABYLON.StandardMaterial("myMaterial", scene); myMaterial.diffuseColor = new BABYLON.Color3(1, 0, 1); myMaterial.specularColor = new BABYLON.Color3(0.5, 0.6, 0.87); myMaterial.emissiveColor = new BABYLON.Color3(1, 1, 1); myMaterial.ambientColor = new BABYLON.Color3(0.23, 0.98, 0.53); poly.material = myMaterial; } As you can see on the screen upper, the red sphere on the background is object, placed in the mathematical center of the hexagon. Now I am thinking, why vertex data connecting it like triangles, but it should look not like this, because faces in the hexasphere object is triangles, so in my cycle I am pushing 5 to 6 triangles (15 to 18 points or 45 to 54 coordinates by triples) in my points array, and for each dot I am adding one new index, so, each duplicate point in faces will be indexed correct, but as you can see, result shows me it like wrong, so it's connecting absolutely wrong points, which do not represent hexagons individually. But for some reasons all 12 pentagons created correct. I am showing one of them, but I checked them all (again repeating, please, do not look at grey sphere). This may confuse, but this pentagon created incorrect, because grey mesh must be in center of pentagon or hexagon. Short in other words, this algorithm for some reason not rendering nor creating 3 of 6 faces of each hexagon, I do not have any idea, why he is doing this. Have any one ideas or explanations, what I am doing wrong? I will be glad to hear any ideas. For now I will try to create not irregular hexagons, but triangles (faces) of each as independent object and will use mesh grouping to create hexagons from them, but it will take some time. p.s I got this idea while I was writing the message. Quote Link to comment Share on other sites More sharing options...
logunov Posted October 27, 2018 Author Share Posted October 27, 2018 Well, after all tests I got the problem, there is the look from outside: And there is the look from inside on the same pentagon: First, as you can see, triangle method give me needed result, BUT not for all meshes. The problem is some of faces are inverted, because of... because of what? I have no idea why it's happens. Second, is any one know, how to solve that problem? Maybe is there a way to change direction of all normals like scale by -1? If it possible, I just can get for each new created mesh one leading face, and inverse all other normals if their direction locally negative to leading one. I think, I isolate problem right now, but I have no ideas which instruments BABYLON gives to me for fix something like that. I will be glad to hear any ideas, maybe there is no need to change normals, but inverse rotation of some meshes, created by face points, but again I have no idea, how to do this in BABYLON. Ofcourse, code to reproduce: for (let i = 0; i < hexaSphere.tiles.length; i++) { let myMaterial = new BABYLON.StandardMaterial("myMaterial", scene); myMaterial.diffuseColor = new BABYLON.Color3(1, 0, 1); myMaterial.specularColor = new BABYLON.Color3(0.5, 0.6, 0.87); myMaterial.emissiveColor = new BABYLON.Color3(1, 1, 1); myMaterial.ambientColor = new BABYLON.Color3(0.23, 0.98, 0.53); //I have no idea is material do something or not here, but I am using this let createIrregularFace = function(name,scene, vertices, indices){ let verData = new BABYLON.VertexData(); //BABYLON.VertexData.ComputeNormals(vertices, indices, normals); verData.positions = vertices; verData.indices = indices; //verData.normals = normals; let polygon = new BABYLON.Mesh(name,scene); verData.applyToMesh(polygon); //polygon.convertToFlatShadedMesh(); //what is it doing? return polygon; }; let faces = []; //meshes array; hexaSphere.tiles[i].faces.forEach( (face) => { let positions = []; let indices = []; face.points.forEach( (point) => { let x = parseFloat(point.x); let y = parseFloat(point.y); let z = parseFloat(point.z); positions.push(x,y,z); indices.push(indices.length); }) indices.reverse(); let result = createIrregularFace("",scene, positions, indices); result.material = myMaterial; faces.push(result); }); } Quote Link to comment Share on other sites More sharing options...
ssaket Posted October 27, 2018 Share Posted October 27, 2018 LOL... happens most of the time ! //polygon.convertToFlatShadedMesh(); //what is it doing? Let's take a cube as an example. let verData = box.getVerticesData(BABYLON.VertexBuffer.PositionKind); Q: How many facets it has ?? Ans: 6 faces -> 6*2 facets (there are the triangles) Q: How many indices ?? Ans: [0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, 8, 9, 10, 8, 10, 11, 12, 13, 14, 12, 14, 15, 16, 17, 18, 16, 18, 19, 20, 21, 22, 20, 22, 23] -> 36 This each of them as Position array index. Now total positions -> 24 => Array Len =24*3 = 72, Now here each vertex is shared by 3 facets triangle, so if we are using any shader on that vertex, others might as well get affected. (012, 023, ....) Let's do convertToFlatShadedMesh. Again, Q: How many indices ?? Ans: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35] -> 36 but wait.. something is different !! now positions are not being shared like before (012, 345, ....) positions len: 36 (from 24) who are these new (36-24=12 members ?? jumping to the q1 we had 12 triangles, looks like they are repeated again but why.. so that each triangle can have it's own shader.. (maybe I am not putting it correctly ) blah.. blah, have a look here https://www.eternalcoding.com/?p=113 ) In short it give sharpness..maybe EDIT: just now found one awesome doc - explains very clearly https://doc.babylonjs.com/resources/facets logunov 1 Quote Link to comment Share on other sites More sharing options...
JohnK Posted October 27, 2018 Share Posted October 27, 2018 Some more info about convertToFlatShadedMesh https://doc.babylonjs.com/resources/normals Note that the CreateBox method produces a flat shaded mesh logunov and ssaket 2 Quote Link to comment Share on other sites More sharing options...
logunov Posted October 29, 2018 Author Share Posted October 29, 2018 Well, I still stuck in that. I read all topics you gave to me, but the problem is I do not find any clear explanation: is facet front determined by normals or there is another parameter? I found example in JohnK resource: https://www.babylonjs-playground.com/#VKBJN#19 and there is the same problem: normals will not change backside visibility, so the answer on my question is to make every mesh double sided, but I can not find any way to make custom mesh doublesided orientated. Quote Link to comment Share on other sites More sharing options...
jerome Posted October 29, 2018 Share Posted October 29, 2018 When creating your geometry (vertexData), create your indices array, your positions array, your normal array and then, before applying it to the vertexData object, just call this private static function : https://github.com/BabylonJS/Babylon.js/blob/master/src/Mesh/babylon.mesh.vertexData.ts#L2828 It will modify your created arrays to add the backsides as requested. logunov 1 Quote Link to comment Share on other sites More sharing options...
JohnK Posted October 29, 2018 Share Posted October 29, 2018 When creating your own custom mesh to make it updatable you need to add a second parameter with value true when applying the mesh to the vertex data. vertexData.applyToMesh(customMesh, true) Please do not keep changing the topic title as it makes it very difficult to return to. Please ask a new question. logunov 1 Quote Link to comment Share on other sites More sharing options...
logunov Posted October 31, 2018 Author Share Posted October 31, 2018 Thx a lot, the first problem about two surfaces solved, but it produce new kind of problem. I think, I will create new post later about it, because it is not about surfaces. Again, thank you all very much, I am very grateful to you and appreciate all your help. p.s About names of topic. I thought it better to change name to not spam themes about new problems. I will no more do this. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.