- Home /
How to calculate uvs for roof procedurally generated?
Hi, after a few attempts I decided to seek help here. I have a roof generated procedurally and I'm using to its coordinates (u, v) the same coordinates of the vertices (x, z), but the result is not as expected and similar to reality.
Can anyone help with any tips on how to calculate the coordinates (u, v)?
Note: Vertices not shared. Have also tried to use this script: link text
Sorry for my english.
Thanks!
Hey, i know it is offtopic but, I am very curoius what algorithm do you use for generating roof mesh because I am currently working on that too. Thanks :)
Answer by DMGregory · May 30, 2014 at 01:19 AM
Try something like this for each vertex...
// This gives a vector pointing up the roof:
Vector3 vAxis = Vector3.Scale(normal, new Vector3(-1, 0, -1)).normalized;
// This will make the u axis perpendicular to the v axis (ie. parallel to the roof edge)
Vector3 uAxis = new Vector3(vAxis.z, 0, -vAxis.x);
// I originally used vAxis here, but changed to position.y so you get more predticable alignment at edges.
// Set eaveHeight to the y coordinate of the bottom edge of the roof.
Vector2 uv = new Vector2(Vector3.Dot(position, uAxis), position.y - eaveHeight);
// You may need to scale the uv vector's x and y to get the aspect ratio you want.
// The scale factor will vary with the roof's slope.
Note that this won't behave well where the vertices on a triangle have different normals, like around a curved turret, or level portions where the normal points straight up.
Edges between different slopes may act up, so it may look good to add an extra bit of geometry to cap them:
$$anonymous$$aybe I did something wrong, because wrong generated. I'll trying to adjust your approach to see if I can adjust. Code:
private void TestUvRoof$$anonymous$$ap($$anonymous$$esh mesh)
{
var newUvs = new Vector2[mesh.vertices.Length];
for (var v = 0; v < mesh.vertices.Length; v++)
{
var vertex = mesh.vertices[v];
var normal = mesh.normals[v];
// This gives a vector pointing up the roof:
var vAxis = Vector3.Scale(normal, new Vector3(-1, 0, -1)).normalized;
// This will make the u axis perpendicular to the v axis (ie. parallel to the roof edge)
var uAxis = new Vector3(vAxis.y, 0, -vAxis.x);
// I originally used vAxis here, but changed to position.y so you get more predticable alignment at edges.
// Set eaveHeight to the y coordinate of the bottom edge of the roof.
var uv = new Vector2(Vector3.Dot(vertex, uAxis), vertex.y - 0);
newUvs[v] = uv;
// You may need to scale the uv vector's x and y to get the aspect ratio you want.
// The scale factor will vary with the roof's slope.
}
mesh.uv = newUvs;
}
Sorry! Typo in my code. Should be z, not y:
var uAxis = new Vector3(vAxis.z, 0, -vAxis.x);
No bother. Sorry I didn't see it right away - I don't get very good notifications from UnityAnswers.
Using the y coordinate ensures that rows of shingles match up, and that the bottom edge of the roof always shows one full row, but the height/aspect ratio of each shingle varies with the slope of the roof segment. (That's what I meant about the scale factor above)
Try this ins$$anonymous$$d:
var vertex = mesh.vertices[v];
var normal = mesh.normals[v];
// This will make the u axis run along the roof edge
// (Same as before, I just collapsed the old "vAxis" into this line)
var uAxis = (new Vector3(-normal.z, 0, normal.x)).normalized;
// This will make the v axis run up the roof
// (Rising off the xz plane, unlike the old one)
var vAxis = Vector3.Cross(uAxis, normal);
// I'm assu$$anonymous$$g the normal is already unit length, but you can normalize for safety.
// Translates the UVs so the eaves sit at v = 0
var eaveCorrection = Dot(vAxis, vertex + vAxis * (eaveHeight - vertex.y)/vAxis.y);
var uv = new Vector2(Vector3.Dot(vertex, uAxis), Dot(vAxis, vertex) - eaveCorrection);
newUvs[v] = uv;
This is just back-of-napkin, and I've got a bit of scotch in me, so I can't 100% guarantee it'll work... ^_^;
Yeah! its working! Even with a bit of scotch! :D $$anonymous$$any thanks again! I'm still newbie with mathematics of vectors.
Not looking at the skeleton of the roof, the mapping was very good! Now I will study your code to learn more.
,
I'll run you through it:
The normal of the roof is a vector pointing out from it perpendicularly. By zeroing its y coordinate, we get a vector in the xz plane pointing in the downslope direction - think of it as the shadow cast by the normal when the sun is straight overhead.
The cross-slope direction (what we want as our u direction) also sits in the xz plane, at 90 degrees to this one. We can make such a vector by exchanging the x and z coordinates of the downslope vector and negating one of them. (This ensures that the dot product of the two vectors is zero: (x, 0, z) dot (-z, 0 x) = -xz + xz = 0, which is a mathematical way of saying "perpendicular")
We want our v axis to be perpendicular to the u axis (so our texture isn't skewed), and in the plane of the roof (perpendicular to the normal). The cross product gives us a vector perpendicular to its two inputs, so we get that almost for free from its definition.
Together, these two axes define a coordinate system for the plane of the roof. Dotting the position with each axis gives us the vertex position in this 2-dimensional roof coordinate system.
$$anonymous$$aking each vector unit length ensures that we're applying the same real-world scale to each texture axis, so we don't get the uneven aspect ratio of the earlier version.
The last bit is ensuring that the bottom of the texture lines up with the bottom of the roof. Here, we calculate what the v axis dot product would be for a vertex at the eaves, and subtract that from every vertex. That way vertices at the eaves get the correct v=0, and all other vertices are adjusted accordingly.
Answer by ivansi · Feb 09, 2015 at 03:30 PM
Hey, i know it is offtopic but, I am very curoius what algorithm do you use for generating roof mesh because I am currently working on that too. Thanks :)
Hello Daviz, I use Straight Skeleton Algorithm to make the roof Skeleton, and after I use triangulation to make the Mesh.
Would you be so kind and share your straight skeleton algorithm? I was searching in the internet for some time and can't found useful code or more detailed example. I'm working on my in game editor, whitch allow players to create their own maps. I have floors, walls, doors (windows) and now I need roofs ;) .... and I stuck here :D I appreciate any help in this regard. Thank you.
Answer by doodo · Sep 19, 2015 at 08:54 PM
easier to use this calculator http://myrooff.com/roof-pitch-calculator/