⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 meshshapes.cpp

📁 file code.zip are used to implement ray tracing technology.
💻 CPP
字号:
#include "MeshShapes.h"
#include <float.h>

Mesh::Mesh()
{
    numVerts = numFaces = numNorms = 0;
    pt = NULL; norm  =  NULL; face = NULL;
    lastVertUsed = lastNormUsed = lastFaceUsed = -1;
    meshFileName = "None";
}

Mesh::Mesh(string fname)
{ // read this file to build mesh
    numVerts = numFaces = numNorms = 0;
    pt = NULL; norm  =  NULL; face = NULL;
    lastVertUsed = lastNormUsed = lastFaceUsed = -1;
    meshFileName = "None";

    readMesh(fname);
/*
	string OBJName = fname.substr(0, fname.find(".")).append(".obj");
	outputOBJ(OBJName); */
}

Mesh::~Mesh() { freeMesh(); }

void Mesh::freeMesh()
{ // free up memory used by this mesh.
    delete [] pt; // release whole vertex list
    delete [] norm;
    for(size_t f = 0; f < numFaces; f++) delete[] face[f].vert; // delete the vert[] array of this face
    delete [] face;
}

void Mesh::makeExtentPoints(PointCluster& clust) {}
bool Mesh::hit(Ray &r, Intersection &inter)
{
	Ray genRay;
    xfrmRay(genRay, r);

	inter.numHits=0;
    float t, bestHitTime = -1;
    VertexID *v, *bestV;

    for(size_t p=0; p < numFaces; p++)
    {
        if(face[p].nVerts != 3) return false;
        v = face[p].vert;

        float a, b, c, d, e, f, g, h, i, j, k, l;
        float M, beta, gama;

        a = pt[v[0].vertIndex].x - pt[v[1].vertIndex].x;
        b = pt[v[0].vertIndex].y - pt[v[1].vertIndex].y;
        c = pt[v[0].vertIndex].z - pt[v[1].vertIndex].z;
        d = pt[v[0].vertIndex].x - pt[v[2].vertIndex].x;
        e = pt[v[0].vertIndex].y - pt[v[2].vertIndex].y;
        f = pt[v[0].vertIndex].z - pt[v[2].vertIndex].z;

        g = genRay.getDir().x;
        h = genRay.getDir().y;
        i = genRay.getDir().z;

        j = pt[v[0].vertIndex].x - genRay.getStart().x;
        k = pt[v[0].vertIndex].y - genRay.getStart().y;
        l = pt[v[0].vertIndex].z - genRay.getStart().z;
        M = a*(e*i - h*f) + b*(g*f-d*i) + c*(d*h-e*g);

        if(M == 0) continue;
        beta = j*(e*i-h*f)+ k*(g*f-d*i)+l*(d*h-e*g);
        gama = i*(a*k-j*b)+ h*(j*c-a*l)+g*(b*l-k*c);
        t = f*(a*k-j*b) + e*(j*c-a*l)+d*(b*l-k*c);
        t *= -1/M;
        beta /= M;
        gama /= M;

        if(beta > 0 && gama > 0 &&(beta+gama) < 1)
        {
            if(t > 0 && (bestHitTime == -1 || t < bestHitTime))
            {
                bestHitTime = t;
                bestV = v;
            }
        }
    }

    if(bestHitTime != -1)
    {
        v = bestV;
        t = bestHitTime;
            
        inter.hit[0].hitTime = t;
        inter.hit[0].hitObject = this;
    
        // Compute Point of Intersection
		Point3 P(genRay.calculatePointOnRay(t));
        inter.hit[0].hitPoint.set(P.x, P.y, P.z);
    
        // Interpolate Normal
        Vector3 N;
        interpolate(v, P, N);
        inter.hit[0].hitNormal.set(N.x, N.y, N.z);
    
        // Fill in reamining hit information
        // NOTE: The following two lines are NOT correct.
        if(genRay.getDir().dot(N) < 0) inter.hit[0].isEntering = true;
        else inter.hit[0].isEntering = false;

        inter.hit[0].surface = 0;
        inter.numHits = 1;
    }

    if(inter.numHits == 0) return false;
    return true;
}

