Reading MXS files


Reading MXS files is useful for importing data from them into a 3D platform. All the functions needed are in maxwell.h header, every "set" function has a "get" function.

This is an example of how to read an MXS file:

#include "maxwell.h"

//------------------------
//   MXS READER EXAMPLE
//------------------------

class MxsReader
{

public:

  enum ReadStatus
  {
    MXS_READED_OK = 0,
    MXS_ERR_NO_FILENAME, // no me has pasado nombre
    MXS_ERR_CANT_OPEN, // no se puede abrir el archivo
    MXS_ERR_BAD_FORMAT, // formato chungo
    MXS_ERR_BAD_GEOMETRY, // no hay geometria
    MXS_ERR_MEM_ERROR, // error memoria
    MXS_ERR_SYNTAX_ERROR, // error de sintaxis
    MXS_ERR_UNKN_WRITE_FORMAT, // tipo desconocido para escribir
    MXS_ERR_UNEXPECTED_FEOF, // fin de archivo antes de tiempo
  };

public:
  MxsReader( void )
  {
  }
  ~MxsReader()
  {
  }

  int readScene( const bool& reload = false, const bool& importFromLibrary = false );

  void readRenderOptions( void );
  void readCameras( void );
  void readSky( void );
  void readHdr( void );
  void readMaterials( void );
  void readGeometry( void );
  void readMatrixAndAttributesOfObject( Cmaxwell::Cobject curObj );
  void readMaterialsOfObject( Cmaxwell::Cobject curObj );
  void readGeometryOfObject( Cmaxwell::Cobject curObj );
  void readInstance( Cmaxwell::Cobject curObj );

private:
  Cmaxwell* pScene;
};

///////////////////////////////////////////////////////////////////////////////////////////////////

byte mxsReadCallback( byte type, const char* pMethod, const char* pError, const void* pValue )
{
  // Callback used by Maxwell to give info during import/export process
  if( type == 0 )
  {
    // There is an error
    String msgError = "Errors in loading Mxs process! \n";
    msgError += String( "%1: %2" ).arg( pMethod ).arg( pError );
    return ( 0 );
  }

	return ( 1 );
}

///////////////////////////////////////////////////////////////////////////////////////////////////

