void MassSpring1DRepresentation::init1D(
	const std::vector<Vector3d> nodes,
	std::vector<size_t> nodeBoundaryConditions,
	double totalMass,
	double stiffnessStretching, double dampingStretching,
	double stiffnessBending, double dampingBending)
{
	std::shared_ptr<SurgSim::Math::OdeState> state;
	state = std::make_shared<SurgSim::Math::OdeState>();
	state->setNumDof(getNumDofPerNode(), nodes.size());

	SURGSIM_ASSERT(nodes.size() > 0) << "Number of nodes incorrect: " << nodes.size();

	// Initialize the nodes position, velocity and mass
	// Note: no need to apply the initialPose here, initialize will take care of it !
	for (size_t massId = 0; massId < nodes.size(); massId++)
	{
		addMass(std::make_shared<Mass>(totalMass / static_cast<double>(nodes.size())));

		SurgSim::Math::setSubVector(nodes[massId], massId, 3, &state->getPositions());
	}

	// Initialize the stretching springs
	if (stiffnessStretching || dampingStretching)
	{
		for (size_t massId = 0; massId < nodes.size() - 1; massId++)
		{
			addSpring(createLinearSpring(state, massId, massId + 1, stiffnessStretching, dampingStretching));
		}
	}

	// Initialize the bending springs
	if (stiffnessBending || dampingBending)
	{
		for (size_t massId = 0; massId < nodes.size() - 2; massId++)
		{
			addSpring(createLinearSpring(state, massId, massId + 2, stiffnessBending, dampingBending));
		}
	}

	// Sets the boundary conditions
	for (auto boundaryCondition = std::begin(nodeBoundaryConditions);
		 boundaryCondition != std::end(nodeBoundaryConditions);
		 boundaryCondition++)
	{
		state->addBoundaryCondition(*boundaryCondition);
	}

	// setInitialState: Initialize all the states + apply initialPose if any
	setInitialState(state);
}
Пример #2
0
void form::update() {
    // we need to get an actually even tesselation!
    float edgeres = 0.25;
    vector <ofPolyline> rawpolys = mMasterCurve->getPath()->getOutline();
    ofPath path;
    ofPolyline master = mMasterCurve->getBasePoly().getResampledByCount(mMasterCurve->getBasePoly().getPerimeter()/(mMaxEdgeLen*edgeres));
    vector<ofVec3f> mvs = master.getVertices();
    for (auto v : mvs) {
        path.lineTo(v);
    }
    
    ofPolyline slave = mSlaveCurve->getBasePoly().getResampledByCount(mSlaveCurve->getBasePoly().getPerimeter()/(mMaxEdgeLen*edgeres));
    vector<ofVec3f> svs =  slave.getVertices();
    for (auto v : svs) {
        path.lineTo(v);
    }
    
    path.close();
    
    for (int i=1;i<rawpolys.size();i++) {
        ofPolyline p = rawpolys[i];
        float len = p.getPerimeter();
        int segs = ceil(len/(mMaxEdgeLen*edgeres));
        if (segs % 2 == 0) segs++;
        ofPolyline resamp = p.getResampledByCount(segs);
        vector<ofPoint> vs = resamp.getVertices();
        path.moveTo(vs[0]);
        for (auto v : vs) {
            path.lineTo(v);
        }
        path.close();
    }
    path.setCurveResolution(1);
    
    
    
    
    mRawMesh = path.getTessellation();
    mRawMesh.enableIndices();
    mMesh.enableIndices();
    
    // clear existing
    mVerts.clear();
    mRawFaces.clear();
    mFaces.clear();
    
    // fill out with current state
    mVerts = mRawMesh.getVertices();
    vector <ofIndexType> raw_inds = mRawMesh.getIndices();
    
    for (int i=0; i<raw_inds.size(); i += 3) {
        mRawFaces.push_back(face(raw_inds[i],raw_inds[i+1],raw_inds[i+2]));
    }
    
    // subdivide
    for (auto f : mRawFaces) {
        trySubdivide(f);
    }
    
    // make new mesh
    mMesh.clear();
    mMesh.enableIndices();
    mMesh.enableNormals();
    mMesh.addVertices(mVerts);
    mMesh.setMode(OF_PRIMITIVE_TRIANGLES);
    for (auto f : mFaces) {
        mMesh.addTriangle(f.a, f.b, f.c);
    }
    
    mOuterMesh.clear();
    mOuterMesh.enableIndices();
    mOuterMesh.enableNormals();
    mOuterMesh.addVertices(mVerts);
    mOuterMesh.setMode(OF_PRIMITIVE_TRIANGLES);
    for (auto f : mFaces) {
        mOuterMesh.addTriangle(f.a, f.b, f.c);
    }
    
    //mMesh = mRawMesh;

    for(auto p : mSprings) p->release();
    mSprings.clear();
    for(auto p : mParticles) p->release();
    mParticles.clear();
    for(auto p : mMasterEdgeParticles) delete p;
    mMasterEdgeParticles.clear();
    for(auto p : mSlaveEdgeParticles) delete p;
    mSlaveEdgeParticles.clear();
    for(auto p : mZipperSprings) p->release();
    mZipperSprings.clear();
    for(auto p : mBottomSprings) p->release();
    mBottomSprings.clear();
    for(auto p : mBottomParticles) p->release();
    mBottomParticles.clear();
    for(auto p : mMiddleSprings) p->release();
    mMiddleSprings.clear();

    mWorld.clear();
    
    float thickness = 10;
    
    int ind = 0;
    for (auto v : mVerts) {
        msa::physics::Particle3D *p = new msa::physics::Particle3D(v,1,0.01); // pos, mass, diam
        setIndex(p,master,slave,ind);
        
        mParticles.push_back(p);
        mWorld.addParticle(p);
        
        msa::physics::Particle3D *bp = new msa::physics::Particle3D(v+ofVec3f(0,0,thickness),1,0.01); // pos, mass, diam
        
        mBottomParticles.push_back(bp);
        mWorld.addParticle(bp);
        
        ind++;
    }
    
    float strength = 0.99;
    for (auto f : mFaces) {
        if (unmade(mParticles[f.a],mParticles[f.b])) {
            float alen = mParticles[f.a]->getPosition().distance(mParticles[f.b]->getPosition());
            
            mSprings.push_back(addSpring(mParticles[f.a],mParticles[f.b],strength,alen));
            
            mBottomSprings.push_back(addSpring(mBottomParticles[f.a],mBottomParticles[f.b],strength,alen));
            
            // add the four middle springs
            mMiddleSprings.push_back(addSpring(mParticles[f.a],mBottomParticles[f.a],strength,thickness));
            //mMiddleSprings.push_back(addSpring(mParticles[f.b],mBottomParticles[f.b],strength,thickness));
            float crosslen = mParticles[f.a]->getPosition().distance(mBottomParticles[f.b]->getPosition());
            mMiddleSprings.push_back(addSpring(mParticles[f.a],mBottomParticles[f.b],strength,crosslen));
            mMiddleSprings.push_back(addSpring(mParticles[f.b],mBottomParticles[f.a],strength,crosslen));
            
        }
        if (unmade(mParticles[f.b],mParticles[f.c])) {
            float blen = mParticles[f.b]->getPosition().distance(mParticles[f.c]->getPosition());
            mSprings.push_back(addSpring(mParticles[f.b],mParticles[f.c],strength,blen));
            
            mBottomSprings.push_back(addSpring(mBottomParticles[f.b],mBottomParticles[f.c],strength,blen));
            
            // add the four middle springs
            mMiddleSprings.push_back(addSpring(mParticles[f.b],mBottomParticles[f.b],strength,thickness));
            //mMiddleSprings.push_back(addSpring(mParticles[f.c],mBottomParticles[f.c],strength,thickness));
            float crosslen = mParticles[f.b]->getPosition().distance(mBottomParticles[f.c]->getPosition());
            mMiddleSprings.push_back(addSpring(mParticles[f.b],mBottomParticles[f.c],strength,crosslen));
            mMiddleSprings.push_back(addSpring(mParticles[f.c],mBottomParticles[f.b],strength,crosslen));
        }
        
        if (unmade(mParticles[f.c],mParticles[f.a])) {
            float clen = mParticles[f.c]->getPosition().distance(mParticles[f.a]->getPosition());
            mSprings.push_back(addSpring(mParticles[f.c],mParticles[f.a],strength,clen));
            
            mBottomSprings.push_back(addSpring(mBottomParticles[f.c],mBottomParticles[f.a],strength,clen));
            
            // add the four middle springs
            mMiddleSprings.push_back(addSpring(mParticles[f.c],mBottomParticles[f.c],strength,thickness));
            //mMiddleSprings.push_back(addSpring(mParticles[f.a],mBottomParticles[f.a],strength,thickness));
            
            float crosslen = mParticles[f.c]->getPosition().distance(mBottomParticles[f.a]->getPosition());
            mMiddleSprings.push_back(addSpring(mParticles[f.c],mBottomParticles[f.a],strength,crosslen));
            mMiddleSprings.push_back(addSpring(mParticles[f.a],mBottomParticles[f.c],strength,crosslen));
        }
    }
    
    orderEdge();
    
    mMasterEdgeParticles[0]->part->makeFixed();
    mSlaveEdgeParticles[0]->part->makeFixed();
    
    // modify all vertices to be partially rotated into place
    ofVec3f pivot = mMasterEdgeParticles[0]->part->getPosition();
    ofVec3f axis = pivot-mSlaveEdgeParticles[0]->part->getPosition();
    axis.normalize();
    
    for (int i=0; i<mParticles.size();i++) {
        msa::physics::Particle3D *p = mParticles[i];
        msa::physics::Particle3D *bp = mBottomParticles[i];
        int sign = 1;
        if (mMasterCurve->getBasePoly().inside(p->getPosition()) || isIn(p,mMasterEdgeParticles)) {
            sign = -1;
        }
        ofVec3f pos = p->getPosition();
        pos.rotate(45*sign, pivot, axis);
        p->moveTo(pos);
        
        pos = bp->getPosition();
        pos.rotate(45*sign, pivot, axis);
        bp->moveTo(pos);
    }
    
    for (int i=0; i<mParticles.size();i++) {
        mMesh.setVertex(i, mParticles[i]->getPosition());
    }
    
    for (int i=0;i<mMasterEdgeParticles.size();i++) {
        msa::physics::Particle3D *pm = mMasterEdgeParticles[i]->part;
        int sind = (1.0-(float)(i)/(float)(mMasterEdgeParticles.size()-1))*(mSlaveEdgeParticles.size()-1);
        msa::physics::Particle3D *sm = mSlaveEdgeParticles[sind]->part;
        
        if (sm->getPosition().distance(pm->getPosition()) > mTol) {
            pm->retain();
            sm->retain();
            msa::physics::Spring3D *spring = new msa::physics::Spring3D(pm,sm,strength*0.25,0.0);
            mZipperSprings.push_back(spring);
        }
        
    }
    
    /*msa::physics::Particle3D *stabalizer = new msa::physics::Particle3D(mMesh.getCentroid(),1,1);
    mWorld.addParticle(stabalizer);
    
    for (auto p : mParticles) {
        mWorld.makeSpring(stabalizer, p, strength*0.1, stabalizer->getPosition().distance(p->getPosition()));
    }*/
    
    mAtZip = 0;
    
    printf("made a mesh with %d vertices and %d faces",mVerts.size(),mFaces.size());
}
Пример #3
0
void OpenCloth::build( std::shared_ptr<ciri::IGraphicsDevice> device ) {
	if( _built ) {
		return;
	}

	_device = device;

	// gpu resources can fail, so create them first
	if( !createGpuResources() ) {
		return;
	}

	_positions = new cc::Vec3f[_totalPoints];
	_lastPositions = new cc::Vec3f[_totalPoints];
	_forces = new cc::Vec3f[_totalPoints];

	// fill in positions
	const int u = _divsX+1;
	const int v = _divsY+1;
	int count = 0;
	for( int j = 0; j <= _divsY; ++j ) {
		for( int i = 0; i <= _divsX; ++i ) {
			const float x = ((float(i) / (u-1)) * 2.0f - 1.0f) * _horizontalSize;
			const float y = 0.0f;//_size+1;
			const float z = ((float(j) / (v-1)) * _size);
			_positions[count] = cc::Vec3f(x, y, z);
			_lastPositions[count] = _positions[count];
			count++;
		}
	}

	// compute number of springs and allocate space
	_springCount = v * (u - 1); // horizontal structure springs
	_springCount += u * (v - 1); // vertical structure springs
	_springCount += ((v - 1) * (u - 1)) * 2; // shear springs
	_springCount += (v * (u - 1)); // bend springs 1
	_springCount += (u * (v - 1)); // bend springs 2
	_springs = new Spring[_springCount];

	// tracks which spring we are modifying; is incremented by addspring()
	int currSpring = 0;

	// horizontal structure springs
	for( int l1 = 0; l1 < v; ++l1 ) {
		for( int l2 = 0; l2 < (u - 1); ++l2 ) {
			const int a = (l1 * u) + l2;
			const int b = (l1 * u) + l2 + 1;
			addSpring(&currSpring, a, b, _ksStruct, _kdStruct);
		}
	}
	// vertical structure springs
	for( int l1 = 0; l1 < u; ++l1 ) {
		for( int l2 = 0; l2 < (v - 1); ++l2 ) {
			const int a = (l2 * u) + l1;
			const int b = ((l2 + 1) * u) + l1;
			addSpring(&currSpring, a, b, _ksStruct, _kdStruct);
		}
	}
	// shear springs
	for( int l1 = 0; l1 < (v - 1); ++l1 ) {
		for( int l2 = 0; l2 < (u - 1); ++l2 ) {
			const int a1 = (l1 * u) + l2;
			const int b1 = ((l1 + 1) * u) + l2 + 1;
			addSpring(&currSpring, a1, b1, _ksShear, _kdShear);
			const int a2 = ((l1 + 1) * u) + l2;
			const int b2 = (l1 * u) + l2 + 1;
			addSpring(&currSpring, a2, b2, _ksShear, _kdShear);
		}
	}
	// bend springs
	for( int l1 = 0; l1 < v; ++l1 ) {
		for( int l2 = 0; l2 < (u - 2); ++l2 ) {
			const int a1 = (l1 * u) + l2;
			const int b1 = (l1 * u) + l2 + 2;
			addSpring(&currSpring, a1, b1, _ksBend, _kdBend);
		}
		const int a2 = (l1 * u) + (u - 3);
		const int b2 = (l1 * u) + (u - 1);
		addSpring(&currSpring, a2, b2, _ksBend, _kdBend);
	}
	for( int l1 = 0; l1 < u; ++l1 ) {
		for( int l2 = 0; l2 < (v - 2); ++l2 ) {
			const int a1 = (l2 * u) + l1;
			const int b1 = ((l2 + 2) * u) + l1;
			addSpring(&currSpring, a1, b1, _ksBend, _kdBend);
		}
		const int a2 = ((v - 3) * u) + l1;
		const int b2 = ((v - 1) * u) + l1;
		addSpring(&currSpring, a2, b2, _ksBend, _kdBend);
	}

	// create gpu stuff
	createGpuBuffers();

	_built = true;

}