void Mesh::interpolate(VertexID* v, Point3 P, Vector3 &N)
{
    float M[9], m[9], n[3], b[3];

    M[0] = pt[v[0].vertIndex].x; M[1] = pt[v[1].vertIndex].x;  M[2] = pt[v[2].vertIndex].x;
    M[3] = pt[v[0].vertIndex].y; M[4] = pt[v[1].vertIndex].y;  M[5] = pt[v[2].vertIndex].y;
    M[6] = pt[v[0].vertIndex].z; M[7] = pt[v[1].vertIndex].z;  M[8] = pt[v[2].vertIndex].z;

    gluInvertMatrixf((GLfloat*)M, (GLfloat*)m, 3);
    
    n[0] = P.x; n[1] = P.y; n[2] = P.z;
    b[0] = b[1] = b[2] = 0;

    // Multiply m and n and put the result in b
    for(int i=0; i<3; i++)
    {
        for(int j=0; j<3; j++)
            b[i] += m[3*i + j]*n[j];
    }

    // Normalize b
    double length = sqrt(b[0]*b[0] + b[1]*b[1] + b[2]*b[2]);
    b[0] /= length; b[1] /= length; b[2] /= length;

    // B represents P in barycentric coordinates.  Multiply the normals at the vertices
    // by B to get the interpolated normal.
    N.x = b[0]*norm[v[0].normIndex].x + b[1]*norm[v[1].normIndex].x + b[2]*norm[v[2].normIndex].x;
    N.y = b[0]*norm[v[0].normIndex].y + b[1]*norm[v[1].normIndex].y + b[2]*norm[v[2].normIndex].y;
    N.z = b[0]*norm[v[0].normIndex].z + b[1]*norm[v[1].normIndex].z + b[2]*norm[v[2].normIndex].z;
}

GLvoid Mesh::gluMakeIdentityf(GLfloat m[], int dimension)
{
    //First, fill with zeros.
    for(int i=0; i<dimension; i++)
        for(int j=0; j<dimension; j++)
            m[i+dimension*j] = 0.0;

    //Second, set the diagonal to ones.
    for(int i=0; i<dimension; i++)
        m[i + dimension*i] = 1.0;
}

int Mesh::gluInvertMatrixf(GLfloat src[], GLfloat inverse[], int dimension)
{
    int i, j, k, swap;
    double t;

	GLfloat** temp = new GLfloat*[dimension];
    for (i=0; i<dimension; i++) {
		temp[i] = new GLfloat[dimension];
        for (j=0; j<dimension; j++) {
            temp[i][j] = src[i*dimension+j];
        }
    }

	gluMakeIdentityf(inverse, dimension);

    for (i = 0; i < dimension; i++) {
        /*
         ** Look for largest element in column
         */
        swap = i;
        for (j = i + 1; j < dimension; j++) {
            if (fabs(temp[j][i]) > fabs(temp[i][i])) {
                swap = j;
            }
        }

        if (swap != i) {
            /*
             ** Swap rows.
             */
            for (k = 0; k < dimension; k++) {
                t = temp[i][k];
                temp[i][k] = temp[swap][k];
                temp[swap][k] = t;

                t = inverse[i*dimension+k];
                inverse[i*dimension+k] = inverse[swap*dimension+k];
                inverse[swap*dimension+k] = t;
            }
        }

        if (temp[i][i] == 0) {
            /*
             ** No non-zero pivot.  The matrix is singular, which shouldn't
             ** happen.  This means the user gave us a bad matrix.
             */

				for(j=0; j<dimension; j++)
					delete [] temp[j];
				delete [] temp;

			return GL_FALSE;
        }

        t = temp[i][i];
        for (k = 0; k < dimension; k++) {
            temp[i][k] /= t;
            inverse[i*dimension+k] /= t;
        }
        for (j = 0; j < dimension; j++) {
            if (j != i) {
                t = temp[j][i];
                for (k = 0; k < dimension; k++) {
                    temp[j][k] -= temp[i][k]*t;
                    inverse[j*dimension+k] -= inverse[i*dimension+k]*t;
                }
            }
        }
    }

	for(i=0; i<dimension; i++)
		delete [] temp[i];
	delete [] temp;

    return GL_TRUE;
}

void Mesh::readMesh(string fname)
{
    meshFileName = fname;
    bool WARNING = false;
 
    fstream inStream;
    inStream.open(fname.c_str(), ios ::in);

    if(inStream.fail() || inStream.eof())
    {
        cout << "Error opening file : " << fname << endl;
        makeEmpty();
		return;
    }

    inStream >> numVerts >> numNorms >> numFaces;

    // make arrays for vertices, normals, and faces
    pt = new Point3[numVerts];        assert(pt != NULL);
    norm = new Vector3[numNorms];     assert(norm != NULL);
    face = new Face[numFaces];        assert(face != NULL);

    for(size_t i = 0; i < numVerts; i++) 				// read in the vertices
        inStream >> pt[i].x >> pt[i].y >> pt[i].z;

	for(size_t ii = 0; ii < numNorms; ii++) 			// read in the normals
        inStream >> norm[ii].x >> norm[ii].y >> norm[ii].z;

    for(size_t f = 0; f < numFaces; f++)				// read in face data
    {
        inStream >> face[f].nVerts;
        if(face[f].nVerts != 3 && !WARNING)
        {
            // Triangulate the face
            cout << "WARNING! Only Triangular Meshes are Supported at this time.\n"
                 << "The mesh object defined in '" << fname << "' will not be drawn.\n";
            WARNING = true;
        }

        size_t n = face[f].nVerts;
        face[f].vert = new VertexID[n]; assert(face[f].vert != NULL);

        for(size_t k = 0; k < n; k++) 		// read vertex indices for this face
            inStream >> face[f].vert[k].vertIndex;

        for(size_t kk = 0; kk < n; kk++) 		// read normal indices for this face
            inStream >> face[f].vert[kk].normIndex;
    }

    inStream.close();
}

