VR Group Project 1

Ashley Triplett

Celambarasan Ramasamy

Zachariah Inks

 

Ennis - Brown House

 

We chose the Ennis-Brown house for our VR project because of its unique geometric shapes and historical media significance.

We created the interior space of the house directly from the blueprints of Frank Lloyd Wright.

The Ennis-Brown house was designed by Frank Lloyd Wright and built near Los Angeles CA in 1924.

It is built from custom concrete blocks in a style similar to Mayan temples.

Most notably it has been used for such movies as:

House on Haunted Hill

Day of the Locust

Blade Runner

 

 

Ennis-Brown House Floor plans and Elevations

 

Custom block use in the house

 

Interior shots of the house

 

Screen shots from the VR environment.

 

Additionally Celu created a custom Maya exporter and parser rather than using a .obj format

 

/* Maya Exporter Plugin for Custom File format .celu */

/* Date 10/25/07 */

 

#include <maya/MIOStream.h>
#include <maya/MSimple.h>
#include <maya/MFileIO.h>
#include <maya/MFileObject.h>
#include <maya/MObject.h>
#include <maya/MStatus.h>
#include <maya/MString.h>
#include <maya/MPxFileTranslator.h>
#include <maya/MFnMesh.h>
#include <maya/MItDag.h>
#include <maya/MGlobal.h>
#include <maya/MFloatPointArray.h>
#include <maya/MPointArray.h>
#include <maya/MDagPathArray.h>
#include <maya/MItMeshPolygon.h>
#include <maya/MFloatVectorArray.h>
#include <maya/MStringArray.h>
#include <maya/MFnPlugin.h>
#include <maya/MSelectionList.h>
#include <maya/MItSelectionList.h>
#include <vector>
#include <fstream>

// The plugin must export two functions namley initialize and uninitialize plugin

# define MLL_EXPORT __declspec(dllexport)

 

void ProcessMesh(MFnMesh& tMeshFunctionSet,MObject& tMeshMObject,std::ofstream& tOutputFileStream,unsigned int& tInstanceCountForCurrentMesh, MStatus * tErrorObject = 0)
{

char tTempString[100];

// Output the name of the Mesh

tOutputFileStream << "m," << tMeshFunctionSet.name().asChar() << ",";


// Get all the Dag Paths associated with this mesh node(and hence the number of mesh instances)

tInstanceCountForCurrentMesh=tMeshFunctionSet.parentCount();

// If instance count is zero, then return failure and quit

if(tInstanceCountForCurrentMesh==0)
{

*tErrorObject=MS::kFailure;

MGlobal::displayError("Instance Count for current mesh is zero,reading scene data failed");

}

// If instance count is greater than one get all the dag paths for the current mesh

MDagPathArray tDagPathsForTheCurrentMesh;

tMeshFunctionSet.getAllPaths(tDagPathsForTheCurrentMesh);

// For each DAG path(instance) get the vertex positions in world space

for(unsigned int i=0; i < tInstanceCountForCurrentMesh; i++)
{

// Write the instance count

sprintf_s(tTempString, "instance,%d,",(i+1));
tOutputFileStream << tTempString;

MFloatPointArray tMeshVertexPointsArray;
MFloatVectorArray tNormalArray;
MStringArray tUVSetsNameArray;

// Attach the MFnMesh function set to the DAGPath objects

MFnMesh tMeshCurrentDAGFunctionSet(tDagPathsForTheCurrentMesh[i],tErrorObject);

// Standard error checking

if(*tErrorObject != MS::kSuccess)
{
MGlobal::displayError("Error Assigning Dag Path to MeshFunctionSet in current mesh");
return;
}

 

// Get the vertex positions from the mesh

tMeshCurrentDAGFunctionSet.getPoints(tMeshVertexPointsArray,MSpace::kWorld);
tMeshCurrentDAGFunctionSet.getNormals(tNormalArray,MSpace::kWorld);

unsigned int tVertexCount=tMeshVertexPointsArray.length();
unsigned int tNormalCount=tNormalArray.length();

 

// Output the number of vertices

//cout << " Total Vertex Count " << tVertexCount << endl << endl;

//write the number of vertices to the file

sprintf_s(tTempString, "vertices,%d,",tVertexCount);
tOutputFileStream << tTempString;

// Itreate throught the array and print all the points

for(unsigned int i=0;i<tVertexCount;i++)
{

//cout << tMeshVertexPointsArray[i].x << " " << tMeshVertexPointsArray[i].y << " " << tMeshVertexPointsArray[i].z << endl;

sprintf_s(tTempString, "v,%e,%e,%e,",tMeshVertexPointsArray[i].x,tMeshVertexPointsArray[i].y,tMeshVertexPointsArray[i].z);
tOutputFileStream << tTempString;

}

//write the number of vertices to the file

sprintf_s(tTempString, "normals,%d,",tNormalCount);
tOutputFileStream << tTempString;


// Output the worldspace normals

for(unsigned int i=0;i < tNormalCount;i++)
{

//cout << tNormalArray[i].x << " " << tNormalArray[i].y << " " << tNormalArray[i].z << endl;

sprintf_s(tTempString, "n,%e,%e,%e,",tNormalArray[i].x,tNormalArray[i].y,tNormalArray[i].z);
tOutputFileStream << tTempString;

}

// Get the names of the UV sets attached to this mesh object

tMeshFunctionSet.getUVSetNames(tUVSetsNameArray);

unsigned int tNumberOfUVSets=tUVSetsNameArray.length();

// A flag to indicate later whether index into the UV array needs to be added in the face data

bool tDoesTextureCoordinateExist=true;

// Check for the case where the mesh has no UV sets attached to it

if((!tNumberOfUVSets) || (!tMeshFunctionSet.numUVs(tUVSetsNameArray[0])))
{
//cout<< "No Texture Data Available";

// No UV set is attached to this object, indicate UV set count as zero

tOutputFileStream << "uvsetcount,0,";

// Dont add index into the UV array for the polygon data

tDoesTextureCoordinateExist=false;

}
else
{

// If texture co-ordinates are available then write them to file

sprintf_s(tTempString, "uvsetcount,%d,",tNumberOfUVSets);
tOutputFileStream << tTempString;

//cout << " Number Of Texture Co-ordinate Sets : " << tNumberOfUVSets << endl;

// For each UV set display the texture co-ordinate for the individual vertices

for(unsigned int i=0;i<tNumberOfUVSets;i++)
{

// write the name of the UVSet to the file

tOutputFileStream << tUVSetsNameArray[i].asChar() << ",";

//cout << tUVSetsNameArray[i].asChar() << endl;

MFloatArray tUCoordinates,tVCoordinates;

tMeshFunctionSet.getUVs(tUCoordinates,tVCoordinates,&tUVSetsNameArray[i]);

// Get the number of texture co-ordinate values in this given set

unsigned int tTextureCoordinateValuesCount=tMeshFunctionSet.numUVs(tUVSetsNameArray[i]);

// Write the number of texture co-ordinate values in this given set to the file

sprintf_s(tTempString, "%d,",tTextureCoordinateValuesCount);
tOutputFileStream << tTempString;

// Loop through and write all the UV coordinates in the current set

for(unsigned int i=0;i<tTextureCoordinateValuesCount;i++)
{

sprintf_s(tTempString, "%e,%e,",tUCoordinates[i],tVCoordinates[i]);
tOutputFileStream << tTempString;

//cout << tUCoordinates[i] << " " << tVCoordinates[i] << endl;
}

}
}

// Get the index for each vertex

// Add a polygon itreator to the mesh object

MItMeshPolygon tCurrentMeshPolygonItreator(tMeshMObject,tErrorObject);

// Standard error checking

if(*tErrorObject != MS::kSuccess)
{
MGlobal::displayError("Error Creating Polygon Itreator for current mesh object");
return;
}

unsigned int tFaceCount=0;

// Loop through and count the number of polygons in the mesh

while(!tCurrentMeshPolygonItreator.isDone())
{
tFaceCount++;
tCurrentMeshPolygonItreator.next();
}

// Reset the face itreator to the first polygon

tCurrentMeshPolygonItreator.reset();

// Write the face count for the current mesh

sprintf_s(tTempString, "facecount,%d,",tFaceCount);
tOutputFileStream << tTempString;

// Loop until all the polygons are done

while(!tCurrentMeshPolygonItreator.isDone())
{

unsigned int tVertexCountForTheCurrentPolygon=tCurrentMeshPolygonItreator.polygonVertexCount();

// Write out the vertex count for the current polygon

sprintf_s(tTempString, "f,%d,",tVertexCountForTheCurrentPolygon);
tOutputFileStream << tTempString;

// Write out vi to indicate the start of vertex index count

tOutputFileStream << "vi,";

// Write out the index into the vertex array

for(unsigned int i=0;i<tVertexCountForTheCurrentPolygon;i++)
{

sprintf_s(tTempString, "%d,",tCurrentMeshPolygonItreator.vertexIndex(i));
tOutputFileStream << tTempString;

//cout << tCurrentMeshPolygonItreator.vertexIndex(i) << " ";
}

// Write out ni to indicate the start of vertex index count

tOutputFileStream << "ni,";

// Write out the index into the normal array

for(unsigned int i=0;i<tVertexCountForTheCurrentPolygon;i++)
{

sprintf_s(tTempString, "%d,",tCurrentMeshPolygonItreator.normalIndex(i));
tOutputFileStream << tTempString;

//cout << tCurrentMeshPolygonItreator.vertexIndex(i) << " ";
}

// Write out the index into the UV array for each vertex of this face, only if texturing info exists for this polygonal face

if(tDoesTextureCoordinateExist)
{

// For each UV set, write out the index into the corresponding UV array for each vertex of the polygonal face

for(unsigned int j=0;j<tNumberOfUVSets;j++)
{

// write out the count that identifies a UV set

sprintf_s(tTempString, "uvi,%d,",j+1);
tOutputFileStream << tTempString;

int tIndexIntoUVArray;

// Write out the index into the UV array

for(unsigned int i=0;i<tVertexCountForTheCurrentPolygon;i++)
{

// Check for error while retreiving UV index

if(tCurrentMeshPolygonItreator.getUVIndex(i,tIndexIntoUVArray,&tUVSetsNameArray[j]) != MS::kSuccess)
{
MGlobal::displayError("Error Retreiving UV index for Polygonal Face");
return;
}

sprintf_s(tTempString, "%d,",tIndexIntoUVArray);
tOutputFileStream << tTempString;

//cout << tCurrentMeshPolygonItreator.vertexIndex(i) << " ";
}
}
}

 

//cout << endl;

tCurrentMeshPolygonItreator.next();
}


}

// This mesh has been read sucessfully

*tErrorObject = MS::kSuccess;

}

 

 

 

//
MStatus ExportCommand( MString tFileName)
{

// Keeps track of the number of mesh objects and their instances

std::vector<int> tMeshAndInstanceCount;

// Take the input argument and create a .celu Data File

MString tDataFileName=tFileName+"_data.celu";
MString tHeaderFileName=tFileName+"_header.celu";

// Create a file output stream for outputting the scene data

std::ofstream tOutputDataFileStream (tDataFileName.asChar(),std::ios::out | std::ios::binary);

// Create another file output stream for outputting the scene data header file

std::ofstream tOutputHeaderFileStream (tHeaderFileName.asChar(),std::ios::out | std::ios::binary);

MStatus tErrorObject;


// Create an Dag Node Itreator and itreate through all the meshes in the scene

MItDag tItreator(MItDag::kDepthFirst,MFn::kMesh,&tErrorObject);

 

// Standard error checking

if(tErrorObject != MS::kSuccess)
{
MGlobal::displayError("Error Creating Dag Itreator");
tOutputDataFileStream.close();
tOutputHeaderFileStream.close();
return tErrorObject;
}

// Loop through all the meshes that are not intermediate objects

while(!tItreator.isDone())
{

// Attach the function set to the object

MFnMesh tMeshFunctionSet(tItreator.item(),&tErrorObject);

// Standard error checking

if(tErrorObject != MS::kSuccess)
{
MGlobal::displayError("Error attaching Mesh function set to DAG node");
tOutputDataFileStream.close();
tOutputHeaderFileStream.close();
return tErrorObject;
}

// We are only interested in non history Items

if(!tMeshFunctionSet.isIntermediateObject())
{

unsigned int tInstanceCountForCurrentMesh=1;

// Process this non history mesh Object

ProcessMesh(tMeshFunctionSet,tItreator.item(),tOutputDataFileStream,tInstanceCountForCurrentMesh,&tErrorObject);

// Standard Error Checking

if(tErrorObject != MS::kSuccess)
{
MGlobal::displayError("Error writing Mesh Data To File");
tOutputDataFileStream.close();
tOutputHeaderFileStream.close();
return tErrorObject;
}

// Update the instance count for the current mesh

tMeshAndInstanceCount.push_back(tInstanceCountForCurrentMesh);

}

tItreator.next();
}

char tTempString[100];

// Write out the scene data header file

sprintf_s(tTempString, "mesh,%d,",(int)tMeshAndInstanceCount.size());
tOutputHeaderFileStream << tTempString;

// Write out the number of instances of each mesh

for(unsigned int i=0;i < tMeshAndInstanceCount.size();i++)
{
sprintf_s(tTempString, "%d,",tMeshAndInstanceCount[i]);
tOutputHeaderFileStream << tTempString;
}

// Close the file after writing

tOutputDataFileStream.close();
tOutputHeaderFileStream.close();

 

return MS::kSuccess;
}

 

