Retrieve texture coords when no UVW tag exists

On 18/05/2015 at 09:30, xxxxxxxx wrote:

User Information:
Cinema 4D Version:   R15 
Platform:   Windows  ;   
Language(s) :     C++  ;

I have an importer for C4D files that worked as expected for a long time, until I got this file with no UVW tag on it.

Until now, I thought the UVW tag was always present in the C4D file, and I could always rely on that for my uvw mapping. Turns out, there are files missing this tag, and as a result, I get an unmapped model in my application.

My problem though, is not the missing tag, but how do I use the "projection" property from the "texture" tag to generate UVW coords for my model. I could generate them myself based on the property, but I'm expecting that Melange SDK has some way of doing this, to avoid extra complexity to my application.


On 18/05/2015 at 10:05, xxxxxxxx wrote:

search for "TexData" in old SDK documentation "I find it in R13 SDK documentation , you may find it also in R15 SDK documentation , but I don't find it in R16 SDK documentation "

On 18/05/2015 at 10:35, xxxxxxxx wrote:

Hi, thanks for you answer.
I saw this ShdProjectionPoint and also ProjectionPoint function in another thread in this forum, but unfortunately I cannot use them, because they are not part of the Melange SDK. I think I can use them to create my own UVs using the code in the SDK, but that's something I would rather avoid.

On 18/05/2015 at 10:52, xxxxxxxx wrote:

then the best solution is: each polygon got 3 or 4 points "a,b,c,d" , make a square UV for them, (0,0) , (1, 0) , (1,1) , (0,1)

On 19/05/2015 at 07:07, xxxxxxxx wrote:

Ok, so the only solution here, seems to be to generate my own UV coords based on the ProjectionPoint function from the SDK.

On 19/05/2015 at 08:22, xxxxxxxx wrote:


Melange is a library that allows you to access C4D files. It is no framework to build 3D applications so it does not offer such functionality (like creating UVW coordinates) and it does not intend to offer such functionality.

Best wishes,

On 19/05/2015 at 08:28, xxxxxxxx wrote:

Hi, I understand that. 
I only thought that the projection type could in some way save UV coordinates to the C4D file, but what I see now, is that this texture projection property, is just a way for the Render to know how to generate UVs.

Thanks for you replies.

On 21/05/2015 at 06:34, xxxxxxxx wrote:

Hi Mohamed,

you were mentioning, that TexData is not in the R16 SDK documentation. While this may have been true, when R16 got release, I'd like to point out, that there's an updated documentation which contains all the content from previous versions plus some more. It's available online (here's TexData) and also for download.

On 21/05/2015 at 08:37, xxxxxxxx wrote:

Hi Andreas,

yep it is there , but the "example" is not there .

On 21/05/2015 at 09:27, xxxxxxxx wrote:

Ooopsy, the example slipped through our hands. Terribly sorry.
We'll add it with the next documentation update.
Thanks for pointing this out to us.

On 21/05/2015 at 16:04, xxxxxxxx wrote:

I ended up using the example code from the TexData to generate my own UVs, but now have a small issue that I ended up understanding, but can't seem to find a solution.

For the Cylindrical projection, I'm getting an odd mapping on the last quad. Looking at the results from the ProjectPoint function, I noticed that the resulting UV values for the last 2 vertexes of my cylinder are 0 instead of 1. This is because the first 2 vertexes and the last 2 are the same and of course the function returns the same value (0).

This doesn't have that much to do with the SDK itself, but maybe someone knows a way to fix it. I'm new to UVs, I tried a lot of workarounds but none seem to be foolproof.

Here's my example, a cylinder with 8 sides (no caps), and the results of the projection a,b,c and d per line:

0.7500  0.7500  0.8750  0.8750
0.0000  0.0000  0.1250  0.1250
0.6250  0.6250  0.7500  0.7500
0.3750  0.3750  0.5000  0.5000
0.1250  0.1250  0.2500  0.2500
0.5000  0.5000  0.6250  0.6250
0.8750  0.8750   **0.0000  0.0000**
0.2500  0.2500  0.3750  0.3750

red lines are relative to the same vertex, and bold red is where I should get 1 instead of 0.

On 21/05/2015 at 17:27, xxxxxxxx wrote:

you are doing it wrong, UV data is per "face" , NOT per "vertex" , so a vertex sharing 2 faces like in Cylinder without caps will have 2 different UV coordinates, 1 for each face.

On 21/05/2015 at 17:37, xxxxxxxx wrote:

Originally posted by xxxxxxxx

you are doing it wrong, UV data is per "face" , NOT per "vertex" , so a vertex sharing 2 faces like in Cylinder without caps will have 2 different UV coordinates, 1 for each face.

Yes, exactly!
Maybe I forgot to mention some extra data on my previous post. Those numbers in that table are for U (X) only, I didn't mention V (Y), because there's no problem there.

Also, each line is the UV data for 1 face, and of course if 1 face has 4 vertexes, I get 4 U's.

On 21/05/2015 at 17:54, xxxxxxxx wrote:

write the function that you use to produce them

On 21/05/2015 at 18:25, xxxxxxxx wrote:

Even better, here are the vertexes for my cylinder:

(0.000000 -100.000000 50.000000) 	(0.000000 100.000000 50.000000) 	(-35.355339 100.000000 35.355339) 	(-35.355339 -100.000000 35.355339)
 **(-50.000000 -100.000000 0.000000) 	(-50.000000 100.000000 0.000000) **	(-35.355339 100.000000 -35.355339) 	(-35.355339 -100.000000 -35.355339)
(35.355339 -100.000000 35.355339) 	(35.355339 100.000000 35.355339) 	(0.000000 100.000000 50.000000) 	(0.000000 -100.000000 50.000000)
(35.355339 -100.000000 -35.355339) 	(35.355339 100.000000 -35.355339) 	(50.000000 100.000000 -0.000000) 	(50.000000 -100.000000 -0.000000)
(-35.355339 -100.000000 -35.355339) (-35.355339 100.000000 -35.355339) 	(-0.000000 100.000000 -50.000000) 	(-0.000000 -100.000000 -50.000000)
(50.000000 -100.000000 -0.000000) 	(50.000000 100.000000 -0.000000) 	(35.355339 100.000000 35.355339) 	(35.355339 -100.000000 35.355339)
(-35.355339 -100.000000 35.355339) 	(-35.355339 100.000000 35.355339) 	 **(-50.000000 100.000000 0.000000) 	(-50.000000 -100.000000 0.000000)**
(-0.000000 -100.000000 -50.000000) 	(-0.000000 100.000000 -50.000000) 	(35.355339 100.000000 -35.355339) 	(35.355339 -100.000000 -35.355339)

And now, how I calculate the UVs for a specific vertex, it's actually very similar to the function ProjectPoint:
This code is executed 4 times per face (for each vertex, a,b,c and d)

if (p.x == 0.0 && p.z == 0.0)
    uvw.x = 0.0;
    **uvw.x = atan2(p.z, p.x) / PI2;**
    uvw.x -= projOffsetx;
    if (projLenx > 0.0 && uvw.x < 0.0)
        uvw.x += 1.0;
    else if (projLenx < 0.0 && uvw.x > 0.0)
        uvw.x -= 1.0;
    uvw.x *= projLenxInv;
uvw.y = -(p.y * 0.5 + projOffsety + 0.5) * projLenyInv;

The important part is in bold, all the rest is code to deal with offsets and repeats. 
So now, if you look at the vertex table I posted above, you'll notice in bold, the same vertexes belonging to different faces, but applying my formula for uvw.x they will get the same U, because they have the same coords.

Again, only U is shown in the image.
The smile face should be completely around the cylinder, but in my case, the last face has a repetition, because the last UV coordinates are wrong.

On 21/05/2015 at 19:02, xxxxxxxx wrote:

what you are missing is a "direction" , so you have 4 points, a,b,c,d, get the normal of the uv polygon

Vector normal = cross(c - a, d - b);
if(normal.z < 0) //do something

On 21/05/2015 at 19:46, xxxxxxxx wrote:

Maybe this will help, but this math is the inverse of mapping a planar image onto a cylinder (so, it maps the cylinder onto the uv planar space).  This math may assume that the origin is at the center of the cylinder.

Let say you have a rectangle image of length: L and height: H.
and a cylinder of radius : R and height H'
A(x,y,z) from the cylinder

A'(u,v) in the image :

v = z*(H/H')

and u = L/(2Pi)* { arccos(x/R) *(sign(y)) (mod(2Pi)) }

On 22/05/2015 at 08:38, xxxxxxxx wrote:

Originally posted by xxxxxxxx

what you are missing is a "direction" , so you have 4 points, a,b,c,d, get the normal of the uv polygon

Vector normal = cross(c - a, d - b);
if(normal.z < 0) //do something

Hey! You nailed it!

Just for the completion of the answer, I will say that I needed to add 1.0 (InverseLength) to the U coordinate C and 😧

Vector normal = Cross(uvw.c - uvw.a, uvw.d - uvw.b); if (normal.z < 0 && projType == TEXTURETAG_PROJECTION_CYLINDRICAL) { uvw.c.x += projLenxInv; uvw.d.x += projLenxInv; }

So, thanks for the help!