void ofxObjLoader::save(string path, ofMesh& mesh){
    path = ofToDataPath(path);
    
    GLuint writeMode = GLM_NONE;
    
    GLMmodel* m = new GLMmodel();
    if(mesh.getNumVertices() > 0){
        m->numvertices = mesh.getNumVertices();
	    m->vertices = new GLfloat[m->numvertices*3+1];
        memcpy(&m->vertices[3], &mesh.getVertices()[0].x, sizeof(ofVec3f) * mesh.getNumVertices());
    }
    else {
        ofLogError("ofxObjLoader::save -- No vertices to save!");
        return;
    }
    
    if(mesh.getNumNormals() > 0){
        m->numnormals = mesh.getNumNormals();
        m->normals = new GLfloat[m->numnormals*3+1];
        memcpy(&m->normals[3], &mesh.getNormals()[0].x, sizeof(ofVec3f)*mesh.getNumNormals());
        writeMode |= GLM_SMOOTH;
    }
	
    if(mesh.getNumTexCoords() > 0){
        m->numtexcoords = mesh.getNumTexCoords();
        m->texcoords = new GLfloat[m->numtexcoords*2+1];
        memcpy(&m->texcoords[2], &mesh.getTexCoords()[0].x, sizeof(ofVec2f)*mesh.getNumTexCoords());
        writeMode |= GLM_TEXTURE;
    }
    
    if(mesh.getNumIndices() > 0){
        //create triangles
		m->numtriangles = mesh.getNumIndices()/3;
        m->triangles = new GLMtriangle[m->numtriangles];
        
        //add them all to one group
        m->groups = new GLMgroup();
        m->groups->next = NULL;
        m->groups->material = NULL;
        string name = "ofMesh";
        m->groups->name = (char*)malloc(sizeof(char) * name.length()+1);
        strcpy(m->groups->name, name.c_str());
        
        m->groups->numtriangles = mesh.getNumIndices()/3;
		m->groups->triangles = new GLuint[m->groups->numtriangles];
        m->numgroups = 1;
        for(int i = 0; i < mesh.getNumIndices()/3; i++){
            memcpy(m->triangles[i].vindices, &mesh.getIndices()[i*3], sizeof(GLuint)*3);
            memcpy(m->triangles[i].nindices, &mesh.getIndices()[i*3], sizeof(GLuint)*3);
            memcpy(m->triangles[i].tindices, &mesh.getIndices()[i*3], sizeof(GLuint)*3);
            m->groups->triangles[i] = i;
        }
    }
    
    glmWriteOBJ(m, (char*)path.c_str(), writeMode);
    glmDelete(m);
}
        //--------------------------------------------------------------
        bool load(const string& path, ofMesh& mesh)
        {
            ofFile file(path, ofFile::ReadOnly, true);
            if (!file.exists()) {
                ofLogError("ofxBinaryMesh::load") << "Cannot open file at " << path;
                return false;
            }

            mesh.clear();

            int numVerts = 0;
            file.read((char *)(&numVerts), sizeof(int));
            if (numVerts > 0) {
                mesh.getVertices().resize(numVerts);
                file.read((char *)(&(mesh.getVertices())[0]), sizeof(ofPoint) * numVerts);
            }

            int numNormals = 0;
            file.read((char *)(&numNormals), sizeof(int));
            if (numNormals > 0) {
                mesh.getNormals().resize(numNormals);
                file.read((char *)(&(mesh.getNormals())[0]), sizeof(ofPoint) * numNormals);
            }

            int numTexCoords = 0;
            file.read((char *)(&numTexCoords), sizeof(int));
            if (numTexCoords > 0) {
                mesh.getTexCoords().resize(numTexCoords);
                file.read((char *)(&(mesh.getTexCoords())[0]), sizeof(ofVec2f) * numTexCoords);
            }

            int numColors = 0;
            file.read((char *)(&numColors), sizeof(int));
            if (numColors > 0) {
                mesh.getColors().resize(numColors);
                file.read((char *)(&(mesh.getColors())[0]), sizeof(ofFloatColor) * numColors);
            }

            int numIndices = 0;
            file.read((char *)(&numIndices), sizeof(int));
            if (numIndices > 0) {
                mesh.getIndices().resize(numIndices);
                file.read((char *)(&(mesh.getIndices())[0]), sizeof(ofIndexType) * numIndices);
            }

            file.close();

			return true;
        }
