.asc (3ds max) Texture coordinates

Hello,

I have a problem with the .asc file from 3ds max. I have drawn a 3d object in 3ds max, and had export it to a .asc file. I have written an converter which displays the object in opengl. Now I have a problem with my Texture coordinates, i have no idea how to use the exported ones.
And i have also no idea how to calculate texture coordinates for the Object.

thank you for reply

helda

p.s. i don’t want to use glTexGen

Hi there!

First hit “MESH_NUMTVERTEX” it says how many texture coordinates you have.

Then followed by “MESH_TVERT” keywords (for each texture coordinate) you have 3 values:
id u_coordinate v_coordinate.

After reading them you have “MESH_TFACE”'s (no.faces times) - each followed by 4 values: id and 3 ids of texture coordinates you’ve just read in.

Hope this helps.

are these parameters in the ase format? can i get this information in the .asc format?

helda

I have no experience with .asc at all.
As for .ASEs - these terms should be in exported file. Make sure you enable texture coordinates export in 3dsmax exporter.

do you have any specification of the .ase format, because i can test it with that. (or any code example)

Here’s cut’n’pasted ASE loader, should help, though its has some engine specific structs/macros.

bool Builder_c::ReadASE()
{
int i, j;
int NumFaces, NumVerts, NumTVerts;
int NumObjects;
int Flags, ShaderID;
Vec3_t *TmpVerts;
Vec2_t *TmpTVerts;
Parser_c Parser;

if (!Parser.Open(“Base/Data/Maps_in/ASE/%s”, FileName))
{
LOL_WARN(“Couldn’t open map file "%s" in "%s"”, Parser.GetFileName());
return false;
}

// Extract name without extension
Name = LOL_ALLOC char[strlen(FileName) - 3];
memcpy(Name, FileName, sizeof(char) * (strlen(FileName) - 4));
Name[strlen(FileName) - 4] = ‘\0’;

LOL_PRINT(“$>Building map from "%s" (%.2f kB)…”, FileName, (float) Parser.FileSize() / 1024);
LOL_REFRESH;

// Materials
//----------

Parser.Next(“*MATERIAL_COUNT”);
LOL_FOR(i = Parser.NextInt(), i > 0, i–)
{
Parser.Next(“*BITMAP”);
ShaderRefs.Alloc();
strcpy(ShaderRefs.Get().Name, Parser.Next());
}

// Objects
//--------

NumObjects = 0;
NumVerts = 1;
NumTVerts = 1;
TmpVerts = LOL_ALLOC Vec3_t[NumVerts];
TmpTVerts = LOL_ALLOC Vec2_t[NumTVerts];

while (!Parser.EOFile())
{
LOL_REFRESH;
if (!Parser.Next2(“*GEOMOBJECT”, “*LIGHTOBJECT”))
{
break;
}

  // Light object
  //-------------

  if (!stricmp("*LIGHTOBJECT", Parser.Curr()))
  {
  	Lights.Alloc();

  	// Default Flags
  	Lights.Get().Flags = LIGHT_SHADOWS | LIGHT_CORONA;

  	// Position
  	Parser.Next("*TM_POS");			
  	Lights.Get().Origin[0] = -Parser.NextFloat();
  	Lights.Get().Origin[2] = Parser.NextFloat();
  	Lights.Get().Origin[1] = Parser.NextFloat();

  	// Color (Alpha == 1 by default)
  	Parser.Next("*LIGHT_COLOR");
  	Lights.Get().Color[0] = Parser.NextFloat();
  	Lights.Get().Color[1] = Parser.NextFloat();
  	Lights.Get().Color[2] = Parser.NextFloat();
  	Lights.Get().Color[3] = 1.0f;

  	continue;
  }

  // Geometric object
  //-----------------

  NumObjects++;

  // Face Flags
  Parser.Next("*NODE_NAME");
  if (stristr(Parser.Next(), "INVISIBLE"))
  {
  	Flags = FACE_INVISIBLE | FACE_SEETHROUGH | FACE_NOTSOLID;
  }
  else if (stristr(Parser.Next(), "SEETHROUGH"))
  {
  	Flags = FACE_SEETHROUGH | FACE_NOTSOLID;
  }
  else
  {
  	Flags = 0;
  }

  Parser.Next("*MESH_NUMVERTEX");
  i = Parser.NextInt();
  
  Parser.Next("*MESH_NUMFACES");
  NumFaces = Parser.NextInt();

  // Verts
  if (i > NumVerts)
  {
  	NumVerts = i;
  	LOL_FREE1D( TmpVerts );
  	TmpVerts = LOL_ALLOC Vec3_t[NumVerts];
  }
  else
  {
  	NumVerts = i;
  }

  LOL_FOR(i = 0, i < NumVerts, i++)
  {
  	Parser.Next("*MESH_VERTEX");
  	Parser.Next();			// Skip int

  	// Exchange Y with Z, negate X
  	TmpVerts[i][0] = -Parser.NextFloat();
  	TmpVerts[i][2] = Parser.NextFloat();
  	TmpVerts[i][1] = Parser.NextFloat();
  }

  // Verts to Faces associations
  LOL_FOR(i = 0, i < NumFaces, i++)
  {
  	Parser.Next("*MESH_FACE");
  	Parser.Next();			// Skip "int:"
  	Parser.Next();			// Skip "A:"

  	Faces.Alloc();
  	Faces.Get().FirstVert = Verts.GetNum();
  	Faces.Get().NumVerts = 3;

  	// Inverse order to clockwise
  	j = Verts.Alloc();
  	Verts.Alloc();
  	Verts.Alloc();

  	Verts.Get(j).Pos = TmpVerts[ Parser.NextInt() ];
  	Parser.Next();			// Skip "B:"
  	Verts.Get(j + 2).Pos = TmpVerts[ Parser.NextInt() ];
  	Parser.Next();			// Skip "C:"
  	Verts.Get(j + 1).Pos = TmpVerts[ Parser.NextInt() ];

  	// Set to NULL for Kill() reasons
  	Faces.Get().EdgesID = NULL;
  }

  if (!(Flags & FACE_INVISIBLE))
  {
  	// Texture coords
  	Parser.Next("*MESH_NUMTVERTEX");
  	i = Parser.NextInt();

  	if (i > NumTVerts)
  	{
  		NumTVerts = i;
  		LOL_FREE1D( TmpTVerts );
  		TmpTVerts = LOL_ALLOC Vec2_t[NumTVerts];
  	}
  	else
  	{
  		NumTVerts = i;
  	}

  	LOL_FOR(i = 0, i < NumTVerts, i++)
  	{
  		Parser.Next("*MESH_TVERT");
  		Parser.Next();		// Skip int

  		TmpTVerts[i][0] = Parser.NextFloat();
  		TmpTVerts[i][1] = Parser.NextFloat();
  	}

  	// Texture coords to faces associations
  	j = Faces.GetNum() - NumFaces;

  	LOL_FOR(i = 0, i < NumFaces, (i++, j++))
  	{
  		Parser.Next("*MESH_TFACE");
  		Parser.Next();		// Skip int

  		// Inverse order to clockwise
  		Verts.Get( Faces.Get(j).FirstVert ).Tex0 = TmpTVerts[ Parser.NextInt() ];
  		Verts.Get( Faces.Get(j).FirstVert + 2 ).Tex0 = TmpTVerts[ Parser.NextInt() ];
  		Verts.Get( Faces.Get(j).FirstVert + 1 ).Tex0 = TmpTVerts[ Parser.NextInt() ];
  	}
  }

  // Material reference
  Parser.Next("*MATERIAL_REF");
  ShaderID = Parser.NextInt();

  // Assign common features for Faces
  j = Faces.GetNum() - NumFaces;

  LOL_FOR(i = 0, i < NumFaces, (i++, j++))
  {
  	Faces.Get(j).Flags = Flags;
  	Faces.Get(j).ShaderID = ShaderID;
  }

}

LOL_FREE1D( TmpVerts );
LOL_FREE1D( TmpTVerts );

LOL_PRINT(“ASE File "%s" read [%d msec]”, FileName, Clock->TestTime());
LOL_PRINT(" - Verts %d", Verts.GetNum());
LOL_PRINT(" - Faces %d", Faces.GetNum());
LOL_PRINT(" - Shaders %d", ShaderRefs.GetNum());
LOL_PRINT(" - Lights %d", Lights.GetNum());
LOL_PRINT(" - Geometric objects %d", NumObjects);
LOL_REFRESH;

return true;
}