Plane::Plane( const cc::Vec3f& a, const cc::Vec3f& b, const cc::Vec3f& c ) { const cc::Vec3f ab = b - a; const cc::Vec3f ac = c - a; const cc::Vec3f cross = ab.cross(ac); _normal = cross.normalized(); _d = -_normal.dot(a); }
static Plane constructFromPointNormal( const cc::Vec3f& point, const cc::Vec3f& normal ) { Plane result; const cc::Vec3f normalizedNormal = normal.normalized(); result.normal = normalizedNormal; result.constant = -point.dot(normalizedNormal); return result; }
void OpenCloth::computeForces( float deltaTime ) { for( int i = 0; i < _totalPoints; ++i ) { _forces[i].x = _forces[i].y = _forces[i].z = 0.0f; const cc::Vec3f velocity = getVerletVelocity(_positions[i], _lastPositions[i], deltaTime); if( (i != 0) && (i != _divsX) ) { _forces[i] += _gravity * _mass; } _forces[i] += _damping * velocity; } for( int i = 0; i < _springCount; ++i ) { const cc::Vec3f& p1 = _positions[_springs[i].p1]; const cc::Vec3f& p1Last = _lastPositions[_springs[i].p1]; const cc::Vec3f& p2 = _positions[_springs[i].p2]; const cc::Vec3f& p2Last = _lastPositions[_springs[i].p2]; const cc::Vec3f v1 = getVerletVelocity(p1, p1Last, deltaTime); const cc::Vec3f v2 = getVerletVelocity(p2, p2Last, deltaTime); const cc::Vec3f deltaP = p1 - p2; const cc::Vec3f deltaV = v1 - v2; const float dist = deltaP.magnitude(); const float leftTerm = -_springs[i].ks * (dist - _springs[i].restLength); const float rightTerm = _springs[i].kd * (deltaV.dot(deltaP) / dist); const cc::Vec3f springForce = (leftTerm + rightTerm) * deltaP.normalized(); if( _springs[i].p1 != 0 && _springs[i].p1 != _divsX ) { _forces[_springs[i].p1] += springForce; } if( _springs[i].p2 != 0 && _springs[i].p2 != _divsX ) { _forces[_springs[i].p2] -= springForce; } } }
cc::Vec3f GeometricPlane::getNormal() { const cc::Vec3f p0 = (_xform.getWorld() * cc::Vec4f(_verts[0].position, 1.0f)).truncated(); const cc::Vec3f p1 = (_xform.getWorld() * cc::Vec4f(_verts[1].position, 1.0f)).truncated(); const cc::Vec3f p2 = (_xform.getWorld() * cc::Vec4f(_verts[2].position, 1.0f)).truncated(); const cc::Vec3f p3 = (_xform.getWorld() * cc::Vec4f(_verts[3].position, 1.0f)).truncated(); const cc::Vec3f a = p1 - p0; const cc::Vec3f b = p3 - p0; return a.cross(b).normalized(); }
void OpenCloth::addSpring( int* idx, int a, int b, float ks, float kd ) { _springs[*idx].p1 = a; _springs[*idx].p2 = b; _springs[*idx].ks = ks; _springs[*idx].kd = kd; const cc::Vec3f deltaP = _positions[a] - _positions[b]; _springs[*idx].restLength = sqrtf(deltaP.dot(deltaP)); *idx += 1; }
static void setVec3Length( cc::Vec3f& vec, float newLength ) { const float length = vec.magnitude(); if( length != 0.0f ) { const float factor = newLength / length; vec.x *= factor; vec.y *= factor; vec.z *= factor; } }
bool ClipMesh::getTriangles( std::vector<int>& indices ) { const size_t numFaces = _faces.size(); for( size_t currFace = 0; currFace < numFaces; ++currFace ) { CFace& face = _faces[currFace]; if( !face.visible ) { continue; } const size_t numEdges = face.edges.size(); //assert(numEdges >= 3); // unexpected condition if( numEdges < 3 ) { return false; } std::vector<int> vOrdered(numEdges+1); if( !orderVertices(face, vOrdered) ) { return false; } const int v0 = vOrdered[0]; const int v2 = vOrdered[numEdges - 1]; const int v1 = vOrdered[(numEdges - 1) >> 1]; const cc::Vec3f diff1 = _vertices[v1].point - _vertices[v0].point; const cc::Vec3f diff2 = _vertices[v2].point - _vertices[v0].point; const float sgnVolume = face.normal.dot(diff1.cross(diff2)); if( sgnVolume < 0.0f ) { // feel free to invert this test // clockwise, need to swap for( unsigned int i = 1; i + 1 < numEdges; ++i ) { indices.push_back(v0); indices.push_back(vOrdered[i + 1]); indices.push_back(vOrdered[i]); } } else { // counterclockwise for( unsigned int i = 1; i + 1 < numEdges; ++i ) { indices.push_back(v0); indices.push_back(vOrdered[i]); indices.push_back(vOrdered[i + 1]); } } } return true; }