Beispiel #3
0
void MeshHelper::fuseNeighbours( ofMesh& outputMesh, const ofMesh& sourceMesh, float fuseDistance )
{
	//@todo tex coords, normals
	assert( sourceMesh.getMode() == OF_PRIMITIVE_TRIANGLES );
	
	if ( fuseDistance < 0 )
	{
		// fuse close-enough vertices
		// first define 'close enough' as 1/10000 of smallest dimension of the bounding box width/height/depth
		ofVec3f tlb, brf; // top left back, bottom right front
		calculateAABoundingBox( sourceMesh, tlb, brf );
		float minDimension = min(brf.x-tlb.x,min(brf.y-tlb.y, brf.z-tlb.z));
		fuseDistance = minDimension * 0.00001f;
	}

	// now fuse
	map<int,int> fused;
	vector<ofVec3f> vertices;
	for ( int i=0; i<sourceMesh.getNumVertices(); i++ )
	{
		const ofVec3f& vertex = sourceMesh.getVertex(i);
		//vertex.rotate(10, 10, 10);
		bool didFuse = false;
		for ( int j=0; j<vertices.size(); j++ ) {
			if ( (vertex-vertices[j]).length()<fuseDistance ) {
				// fuse i to j
				fused[i] = j;
				didFuse = true;
				break;
			}
		}
		if ( !didFuse ) {
			vertices.push_back( vertex );
			fused[i] = vertices.size()-1;
		}
	}
		
	// build the output mesh
	outputMesh.clear();
	outputMesh.addVertices(vertices);
	if ( sourceMesh.getNumIndices() > 0 ) {
		// walk through indices to build up the new mesh
		const vector<ofIndexType>& indices = sourceMesh.getIndices();
		for ( int i=0; i<indices.size(); i+=3 ) {
			assert( fused.find( indices[i] ) != fused.end() );
			assert( fused.find( indices[i+1] ) != fused.end() );
			assert( fused.find( indices[i+2] ) != fused.end() );
			outputMesh.addTriangle( fused[indices[i]], fused[indices[i+1]], fused[indices[i+2]] );
		}
	} else {
		// triangles are just triples of vertices
		for ( int i=0; i<sourceMesh.getNumVertices(); i+=3 ) {
			outputMesh.addTriangle( fused[i], fused[i+1], fused[i+2] );
		}
	}
	
	ofLogNotice("MeshHelper") << "fuseNeighbours: input " << sourceMesh.getNumVertices() << " vertices/" << sourceMesh.getNumIndices() << " indices, output " << outputMesh.getNumVertices() << " vertices/" << outputMesh.getNumIndices() << " indices";
}
Beispiel #4
0
void MeshHelper::fuseNeighbours( ofMesh& mesh, float fuseDistance )
{
	//@todo tex coords, normals
	assert( mesh.getMode() == OF_PRIMITIVE_TRIANGLES );
	int oldNumVerts = mesh.getNumVertices();
	int oldNumIndices = mesh.getNumIndices();
	
	if ( fuseDistance < 0 )
	{
		// fuse close-enough vertices
		// first define 'close enough' as 1/10000 of smallest dimension of the bounding box width/height/depth
		ofVec3f tlb, brf; // top left back, bottom right front
		calculateAABoundingBox( mesh, tlb, brf );
		float minDimension = min(brf.x-tlb.x,min(brf.y-tlb.y, brf.z-tlb.z));
		fuseDistance = minDimension * 0.00001f;
	}
	
	// now fuse
	map<ofIndexType,ofIndexType> fused;
	vector<ofVec3f> newVertices;
	vector<ofIndexType> remove;
	for ( ofIndexType i=0; i<mesh.getNumVertices(); i++ )
	{
		const ofVec3f& vertex = mesh.getVertex(i);
		// look at all the earlier vertices
		bool didFuse = false;
		for ( ofIndexType j=0; j<newVertices.size(); j++ ) {
			if ( (vertex-newVertices[j]).length()<fuseDistance ) {
				// fuse i to j
				fused[i] = j;
				remove.push_back(i);
				didFuse = true;
				break;
			}
		}
		if ( !didFuse ) {
			newVertices.push_back( vertex );
			fused[i] = newVertices.size()-1;
		}
	}
	
	// update indices
	for ( int i=0; i<mesh.getNumIndices(); i++ ) {
		ofIndexType originalIndex = mesh.getIndex(i);
		assert( fused.find( originalIndex ) != fused.end() );
		if ( fused.find(originalIndex) != fused.end() ) {
			mesh.getIndices()[i] = fused[originalIndex];
		}
	}
	
	// remove the fused
	for ( int i=remove.size()-1; i>=0; i-- ) {
		mesh.removeVertex( remove[i] );
	}
		
	ofLogNotice("MeshHelper") << "fuseNeighbours inplace: input " << oldNumVerts << " vertices/" << oldNumIndices << " indices, output " << mesh.getNumVertices() << " vertices/" << mesh.getNumIndices() << " indices";

}
//--------------------------------------------------------------
void ofxBulletSoftTriMesh::create( ofxBulletWorldSoft* a_world, ofMesh& aMesh, btTransform &a_bt_tr, float a_mass ) {
    
    if(a_world == NULL) {
        ofLogError("ofxBulletSoftTriMesh") << "create(): a_world param is NULL";
        return;
    }
    
    if( aMesh.getMode() != OF_PRIMITIVE_TRIANGLES ) {
        ofLogError("ofxBulletSoftTriMesh") << " only excepts meshes that are triangles";
        return;
    }
    
    _world = a_world;
    
    _cachedMesh.clear();
    _cachedMesh = aMesh;
    
    if( bullet_vertices != NULL ) {
        delete bullet_vertices;
        bullet_vertices = NULL;
    }
    
    int vertStride  = sizeof(btVector3);
    int indexStride = 3*sizeof(int);
    
    int totalVerts    = (int)aMesh.getNumVertices();
    int totalIndices  = (int)aMesh.getNumIndices();
    
    bullet_vertices = new btScalar[ totalVerts * 3 ];
    int* bullet_indices = new int[ totalIndices ];
    
    auto& tverts       = aMesh.getVertices();
    vector< ofIndexType >& tindices = aMesh.getIndices();
    
    for( int i = 0; i < totalVerts; i++ ) {
        bullet_vertices[i*3+0] = tverts[i].x;
        bullet_vertices[i*3+1] = tverts[i].y;
        bullet_vertices[i*3+2] = tverts[i].z;
    }
    for( int i = 0; i < totalIndices; i++ ) {
        bullet_indices[i] = tindices[i];
    }
    
    _softBody = btSoftBodyHelpers::CreateFromTriMesh( _world->getInfo(),
                                                         bullet_vertices,
                                                         bullet_indices,
                                                         totalIndices/3 );
    _softBody->transform( a_bt_tr );
    setMass( a_mass, true );
    
    setCreated(_softBody);
    createInternalUserData();

    delete [] bullet_indices;
    
}
Beispiel #6
0
void MeshHelper::appendMesh( ofMesh& targetMesh, const ofMesh& toAppend, bool fuse )
{
	ofIndexType indexOffset = targetMesh.getNumVertices();
	targetMesh.addVertices( toAppend.getVertices() );
	// append indices
	const vector<ofIndexType>& indices = toAppend.getIndices();
	for ( int i=0; i<indices.size(); i++ ) {
		targetMesh.addIndex( indices[i]+indexOffset );
	}
	
	if ( fuse )
		fuseNeighbours(targetMesh);
}
Beispiel #7
0
void buildNormalsAverage(ofMesh& mesh) {
    vector<ofIndexType>& indices = mesh.getIndices();
    vector<ofVec3f> normals(mesh.getNumVertices());
    for(int i = 0; i < indices.size(); i += 3) {
        int i0 = indices[i + 0], i1 = indices[i + 1], i2 = indices[i + 2];
        ofVec3f normal = getNormal(mesh.getVertices()[i0], mesh.getVertices()[i1], mesh.getVertices()[i2]);
        normals[i0] += normal;
        normals[i1] += normal;
        normals[i2] += normal;
    }
    for(int i = 0; i < normals.size(); i++) {
        normals[i].normalize();
    }
    mesh.addNormals(normals);
}
Beispiel #8
0
void ofxMesh::fromMesh(const ofMesh & mesh){
    if (mesh.hasVertices()) {
        getVertices()=mesh.getVertices();
    }
    if (mesh.hasColors()) {
        getColors()=mesh.getColors();
    }
    if (mesh.hasNormals()) {
        getNormals()=mesh.getNormals();
    }
    if (mesh.hasTexCoords()) {
        getTexCoords()=mesh.getTexCoords();
    }
    if (mesh.hasIndices()) {
        getIndices()=mesh.getIndices();
    }
}
Beispiel #9
0
void ofxMesh::toMesh(ofMesh & mesh){
    mesh.clear();
    if (hasVertices()) {
        mesh.getVertices()=getVertices();
    }
    if (hasColors()) {
        mesh.getColors()=getColors();
    }
    if (hasNormals()) {
        mesh.getNormals()=getNormals();
    }
    if (hasTexCoords()) {
        mesh.getTexCoords()=getTexCoords();
    }
    if (hasIndices()) {
        mesh.getIndices()=getIndices();
    }
}
Beispiel #10
0
glmMesh toGlm(const ofMesh &_mesh){
    glmMesh mesh;
    
    for (auto &it : _mesh.getColors()) {
        mesh.addColor(toGlm(it));
    }
    
    for (auto &it : _mesh.getVertices()) {
        mesh.addVertex(toGlm(it));
    }
    
    for (auto &it : _mesh.getNormals()) {
        mesh.addNormal(toGlm(it));
    }
    
    for (auto &it : _mesh.getTexCoords()) {
        mesh.addTexCoord(toGlm(it));
    }
    
    for (auto &it : _mesh.getIndices()) {
        mesh.addIndex(toGlm(it));
    }
    
    GLenum drawMode = ofGetGLPrimitiveMode(_mesh.getMode());
    if (drawMode == GL_POINTS) {
        mesh.setDrawMode(POINTS);
    } else if (drawMode == GL_LINES){
        mesh.setDrawMode(LINES);
    } else if (drawMode == GL_LINE_STRIP){
        mesh.setDrawMode(LINE_STRIP);
    } else if (drawMode == GL_TRIANGLES){
        mesh.setDrawMode(TRIANGLES);
    } else if (drawMode == GL_TRIANGLE_STRIP){
        mesh.setDrawMode(TRIANGLE_STRIP);
    }
    
    
    
    return mesh;
}
void CloudsVisualSystem3DModelLoader::facetMesh( ofMesh& smoothedMesh, ofMesh& targetMesh )
{
	//get our vertex, uv and face info
	vector<ofVec3f>& v = smoothedMesh.getVertices();
	vector<ofVec2f>& uv = smoothedMesh.getTexCoords();
	vector<ofIndexType>& indices = smoothedMesh.getIndices();
	bool hasTC = smoothedMesh.getNumTexCoords();
	
	//use these to store our new mesh info
	vector<ofVec3f> facetedVertices( indices.size() );
	vector<ofVec3f> facetedNormals( indices.size() );
	vector<ofVec2f> facetedTexCoords;
	if(hasTC){
		facetedTexCoords.resize( indices.size() );
	}
	vector<ofIndexType> facetedIndices( indices.size() );
	
	//store vertex and uv data
	for (int i=0; i < indices.size(); i++) {
		facetedIndices[i] = i;
		facetedVertices[i] = v[indices[i]];
		if(hasTC)	facetedTexCoords[i] = uv[indices[i]];
	}
	
	//calculate our face normals
	ofVec3f n;
	for (int i=0; i < facetedIndices.size(); i+=3) {
		n = normalFrom3Points( facetedVertices[i], facetedVertices[i+1], facetedVertices[i+2]);
		facetedNormals[i] = n;
		facetedNormals[i+1] = n;
		facetedNormals[i+2] = n;
	}
	
	//setup our faceted mesh. this should still work if our targetMesh is our smoothMesh
	targetMesh.clear();
	targetMesh.addVertices( facetedVertices );
	targetMesh.addNormals( facetedNormals );
	if(hasTC)	targetMesh.addTexCoords( facetedTexCoords );
	targetMesh.addIndices( facetedIndices );
}
// adjacency list of triangulation
vector< set<size_t> > ofxDelaunay2D::adjacencyForTriMesh(ofMesh &triMesh) {
    vector< set<size_t> > adjacency; adjacency.reserve(triMesh.getNumVertices());

    for(size_t i=0; i<(size_t)(triMesh.getNumVertices()); ++i) {
        adjacency.push_back(set<size_t>());
    }

    for(int i0=0; i0<(int)triMesh.getIndices().size() - 2; i0+=3) {
        size_t i = triMesh.getIndex(i0);
        size_t j = triMesh.getIndex(i0 + 1);
        size_t k = triMesh.getIndex(i0 + 2);

        adjacency[i].insert(j);
        adjacency[j].insert(i);
        adjacency[i].insert(k);
        adjacency[k].insert(i);
        adjacency[j].insert(k);
        adjacency[k].insert(j);
    }

    return adjacency;
}
        //--------------------------------------------------------------
        void save(const string& path, const ofMesh& mesh)
        {
            ofFile file(path, ofFile::WriteOnly, true);

            int numVerts = mesh.getNumVertices();
            file.write((char *)(&numVerts), sizeof(int));
            if (numVerts > 0) {
                file.write((char *)(&(mesh.getVertices())[0]), sizeof(ofPoint) * numVerts);
            }

            int numNormals = mesh.getNumNormals();
            file.write((char *)(&numNormals), sizeof(int));
            if (numNormals > 0) {
                file.write((char *)(&(mesh.getNormals())[0]), sizeof(ofPoint) * numNormals);
            }

            int numTexCoords = mesh.getNumTexCoords();
            file.write((char *)(&numTexCoords), sizeof(int));
            if (numTexCoords > 0) {
                file.write((char *)(&(mesh.getTexCoords())[0]), sizeof(ofVec2f) * numTexCoords);
            }

            int numColors = mesh.getNumColors();
            file.write((char *)(&numColors), sizeof(int));
            if (numColors > 0) {
                file.write((char *)(&(mesh.getColors())[0]), sizeof(ofFloatColor) * numColors);
            }

            int numIndices = mesh.getNumIndices();
            file.write((char *)(&numIndices), sizeof(int));
            if (numIndices > 0) {
                file.write((char *)(&(mesh.getIndices())[0]), sizeof(ofIndexType) * numIndices);
            }

            file.close();
        }
