View Full Version : Parametric UVMapping
MrSparkle 03 March 2006, 11:11 PM Hi!
I want to write a script that unwraps the UVs of a polygon selection similar to the parametric UVs of NURBS objects.
The idea of the script is shown in the attached images. In the second image you can see the polygon selection of the object that should be unwrapped.
When the script starts, the user selects four corner vertices of the map, which should have these uv coordinates: 0,0  1,0  0,1  1,1 (shown in the first image).
Then the script interpolates the UVs of all other vertices to apply a mapping as shown in the third image. Appearently the map is distorted due to the triangulation of the polygons.
How can I avoid the distortion of the maps without using NURBS surfaces?
Is there an easy way to identify all borderedges of a polygon selection?
Thanks,
Christian


arketip
03 March 2006, 10:08 AM
Appearently the map is distorted due to the triangulation of the polygons.
How can I avoid the distortion of the maps without using NURBS surfaces?
This distorsion is only visual (if yours uvs are correct of course).
That is just a problem of display...
The only means to avoid it is to increase the number of segments.
That is the reason for which it works very well in NURBS: there are more segments and the structure is very regular what avoids the distortions.
Is there an easy way to identify all borderedges of a polygon selection?
Yes. Here is the code:
fn getOutlineEdges obj theFaces = (
local faceEdges = polyOp.getEdgesUsingFace obj theFaces
local outlineEdges = #{}
for e in faceEdges where (((polyOp.getFacesUsingEdge obj e)*theFaces).numberSet == 1) do outlineEdges[e]=true
outlineEdges
)
(
local obj=selection[1]
if classof obj==Editable_Poly do (
local theFaces = polyOp.getFaceSelection obj
local theOutlineEdges = getOutlineEdges obj theFaces
polyOp.setEdgeSelection obj theOutlineEdges
subObjectLevel=2
)
)
This example is for Editable_Poly only.
It is a bit more complex for a mesh because the structure is different and the function getFacesUsingEdge don't return the expected result.
I am interested by your project.
Indeed I wrote a script which acts in a similar way :
http://users.skynet.be/arketip/arketip_morphMapENG.htm
But my script was conceived to work with flat surfaces only.
It will give you can be some ideas...
How would you make to attribute mapping coordinates to a volume?
If you can create a script that works on a volume that would be terrific :thumbsup:
MrSparkle
03 March 2006, 02:21 PM
Hi Arketip,
your script is GREAT!! I tried to map the model of the arc in my first posting and it worked. Then I tried to map the road on the terrain model in the attached image. I had to map it in three steps and there are almost no distortions in the texture!
But I want to understand how it works ;) Can you tell me what is the reason why I have to map the road in different steps?
Thanks!
Christian
arketip
03 March 2006, 04:05 PM
Hi, Happy to see that you like my script.
Can you tell me what is the reason why I have to map the road in different steps?
The reason is pretty simple: lets say you have a road with a form ' J '
The length of the left border and the right border of the road is not the same... And my script uses this distance to balance the UVs. The length is balanced along the whole road.
In this case the deformation would be only in turns.
In this case, the deformation has to appear only in the bends and never in the straight lines.
This is the reason.
You speak about interpolation in your project...
Do you believe that it is possible to improve my script to put on it on volumes?
Have you another method or this is just an hypothesis?
MrSparkle
03 March 2006, 05:58 PM
Your script looks really professional! But I don't understand how you detect the corner vertices.
My idea is to first let the user select the four corner vertices. Then the script interpolates all the vertices along the border edges using the distance to the next both corner vertices.
The two attached images shows how I would map the Jshaped road.
I can't really imagine what you mean with applying this method to volumes. I think you have to add the ability to break some of the edges apart. I think the best method to do this would be Peltmapping...
arketip
03 March 2006, 09:37 PM
Your script looks really professional! But I don't understand how you detect the corner vertices.
Magic
Seriously this part of the script is the most difficult to write. It is a combination of various calculations. It was necessary to make tests to find the good balance.
The automatic corners detection is really indispensable to make this kind of script pleasant to use.
My idea is to first let the user select the four corner vertices. Then the script interpolates all the vertices along the border edges using the distance to the next both corner vertices.
The two attached images shows how I would map the Jshaped road.
These pictures explain clearly your method :thumbsup:
It is exactly as it that works my script.
You see that the red line is shorter than the opposite (and especially the bend part) That's why it is necessary to run the script in 2 steps.
I can't really imagine what you mean with applying this method to volumes.
The problem of the volume occurs when one vertex is between the 2 opposite edges : What happens if this internal point is not situated inside the plan formed by 2 opposite edges?
How to calculate the uv coordinate?
That is the question...
MrSparkle
03 March 2006, 12:21 AM
The automatic corners detection is really indispensable to make this kind of script pleasant to use.
Yes, this is indeed very useful... I will get deeper into this topic to understand how your script works ;)
You see that the red line is shorter than the opposite (and especially the bend part) That's why it is necessary to run the script in 2 steps.
In the first step I would interpolate all the UVs of the vertices along the border edges (with u or v = 0). Then, in the second step, the inner vertices are left and can be interpolated from the outer vertices.
The problem of the volume occurs when one vertex is between the 2 opposite edges : What happens if this internal point is not situated inside the plan formed by 2 opposite edges?
How to calculate the uv coordinate?
That is the question...
You have to do some kind of unwrapping to the object. This means you have to virtually transfer the volume object to a planar surface. Then you can detect the edge vertices and apply the mapping. But I guess this cannot be computed without heavy distortions...
What kind of geometry you are thinking of?
arketip
03 March 2006, 11:26 AM
In the first step I would interpolate all the UVs of the vertices along the border edges (with u or v = 0). Then, in the second step, the inner vertices are left and can be interpolated from the outer vertices.
Here is an picture which shows how my script works at present:
http://users.skynet.be/arketip/morphMapsteps.gif
What kind of geometry you are thinking of?
this kind of geometry :
http://users.skynet.be/arketip/morphMapvolumeError.gif
As you see, the surface of the grid is interpolated with the flat edges.
In this case the script have the same effect than an planar mapping...
MrSparkle
03 March 2006, 01:31 PM
In my oppinion, there is no solution for this kind of geometry. I have no idea how to unwrap the object in your picture without distortions or without seams. That means you will have eighter distortions in your texture or seams in your mapping...
You can try to create the desired mapping manually but I cannot imagine how it should look. Maybe you could post a picture of how your final map should appear on your object?
arketip
03 March 2006, 02:54 AM
Here is how my final map should appear on the object :
http://users.skynet.be/arketip/CGtalk/morphMapvolumeSimulation.jpg
(the object was simplified)
At the left, I show to you the final object. And at the Right, a simple planar projection.
and the unwrap associed:
http://users.skynet.be/arketip/CGtalk/morphMapvolSim.gif
MrSparkle
03 March 2006, 09:49 AM
The script has to recognize the 3d shape of the object in order to unwrap it in this way. To apply a U or V coordinate to a vertice, the script has to consider the path from one border edge to the opposite border.
In the attached image, you need to calculate the total length of the "a" and "b" lines in 3d space, then apply the u and v coordinates proportionally to the vertices on the red lines. I think the result would be the same as your manually unwrapped map.
How does your script handle 3d objects? It works with nonplanar shapes yet as shown on your website (first image). So it seems to be quite easy to implement the ability to handle irregular 3d objects...
arketip
03 March 2006, 01:30 PM
You are probably right but I shall need a little of time to imagine the routine which allows me to make that.
The example which I gave here was very simple. The edges of the object are flat. It is easy to define a slice plane through this object. But if the edges don't have a flat shape then that would be more complicated...
Thanks for the idea :)
MrSparkle
03 March 2006, 02:24 PM
The routine would be pretty much the same as in this example:
1. You start with 4 corner vertices which are connected through the border edges
2. You have to calculate the overall length of each border edge. This is the sum of the lengths of all edges between two corner vertices.
3. Each vertice on the border edges has eighter a U or a V coordinate which is proportional to the vertice's position relative to the overall edge length.
4. All other vertices get their uv coordinates from the distance to the next 2 vertices on the border edges. Distance is the actual length of all edges between the points (in 3d space).
This is how I would write the script. Unfortunately I don't have much time to figure out how it can be done in MaxScript...
arketip
03 March 2006, 07:01 PM
3 first ones are exactly what already makes my script.
The fourth point is different...
To my opinion, the results will be wrong with this method except with very regular forms.
To compare the position of the other vertices with edges will create errors in uv. There are cases where the most close 2 points are not the right choice...
MrSparkle
03 March 2006, 10:58 AM
Yes, your right. This would only work on regular geometry...
How does your script calculates the uv coordinates of the interior vertices? How does the texture of the last object look like after mapped with you script?
arketip
03 March 2006, 02:39 PM
I create a grid. You can show this grid and you will understand my method : replace the option 'show corners (marker)' by 'show grid (shape)' under group 'morphMap'
The grid will appear and is used to calculate the uvs. (Except vertices on the border edges)
MrSparkle
03 March 2006, 10:12 PM
Seems that your method only recognizes the the alignment of the border edges. For example, if I modify your object by moving the border vertices, it creates a grid that perfectly fits the border edges. But when I move only the interior vertices, the grid will still have the same shape.
Maybe the solution would be to create a grid for each polygon like you do for the borders. Try to go recursively through all edges in the selection and change the grid so it would follow the shape of the object.
I found another method to map complex geometry here: http://www.nesnausk.org/inoutside/Technology.php#tech_tex
They say that they "project tileable stone textures onto the model's surface from several angles; and weight the results according to the orientation of the surface (surface's normal)."
I guess that this method would give the same result as aligning your grid to each polygon.
What do you think?
arketip
03 March 2006, 01:36 PM
Seems that your method only recognizes the the alignment of the border edges. For example, if I modify your object by moving the border vertices, it creates a grid that perfectly fits the border edges. But when I move only the interior vertices, the grid will still have the same shape.
Indeed, only edges are used to generate the grid. For points going away from the grid, the script makes a projection. It is very similar to a planar mapping but the shape does not need to be rectangular.
Maybe the solution would be to create a grid for each polygon like you do for the borders. Try to go recursively through all edges in the selection and change the grid so it would follow the shape of the object.
I found another method to map complex geometry here: http://www.nesnausk.org/inoutside/Technology.php#tech_tex
They say that they "project tileable stone textures onto the model's surface from several angles; and weight the results according to the orientation of the surface (surface's normal)."
I guess that this method would give the same result as aligning your grid to each polygon.
What do you think?
You give several interesting propositions.
To begin let us speak about the first idea:
When I have created morphMap, I thought at first of realizing the mapping 'by propagation', like this:
1 at first apply a face mapping
2 unify the directions
3 recalculate the uvs by using the edges length
But this algorithm is very dependent on the regularity of the mesh. The weakness is situated at the point 2. There are cases where to unify the direction is not possible.
For example this one:
http://users.skynet.be/arketip/CGtalk/propagationHypothesis2.jpg
And calculate the uvs of an irregular poly isn't obvious.
Maybe there are a solution there but I do not see at the moment.
Nevertheless to use the size of edges seems interesting...
MrSparkle
03 March 2006, 06:05 PM
I think we are on the right way to solve our problem ;)
But I still have serious problems to imagine the process to flatten the surface.
I created a pyramid with: width = height = depth = 100.0m, then cut off the upper part and extruded the cap polygon 20m inside the object. This object is pretty much the same as in your example, but it has 2 edges which are orthografically aligned to the orientation of the mapping plane. The egdes B and B' in the picture would have a length of 0 when projected into uv space.
So my approach would be to calculate the uv coordinates from the distance between each vertice relative to the distance to the corresponding edge points. I demonstrate it using the profile at the center of the object (the red edges in the picture). The edges have the following lengths:
A = A' = 56m
B = B' = 20m
C = 50m
The overall distance is 56 + 56 + 20 + 20 + 50 = 202m. Corresponding to this length each line section would have the following lengths in uv space:
A = 27.7% = 0.277
B = 9.9% = 0.099
C = 24.7% = 0.247
This is only works in 2d space, thats why I used only the profile at the center of the object. I cannot imagine how it could work in 3d space, that means for all the other edges of the object. Maybe you have to construct a profile in u and in v direction for each vertice, then calculating the overall length of the profiles then the u and v coordinate of the vertice. But I still don't have an answer how the orientientation of the profiles could be calculated. I guess this involves some serious vector and algebra equations...
arketip
03 March 2006, 11:33 AM
The method by propagation of faces is not possible. I thought about it and when the geometry is not regular there are too many problems. For example if faces are hexagonal.
There is another solution : I have to project my grid on the object.
As any projection I need an axis. I think that we can find this axis with the normal of the outline. Of course it is an approximation but that should work in quite a lot of case. Later I revalue the grid according to the distances.
It will not work with the perpendicular surfaces in the axis of projection...
Other solution is to cut the object with this axis as you propose it. But that is probably time consuming.
arketip
03 March 2006, 09:11 AM
I found another solution: I project vertices on the grid and I store their height.
With this algorithm that will function for vertical surfaces, without needing to cut out the object. I will give more explanations in one or two days.
arketip
03 March 2006, 09:41 AM
Hi
Here is the method
 a first grid is created with the outline vertices. (It's the current morphMap grid.)
 the vertices of the object are projected on this grid. The axis of projection is the normal vector of the outline.
 for each impact point there are a coordinate. The elevation is the distance between the point and the impact point.
 by using an interpolation, the UV of the new points are calculated : a division is added to the outline at this position.
 a second grid is created with new divisions and by using the elevations.
 the right UV is calculated with the new grid. (by using the length of the segments of the grid)
The method accept vertical surfaces because several points are created at the same place but with an other elevation.
Unfortunately, I see now that there are a problem: if the axis is bad, a points can be projected outside the grid... How to calculate the division in this case?
It is pity because the method could calculate a lot of volumes.
Maybe that inpire an idea to somebody ?
stuh505
03 March 2006, 02:10 PM
 a second grid is created with new divisions and by using the elevations.
 the right UV is calculated with the new grid. (by using the length of the segments of the grid)
Are you using Max's "relax uv's" function to do this? Or your own similar function?
Unfortunately, I see now that there are a problem: if the axis is bad, a points can be projected outside the grid... How to calculate the division in this case?
No need to actually make a grid the first time around. Just consider the equation for an infinite plane that is defined by the average normal of the selected vertices
arketip
03 March 2006, 08:56 PM
Are you using Max's "relax uv's" function to do this? Or your own similar function?
Nothing so complex. I create the first grid as a morphing from an edge to the other one.
Here is the reason of the script name: morphMap (morphing mapping)
It is just an interpolation of vertices position. For example if i have to create an element at position U=0.2, the points of left edge are mixed by the right edge : 0.8 for the left edge and 0.2 for the right edge.
This interpolation is a bit modified (move, scale, rotation) to follow the 2 other edges (they are a kind of guide).
I obtain the grid.
For the second grid it is the same but I will add a deplacement: the elevation.
No need to actually make a grid the first time around. Just consider the equation for an infinite plane that is defined by the average normal of the selected vertices
Unfortunally the first grid exist to evaluate the position in the UV space and it's not always planar.
And I don't work with an regular space. Nothing can be outside 01.
But There is certainly a solution.
That becomes every day clearer.
Today i realize that I do not need a projection...
stuh505
03 March 2006, 11:58 PM
Hmm, I guess I don't understand the problem then
MrSparkle
03 March 2006, 09:39 AM
Thanks for the update! I do understand where the problem is, but I still don't have a solution for this. When projecting the vertices to the plane, there will be some points that could be projected outside the grid area. But that would be a wrong solution because the texture sould be wrapped around the geometry...
Maybe the grid does not only need to be deformed by an elevation (along the local z axis) but by a vector that also allows to translate the grid points into 3 directions (xyz)?
Just an idea... I'm looking forward to see your script working!
CGTalk Moderation
03 March 2006, 09:39 AM
This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.