예제 #1
0
bool PivotScaled(ScaleValue& sv)
{
	ScaleValue noscale(Point3(1,1,1));
	Point3 p = sv.s - noscale.s;
	Point3 q(sv.q.x - noscale.q.x, sv.q.y - noscale.q.y, sv.q.z - noscale.q.z);
	float w = sv.q.w - noscale.q.w;
	float  v = p.LengthSquared() + q.LengthSquared() + w * w;
	return v > gTolerenceEpsilon;
}
예제 #2
0
bool IsScaled(Matrix3& tm)
{
	Matrix3 t(1);
	t = tm - t;
	Point3 x = t.GetRow(0), y = t.GetRow(1), z = t.GetRow(2), u = t.GetRow(3);
	float v = x.LengthSquared() + y.LengthSquared() + z.LengthSquared() + u.LengthSquared();
	if(v > gTolerenceEpsilon)
		return true;
	else
		return false;
}
// Calculate bounding sphere using average position of the points.  Better fit but slower.
void CalcCenteredSphere(Mesh& mesh, Point3& center, float& radius)
{
	int nv = mesh.getNumVerts();
	Point3 sum(0.0f, 0.0f, 0.0f);
	for (int i=0; i<nv; ++i)
		sum += mesh.getVert(i);
	center = sum / float(nv);
	float radsq = 0.0f;
	for (int i=0; i<nv; ++i){
		Point3 diff = mesh.getVert(i) - center;
		float mag = diff.LengthSquared();
		radsq = max(radsq, mag);
	}
	radius = Sqrt(radsq);
}
예제 #4
0
Point3 plDistributor::IPerpAxis(const Point3& p) const
{
    const float kMinLengthSquared = 1.e-1f;

    int minAx = p.MinComponent();
    Point3 ax(0,0,0);
    ax[minAx] = 1.f;

    Point3 perp = p ^ ax;
    if( perp.LengthSquared() < kMinLengthSquared )
    {
        // hmm, think we might be screwed, but this shouldn't happen.
    }

    return perp = perp.FNormalize();
}
예제 #5
0
// Generate local to world from face info (pos, normal, etc)
Matrix3 plDistributor::IGenerateTransform(int iRepNode, int iFace, const Point3& pt, const Point3& bary) const
{
    const float kMinVecLengthSq = 1.e-6f;
    Matrix3 l2w(true);

    // First, set the scale
    Point3 scale;
    switch( fScaleLock )
    {
    case kLockX | kLockY:
        scale.x = fRand.RandRangeF(fScaleLo.x, fScaleHi.x);
        scale.y = scale.x;
        scale.z = fRand.RandRangeF(fScaleLo.z, fScaleHi.z);
        break;
    case kLockX | kLockY | kLockZ:
        scale.x = fRand.RandRangeF(fScaleLo.x, fScaleHi.x);
        scale.y = scale.z = scale.x;
        break;
    default:
        scale.x = fRand.RandRangeF(fScaleLo.x, fScaleHi.x);
        scale.y = fRand.RandRangeF(fScaleLo.y, fScaleHi.y);
        scale.z = fRand.RandRangeF(fScaleLo.z, fScaleHi.z);
        break;
    }

    l2w.Scale(scale);

    // Next up, get the rotation.
    // First we'll randomly rotate about local Z
    float azimRot = fRand.RandMinusOneToOne() * fAzimuthRange;
    Matrix3 azimMat;
    azimMat.SetRotateZ(azimRot);

    l2w = l2w * azimMat;

    // Now align with the surface.
    // Get the interpolated surface normal.
    Point3 surfNorm = IGetSurfaceNormal(iFace, bary);

    Matrix3 repNodeTM = fRepNodes[iRepNode]->GetNodeTM(TimeValue(0));

    Point3 alignVec = repNodeTM.GetRow(2);
    alignVec = alignVec * fWorldToSurfVec;
    alignVec = FNormalize(alignVec);

    Point3 norm = surfNorm + (alignVec - surfNorm) * fAlignWgt;
    // The norm can come out of this zero length, if the surace normal
    // is directly opposite the "natural" up direction and the weight
    // is 50% (for example). In that case, this is just a bad place
    // to drop this replicant.
    if( norm.LengthSquared() < kMinVecLengthSq )
    {
        l2w.IdentityMatrix();
        return l2w;
    }
    norm = norm.Normalize();

    // Randomize through the cone around that.
    Point3 rndNorm = norm;
    Point3 rndDir = IPerpAxis(norm);
    Point3 rndOut = rndDir ^ norm;
    rndDir *= fRand.RandMinusOneToOne();
    float len = sqrt(1.f - rndDir.LengthSquared());
    rndOut *= len;
    if( fRand.RandMinusOneToOne() < 0 )
        rndOut *= -1.f;
    Point3 rndPol = rndDir + rndOut;

    float polScale = fRand.RandZeroToOne() * fTanPolarRange;

    // Combine using the bunching factor
    polScale = polScale * (1.f - fPolarBunch) + polScale * polScale * fPolarBunch;

    rndPol *= polScale;
    rndNorm += rndPol;
    norm = rndNorm.Normalize();

    // Have "up" alignment, now just generate random dir vector perpindicular to up
    Point3 dir = repNodeTM.GetRow(1);
    dir = dir * fWorldToSurfVec;
    Point3 out = dir ^ norm;
    if( out.LengthSquared() < kMinVecLengthSq )
    {
        if( fAzimuthRange < M_PI * 0.5f )
        {
            l2w.IdentityMatrix();
            return l2w;
        }
        else
        {
            dir = IPerpAxis(norm);
            out = dir ^ norm;
        }
    }
    out = FNormalize(out);
    dir = norm ^ out;

    // If our "up" direction points into the surface, return an "up" direction
    // tangent to the surface. Also, make the "dir" direction point out from
    // the surface. So if the alignVec/fAlignWgt turns the replicant around
    // to penetrate the surface, it just lies down instead.
    //
    // There's an early out here, for the case where the surface normal is
    // exactly opposed to the destination normal. This usually means the
    // surface normal is directly opposite the alignVec. In that
    // case, we just want to bag it.
    if( DotProd(norm, surfNorm) < 0 )
    {
        dir = surfNorm;
        dir = dir.Normalize();
        out = dir ^ norm;
        if( out.LengthSquared() < kMinVecLengthSq )
        {
            l2w.IdentityMatrix();
            return l2w;
        }
        out = out.Normalize();
        norm = out ^ dir;
    }

    Matrix3 align;
    align.Set(out, dir, norm, Point3(0,0,0));

    l2w = l2w * align;


    // Lastly, set the position.
    Point3 pos = pt;
    const float offset = fRand.RandRangeF(fOffsetMin, fOffsetMax);
    pos += norm * offset;
    l2w.Translate(pos);

    l2w = l2w * fSurfNode->GetObjectTM(TimeValue(0));

    return l2w;
}