int MxsReader::readScene( const char& mxsPath )
{
	Cmaxwell* pScene = new Cmaxwell( mxsReadCallback );

	byte mxsReadStatus = pScene->readMXS( mxsPath );
	if ( mxsReadStatus != 1 )
  {
    printMsg( "Error reading MXS file!" );
	  return 0;
  }

  dword nObjects_;
  dword nMaterials_;
  dword nTriangleGroups_;
  dword nCameras_;

  pScene->getNumObjects( nObjects_ );
  pScene->getNumMaterials( nMaterials_ );
  pScene->getNumClusters( nTriangleGroups_ );
  pScene->getNumCameras( nCameras_ );

  // Read all the scene
  readRenderOptions();
  readCameras();
  readSky();
  readHdr();
  readMaterials();
  readGeometry();
  readGroups();
  readTriangleGroups();

  pScene->freeScene();

  delete ( pScene );
  pScene = NULL;

  return MXS_READED_OK;
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void MxsReader::readRenderOptions( void )
{
  dword maxTime, numThreads;
  float samplingLevel;
  real monitorGamma, burn, advancedMonitorGamma, advancedBurn;
	byte doMultilight, enableHD;
	byte disableBitmaps = 0;
  byte doDirectLayer, doIndirectLayer, doDRFL, doDRFR, doIRFL, doIRFR;

  byte  outputBitDepthMode;
  const char* imagePath = pScene->getPath( "RENDER", outputBitDepthMode );

  char mxiChar[512];
  pScene->getRenderParameter ( "MXI FULLNAME", 0, &mxiChar );


  // Color space
  dword colorSpace = 0;
  pScene->getColorSpace( colorSpace );
  renderOptns->colorSpaceCombo->setCurrentIndex( colorSpace );

  pScene->getRenderParameter( "STOP TIME", sizeof ( dword ), &maxTime );
  pScene->getRenderParameter( "SAMPLING LEVEL", sizeof ( float ), &samplingLevel );
  pScene->getRenderParameter( "NUM THREADS", sizeof ( dword ), &numThreads );
  pScene->getRenderParameter ("USE MULTILIGHT",sizeof(byte), &doMultilight);
  pScene->getRenderParameter ("USE HARDDISK",sizeof(byte), &enableHD);

	pScene->getRenderParameter ("DO DIRECT LAYER",sizeof(byte), &doDirectLayer);
  pScene->getRenderParameter ("DO INDIRECT LAYER",sizeof(byte), &doIndirectLayer);
  pScene->getRenderParameter ("DO DIRECT REFLECTION CAUSTIC LAYER",sizeof(byte), &doDRFL);
  pScene->getRenderParameter ("DO INDIRECT REFLECTION CAUSTIC LAYER",sizeof(byte), &doIRFL);
  pScene->getRenderParameter ("DO DIRECT REFRACTION CAUSTIC LAYER",sizeof(byte), &doDRFR);
  pScene->getRenderParameter ("DO INDIRECT REFRACTION CAUSTIC LAYER",sizeof(byte), &doIRFR);


  byte doRenderChannel, doAlphaChannel, doAlphaOpaqueChannel, doIdObjectChannel, doIdMaterialChannel;
  byte doShadowsChannel, doVelocityChannel, doZbufferChannel, doDiffussePass, doReflectionPass;
  real zRange[2];

  pScene->getRenderParameter ("DO RENDER CHANNEL",sizeof(byte), &doRenderChannel);
  pScene->getRenderParameter ("DO ALPHA CHANNEL",sizeof(byte), &doAlphaChannel);
  pScene->getRenderParameter ("OPAQUE ALPHA",sizeof(byte), &doAlphaOpaqueChannel);
  pScene->getRenderParameter ("DO IDOBJECT CHANNEL",sizeof(byte), &doIdObjectChannel);
  pScene->getRenderParameter ("DO IDMATERIAL CHANNEL",sizeof(byte), &doIdMaterialChannel);
  pScene->getRenderParameter ("DO SHADOW PASS CHANNEL",sizeof(byte), &doShadowsChannel);
  pScene->getRenderParameter ("DO VELOCITY CHANNEL",sizeof(byte), &doVelocityChannel);
  pScene->getRenderParameter ("DO ZBUFFER CHANNEL",sizeof(byte), &doZbufferChannel);
  pScene->getRenderParameter ("ZBUFFER RANGE", 2 * sizeof( real ), zRange);
  pScene->getRenderParameter( "DO DIFFUSE LAYER",sizeof(byte), &doDiffussePass );
  pScene->getRenderParameter( "DO REFLECTION LAYER",sizeof(byte), &doReflectionPass );


  pScene->getToneMapping( monitorGamma, burn );

  // Simulens
  bool diffEnabled;
  real diffIntensity, diffFreq;
  const char* diffAperture = NULL;
  const char* diffObstacle = NULL;
  pScene->getDiffraction( diffEnabled, diffIntensity, diffFreq, &diffAperture, &diffObstacle );
  if( diffEnabled )
    renderOptns->diffractionCheck->setChecked( true );
  if( diffAperture != NULL )
    renderOptns->aperturePath->setPath( diffAperture );
  if( diffObstacle != NULL )
    renderOptns->obstaclePath->setPath( diffObstacle );


  byte doScatt, doVignett;
  real scattering, vignetting;

  pScene->getRenderParameter ( "DO SCATTERING_LENS", sizeof( byte ), &doScatt );
  pScene->getRenderParameter ( "SCATTERING_LENS", sizeof( real ), &scattering );

  pScene->getRenderParameter ( "DO DEVIGNETTING", sizeof( byte ), &doVignett );
  pScene->getRenderParameter ( "DEVIGNETTING", sizeof( real ), &vignetting );
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void MxsReader::readCameras( void )
{
  Cmaxwell::Ccamera::Citerator itcam;
  Cmaxwell::Ccamera curCamera = itcam.first( pScene );

	while ( !curCamera.isNull() )
	{
    Cpoint maxorigin, maxto;
    Cvector maxup;
    real maxfl, maxft, maxshut, maxfilw, maxfilh, maxiso, maxangle, maxpixelaspect, zClipMin, zClipMax, shiftLensX, shiftLensY;
    const char* maxdiaph;
    dword nSteps, maxblades, maxfps, maxxres, maxyres;
    bool zClipEnabled;

    QString candidateCamName = curCamera.getValues( nSteps, maxshut, maxfilw, maxfilh, maxiso, &maxdiaph, maxangle, maxblades, maxfps, maxxres, maxyres, maxpixelaspect );
    curCamera.getStep( 0, maxorigin, maxto, maxup, maxfl, maxft );

    real focalDistance( maxorigin.distance( maxto ) );
    real correctedFocalLength = 1.0 / ( 1.0 / maxfl - 1.0 / focalDistance );
    curCamera.getCutPlanes( zClipMin, zClipMax, zClipEnabled );
    curCamera.getShiftLens( shiftLensX, shiftLensY );

    bool isCamHidden = false;
    curCamera.isHide( isCamHidden );

    // Set the active camera
    if ( pScene->getActiveCamera().getPointer() == curCamera.getPointer() )
    {
      // This camera is the active one
    }
		curCamera = itcam.next();
  }
} // End readCameras

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void MxsReader::readSky( void )
{
  const char* activeSky = pScene->getActiveSky();

	Crgb skyColor;
  real radianceScalar, longitude, latitude, timeOfDay, sunRot, sunTemperature, sunPowerScaleFactor, planetReflectance;
  real ozone, water, angstromTurbidity, wavelengthTurbidity, aerosolAlbedo, asimmetryFactor;
  int sm;
  dword dayOfYear, sunPositionType;
  byte useSunInConstant, sunActive;

  // Now the sky type is stored in the custom data
  if ( activeSky != NULL )
  {
    // SKY DOME
    byte isSkyDomeOk = 0;
    isSkyDomeOk = pScene->getSkyConstant( skyColor, radianceScalar, useSunInConstant );
    if( !isSkyDomeOk )
    {
      printMsg( "Error reading sky dome" );
    }

    // PHYSICHAL SKY
    byte isPhysicalSkyOk = 0;
    isPhysicalSkyOk = pScene->getPhysicalSkyGeometry( longitude, latitude, sm, dayOfYear, timeOfDay, sunRot, sunPositionType );
    if( isPhysicalSkyOk )
    {
      isPhysicalSkyOk = pScene->getPhysicalSkySun( sunActive, sunTemperature, sunPowerScaleFactor, planetReflectance );
      isPhysicalSkyOk = pScene->getPhysicalSkyAtmosphere( ozone, water, angstromTurbidity, wavelengthTurbidity, aerosolAlbedo, asimmetryFactor );
    }

    if( isPhysicalSkyOk )
    {
      //...
    }
    else
    {
      printMsg( "Error reading physical sky" );
    }

    if ( strncmp( activeSky, "CONSTANT", 8 ) == 0 )
    {
      // Sky constant is active
    }
    else if ( strncmp( activeSky, "PHYSICAL", 8 ) == 0 )
    {
      // Physical sky is active
    }
  }
  else //-->the sky is null
  {
  }
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void MxsReader::readHdr( void )
{
  bool isEnv = false;
  pScene->isEnvironmentEnabled( isEnv );

  char* bkTexture = NULL;
  char* rflTexture = NULL;
  char* rfrTexture = NULL;
  char* illumTexture = NULL;
  QString bkTextureFinal, rflTextureFinal, rfrTextureFinal, illumTextureFinal;

  bool useActiveSky = false;
  bool sphMapping = true;
  real intensity, uTile, vTile, uOffset, vOffset;

  pScene->getEnvironmentLayer( "background", bkTexture, useActiveSky, sphMapping, intensity, uTile, vTile, uOffset, vOffset );
  pScene->getEnvironmentLayer( "reflection", rflTexture, useActiveSky, sphMapping, intensity, uTile, vTile, uOffset, vOffset );
  pScene->getEnvironmentLayer( "refraction", rfrTexture, useActiveSky, sphMapping, intensity, uTile, vTile, uOffset, vOffset );
  pScene->getEnvironmentLayer( "illumination", illumTexture, useActiveSky, sphMapping, intensity, uTile, vTile, uOffset, vOffset );
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void MxsReader::readMaterials( void )
{
  Cmaxwell::Cmaterial::Citerator itm;
  Cmaxwell::Cmaterial curMat = itm.first( pScene );

  while ( !curMat.isNull() )
  {
    QString matName = curMat.getName();
    //... read material parameters....
	  curMat = itm.next();
  } // End of traversing materials
} // End of Read materials

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void MxsReader::readGeometry( void )
{
  Cmaxwell::Cobject::Citerator it;
	Cmaxwell::Cobject curObj = it.first( pScene );

  while ( !curObj.isNull() )
	{
		byte bOk;
		curObj.isMesh( bOk );

    // Look for instances
		if ( bOk == 0 )
		{
      curObj.isInstance( bOk );
      if ( bOk == 1 )
      {
        readInstance( curObj );
      }
			curObj = it.next ();
			continue;
		}

    char* objName = NULL;
    curObj.getName( &objName );

    // Look for its parent
    Cmaxwell::Cobject parent;
    curObj.getParent( parent );
    if( !parent.isNull() )
    {
      char* parentNameAux = NULL;
      parent.getName( &parentNameAux );
    }

    // Check if this is a null object
    dword nTriangulos = 0;
    dword nVertices = 0;
    dword nNormales = 0;
    dword nPositions = 0;

    isOk = curObj.getNumTriangles ( nTriangulos );
    isOk = curObj.getNumVertexes ( nVertices );
    isOk = curObj.getNumNormals ( nNormales );

    if( nTriangulos == 0 || nVertices == 0 )
    {
      // we have a null object or a Realflow renderkit object
      Cmaxwell::Cmaterial nullMat;
      curObj.getMaterial( nullMat );

      bool isRfrk = false;
      pScene->isRFRK( curObj, isRfrk );
      if( isRfrk )
      {
        // Call pScene->getRFRKParameters( ... );
      }

      readMatrixAndAttributesOfObject( curObj );
      curObj = it.next();
      continue;
    }

    // Read main object data
    readGeometryOfObject( curObj );
    readMatrixAndAttributesOfObject( curObj );
    readMaterialsOfObject( curObj );

    curObj = it.next();
	} // End traverse objects
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void MxsReader::readMatrixAndAttributesOfObject( Cmaxwell::Cobject curObj )
{
  // OBJECT TRANSFORMATIONS

  Cbase base, pivot;
  curObj.getBaseAndPivot( base, pivot );

  bool refreshTransformValues = false;

  bool hasPosRotSca = false;
  byte isOk = curObj.isPosRotScaleInitialized( hasPosRotSca );

  if( hasPosRotSca && isOk ) //We have true pos/rot/sca values ---> Cool
  {
    Cvector pos, rot, sca, pivPos, pivRot, shear;
    curObj.getPosition( pos );
    curObj.getRotation( rot );
    curObj.getScale( sca );
    curObj.getPivotPosition( pivPos );
    curObj.getPivotRotation( pivRot );
    curObj.getShear( shear );
  }


  // object attributtes
  bool attrib;
  curObj.getHide( attrib );

  curObj.getHideToCamera( attrib );
  curObj.getHideToReflectionsRefractions( attrib );
  curObj.getHideToGI( attrib );
  curObj.isExcludedOfCutPlanes( attrib );
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void MxsReader::readMaterialsOfObject( Cmaxwell::Cobject curObj )
{
    // ASSING MATERIALS TO OBJECT
	  Cmaxwell::Cmaterial objMat;
	  curObj.getMaterial( objMat );

    if ( !objMat.isNull() )
    {
    }
    else // objMat isNull()
    {
      // This object is multimaterial or has not material applied to some triangles
    }
} // End of readMaterialsOfObject

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void MxsReader::readGeometryOfObject( Cmaxwell::Cobject curObj )
{
  dword nTriangulos = 0;
  dword nVertices = 0;
  dword nNormales = 0;
  dword nPositions = 0;

  curObj.getNumTriangles ( nTriangulos );
  curObj.getNumVertexes ( nVertices );
  curObj.getNumNormals ( nNormales );

  curObj.getNumPositionsPerVertex( nPositions ); // Motion blur

  Cvector vecTemp;
  if ( nPositions <= 1 )
  {
    // No motion blur
    for ( NL_UINT32 i = 0; i < nNormales; i++ )
    {
      curObj.getNormal( i, 0, vecTemp );
    }
    for ( NL_UINT32 i = 0; i < nVertices; i++ )
    {
      curObj.getVertex( i, 0, vecTemp );
    }
  }
  else // We have motion blur!
  {
    for ( NL_UINT32 i = 0; i < nNormales; i++ )
    {
      curObj.getNormal( i, 0, vecTemp );
      curObj.getNormal( i, 1, vecTemp );
    }
	  for ( NL_UINT32 i = 0; i < nVertices; i++ )
	  {
      curObj.getVertex( i, 0 /*MB substep*/, vecTemp );
      curObj.getVertex( i, 1, vecTemp );
	  }
  }

  for ( NL_UINT32 i = 0; i < nTriangulos; i++ )
  {
    dword iA, iB, iC, iG, nA, nB, nC;
    curObj.getTriangle( i, iA, iB, iC, nA, nB, nC );
  }


  // Texture coordinates
  float* pChannelsUVW = NULL;
  dword nChannelsUVW = 0;
  curObj.getNumChannelsUVW( nChannelsUVW );

  if ( nChannelsUVW > 0 )
  {
    for ( NL_UINT32 iChannel = 0; iChannel < nChannelsUVW; iChannel++ )
    {
	    float u1, v1, w1, u2, v2, w2, u3, v3, w3;
	    for ( NL_UINT32 it = 0; it < nTriangulos; it++ )
	    {
        curObj.getTriangleUVW( it, iChannel, u1, v1, w1, u2, v2, w2, u3, v3, w3 );
	    }
    }
  }
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void MxsReader::readInstance( Cmaxwell::Cobject curObj )
{
  // Exactly as in objects
  char* objName = NULL;
  curObj.getName( &objName ); // get instance name
  Cmaxwell::Cobject curObjInstanced = curObj.getInstanced();
  char* objNameInstanced = NULL;
  curObjInstanced.getName( &objNameInstanced ); //parent obj name

  Cbase instBase;
  curObj.getBase( instBase );
  Cbase instPivot;
  curObj.getPivot( instPivot );

  // Material
  Cmaxwell::Cmaterial instMat;
  curObj.getMaterial( instMat );

  // Instance attributtes (the same as in objects)
  bool tempIsHide, tempIsHideToCamera, tempIsHideToRefAndRefr, tempIsHideToIG, tempIsExcludedFromZplanes;
  curObj.getHide( tempIsHide );
  curObj.getHideToCamera( tempIsHideToCamera );
  curObj.getHideToReflectionsRefractions( tempIsHideToRefAndRefr );
  curObj.getHideToGI( tempIsHideToIG );
  curObj.isExcludedOfCutPlanes( tempIsExcludedFromZplanes );
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////