Ejemplo n.º 1
0
void UprightFrame::unwrapYaw(UprightFrame* a, int N) {
    // Use the first point to establish the wrapping convention
    for (int i = 1; i < N; ++i) {
        const float prev = a[i - 1].yaw;
        float& cur = a[i].yaw;

        // No two angles should be more than pi (i.e., 180-degrees) apart.  
        if (abs(cur - prev) > G3D::pi()) {
            // These angles must have wrapped at zero, causing them
            // to be interpolated the long way.

            // Find canonical [0, 2pi] versions of these numbers
            float p = wrap(prev, twoPi());
            float c = wrap(cur, twoPi());
            
            // Find the difference -pi < diff < pi between the current and previous values
            float diff = c - p;
            if (diff < -G3D::pi()) {
                diff += twoPi();
            } else if (diff > G3D::pi()) {
                diff -= twoPi();
            } 

            // Offset the current from the previous by the difference
            // between them.
            cur = prev + diff;
        }
    }
}
Ejemplo n.º 2
0
float Cylinder::area() const {
    return
        // Sides
        (twoPi() * mRadius) * height() +

         // Caps
         twoPi() * square(mRadius);
}
Ejemplo n.º 3
0
void Cylinder::getRandomSurfacePoint(Vector3& p, Vector3& N) const {
    float h = height();
    float r = radius();

    // Create a random point on a standard cylinder and then rotate to the global frame.

    // Relative areas (factor of 2PI already taken out)
    float capRelArea  = square(r) / 2.0f;
    float sideRelArea = r * h;

    float r1 = uniformRandom(0, capRelArea * 2 + sideRelArea);

    if (r1 < capRelArea * 2) {

        // Select a point uniformly at random on a disk
        // @cite http://mathworld.wolfram.com/DiskPointPicking.html
        float a = uniformRandom(0, (float)twoPi());
        float r2 = sqrt(uniformRandom(0, 1)) * r;
        p.x = cos(a) * r2;
        p.z = sin(a) * r2;

        N.x = 0;
        N.z = 0;
        if (r1 < capRelArea) {
            // Top
            p.y = h / 2.0f;
            N.y = 1;
        } else {
            // Bottom
            p.y = -h / 2.0f;
            N.y = -1;
        }
    } else {
        // Side
        float a = uniformRandom(0, (float)twoPi());
        N.x = cos(a);
        N.y = 0;
        N.z = sin(a);
        p.x = N.x * r;
        p.z = N.y * r;
        p.y = uniformRandom(-h / 2.0f, h / 2.0f);
    }

    // Transform to world space
    CoordinateFrame cframe;
    getReferenceFrame(cframe);
    
    p = cframe.pointToWorldSpace(p);
    N = cframe.normalToWorldSpace(N);
}
Ejemplo n.º 4
0
float Capsule::area() const {

	return
		// Sphere area
		pow(_radius, 2) * 4 * pi() +

		// Cylinder area
		twoPi() * _radius * (p1 - p2).magnitude();
}
Ejemplo n.º 5
0
void Quat::toAxisAngleRotation(
    Vector3&            axis,
    double&             angle) const {
   
    // Decompose the quaternion into an angle and an axis.
    
    axis = Vector3(x, y, z);
    angle = 2 * acos(w);

    float len = sqrt(1.0f - w * w);

    if (fuzzyGt(abs(len), 0.0f)) {
        axis /= len;
    }

    // Reduce the range of the angle.

    if (angle < 0) {		
		angle = -angle;
		axis = -axis;
    }

	while (angle > twoPi()) {
        angle -= twoPi();
    }

	if (abs(angle) > pi()) {
		angle -= twoPi();
    }

    // Make the angle positive.

	if (angle < 0.0f) {		
		angle = -angle;
        axis = -axis;
	}
}
Ejemplo n.º 6
0
void FunctionApproximatorIRFRLS::train(const MatrixXd& inputs, const MatrixXd& targets)
{
  if (isTrained())  
  {
    cerr << "WARNING: You may not call FunctionApproximatorIRFRLS::train more than once. Doing nothing." << endl;
    cerr << "   (if you really want to retrain, call reTrain function instead)" << endl;
    return;
  }
  
  assert(inputs.rows() == targets.rows()); // Must have same number of examples
  assert(inputs.cols()==getExpectedInputDim());
  
  const MetaParametersIRFRLS* meta_parameters_irfrls = 
    static_cast<const MetaParametersIRFRLS*>(getMetaParameters());

  int nb_cos = meta_parameters_irfrls->number_of_basis_functions_;

  // Init random generator.
  boost::mt19937 rng(getpid() + time(0));

  // Draw periodes
  boost::normal_distribution<> twoGamma(0, sqrt(2 * meta_parameters_irfrls->gamma_));
  boost::variate_generator<boost::mt19937&, boost::normal_distribution<> > genPeriods(rng, twoGamma);
  MatrixXd cosines_periodes(nb_cos, inputs.cols());
  for (int r = 0; r < nb_cos; r++)
    for (int c = 0; c < inputs.cols(); c++)
      cosines_periodes(r, c) = genPeriods();

  // Draw phase
  boost::uniform_real<> twoPi(0, 2 * boost::math::constants::pi<double>());
  boost::variate_generator<boost::mt19937&, boost::uniform_real<> > genPhases(rng, twoPi);
  VectorXd cosines_phase(nb_cos);
  for (int r = 0; r < nb_cos; r++)
      cosines_phase(r) = genPhases();

  MatrixXd proj_inputs;
  proj(inputs, cosines_periodes, cosines_phase, proj_inputs);

  // Compute linear model analatically
  double lambda = meta_parameters_irfrls->lambda_;
  MatrixXd toInverse = lambda * MatrixXd::Identity(nb_cos, nb_cos) + proj_inputs.transpose() * proj_inputs;
  VectorXd linear_model = toInverse.inverse() *
    (proj_inputs.transpose() * targets);

  setModelParameters(new ModelParametersIRFRLS(linear_model, cosines_periodes, cosines_phase));
}
Ejemplo n.º 7
0
Vector3 Cylinder::randomInteriorPoint() const {
    float h = height();
    float r = radius();

    // Create a random point in a standard cylinder and then rotate to the global frame.

    // Select a point uniformly at random on a disk
    // @cite http://mathworld.wolfram.com/DiskPointPicking.html
    float a = uniformRandom(0, (float)twoPi());
    float r2 = sqrt(uniformRandom(0, 1)) * r;

    Vector3 p(  cos(a) * r2,
                uniformRandom(-h / 2.0f, h / 2.0f),
                sin(a) * r2);

    // Transform to world space
    CoordinateFrame cframe;
    getReferenceFrame(cframe);
    
    return cframe.pointToWorldSpace(p);
}
Ejemplo n.º 8
0
void Capsule::getRandomSurfacePoint(Vector3& p, Vector3& N) const {
    float h = height();
    float r = radius();

    // Create a random point on a standard capsule and then rotate to the global frame.

    // Relative areas
    float capRelArea  = sqrt(r) / 2.0f;
    float sideRelArea = r * h;

    float r1 = uniformRandom(0, capRelArea * 2 + sideRelArea);

    if (r1 < capRelArea * 2) {

        // Select a point uniformly at random on a sphere
        N = Sphere(Vector3::zero(), 1).randomSurfacePoint();
        p = N * r;
        p.y += sign(p.y) * h / 2.0f;
    } else {
        // Side
        float a = uniformRandom(0, (float)twoPi());
        N.x = cos(a);
        N.y = 0;
        N.z = sin(a);
        p.x = N.x * r;
        p.z = N.y * r;
        p.y = uniformRandom(-h / 2.0f, h / 2.0f);
    }

    // Transform to world space
    CoordinateFrame cframe;
    getReferenceFrame(cframe);
    
    p = cframe.pointToWorldSpace(p);
    N = cframe.normalToWorldSpace(N);
}
Ejemplo n.º 9
0
Vector3 Capsule::randomInteriorPoint() const {
    float h = height();
    float r = radius();

    // Create a random point in a standard capsule and then rotate to the global frame.

    Vector3 p;

    float hemiVolume = pi() * (r*r*r) * 4 / 6.0;
    float cylVolume = pi() * square(r) * h;
    
    float r1 = uniformRandom(0, 2.0 * hemiVolume + cylVolume);

    if (r1 < 2.0 * hemiVolume) {

        p = Sphere(Vector3::zero(), r).randomInteriorPoint();

        p.y += sign(p.y) * h / 2.0f;

    } else {

        // Select a point uniformly at random on a disk
        float a = uniformRandom(0, (float)twoPi());
        float r2 = sqrt(uniformRandom(0, 1)) * r;

        p = Vector3(cos(a) * r2,
                    uniformRandom(-h / 2.0f, h / 2.0f),
                    sin(a) * r2);
    }

    // Transform to world space
    CoordinateFrame cframe;
    getReferenceFrame(cframe);
    
    return cframe.pointToWorldSpace(p);
}
Ejemplo n.º 10
0
    virtual CFrame computeFrame(SimTime time) const override {
		const float angle = float(twoPi() * time) / m_period;
		return CFrame::fromXYZYPRRadians(sin(angle) * m_radius, 0, cos(angle) * m_radius, angle);
    }
Ejemplo n.º 11
0
ThirdPersonManipulator::ThirdPersonManipulator() : 
    m_axisScale(1), 
    m_dragging(false), 
    m_dragKey(GKey::LEFT_MOUSE),
    m_doubleAxisDrag(false),
    m_overAxis(NO_AXIS),
    m_maxAxisDistance2D(15),
    m_maxRotationDistance2D(10),
    m_rotationEnabled(true),
    m_translationEnabled(true),
    m_enabled(true) {

    for (int i = 0; i < NUM_GEOMS; ++i) {
        m_usingAxis[i] = false;
    }

    // Size of the 2-axis control widget
    const float hi = 0.80f, lo = 0.60f;

    // Single axis (cut a hole out of the center for grabbing all)
    const float cut = 0.20f;

    Array<Vector3> vertex;

    // Create the translation axes.  They will be rendered separately.
    vertex.clear();
    vertex.append(Vector3(cut, 0, 0), Vector3(1.1f, 0, 0));
    m_geomArray[X].line3D.append(_internal::PolyLine(vertex));
    m_geomArray[X].visible = false;

    vertex.clear();
    vertex.append(Vector3(0, cut, 0), Vector3(0, 1.1f, 0));
    m_geomArray[Y].line3D.append(_internal::PolyLine(vertex));
    m_geomArray[Y].visible = false;

    vertex.clear();
    vertex.append(Vector3(0, 0, cut), Vector3(0, 0, 1.1f));
    m_geomArray[Z].line3D.append(_internal::PolyLine(vertex));
    m_geomArray[Z].visible = false;

    // Create the translation squares that lie inbetween the axes
    if (m_doubleAxisDrag) {
        vertex.clear();
        vertex.append(Vector3(lo, hi, 0), Vector3(lo, lo, 0), Vector3(hi, lo, 0), Vector3(hi, hi, 0));
        m_geomArray[XY].poly3D.append(ConvexPolygon(vertex));

        vertex.clear();
        vertex.append(Vector3(0, hi, hi), Vector3(0, lo, hi), Vector3(0, lo, lo), Vector3(0, hi, lo));
        m_geomArray[YZ].poly3D.append(ConvexPolygon(vertex));

        vertex.clear();
        vertex.append(Vector3(lo, 0, lo), Vector3(lo, 0, hi), Vector3(hi, 0, hi), Vector3(hi, 0, lo));
        m_geomArray[ZX].poly3D.append(ConvexPolygon(vertex));
    }

    // Create the rotation circles
    const int ROT_SEGMENTS = 40;
    const float ROT_RADIUS = 0.65f;
    vertex.resize(ROT_SEGMENTS + 1);
    for (int v = 0; v <= ROT_SEGMENTS; ++v) {
        float a = twoPi() * (float)v / ROT_SEGMENTS;
        vertex[v].x = 0;
        vertex[v].y = cos(a) * ROT_RADIUS;
        vertex[v].z = sin(a) * ROT_RADIUS;
    }
    m_geomArray[RX].line3D.append(_internal::PolyLine(vertex));

    for (int v = 0; v <= ROT_SEGMENTS; ++v) {
        vertex[v] = vertex[v].zxy();
    }
    m_geomArray[RY].line3D.append(_internal::PolyLine(vertex));

    for (int v = 0; v <= ROT_SEGMENTS; ++v) {
        vertex[v] = vertex[v].zxy();
    }
    m_geomArray[RZ].line3D.append(_internal::PolyLine(vertex));

    m_posedModel = new TPMPosedModel(this);
}
Ejemplo n.º 12
0
    /** If given an IFS filename, loads it, otherwise generates
        a gear with high vertex coherence.
        Only the constructor uses G3D.  */
    Model(const std::string& filename) {

        tex = Texture::fromFile("tiny.jpg");
        textureID = tex->openGLID();

        if (filename != "") {
            Surface::Ref m = IFSModel::fromFile(filename)->pose();
            // Copy fields out into arrays
            {
                const Array<int>& index = m->triangleIndices();
                int N = index.size();
                cpuIndex.resize(N);
                System::memcpy(&cpuIndex[0], index.getCArray(), sizeof(int) * N);
            }

            {
                const MeshAlg::Geometry& g = m->objectSpaceGeometry(); 
                int N = g.vertexArray.size();
                cpuVertex.resize(N);
                cpuNormal.resize(N);
                cpuColor.resize(N);
                cpuTexCoord.resize(N);
                System::memcpy(&cpuVertex[0], g.vertexArray.getCArray(), N * sizeof(Vec3));
                System::memcpy(&cpuNormal[0], g.normalArray.getCArray(), N * sizeof(Vec3));

                for (int i = 0; i < N; ++i) {
                    // Copy the normals over the colors, too
                    cpuColor[i].x = g.normalArray[i].x * 0.5 + 0.5;
                    cpuColor[i].y = g.normalArray[i].y * 0.5 + 0.5;
                    cpuColor[i].z = g.normalArray[i].z * 0.5 + 0.5;
                    cpuColor[i].w = 1.0f;

                    // Cylindrical projection to get tex coords
                    Vector3 dir = g.vertexArray[i].direction();
                    cpuTexCoord[i].x = (atan2(dir.x, dir.z) / twoPi() + 0.5) * 5;
                    cpuTexCoord[i].y = (0.5 - dir.y * 0.5) * 5;
                }
            }
        } else {

            // Generate gear
            // Vertices per side
            const int sq = 187;

            // Number of indices
            const int N = (sq - 1) * (sq - 1) * 3 * 2;

            // Number of vertices
            const int V = sq * sq;

            // Make a grid of triangles
            cpuIndex.resize(N);
            {
                int k = 0;
                for (int i = 0; i < sq - 1; ++i) {
                    for (int j = 0; j < sq - 1; ++j) {
                        debugAssert(k < N - 5);

                        // Bottom triangle
                        cpuIndex[k + 0] = i + j * sq;
                        cpuIndex[k + 1] = i + (j + 1) * sq;
                        cpuIndex[k + 2] = (i + 1) + (j + 1) * sq;

                        // Top triangle
                        cpuIndex[k + 3] = i + j * sq;
                        cpuIndex[k + 4] = (i + 1) + (j + 1) * sq;
                        cpuIndex[k + 5] = (i + 1) + j * sq;

                        k += 6;
                    }
                }
            }

            // Create data
            cpuVertex.resize(V);
            cpuNormal.resize(V);
            cpuTexCoord.resize(V);
            cpuColor.resize(V);

            // Map V indices to a sq x sq grid
            for (int i = 0; i < sq; ++i) {
                for (int j = 0; j < sq; ++j) {

                    int v = (i + j * sq);

                    float x = (i / (float)sq - 0.5) * 2;
                    float y = 0.5 - j / (float)sq;
                    float a = x * 2 * 3.1415927;
                    float r = ceil(cos(a * 10)) * 0.05 + 0.3;

                    cpuVertex[v].x = -cos(a) * r;
                    cpuVertex[v].y = y;
                    cpuVertex[v].z = sin(a) * r;

                    // Scale the normal
                    float s = 1.0 / sqrt(0.0001 + square(cpuVertex[v].x) + square(cpuVertex[v].y) + square(cpuVertex[v].z));
                    cpuNormal[v].y = cpuVertex[v].x * s;
                    cpuNormal[v].x = cpuVertex[v].y * s;
                    cpuNormal[v].z = cpuVertex[v].z * s;

                    cpuColor[v].x = r + 0.7;
                    cpuColor[v].y = 0.5;
                    cpuColor[v].z = 1.0 - r;
                    cpuColor[v].w = 1.0f;

                    cpuTexCoord[v].x = i / (float)sq;
                    cpuTexCoord[v].y = j / (float)sq;
                }
            }
        } // if

        cpuIndex16.resize(cpuIndex.size());
        for (int i = 0; i < (int)cpuIndex.size(); ++i) {
          cpuIndex16[i] = (G3D::uint16)cpuIndex[i];
        }
    }