void Mesh::writeMesh(char * fname)
{ // write this mesh object into a new Chapter 6 format file.
    if(numVerts == 0 || numNorms   == 0 || numFaces == 0) return; //empty

    fstream outStream(fname, ios ::out); // open the output stream
    if(outStream.fail()) {cout << "can't make new file: " << fname << endl; return;}

    outStream << numVerts << " " << numNorms << " " << numFaces << "\n";

    // write the vertex and vertex normal list
    for(size_t i = 0; i < numVerts; i++)
        outStream << pt[i].x   << " " << pt[i].y   << " " << pt[i].z << "\n";
    for(size_t ii = 0; ii < numNorms; ii++)
        outStream  << norm[ii].x << " " << norm[ii].y << " " << norm[ii].z << "\n";

    // write the face data
    for(size_t f = 0; f < numFaces; f++)
    {
        size_t n = face[f].nVerts;
        outStream << n << "\n";
        for(size_t v = 0; v < n; v++)// write vertex indices for this face
            outStream << face[f].vert[v].vertIndex << " ";	outStream << "\n";
        for(size_t k = 0; k < n; k++)	// write normal indices for this face
            outStream << face[f].vert[k].normIndex << " "; outStream << "\n";
    }

    outStream.close();
}

// Generate and OBJ file from the mesh data in this object
void Mesh::outputOBJ(string fname)
{
	// Is there any data to write out?
	if(numVerts == 0 || numNorms   == 0 || numFaces == 0) return; //empty 

	// Create the output stream.
	ofstream outStream;
	outStream.open(fname.c_str()); // open the output stream 
	if(outStream.fail())
	{
		cout << "can't make new file: " << fname << endl;
		return;
	} 

	// Write a comment identifying the file
	outStream << "# Generated by Mesh::outputOBJ() from '" << meshFileName << "'" << endl;

	// Write out a default group indicator
	outStream << "g default" << endl;
	
	// Write the vertex and vertex normal list 
	size_t i;
	for(i = 0; i < numVerts; i++) 
		outStream << "v " << pt[i].x   << " " << pt[i].y   << " " << pt[i].z << endl; 
	outStream << endl;

	for(i = 0; i < numNorms; i++) 
		outStream << "vn " << norm[i].x << " " << norm[i].y << " " << norm[i].z << endl; 
	outStream << endl;

	// Write the face data
	for(size_t f = 0; f < numFaces; f++) 
	{ 
		outStream << "f ";
		for(i = 0; i < face[f].nVerts; i++)
			outStream << face[f].vert[i].vertIndex+1 << "//" << face[f].vert[i].normIndex+1 << " ";
		outStream << endl;
	}

	// Close the output
	outStream.close(); 
}

void Mesh::drawOpenGL() {}

int Mesh::isEmpty() { return (numVerts == 0) || (numFaces == 0); } //|| (numNorms == 0);}
void Mesh::makeEmpty() { numVerts = numFaces = numNorms = 0;}

void Mesh::print(void) { cout << "Object: Mesh\n"; }


//@$@$@$@$@$@$@$@$@$@ Tetrahedron class @$@$@$@$@$@$@$@$@$
Tetrahedron::Tetrahedron():Mesh("Data/Tetrahedron.3vn") {}

void Tetrahedron::print()
{
        cout << "Object: Tetrahedron" << endl;
        transf.print();
}


//@$@$@$@$@$@$@$@$@$@ Octahedron class @$@$@$@$@$@$@$@$@$
Octahedron::Octahedron():Mesh("Data/Octahedron.3vn") {}

void Octahedron::print()
{
    cout << "Object: Octahedron" << endl;
    transf.print();
}


//@$@$@$@$@$@$@$@$@$@ Dodecahedron class @$@$@$@$@$@$@$@$@$
Dodecahedron::Dodecahedron():Mesh("Data/Dodecahedron.3vn") {}

void Dodecahedron::print()
{
    cout << "Object: Dodecahedron" << endl;
    transf.print();
}


//@$@$@$@$@$@$@$@$@$@ Icosahedron class @$@$@$@$@$@$@$@$@$
Icosahedron::Icosahedron():Mesh("Data/Icosahedron.3vn") {}

void Icosahedron::print()
{
    cout << "Object: Icosahedron" << endl;
    transf.print();
}


//@$@$@$@$@$@$@$@$@$@ BuckyBall class @$@$@$@$@$@$@$@$@$
BuckyBall::BuckyBall():Mesh("Data/BuckyBall.3vn") {}

void BuckyBall::print()
{
    cout << "Object: BuckyBall" << endl;
    transf.print();
}


//@$@$@$@$@$@$@$@$@$@ Diamond class @$@$@$@$@$@$@$@$@$
Diamond::Diamond():Mesh("Data/Diamond.3vn") {}

void Diamond::print()
{
    cout << "Object: Diamond" << endl;
    transf.print();
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -