Jump to content

UV cubic map procedurally


Mzigaib

Recommended Posts

Thanks for the feedback.

Is about the way the uvs are layed, it needs to be layed follow a cubic vertical environment cube.

UV unwrap works for texturing but it doesn´t position the uv´s right away with the cross cubic env image you have to do it by hand. Does it make sense?

Link to comment
Share on other sites

You can do this by doing 6 separate projections (UV texture or UV project) for each side to the cube and move them in position.

If you simply do that upfront, you can afterwards change the cube and the UVs should remain intact.

You could even morph this cube in a quad sphere if that is what you are looking for.

Shameless self plug is shameless:

http://www.twandegraaf.nl/Art/Documents/Procedural%20planets%20into%20detail,%20Twan%20de%20Graaf%202012.pdf

see page 6.

  • Like 1
Link to comment
Share on other sites

  • 3 years later...
  • 3 weeks later...
  • 7 months later...
  • 1 year later...
  • 7 months later...

Ok, it's been a while, but let's try it one by one:

1. Scaling world coordinates to unit size

vector bbox = relbbox(0, @P);
vector size  = getbbox_size(0);
vector ratio = size / max(size);
vector scale = bbox * ratio;

relbbox() creates linear gradients along each axis of the object from 0.0 to 1.0. Those can be spread out in UV space later.
getbbox_size() returns the absolute dimensions of the object. While we don't care about the actual size, we need to factor in how those dimensions relate to one another:
size / max(size) Dividing all dimensions by the biggest one effectively scales them to unit size while keeping the proportions. This is the aspect ratio for X, Y and Z.
bbox * ratio combines the gradients on all mesh points with the overall aspect ratio. All projections fit proportionally onto the UV grid now, we only need to split them up and lay them out.

 

2. Splitting up projection sides

vector side = sign(v@N);
vector nml  = abs(v@N);

if      (nml.x == max(nml)) { ...	}
else if (nml.y == max(nml)) { ...	}
else                        { ...	}

sign(v@N) decides towards which side the normals point to. Its either left or right, top or bottom, front or back. Later this will compensate for..
abs(v@N) setting all normals to positive values. So we can easily compare which direction they are mainly facing, using:
if (nml.x == max(nml)) for X, else if (nml.y == max(nml)) for Y and else for Z. By comparing each absolute component with the normals' maximum, we split the geometry into UV islands.

 

3. Laying out UV coordinates

if      (nml.x == max(nml)) { @uv = set(scale.y * side.x, scale.z, 0);             }
else if (nml.y == max(nml)) { @uv = set(scale.x * side.y, scale.z, 0); @uv.y += 1; }
else                        { @uv = set(scale.x * side.z, scale.y, 0); @uv.y += 2; }
@uv *= 0.3333;
@uv.x += 0.5;

set(scale.x * side.y, scale.z, 0); Depending on which side has won, the UV coordinates are composed of either top or side views (first component) and front or side views (second component). Setting the scale variables negative can be used to sort out direction issues.
*side.x*side.y and *side.z are simply flipping directions in case the normal directions have been negative. Thus getting their own islands on the left side. 
@uv.y += 1; and @uv.y += 2; are moving the UV islands upwards, so they are not landing on top of each other.
@uv *= 0.3333; Currently UV coordinates span across six unit spaces, so we scale them down to fit into one.
@uv.x += 0.5; Because of flipping the sides we also have to move all our coordinates to the right by half.

 

Alright, I hope things got less confusing now. ;)

Edited by konstantin magnus
  • Like 5
  • Thanks 1
Link to comment
Share on other sites

  • 9 months later...
On 10/4/2017 at 2:06 AM, konstantin magnus said:

Here is a vertexwrangle method for projecting cubic UVs on any kind of mesh:


vector bbox = relbbox(0, @P);
vector side = sign(@N);
vector nml  = abs(@N);

vector size  = getbbox_size(0);
vector ratio = size / max(size);
vector scale = bbox * ratio;

if      (nml.x == max(nml)) { @uv = set(scale.y * side.x, scale.z, 0);             }
else if (nml.y == max(nml)) { @uv = set(scale.x * side.y, scale.z, 0); @uv.y += 1; }
else                        { @uv = set(scale.x * side.z, scale.y, 0); @uv.y += 2; }

@uv *= 0.3333;
@uv.x += 0.5;

 

Thanks Konstantin, that's amazing!

For those who get some weird stretched uv, I solved by deleting any Normal attribute before feeding geo into vertex wrangler. Very basic but it took me a while to figure it out.. ;)

Link to comment
Share on other sites

  • 1 year later...

Always cool to have stuff in vex! I just wanted to mention, that this is also implemented natively with the uvunwrap node.

 

Edit: Was just reading about the cubic vertical environment cube uv layout thing. Missed that one.

Edited by Drughi
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.

×
×
  • Create New...