// CeluMayaExporter is the maya class that contains the functionality of the file exporter...it should derive from the maya's MPxFileTranslator class

class CeluMayaExporter : public MPxFileTranslator
{
public:

// Default Constructor

CeluMayaExporter():MPxFileTranslator()
{}

// Destructor

~CeluMayaExporter()
{}

// Writer method that must be overloaded to implement the export function

MStatus writer(const MFileObject &file,const MString& tOptions,FileAccessMode mode)
{

MStatus tErrorObject;

// Export selection mode not supported yet

if(mode == kExportActiveAccessMode)
{

cout << "Export selection not implemented yet..exporting the entire scene" << endl;

}

// Get the name for the new file to be created and create the file

tErrorObject=ExportCommand(file.name());

if(tErrorObject!=MS::kSuccess)
{
cout << "Error Exporting Scene";
}

 

return tErrorObject;
}


MStatus reader( const MFileObject& file,const MString& optionsString,FileAccessMode mode)
{
MStatus tDummyObject;

return tDummyObject;
}

// Identifies if the writer function has been exported

bool haveWriteMethod() const
{
return true;
}

// Returns the default file format extension for this translator

MString defaultExtension() const
{
return "celu";
}

// Used by maya to create a new instance of our exporter

static void *creator()
{
return new CeluMayaExporter();
}

};

 

 

 

 

// The initialize function is called initially when the plugin is loaded,the registration of the plugin takes place here

MLL_EXPORT MStatus initializePlugin(MObject tObject)
{

MStatus tErrorObject;

// Attach a plugin funtion set to the received maya object

MFnPlugin tPlugin(tObject,"Celu","1.0","Any",&tErrorObject);

// Standard error checking

if(tErrorObject != MS::kSuccess)
{
printf(" Error attaching MFnPlugin function to the MObject in the plugin initialization function ");

return tErrorObject;
}

tErrorObject=tPlugin.registerFileTranslator("Celu Exporter For Maya","none",CeluMayaExporter::creator);

// Standard error checking

if(tErrorObject != MS::kSuccess)
{
printf(" Error registering the file translator plugin in the initialization method");

return tErrorObject;
}

return tErrorObject;
}

// The second function is the uninitialize function that is called when the plugin is unloaded

MLL_EXPORT MStatus uninitializePlugin(MObject tObject)
{

MStatus tErrorObject;

// Attach a plugin funtion set to the received maya object

MFnPlugin tPlugin(tObject,"Celu","1.0","Any",&tErrorObject);

// Standard error checking

if(tErrorObject != MS::kSuccess)
{
printf(" Error attaching MFnPlugin function to the MObject in the plugin uninitialization function ");

return tErrorObject;
}

// Deregister the file translator plugin with maya

tErrorObject=tPlugin.deregisterFileTranslator("Celu Exporter For Maya");

// Standard error checking

if(tErrorObject != MS::kSuccess)
{
printf(" Error deregistering the file translator plugin in the uninitialization method");

return tErrorObject;
}

return tErrorObject;

}