NasimiAsl Posted February 28, 2015 Share Posted February 28, 2015 let me explain with sample: vertiex : p1: 0,0,0 uv : 0.0,0.0p2: 0,0,1 uv : 0.5,0.0p3: 1,0,0 : face 1(p1,p2,p3) uv : 0.0,0.5p4: 1,0,1 : face 2(p2,p3,p4) uv : 0.5,0.5 everything is ok to p4so i want fill back face with out append more vertex so face 3 (p4,p2,p3) : i cant set any new uv face 4 (p3,p1,p2) : *** same problem * in babylonjs i can set uv per vertex but in .obj format i have more uvs per vertex Quote Link to comment Share on other sites More sharing options...
Dad72 Posted February 28, 2015 Share Posted February 28, 2015 Hein . sorry, but I understood nothing. NasimiAsl 1 Quote Link to comment Share on other sites More sharing options...
NasimiAsl Posted February 28, 2015 Author Share Posted February 28, 2015 i apologize for bad writing . we have a simple plan with 4 point like vertices : [{x:0,y:0,z:0}, {x:1,y:0,z:0} , {x:1,y:0,z:1} , {x:0,y:0,z:1}] faces : [{ a: 0,b:1,c:2} , { a:1,b: 2, c: 3 } ] // two face for up side of plan uvs : [ [0,0], [0.5,0], [0.5,0.5] , [0,0.5] ] // per vertex now i want add back side without append any vertex so push two face like this : faces .push({ a: 3,b:1,c:2} , { a:0,b: 2, c: 1 }); i fill UVS from 0 to 0.5 for Up Side of Plan now i want continue UV from 0.5 to 1.0 but when i push new uvs nothing change in my geometry and back side have uv like up side * important we need build this plan with 4 points. Quote Link to comment Share on other sites More sharing options...
jerome Posted February 28, 2015 Share Posted February 28, 2015 UVs are per vertex. 3 vertices <=> 3 UV pairs. If you need to stretch your texture backside with other UV values than the ones used for the front side, you have then to add three more vertices In your example, you have only 3 vertices ... whatever the number of faces they are used, or re-used, in.So only the 3 first coordinate pairs in your UV array will be be used. http://www.html5gamedevs.com/topic/12467-double-sided-mesh/?p=71736 Quote Link to comment Share on other sites More sharing options...
NasimiAsl Posted February 28, 2015 Author Share Posted February 28, 2015 thanks jerome i want import .obj geometry i dont want change the vertices array but i have problem in last face . some vertex in last faces have uvs but need a new uvs .i want know why uvs defined per vertex but in 3d software it is not like this . i thinks in three js it is not like this so maybe we can correct babylonjs core? Quote Link to comment Share on other sites More sharing options...
jerome Posted February 28, 2015 Share Posted February 28, 2015 I guess ThreeJS and BJS behave the same way on this topic, because it's just the WebGL / OpenGL rule : a normal per vertex and a UV per vertex only. You could get your vertex array and face array, instanciate a VertexData object andt hen use the (public and private) methods :ComputeNormals(positions, indices, normals) : re-computes the normals array given positions and indicesand _ComputeSides(sideOrientation, positions, indices, normals, uvs) : re-computes vertex, indices, normals and uv arrays given a sideOrientation value.This method will add the missing backside vertices, faces, normals and uvs for you if you want a double sided mesh. sideOrientation values are detailed here in the Side Orientation part: http://doc.babylonjs.com/page.php?p=22011 https://github.com/BabylonJS/Babylon.js/blob/master/Babylon/Mesh/babylon.mesh.vertexData.ts#L1162 Quote Link to comment Share on other sites More sharing options...
NasimiAsl Posted February 28, 2015 Author Share Posted February 28, 2015 // this method append mor than 1 uvs per vertexgeometry.faceVertexUvs[ 0 ].push( [uvs[ parseUVIndex( a ) ].clone(),uvs[ parseUVIndex( b ) ].clone(),uvs[ parseUVIndex( c ) ].clone()] ); Quote Link to comment Share on other sites More sharing options...
jerome Posted February 28, 2015 Share Posted February 28, 2015 Well, maybe you could edit your post and wrap the code in the code tag (select the text and click on "<>" in the tool bar) so it will be easier to read.I just can't read in this function what gives the ability to have more and an uv per vertex so far. here is a part of the khronos (the guys who made Wegl) group forum :https://www.khronos.org/message_boards/showthread.php/7063-Texture-coordinates-per-face-index-instead-of-per-vertexNo - you should duplicate the vertex if the texture coord is different (note also that your surface normal vector will also be different - which gives you two reasons to duplicate it). btw, there's a uv2 property in the VertexData object, but I don't know what is for ... NasimiAsl 1 Quote Link to comment Share on other sites More sharing options...
Wingnut Posted February 28, 2015 Share Posted February 28, 2015 I think you can delete the code from your post, if you wish. I think the same code is here: http://threejs.org/examples/js/loaders/OBJLoader.js there seems to be ANOTHER version... for Ejecta. https://gist.github.com/phoboslab/5964733 *shrug* I think we need to write a book called "The Last UV". The last uv has troubled quite a few people. The book will be about a team of relay racers... with troubles. They keep making the mistake of trying to hand the baton to the first runner... when the last runner reaches the finish line. The first runner says "NO NO, I already gave that away to somebody". (Wingnut trying comedy, failing) Maybe the last uv needs to be treated like a VALUE that is "averaged" with the first uv. The first uv gets adjusted to "split the difference", and then the last uv values are discarded. *shrug* Just guessing. NasimiAsl 1 Quote Link to comment Share on other sites More sharing options...
NasimiAsl Posted February 28, 2015 Author Share Posted February 28, 2015 uv2 just for use 2 type of uv map for geo in shader and can set 2 texture . we need .obj loader for babylonjs anyway i convert that but i have problem with last uv i can find last faces but i want resolve that without change vertices of geometry any append new vertex make problem for smooth property so help me to resolve that. Wingnut 1 Quote Link to comment Share on other sites More sharing options...
RaananW Posted February 28, 2015 Share Posted February 28, 2015 Hi!Trying to understand your initial question - You have 4 vertices, defined with xyz on each. Each has a uv (v and u).So your positions and usv vector look like this (babylon format):positions = [0,0,0,0,0,1,1,0,0,1,0,1] // 12 itemsuvs = [0,0,0,0.5,0.5,0,0.5,0.5] // 8 itemsindices vector (the faces) will look like this:indices = [0, 1, 2, 0, 2, 3] This created a plane.Now, If I understand you fully, you wanted to "reuse" the positions and add a new uv definition.In OBJ you can reference the location of both position and uv in the faces definition :f 1/2 2/1 3/2Which avoids having redundant uv definitions.The babylon format works differently. It is rather redundant, but wonderful for performance. If you want to add a new uv to an existing position definition, you will have to duplicate this position and add the uvs definition at the correct position. This is due to the indices definition. Not like obj, indices is only 1 number, meaning 1 position of the array. You can't reference a specific uv definition and a different positions definition. So - to do what you wanted to do, you would have to add a new position to the positions (which is a duplicate of an existing position) and add the uv: (let's say you want to add a new uv definition for the 0,0,0 positions)positions = [0,0,0,0,0,1,1,0,0,1,0,1, 0,0,0] //15 itemsuvs = [0,0,0,0.5,0.5,0,0.5,0.5, 0.5,1.0] // 10 itemsand now create a new face using the 4th "definition location"indices = [0, 1, 2, 0, 2, 3, 1, 2, 4] I am not sure if I understood your question correctly, I hope this clears things up a bit. jerome and amo yeh 2 Quote Link to comment Share on other sites More sharing options...
NasimiAsl Posted March 1, 2015 Author Share Posted March 1, 2015 thanks RaananW we wont add a new position actually this problem is not for a simple plan we want have solution for all object . Main Problem : We have some vertices in the .obj format that have many uvs but in babylon js we have one uv(two number) per vertex. Quote Link to comment Share on other sites More sharing options...
NasimiAsl Posted March 1, 2015 Author Share Posted March 1, 2015 I think you can delete the code from your post, if you wish. I think the same code is here: http://threejs.org/examples/js/loaders/OBJLoader.js there seems to be ANOTHER version... for Ejecta. https://gist.github.com/phoboslab/5964733 *shrug* I think we need to write a book called "The Last UV". The last uv has troubled quite a few people. The book will be about a team of relay racers... with troubles. They keep making the mistake of trying to hand the baton to the first runner... when the last runner reaches the finish line. The first runner says "NO NO, I already gave that away to somebody". (Wingnut trying comedy, failing) Maybe the last uv needs to be treated like a VALUE that is "averaged" with the first uv. The first uv gets adjusted to "split the difference", and then the last uv values are discarded. *shrug* Just guessing. main question is why uvs set per vertex 1<=>1 ( who design this?) ) Quote Link to comment Share on other sites More sharing options...
RaananW Posted March 1, 2015 Share Posted March 1, 2015 Can you show us how it's done in the obj file?An obj consists of a lot of vt, vn and v, connected using faces (f), but I'm not sure how you achieve what you mean. Quote Link to comment Share on other sites More sharing options...
NasimiAsl Posted March 1, 2015 Author Share Posted March 1, 2015 16 face any face have 3 point with 3 uv index so 16 * 3 ( vertex count) = 48all vertex count = 26all indexed uv count = 43 ( same uv removed when indexed) what we have 26 place for uv255.txt Quote Link to comment Share on other sites More sharing options...
RaananW Posted March 1, 2015 Share Posted March 1, 2015 This is exactly what I meant in my post. And it's more than possible, Babylon supports creating such objects, naturally.The obj representation of a face is more complex than babylon's. In obj you can choose the uv, v and normal for a single face vertex. Babylon requires you to duplicate the data. Look at the first face in your txt file. 1/1/1, 2/2/2 etc. This is how Babylon works. You can't dof 1/2/1 2/2/3, 1/4/1in Babylon. The amount of faces will eventually be the same. The size of the array that represents the vertices will be bigger.If it's not clear, I'll try explaining a bit more thoroughly, not a problem. Btw - maybe try the asset converter with your obj and see how the data is represented. http://www.babylonjs.com/converter.html Quote Link to comment Share on other sites More sharing options...
jerome Posted March 1, 2015 Share Posted March 1, 2015 As Raanaw said, the indices array is the reference.The indices refers what vertex triplet should be used from the positions array to draw a face (triangle), but also what normal from normals array to apply to each vertex and what uv froms uvs array to associate to each vertex.This is way the indices array is iterated (I guess). If you have more positions elements than indices corresponding elements, they don't matter, they aren't used.The same for normals and uvs. This is the reason why your extra uvs aren't applied.If you have less positions elements than indices corresponding elements, it will raise a WebGL error in the console. You can therefore have less or none normals and uvs elements than indices elements (set to zero by default ?). I don't really know if it is a BJS design choice or a WebGL limitation.As they often talk about this need for vertex duplication in openGL forums, I guess it's related to WebGL itself, but don't sincerely know. Briefly, you still want to use BJS, you will have to duplicate vertices to have normals and uvs both side of your mesh. This is why I just led you to this internal function doing the job : _ComputeSides(sideOrientation, positions, indices, normals, uvs) : re-computes vertex, indices, normals and uv arrays given a sideOrientationvalue.This method will add the missing backside vertices, faces, normals and uvs for you if you want a double sided mesh. Wingnut 1 Quote Link to comment Share on other sites More sharing options...
NasimiAsl Posted March 1, 2015 Author Share Posted March 1, 2015 thanks all i Submission and rewrite objloader (objparser ) for babaylon js ( used by threejs objloader http://threejs.org/e...rs/OBJLoader.js ) let me refactor that i put it here. unbeautyfull code just for now create only geometry without material and normals corrected lastUV function def(a, d) { if (a != undefined && a != null) return (d != undefined && def != null ? a : true); else if (d != _null) return (d != undefined && d != null ? d : false); return null;}function n_1(ar) { ar = def(ar, []); if (!def(ar.length)) return null; return ar[ar.length - 1];}objParse = function (text) { var objects = []; var correctLastUVIndexer = 0; var uvsHelper = []; var geometry = null; var i0 = 0; function parseVertexIndex(index) { index = parseInt(index); return index >= 0 ? index - 1 : index + vertices.length; } function parseUVIndex(index) { index = parseInt(index); return index >= 0 ? index - 1 : 1.0; } function add_face(a, b, c, uvs) { a = parseVertexIndex(a - oldIndex); b = parseVertexIndex(b - oldIndex); c = parseVertexIndex(c - oldIndex); if (def(n_1(objects).uvs[a * 2]) && n_1(objects).uvs[a * 2] != uvsHelper[parseUVIndex(uvs[0])].x && n_1(objects).uvs[a * 2 + 1] != uvsHelper[parseUVIndex(uvs[0])].y) { correctLastUVIndexer++; a = $3d.tools.push1(n_1(objects), { x: parseFloat(n_1(objects).positions[a * 3]), y: parseFloat(n_1(objects).positions[a * 3 + 1]), z: parseFloat(n_1(objects).positions[a * 3 + 2]) }, false); } if (def(n_1(objects).uvs[b * 2]) && n_1(objects).uvs[b * 2] != uvsHelper[parseUVIndex(uvs[1])].x && n_1(objects).uvs[b * 2 + 1] != uvsHelper[parseUVIndex(uvs[1])].y) { b = $3d.tools.push1(n_1(objects), { x: parseFloat(n_1(objects).positions[b * 3]), y: parseFloat(n_1(objects).positions[b * 3 + 1]), z: parseFloat(n_1(objects).positions[b * 3 + 2]) }, false); correctLastUVIndexer++; } if (def(n_1(objects).uvs[c * 2]) && n_1(objects).uvs[c * 2] != uvsHelper[parseUVIndex(uvs[2])].x && n_1(objects).uvs[c * 2 + 1] != uvsHelper[parseUVIndex(uvs[2])].y) { c = $3d.tools.push1(n_1(objects), { x: parseFloat(n_1(objects).positions[c * 3]), y: parseFloat(n_1(objects).positions[c * 3 + 1]), z: parseFloat(n_1(objects).positions[c * 3 + 2]) }, false); correctLastUVIndexer++; } $3d.tools.face3(n_1(objects), a, b, c, { flip: !def(op.back, false) } ); if (!def(n_1(objects).uvs[a * 2])) n_1(objects).uvs[a * 2] = uvsHelper[parseUVIndex(uvs[0])].x; if (!def(n_1(objects).uvs[a * 2 + 1])) n_1(objects).uvs[a * 2 + 1] = uvsHelper[parseUVIndex(uvs[0])].y; if (!def(n_1(objects).uvs[b * 2])) n_1(objects).uvs[b * 2] = uvsHelper[parseUVIndex(uvs[1])].x; if (!def(n_1(objects).uvs[b * 2 + 1])) n_1(objects).uvs[b * 2 + 1] = uvsHelper[parseUVIndex(uvs[1])].y; if (!def(n_1(objects).uvs[c * 2])) n_1(objects).uvs[c * 2] = uvsHelper[parseUVIndex(uvs[2])].x; if (!def(n_1(objects).uvs[c * 2 + 1])) n_1(objects).uvs[c * 2 + 1] = uvsHelper[parseUVIndex(uvs[2])].y; } function handle_face_line(faces, uvs, normals_inds) { uvs = def(uvs, [0, 0, 0, 0]); if (faces[3] === undefined) { add_face(faces[0], faces[1], faces[2], uvs); } else { add_face(faces[0], faces[1], faces[3], [uvs[0], uvs[1], uvs[3]]); add_face(faces[1], faces[2], faces[3], [uvs[1], uvs[2], uvs[3]]); } } // create mesh if no objects in text if (/^o /gm.test(text) === false) { geometry = $3d.tools.geometryBase(); objects.push(geometry); } // v float float float var vertex_pattern = /v( +[\d|\.|\+|\-|e]+)( +[\d|\.|\+|\-|e]+)( +[\d|\.|\+|\-|e]+)/; // vn float float float var normal_pattern = /vn( +[\d|\.|\+|\-|e]+)( +[\d|\.|\+|\-|e]+)( +[\d|\.|\+|\-|e]+)/; // vt float float var uv_pattern = /vt( +[\d|\.|\+|\-|e]+)( +[\d|\.|\+|\-|e]+)/; // f vertex vertex vertex ... var face_pattern1 = /f( +-?\d+)( +-?\d+)( +-?\d+)( +-?\d+)?/; // f vertex/uv vertex/uv vertex/uv ... var face_pattern2 = /f( +(-?\d+)\/(-?\d+))( +(-?\d+)\/(-?\d+))( +(-?\d+)\/(-?\d+))( +(-?\d+)\/(-?\d+))?/; // f vertex/uv/normal vertex/uv/normal vertex/uv/normal ... var face_pattern3 = /f( +(-?\d+)\/(-?\d+)\/(-?\d+))( +(-?\d+)\/(-?\d+)\/(-?\d+))( +(-?\d+)\/(-?\d+)\/(-?\d+))( +(-?\d+)\/(-?\d+)\/(-?\d+))?/; // f vertex//normal vertex//normal vertex//normal ... var face_pattern4 = /f( +(-?\d+)\/\/(-?\d+))( +(-?\d+)\/\/(-?\d+))( +(-?\d+)\/\/(-?\d+))( +(-?\d+)\/\/(-?\d+))?/ // var lines = text.split('\n'); var oldIndex = 0; var oldLine = ''; var lastchar = ''; function newGeo() { if (objects.length == 0 || n_1(objects).vertices.length > 0) { oldIndex += objects.length > 0 ? n_1(objects).vertices.length - correctLastUVIndexer : 0; correctLastUVIndexer = 0; geometry = $3d.tools.geometryBase(); objects.push(geometry); } } for (var i = 0; i < lines.length; i++) { var line = lines[i]; line = line.trim(); var result; if (line.length === 0 || line.charAt(0) === '#') { continue; } else if ((result = vertex_pattern.exec(line)) !== null) { // ["v 1.0 2.0 3.0", "1.0", "2.0", "3.0"] if (lastchar == 'g') newGeo(); $3d.tools.push1(n_1(objects), { x: -1 * result[1], y: result[2], z: result[3] }, false); lastchar = 'v'; } else if ((result = normal_pattern.exec(line)) !== null) { // ["vn 1.0 2.0 3.0", "1.0", "2.0", "3.0"] // normals.push({ x: result[1], y: result[2], z: result[3] }); lastchar = 'n'; } else if ((result = uv_pattern.exec(line)) !== null) { // ["vt 0.1 0.2", "0.1", "0.2"] uvsHelper.push({ x: parseFloat(result[1]), y: parseFloat(result[2]) }); // uvs.push({ x: result[1], y: result[2] }); lastchar = 't'; } else if ((result = face_pattern1.exec(line)) !== null) { // ["f 1 2 3", "1", "2", "3", undefined] handle_face_line( [result[1], result[2], result[3], result[4]] ); lastchar = 'f'; } else if ((result = face_pattern2.exec(line)) !== null) { // ["f 1/1 2/2 3/3", " 1/1", "1", "1", " 2/2", "2", "2", " 3/3", "3", "3", undefined, undefined, undefined] handle_face_line( [result[2], result[5], result[8], result[11]], //faces [result[3], result[6], result[9], result[12]] //uv ); lastchar = 'f'; } else if ((result = face_pattern3.exec(line)) !== null) { // ["f 1/1/1 2/2/2 3/3/3", " 1/1/1", "1", "1", "1", " 2/2/2", "2", "2", "2", " 3/3/3", "3", "3", "3", undefined, undefined, undefined, undefined] handle_face_line( [result[2], result[6], result[10], result[14]], //faces [result[3], result[7], result[11], result[15]], //uv [result[4], result[8], result[12], result[16]] //normal ); lastchar = 'f'; } else if ((result = face_pattern4.exec(line)) !== null) { // ["f 1//1 2//2 3//3", " 1//1", "1", "1", " 2//2", "2", "2", " 3//3", "3", "3", undefined, undefined, undefined] handle_face_line( [result[2], result[5], result[8], result[11]], //faces [], //uv [result[3], result[6], result[9], result[12]] //normal ); lastchar = 'f'; } else if (/^o /.test(line)) { // || /^g /.test(line)) { if (line.replace('o', '').trim() != 'default') { oldLine = line.replace('o', '').trim(); if (oldLine != '' && objects.length > 0) n_1(objects).refname = oldLine; } else oldLine = ''; newGeo(); lastchar = 'o'; } else if (/^g /.test(line)) { if (line.replace('g', '').trim() != 'default') { oldLine = line.replace('g', '').trim(); if (oldLine != '' && objects.length > 0) n_1(objects).refname = oldLine; } else oldLine = ''; lastchar = 'g'; } else if (/^usemtl /.test(line)) { // material // material.name = line.substring( 7 ).trim(); lastchar = 'u'; } else if (/^mtllib /.test(line)) { // mtl file lastchar = 'm'; } else if (/^s /.test(line)) { // smooth shading lastchar = 's'; } else { // console.log( "THREE.OBJLoader: Unhandled line " + line ); } } return objects;}/// $3d.tools.geometryBase() : you need initialize in again for yourself///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //geometryBase: function (firstp, builder, exgeo, custom, op) { // var geo = { // faces: [], // vertices: [], // normals: [], // positions: [], // uvs: [] // }; // // if (!exgeo) // exgeo = geo; // // if (builder) { // builder(firstp, exgeo); // } // // if (custom) { // exgeo = custom(exgeo); // } // // return exgeo; // }, ///// /// $3d.tools.push1 = push vertex match by custom engin just push a vertics array [{x,y,z},..] and positions [x,y,x,..]////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// my push method //////////// push1: function (geo, p1, uv) {// uv = def(uv, true);// geo.vertices.push(p1); geo.positions.push(p1.x, p1.y, p1.z);// if (uv) geo.uvs.push(0.0, 0.0);// return geo.vertices.length - 1;// },//// $3d.tools.face3///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// my push face method //////////////////// face3: function (geo, p1, p2, p3, op) {// if (!op) { op = {}; }// function exch(p) { return (p.x || p.x == 0.0); }// if (!op.uv) { op.uv = "0123"; }//// if (def(op.noUV, false)) op.uv = ".....";//function addUv(i) {// if (op.uv[i].toString() == "0") geo.uvs.push(0.0, 0.0);// if (op.uv[i].toString() == "1") geo.uvs.push(0.0, op.vp);// if (op.uv[i].toString() == "2") geo.uvs.push(op.up, 0.0);//};//if (!op.up) { op.up = 1.0; }//if (!op.vp) { op.vp = 1.0; }//if (exch(p1)) { geo.vertices.push(p1); geo.positions.push(p1.x, p1.y, p1.z); addUv(0); op.p1Ind = geo.vertices.length - 1; }//if (exch(p2)) { geo.vertices.push(p2); geo.positions.push(p2.x, p2.y, p2.z); addUv(1); op.p2Ind = geo.vertices.length - 1; }//if (exch(p3)) { geo.vertices.push(p3); geo.positions.push(p3.x, p3.y, p3.z); addUv(2); op.p3Ind = geo.vertices.length - 1; }//if (op.p1Ind == null || op.p1Ind == undefined) op.p1Ind = p1;//if (op.p2Ind == null || op.p2Ind == undefined) op.p2Ind = p2;//if (op.p3Ind == null || op.p3Ind == undefined) op.p3Ind = p3;//if (!def(isInOp)) {// if (op.flip) {// geo.faces.push(op.p1Ind, op.p2Ind, op.p3Ind);// }// else {// geo.faces.push(op.p1Ind, op.p3Ind, op.p2Ind);// }//}//else {// if (op.flip) {// if (isInOp.a && isInOp.b && isInOp.c) geo.faces.push(op.p1Ind, op.p2Ind, op.p3Ind);// }// else {// if (isInOp.a && isInOp.c && isInOp. geo.faces.push(op.p1Ind, op.p3Ind, op.p2Ind);// }//}//isInOp = null;//return [op.p1Ind, op.p2Ind, op.p3Ind];//}, Wingnut 1 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.