void Curve::Evaluate( GraphDirection direction ) { uint32_t controlCount = 0; V_Vector3 points; { OS_HierarchyNodeDumbPtr::Iterator childItr = GetChildren().Begin(); OS_HierarchyNodeDumbPtr::Iterator childEnd = GetChildren().End(); for ( ; childItr != childEnd; ++childItr ) { CurveControlPoint* point = Reflect::SafeCast< CurveControlPoint >( *childItr ); if ( point ) { points.push_back( point->GetPosition() ); ++controlCount; } } } if ( controlCount < 4 || m_Type == CurveType::Linear ) { m_Points = points; } else if ( m_Type == CurveType::BSpline ) { CurveGenerator::ComputeCurve( points, m_Resolution, m_Closed, CurveGenerator::kBSpline, m_Points ); } else if ( m_Type == CurveType::CatmullRom ) { CurveGenerator::ComputeCurve( points, m_Resolution, m_Closed, CurveGenerator::kCatmullRom, m_Points ); } else { //whoa, did we get a bum curve type? HELIUM_BREAK(); } // // Update buffer // if ( controlCount > 0 ) { controlCount++; } uint32_t pointCount = (uint32_t)m_Points.size(); if ( pointCount > 0 ) { pointCount++; } m_Vertices->SetElementCount( controlCount + pointCount ); m_Vertices->Update(); Base::Evaluate(direction); }
void CreateTool::GenerateInstanceOffsets( PlacementStyle style, float radius, float instanceRadius, V_Vector3& positions ) { switch ( style ) { case PlacementStyles::Grid: { float radiusSquared = radius * radius; int numInstances = MAX( 2, (int) sqrt( radiusSquared / ( instanceRadius * instanceRadius ) ) ); float delta = radius * 2.0f / numInstances; for ( float x = -radius; x <= radius; x += delta ) { for ( float y = -radius; y <= radius; y += delta ) { if ( x * x + y * y < radiusSquared ) { Vector3 v = ( Editor::UpVector * x ) + ( Editor::OutVector * y ); positions.push_back( v ); } } } break; } case PlacementStyles::Radial: default: { float currentRadius = 0.0f; while ( currentRadius < radius ) { float circumference = static_cast< float32_t >( HELIUM_TWOPI ) * currentRadius; int numInstances = MAX( 1, (int) ( circumference / ( 2.0f * instanceRadius ) ) ); float deltaAngle = static_cast< float32_t >( HELIUM_TWOPI ) / numInstances; float currentAngle = static_cast< float32_t >( HELIUM_TWOPI ) * rand() / ( (float) RAND_MAX + 1.0f ); for ( int i = 0; i < numInstances; ++i ) { float x = currentRadius * cos( currentAngle ); float y = currentRadius * sin( currentAngle ); Vector3 v = ( Editor::UpVector * x ) + ( Editor::OutVector * y ); positions.push_back( v ); currentAngle += deltaAngle; while ( currentAngle > HELIUM_TWOPI ) { currentAngle -= static_cast< float32_t >( HELIUM_TWOPI ); } } currentRadius += instanceRadius + instanceRadius; } break; } } }
static void MakeClosed(V_Vector3& cvs) { // synthisize a new knot from the last two and first two cvs cvs.insert(cvs.begin(), cvs[cvs.size()-1]); cvs.insert(cvs.begin(), cvs[cvs.size()-2]); // this is 2 and 3 since we inserted @ 0 above cvs.push_back(cvs[2]); cvs.push_back(cvs[3]); }
void CreateTool::SetupInstanceOffsets( float instanceRadius, V_Vector3& instanceOffsets ) { instanceOffsets.clear(); instanceOffsets.reserve( 256 ); float adjustedInstanceRadius = instanceRadius / s_PaintDensity; GenerateInstanceOffsets( s_PaintPlacementStyle, s_PaintRadius, adjustedInstanceRadius, instanceOffsets ); SelectInstanceOffsets( s_PaintDistributionStyle, s_PaintRadius, instanceOffsets ); JitterInstanceOffsets( instanceRadius, s_PaintJitter, instanceOffsets ); RandomizeInstanceOffsets( instanceOffsets ); }
bool Frustum::IntersectsBox(const AlignedBox& box, bool precise) const { MATH_FUNCTION_TIMER(); if ( fabs((box.maximum - box.minimum).Length()) < LinearIntersectionError ) { return IntersectsPoint( box.Center() ); } else { f32 m, n; Vector3 c = box.Center(); Vector3 d = box.maximum - c; for (i32 i=0; i<6; i++) { const Plane& p = (*this)[i]; m = (c.x * p.A()) + (c.y * p.B()) + (c.z * p.C()) + p.D(); n = (d.x * abs(p.A())) + (d.y * abs(p.B())) + (d.z * abs(p.C())); if (m + n < 0) { return false; } } if ( precise ) { #pragma TODO("This precise test should be using separated axis testing instead of triangle decimation") V_Vector3 vertices; vertices.reserve(8); box.GetVertices(vertices); V_Vector3 triangleList; triangleList.reserve(36); AlignedBox::GetTriangulated(vertices, triangleList); for ( int i=0; i<36; i+=3 ) { if ( IntersectsTriangle( triangleList[i], triangleList[i+1], triangleList[i+2] ) ) { return true; } } return false; } } return true; }
bool CurveGenerator::ComputeCurve( const V_Vector3& controlPoints, const uint32_t resolution, const bool closed, const Type type, V_Vector3& points ) { bool success = false; if (resolution == 0 || controlPoints.size()<4) return success; success = true; points.clear( ); V_Vector3 tempControlPoints( controlPoints ); if( closed ) { MakeClosed( tempControlPoints ); } else { MakeContinuous( tempControlPoints ); } switch( type ) { case CurveGenerator::kLinear: { points = tempControlPoints; break; } case CurveGenerator::kBSpline: { ComputeBSpline( tempControlPoints, resolution, closed, points ); break; } case CurveGenerator::kCatmullRom: { ComputeCatmullRom( tempControlPoints, resolution, closed, points ); break; } default: { points = tempControlPoints; break; } } return success; }
float32_t Curve::CalculateCurveLength() const { const Matrix4& globalTransform = this->GetGlobalTransform(); V_Vector3 points = m_Points; float32_t curveLength = 0.f; for ( uint32_t i = 1; i < points.size() ; ++i ) { Vector3 endPoint = points[i]; Vector3 startPoint = points[i-1]; globalTransform.TransformVertex( endPoint ); globalTransform.TransformVertex( startPoint ); curveLength += (endPoint - startPoint).Length(); } return curveLength; }
void CreateTool::JitterInstanceOffsets( float instanceRadius, float maxJitter, V_Vector3& offsets ) { V_Vector3 jitterVectors; jitterVectors.push_back( Editor::UpVector ); jitterVectors.push_back( Editor::OutVector ); V_Vector3::iterator itr = offsets.begin(); V_Vector3::iterator end = offsets.end(); for ( ; itr != end; ++itr ) { V_Vector3::const_iterator jitterItr = jitterVectors.begin(); V_Vector3::const_iterator jitterEnd = jitterVectors.end(); for ( ; jitterItr != jitterEnd; ++jitterItr ) { int searchTries = 10; while ( searchTries > 0 ) { --searchTries; float jitter = ( rand() / ( (float) RAND_MAX + 1.0f ) ) * 2.0f - 1.0f; float randomNumber = rand() / ( (float) RAND_MAX + 1.0f ); float testNumber = GetNormalProbabilityFromPercent( jitter ); if ( randomNumber <= testNumber ) { (*itr) += (*jitterItr) * jitter * maxJitter; searchTries = 0; } } } } }
void AlignedBox::Transform(const Matrix4& matrix) { // get the currents sample bounds V_Vector3 vertices; GetVertices( vertices ); // reseed this box Reset(); // iterate and resample the bounds V_Vector3::iterator itr = vertices.begin(); V_Vector3::iterator end = vertices.end(); for ( ; itr != end; ++itr ) { // transform the sample matrix.TransformVertex( *itr ); // test the sample Test( *itr ); } }
void AlignedBox::GetVertices(V_Vector3& vertices) const { vertices.resize(8); vertices[0] = Vector3 (maximum.x, maximum.y, maximum.z); vertices[1] = Vector3 (maximum.x, minimum.y, maximum.z); vertices[2] = Vector3 (minimum.x, minimum.y, maximum.z); vertices[3] = Vector3 (minimum.x, maximum.y, maximum.z); vertices[4] = Vector3 (maximum.x, maximum.y, minimum.z); vertices[5] = Vector3 (maximum.x, minimum.y, minimum.z); vertices[6] = Vector3 (minimum.x, minimum.y, minimum.z); vertices[7] = Vector3 (minimum.x, maximum.y, minimum.z); }
void ComputeCatmullRom( V_Vector3& controlPoints, const uint32_t resolution, const bool closed, V_Vector3& points ) { float32_t t = 0.0f; uint32_t start = 0; uint32_t end = resolution;// + 1;//for Catmull Rom uint32_t countControlPoints = uint32_t( controlPoints.size( ) - 3 ); float32_t step = 1.0f/static_cast<float32_t>( resolution ); for( uint32_t i = 0; i < countControlPoints; ++i ) { t = 0.0f; end = resolution; //if( i != 0 ) //for Catmull Rom // start = 1; if( i == countControlPoints - 1 ) { if( closed ) break; end++; } //only incur the cost of copying from the STL vector once const Vector3& cp0 = controlPoints[ i ]; const Vector3& cp1 = controlPoints[ i + 1 ]; const Vector3& cp2 = controlPoints[ i + 2 ]; const Vector3& cp3 = controlPoints[ i + 3 ]; for( uint32_t j = start; j < end; ++j ) { points.push_back( ComputePoint( t, cp0, cp1, cp2, cp3, CurveGenerator::kCatmullRom ) ); t += step; } } }
void ComputeBSpline( V_Vector3& controlPoints, const uint32_t resolution, const bool closed, V_Vector3& points ) { float32_t t = 0.0f; uint32_t start = 0; uint32_t end = resolution; uint32_t countControlPoints = (uint32_t)( controlPoints.size( ) - 3 ); float32_t step = 1.0f/static_cast<float32_t>( resolution ); for( uint32_t i = 0; i < countControlPoints; ++i ) { t = 0.0f; end = resolution; //push end forward to get the last point if( i == countControlPoints - 1 ) { if( closed ) break; end++; } //only incur the cost of copying from the STL vector once const Vector3& cp0 = controlPoints[ i ]; const Vector3& cp1 = controlPoints[ i + 1 ]; const Vector3& cp2 = controlPoints[ i + 2 ]; const Vector3& cp3 = controlPoints[ i + 3 ]; for( uint32_t j = start; j < end; ++j ) { points.push_back( ComputePoint( t, cp0, cp1, cp2, cp3, CurveGenerator::kBSpline ) ); t += step; } } }
static void MakeContinuous(V_Vector3& cvs) { // ensure continuity through to first and last cvs by creating new begin and end tagent cvs Vector3 ab = cvs[0] - cvs[1]; cvs.insert(cvs.begin(), cvs[0] + ab); Vector3 cd = cvs[ cvs.size() - 1 ] - cvs[ cvs.size() - 2 ]; cvs.push_back(cvs[ cvs.size() - 1 ] + cd); }
bool Frustum::Contains(const AlignedBox& box) const { MATH_FUNCTION_TIMER(); V_Vector3 verts; box.GetVertices(verts); for (size_t i=0; i<verts.size(); i++) { // for each plane for (i32 j=0; j<6; j++) { const Plane& p = (*this)[j]; // we need this vert to be above each plane if ((verts[i].x * p.A()) + (verts[i].y * p.B()) + (verts[i].z * p.C()) + p.D() < 0) { return false; } } } return true; }
void OctreeVisualizer::incomingOctreeCallback() { scan_utils::Octree<char> octree(0, 0, 0, 0, 0, 0, 1, 0); octree.setFromMsg(octree_message_); std::list<scan_utils::Triangle> triangles; octree.getAllTriangles(triangles); V_Vector3 vertices; V_Vector3 normals; vertices.resize( triangles.size() * 3 ); normals.resize( triangles.size() ); size_t vertexIndex = 0; size_t normalIndex = 0; std::list<scan_utils::Triangle>::iterator it = triangles.begin(); std::list<scan_utils::Triangle>::iterator end = triangles.end(); for ( ; it != end; it++ ) { Ogre::Vector3& v1 = vertices[vertexIndex++]; Ogre::Vector3& v2 = vertices[vertexIndex++]; Ogre::Vector3& v3 = vertices[vertexIndex++]; Ogre::Vector3& n = normals[normalIndex++]; v1 = Ogre::Vector3( it->p1.x, it->p1.y, it->p1.z ); v2 = Ogre::Vector3( it->p2.x, it->p2.y, it->p2.z ); v3 = Ogre::Vector3( it->p3.x, it->p3.y, it->p3.z ); robotToOgre(v1); robotToOgre(v2); robotToOgre(v3); n = ( v2 - v1 ).crossProduct( v3 - v1 ); n.normalise(); } triangles_mutex_.lock(); vertices_.clear(); normals_.clear(); vertices.swap( vertices_ ); normals.swap( normals_ ); new_message_ = true; triangles_mutex_.unlock(); }
void AlignedBox::GetTriangulated(const V_Vector3& vertices, V_Vector3& triangleList, bool clear) { if (clear) { triangleList.clear(); } //front 2103 triangleList.push_back(vertices[2]); triangleList.push_back(vertices[1]); triangleList.push_back(vertices[0]); triangleList.push_back(vertices[0]); triangleList.push_back(vertices[3]); triangleList.push_back(vertices[2]); //right 1540 triangleList.push_back(vertices[1]); triangleList.push_back(vertices[5]); triangleList.push_back(vertices[4]); triangleList.push_back(vertices[4]); triangleList.push_back(vertices[0]); triangleList.push_back(vertices[1]); //back 5674 triangleList.push_back(vertices[5]); triangleList.push_back(vertices[6]); triangleList.push_back(vertices[7]); triangleList.push_back(vertices[7]); triangleList.push_back(vertices[4]); triangleList.push_back(vertices[5]); //left 6237 triangleList.push_back(vertices[6]); triangleList.push_back(vertices[2]); triangleList.push_back(vertices[3]); triangleList.push_back(vertices[3]); triangleList.push_back(vertices[7]); triangleList.push_back(vertices[6]); //top 3047 triangleList.push_back(vertices[3]); triangleList.push_back(vertices[0]); triangleList.push_back(vertices[4]); triangleList.push_back(vertices[4]); triangleList.push_back(vertices[7]); triangleList.push_back(vertices[3]); //bottom 6512 triangleList.push_back(vertices[6]); triangleList.push_back(vertices[5]); triangleList.push_back(vertices[1]); triangleList.push_back(vertices[1]); triangleList.push_back(vertices[2]); triangleList.push_back(vertices[6]); }
void CreateTool::SelectInstanceOffsets( DistributionStyle style, float radius, V_Vector3& offsets ) { V_Vector3 selectedOffsets; selectedOffsets.reserve( offsets.size() ); V_Vector3::iterator itr = offsets.begin(); V_Vector3::iterator end = offsets.end(); for ( ; itr != end; ++itr ) { switch ( style ) { case DistributionStyles::Uniform: { float randomNumber = rand() / ( (float) RAND_MAX + 1.0f ); if ( randomNumber <= 0.5f ) { selectedOffsets.push_back( *itr ); } break; } case DistributionStyles::Linear: { float radiusPercent = (*itr).Length() / radius; float randomNumber = rand() / ( (float) RAND_MAX + 1.0f ); float testNumber = 1.0f - radiusPercent; if ( randomNumber <= testNumber ) { selectedOffsets.push_back( *itr ); } break; } case DistributionStyles::Normal: { float radiusPercent = (*itr).Length() / radius; float randomNumber = rand() / ( (float) RAND_MAX + 1.0f ); float testNumber = GetNormalProbabilityFromPercent( radiusPercent ); if ( randomNumber <= testNumber ) { selectedOffsets.push_back( *itr ); } break; } case DistributionStyles::Constant: default: selectedOffsets.push_back( *itr ); break; } } offsets.clear(); offsets.reserve( selectedOffsets.size() ); itr = selectedOffsets.begin(); end = selectedOffsets.end(); for ( ; itr != end; ++itr ) { offsets.push_back( *itr ); } }
void AlignedBox::GetWireframe(const V_Vector3& vertices, V_Vector3& lineList, bool clear) { if (clear) { lineList.clear(); } //front 2103 lineList.push_back(vertices[2]); lineList.push_back(vertices[1]); lineList.push_back(vertices[1]); lineList.push_back(vertices[0]); lineList.push_back(vertices[0]); lineList.push_back(vertices[3]); lineList.push_back(vertices[3]); lineList.push_back(vertices[2]); //back 5674 lineList.push_back(vertices[5]); lineList.push_back(vertices[6]); lineList.push_back(vertices[6]); lineList.push_back(vertices[7]); lineList.push_back(vertices[7]); lineList.push_back(vertices[4]); lineList.push_back(vertices[4]); lineList.push_back(vertices[5]); //middle lineList.push_back(vertices[1]); lineList.push_back(vertices[5]); lineList.push_back(vertices[3]); lineList.push_back(vertices[7]); lineList.push_back(vertices[0]); lineList.push_back(vertices[4]); lineList.push_back(vertices[6]); lineList.push_back(vertices[2]); }
void CreateTool::RandomizeInstanceOffsets( V_Vector3& offsets ) { V_Vector3 newOffsets; newOffsets.reserve( offsets.size() ); while ( offsets.size() ) { V_Vector3::iterator itr = offsets.begin() + ( rand() % offsets.size() ); newOffsets.push_back( *itr ); offsets.erase( itr ); } V_Vector3::iterator itr = newOffsets.begin(); V_Vector3::iterator end = newOffsets.end(); for ( ; itr != end; ++itr ) { offsets.push_back( *itr ); } }