Beispiel #1
0
// Create a polygonal mesh for this torus using parameterization as follows:
// u = [0, 2*Pi] traces a circle in the x-y plane with radius torusRadius,
// which is the centroid of the torus. A point P on this circle is
// given by P = torusRadius*~[cos(u) sin(u) 0].
// v = [0, 2*Pi] traces a circle arond the cross-section (or tube) of the
// torus with radius tubeRadius, at a given u. A point Q on this circle
// is given by Q = (torusRadius + tubeRadius*cos(v))*e1 + tubeRadius*(~[0 0 1]*sin(v))
// where e1 = ~[sin(u) cos(u) 0]. The tube circle is in a plane spanned
// by e1 and the z-axis.
void ContactGeometry::Torus::Impl::createPolygonalMesh(PolygonalMesh& mesh) const {
    // TODO add resolution argument
    const int numSides = 12; //*resolution;
    const int numSlices = 36; //*resolution;   

    // add vertices 
    for (int i = 0; i < numSlices; ++i) {
      Real u = Real((i*2*SimTK_PI)/numSlices);
      UnitVec3 e1(std::sin(u), std::cos(u), 0); // torus circle aligned with z-axis (z-axis through hole)
      for (int j = 0; j < numSides; ++j) {
        Real v = Real((j*2*SimTK_PI)/numSides);
        Vec3 vtx = (torusRadius + tubeRadius*std::cos(v))*e1 + tubeRadius*std::sin(v)*Vec3(0,0,1); // use ZAXIS? 
        mesh.addVertex(vtx);  
      }
    }

    // add faces, be careful to wrap indices for the last slice
    int numVertices = mesh.getNumVertices();
//    cout << "num verts = " << numVertices << endl;
    for (int i = 0; i < numVertices; ++i) {
//      cout << "v" << i << ": " << mesh.getVertexPosition(i) << endl;
      // define counter-clockwise quad faces
      Array_<int> faceIndices;
      faceIndices.push_back(i); // u_i,v_i
      faceIndices.push_back((i+1)%numVertices); // u_i, v_i+1
      faceIndices.push_back((i+1+numSides)%numVertices); // u_i+1, v_i+1
      faceIndices.push_back((i+numSides)%numVertices); // u_i+1, v_i
      mesh.addFace(faceIndices);	
    }

}
void ContactGeometry::TriangleMesh::Impl::
createPolygonalMesh(PolygonalMesh& mesh) const {
    for (unsigned vx=0; vx < vertices.size(); ++vx)
        mesh.addVertex(vertices[vx].pos);
    for (unsigned fx=0; fx < faces.size(); ++fx) {
        const Face& face = faces[fx];
        const ArrayViewConst_<int> verts(face.vertices, face.vertices+3);
        mesh.addFace(verts);
    }
}
void testLoadObjFile() {
    string file;
    file += "# This is a comment\n";
    file += "v -1.0 1.0 2.0\n";
    file += "v -2.0 2.0 3.0\n";
    file += "v -3.0 3.0 \\\n";
    file += "4.0\n";
    file += "v -4.0 4.0 5.0\n";
    file += "v -5.0 5.0 6.0\n";
    file += "f 1 2 3\n";
    file += "f 2// 3/4/5 4//2\n";
    file += "f -3 -2/3/4 -1\n";
    file += "f 1 3\\\n";
    file += "5 2\n";
    PolygonalMesh mesh;
    stringstream stream(file);
    mesh.loadObjFile(stream);
    ASSERT(mesh.getNumVertices() == 5);
    ASSERT(mesh.getNumFaces() == 4);
    for (int i = 0; i < mesh.getNumVertices(); i++) {
        const Vec3& pos = mesh.getVertexPosition(i);
        ASSERT(pos[0] == -(i+1));
        ASSERT(pos[1] == i+1);
        ASSERT(pos[2] == i+2);
    }
    for (int i = 0; i < 3; i++) {
        ASSERT(mesh.getNumVerticesForFace(i) == 3);
        ASSERT(mesh.getFaceVertex(i, 0) == i);
        ASSERT(mesh.getFaceVertex(i, 1) == i+1);
        ASSERT(mesh.getFaceVertex(i, 2) == i+2);
    }
    ASSERT(mesh.getNumVerticesForFace(3) == 4);
    ASSERT(mesh.getFaceVertex(3, 0) == 0);
    ASSERT(mesh.getFaceVertex(3, 1) == 2);
    ASSERT(mesh.getFaceVertex(3, 2) == 4);
    ASSERT(mesh.getFaceVertex(3, 3) == 1);
}
void testCreateMesh() {
    PolygonalMesh mesh;
    ASSERT(mesh.getNumFaces() == 0);
    ASSERT(mesh.getNumVertices() == 0);
    ASSERT(mesh.addVertex(Vec3(0)) == 0);
    ASSERT(mesh.addVertex(Vec3(0, 1, 0)) == 1);
    ASSERT(mesh.addVertex(Vec3(0, 0, 1)) == 2);
    Array_<int> v;
    v.push_back(1);
    v.push_back(2);
    v.push_back(0);
    ASSERT(mesh.addFace(v) == 0);
    ASSERT(mesh.getNumFaces() == 1);
    ASSERT(mesh.getNumVertices() == 3);
    ASSERT(mesh.getFaceVertex(0, 0) == 1);
    ASSERT(mesh.getFaceVertex(0, 1) == 2);
    ASSERT(mesh.getFaceVertex(0, 2) == 0);
    ASSERT(mesh.getVertexPosition(0) == Vec3(0));
    ASSERT(mesh.getVertexPosition(1) == Vec3(0, 1, 0));
    ASSERT(mesh.getVertexPosition(2) == Vec3(0, 0, 1));

    // Make sure copy and assignment are shallow.
    PolygonalMesh mesh2(mesh); // shallow copy construction
    ASSERT(&mesh2.getImpl() == &mesh.getImpl());
    ASSERT(mesh.getImplHandleCount()==2);

    PolygonalMesh mesh3;
    mesh3 = mesh; // shallow assignment
    ASSERT(&mesh3.getImpl() == &mesh.getImpl());
    ASSERT(mesh.getImplHandleCount()==3);

    PolygonalMesh mesh4;
    mesh4.copyAssign(mesh); // deep copy
    ASSERT(mesh4.getNumVertices() == mesh.getNumVertices());
    ASSERT(&mesh4.getImpl() != &mesh.getImpl());
    ASSERT(mesh4.getImplHandleCount()==1);
    ASSERT(mesh.getImplHandleCount()==3);
}
void flexionFDSimulationWithHitMap(Model& model)
{
	addFlexionController(model);
	//addExtensionController(model);
	//addTibialLoads(model, 0);

    model.setUseVisualizer(true);

	// init system
	std::time_t result = std::time(nullptr);
	std::cout << "\nBefore initSystem() " << std::asctime(std::localtime(&result)) << endl;
	SimTK::State& si = model.initSystem();
	result = std::time(nullptr);
	std::cout << "\nAfter initSystem() " << std::asctime(std::localtime(&result)) << endl;
	
	// set gravity
	//model.updGravityForce().setGravityVector(si, Vec3(-9.80665,0,0));
	//model.updGravityForce().setGravityVector(si, Vec3(0,0,0));
	
	//setHipAngle(model, si, 90);
	//setKneeAngle(model, si, 0, false, false);
	//model.equilibrateMuscles( si);

	MultibodySystem& system = model.updMultibodySystem();
	SimbodyMatterSubsystem& matter = system.updMatterSubsystem();
	GeneralForceSubsystem forces(system);
	ContactTrackerSubsystem  tracker(system);
    CompliantContactSubsystem contactForces(system, tracker);
	contactForces.setTrackDissipatedEnergy(true);
    //contactForces.setTransitionVelocity(1e-3);

	for (int i=0; i < matter.getNumBodies(); ++i) {
		MobilizedBodyIndex mbx(i);
		if (i==19 || i==20 || i==22)// || i==15 || i==16)
		{
			MobilizedBody& mobod = matter.updMobilizedBody(mbx);
			std::filebuf fb;
			//cout << mobod.updBody().
			if (i==19)
				fb.open ( "../resources/femur_lat_r.obj",std::ios::in);
			else if (i==20)
				fb.open ( "../resources/femur_med_r.obj",std::ios::in);
			else if (i==22)
				fb.open ( "../resources/tibia_upper_r.obj",std::ios::in);
			//else if (i==15)
				//fb.open ( "../resources/meniscus_lat_r.obj",std::ios::in);
			//else if (i==16)
				//fb.open ( "../resources/meniscus_med_r.obj",std::ios::in);
			std::istream is(&fb);
			PolygonalMesh polMesh;
			polMesh.loadObjFile(is);
			fb.close();
			SimTK::ContactGeometry::TriangleMesh mesh(polMesh);
			ContactSurface contSurf;//(mesh, ContactMaterial(1.0e6, 1, 1, 0.03, 0.03), 0.001);
			if (i==19 || i==20 || i==22)
				contSurf = ContactSurface(mesh, ContactMaterial(10, 1, 1, 0.03, 0.03), 0.001);
			//else if (i==15 || i==16)
				//contSurf = ContactSurface(mesh, ContactMaterial(10, 3, 1, 0.03, 0.03), 0.001);
			DecorativeMesh showMesh(mesh.createPolygonalMesh());
			showMesh.setOpacity(0.5);
			mobod.updBody().addDecoration( showMesh);
			mobod.updBody().addContactSurface(contSurf);
		}
    }

	ModelVisualizer& viz(model.updVisualizer());
	//Visualizer viz(system);
	viz.updSimbodyVisualizer().addDecorationGenerator(new HitMapGenerator(system,contactForces));
    viz.updSimbodyVisualizer().setMode(Visualizer::RealTime);
    viz.updSimbodyVisualizer().setDesiredBufferLengthInSec(1);
    viz.updSimbodyVisualizer().setDesiredFrameRate(30);
    viz.updSimbodyVisualizer().setGroundHeight(-3);
    viz.updSimbodyVisualizer().setShowShadows(true);
	
    Visualizer::InputSilo* silo = new Visualizer::InputSilo();
	viz.updSimbodyVisualizer().addInputListener(silo);
    Array_<std::pair<String,int> > runMenuItems;
    runMenuItems.push_back(std::make_pair("Go", GoItem));
    runMenuItems.push_back(std::make_pair("Replay", ReplayItem));
    runMenuItems.push_back(std::make_pair("Quit", QuitItem));
    viz.updSimbodyVisualizer().addMenu("Run", RunMenuId, runMenuItems);

    Array_<std::pair<String,int> > helpMenuItems;
    helpMenuItems.push_back(std::make_pair("TBD - Sorry!", 1));
    viz.updSimbodyVisualizer().addMenu("Help", HelpMenuId, helpMenuItems);

    system.addEventReporter(new MyReporter(system,contactForces,ReportInterval));
	//system.addEventReporter(new Visualizer::Reporter(viz.updSimbodyVisualizer(), ReportInterval));
	
    // Check for a Run->Quit menu pick every <x> second.
	system.addEventHandler(new UserInputHandler(*silo, 0.001));

	system.realizeTopology();

	//Show ContactSurfaceIndex for each contact surface
  //  for (int i=0; i < matter.getNumBodies(); ++i) {
		//MobilizedBodyIndex mbx(i);
  //      const MobilizedBody& mobod = matter.getMobilizedBody(mbx);
  //      const int nsurfs = mobod.getBody().getNumContactSurfaces();
        //printf("mobod %d has %d contact surfaces\n", (int)mbx, nsurfs);
		////cout << "mobod with mass: " << (float)mobod.getBodyMass(si) << " has " << nsurfs << " contact surfaces" << endl;
		// //for (int i=0; i<nsurfs; ++i) {
  //          //printf("%2d: index %d\n", i, 
  //                 //(int)tracker.getContactSurfaceIndex(mbx,i)); 
  //      //}
  //  }

	//cout << "tracker num of surfaces: " << tracker.getNumSurfaces() << endl;

	//State state = system.getDefaultState();
	//viz.report(state);
	State& state = model.initializeState();
	viz.updSimbodyVisualizer().report(state);

	// Add reporters
    ForceReporter* forceReporter = new ForceReporter(&model);
    model.addAnalysis(forceReporter);

	CustomAnalysis* customReporter = new CustomAnalysis(&model, "r");
	model.addAnalysis(customReporter);

	// Create the integrator and manager for the simulation.
	SimTK::RungeKuttaMersonIntegrator integrator(model.getMultibodySystem());
	//SimTK::CPodesIntegrator integrator(model.getMultibodySystem());
	//integrator.setAccuracy(.01);
	//integrator.setAccuracy(1e-3);
	//integrator.setFixedStepSize(0.001);
	Manager manager(model, integrator);

	// Define the initial and final simulation times
	double initialTime = 0.0;
	double finalTime = 0.2;

	// Integrate from initial time to final time
	manager.setInitialTime(initialTime);
	manager.setFinalTime(finalTime);
	std::cout<<"\n\nIntegrating from "<<initialTime<<" to " <<finalTime<<std::endl;

	result = std::time(nullptr);
	std::cout << "\nBefore integrate(si) " << std::asctime(std::localtime(&result)) << endl;

	manager.integrate(state);

	result = std::time(nullptr);
	std::cout << "\nAfter integrate(si) " << std::asctime(std::localtime(&result)) << endl;

	// Save the simulation results
	Storage statesDegrees(manager.getStateStorage());
	statesDegrees.print("../outputs/states_flex.sto");
	model.updSimbodyEngine().convertRadiansToDegrees(statesDegrees);
	statesDegrees.setWriteSIMMHeader(true);
	statesDegrees.print("../outputs/states_degrees_flex.mot");
	// force reporter results
	forceReporter->getForceStorage().print("../outputs/force_reporter_flex.mot");
	//customReporter->print( "../outputs/custom_reporter_flex.mot");

	//cout << "You can choose 'Replay'" << endl;
	int menuId, item;
	unsigned int frameRate = 5;
	do { 
		cout << "Please choose 'Replay' or 'Quit'" << endl;
		viz.updInputSilo().waitForMenuPick(menuId, item);

        if (item != ReplayItem && item != QuitItem) 
            cout << "\aDude... follow instructions!\n";
		if (item == ReplayItem)
		{
			cout << "Type desired frame rate (integer) for playback and press Enter (default = 1) : ";
			//frameRate = cin.get();		
			cin >> frameRate;
			if (cin.fail()) 
			{
				cout << "Not an int. Setting default frame rate." << endl;
				cin.clear();
				cin.ignore(std::numeric_limits<int>::max(),'\n');
				frameRate = 1;
			}

			//cout << "saveEm size: " << saveEm.size() << endl;
			for (unsigned int i=0; i<saveEm.size(); i++)
			{
				viz.updSimbodyVisualizer().drawFrameNow(saveEm.getElt(i));
				if (frameRate == 0)
					frameRate = 1;
				usleep(1000000/frameRate);
			}
		}
	} while (menuId != RunMenuId || item != QuitItem);
}
ContactGeometry::TriangleMesh::Impl::Impl
   (const PolygonalMesh& mesh, bool smooth)