Beispiel #14
0
//--------------------------------------------------------------
bool ofxBulletCustomShape::addMesh( ofMesh a_mesh, ofVec3f a_localScaling, bool a_bUseConvexHull ) {
	if(a_mesh.getMode() != OF_PRIMITIVE_TRIANGLES) {
		ofLog( OF_LOG_ERROR, "ofxBulletCustomShape :: addMesh : mesh must be set to OF_PRIMITIVE_TRIANGLES!! aborting");
		return false;
	}
	if(_bAdded == true) {
		ofLog( OF_LOG_ERROR, "ofxBulletCustomShape :: addMesh : can not call after calling add()" );
		return false;
	}
	
	btVector3 localScaling( a_localScaling.x, a_localScaling.y, a_localScaling.z );
	auto indicies = a_mesh.getIndices();
	auto verticies = a_mesh.getVertices();
    
	btVector3 centroid = btVector3(0, 0, 0);
	
	if(!a_bUseConvexHull) {
		for(int i = 0; i < verticies.size(); i++) {
			btVector3 tempVec = btVector3(verticies[i].x, verticies[i].y, verticies[i].z);
			tempVec *= localScaling;
			centroid += tempVec;
		}
		centroid /= (float)verticies.size();
		
		vector<btVector3> newVerts;
		for ( int i = 0; i < indicies.size(); i++) {
			btVector3 vertex( verticies[indicies[i]].x, verticies[indicies[i]].y, verticies[indicies[i]].z);
			vertex *= localScaling;
			vertex -= centroid;
			newVerts.push_back(vertex);
		}
		
		btConvexHullShape* convexShape = new btConvexHullShape(&(newVerts[0].getX()), newVerts.size());
		convexShape->setMargin( 0.01f );
		shapes.push_back( convexShape );
		centroids.push_back( ofVec3f(centroid.getX(), centroid.getY(), centroid.getZ()) );
	} else {
		// HULL Building code from example ConvexDecompositionDemo.cpp //
		btTriangleMesh* trimesh = new btTriangleMesh();
		
		for ( int i = 0; i < indicies.size()/3; i++) {
			int index0 = indicies[i*3];
			int index1 = indicies[i*3+1];
			int index2 = indicies[i*3+2];
			
			btVector3 vertex0( verticies[index0].x, verticies[index0].y, verticies[index0].z );
			btVector3 vertex1( verticies[index1].x, verticies[index1].y, verticies[index1].z );
			btVector3 vertex2( verticies[index2].x, verticies[index2].y, verticies[index2].z );
			
			vertex0 *= localScaling;
			vertex1 *= localScaling;
			vertex2 *= localScaling;
			
			trimesh->addTriangle(vertex0, vertex1, vertex2);
		}
		
		//cout << "ofxBulletCustomShape :: addMesh : input triangles = " << trimesh->getNumTriangles() << endl;
		//cout << "ofxBulletCustomShape :: addMesh : input indicies = " << indicies.size() << endl;
		//cout << "ofxBulletCustomShape :: addMesh : input verticies = " << verticies.size() << endl;
		
		btConvexShape* tmpConvexShape = new btConvexTriangleMeshShape(trimesh);
		
		//create a hull approximation
		btShapeHull* hull = new btShapeHull(tmpConvexShape);
		btScalar margin = tmpConvexShape->getMargin();
		hull->buildHull(margin);
		tmpConvexShape->setUserPointer(hull);
		
		centroid = btVector3(0., 0., 0.);
		for (int i = 0; i < hull->numVertices(); i++) {
			centroid += hull->getVertexPointer()[i];
		}
		centroid /= (float)hull->numVertices();
		
		//printf("ofxBulletCustomShape :: addMesh : new hull numTriangles = %d\n", hull->numTriangles());
		//printf("ofxBulletCustomShape :: addMesh : new hull numIndices = %d\n", hull->numIndices());
		//printf("ofxBulletCustomShape :: addMesh : new hull numVertices = %d\n", hull->numVertices());
		
		btConvexHullShape* convexShape = new btConvexHullShape();
		for (int i=0;i<hull->numVertices();i++) {
			convexShape->addPoint(hull->getVertexPointer()[i] - centroid);
		}
		
		delete tmpConvexShape;
		delete hull;
		
		shapes.push_back( convexShape );
		centroids.push_back( ofVec3f(centroid.getX(), centroid.getY(), centroid.getZ()) );
	}
	return true;
}
//--------------------------------------------------------------
void ofxBulletTriMeshShape::create( btDiscreteDynamicsWorld* a_world, ofMesh& aMesh, btTransform &a_bt_tr, float a_mass, glm::vec3 aAAbbMin, glm::vec3 aAAbbMax ) {
    if( aMesh.getMode() != OF_PRIMITIVE_TRIANGLES ) {
        ofLogWarning() << " ofxBulletTriMeshShape :: create : mesh must be using triangles, not creating!!" << endl;
        return;
    }
    if( aMesh.getNumIndices() < 3 ) {
        ofLogWarning() << " ofxBulletTriMeshShape :: create : mesh must have indices, not creating!" << endl;
        return;
    }
    
    
    if( !_bInited || _shape == NULL ) {
        int vertStride  = sizeof(btVector3);
        int indexStride = 3*sizeof(int);
        
        totalVerts    = (int)aMesh.getNumVertices();
        totalIndices  = (int)aMesh.getNumIndices();
        
        const int totalTriangles = totalIndices / 3;
        
        if( bullet_indices != NULL ) {
            removeShape();
        }
        if( bullet_vertices != NULL ) {
            removeShape();
        }
        if( bullet_indexVertexArrays != NULL ) {
            removeShape();
        }
        if( _shape != NULL ) {
            removeShape();
        }
        
        bullet_vertices   = new btVector3[ totalVerts ];
        bullet_indices    = new int[ totalIndices ];
        
        auto& tverts = aMesh.getVertices();
        auto& tindices = aMesh.getIndices();
        
        for( int i = 0; i < totalVerts; i++ ) {
            bullet_vertices[i].setValue( tverts[i].x, tverts[i].y, tverts[i].z );
        }
        for( int i = 0; i < totalIndices; i++ ) {
            bullet_indices[i] = (int)tindices[i];
        }
        
        bullet_indexVertexArrays = new btTriangleIndexVertexArray(totalTriangles, bullet_indices, indexStride,
                                                                  totalVerts, (btScalar*) &bullet_vertices[0].x(), vertStride);
        
        
//        if you are having trouble with objects falling through, try passing in smaller or larger aabbMin and aabbMax
//        to something closer to the size of your object //
//        btVector3 aabbMin(-10000,-10000,-10000),aabbMax(10000,10000,10000);
        if( aAAbbMin.length() > 0 && aAAbbMax.length() > 0 ) {
            btVector3 aabbMin( aAAbbMin.x, aAAbbMin.y, aAAbbMin.z );
            btVector3 aabbMax( aAAbbMax.x, aAAbbMax.y, aAAbbMax.z );
            _shape  = new btBvhTriangleMeshShape(bullet_indexVertexArrays, true, aabbMin, aabbMax );
        } else {
            _shape  = new btBvhTriangleMeshShape(bullet_indexVertexArrays, true, true );
        }
	}
    
    ofxBulletRigidBody::create( a_world, _shape, a_bt_tr, a_mass );
    
    
    createInternalUserData();
    updateMesh( a_world, aMesh );
}
Beispiel #16
0
//--------------------------------------------------------------
void ofxBulletConvexShape::init( ofMesh& aMesh, ofVec3f a_localScaling, bool a_bUseConvexHull ) {
    _centroid.zero();
    btVector3 centroid = btVector3(0, 0, 0);
    btVector3 localScaling( a_localScaling.x, a_localScaling.y, a_localScaling.z );
    
    vector <ofIndexType>	indicies    = aMesh.getIndices();
	vector <ofVec3f>		verticies   = aMesh.getVertices();
	
	if(!a_bUseConvexHull) {
		for(int i = 0; i < verticies.size(); i++) {
			btVector3 tempVec = btVector3(verticies[i].x, verticies[i].y, verticies[i].z);
			tempVec *= localScaling;
			centroid += tempVec;
		}
		centroid /= (float)verticies.size();
		
		vector<btVector3> newVerts;
		for ( int i = 0; i < indicies.size(); i++) {
			btVector3 vertex( verticies[indicies[i]].x, verticies[indicies[i]].y, verticies[indicies[i]].z);
			vertex *= localScaling;
			vertex -= centroid;
			newVerts.push_back(vertex);
		}
		
		btConvexHullShape* convexShape = new btConvexHullShape(&(newVerts[0].getX()), newVerts.size());
		convexShape->setMargin( 0.01f );
        _shape = convexShape;
        _centroid = ofVec3f(centroid.getX(), centroid.getY(), centroid.getZ() );
	} else {
		// HULL Building code from example ConvexDecompositionDemo.cpp //
		btTriangleMesh* trimesh = new btTriangleMesh();
		
		for ( int i = 0; i < indicies.size()/3; i++) {
			int index0 = indicies[i*3];
			int index1 = indicies[i*3+1];
			int index2 = indicies[i*3+2];
			
			btVector3 vertex0( verticies[index0].x, verticies[index0].y, verticies[index0].z );
			btVector3 vertex1( verticies[index1].x, verticies[index1].y, verticies[index1].z );
			btVector3 vertex2( verticies[index2].x, verticies[index2].y, verticies[index2].z );
			
			vertex0 *= localScaling;
			vertex1 *= localScaling;
			vertex2 *= localScaling;
			
			trimesh->addTriangle(vertex0, vertex1, vertex2);
		}
		
		btConvexShape* tmpConvexShape = new btConvexTriangleMeshShape(trimesh);
		
		//create a hull approximation
		btShapeHull* hull = new btShapeHull(tmpConvexShape);
		btScalar margin = tmpConvexShape->getMargin();
		hull->buildHull(margin);
		tmpConvexShape->setUserPointer(hull);
		
		centroid = btVector3(0., 0., 0.);
		for (int i = 0; i < hull->numVertices(); i++) {
			centroid += hull->getVertexPointer()[i];
		}
		centroid /= (float)hull->numVertices();
		
		btConvexHullShape* convexShape = new btConvexHullShape();
		for (int i=0;i<hull->numVertices();i++) {
			convexShape->addPoint(hull->getVertexPointer()[i] - centroid);
		}
		
		delete tmpConvexShape;
		delete hull;
		
        _shape = convexShape;
        _centroid = ofVec3f(centroid.getX(), centroid.getY(), centroid.getZ() );
	}
    
	_bInited	= true;
}
Beispiel #17
0
vector<float> Model::generateTangents(ofMesh& mesh) {
	// Tangent generation adapted from algorithm at http://www.terathon.com/code/tangent.html
	auto vertices = mesh.getVertices();
	auto normals = mesh.getNormals();
	auto texcoords = mesh.getTexCoords();
	auto triangles = mesh.getIndices();

	vector<float> tangents(vertices.size()*4);

	vector<ofVec3f> tan1(vertices.size(), ofVec3f(0,0,0));
	vector<ofVec3f> tan2(vertices.size(), ofVec3f(0,0,0));

	for (unsigned int i = 0; i < triangles.size(); i += 3) {
		long i1 = triangles[i];
		long i2 = triangles[i+1];
		long i3 = triangles[i+2];

		const ofVec3f& v1 = vertices[i1];
		const ofVec3f& v2 = vertices[i2];
		const ofVec3f& v3 = vertices[i3];

		const ofVec2f& w1 = texcoords[i1];
		const ofVec2f& w2 = texcoords[i2];
		const ofVec2f& w3 = texcoords[i3];

		float x1 = v2.x - v1.x;
		float x2 = v3.x - v1.x;
		float y1 = v2.y - v1.y;
		float y2 = v3.y - v1.y;
		float z1 = v2.z - v1.z;
		float z2 = v3.z - v1.z;

		float s1 = w2.x - w1.x;
		float s2 = w3.x - w1.x;
		float t1 = w2.y - w1.y;
		float t2 = w3.y - w1.y;

		float r = 1.0F / (s1 * t2 - s2 * t1);
		ofVec3f sdir((t2 * x1 - t1 * x2) * r, 
					 (t2 * y1 - t1 * y2) * r,
					 (t2 * z1 - t1 * z2) * r);
		ofVec3f tdir((s1 * x2 - s2 * x1) * r,
					 (s1 * y2 - s2 * y1) * r,
					 (s1 * z2 - s2 * z1) * r);

		tan1[i1] += sdir;
		tan1[i2] += sdir;
		tan1[i3] += sdir;

		tan2[i1] += tdir;
		tan2[i2] += tdir;
		tan2[i3] += tdir;
	}

	for (unsigned int i = 0; i < vertices.size(); ++i) {
		ofVec3f& n = normals[i];
		ofVec3f& t = tan1[i];

		// Gram-Schmidt orthogonalize
		auto tangent = (t - n * n.dot(t)).normalize();
		// Calculate handedness
		float w = (n.cross(t).dot(tan2[i]) < 0.0) ? -1.0 : 1.0;

		tangents[i*4] = tangent.x;
		tangents[i*4+1] = tangent.y;
		tangents[i*4+2] = tangent.z;
		tangents[i*4+3] = w;
	}

	return tangents;
}
void CloudsVisualSystem3DModelLoader::smoothMesh( ofMesh& facetedMesh, ofMesh& targetMesh, int precision)
{
	cout << "smoothing mesh" << endl;
	
	//get our vertex, uv and face info
	vector<ofVec3f>& v = facetedMesh.getVertices();
	vector<ofVec2f>& uv = facetedMesh.getTexCoords();
	vector<ofIndexType>& indices = facetedMesh.getIndices();
	bool hasTC = facetedMesh.getNumTexCoords();
	
	//use these to store our new mesh info
	map<string, unsigned int> mergeMap;
	vector<ofVec3f> smoothVertices;
	vector<ofVec3f> smoothNormals;
	vector<ofVec2f> smoothTexCoords;
	vector<ofIndexType> smoothIndices;
	
	//merge our vertices by pointing near by vertices to the same index
	for (int i=0; i<v.size(); i++)
	{
		mergeMap[ vec3ToString( v[i], precision ) ] = i;
	}
	
	//fill our smoothed vertex array with merged vertices & tex coords
	smoothVertices.resize( mergeMap.size() );
	if(hasTC)	smoothTexCoords.resize( mergeMap.size() );
	int smoothVertexCount = 0;
	for (map<string, unsigned int>::iterator it = mergeMap.begin(); it != mergeMap.end(); it++)
	{
		smoothVertices[smoothVertexCount] = v[it->second];
		if(hasTC)	smoothTexCoords[smoothVertexCount] = uv[it->second];
		it->second = smoothVertexCount;//store our new vertex index
		smoothVertexCount++;
	}
	
	
	//reconstruct our faces by reassigning their indices to the merged vertices
	smoothIndices.resize( indices.size() );
	for (int i=0; i<indices.size(); i++)
	{
		//use our old vertex poisition to retrieve our new index
		smoothIndices[i] = mergeMap[ vec3ToString( v[ indices[i] ], precision ) ];
	}
	
	//calculate our normals
	smoothNormals.resize( smoothVertices.size() );
	ofVec3f n;
	for (int i=0; i<smoothIndices.size(); i+=3)
	{
		n = normalFrom3Points( smoothVertices[smoothIndices[i]], smoothVertices[smoothIndices[i+1]], smoothVertices[smoothIndices[i+2]] );
		smoothNormals[smoothIndices[i]] += n;
		smoothNormals[smoothIndices[i+1]] += n;
		smoothNormals[smoothIndices[i+2]] += n;
	}
	
	for (int i=0; i<smoothNormals.size(); i++)
	{
		smoothNormals[i].normalize();
	}
	
	//setup our smoothed mesh. this should still work if our targetMesh is our facetedMesh
	targetMesh.clear();
	targetMesh.addVertices( smoothVertices );
	targetMesh.addNormals( smoothNormals );
	if(hasTC)	targetMesh.addTexCoords( smoothTexCoords );
	targetMesh.addIndices( smoothIndices );
}