3ds with max's texture coordinates

F923e021a633170fb10416df23dffddd
0
urika 101 Aug 10, 2003 at 13:20

i loaded a 3ds object into my program , i managed to load the texture as well but not as i mapped it in 3d studio max 5
the “preserve max’s texture coordinates” is checked but still it kinda puts the jpg on the object without mapping
can anyone help?

32 Replies

Please log in or register to post a reply.

F7a4a748ecf664f189bb704a660b3573
0
anubis 101 Aug 10, 2003 at 18:52

well, without seeing any code it’s hard to help you

F923e021a633170fb10416df23dffddd
0
urika 101 Aug 12, 2003 at 07:55

its basicly the 3ds loader from gametutorials (that can also read jpeg)
i changed the 3ds object to mine.
i can post code but since i dont know where the problem is i dont really know what to post :blush:
while i m looking 4 a solution myself i came across glTexCoordPointer
does this have something to do with it (or something like it)?

F7a4a748ecf664f189bb704a660b3573
0
anubis 101 Aug 12, 2003 at 12:26

well, if you pass glTexCoordPointer the texture coordiantes from your max file i don’t know why it doesn’t work. it looks like some small bug in your code… which i can’t fix for you ;)

F923e021a633170fb10416df23dffddd
0
urika 101 Aug 12, 2003 at 13:55

i did not use glTexCoordPointer yet!
i just saw it in the msdn help as i was looking for a solution.
can anyone post some code with glTexCoordPointer?
or just tell me where i can find something helpful.. :nod:

F7a4a748ecf664f189bb704a660b3573
0
anubis 101 Aug 12, 2003 at 15:02

try to find out about opengl vertex buffers. you might want to google for the “opengl red book”

F923e021a633170fb10416df23dffddd
0
urika 101 Aug 14, 2003 at 12:48

here is some code that i think should texture correctly but doesnt
if(pObject->bHasTexture)
{

// Make sure there was a UVW map applied to the object or else it won’t have tex coords.
if(pObject->pTexVerts)
{
glTexCoord2f(pObject->pTexVerts[ index ].x, pObject->pTexVerts[ index ].y);
}
}

i assume the info in pTexVerts is correct but still it doesnt texturize correctly

F923e021a633170fb10416df23dffddd
0
urika 101 Aug 24, 2003 at 09:00

after working on it and changing the order of things , the texture appears on the object but not as in 3d studio max, why ????? is there something in max that i need to change? :blink:

6ad5f8c742f1e8ec61000e2b0900fc76
0
davepermen 101 Aug 24, 2003 at 11:04

how “different”? mirrored or what?

i don’t know. we never had such problems, it… just worked.. :
F923e021a633170fb10416df23dffddd
0
urika 101 Aug 24, 2003 at 12:06

first of all thanks for trying.
my object is a jet fighter, in max i put a texture using unwrap uvw so it would look lifelike.
when i use the object in opengl , it uses the same jpg allright but the coordinates have moved , for instance the back fin texture is smeared on the wing.
i don’t know WHERE the problem is openGL? Max?(it looks good in max) :eek:

6ad5f8c742f1e8ec61000e2b0900fc76
0
davepermen 101 Aug 24, 2003 at 17:27

hm.. comparison pics (hint: my webspace for hosting), or actual loading code could help i guess.. difficult without any info on WHAT is wrong, or HOW its wrong..

F923e021a633170fb10416df23dffddd
0
urika 101 Aug 28, 2003 at 08:34

it works!!!!
the problem was this:
there was glTexCoord2f(pObject->pTexVerts[ind].x, pObject->pTexVerts[ind].y);
and when i changed it to
glTexCoord2f(pObject->pTexVerts[ind].x, -pObject->pTexVerts[ind].y);
it works (the “-“ made the differance).
i dont exactly understand why…
can any one enlighten me? B)

F7a4a748ecf664f189bb704a660b3573
0
anubis 101 Aug 28, 2003 at 08:52

max has strange ways of dealing with coordinates in general… y - z axis mixed up, etc. i wouldn’t know y it should store negative texture coordinates. also i never had that problem…

6ad5f8c742f1e8ec61000e2b0900fc76
0
davepermen 101 Aug 29, 2003 at 07:34

hm… very weird.. what format is the texture? and what do you use to load it?

because some images are known to be stored “topdown” => you have to flip the y-coord (actually you have to calc 1-ycoord, but if you have GL_REPEAT, result is the same..)

F7a4a748ecf664f189bb704a660b3573
0
anubis 101 Aug 29, 2003 at 08:17

hey… that might be the solution… why didn’t i think of that ???
i bet he’s using targas for textures…

F923e021a633170fb10416df23dffddd
0
urika 101 Aug 31, 2003 at 10:03

the texture format is jpg , i dont know what is “targas”.
my loader is basically from gametutorials.com

0684f9d33f52fa189aad7ac9e8c87510
0
baldurk 101 Aug 31, 2003 at 10:09

The Targa image format is quite common. The file extension is generally .tga

F7a4a748ecf664f189bb704a660b3573
0
anubis 101 Aug 31, 2003 at 10:27

and very often they are stored upside-down

F923e021a633170fb10416df23dffddd
0
urika 101 Sep 01, 2003 at 08:00

nope, jpg

6ad5f8c742f1e8ec61000e2b0900fc76
0
davepermen 101 Sep 01, 2003 at 12:12

well, all i know is jpg and bmp are upsidedown with relation to eachother.. i always “loved” that in DevIL.. but you could set there a mode to lode in the correct orientation..

i guess its that.. flip your jpgs..

A504dbae5d83a5bbdbc5075e2f1ecf2c
0
Vifani 101 Sep 04, 2003 at 15:05

Hi guys,

can you tell me how to flip y coords ? have you some code?

I have a problem with TGA and JPG file, while with BMP file all looks great!

A504dbae5d83a5bbdbc5075e2f1ecf2c
0
Vifani 101 Sep 05, 2003 at 12:18

Can anyone help me ? :unsure:

Fdbdc4176840d77fe6a8deca457595ab
0
dk 158 Sep 05, 2003 at 15:30

Try this:

unsigned char *temp = new unsigned char[width * height * 4];
memcpy(temp, data, width * height * 4);
for(j = 0; j < height; j++)
{
    memcpy(&data[((height-1) - j)*4*width], &temp[j*4*width], 4*width);
}
delete[] temp;

I didn’t check if it works though :D

6ad5f8c742f1e8ec61000e2b0900fc76
0
davepermen 101 Sep 05, 2003 at 15:45

@Vifani

Hi guys,

can you tell me how to flip y coords ? have you some code?

I have a problem with TGA and JPG file, while with BMP file all looks great!

hm.. statistically, this rather means you have a problem with your bmp files, and in your code another problem wich makes your bmp problem dissapear:D

A504dbae5d83a5bbdbc5075e2f1ecf2c
0
Vifani 101 Sep 05, 2003 at 16:09

@apex

Try this:

unsigned char *temp = new unsigned char[width * height * 4];memcpy(temp, data, width * height * 4);for(j = 0; j < height; j++){    memcpy(&data[((height-1) - j)*4*width], &temp[j*4*width], 4*width);}delete[] temp;

I didn’t check if it works though :D

Thank you for this code but the result is the same :sigh:

davepermen the problem is caused by the different data order stored in JPG and TGA. The texture coords are generated by 3D Studio Max so that are surely exact (with BMP all works fine!).

Have anyone ideas to solve this problem ?

A504dbae5d83a5bbdbc5075e2f1ecf2c
0
Vifani 101 Sep 05, 2003 at 16:18

With BMP
bmp.jpg

With TGA
tga.jpg

F7a4a748ecf664f189bb704a660b3573
0
anubis 101 Sep 05, 2003 at 21:28

this looks like some tga loading error… check your loader… it might be a cast error… this kind of error might be induced by some really small bug in your code… double check everything

A504dbae5d83a5bbdbc5075e2f1ecf2c
0
Vifani 101 Sep 05, 2003 at 21:46

The problem is the texture resolution. When I use a resolution such as 510x1001 the problem is present. if I use a texture 512x1024 all look fine!

This is normal for you ?

With BMP I can use all texture that I need without any limits (2048x2048 is the hardware limit).

Fdbdc4176840d77fe6a8deca457595ab
0
dk 158 Sep 06, 2003 at 05:16

It doesn’t look to me that your y-coords is flipped; It seems to me that you loaded the file incorrectly.

Could you show some code as to how you’re loading the image?

Oh, btw, I think you’re only supposed to load images in power of 2’s

A504dbae5d83a5bbdbc5075e2f1ecf2c
0
Vifani 101 Sep 06, 2003 at 09:22

The code is the same of GameTutorials.com

tImageTGA *t3DModel::LoadTGA(const char *filename)
{
    tImageTGA *pImageData = NULL; // This stores our important image data
    WORD width = 0, height = 0;     // The dimensions of the image
    byte length = 0;    // The length in bytes to the pixels
    byte imageType = 0;     // The image type (RLE, RGB, Alpha...)
    byte bits = 0;   // The bits per pixel for the image (16, 24, 32)
    FILE *pFile = NULL;     // The file pointer
    int channels = 0;   // The channels of the image (3 = RGA : 4 = RGBA)
    int stride = 0;   // The stride (channels * width)
    int i = 0;      // A counter
 
    // This function loads in a TARGA (.TGA) file and returns its data to be
    // used as a texture or what have you. This currently loads in a 16, 24
    // and 32-bit targa file, along with RLE compressed files. Eventually you
    // will want to do more error checking to make it more robust. This is
    // also a perfect start to go into a modular class for an engine.
    // Basically, how it works is, you read in the header information, then
    // move your file pointer to the pixel data. Before reading in the pixel
    // data, we check to see the if it's an RLE compressed image. This is because
    // we will handle it different. If it isn't compressed, then we need another
    // check to see if we need to convert it from 16-bit to 24 bit. 24-bit and
    // 32-bit textures are very similar, so there's no need to do anything special.
    // We do, however, read in an extra bit for each color.

    // Open a file pointer to the targa file and check if it was found and opened 
    if((pFile = fopen(filename, "rb")) == NULL) 
    {
 // Display an error message saying the file was not found, then return NULL
 MessageBox(istanza.hWnd, "Unable to load TGA File!", "Error", MB_OK);
 return NULL;
    }
 
    // Allocate the structure that will hold our eventual image data (must free it!)
    pImageData = (tImageTGA*)malloc(sizeof(tImageTGA));

    // Read in the length in bytes from the header to the pixel data
    fread(&length, sizeof(byte), 1, pFile);
    
    // Jump over one byte
    fseek(pFile,1,SEEK_CUR); 

    // Read in the imageType (RLE, RGB, etc...)
    fread(&imageType, sizeof(byte), 1, pFile);
    
    // Skip past general information we don't care about
    fseek(pFile, 9, SEEK_CUR); 

    // Read the width, height and bits per pixel (16, 24 or 32)
    fread(&width, sizeof(WORD), 1, pFile);
    fread(&height, sizeof(WORD), 1, pFile);
    fread(&bits,  sizeof(byte), 1, pFile);
    
    // Now we move the file pointer to the pixel data
    fseek(pFile, length + 1, SEEK_CUR); 

    // Check if the image is RLE compressed or not
    if(imageType != TGA_RLE)
    {
 // Check if the image is a 24 or 32-bit image
 if(bits == 24 || bits == 32)
 {
    // Calculate the channels (3 or 4) - (use bits >> 3 for more speed).
    // Next, we calculate the stride and allocate enough memory for the pixels.
    channels = bits / 8;
    stride = channels * width;
    pImageData->data = new unsigned char[stride * height];

    // Load in all the pixel data line by line
    for(int y = 0; y < height; y++)
    {
  // Store a pointer to the current line of pixels
  unsigned char *pLine = &(pImageData->data[stride * y]);

  // Read in the current line of pixels
  fread(pLine, stride, 1, pFile);
    
  // Go through all of the pixels and swap the B and R values since TGA
  // files are stored as BGR instead of RGB (or use GL_BGR_EXT verses GL_RGB)
  for(i = 0; i < stride; i += channels)
  {
    int temp   = pLine[i];
    pLine[i]   = pLine[i + 2];
    pLine[i + 2] = temp;
  }
    }
 }
 // Check if the image is a 16 bit image (RGB stored in 1 unsigned short)
 else if(bits == 16)
 {
    unsigned short pixels = 0;
    int r=0, g=0, b=0;

    // Since we convert 16-bit images to 24 bit, we hardcode the channels to 3.
    // We then calculate the stride and allocate memory for the pixels.
    channels = 3;
    stride = channels * width;
    pImageData->data = new unsigned char[stride * height];

    // Load in all the pixel data pixel by pixel
    for(int i = 0; i < width*height; i++)
    {
  // Read in the current pixel
  fread(&pixels, sizeof(unsigned short), 1, pFile);
  
  // To convert a 16-bit pixel into an R, G, B, we need to
  // do some masking and such to isolate each color value.
  // 0x1f = 11111 in binary, so since 5 bits are reserved in
  // each unsigned short for the R, G and B, we bit shift and mask
  // to find each value. We then bit shift up by 3 to get the full color.
  b = (pixels & 0x1f) << 3;
  g = ((pixels >> 5) & 0x1f) << 3;
  r = ((pixels >> 10) & 0x1f) << 3;
  
  // This essentially assigns the color to our array and swaps the
  // B and R values at the same time.
  pImageData->data[i * 3 + 0] = r;
  pImageData->data[i * 3 + 1] = g;
  pImageData->data[i * 3 + 2] = b;
    }
 }  
 // Else return a NULL for a bad or unsupported pixel format
 else
    return NULL;
    }
    // Else, it must be Run-Length Encoded (RLE)
    else
    {
 // First, let me explain real quickly what RLE is. 
 // For further information, check out Paul Bourke's intro article at: 
 // http://astronomy.swin.edu.au/~pbourke/dataformats/rle/
 // 
 // Anyway, we know that RLE is a basic type compression. It takes
 // colors that are next to each other and then shrinks that info down
 // into the color and a integer that tells how much of that color is used.
 // For instance:
 // aaaaabbcccccccc would turn into a5b2c8
 // Well, that's fine and dandy and all, but how is it down with RGB colors?
 // Simple, you read in an color count (rleID), and if that number is less than 128,
 // it does NOT have any optimization for those colors, so we just read the next
 // pixels normally. Say, the color count was 28, we read in 28 colors like normal.
 // If the color count is over 128, that means that the next color is optimized and
 // we want to read in the same pixel color for a count of (colorCount - 127).
 // It's 127 because we add 1 to the color count, as you'll notice in the code.

 // Create some variables to hold the rleID, current colors read, channels, & stride.
 byte rleID = 0;
 int colorsRead = 0;
 channels = bits / 8;
 stride = channels * width;

 // Next we want to allocate the memory for the pixels and create an array,
 // depending on the channel count, to read in for each pixel.
 pImageData->data = new unsigned char[stride * height];
 byte *pColors = new byte [channels];

 // Load in all the pixel data
 while(i < width*height)
 {
    // Read in the current color count + 1
    fread(&rleID, sizeof(byte), 1, pFile);
    
    // Check if we don't have an encoded string of colors
    if(rleID < 128)
    {
  // Increase the count by 1
  rleID++;

  // Go through and read all the unique colors found
  while(rleID)
  {
    // Read in the current color
    fread(pColors, sizeof(byte) * channels, 1, pFile);

    // Store the current pixel in our image array
    pImageData->data[colorsRead + 0] = pColors[2];
    pImageData->data[colorsRead + 1] = pColors[1];
    pImageData->data[colorsRead + 2] = pColors[0];

    // If we have a 4 channel 32-bit image, assign one more for the alpha
    if(bits == 32)
   pImageData->data[colorsRead + 3] = pColors[3];

    // Increase the current pixels read, decrease the amount
    // of pixels left, and increase the starting index for the next pixel.
    i++;
    rleID--;
    colorsRead += channels;
  }
    }
    // Else, let's read in a string of the same character
    else
    {
  // Minus the 128 ID + 1 (127) to get the color count that needs to be read
  rleID -= 127;

  // Read in the current color, which is the same for a while
  fread(pColors, sizeof(byte) * channels, 1, pFile);

  // Go and read as many pixels as are the same
  while(rleID)
  {
    // Assign the current pixel to the current index in our pixel array
    pImageData->data[colorsRead + 0] = pColors[2];
    pImageData->data[colorsRead + 1] = pColors[1];
    pImageData->data[colorsRead + 2] = pColors[0];

    // If we have a 4 channel 32-bit image, assign one more for the alpha
    if(bits == 32)
   pImageData->data[colorsRead + 3] = pColors[3];

    // Increase the current pixels read, decrease the amount
    // of pixels left, and increase the starting index for the next pixel.
    i++;
    rleID--;
    colorsRead += channels;
  }
  
    }
  
 }

 // Free up pColors
 delete[] pColors;
    }

    // Close the file pointer that opened the file
    fclose(pFile);

    // Fill in our tImageTGA structure to pass back
    pImageData->channels = channels;
    pImageData->sizeX  = width;
    pImageData->sizeY  = height;

    // Return the TGA data (remember, you must free this data after you are done)
    return pImageData;
}
F7a4a748ecf664f189bb704a660b3573
0
anubis 101 Sep 06, 2003 at 18:19

as apex said. with opengl you are only allowed to use pow 2 textures. if you use other resolutions the result is unpredictable

A504dbae5d83a5bbdbc5075e2f1ecf2c
0
Vifani 101 Sep 06, 2003 at 20:26

Thank you guys. I have already implemented also DXTC 1, 3 and 5 texture compression. :)

6ad5f8c742f1e8ec61000e2b0900fc76
0
davepermen 101 Sep 10, 2003 at 22:11

well, the pow2 will change with gl1.5.. can’t wait.. new drivers are not yet gl1.5 :(