Пример #1
0
bool cGrCelestialBody::reposition( sgVec3 p, double angle, double rightAscension, double declination, double sol_dist )
{
    sgMat4 T1, T2, GST, RA, DEC;
    sgVec3 axis;
    sgVec3 v;

    sgMakeTransMat4( T1, p );

    sgSetVec3( axis, 0.0, 0.0, -1.0 );
    sgMakeRotMat4( GST, (float)angle, axis );

    sgSetVec3( axis, 0.0, 0.0, 1.0 );
    sgMakeRotMat4( RA, (float)((rightAscension * SGD_RADIANS_TO_DEGREES) - 90.0), axis );

    sgSetVec3( axis, 1.0, 0.0, 0.0 );
    sgMakeRotMat4( DEC, (float)(declination * SGD_RADIANS_TO_DEGREES), axis );

    sgSetVec3( v, 0.0, (float)sol_dist, 0.0 );
    sgMakeTransMat4( T2, v );

    sgMat4 TRANSFORM;
    sgCopyMat4( TRANSFORM, T1 );
    sgPreMultMat4( TRANSFORM, GST );
    sgPreMultMat4( TRANSFORM, RA );
    sgPreMultMat4( TRANSFORM, DEC );
    sgPreMultMat4( TRANSFORM, T2 );

    sgCoord skypos;
    sgSetCoord( &skypos, TRANSFORM );

    transform->setTransform( &skypos );

    return true;
}
Пример #2
0
bool cGrMoon::reposition(sgVec3 p, double angle, double moonrightAscension, double moondeclination, double moon_dist)
{
    sgMat4 T1, T2, GST, RA, DEC;
    sgVec3 axis;
    sgVec3 v;

    sgMakeTransMat4( T1, p );

    sgSetVec3( axis, 0.0, 0.0, -1.0 );
    sgMakeRotMat4( GST, angle, axis );
    sgSetVec3( axis, 0.0, 0.0, 1.0 );
    sgMakeRotMat4( RA, (moonrightAscension * SGD_RADIANS_TO_DEGREES) - 90.0, axis );
    sgSetVec3( axis, 1.0, 0.0, 0.0 );
    sgMakeRotMat4( DEC, moondeclination * SGD_RADIANS_TO_DEGREES, axis );
    sgSetVec3( v, 0.0, moon_dist, 0.0 );
    sgMakeTransMat4( T2, v );

    sgMat4 TRANSFORM;
    sgCopyMat4( TRANSFORM, T1 );
    sgPreMultMat4( TRANSFORM, GST );
    sgPreMultMat4( TRANSFORM, RA );
    sgPreMultMat4( TRANSFORM, DEC );
    sgPreMultMat4( TRANSFORM, T2 );

    sgCoord skypos;
    sgSetCoord( &skypos, TRANSFORM );

    moon_transform->setTransform( &skypos );

    return true;
}
Пример #3
0
bool cGrSkyDome::reposition( sgVec3 p, double lon, double lat, double spin )
{
  sgMat4 T, LON, LAT, SPIN;
  sgVec3 axis;

  // Translate to view position
  sgMakeTransMat4( T, p );

  // Rotate to proper orientation
  sgSetVec3( axis, 0.0, 0.0, 1.0 );
  sgMakeRotMat4( LON, (float)(lon * SGD_RADIANS_TO_DEGREES), axis );

  sgSetVec3( axis, 0.0, 1.0, 0.0 );
  sgMakeRotMat4( LAT, (float)(90.0 - lat * SGD_RADIANS_TO_DEGREES), axis );

  sgSetVec3( axis, 0.0, 0.0, 1.0 );
  sgMakeRotMat4( SPIN, (float)(spin * SGD_RADIANS_TO_DEGREES), axis );

  sgMat4 TRANSFORM;

  sgCopyMat4( TRANSFORM, T );
  sgPreMultMat4( TRANSFORM, LON );
  sgPreMultMat4( TRANSFORM, LAT );
  sgPreMultMat4( TRANSFORM, SPIN );

  sgCoord skypos;
  sgSetCoord( &skypos, TRANSFORM );

  dome_transform->setTransform( &skypos );
  asl = - skypos.xyz[2];

  return true;
}
Пример #4
0
bool cGrStars::reposition( sgVec3 p, double angle )
{
  sgMat4 T1, GST;
  sgVec3 axis;

  sgMakeTransMat4( T1, p );

  sgSetVec3( axis, 0.0, 0.0, -1.0 );
  sgMakeRotMat4( GST, (float)angle, axis );

  sgMat4 TRANSFORM;
  sgCopyMat4( TRANSFORM, T1 );
  sgPreMultMat4( TRANSFORM, GST );

  sgCoord skypos;
  sgSetCoord( &skypos, TRANSFORM );

  stars_transform->setTransform( &skypos );

  return true;
}
Пример #5
0
void grDrawCar(tCarElt *car, tCarElt *curCar, int dispCarFlag, int dispDrvFlag, double curTime, class cGrPerspCamera *curCam)
{
	sgCoord wheelpos;
	int index, i, j;
	static float maxVel[3] = { 20.0, 40.0, 70.0 };
	float lod;

	TRACE_GL("cggrDrawCar: start");

	index = car->index;
	if (car->priv.collision_state.collision_count > 0) {
		tCollisionState* collision_state = &car->priv.collision_state;
		grPropagateDamage (grCarInfo[index].carEntity, collision_state->pos, collision_state->force, 0);
		collision_state->collision_count = 0;
	}
	
	grCarInfo[index].distFromStart=grGetDistToStart(car);
	grCarInfo[index].envAngle=RAD2DEG(car->_yaw);

	if ((car == curCar) && (dispCarFlag != 1)) {
		grCarInfo[index].LODSelector->select(0);
	} else {
		lod = curCam->getLODFactor(car->_pos_X, car->_pos_Y, car->_pos_Z);
		i = 0;
		while (lod < grCarInfo[index].LODThreshold[i] * grLodFactorValue) {
			i++;
		}
		if ((car->_state & RM_CAR_STATE_DNF) && (grCarInfo[index].LODThreshold[i] > 0.0)) {
			i++;
		}
		grCarInfo[index].LODSelector->select(grCarInfo[index].LODSelectMask[i]);
		if (dispDrvFlag) {
			grCarInfo[index].driverSelector->select(1);
		} else {
			grCarInfo[index].driverSelector->select(0);
		}
	}

	sgCopyMat4(grCarInfo[index].carPos, car->_posMat);
	grCarInfo[index].px=car->_pos_X;
	grCarInfo[index].py=car->_pos_Y;

	grCarInfo[index].carTransform->setTransform(grCarInfo[index].carPos);

	if ((car == curCar) && (dispCarFlag != 1)) {
		grDrawShadow(car, 0);
	} else {
		grDrawShadow(car, 1);
	}
	
	grUpdateSkidmarks(car, curTime); 
	grDrawSkidmarks(car);
	grAddSmoke(car, curTime);
	
	if ((car == curCar) && (dispCarFlag != 1)) {
		grUpdateCarlight(car, curCam, 0);
	} else {
		grUpdateCarlight(car, curCam, 1);
	}

	/* Env mapping selection by the position on the track */
	grCarInfo[index].envSelector->selectStep(car->_trkPos.seg->envIndex);

	/* wheels */
	for (i = 0; i < 4; i++) {
		float	*clr;

		sgSetCoord(&wheelpos, car->priv.wheel[i].relPos.x, car->priv.wheel[i].relPos.y, car->priv.wheel[i].relPos.z,
					RAD2DEG(car->priv.wheel[i].relPos.az), RAD2DEG(car->priv.wheel[i].relPos.ax), 0);
		grCarInfo[index].wheelPos[i]->setTransform(&wheelpos);
		sgSetCoord(&wheelpos, 0, 0, 0, 0, 0, RAD2DEG(car->priv.wheel[i].relPos.ay));
		grCarInfo[index].wheelRot[i]->setTransform(&wheelpos);
		for (j = 0; j < 3; j++) {
			if (fabs(car->_wheelSpinVel(i)) < maxVel[j]) 
				break;
		}
		grCarInfo[index].wheelselector[i]->select(1<<j);
		clr = grCarInfo[index].brkColor[i]->get(0);
		clr[0] = 0.1 + car->_brakeTemp(i) * 1.5;
		clr[1] = 0.1 + car->_brakeTemp(i) * 0.3;
		clr[2] = 0.1 - car->_brakeTemp(i) * 0.3;
	}

	/* push the car at the end of the display order */
	CarsAnchorTmp->addKid(grCarInfo[index].carTransform);
	CarsAnchor->removeKid(grCarInfo[index].carTransform);
	CarsAnchor->addKid(grCarInfo[index].carTransform);
	CarsAnchorTmp->removeKid(grCarInfo[index].carTransform);

	TRACE_GL("cggrDrawCar: end");
}
Пример #6
0
/**
 * \brief Tile the terrain
 *
 * This function recursively walks the scene graph and sorts all
 * triangles into a grid of smaller graphs. This reduces the
 * calculation effort: If the position of the plane and therefore
 * the grid below it is known, only a small fraction of all
 * triangles has to be tested.
 *
 * During the recursive walk down the tree, the function tracks
 * all transformations. If a leaf node is encountered, the contained
 * triangles are transformed by the tracked transformations to
 * get the absolute position of each triangle. Then all triangles
 * are sorted into the grid by their absolute position.
 *
 * \param e       Pointer to the currently processed entity
 * \param xform   Reference to the current transformation
 */
