Esempio n. 1
0
// Load a 3D Studio MAX model and convert its vertex and texture coordinates
// from 3DS' right-handed coordinate system to Aleph One's left-handed system.
bool LoadModel_Studio_RightHand(FileSpecifier& Spec, Model3D& Model)
{
	bool Result = LoadModel_Studio(Spec, Model);
	if (!Result) return Result;

	logTrace("Converting handedness.");

	// Wings 3d and Blender produce 3DS models with a z-up orientation,
	// and for Blender models y increases towards the back. In Aleph One,
	// z increases upward, and items that have been placed with 0 degrees
	// of rotation face in the positive-x direction.
	// Preserve the orientation and switch handedness by swapping and
	// flipping x and y.
	for (unsigned XPos = 0; XPos < Model.Positions.size(); XPos += 3)
	{
		GLfloat X = Model.Positions[XPos];
		Model.Positions[XPos] = -Model.Positions[XPos + 1];
		Model.Positions[XPos + 1] = -X;
	}

	// Put the vertices of faces back into clockwise order.
	for (unsigned IPos = 0; IPos < Model.VertIndices.size(); IPos += 3)
	{
		int Index = Model.VertIndices[IPos + 1];
		Model.VertIndices[IPos + 1] = Model.VertIndices[IPos];
		Model.VertIndices[IPos] = Index;
	}

	// Switch texture coordinates from right-handed (x,y) to
	// left-handed (row,column).
	for (unsigned YPos = 1; YPos < Model.TxtrCoords.size(); YPos += 2)
	{
		Model.TxtrCoords[YPos] = 1.0 - Model.TxtrCoords[YPos];
	}

	return true;
}
Esempio n. 2
0
void OGL_ModelData::Load()
{
  // Already loaded?
  if (ModelPresent()) {
    return;
  }

  // Load the model
  Model.Clear();

  if (ModelFile == FileSpecifier()) {
    return;
  }
  if (!ModelFile.Exists()) {
    return;
  }

  bool Success = false;

  char *Type = &ModelType[0];
  if (StringsEqual(Type,"wave",4)) {
    // Alias|Wavefront
    Success = LoadModel_Wavefront(ModelFile, Model);
  }
  else if (StringsEqual(Type,"3ds",3)) {
    // 3D Studio Max
    Success = LoadModel_Studio(ModelFile, Model);
  }
  else if (StringsEqual(Type,"dim3",4)) {
    // Brian Barnes's "Dim3" model format (first pass: model geometry)
    Success = LoadModel_Dim3(ModelFile, Model, LoadModelDim3_First);

    // Second and third passes: frames and sequences
    try
    {
      if (ModelFile1 == FileSpecifier()) {
        throw 0;
      }
      if (!ModelFile1.Exists()) {
        throw 0;
      }
      if (!LoadModel_Dim3(ModelFile1, Model, LoadModelDim3_Rest)) {
        throw 0;
      }
    }
    catch(...)
    {}
    //
    try
    {
      if (ModelFile2 == FileSpecifier()) {
        throw 0;
      }
      if (!ModelFile2.Exists()) {
        throw 0;
      }
      if (!LoadModel_Dim3(ModelFile2, Model, LoadModelDim3_Rest)) {
        throw 0;
      }
    }
    catch(...)
    {}
  }
#if HAVE_QUESA
  else if (StringsEqual(Type,
                        "qd3d") ||
           StringsEqual(Type,"3dmf") || StringsEqual(Type,"quesa")) {
    // QuickDraw 3D / Quesa
    Success = LoadModel_QD3D(ModelFile, Model);
  }
#endif

  if (!Success) {
    Model.Clear();
    return;
  }

  // Calculate transformation matrix
  GLfloat Angle, Cosine, Sine;
  GLfloat RotMatrix[3][3], NewRotMatrix[3][3], IndivRotMatrix[3][3];
  MatIdentity(RotMatrix);

  MatIdentity(IndivRotMatrix);
  Angle = (float)Degree2Radian*XRot;
  Cosine = (float)cos(Angle);
  Sine = (float)sin(Angle);
  IndivRotMatrix[1][1] = Cosine;
  IndivRotMatrix[1][2] = -Sine;
  IndivRotMatrix[2][1] = Sine;
  IndivRotMatrix[2][2] = Cosine;
  MatMult(IndivRotMatrix,RotMatrix,NewRotMatrix);
  MatCopy(NewRotMatrix,RotMatrix);

  MatIdentity(IndivRotMatrix);
  Angle = (float)Degree2Radian*YRot;
  Cosine = (float)cos(Angle);
  Sine = (float)sin(Angle);
  IndivRotMatrix[2][2] = Cosine;
  IndivRotMatrix[2][0] = -Sine;
  IndivRotMatrix[0][2] = Sine;
  IndivRotMatrix[0][0] = Cosine;
  MatMult(IndivRotMatrix,RotMatrix,NewRotMatrix);
  MatCopy(NewRotMatrix,RotMatrix);

  MatIdentity(IndivRotMatrix);
  Angle = (float)Degree2Radian*ZRot;
  Cosine = (float)cos(Angle);
  Sine = (float)sin(Angle);
  IndivRotMatrix[0][0] = Cosine;
  IndivRotMatrix[0][1] = -Sine;
  IndivRotMatrix[1][0] = Sine;
  IndivRotMatrix[1][1] = Cosine;
  MatMult(IndivRotMatrix,RotMatrix,NewRotMatrix);
  MatCopy(NewRotMatrix,RotMatrix);

  MatScalMult(NewRotMatrix,Scale);                              // For the position vertices
  if (Scale < 0) {
    MatScalMult(RotMatrix,-1);                          // For the normals
  }
  // Is model animated or static?
  // Test by trying to find neutral positions (useful for working with the normals later on)
  if (Model.FindPositions_Neutral(false)) {
    // Copy over the vector and normal transformation matrices:
    for (int k=0; k<3; k++)
      for (int l=0; l<3; l++)
      {
        Model.TransformPos.M[k][l] = NewRotMatrix[k][l];
        Model.TransformNorm.M[k][l] = RotMatrix[k][l];
      }

    Model.TransformPos.M[0][3] = XShift;
    Model.TransformPos.M[1][3] = YShift;
    Model.TransformPos.M[2][3] = ZShift;

    // Find the transformed bounding box:
    bool RestOfCorners = false;
    GLfloat NewBoundingBox[2][3];
    // The indices i1, i2, and i3 are for selecting which of the box's two principal corners
    // to get coordinates from
    for (int i1=0; i1<2; i1++)
    {
      GLfloat X = Model.BoundingBox[i1][0];
      for (int i2=0; i2<2; i2++)
      {
        GLfloat Y = Model.BoundingBox[i2][0];
        for (int i3=0; i3<2; i3++)
        {
          GLfloat Z = Model.BoundingBox[i3][0];

          GLfloat Corner[3];
          for (int ic=0; ic<3; ic++)
          {
            GLfloat *Row = Model.TransformPos.M[ic];
            Corner[ic] = Row[0]*X + Row[1]*Y + Row[2]*Z + Row[3];
          }

          if (RestOfCorners) {
            // Find minimum and maximum for each coordinate
            for (int ic=0; ic<3; ic++)
            {
              NewBoundingBox[0][ic] = min(NewBoundingBox[0][ic],Corner[ic]);
              NewBoundingBox[1][ic] = max(NewBoundingBox[1][ic],Corner[ic]);
            }
          }
          else
          {
            // Simply copy it in:
            for (int ic=0; ic<3; ic++)
              NewBoundingBox[0][ic] = NewBoundingBox[1][ic] = Corner[ic];
            RestOfCorners = true;
          }
        }
      }
    }

    for (int ic=0; ic<2; ic++)
      objlist_copy(Model.BoundingBox[ic],NewBoundingBox[ic],3);
  }
  else
  {
    // Static model
    size_t NumVerts = Model.Positions.size()/3;

    for (size_t k=0; k<NumVerts; k++)
    {
      GLfloat *Pos = Model.PosBase() + 3*k;
      GLfloat NewPos[3];
      MatVecMult(NewRotMatrix,Pos,NewPos);                      // Has the scaling
      Pos[0] = NewPos[0] + XShift;
      Pos[1] = NewPos[1] + YShift;
      Pos[2] = NewPos[2] + ZShift;
    }

    size_t NumNorms = Model.Normals.size()/3;
    for (size_t k=0; k<NumNorms; k++)
    {
      GLfloat *Norms = Model.NormBase() + 3*k;
      GLfloat NewNorms[3];
      MatVecMult(RotMatrix,Norms,NewNorms);                     // Not scaled
      objlist_copy(Norms,NewNorms,3);
    }

    // So as to be consistent with the new points
    Model.FindBoundingBox();
  }

  Model.AdjustNormals(NormalType,NormalSplit);
  Model.CalculateTangents();

  // Don't forget the skins
  OGL_SkinManager::Load();
}