:   ContactGeometryImpl(), smooth(smooth)
{   // Create the mesh, triangulating faces as necessary.
    Array_<Vec3>    vertexPositions;
    Array_<int>     faceIndices;
    for (int i = 0; i < mesh.getNumVertices(); i++)
        vertexPositions.push_back(mesh.getVertexPosition(i));
    for (int i = 0; i < mesh.getNumFaces(); i++) {
        int numVert = mesh.getNumVerticesForFace(i);
        if (numVert < 3)
            continue; // Ignore it.
        if (numVert == 3) {
            faceIndices.push_back(mesh.getFaceVertex(i, 0));
            faceIndices.push_back(mesh.getFaceVertex(i, 1));
            faceIndices.push_back(mesh.getFaceVertex(i, 2));
        }
        else if (numVert == 4) {
            // Split it into two triangles.

            faceIndices.push_back(mesh.getFaceVertex(i, 0));
            faceIndices.push_back(mesh.getFaceVertex(i, 1));
            faceIndices.push_back(mesh.getFaceVertex(i, 2));
            faceIndices.push_back(mesh.getFaceVertex(i, 2));
            faceIndices.push_back(mesh.getFaceVertex(i, 3));
            faceIndices.push_back(mesh.getFaceVertex(i, 0));
        }
        else {
            // Add a vertex at the center, then split it into triangles.

            Vec3 center(0);
            for (int j = 0; j < numVert; j++)
                center += vertexPositions[mesh.getFaceVertex(i, j)];
            center /= numVert;
            vertexPositions.push_back(center);
            int newIndex = vertexPositions.size()-1;
            for (int j = 0; j < numVert-1; j++) {
                faceIndices.push_back(mesh.getFaceVertex(i, j));
                faceIndices.push_back(mesh.getFaceVertex(i, j+1));
                faceIndices.push_back(newIndex);
            }
            // Close the face (thanks, Alexandra Zobova).
            faceIndices.push_back(mesh.getFaceVertex(i, numVert-1));
            faceIndices.push_back(mesh.getFaceVertex(i, 0));
            faceIndices.push_back(newIndex);
        }
    }
    init(vertexPositions, faceIndices);

    // Make sure the mesh normals are oriented correctly.

    Vec3 origin(0);
    for (int i = 0; i < 3; i++)
        origin += vertices[faces[0].vertices[i]].pos;
    origin /= 3; // this is the face centroid

    const UnitVec3 direction = -faces[0].normal;
    // Calculate a ray origin that is guaranteed to be outside the
    // mesh. If the topology is right (face 0 normal points outward), we'll be
    // outside on the side containing face 0. If it is wrong, we'll be outside
    // on the opposite side of the mesh. Then we'll shoot a ray back along the
    // direction we came from (that is, towards the interior of the mesh from
    // outside). We'll hit *some* face. If the topology is right, the hit
    // face's normal will be pointing back at us. If it is wrong, the face
    // normal will also be pointing inwards, in roughly the same direction as
    // the ray.
    origin -= max(obb.bounds.getSize())*direction;
    Real distance;
    int face;
    Vec2 uv;
    bool intersects = intersectsRay(origin, direction, distance, face, uv);
    assert(intersects);
    // Now dot the hit face normal with the ray direction; correct topology
    // will have them pointing in more-or-less opposite directions.
    if (dot(faces[face].normal, direction) > 0) {
        // We need to invert the mesh topology.

        for (int i = 0; i < (int) faces.size(); i++) {
            Face& f = faces[i];
            int temp = f.vertices[0];
            f.vertices[0] = f.vertices[1];
            f.vertices[1] = temp;
            temp = f.edges[1];
            f.edges[1] = f.edges[2];
            f.edges[2] = temp;
            f.normal *= -1;
        }
        for (int i = 0; i < (int) vertices.size(); i++)
            vertices[i].normal *= -1;
    }
}
void VisualizerProtocol::drawPolygonalMesh(const PolygonalMesh& mesh, const Transform& X_GM, const Vec3& scale, const Vec4& color, int representation) {
    const void* impl = &mesh.getImpl();
    map<const void*, unsigned short>::const_iterator iter = meshes.find(impl);

    if (iter != meshes.end()) {
        // This mesh was already cached; just reference it by index number.
        drawMesh(X_GM, scale, color, (short)representation, iter->second, 0);
        return;
    }

    // This is a new mesh, so we need to send it to the visualizer. Build lists
    // of vertices and faces, triangulating as necessary.

    vector<float> vertices;
    vector<unsigned short> faces;
    for (int i = 0; i < mesh.getNumVertices(); i++) {
        Vec3 pos = mesh.getVertexPosition(i);
        vertices.push_back((float) pos[0]);
        vertices.push_back((float) pos[1]);
        vertices.push_back((float) pos[2]);
    }
    for (int i = 0; i < mesh.getNumFaces(); i++) {
        int numVert = mesh.getNumVerticesForFace(i);
        if (numVert < 3)
            continue; // Ignore it.
        if (numVert == 3) {
            faces.push_back((unsigned short) mesh.getFaceVertex(i, 0));
            faces.push_back((unsigned short) mesh.getFaceVertex(i, 1));
            faces.push_back((unsigned short) mesh.getFaceVertex(i, 2));
        }
        else if (numVert == 4) {
            // Split it into two triangles.

            faces.push_back((unsigned short) mesh.getFaceVertex(i, 0));
            faces.push_back((unsigned short) mesh.getFaceVertex(i, 1));
            faces.push_back((unsigned short) mesh.getFaceVertex(i, 2));
            faces.push_back((unsigned short) mesh.getFaceVertex(i, 2));
            faces.push_back((unsigned short) mesh.getFaceVertex(i, 3));
            faces.push_back((unsigned short) mesh.getFaceVertex(i, 0));
        }
        else {
            // Add a vertex at the center, then split it into triangles.

            Vec3 center(0);
            for (int j = 0; j < numVert; j++) {
                Vec3 pos = mesh.getVertexPosition(mesh.getFaceVertex(i,j));
                center += pos;
            }
            center /= numVert;
            vertices.push_back((float) center[0]);
            vertices.push_back((float) center[1]);
            vertices.push_back((float) center[2]);
            const unsigned newIndex = (unsigned)(vertices.size()/3-1);
            for (int j = 0; j < numVert-1; j++) {
                faces.push_back((unsigned short) mesh.getFaceVertex(i, j));
                faces.push_back((unsigned short) mesh.getFaceVertex(i, j+1));
                faces.push_back((unsigned short) newIndex);
            }
            // Close the face (thanks, Alexandra Zobova).
            faces.push_back((unsigned short) mesh.getFaceVertex(i, numVert-1));
            faces.push_back((unsigned short) mesh.getFaceVertex(i, 0));
            faces.push_back((unsigned short) newIndex);
        }
    }
    SimTK_ERRCHK1_ALWAYS(vertices.size() <= 65535*3, 
        "VisualizerProtocol::drawPolygonalMesh()",
        "Can't display a DecorativeMesh with more than 65535 vertices;"
        " received one with %llu.", (unsigned long long)vertices.size());
    SimTK_ERRCHK1_ALWAYS(faces.size() <= 65535*3, 
        "VisualizerProtocol::drawPolygonalMesh()",
        "Can't display a DecorativeMesh with more than 65535 vertices;"
        " received one with %llu.", (unsigned long long)faces.size());

    const int index = NumPredefinedMeshes + (int)meshes.size();
    SimTK_ERRCHK_ALWAYS(index <= 65535,
        "VisualizerProtocol::drawPolygonalMesh()",
        "Too many unique DecorativeMesh objects; max is 65535.");
    
    meshes[impl] = (unsigned short)index;    // insert new mesh
    WRITE(outPipe, &DefineMesh, 1);
    unsigned short numVertices = (unsigned short)(vertices.size()/3);
    unsigned short numFaces = (unsigned short)(faces.size()/3);
    WRITE(outPipe, &numVertices, sizeof(short));
    WRITE(outPipe, &numFaces, sizeof(short));
    WRITE(outPipe, &vertices[0], (unsigned)(vertices.size()*sizeof(float)));
    WRITE(outPipe, &faces[0], (unsigned)(faces.size()*sizeof(short)));

    drawMesh(X_GM, scale, color, (short) representation, (unsigned short)index, 0);
}
PolygonalMesh* Polygonizer::computeSurfaceNerLinear(float epsilon, float tau)
{
	bool ***isIn = new bool**[dimZ+1];
	float ***value = new float**[dimZ+1];
	for(int i=0; i<dimZ+1; i++){
		isIn[i] = new bool*[dimY+1];
		value[i] = new float*[dimY+1];

		for(int j=0; j<dimY+1; j++){
			isIn[i][j] = new bool[dimX+1];
			value[i][j] = new float[dimX+1];

			for(int k=0; k<dimX+1; k++){
				isIn[i][j][k] = false;
				value[i][j][k] = 0;
			}
		}
	}

	float o[3];
	o[0] = originX;
	o[1] = originY;
	o[2] = originZ;
	float space[3];
	space[0] = spaceX;
	space[1] = spaceY;
	space[2] = spaceZ;
	int dim[3];
	dim[0] = dimX;
	dim[1] = dimY;
	dim[2] = dimZ;

	func->asignValueToVoxels(value, isIn, o, space, dim);

	int ***index = new int**[dimZ+1];
	for(int i=0; i<dimZ+1; i++){
		index[i] = new int*[dimY+1];
		for(int j=0; j<dimY+1; j++){
			index[i][j] = new int[dimX+1];
			for(int k=0; k<dimX+1; k++)
				index[i][j][k] = -1;
		}
	}

	int current = 0;
	int face_N = 0;
	for(int i=0; i<dimZ; i++)
		for(int j=0; j<dimY; j++)
			for(int k=0; k<dimX-1; k++){
				if(!isIn[i][j][k] || !isIn[i][j][k+1])
					continue;
				if((value[i][j][k] > 0 && value[i][j][k+1] <= 0) || 
				    (value[i][j][k] <= 0 && value[i][j][k+1] > 0)){
					face_N++;
					if(index[i][j][k+1] < 0){
						index[i][j][k+1] = current;
						current++;
					}
					if(index[i][j+1][k+1] < 0){
						index[i][j+1][k+1] = current;
						current++;
					}
					if(index[i+1][j][k+1] < 0){
						index[i+1][j][k+1] = current;
						current++;
					}
					if(index[i+1][j+1][k+1] < 0){
						index[i+1][j+1][k+1] = current;
						current++;
					}
				}
			}

	for(int i=0; i<dimX; i++)
		for(int j=0; j<dimZ; j++)
			for(int k=0; k<dimY-1; k++){
				if(!isIn[j][k][i] || !isIn[j][k+1][i])
					continue;
				if((value[j][k][i] > 0 && value[j][k+1][i] <= 0) || 
				    (value[j][k][i] <= 0&& value[j][k+1][i] > 0)){
					face_N++;
					if(index[j][k+1][i] < 0){
						index[j][k+1][i] = current;
						current++;
					}
					if(index[j+1][k+1][i] < 0){
						index[j+1][k+1][i] = current;
						current++;
					}
					if(index[j][k+1][i+1] < 0){
						index[j][k+1][i+1] = current;
						current++;
					}
					if(index[j+1][k+1][i+1] < 0){
						index[j+1][k+1][i+1] = current;
						current++;
					}
				}
			}

	for(int i=0; i<dimY; i++)
		for(int j=0; j<dimX; j++)
			for(int k=0; k<dimZ-1; k++){
				if(!isIn[k][i][j] || !isIn[k+1][i][j])
					continue;
				if((value[k][i][j] > 0  && value[k+1][i][j] <= 0) || 
				    (value[k][i][j] <= 0 && value[k+1][i][j] > 0)){
					face_N++;
					if(index[k+1][i][j] < 0){
						index[k+1][i][j] = current;
						current++;
					}
					if(index[k+1][i+1][j] < 0){
						index[k+1][i+1][j] = current;
						current++;
					}
					if(index[k+1][i][j+1] < 0){
						index[k+1][i][j+1] = current;
						current++;
					}
					if(index[k+1][i+1][j+1] < 0){
						index[k+1][i+1][j+1] = current;
						current++;
					}
				}
			}

	PolygonalMesh* mesh = new PolygonalMesh;
	int vertex_N = current;
	mesh->setVertexCount(vertex_N);
	float (*vertex)[3] = mesh->vertex;
	int* degree = mesh->degree_f = new int[vertex_N];
	current = 0;
	for(int i=0; i<vertex_N; i++){
		vertex[i][0] = vertex[i][1] = vertex[i][2] = 0;
		degree[i] = 0;
	}

	mesh->setFaceCount(face_N);
	double (*Q)[10] = new double[vertex_N][10];
	for(int i=0; i<vertex_N; i++)
		MAT_INIT(Q[i]);
	for(int i=0; i<face_N; i++)
		mesh->setPolygonCount(i, 4);
	face_N = 0;
	int **face = mesh->face;
	bool flag = false;
	for(int i=0; i<dimZ; i++)
		for(int j=0; j<dimY; j++)
			for(int k=0; k<dimX-1; k++){
				if(!isIn[i][j][k] || !isIn[i][j][k+1])
					continue;
				if(value[i][j][k] > 0 && value[i][j][k+1] <= 0){
					face[face_N][0] = index[i][j][k+1];
					face[face_N][1] = index[i][j+1][k+1];
					face[face_N][2] = index[i+1][j+1][k+1];
					face[face_N][3] = index[i+1][j][k+1];
					face_N++;
					flag = true;
				}
				else if(value[i][j][k] <= 0 && value[i][j][k+1] > 0){
					face[face_N][0] = index[i][j][k+1];
					face[face_N][1] = index[i+1][j][k+1];
					face[face_N][2] = index[i+1][j+1][k+1];
					face[face_N][3] = index[i][j+1][k+1];
					face_N++;
					flag = true;
				}
				if(!flag)
					continue;
				flag = false;
				float p[3], s[3], e[3];
				s[0] = originX + k*spaceX;
				e[0] = originX + (k+1)*spaceX;
				s[1] = e[1] = originY + j*spaceY;
				s[2] = e[2] = originZ + i*spaceZ;
				float f1 = value[i][j][k];
				float f2 = value[i][j][k+1];
				searchZero(p, s, e, f1, f2, epsilon);
				
				float g[3];
				//func->gradient(g, p[0], p[1], p[2]);
				double len = PolygonalMesh::LENGTH(g);
			
				double nor[3];
				nor[0] = g[0]/len;
				nor[1] = g[1]/len;
				nor[2] = g[2]/len;

				double d = -PolygonalMesh::DOT(nor, p);
				double Q_tmp[10];
				MATRIX(Q_tmp, nor, d);

				int i0 = index[i][j][k+1];
				MAT_SUM(Q[i0], Q_tmp);
				vertex[i0][0] += p[0];
				vertex[i0][1] += p[1];
				vertex[i0][2] += p[2];
				degree[i0]++;

				i0 = index[i][j+1][k+1];
				MAT_SUM(Q[i0], Q_tmp);
				vertex[i0][0] += p[0];
				vertex[i0][1] += p[1];
				vertex[i0][2] += p[2];
				degree[i0]++;

				i0 = index[i+1][j+1][k+1];
				MAT_SUM(Q[i0], Q_tmp);
				vertex[i0][0] += p[0];
				vertex[i0][1] += p[1];
				vertex[i0][2] += p[2];
				degree[i0]++;

				i0 = index[i+1][j][k+1];
				MAT_SUM(Q[i0], Q_tmp);
				vertex[i0][0] += p[0];
				vertex[i0][1] += p[1];
				vertex[i0][2] += p[2];
				degree[i0]++;
			}

	for(int i=0; i<dimX; i++)
		for(int j=0; j<dimZ; j++)
			for(int k=0; k<dimY-1; k++){
				if(!isIn[j][k][i] || !isIn[j][k+1][i])
					continue;
				if(value[j][k][i] > 0 && value[j][k+1][i] <= 0){
					face[face_N][0] = index[j][k+1][i];
					face[face_N][1] = index[j+1][k+1][i];
					face[face_N][2] = index[j+1][k+1][i+1];
					face[face_N][3] = index[j][k+1][i+1];
					face_N++;
					flag = true;
				}
				else if(value[j][k][i] <= 0 && value[j][k+1][i] > 0){
					face[face_N][0] = index[j][k+1][i];
					face[face_N][1] = index[j][k+1][i+1];
					face[face_N][2] = index[j+1][k+1][i+1];
					face[face_N][3] = index[j+1][k+1][i];
					face_N++;
					flag = true;
				}
				if(!flag)
					continue;
				flag = false;
				float p[3], s[3], e[3];
				s[1] = originY + k*spaceY;
				e[1] = originY + (k+1)*spaceY;
				s[2] = e[2] = originZ + j*spaceZ;
				s[0] = e[0] = originX + i*spaceX;
				float f1 = value[j][k][i];
				float f2 = value[j][k+1][i];
				searchZero(p, s, e, f1, f2, epsilon);
				
				float g[3];
				//func->gradient(g, p[0], p[1], p[2]);
				double len = PolygonalMesh::LENGTH(g);
			
				double nor[3];
				nor[0] = g[0]/len;
				nor[1] = g[1]/len;
				nor[2] = g[2]/len;

				double d = -PolygonalMesh::DOT(nor, p);
				double Q_tmp[10];
				MATRIX(Q_tmp, nor, d);
				
				int i0 = index[j][k+1][i];
				MAT_SUM(Q[i0], Q_tmp);
				vertex[i0][0] += p[0];
				vertex[i0][1] += p[1];
				vertex[i0][2] += p[2];
				degree[i0]++;

				i0 = index[j+1][k+1][i];
				MAT_SUM(Q[i0], Q_tmp);
				vertex[i0][0] += p[0];
				vertex[i0][1] += p[1];
				vertex[i0][2] += p[2];
				degree[i0]++;

				i0 = index[j+1][k+1][i+1];
				MAT_SUM(Q[i0], Q_tmp);
				vertex[i0][0] += p[0];
				vertex[i0][1] += p[1];
				vertex[i0][2] += p[2];
				degree[i0]++;

				i0 = index[j][k+1][i+1];
				MAT_SUM(Q[i0], Q_tmp);
				vertex[i0][0] += p[0];
				vertex[i0][1] += p[1];
				vertex[i0][2] += p[2];
				degree[i0]++;
			}

	for(int i=0; i<dimY; i++)
		for(int j=0; j<dimX; j++)
			for(int k=0; k<dimZ-1; k++){
				if(!isIn[k][i][j] || !isIn[k+1][i][j])
					continue;
				if(value[k][i][j] > 0 && value[k+1][i][j] <= 0){
					face[face_N][0] = index[k+1][i][j];
					face[face_N][1] = index[k+1][i][j+1];
					face[face_N][2] = index[k+1][i+1][j+1];
					face[face_N][3] = index[k+1][i+1][j];
					face_N++;
					flag = true;
				}
				else if(value[k][i][j] <= 0 && value[k+1][i][j] > 0){
					face[face_N][0] = index[k+1][i][j];
					face[face_N][1] = index[k+1][i+1][j];
					face[face_N][2] = index[k+1][i+1][j+1];
					face[face_N][3] = index[k+1][i][j+1];
					face_N++;
					flag = true;
				}
				if(!flag)
					continue;
				flag = false;
				float p[3], s[3], e[3];
				s[2] = originZ + k*spaceZ;
				e[2] = originZ + (k+1)*spaceZ;
				s[0] = e[0] = originX + j*spaceX;
				s[1] = e[1] = originY + i*spaceY;
				float f1 = value[k][i][j];
				float f2 = value[k+1][i][j];
				searchZero(p, s, e, f1, f2, epsilon);
				
				float g[3];
				//func->gradient(g, p[0], p[1], p[2]);
				double len = PolygonalMesh::LENGTH(g);
				
				double nor[3];
				nor[0] = g[0]/len;
				nor[1] = g[1]/len;
				nor[2] = g[2]/len;

				double d = -PolygonalMesh::DOT(nor, p);
				double Q_tmp[10];
				MATRIX(Q_tmp, nor, d);

				int i0 = index[k+1][i][j];
				MAT_SUM(Q[i0], Q_tmp);
				vertex[i0][0] += p[0];
				vertex[i0][1] += p[1];
				vertex[i0][2] += p[2];
				degree[i0]++;

				i0 = index[k+1][i][j+1];
				MAT_SUM(Q[i0], Q_tmp);
				vertex[i0][0] += p[0];
				vertex[i0][1] += p[1];
				vertex[i0][2] += p[2];
				degree[i0]++;

				i0 = index[k+1][i+1][j+1];
				MAT_SUM(Q[i0], Q_tmp);
				vertex[i0][0] += p[0];
				vertex[i0][1] += p[1];
				vertex[i0][2] += p[2];
				degree[i0]++;

				i0 = index[k+1][i+1][j];
				MAT_SUM(Q[i0], Q_tmp);
				vertex[i0][0] += p[0];
				vertex[i0][1] += p[1];
				vertex[i0][2] += p[2];
				degree[i0]++;
			}
	
	//FOR SVD
			
  vnl_matrix< float > A( 3, 3, 0. ); 
  vnl_vector<float> b( 3, 0. );

	for(int i=0; i<vertex_N; i++){
		if(degree[i] == 0)
			continue;
		vertex[i][0] /= degree[i];
		vertex[i][1] /= degree[i];
		vertex[i][2] /= degree[i];
continue;
		A[0][0] = (float)Q[i][0];
		A[1][0] = A[0][1] = (float)Q[i][1];
		A[2][0] = A[0][2] = (float)Q[i][2];
		A[1][1] = (float)Q[i][3];
		A[1][2] = A[2][1] = (float)Q[i][4];
		A[2][2] = (float)Q[i][5];

		float Av[3];
		MAT_BY_VEC(Av, Q[i], vertex[i]);
		b[1] = -(float)Q[i][6] - Av[0];
		b[2] = -(float)Q[i][7] - Av[1];
		b[3] = -(float)Q[i][8] - Av[2];

    vnl_svd<float> svd( A );
    svd.zero_out_absolute( tau );

    vnl_vector< float > x = svd.solve( b );

		if(fabs(x[1]) > spaceX || fabs(x[2]) > spaceY || fabs(x[3]) > spaceZ)
			continue;

		mesh->vertex[i][0] += x[1];
		mesh->vertex[i][1] += x[2];
		mesh->vertex[i][2] += x[3];
	}

	for(int i=0; i<dimZ+1; i++){
		for(int j=0; j<dimY+1; j++){
			delete[] isIn[i][j];
			delete[] index[i][j];
			delete[] value[i][j];
		}
		delete[] isIn[i];
		delete[] index[i];
		delete[] value[i];
	}
	delete[] isIn;
	delete[] index;
	delete[] Q;
	delete[] value;

	return mesh;
}
Beispiel #9
0
int main() {
  try
  { std::cout << "Current working directory: " 
              << Pathname::getCurrentWorkingDirectory() << std::endl;

    // Create the system.
    
    MultibodySystem         system; system.setUseUniformBackground(true);
    SimbodyMatterSubsystem  matter(system);
    GeneralForceSubsystem   forces(system);
    Force::UniformGravity   gravity(forces, matter, 0*Vec3(2, -9.8, 0));

    ContactTrackerSubsystem  tracker(system);
    CompliantContactSubsystem contactForces(system, tracker);
    contactForces.setTrackDissipatedEnergy(true);

    GeneralContactSubsystem OLDcontact(system);
    const ContactSetIndex OLDcontactSet = OLDcontact.createContactSet();

    contactForces.setTransitionVelocity(1e-3);

    std::ifstream meshFile1, meshFile2;
    PolygonalMesh femurMesh; 
    meshFile1.open("ContactBigMeshes_Femur.obj"); 
    femurMesh.loadObjFile(meshFile1); meshFile1.close();
    PolygonalMesh patellaMesh; 
    meshFile2.open("ContactBigMeshes_Patella.obj"); 
    patellaMesh.loadObjFile(meshFile2); meshFile2.close();

    ContactGeometry::TriangleMesh femurTri(femurMesh);
    ContactGeometry::TriangleMesh patellaTri(patellaMesh);

    DecorativeMesh showFemur(femurTri.createPolygonalMesh());
    Array_<DecorativeLine> femurNormals;
    const Real NormalLength = .02;
    //for (int fx=0; fx < femurTri.getNumFaces(); ++fx)
    //    femurNormals.push_back(
    //    DecorativeLine(femurTri.findCentroid(fx),
    //                   femurTri.findCentroid(fx)
    //                       + NormalLength*femurTri.getFaceNormal(fx)));

    DecorativeMesh showPatella(patellaTri.createPolygonalMesh());
    Array_<DecorativeLine> patellaNormals;
    //for (int fx=0; fx < patellaTri.getNumFaces(); ++fx)
    //    patellaNormals.push_back(
    //    DecorativeLine(patellaTri.findCentroid(fx),
    //                   patellaTri.findCentroid(fx)
    //                       + NormalLength*patellaTri.getFaceNormal(fx)));

    // This transform has the meshes close enough that their OBBs overlap
    // but in the end none of the faces are touching.
    const Transform X_FP(
        Rotation(Mat33( 0.97107625831404454, 0.23876955530133021, 0,
                       -0.23876955530133021, 0.97107625831404454, 0,
                        0,                   0,                   1), true),
        Vec3(0.057400580865008571, 0.43859170879135373, 
             -0.00016506240185135300)
        );


    const Real fFac =1; // to turn off friction
    const Real fDis = .5*0.2; // to turn off dissipation
    const Real fVis =  .1*.1; // to turn off viscous friction
    const Real fK = 100*1e6; // pascals

    // Put femur on ground at origin
    matter.Ground().updBody().addDecoration(Vec3(0,0,0),
        showFemur.setColor(Cyan).setOpacity(.2));
    matter.Ground().updBody().addContactSurface(Vec3(0,0,0),
        ContactSurface(femurTri,
            ContactMaterial(fK*.01,fDis*.9,fFac*.8,fFac*.7,fVis*10),
            .01 /*thickness*/));


    Body::Rigid patellaBody(MassProperties(1.0, Vec3(0), Inertia(1)));
    patellaBody.addDecoration(Transform(), 
        showPatella.setColor(Red).setOpacity(.2));
    patellaBody.addContactSurface(Transform(),
        ContactSurface(patellaTri,
            ContactMaterial(fK*.001,fDis*.9,fFac*.8,fFac*.7,fVis*10),
            .01 /*thickness*/));

    MobilizedBody::Free patella(matter.Ground(), Transform(Vec3(0)), 
                                patellaBody,    Transform(Vec3(0)));


    //// The old way ...
    //OLDcontact.addBody(OLDcontactSet, ball,
    //    pyramid, Transform());

    //OLDcontact.addBody(OLDcontactSet, matter.updGround(),
    //    ContactGeometry::HalfSpace(), Transform(R_xdown, Vec3(0,-3,0)));
    //ElasticFoundationForce ef(forces, OLDcontact, OLDcontactSet);
    //Real stiffness = 1e6, dissipation = 0.01, us = 0.1, 
    //    ud = 0.05, uv = 0.01, vt = 0.01;
    ////Real stiffness = 1e6, dissipation = 0.1, us = 0.8, 
    ////    ud = 0.7, uv = 0.01, vt = 0.01;

    //ef.setBodyParameters(ContactSurfaceIndex(0), 
    //    stiffness, dissipation, us, ud, uv);
    //ef.setTransitionVelocity(vt);
    //// end of old way.

    Visualizer viz(system);
    Visualizer::Reporter& reporter = *new Visualizer::Reporter(viz, ReportInterval);
    viz.addDecorationGenerator(new ForceArrowGenerator(system,contactForces));
    MyReporter& myRep = *new MyReporter(system,contactForces,ReportInterval);

    system.addEventReporter(&myRep);
    system.addEventReporter(&reporter);

    // Initialize the system and state.
    
    system.realizeTopology();
    State state = system.getDefaultState();

    viz.report(state);
    printf("Reference state -- hit ENTER\n");
    cout << "t=" << state.getTime() 
         << " q=" << patella.getQAsVector(state)  
         << " u=" << patella.getUAsVector(state)  
         << endl;
    char c=getchar();

    patella.setQToFitTransform(state, ~X_FP);
    viz.report(state);
    printf("Initial state -- hit ENTER\n");
    cout << "t=" << state.getTime() 
         << " q=" << patella.getQAsVector(state)  
         << " u=" << patella.getUAsVector(state)  
         << endl;
    c=getchar();
    
    // Simulate it.
    const clock_t start = clock();

    RungeKutta3Integrator integ(system);
    TimeStepper ts(system, integ);
    ts.initialize(state);
    ts.stepTo(2.0);

    const double timeInSec = (double)(clock()-start)/CLOCKS_PER_SEC;
    const int evals = integ.getNumRealizations();
    cout << "Done -- took " << integ.getNumStepsTaken() << " steps in " <<
        timeInSec << "s for " << ts.getTime() << "s sim (avg step=" 
        << (1000*ts.getTime())/integ.getNumStepsTaken() << "ms) " 
        << (1000*ts.getTime())/evals << "ms/eval\n";

    printf("Using Integrator %s at accuracy %g:\n", 
        integ.getMethodName(), integ.getAccuracyInUse());
    printf("# STEPS/ATTEMPTS = %d/%d\n", integ.getNumStepsTaken(), integ.getNumStepsAttempted());
    printf("# ERR TEST FAILS = %d\n", integ.getNumErrorTestFailures());
    printf("# REALIZE/PROJECT = %d/%d\n", integ.getNumRealizations(), integ.getNumProjections());


    while(true) {
        for (int i=0; i < (int)saveEm.size(); ++i) {
            viz.report(saveEm[i]);
        }
        getchar();
    }

  } catch (const std::exception& e) {
    std::printf("EXCEPTION THROWN: %s\n", e.what());
    exit(1);

  } catch (...) {
    std::printf("UNKNOWN EXCEPTION THROWN\n");
    exit(1);
  }

    return 0;
}
PolygonalMesh* Polygonizer::computeSurfaceNetSIG02(float epsilon, float tau)
{
	float p[3];
	bool ***isIn = new bool**[dimZ+1];
	bool ***isValid = new bool**[dimZ+1];
	for(int i=0; i<dimZ+1; i++){
		isIn[i] = new bool*[dimY+1];
		isValid[i] = new bool*[dimY+1];
		p[2] = originZ + i*spaceZ;
		for(int j=0; j<dimY+1; j++){
			isIn[i][j] = new bool[dimX+1];
			isValid[i][j] = new bool[dimX+1];
			p[1] = originY + j*spaceY;
			for(int k=0; k<dimX+1; k++){
				p[0] = originX + k*spaceX;
				isIn[i][j][k] 
					= (func->value(p[0], p[1], p[2], isValid[i][j][k]) > 0);
			}
		}
	}

	int ***index = new int**[dimZ+1];
	for(int i=0; i<dimZ+1; i++){
		index[i] = new int*[dimY+1];
		for(int j=0; j<dimY+1; j++){
			index[i][j] = new int[dimX+1];
			for(int k=0; k<dimX+1; k++)
				index[i][j][k] = -1;
		}
	}

	int current = 0;
	int face_N = 0;
	for(int i=0; i<dimZ; i++)
		for(int j=0; j<dimY; j++)
			for(int k=0; k<dimX-1; k++){
				if(!isValid[i][j][k] || !isValid[i][j][k+1])
					continue;
				if((!isIn[i][j][k] && isIn[i][j][k+1]) || 
				    (isIn[i][j][k] && !isIn[i][j][k+1])){
					face_N++;
					if(index[i][j][k+1] < 0){
						index[i][j][k+1] = current;
						current++;
					}
					if(index[i][j+1][k+1] < 0){
						index[i][j+1][k+1] = current;
						current++;
					}
					if(index[i+1][j][k+1] < 0){
						index[i+1][j][k+1] = current;
						current++;
					}
					if(index[i+1][j+1][k+1] < 0){
						index[i+1][j+1][k+1] = current;
						current++;
					}
				}
			}

	for(int i=0; i<dimX; i++)
		for(int j=0; j<dimZ; j++)
			for(int k=0; k<dimY-1; k++){
				if(!isValid[j][k][i] || !isValid[j][k+1][i])
					continue;
				if((!isIn[j][k][i] && isIn[j][k+1][i]) || 
				    (isIn[j][k][i] && !isIn[j][k+1][i])){
					face_N++;
					if(index[j][k+1][i] < 0){
						index[j][k+1][i] = current;
						current++;
					}
					if(index[j+1][k+1][i] < 0){
						index[j+1][k+1][i] = current;
						current++;
					}
					if(index[j][k+1][i+1] < 0){
						index[j][k+1][i+1] = current;
						current++;
					}
					if(index[j+1][k+1][i+1] < 0){
						index[j+1][k+1][i+1] = current;
						current++;
					}
				}
			}

	for(int i=0; i<dimY; i++)
		for(int j=0; j<dimX; j++)
			for(int k=0; k<dimZ-1; k++){
				if(!isValid[k][i][j] || !isValid[k+1][i][j])
					continue;
				if((!isIn[k][i][j] && isIn[k+1][i][j]) || 
				    (isIn[k][i][j] && !isIn[k+1][i][j])){
					face_N++;
					if(index[k+1][i][j] < 0){
						index[k+1][i][j] = current;
						current++;
					}
					if(index[k+1][i+1][j] < 0){
						index[k+1][i+1][j] = current;
						current++;
					}
					if(index[k+1][i][j+1] < 0){
						index[k+1][i][j+1] = current;
						current++;
					}
					if(index[k+1][i+1][j+1] < 0){
						index[k+1][i+1][j+1] = current;
						current++;
					}
				}
			}
	
	PolygonalMesh* mesh = new PolygonalMesh;
	int vertex_N = current;
	mesh->setVertexCount(vertex_N);
	float (*vertex)[3] = mesh->vertex;
	int* degree = mesh->degree_f = new int[vertex_N];
	current = 0;
	for(int i=0; i<vertex_N; i++){
		vertex[i][0] = vertex[i][1] = vertex[i][2] = 0;
		degree[i] = 0;
	}
	/*
	for(i=0; i<dimZ+1; i++)
		for(int j=0; j<dimY+1; j++)
			for(int k=0; k<dimX+1; k++)
				if(index[i][j][k] >= 0){
					index[i][j][k] = current;
					vertex[current][0] = spaceX*((float)k-0.5f) + originX;
					vertex[current][1] = spaceY*((float)j-0.5f) + originY;
					vertex[current][2] = spaceZ*((float)i-0.5f) + originZ;
					current++;
				}
				*/


	mesh->setFaceCount(face_N);
	double (*Q)[10] = new double[vertex_N][10];
	for(int i=0; i<vertex_N; i++)
		MAT_INIT(Q[i]);
	for(int i=0; i<face_N; i++)
		mesh->setPolygonCount(i, 4);
	face_N = 0;
	int **face = mesh->face;
	bool flag = false;
	for(int i=0; i<dimZ; i++)
		for(int j=0; j<dimY; j++)
			for(int k=0; k<dimX-1; k++){
				if(!isValid[i][j][k] || !isValid[i][j][k+1])
					continue;
				if(isIn[i][j][k] && !isIn[i][j][k+1]){
					face[face_N][0] = index[i][j][k+1];
					face[face_N][1] = index[i][j+1][k+1];
					face[face_N][2] = index[i+1][j+1][k+1];
					face[face_N][3] = index[i+1][j][k+1];
					face_N++;
					flag = true;
				}
				else if(!isIn[i][j][k] && isIn[i][j][k+1]){
					face[face_N][0] = index[i][j][k+1];
					face[face_N][1] = index[i+1][j][k+1];
					face[face_N][2] = index[i+1][j+1][k+1];
					face[face_N][3] = index[i][j+1][k+1];
					face_N++;
					flag = true;
				}
				if(!flag)
					continue;
				flag = false;
				float p[3], s[3], e[3];
				s[0] = originX + k*spaceX;
				e[0] = originX + (k+1)*spaceX;
				s[1] = e[1] = originY + j*spaceY;
				s[2] = e[2] = originZ + i*spaceZ;
				bisection(p, s, e, epsilon);
				
				float g[3];
				func->gradient(g, p[0], p[1], p[2]);
				double len = PolygonalMesh::LENGTH(g);
				//if((float)len == 0)
					//continue;
				double nor[3];
				nor[0] = g[0]/len;
				nor[1] = g[1]/len;
				nor[2] = g[2]/len;

				double d = -PolygonalMesh::DOT(nor, p);
				double Q_tmp[10];
				MATRIX(Q_tmp, nor, d);

				int i0 = index[i][j][k+1];
				MAT_SUM(Q[i0], Q_tmp);
				vertex[i0][0] += p[0];
				vertex[i0][1] += p[1];
				vertex[i0][2] += p[2];
				degree[i0]++;

				i0 = index[i][j+1][k+1];
				MAT_SUM(Q[i0], Q_tmp);
				vertex[i0][0] += p[0];
				vertex[i0][1] += p[1];
				vertex[i0][2] += p[2];
				degree[i0]++;

				i0 = index[i+1][j+1][k+1];
				MAT_SUM(Q[i0], Q_tmp);
				vertex[i0][0] += p[0];
				vertex[i0][1] += p[1];
				vertex[i0][2] += p[2];
				degree[i0]++;

				i0 = index[i+1][j][k+1];
				MAT_SUM(Q[i0], Q_tmp);
				vertex[i0][0] += p[0];
				vertex[i0][1] += p[1];
				vertex[i0][2] += p[2];
				degree[i0]++;
			}

	for(int i=0; i<dimX; i++)
		for(int j=0; j<dimZ; j++)
			for(int k=0; k<dimY-1; k++){
				if(!isValid[j][k][i] || !isValid[j][k+1][i])
					continue;
				if(isIn[j][k][i] && !isIn[j][k+1][i]){
					face[face_N][0] = index[j][k+1][i];
					face[face_N][1] = index[j+1][k+1][i];
					face[face_N][2] = index[j+1][k+1][i+1];
					face[face_N][3] = index[j][k+1][i+1];
					face_N++;
					flag = true;
				}
				else if(!isIn[j][k][i] && isIn[j][k+1][i]){
					face[face_N][0] = index[j][k+1][i];
					face[face_N][1] = index[j][k+1][i+1];
					face[face_N][2] = index[j+1][k+1][i+1];
					face[face_N][3] = index[j+1][k+1][i];
					face_N++;
					flag = true;
				}
				if(!flag)
					continue;
				flag = false;
				float p[3], s[3], e[3];
				s[1] = originY + k*spaceY;
				e[1] = originY + (k+1)*spaceY;
				s[2] = e[2] = originZ + j*spaceZ;
				s[0] = e[0] = originX + i*spaceX;
				bisection(p, s, e, epsilon);
				
				float g[3];
				func->gradient(g, p[0], p[1], p[2]);
				double len = PolygonalMesh::LENGTH(g);
				//if((float)len == 0)
					//continue;
				double nor[3];
				nor[0] = g[0]/len;
				nor[1] = g[1]/len;
				nor[2] = g[2]/len;

				double d = -PolygonalMesh::DOT(nor, p);
				double Q_tmp[10];
				MATRIX(Q_tmp, nor, d);
				
				int i0 = index[j][k+1][i];
				MAT_SUM(Q[i0], Q_tmp);
				vertex[i0][0] += p[0];
				vertex[i0][1] += p[1];
				vertex[i0][2] += p[2];
				degree[i0]++;

				i0 = index[j+1][k+1][i];
				MAT_SUM(Q[i0], Q_tmp);
				vertex[i0][0] += p[0];
				vertex[i0][1] += p[1];
				vertex[i0][2] += p[2];
				degree[i0]++;

				i0 = index[j+1][k+1][i+1];
				MAT_SUM(Q[i0], Q_tmp);
				vertex[i0][0] += p[0];
				vertex[i0][1] += p[1];
				vertex[i0][2] += p[2];
				degree[i0]++;

				i0 = index[j][k+1][i+1];
				MAT_SUM(Q[i0], Q_tmp);
				vertex[i0][0] += p[0];
				vertex[i0][1] += p[1];
				vertex[i0][2] += p[2];
				degree[i0]++;
			}

	for(int i=0; i<dimY; i++)
		for(int j=0; j<dimX; j++)
			for(int k=0; k<dimZ-1; k++){
				if(!isValid[k][i][j] || !isValid[k+1][i][j])
					continue;
				if(isIn[k][i][j] && !isIn[k+1][i][j]){
					face[face_N][0] = index[k+1][i][j];
					face[face_N][1] = index[k+1][i][j+1];
					face[face_N][2] = index[k+1][i+1][j+1];
					face[face_N][3] = index[k+1][i+1][j];
					face_N++;
					flag = true;
				}
				else if(!isIn[k][i][j] && isIn[k+1][i][j]){
					face[face_N][0] = index[k+1][i][j];
					face[face_N][1] = index[k+1][i+1][j];
					face[face_N][2] = index[k+1][i+1][j+1];
					face[face_N][3] = index[k+1][i][j+1];
					face_N++;
					flag = true;
				}
				if(!flag)
					continue;
				flag = false;
				float p[3], s[3], e[3];
				s[2] = originZ + k*spaceZ;
				e[2] = originZ + (k+1)*spaceZ;
				s[0] = e[0] = originX + j*spaceX;
				s[1] = e[1] = originY + i*spaceY;
				bisection(p, s, e, epsilon);
				
				float g[3];
				func->gradient(g, p[0], p[1], p[2]);
				double len = PolygonalMesh::LENGTH(g);
				//if((float)len == 0)
					//continue;
				double nor[3];
				nor[0] = g[0]/len;
				nor[1] = g[1]/len;
				nor[2] = g[2]/len;

				double d = -PolygonalMesh::DOT(nor, p);
				double Q_tmp[10];
				MATRIX(Q_tmp, nor, d);

				int i0 = index[k+1][i][j];
				MAT_SUM(Q[i0], Q_tmp);
				vertex[i0][0] += p[0];
				vertex[i0][1] += p[1];
				vertex[i0][2] += p[2];
				degree[i0]++;

				i0 = index[k+1][i][j+1];
				MAT_SUM(Q[i0], Q_tmp);
				vertex[i0][0] += p[0];
				vertex[i0][1] += p[1];
				vertex[i0][2] += p[2];
				degree[i0]++;

				i0 = index[k+1][i+1][j+1];
				MAT_SUM(Q[i0], Q_tmp);
				vertex[i0][0] += p[0];
				vertex[i0][1] += p[1];
				vertex[i0][2] += p[2];
				degree[i0]++;

				i0 = index[k+1][i+1][j];
				MAT_SUM(Q[i0], Q_tmp);
				vertex[i0][0] += p[0];
				vertex[i0][1] += p[1];
				vertex[i0][2] += p[2];
				degree[i0]++;
			}
	
	//FOR SVD
			
	vnl_matrix< float > A( 3, 3, 0. ); 
	vnl_vector< float > b(3, 0.), x(3, 0.);

	for(int i=0; i<vertex_N; i++){
		if(degree[i] == 0)
			continue;
		vertex[i][0] /= degree[i];
		vertex[i][1] /= degree[i];
		vertex[i][2] /= degree[i];
continue;
		A[0][0] = (float)Q[i][0];
		A[1][0] = A[0][1] = (float)Q[i][1];
		A[2][0] = A[0][2] = (float)Q[i][2];
		A[1][1] = (float)Q[i][3];
		A[1][2] = A[2][1] = (float)Q[i][4];
		A[2][2] = (float)Q[i][5];

		float Av[3];
		MAT_BY_VEC(Av, Q[i], vertex[i]);
		b[0] = -(float)Q[i][6] - Av[0];
		b[1] = -(float)Q[i][7] - Av[1];
		b[2] = -(float)Q[i][8] - Av[2];

    vnl_svd<float> svd( A );
    svd.zero_out_absolute( 0.0000001 );

    x = svd.solve( b );

    if(fabs(x[1]) > spaceX || fabs(x[2]) > spaceY || fabs(x[3]) > spaceZ)
			continue;

		mesh->vertex[i][0] += x[1];
		mesh->vertex[i][1] += x[2];
		mesh->vertex[i][2] += x[3];
	}

	for(int i=0; i<dimZ+1; i++){
		for(int j=0; j<dimY+1; j++){
			delete[] isIn[i][j];
			delete[] index[i][j];
		}
		delete[] isIn[i];
		delete[] index[i];
	}
	delete[] isIn;
	delete[] index;
	delete[] Q;
	delete[] isValid;

	return mesh;
}
PolygonalMesh* Polygonizer::computeSurfaceNet()
{
	float p[3];
	bool ***isIn = new bool**[dimZ+1];
	bool ***isValid = new bool**[dimZ+1];
	for(int i=0; i<dimZ+1; i++){
		isIn[i] = new bool*[dimY+1];
		isValid[i] = new bool*[dimY+1];
		p[2] = originZ + i*spaceZ;
		for(int j=0; j<dimY+1; j++){
			isIn[i][j] = new bool[dimX+1];
			isValid[i][j] = new bool[dimX+1];
			p[1] = originY + j*spaceY;
			for(int k=0; k<dimX+1; k++){
				p[0] = originX + k*spaceX;
				isIn[i][j][k] 
					= (func->value(p[0], p[1], p[2], isValid[i][j][k]) > 0);
			}
		}
	}

	int ***index = new int**[dimZ+1];
	for(int i=0; i<dimZ+1; i++){
		index[i] = new int*[dimY+1];
		for(int j=0; j<dimY+1; j++){
			index[i][j] = new int[dimX+1];
			for(int k=0; k<dimX+1; k++)
				index[i][j][k] = -1;
		}
	}

	int current = 0;
	int face_N = 0;
	for(int i=0; i<dimZ; i++)
		for(int j=0; j<dimY; j++)
			for(int k=0; k<dimX-1; k++){
				if(!isValid[i][j][k] || !isValid[i][j][k+1])
					continue;
				if((!isIn[i][j][k] && isIn[i][j][k+1]) || 
				    (isIn[i][j][k] && !isIn[i][j][k+1])){
					face_N++;
					if(index[i][j][k+1] < 0){
						index[i][j][k+1] = current;
						current++;
					}
					if(index[i][j+1][k+1] < 0){
						index[i][j+1][k+1] = current;
						current++;
					}
					if(index[i+1][j][k+1] < 0){
						index[i+1][j][k+1] = current;
						current++;
					}
					if(index[i+1][j+1][k+1] < 0){
						index[i+1][j+1][k+1] = current;
						current++;
					}
				}
			}

	for(int i=0; i<dimX; i++)
		for(int j=0; j<dimZ; j++)
			for(int k=0; k<dimY-1; k++){
				if(!isValid[j][k][i] || !isValid[j][k+1][i])
					continue;
				if((!isIn[j][k][i] && isIn[j][k+1][i]) || 
				    (isIn[j][k][i] && !isIn[j][k+1][i])){
					face_N++;
					if(index[j][k+1][i] < 0){
						index[j][k+1][i] = current;
						current++;
					}
					if(index[j+1][k+1][i] < 0){
						index[j+1][k+1][i] = current;
						current++;
					}
					if(index[j][k+1][i+1] < 0){
						index[j][k+1][i+1] = current;
						current++;
					}
					if(index[j+1][k+1][i+1] < 0){
						index[j+1][k+1][i+1] = current;
						current++;
					}
				}
			}

	for(int i=0; i<dimY; i++)
		for(int j=0; j<dimX; j++)
			for(int k=0; k<dimZ-1; k++){
				if(!isValid[k][i][j] || !isValid[k+1][i][j])
					continue;
				if((!isIn[k][i][j] && isIn[k+1][i][j]) || 
				    (isIn[k][i][j] && !isIn[k+1][i][j])){
					face_N++;
					if(index[k+1][i][j] < 0){
						index[k+1][i][j] = current;
						current++;
					}
					if(index[k+1][i+1][j] < 0){
						index[k+1][i+1][j] = current;
						current++;
					}
					if(index[k+1][i][j+1] < 0){
						index[k+1][i][j+1] = current;
						current++;
					}
					if(index[k+1][i+1][j+1] < 0){
						index[k+1][i+1][j+1] = current;
						current++;
					}
				}
			}
	
	PolygonalMesh* mesh = new PolygonalMesh;
	int vertex_N = current;
	mesh->setVertexCount(vertex_N);
	float (*vertex)[3] = mesh->vertex;
	current = 0;
	for(int i=0; i<dimZ+1; i++)
		for(int j=0; j<dimY+1; j++)
			for(int k=0; k<dimX+1; k++)
				if(index[i][j][k] >= 0){
					index[i][j][k] = current;
					vertex[current][0] = spaceX*((float)k-0.5f) + originX;
					vertex[current][1] = spaceY*((float)j-0.5f) + originY;
					vertex[current][2] = spaceZ*((float)i-0.5f) + originZ;
					current++;
				}


	mesh->setFaceCount(face_N);
	for(int i=0; i<face_N; i++)
		mesh->setPolygonCount(i, 4);
	face_N = 0;
	int **face = mesh->face;
	for(int i=0; i<dimZ; i++)
		for(int j=0; j<dimY; j++)
			for(int k=0; k<dimX-1; k++){
				if(!isValid[i][j][k] || !isValid[i][j][k+1])
					continue;
				if(isIn[i][j][k] && !isIn[i][j][k+1]){
					face[face_N][0] = index[i][j][k+1];
					face[face_N][1] = index[i][j+1][k+1];
					face[face_N][2] = index[i+1][j+1][k+1];
					face[face_N][3] = index[i+1][j][k+1];
					face_N++;
				}
				else if(!isIn[i][j][k] && isIn[i][j][k+1]){
					face[face_N][0] = index[i][j][k+1];
					face[face_N][1] = index[i+1][j][k+1];
					face[face_N][2] = index[i+1][j+1][k+1];
					face[face_N][3] = index[i][j+1][k+1];
					face_N++;
				}
			}

	for(int i=0; i<dimX; i++)
		for(int j=0; j<dimZ; j++)
			for(int k=0; k<dimY-1; k++){
				if(!isValid[j][k][i] || !isValid[j][k+1][i])
					continue;
				if(isIn[j][k][i] && !isIn[j][k+1][i]){
					face[face_N][0] = index[j][k+1][i];
					face[face_N][1] = index[j+1][k+1][i];
					face[face_N][2] = index[j+1][k+1][i+1];
					face[face_N][3] = index[j][k+1][i+1];
					face_N++;
				}
				else if(!isIn[j][k][i] && isIn[j][k+1][i]){
					face[face_N][0] = index[j][k+1][i];
					face[face_N][1] = index[j][k+1][i+1];
					face[face_N][2] = index[j+1][k+1][i+1];
					face[face_N][3] = index[j+1][k+1][i];
					face_N++;
				}
			}

	for(int i=0; i<dimY; i++)
		for(int j=0; j<dimX; j++)
			for(int k=0; k<dimZ-1; k++){
				if(!isValid[k][i][j] || !isValid[k+1][i][j])
					continue;
				if(isIn[k][i][j] && !isIn[k+1][i][j]){
					face[face_N][0] = index[k+1][i][j];
					face[face_N][1] = index[k+1][i][j+1];
					face[face_N][2] = index[k+1][i+1][j+1];
					face[face_N][3] = index[k+1][i+1][j];
					face_N++;
				}
				else if(!isIn[k][i][j] && isIn[k+1][i][j]){
					face[face_N][0] = index[k+1][i][j];
					face[face_N][1] = index[k+1][i+1][j];
					face[face_N][2] = index[k+1][i+1][j+1];
					face[face_N][3] = index[k+1][i][j+1];
					face_N++;
				}
			}
	
	for(int i=0; i<dimZ+1; i++){
		for(int j=0; j<dimY+1; j++){
			delete[] isIn[i][j];
			delete[] index[i][j];
		}
		delete[] isIn[i];
		delete[] index[i];
	}
	delete[] isIn;
	delete[] index;

	return mesh;
}
PolygonalMesh* Polygonizer::computeSurfaceNetOctTree(float tol, int min, int max)
{
	OctTreeP oct;
	oct.func = func;
	oct.originX = originX;
	oct.originY = originY;
	oct.originZ = originZ;
	oct.sizeX = dimX*spaceX;
	oct.sizeY = dimY*spaceY;
	oct.sizeZ = dimZ*spaceZ;
	oct.constructStandard(min, max);

	int vertex_N, face_N;
	oct.countVertexAndFace(vertex_N, face_N);
	PolygonalMesh* mesh = new PolygonalMesh;
	mesh->setVertexCount(vertex_N);
	mesh->setFaceCount(face_N);
	for(int i=0; i<face_N; i++)
		mesh->setPolygonCount(i, 4);
	
	double (*Q)[10] = new double[vertex_N][10];
	for(int i=0; i<vertex_N; i++)
		MAT_INIT(Q[i]);

	oct.simplify(Q, tol);
	oct.polygonize2(mesh->vertex, mesh->face);
	//return mesh;

	//oct.simplify(Q, tol);
	//oct.polygonize2(mesh->vertex, mesh->face);

	//FOR SVD
			
  vnl_matrix< float > A( 3, 3, 0. );
  
  vnl_vector<float> b( 3, 0. ), x( 3, 0. );
	for(int i=0; i<vertex_N; i++){
		A[0][0] = Q[i][0];
		A[1][0] = A[0][1] = Q[i][1];
		A[2][0] = A[0][2] = Q[i][2];
		A[1][1] = Q[i][3];
		A[1][2] = A[2][1] = Q[i][4];
		A[2][2] = Q[i][5];

		float tmp[3];
		MAT_BY_VEC(tmp, Q[i], mesh->vertex[i]);
		
		b[1] = -Q[i][6] - tmp[0];
		b[2] = -Q[i][7] - tmp[1];
		b[3] = -Q[i][8] - tmp[2];
		
        vnl_svd< float > svd( A );
        svd.zero_out_relative( 0.025 );
		x = svd.solve( b );

		mesh->vertex[i][0] += x[1];
		mesh->vertex[i][1] += x[2];
		mesh->vertex[i][2] += x[3];
	}

	delete[] Q;
	return mesh;
}
Beispiel #13
0
//2D mesh for cross sections. (for the paper)
PolygonalMesh* HRBF::generateCrossSection(float o[], float t1[], float t2[], int n, int m)
{
	PolygonalMesh *mesh = new PolygonalMesh;
	mesh->setVertexCount(n*m);
	mesh->setFaceCount((n-1)*(m-1));
	int **face = mesh->face;
	float (*vertex)[3] = mesh->vertex;
	float *v = mesh->value = new float[mesh->vertex_N];
	mesh->isValid = new bool[mesh->vertex_N];
	mesh->isCovered = new bool[mesh->vertex_N];

	double t3[3];
	PolygonalMesh::CROSS(t3, t1, t2);
	double len = PolygonalMesh::LENGTH(t3);
	//0.3 for kernal
	t3[0] /= -0.4*len;
	t3[1] /= -0.4*len;
	t3[2] /= -0.4*len;

	int i;
	for(i = 0; i< mesh->vertex_N; i++)
		mesh->isValid[i] = true;

	for(i=0; i<n; i++){
		float p1[3];
		p1[0] = o[0] + t1[0]*i;
		p1[1] = o[1] + t1[1]*i;
		p1[2] = o[2] + t1[2]*i;
		for(int j=0; j<m; j++){
			float p2[3];
			p2[0] = t2[0]*j;
			p2[1] = t2[1]*j;
			p2[2] = t2[2]*j;

			int index = i*m+j;
			vertex[index][0] = p1[0] + p2[0];
			vertex[index][1] = p1[1] + p2[1];
			vertex[index][2] = p1[2] + p2[2];

			bool flag;
			float f = value(vertex[index][0], vertex[index][1], vertex[index][2], flag);//);//
			

			if(_isnan(f)){
				v[index] = 0;
				continue;
			}

			/*
			vertex[index][0] += f*(float)t3[0];
			vertex[index][1] += f*(float)t3[1];
			vertex[index][2] += f*(float)t3[2];
			*/
			
			v[index] = f;
			mesh->isCovered[index] = flag;
			//if(!flag)
				//v[index] = 1000000;
			//else
				//v[index] = -10000000;
		}
	}

	for(i=0; i<n-1; i++){
		for(int j=0; j<m-1; j++){
			int index = i*(m-1)+j;
			mesh->setPolygonCount(index, 4);
			face[index][3] = i*m+j;
			face[index][2] = (i+1)*m+j;
			face[index][1] = (i+1)*m+j+1;
			face[index][0] = i*m+j+1;
			//bool flag = (v[face[index][0]] > 0);
			
			/*
			if(PolygonalMesh::LENGTH(vertex[face[index][0]]) > 5 ||
				PolygonalMesh::LENGTH(vertex[face[index][1]]) > 5 ||
				PolygonalMesh::LENGTH(vertex[face[index][2]]) > 5 ||
				PolygonalMesh::LENGTH(vertex[face[index][3]]) > 5)
				face[index][0] = -1;
				*/
			/*
			for(int k=1; k<4; k++){ 
				if(flag != (v[face[index][k]] > 0)){
					v[i*n+j] = -100;
				}
			}*/
			/*
			if(v[face[index][0]] == v[face[index][1]] 
				== v[face[index][2]] == v[face[index][3]] == 0)
				v[i*n+j] = 1000000;*/
		}
	}
	mesh->computeFaceNormal();
	return mesh;
}
int main() {
  try {    
    // Create the system.   
    MultibodySystem system;
    SimbodyMatterSubsystem matter(system);

    matter.setShowDefaultGeometry(false);

    CableTrackerSubsystem cables(system);
    GeneralForceSubsystem forces(system);

    Force::Gravity gravity(forces, matter, -YAxis, 9.81);
    // Force::GlobalDamper(forces, matter, 5);

    system.setUseUniformBackground(true);    // no ground plane in display
    MobilizedBody Ground = matter.Ground(); // convenient abbreviation

    // Read in some bones.
    PolygonalMesh femur;
    PolygonalMesh tibia;

    femur.loadVtpFile("CableOverBicubicSurfaces-femur.vtp");
    tibia.loadVtpFile("CableOverBicubicSurfaces-tibia.vtp");
    femur.scaleMesh(30);
    tibia.scaleMesh(30);

    // Build a pendulum
    Body::Rigid pendulumBodyFemur(    MassProperties(1.0, Vec3(0, -5, 0), 
                                    UnitInertia(1).shiftFromCentroid(Vec3(0, 5, 0))));

    pendulumBodyFemur.addDecoration(Transform(), DecorativeMesh(femur).setColor(Vec3(0.8, 0.8, 0.8)));

    Body::Rigid pendulumBodyTibia(    MassProperties(1.0, Vec3(0, -5, 0), 
                                    UnitInertia(1).shiftFromCentroid(Vec3(0, 5, 0))));

    pendulumBodyTibia.addDecoration(Transform(), DecorativeMesh(tibia).setColor(Vec3(0.8, 0.8, 0.8)));

    Rotation z180(Pi, YAxis);

    MobilizedBody::Pin pendulumFemur(    matter.updGround(),
                                        Transform(Vec3(0, 0, 0)),
                                        pendulumBodyFemur,
                                        Transform(Vec3(0, 0, 0)) );

    Rotation rotZ45(-Pi/4, ZAxis);

    MobilizedBody::Pin pendulumTibia(   pendulumFemur,
                                        Transform(rotZ45, Vec3(0, -12, 0)),
                                        pendulumBodyTibia,
                                        Transform(Vec3(0, 0, 0)) );

    Real initialPendulumOffset = -0.25*Pi;

    Constraint::PrescribedMotion pres(matter, 
       new Function::Sinusoid(0.25*Pi, 0.2*Pi, 0*initialPendulumOffset), pendulumTibia, MobilizerQIndex(0));
               
    // Build a wrapping cable path
    CablePath path2(cables, Ground, Vec3(1, 3, 1),             // origin
                            pendulumTibia, Vec3(1, -4, 0));  // termination
    
    // Create a bicubic surface
    Vec3 patchOffset(0, -5, -1);
    Rotation rotZ90(0.5*Pi, ZAxis);
    Rotation rotX90(0.2*Pi, XAxis);

    Rotation patchRotation = rotZ90 * rotX90 * rotZ90;
    Transform patchTransform(patchRotation, patchOffset);

    Real patchScaleX = 2.0;
    Real patchScaleY = 2.0;
    Real patchScaleF = 0.75;

    const int Nx = 4, Ny = 4;
  
    const Real xData[Nx] = {  -2, -1, 1, 2 };
    const Real yData[Ny] = {  -2, -1, 1, 2 };

    const Real fData[Nx*Ny] = { 2,        3,        3,        1,
                                0,         1.5,  1.5,        0,
                                0,        1.5,  1.5,        0,
                                2,        3,        3,        1    };

    const Vector x_(Nx,        xData);
    const Vector y_(Ny,     yData);
    const Matrix f_(Nx, Ny, fData);

    Vector x = patchScaleX*x_;
    Vector y = patchScaleY*y_;
    Matrix f = patchScaleF*f_; 

    BicubicSurface patch(x, y, f, 0);

    Real highRes = 30;
    Real lowRes  = 1;

    PolygonalMesh highResPatchMesh = patch.createPolygonalMesh(highRes);
    PolygonalMesh lowResPatchMesh = patch.createPolygonalMesh(lowRes);

   
    pendulumFemur.addBodyDecoration(patchTransform,
        DecorativeMesh(highResPatchMesh).setColor(Cyan).setOpacity(.75));

    pendulumFemur.addBodyDecoration(patchTransform,
         DecorativeMesh(lowResPatchMesh).setRepresentation(DecorativeGeometry::DrawWireframe));

    Vec3 patchP(-0.5,-1,2), patchQ(-0.5,1,2);

    pendulumFemur.addBodyDecoration(patchTransform,
        DecorativePoint(patchP).setColor(Green).setScale(2));

    pendulumFemur.addBodyDecoration(patchTransform,
        DecorativePoint(patchQ).setColor(Red).setScale(2));

     CableObstacle::Surface patchObstacle(path2, pendulumFemur, patchTransform,
         ContactGeometry::SmoothHeightMap(patch));
        
      patchObstacle.setContactPointHints(patchP, patchQ);
    
      patchObstacle.setDisabledByDefault(true);

    // Sphere
    Real      sphRadius = 1.5;

    Vec3      sphOffset(0, -0.5, 0);
    Rotation  sphRotation(0*Pi, YAxis);
    Transform sphTransform(sphRotation, sphOffset);

    CableObstacle::Surface tibiaSphere(path2, pendulumTibia, sphTransform,
        ContactGeometry::Sphere(sphRadius));

    Vec3 sphP(1.5,-0.5,0), sphQ(1.5,0.5,0);
    tibiaSphere.setContactPointHints(sphP, sphQ);

    pendulumTibia.addBodyDecoration(sphTransform,
        DecorativeSphere(sphRadius).setColor(Red).setOpacity(0.5));

    // Make cable a spring
    CableSpring cable2(forces, path2, 50., 18., 0.1); 

    Visualizer viz(system);
    viz.setShowFrameNumber(true);
    system.addEventReporter(new Visualizer::Reporter(viz, 1./30));
    system.addEventReporter(new ShowStuff(system, cable2, 0.02));    
    // Initialize the system and state.
    
    system.realizeTopology();
    State state = system.getDefaultState();

    system.realize(state, Stage::Position);
    viz.report(state);
    cout << "path2 init length=" << path2.getCableLength(state) << endl;
    cout << "Hit ENTER ...";
    getchar();

    // path1.setIntegratedCableLengthDot(state, path1.getCableLength(state));

    // Simulate it.
    saveStates.clear(); saveStates.reserve(2000);

    // RungeKutta3Integrator integ(system);
    RungeKuttaMersonIntegrator integ(system);
    // CPodesIntegrator integ(system);
    // integ.setAllowInterpolation(false);
    integ.setAccuracy(1e-5);
    TimeStepper ts(system, integ);
    ts.initialize(state);
    ShowStuff::showHeading(cout);

    const Real finalTime = 10;
    const double startTime = realTime();
    ts.stepTo(finalTime);
    cout << "DONE with " << finalTime 
         << "s simulated in " << realTime()-startTime
         << "s elapsed.\n";

    while (true) {
        cout << "Hit ENTER FOR REPLAY, Q to quit ...";
        const char ch = getchar();
        if (ch=='q' || ch=='Q') break;
        for (unsigned i=0; i < saveStates.size(); ++i)
            viz.report(saveStates[i]);
    }

  } catch (const std::exception& e) {
    cout << "EXCEPTION: " << e.what() << "\n";
  }
}
Beispiel #15
0
BreakableMesh::BreakableMesh(const PolygonalMesh& m) {
    this->points = m.getPoints();
    this->polygons = m.getPolygons();
    this->edges = m.getSegments();
    this->region = m.getRegion();
}
Beispiel #16
0
int main(int argc, char** argv) {

    cout << "Welcome to Le Fancy Vase Drawer.\n" << endl;
    printf("Instructions:\n"\
           "r,g,b - Change colour of mesh to red, green, blue\n"\
           "k     - Colour the mesh black\n"\
           "p     - RAINBOW.\n"\
           "1,3   - Zoom in, zoom out\n"\
           "w,s   - Move camera up, down\n"\
           "a,d   - Rotate mesh left, right\n"\
           "q,e   - Move gaze point up, down\n"\
           "z,c   - Move camera and gaze point up, down\n");

    float viewingAngle = 60.; // degrees
    float aspectRatio = 1;
    float N = 5.;  // near plane
    float F = 30.; // far plane
    float t = N * tan(CV_PI / 360 * viewingAngle); // top
    float b = -t; // bottom
    float r = aspectRatio*t; // right
    float l = -r; // left
    int   w = 512,
          h = 512;

    bool camChanged = true;
    bool rainbow = true;
    int rotationInc = 5;
    int roll = 0;

    namedWindow(wndName, CV_WINDOW_AUTOSIZE);

    // used as row vectors, so they can be appended to Matrix easily
    Mat e = (Mat_<float>(1, 3) << 30., 30., 22.); // camera vector.  15, 15, 10
    Mat g = (Mat_<float>(1, 3) <<  0., 0., 18.); // a point through which the gaze direction unit vector n points to
    Mat p = (Mat_<float>(1, 3) <<  0., 0., 1.); // x, y, z, w
    Mat n, u, v;
    Mat screen(w, h, CV_8UC3);
    int flip = 1; // -1 to flip along X

    Mat Mv(0, 3, CV_32FC1);

    Mat S1T1Mp = (Mat_<float>(4, 4) <<
                  (2*N)/(r-l), 0, (r+l)/(r-l), 0,
                  0, (2*N)/(t-b), (t+b)/(t-b), 0,
                  0, 0, -(F+N)/(F-N), -2*F*N/(F-N),
                  0, 0, -1, 0
                  );

    Mat WS2T2 = (Mat_<float>(4, 4) <<
                 w/2, 0, 0, w/2,
                 0, flip*h/2, 0, -h/2+h,
                 0, 0, 1, 0,
                 0, 0, 0, 1
                 );

    // container for screen coords
    vector<Point2i> coords;

    // background colour and line colour
    Scalar bgColour(255, 255, 255);
    Scalar lineColour(0);

    // HSV and BGR matrices for colours of the rainbow
    int sat = 200, val = 200;
    Mat hsv(Size(1,1),CV_8UC3, Scalar(10,sat,val)), bgr;

    // the polygonal mesh object
    PolygonalMesh poly;
    poly.readFromFile("PolyVase.xml");

    bool normalChanged = true;

    char c = -1; // input char
    while (true) {
        if (camChanged) {
            if (normalChanged) {
                // normalize vector from camera to gaze point
                normalize(e - g, n);
                // generate vectors describing camera plane
                //u = (getRotationMatrix(n, rotationInc) * u.t()).t();
                //v = (getRotationMatrix(n, rotationInc) * v.t()).t();
                // normalize to keep window same size
                //normalize(u, u);
                //normalize(v, v);
                u = p.cross(n);
                v = u.cross(n);
                u = (getRotationMatrix(n, roll) * u.t()).t();
                v = (getRotationMatrix(n, roll) * v.t()).t();
                normalize(u, u);
                normalize(v, v);

                normalChanged = false;
            }

            // construct matrix for world coords to camera viewing coords
            Mv = Mat(0, 3, CV_32FC1);
            Mv.push_back(u);
            Mv.push_back(v);
            Mv.push_back(n);
            Mv = Mv.t();
            Mv.push_back(Mat((Mat_<float>(1, 3) << -e.dot(u), -e.dot(v), -e.dot(n))));
            Mv = Mv.t();
            Mv.push_back(Mat((Mat_<float>(1, 4) << 0, 0, 0, 1))); // works

            //scale, transformation, and projection matrix
            S1T1Mp = (Mat_<float>(4, 4) <<
                          (2*N)/(r-l), 0, (r+l)/(r-l), 0,
                          0, (2*N)/(t-b), (t+b)/(t-b), 0,
                          0, 0, -(F+N)/(F-N), -2*F*N/(F-N),
                          0, 0, -1, 0
                          );

            // scal, transform from viewing volume to canonical viewing volume.
            // Flip along X-axis is desired
            WS2T2 = (Mat_<float>(4, 4) <<
                         w/2, 0, 0, w/2,
                         0, flip*h/2, 0, -h/2+h,
                         0, 0, 1, 0,
                         0, 0, 0, 1
                         );

            // colour the background
            screen.setTo(bgColour);

            camChanged = false;
        }
        
        coords.clear();
        coords.reserve(poly.vertsH.size());
        for (int i = 0; i < poly.vertsH.size(); i++) {
            // Apply transformations to convert from world coordinates to screen coords
            Mat pt = WS2T2 * (S1T1Mp * (Mv * poly.vertsH[i]));
            // Perspective divide
            pt /= pt.at<float>(3, 0);
            // store generated coordinate in coords container
            coords.push_back(Point2f((int)pt.at<float>(0), (int)pt.at<float>(1)));
        }
        if (rainbow) {
            hsv = Mat(Size(1, 1), CV_8UC3, Scalar(10, sat, val));
        }
        for (int i = 0; i < poly.faces.size(); i++) {
            Face& f           = poly.faces[i];
            Normal faceNormal = poly.norms[f.data[Face::NORM]];
            Mat tv            = poly.vertsH[f.data[Face::PT0]]; //  triangle 1st vertex
            // generate camera to triangle vector
            Vec3f  camToTri(tv.at<float>(X) - e.at<float>(X),
                            tv.at<float>(Y) - e.at<float>(Y),
                            tv.at<float>(Z) - e.at<float>(Z));

            // compute dot product to determine which faces to draw.
            float b = faceNormal.dot(camToTri); // camToTri.dot(faceNormal);

            if (rainbow) {
                // increment hue value, then convert from HSV to BGR
                Vec3b clr = hsv.at<Vec3b>(0, 0);
                clr[0]++;
                hsv.at<Vec3b>(0, 0) = clr;
                cvtColor(hsv, bgr, CV_HSV2BGR);
                Vec3b bgr3 = bgr.at<Vec3b>(0, 0);
                lineColour = Scalar(bgr3[0], bgr3[1], bgr3[2]);
            }
            if (b >= 0) {
                // draw triangle from 3 face coords
                line(screen, coords[f.data[Face::PT0]], coords[f.data[Face::PT1]], lineColour);
                line(screen, coords[f.data[Face::PT0]], coords[f.data[Face::PT2]], lineColour);
                line(screen, coords[f.data[Face::PT1]], coords[f.data[Face::PT2]], lineColour);
            }
        }

        // draw the image to the screen
        imshow(wndName, screen);

        c = waitKey(0);
        switch (c) {
            case 'w':
                // move camera up
                e.at<float>(Z) += 1;
                camChanged = true;
                normalChanged = true;
                break;
            case 's':
                // move camera down
                e.at<float>(Z) -= 1;
                camChanged = true;
                normalChanged = true;
                break;
            case 'a':{
                // rotate by 5 degrees along z axis
                float a = rotationInc/180.*CV_PI;
                e = ((Mat_<float>(3, 3) <<
                    cos(a), sin(a), 0,
                    -sin(a), cos(a), 0,
                    0, 0, 1) * e.t()).t();
                camChanged = true;
                normalChanged = true;
            }
                break;
            case 'd':{
                // rotate by -5 degrees along z axis
                float a = -rotationInc/180.*CV_PI;
                e = ((Mat_<float>(3, 3) <<
                    cos(a), sin(a), 0,
                    -sin(a), cos(a), 0,
                    0, 0, 1) * e.t()).t();
                camChanged = true;
                normalChanged = true;
            }
                break;
            case 'y': {
                roll += rotationInc;
                // rotate camera
                // rotate around unit vector 'n' -- from gaze point to cam
                //u = (getRotationMatrix(n, rotationInc) * u.t()).t();
                //v = (getRotationMatrix(n, rotationInc) * v.t()).t();
                // normalize to keep window same size
                //normalize(u, u);
                //normalize(v, v);
                normalChanged = true;
                camChanged = true;
            }
                break;
            case 'u':
                roll -= rotationInc;
                //u = (getRotationMatrix(n, -rotationInc) * u.t()).t();
                //v = (getRotationMatrix(n, -rotationInc) * v.t()).t();
                //normalize(u, u);
                //normalize(v, v);
                normalChanged = true;
                camChanged = true;
                break;
            case 'q':
                // shift gaze vector down
                g.at<float>(Z) -= 1;
                camChanged = true;
                normalChanged = true;
                break;
            case 'e':
                // shift gaze vector up
                g.at<float>(Z) += 1;
                camChanged = true;
                normalChanged = true;
                break;
            case 'c':
                // move camera and gaze vector up
                g.at<float>(Z) += 1;
                e.at<float>(Z) += 1;
                camChanged = true;
                break;
            case 'z':
                // move camera and gaze vector down
                g.at<float>(Z) -= 1;
                e.at<float>(Z) -= 1;
                camChanged = true;
                break;
            case '1':
                // move camera closer to object by 10%
                e *= 0.9;
                camChanged = true;
                break;
            case '3':
                // move cam further from object by 10%
                e *= 1.1;
                camChanged = true;
                break;
            case 'r':
                // colour the mesh red, green, blue, black (next 4 cases)
                lineColour = Scalar(0, 0, 255);
                rainbow = false;
                break;
            case 'g':
                lineColour = Scalar(0, 150, 0);
                rainbow = false;
                break;
            case 'b':
                lineColour = Scalar(255, 0, 0);
                rainbow = false;
                break;
            case 'k':
                lineColour = Scalar(0, 0, 0);
                rainbow = false;
                break;
            case 'p':
                //set the rainbow flag
                rainbow = true;
                break;
            default:
                break;
        }
    }

    // chillout until the user has hit a key
    waitKey();
    getchar();
}