void HD_TilingTerrain::tiling_terrain(ssgEntity * e, sgMat4 xform)
{
  // only continue if HOT traversal is enabled for this entity
  if ( e->getTraversalMask() & SSGTRAV_HOT )
  {
    if ( e->isAKindOf(ssgTypeBranch()) )
    {
      ssgBranch *br = (ssgBranch *) e ;
      if ( e -> isA ( ssgTypeTransform() ) )
      {
        sgMat4 xform1;
        ((ssgTransform *)e)->getTransform ( xform1 ) ;
        sgPreMultMat4  ( xform, xform1 ) ;//Pre or Post ???
        /*
        std::cout << "------tranform " << br<< std::endl;
        std::cout << "-------------- " << xform[0][0]<<"  "<< xform[0][1]<<"  "<< xform[0][2]<<"  "<< xform[0][3]<< std::endl;
        std::cout << "-------------- " << xform[1][0]<<"  "<< xform[1][1]<<"  "<< xform[1][2]<<"  "<< xform[1][3]<< std::endl;
        std::cout << "-------------- " << xform[2][0]<<"  "<< xform[2][1]<<"  "<< xform[2][2]<<"  "<< xform[2][3]<< std::endl;
        std::cout << "-------------- " << xform[3][0]<<"  "<< xform[3][1]<<"  "<< xform[3][2]<<"  "<< xform[3][3]<< std::endl;
        */
      }
      //else std::cout << "------branch " << br<< std::endl;
      
      // Bug #16552: "xform" is actually passed by reference and
      // not by value. Therefore we have to store it locally and
      // restore it before recursing to the next child. Else all
      // children receive an xform matrix that was modified by
      // the previous child.
      sgMat4 local_xform;
      sgCopyMat4(local_xform, xform);
      for ( int i = 0 ; i < br -> getNumKids () ; i++ )
      {
        tiling_terrain ( br -> getKid ( i ), xform);
        // restore transformation matrix
        sgCopyMat4(xform, local_xform);
      }
    }
    else if ( e -> isAKindOf ( ssgTypeLeaf() ) )
    {
      //std::cout << "------leaf " << e<< std::endl;
      ssgLeaf  *leaf = (ssgLeaf  *) e ;
      int nt = leaf->getNumTriangles();
      //std::cout << "------n triangles " << nt<< std::endl;
      for ( int i = 0 ; i < nt ; i++ )//pour chaque triangle
      {
        short iv1,iv2,iv3;/*float *v1, *v2, *v3;*/
        sgVec3 v1,v2,v3;
        leaf->getTriangle ( i, &iv1, &iv2,  &iv3 );

        sgCopyVec3 (v1 , leaf->getVertex(iv1));
        sgXformPnt3( v1, xform);
        sgCopyVec3 (v2 , leaf->getVertex(iv2));
        sgXformPnt3( v2, xform);
        sgCopyVec3 (v3 , leaf->getVertex(iv3));
        sgXformPnt3( v3, xform);
        /*
        std::cout << "------triangle " << std::endl;
        std::cout << "-------------- " << v1[0]<<"  "<< v1[1]<<"  "<< v1[2]<<"  "<< std::endl;
        std::cout << "-------------- " << v2[0]<<"  "<< v2[1]<<"  "<< v2[2]<<"  "<< std::endl;
        std::cout << "-------------- " << v3[0]<<"  "<< v3[1]<<"  "<< v3[2]<<"  "<< std::endl;
        */
        //calcule cube englobant
        sgBox box;
        box.empty();
        box.extend(v1);
        box.extend(v2);
        box.extend(v3);
        //std::cout << "Min " << box.min[0]<<", "<<box.min[1]<<", "<<box.min[2]<<" Max"<<box.max[0]<<", "<<box.max[1]<<", "<<box.max[2]<< std::endl;
        //ajoute dans cellules recouvertes
        int save =  1;
        int i1 = (int)(-0.1+box.min[0]/SIZE_CELL_GRID_PLANES) + SIZE_GRID_PLANES/2;
        int i2 = (int)(0.1+box.max[0]/SIZE_CELL_GRID_PLANES) + SIZE_GRID_PLANES/2;
        int j1 = (int)(-0.1+box.min[2]/SIZE_CELL_GRID_PLANES) + SIZE_GRID_PLANES/2;
        int j2 = (int)(0.1+box.max[2]/SIZE_CELL_GRID_PLANES) + SIZE_GRID_PLANES/2;
        if (((i1<0) && (i2<0)) ||((i1>SIZE_GRID_PLANES) && (i2>SIZE_GRID_PLANES)) )
        {
          save = 0;
        }
        if (((j1<0) && (j2<0)) ||((j1>SIZE_GRID_PLANES) && (j2>SIZE_GRID_PLANES)) )
        {
          save = 0;
        }
        if (i1<0)
          i1=0;
        if (i1>SIZE_GRID_PLANES)
          i1 = SIZE_GRID_PLANES;
        if (i2<0)
          i2=0;
        if (i2>SIZE_GRID_PLANES)
          i2 = SIZE_GRID_PLANES;
        if (j1<0)
          j1=0;
        if (j1>SIZE_GRID_PLANES)
          j1 = SIZE_GRID_PLANES;
        if (j2<0)
          j2=0;
        if (j2>SIZE_GRID_PLANES)
          j2 = SIZE_GRID_PLANES;
        //std::cout << "cellules i, j  " << i1 <<", "<<i2<<", "<<j1<<","<<j2<< std::endl;
        if (save)
        {
          for ( int i = i1 ; i <= i2; i++ )
          {
            for ( int j = j1 ; j <= j2; j++ )
            {
              //std::cout << "met dans cellule " << i <<", "<<j<<  std::endl;
              tile_table[i][j]->add(v1);
              tile_table[i][j]->add(v2);
              tile_table[i][j]->add(v3);
            }
          }
        }
      }
    }
  }
}
Пример #7
0
bool cGrCloudLayer::reposition( sgVec3 p, sgVec3 up, double lon, double lat, double alt, double dt )
{
  sgMat4 T1, LON, LAT;
  sgVec3 axis;

  // combine p and asl (meters) to get translation offset
  sgVec3 asl_offset;
  sgCopyVec3( asl_offset, up );
  sgNormalizeVec3( asl_offset );
  if ( alt <= layer_asl ) 
  {
    sgScaleVec3( asl_offset, layer_asl );
  }
  else 
  {
    sgScaleVec3( asl_offset, layer_asl + layer_thickness );
  }
  sgAddVec3( asl_offset, p );

  // Translate to zero elevation
  sgMakeTransMat4( T1, asl_offset );

  // Rotate to proper orientation
  sgSetVec3( axis, 0.0, 0.0, 1.0 );
  sgMakeRotMat4( LON, (float)(lon * SGD_RADIANS_TO_DEGREES), axis );

  sgSetVec3( axis, 0.0, 1.0, 0.0 );
  sgMakeRotMat4( LAT, (float)(90.0 - lat * SGD_RADIANS_TO_DEGREES), axis );

  sgMat4 TRANSFORM;

  sgCopyMat4( TRANSFORM, T1 );
  sgPreMultMat4( TRANSFORM, LON );
  sgPreMultMat4( TRANSFORM, LAT );

  sgCoord layerpos;
  sgSetCoord( &layerpos, TRANSFORM );

  layer_transform->setTransform( &layerpos );

  // now calculate update texture coordinates
  if ( last_lon < -900 ) 
  {
    last_lon = lon;
    last_lat = lat;
  }

  double sp_dist = speed*dt;

  if ( lon != last_lon || lat != last_lat || sp_dist != 0 ) 
  {
    double course = 0.0, dist = 0.0;
    if ( lon != last_lon || lat != last_lat ) 
    {
	sgVec2 start, dest;
	sgSetVec2(start, (float)last_lon, (float)last_lat);
	sgSetVec2(dest, (float)lon, (float)lat);
	calc_gc_course_dist( dest, start, &course, &dist );
    }

    // calculate cloud movement
    double ax = 0.0, ay = 0.0, bx = 0.0, by = 0.0;

    if (dist > 0.0) 
    {
      ax = cos(course) * dist;
      ay = sin(course) * dist;
    }

    if (sp_dist > 0) 
    {
      bx = cos(-direction * SGD_DEGREES_TO_RADIANS) * sp_dist;
      by = sin(-direction * SGD_DEGREES_TO_RADIANS) * sp_dist;
    }

    float xoff = (float)((ax + bx) / (2 * scale));
    float yoff = (float)((ay + by) / (2 * scale));

    const float layer_scale = layer_span / scale;

    float *base, *tc;

    base = tl[0]->get( 0 );
    base[0] += xoff;

    if ( base[0] > -10.0 && base[0] < 10.0 ) 
    {
      base[0] -= (int)base[0];
    }
    else 
    {
      base[0] = 0.0;
	  ulSetError(UL_WARNING, "Warning: base1\n");
    }

    base[1] += yoff;

    if ( base[1] > -10.0 && base[1] < 10.0 ) 
    {
      base[1] -= (int)base[1];
    }
    else 
    {
      base[1] = 0.0;
	  ulSetError(UL_WARNING, "Warning: base2\n");
    }

    for (int i = 0; i < 4; i++) 
    {
      tc = tl[i]->get( 0 );
      sgSetVec2( tc, base[0] + layer_scale * i/4, base[1] );

      for (int j = 0; j < 4; j++) 
      {
        tc = tl[i]->get( j*2+1 );
        sgSetVec2( tc, base[0] + layer_scale * (i+1)/4,
        base[1] + layer_scale * j/4 );

        tc = tl[i]->get( (j+1)*2 );
        sgSetVec2( tc, base[0] + layer_scale * i/4,
        base[1] + layer_scale * (j+1)/4 );
      }

      tc = tl[i]->get( 9 );
      sgSetVec2( tc, base[0] + layer_scale * (i+1)/4,
      base[1] + layer_scale );
    }

    last_lon = lon;
    last_lat = lat;
  }

  return true;
}
Пример #8
0
bool cGrCloudLayer::repositionFlat( sgVec3 p, double dt )
{
  sgMat4 T1;

  // combine p and asl (meters) to get translation offset
  sgVec3 asl_offset;
  if ( p[SG_Z] <= layer_asl ) 
  {
    sgSetVec3( asl_offset, p[SG_X], p[SG_Y], layer_asl );
  }
  else 
  {
    sgSetVec3( asl_offset, p[SG_X], p[SG_Y], layer_asl + layer_thickness );
  }

  // Translate to elevation
  sgMakeTransMat4( T1, asl_offset );

  sgMat4 TRANSFORM;
  sgCopyMat4( TRANSFORM, T1 );

  sgCoord layerpos;
  sgSetCoord( &layerpos, TRANSFORM );

  layer_transform->setTransform( &layerpos );

  // now calculate update texture coordinates
  double sp_dist = speed*dt;

  if ( p[SG_X] != last_x || p[SG_Y] != last_y || sp_dist != 0 ) 
  {
    // calculate cloud movement
    double ax = 0.0, ay = 0.0, bx = 0.0, by = 0.0;

    ax = p[SG_X] - last_x;
    ay = p[SG_Y] - last_y;

    if (sp_dist > 0) 
    {
      bx = cos(-direction * SGD_DEGREES_TO_RADIANS) * sp_dist;
      by = sin(-direction * SGD_DEGREES_TO_RADIANS) * sp_dist;
    }

    float xoff = (float)((ax + bx) / (2 * scale));
    float yoff = (float)((ay + by) / (2 * scale));

    const float layer_scale = layer_span / scale;

    float *base, *tc;

    base = tl[0]->get( 0 );
    base[0] += xoff;

    // the while loops can lead to *long* pauses if base[0] comes
    // with a bogus value.
    // while ( base[0] > 1.0 ) { base[0] -= 1.0; }
    // while ( base[0] < 0.0 ) { base[0] += 1.0; }
    if ( base[0] > -10.0 && base[0] < 10.0 ) 
    {
      base[0] -= (int)base[0];
    }
    else 
    {
      base[0] = 0.0;
	  ulSetError(UL_WARNING, "Warning: base1\n");
    }

    base[1] += yoff;
    // the while loops can lead to *long* pauses if base[0] comes
    // with a bogus value.
    // while ( base[1] > 1.0 ) { base[1] -= 1.0; }
    // while ( base[1] < 0.0 ) { base[1] += 1.0; }
    if ( base[1] > -10.0 && base[1] < 10.0 ) 
    {
      base[1] -= (int)base[1];
    }
    else 
    {
      base[1] = 0.0;
	  ulSetError(UL_WARNING, "Warning: base2\n");
    }

    for (int i = 0; i < 4; i++) 
    {
      tc = tl[i]->get( 0 );
      sgSetVec2( tc, base[0] + layer_scale * i/4, base[1] );

      for (int j = 0; j < 4; j++) 
      {
        tc = tl[i]->get( j*2+1 );
        sgSetVec2( tc, base[0] + layer_scale * (i+1)/4,
        base[1] + layer_scale * j/4 );

        tc = tl[i]->get( (j+1)*2 );
        sgSetVec2( tc, base[0] + layer_scale * i/4,
        base[1] + layer_scale * (j+1)/4 );
      }

      tc = tl[i]->get( 9 );
      sgSetVec2( tc, base[0] + layer_scale * (i+1)/4,
      base[1] + layer_scale );
    }

    last_x = p[SG_X];
    last_y = p[SG_Y];
  }

  return true;
}
Пример #9
0
void calc_coord(void)
{
    sgMat4	m, m2;
    int		i, j;
    tFace	*curFace;
    float	width, height;
    float	scale, offX, offY;
    int		largerRow;
    float	maxWidth;
    int		col;
    ssgBranch	*branch;

    ColWidth = (float*)calloc(NbMaxCols, sizeof(float));

    fprintf(stderr, "After Rotation:\n");
    largerRow = 0;
    maxWidth = 0;
    for (i = 0; i < NbRows; i++) {
	curFace = GF_TAILQ_FIRST(&(Row[i].faces));
	while (curFace) {
	    if (curFace->isPresent) {
		branch = curFace->branch->getParent(0);
		if (branch->isAKindOf(_SSG_TYPE_BASETRANSFORM)) {
		    ((ssgBaseTransform*)branch)->getTransform(m2);
		    curFace->align[0] *= m2[3][0];
		    curFace->align[1] *= m2[3][1];
		    curFace->align[2] *= m2[3][2];
		    fprintf(stderr, "Align face %s : %f %f %f\n", curFace->faceName, curFace->align[0], curFace->align[1], curFace->align[2]);
		}
		sgMakeTransMat4(m, curFace->align);


		sgMakeIdentMat4(m2);
		for (j = 0; j < 3; j++) {
		    m2[j][j] = curFace->lscale[j];
		}
		sgPostMultMat4(m, m2);

		sgMakeRotMat4(m2, curFace->xform.hpr);
		sgPostMultMat4(m, m2);

		sgCopyMat4(curFace->mat, m);

		sgXformPnt3(curFace->sbbmin, curFace->lbbmin, m);
		sgXformPnt3(curFace->sbbmax, curFace->lbbmax, m);

		fprintf(stderr, "      Face %s : %f %f %f  ---  %f %f %f\n",
			curFace->faceName, curFace->sbbmin[0], curFace->sbbmin[1], curFace->sbbmin[2],
			curFace->sbbmax[0], curFace->sbbmax[1], curFace->sbbmax[2]);
		curFace->lwidth = 2.0 * MAX(fabs(curFace->sbbmin[0]), fabs(curFace->sbbmax[0]));
		curFace->lheight = 2.0 * MAX(fabs(curFace->sbbmin[2]), fabs(curFace->sbbmax[2]));
		//curFace->lwidth = fabs(curFace->sbbmin[0] - curFace->sbbmax[0]);
		//curFace->lheight = fabs(curFace->sbbmin[2] - curFace->sbbmax[2]);
		Row[i].lwidth += curFace->lwidth;
		Row[i].lheight = MAX(Row[i].lheight, curFace->lheight);
	    }
	    curFace = GF_TAILQ_NEXT(curFace, link);
	}
	if (Row[i].lwidth > maxWidth) {
	    maxWidth = Row[i].lwidth;
	    largerRow = i;
	}
    }

    height = 0;
    fprintf(stderr, "After Scaling:\n");
    for (i = 0; i < NbRows; i++) {
	height += Row[i].lheight;
    }
    width = maxWidth;
    scale = (float)ImgSize / MAX(width, height);

    curFace = GF_TAILQ_FIRST(&(Row[largerRow].faces));
    i = 0;
    fprintf(stderr, "Columns : ");
    while (curFace) {
	ColWidth[i] = curFace->lwidth * scale;
	fprintf(stderr, "%.2f  ", ColWidth[i]);
	curFace = GF_TAILQ_NEXT(curFace, link);
	i++;
    }
    fprintf(stderr, "\n");

    fprintf(stderr, "Total Width = %.2f   Height = %.2f\n", width, height);
    fprintf(stderr, "Image Width = %.2f   Height = %.2f\n", width*scale, height*scale);

    offY = - (float)ImgSize / 2.0;
    for (i = 0; i < NbRows; i++) {
	curFace = GF_TAILQ_FIRST(&(Row[i].faces));
	offY += Row[i].lheight*scale / 2.0;
	col = 0;
	offX = - (float)ImgSize / 2.0;
	while (curFace) {
	    if (curFace->isPresent) {
		sgCopyMat4(m, curFace->mat);
		curFace->texScale = scale;
		sgMakeIdentMat4(m2);
		for (j = 0; j < 3; j++) {
		    m2[j][j] = scale;
		}
		sgPostMultMat4(m, m2);
		sgXformPnt3(curFace->sbbmin, curFace->lbbmin, m);
		sgXformPnt3(curFace->sbbmax, curFace->lbbmax, m);
		offX += ColWidth[col] / 2.0;
		curFace->offset[0] = offX;
		curFace->offset[2] = offY;
		offX += ColWidth[col] / 2.0;
		sgMakeTransMat4(m2, curFace->offset);
		sgPostMultMat4(m, m2);
		sgCopyMat4(curFace->mat, m);

		curFace->branch->setTransform(m);
	    } else {
		offX += ColWidth[col];
	    }
	    col++;

	    curFace = GF_TAILQ_NEXT(curFace, link);
	}
	offY += Row[i].lheight*scale / 2.0;
    }
}