hsBool plCullPoly::Validate() const
{
    const float kMinMag = 1.e-8f;
    float magSq = fNorm.MagnitudeSquared();
    if( magSq < kMinMag )
        return false;
    if( fVerts.GetCount() < 3 )
        return false;
    hsVector3 norm = hsVector3(&fVerts[1], &fVerts[0]) % hsVector3(&fVerts[2], &fVerts[0]);
    magSq = norm.MagnitudeSquared();
    if( magSq < kMinMag )
        return false;
    norm *= hsFastMath::InvSqrtAppr(magSq);
    int i;
    for( i = 3; i < fVerts.GetCount(); i++ )
    {
        hsVector3 nextNorm = hsVector3(&fVerts[i-1], &fVerts[0]) % hsVector3(&fVerts[i], &fVerts[0]);
        magSq = nextNorm.MagnitudeSquared();
        if( magSq < kMinMag )
            return false;
        nextNorm *= hsFastMath::InvSqrtAppr(magSq);
        if( nextNorm.InnerProduct(norm) < kMinMag )
            return false;
    }
    return true;
}
Beispiel #2
0
void hsBounds3Ext::unalign() {
    fCorner = fMins;
    fExtFlags = 0;

    float x = fMaxs.X - fMins.X;
    if (x < 0.00001) {
        fExtFlags |= kAxisZeroZero;
        x = 1.0;
    }
    fAxes[0] = hsVector3(x, 0.0, 0.0);

    float y = fMaxs.Y - fMins.Y;
    if (y < 0.00001) {
        fExtFlags |= kAxisOneZero;
        y = 1.0;
    }
    fAxes[1] = hsVector3(0.0, y, 0.0);

    float z = fMaxs.Z - fMins.Z;
    if (z < 0.00001) {
        fExtFlags |= kAxisTwoZero;
        z = 1.0;
    }
    fAxes[2] = hsVector3(0.0, 0.0, z);
}
Beispiel #3
0
static int pyVector3___init__(pyVector3* self, PyObject* args, PyObject* kwds) {
    float x = 0.0f, y = 0.0f, z = 0.0f;
    PyObject* init = NULL;
    static char* kwlist[] = { _pycs("X"), _pycs("Y"), _pycs("Z"), NULL };
    static char* kwlist2[] = { _pycs("vector"), NULL };

    if (PyArg_ParseTupleAndKeywords(args, kwds, "fff", kwlist, &x, &y, &z)) {
        (*self->fThis) = hsVector3(x, y, z);
    } else if (PyErr_Clear(), PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwlist2, &init)) {
        if (init == NULL) {
            (*self->fThis) = hsVector3();
            return 0;
        }
        if (pyVector3_Check(init)) {
            (*self->fThis) = (*((pyVector3*)init)->fThis);
        } else {
            PyErr_SetString(PyExc_TypeError, "__init__ expects a vector");
            return -1;
        }
    } else {
        return -1;
    }

    return 0;
}
Beispiel #4
0
static bool     PointsOnSameSide( const hsPoint3 &line1, const hsPoint3 &line2, const hsPoint3 &pointA, const hsPoint3 &pointB )
{
    hsVector3 baseVec( &line2, &line1 );
    hsVector3   cp1 = hsVector3( &pointA, &line1 ) % baseVec;
    hsVector3   cp2 = hsVector3( &pointB, &line1 ) % baseVec;
    return ( cp1.fZ * cp2.fZ > 0 ) ? true : false;
}
static int pySpanTemplateVertex_setUVWs(pySpanTemplateVertex* self, PyObject* value, void*) {
    hsTArray<hsVector3> uvws;
    if (value == NULL || !PyList_Check(value)) {
        PyErr_SetString(PyExc_TypeError, "UVWs should be a list of up to 10 hsVector3 objects");
        return -1;
    }
    uvws.setSize(PyList_Size(value));
    if (uvws.getSize() > 10) {
        PyErr_SetString(PyExc_RuntimeError, "UVWs should be a list of up to 10 hsVector3 objects");
        return -1;
    }
    for (size_t i=0; i<uvws.getSize(); i++) {
        PyObject* itm = PyList_GetItem(value, i);
        if (!pyVector3_Check(itm)) {
            PyErr_SetString(PyExc_TypeError, "UVWs should be a list of up to 10 hsVector3 objects");
            return -1;
        }
        uvws[i] = *((pyVector3*)itm)->fThis;
    }
    for (size_t i=0; i<uvws.getSize(); i++)
        self->fThis->fUVWs[i] = uvws[i];
    for (size_t i=uvws.getSize(); i<10; i++)
        self->fThis->fUVWs[i] = hsVector3(0.0f, 0.0f, 0.0f);
    return 0;
}
//
// find the up vector for this object (if there are more than one, just the first one)
PyObject* pySceneObject::GetRightVector()
{
    // make sure that there are sceneobjects
    if ( fSceneObjects.Count() > 0 )
    {
        // get the object pointer of just the first one in the list
        // (We really can't tell which one the user is thinking of if they are
        // referring to multiple objects, so the first one in the list will do.)
        plSceneObject* obj = plSceneObject::ConvertNoRef(fSceneObjects[0]->ObjectIsLoaded());
        if ( obj )
        {
            const plCoordinateInterface* ci = obj->GetCoordinateInterface();
            if ( ci )
                return pyVector3::New(ci->GetLocalToWorld().GetAxis(hsMatrix44::kRight));
            else
            {
                plString errmsg = plString::Format("Sceneobject %s does not have a coordinate interface.",
                                                   obj->GetKeyName().c_str());
                PyErr_SetString(PyExc_RuntimeError, errmsg.c_str());
                return nil; // return nil to tell python we errored
            }
        }
    }
    // if we couldn't find any sceneobject or a coordinate interface
    return pyVector3::New(hsVector3(0,0,0));
}
void plAnimatedMovementStrategy::IRecalcAngularVelocity(float elapsed, hsMatrix44 &prevMat, hsMatrix44 &curMat)
{
    fAnimAngularVel = 0.0f;
    float appliedVelocity = 0.0f;
    hsVector3 prevForward = GetYAxis(prevMat);
    hsVector3 curForward = GetYAxis(curMat);

    float angleSincePrev = AngleRad2d(curForward.fX, curForward.fY, prevForward.fX, prevForward.fY);
    bool sincePrevSign = angleSincePrev > 0.0f;
    if (angleSincePrev > float(M_PI))
        angleSincePrev = angleSincePrev - TWO_PI;

    const hsVector3 startForward = hsVector3(0.0f, -1.0f, 0.0f);    // the Y orientation of a "resting" armature....
    float angleSinceStart = AngleRad2d(curForward.fX, curForward.fY, startForward.fX, startForward.fY);
    bool sinceStartSign = angleSinceStart > 0.0f;
    if (angleSinceStart > float(M_PI))
        angleSinceStart = angleSinceStart - TWO_PI;

    // HANDLING ANIMATION WRAPPING:
    // under normal conditions, the angle from rest to the current frame will have the same
    // sign as the angle from the previous frame to the current frame.
    // if it does not, we have (most likely) wrapped the motivating animation from frame n back
    // to frame zero, creating a large angle from the previous frame to the current one
    if (sincePrevSign == sinceStartSign)
    {
        // signs are the same; didn't wrap; use the frame-to-frame angle difference
        appliedVelocity = angleSincePrev / elapsed;	// rotation / time
        if (fabs(appliedVelocity) < 3)
        {
            fAnimAngularVel = appliedVelocity;
        }
    }
}
Beispiel #8
0
static int pyPlane3___init__(pyPlane3* self, PyObject* args, PyObject* kwds) {
    float x = 0.0f, y = 0.0f, z = 0.0f, w = 0.0f;
    PyObject* init = NULL;
    static char* kwlist[] = { "X", "Y", "Z", "W", NULL };
    static char* kwlist2[] = { "Plane", NULL };

    if (PyArg_ParseTupleAndKeywords(args, kwds, "ffff", kwlist, &x, &y, &z, &w)) {
        (*self->fThis) = hsPlane3(hsVector3(x, y, z), w);
    } else if (PyErr_Clear(), PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwlist2, &init)) {
        if (init == NULL) {
            (*self->fThis) = hsPlane3();
            return 0;
        }
        if (pyPlane3_Check(init)) {
            (*self->fThis) = (*((pyPlane3*)init)->fThis);
        } else {
            PyErr_SetString(PyExc_TypeError, "__init__ expects a Plane");
            return -1;
        }
    } else {
        return -1;
    }

    return 0;
}
PyObject* pySceneObject::GetAvatarVelocity()
{
    // loop through all the sceneobject... looking for avatar modifiers
    int j;
    for ( j=0 ; j<fSceneObjects.Count() ; j++ )
    {
        // get the object pointer of just the first one in the list
        // (We really can't tell which one the user is thinking of if they are
        // referring to multiple objects, so the first one in the list will do.)
        plSceneObject* obj = plSceneObject::ConvertNoRef(fSceneObjects[j]->ObjectIsLoaded());
        if ( obj )
        {
            // search through its modifiers to see if one of them is an avatar modifier
            int i;
            for ( i=0; i<obj->GetNumModifiers(); i++ )
            {
                const plModifier* mod = obj->GetModifier(i);
                // see if it is an avatar mod base class
                const plArmatureMod* avatar = plArmatureMod::ConvertNoRef(mod);
                if ( avatar && avatar->GetController() )
                {
                    hsVector3 vel = avatar->GetController()->GetLinearVelocity();
                    return pyVector3::New(vel);
                }
            }
        }
    }

    // if we couldn't find any sceneobject that had an avatar mod then this ain't an avatar
    return pyVector3::New(hsVector3(0,0,0));
}
hsVector3 plAvBrainCritter::VectorToPlayer(unsigned long id) const
{
    plArmatureMod* avatar = plAvatarMgr::GetInstance()->FindAvatarByPlayerID(id);
    if (!avatar)
        return hsVector3(0, 0, 0);

    hsPoint3 avPos;
    hsQuat avRot;
    avatar->GetPositionAndRotationSim(&avPos, &avRot);

    hsPoint3 creaturePos;
    hsQuat creatureRot;
    fAvMod->GetPositionAndRotationSim(&creaturePos, &creatureRot);

    return hsVector3(creaturePos - avPos);
}
void plPXPhysicalControllerCore::IDrawDebugDisplay()
{
    plDebugText     &debugTxt = plDebugText::Instance();
    char            strBuf[ 2048 ];
    int             lineHeight = debugTxt.GetFontSize() + 4;
    uint32_t          scrnWidth, scrnHeight;

    debugTxt.GetScreenSize( &scrnWidth, &scrnHeight );
    int y = 10;
    int x = 10;

    sprintf(strBuf, "Controller Count: %d", gControllers.size());
    debugTxt.DrawString(x, y, strBuf);
    y += lineHeight;

    debugTxt.DrawString(x, y, "Avatar Collisions:");
    y += lineHeight;

    int i;
    for (i = 0; i < fDbgCollisionInfo.GetCount(); i++)
    {
        hsVector3 normal = fDbgCollisionInfo[i].fNormal;
        char *overlapStr = fDbgCollisionInfo[i].fOverlap ? "yes" : "no";
        float angle = hsRadiansToDegrees(acos(normal * hsVector3(0, 0, 1)));
        sprintf(strBuf, "    Obj: %s, Normal: (%.2f, %.2f, %.2f), Angle(%.1f), Overlap(%3s)",
                fDbgCollisionInfo[i].fSO->GetKeyName().c_str(),
                normal.fX, normal.fY, normal.fZ, angle, overlapStr);
        debugTxt.DrawString(x, y, strBuf);
        y += lineHeight;
    }
}
void plCullNode::ITakeHalfPoly(const plCullPoly& srcPoly, 
                               const hsTArray<int>& vtxIdx, 
                               const hsBitVector& onVerts, 
                               plCullPoly& outPoly) const
{
    if( vtxIdx.GetCount() > 2 )
    {
        int i;
        for( i = 0; i < vtxIdx.GetCount(); i++ )
        {
            int next = i < vtxIdx.GetCount()-1 ? i+1 : 0;
            int last = i ? i-1 : vtxIdx.GetCount()-1;

            // If these 3 verts are all on the plane, we may have created a collinear vertex (the middle one)
            // which we now want to skip.
            if( onVerts.IsBitSet(vtxIdx[i]) && onVerts.IsBitSet(vtxIdx[last]) && onVerts.IsBitSet(vtxIdx[next]) )
            {
#if 0 // FISH
                float dot = hsVector3(&srcPoly.fVerts[vtxIdx[last]], &srcPoly.fVerts[vtxIdx[i]]).InnerProduct(hsVector3(&srcPoly.fVerts[vtxIdx[next]], &srcPoly.fVerts[vtxIdx[i]]));
                if( dot <= 0 )
#endif // FISH
                    continue;
            }
            if( srcPoly.fClipped.IsBitSet(vtxIdx[i])
                ||(onVerts.IsBitSet(vtxIdx[i]) && onVerts.IsBitSet(vtxIdx[next])) )
                    outPoly.fClipped.SetBit(outPoly.fVerts.GetCount());
            outPoly.fVerts.Append(srcPoly.fVerts[vtxIdx[i]]);
        }
    }
    else
    {
        // Just need a break point
        hsStatusMessage("Under 2"); // FISH
    }
}
void plCullTree::IVisPolyEdge(const hsPoint3& p0, const hsPoint3& p1, hsBool dark) const
{
    hsColorRGBA color;
    if( dark )
        color.Set(0.2f, 0.2f, 0.2f, 1.f);
    else
        color.Set(1.f, 1.f, 1.f, 1.f);

    int vertStart = fVisVerts.GetCount();

    hsVector3 dir0(&p0, &fViewPos);
    hsFastMath::NormalizeAppr(dir0);
    dir0 *= fVisYon;
    hsVector3 dir1(&p1, &fViewPos);
    hsFastMath::NormalizeAppr(dir1);
    dir1 *= fVisYon;

    hsPoint3 p3 = fViewPos;
    p3 += dir0;
    hsPoint3 p2 = fViewPos;
    p2 += dir1;

    hsVector3 norm = hsVector3(&p0, &fViewPos) % hsVector3(&p1, &fViewPos);
    hsFastMath::NormalizeAppr(norm);

    fVisVerts.Append(p0);
    fVisNorms.Append(norm);
    fVisColors.Append(color);
    fVisVerts.Append(p1);
    fVisNorms.Append(norm);
    fVisColors.Append(color);
    fVisVerts.Append(p2);
    fVisNorms.Append(norm);
    fVisColors.Append(color);
    fVisVerts.Append(p3);
    fVisNorms.Append(norm);
    fVisColors.Append(color);

    fVisTris.Append(vertStart + 0);
    fVisTris.Append(vertStart + 2);
    fVisTris.Append(vertStart + 1);

    fVisTris.Append(vertStart + 0);
    fVisTris.Append(vertStart + 3);
    fVisTris.Append(vertStart + 2);
}
Beispiel #14
0
hsTArray<hsVector3> plSpanInstance::getPosDeltas() const {
    hsTArray<hsVector3> verts;
    verts.setSize(fNumVerts);

    switch (fEncoding.getCode() & plSpanEncoding::kPosMask) {
    case plSpanEncoding::kPos888:
        {
            unsigned char* pp = fPosDelta;
            for (unsigned int i=0; i<fNumVerts; i++) {
                verts[i].X = pp[0] * fEncoding.getPosScale();
                verts[i].Y = pp[1] * fEncoding.getPosScale();
                verts[i].Z = pp[2] * fEncoding.getPosScale();
                pp += 3;
            }
        }
        break;
    case plSpanEncoding::kPos161616:
        {
            unsigned short* pp = (unsigned short*)fPosDelta;
            for (unsigned int i=0; i<fNumVerts; i++) {
                verts[i].X = pp[0] * fEncoding.getPosScale();
                verts[i].Y = pp[1] * fEncoding.getPosScale();
                verts[i].Z = pp[2] * fEncoding.getPosScale();
                pp += 3;
            }
        }
        break;
    case plSpanEncoding::kPos101010:
        {
            unsigned int* pp = (unsigned int*)fPosDelta;
            for (unsigned int i=0; i<fNumVerts; i++) {
                verts[i].Z = ((*pp >> 20) & 0x3F) * fEncoding.getPosScale();
                verts[i].Y = ((*pp >> 10) & 0x3F) * fEncoding.getPosScale();
                verts[i].X = ((*pp >>  0) & 0x3F) * fEncoding.getPosScale();
                pp++;
            }
        }
        break;
    case plSpanEncoding::kPos008:
        {
            unsigned char* pp = fPosDelta;
            for (unsigned int i=0; i<fNumVerts; i++) {
                verts[i].X = 0.0f;
                verts[i].Y = 0.0f;
                verts[i].Z = (*pp) * fEncoding.getPosScale();
                pp++;
            }
        }
        break;
    default:
        for (unsigned int i=0; i<fNumVerts; i++)
            verts[i] = hsVector3(0.0f, 0.0f, 0.0f);
        break;
    }
    return verts;
}
void plAvBrainCritter::SightCone(float coneRad)
{
    fSightConeAngle = coneRad;

    // calculate the minimum dot product for the cone of sight (angle/2 vector dotted with straight ahead)
    hsVector3 straightVector(1, 0, 0), viewVector(1, 0, 0), up(0, 1, 0);
    hsQuat rotation(fSightConeAngle/2, &up);
    viewVector = hsVector3(rotation.Rotate(&viewVector));
    viewVector.Normalize();
    fSightConeDotMin = straightVector * viewVector;
}
float plCullPoly::ICalcRadius() const
{
    float radSq = 0;
    int i;
    for( i = 0; i < fVerts.GetCount(); i++ )
    {
        float tmpSq = hsVector3(&fVerts[i], &fCenter).MagnitudeSquared();
        if( tmpSq > radSq )
            radSq = tmpSq;
    }
    return radSq * hsFastMath::InvSqrt(radSq);
}
void plPhysicalControllerCore::MoveActorToSim()
{
        // Get the current position of the physical
        hsPoint3 curLocalPos;
        hsPoint3 lastLocalPos;
        GetPositionSim(curLocalPos);
        MoveKinematicToController(curLocalPos);
        lastLocalPos=GetLocalPosition();
        fDisplacementThisStep=  hsVector3(curLocalPos - lastLocalPos);
        fLocalPosition = curLocalPos;
        if(fSimLength>0.0f)
        fAchievedLinearVelocity=fDisplacementThisStep/fSimLength;
        else fAchievedLinearVelocity.Set(0.0f,0.0f,0.0f);
}
Beispiel #18
0
float plAnimPath::ICheckInterval(hsPoint3 &pt) const
{
    if( fDelTime <= kTerminateDelTime &&
        hsVector3(&fCurPos, &fPrevPos).MagnitudeSquared() < kTerminateDelDistSq)
    {
        return IBestTime();
    }

    if( fThisTime < 0 )
        return 0;

    if( fThisTime > fLength )
        return fLength;

    if( GetFarthest() )
    {
        if( (fLastDistSq > fThisDistSq)&&(fLastDistSq >= fNextDistSq) )
            return IShiftBack(pt);

        if( (fNextDistSq > fThisDistSq)&&(fNextDistSq >= fLastDistSq) )
            return IShiftFore(pt);

        if( (fThisDistSq >= fLastDistSq)&&(fLastDistSq >= fNextDistSq) )
            return ISubDivBack(pt);

        if( (fThisDistSq >= fNextDistSq)&&(fNextDistSq >= fLastDistSq) )
            return ISubDivFore(pt);
    }
    else
    {
        if( (fLastDistSq < fThisDistSq)&&(fLastDistSq <= fNextDistSq) )
            return IShiftBack(pt);

        if( (fNextDistSq < fThisDistSq)&&(fNextDistSq <= fLastDistSq) )
            return IShiftFore(pt);

        if( (fThisDistSq <= fLastDistSq)&&(fLastDistSq <= fNextDistSq) )
            return ISubDivBack(pt);

        if( (fThisDistSq <= fNextDistSq)&&(fNextDistSq <= fLastDistSq) )
            return ISubDivFore(pt);
    }

    hsAssert(false, "Shouldn't have gotten here");
    return 0;
}
void plPhysicalControllerCore::IncrementAngle(float deltaAngle)
{
    float angle;
    hsVector3 axis;
    fLocalRotation.NormalizeIfNeeded();
    fLocalRotation.GetAngleAxis(&angle, &axis);
    // adjust it (quaternions are weird...)
    if (axis.fZ < 0)
        angle = (2*M_PI) - angle; // axis is backwards, so reverse the angle too
    angle += deltaAngle;
    // make sure we wrap around
    if (angle < 0)
        angle = (2*M_PI) + angle; // angle is -, so this works like a subtract
    if (angle >= (2*M_PI))
        angle = angle - (2*M_PI);
    // and set the new angle
    fLocalRotation.SetAngleAxis(angle, hsVector3(0,0,1));
}
Beispiel #20
0
//
// Precompute array of arclen deltas for lookahead ability.
// Changes current time!
//
void plAnimPath::ComputeArcLenDeltas(int32_t numSamples)
{
    if (fArcLenDeltas.GetCount() >= numSamples)
        return;     // already computed enough samples

    // compute arc len deltas
    fArcLenDeltas.Reset();
    fArcLenDeltas.SetCount(numSamples);
    float animLen = GetLength();
    float timeInc = animLen/(numSamples-1);  // use num-1 since we'll create the zeroth entry by hand
    float time=0;
    hsPoint3 p1, p2;

    int32_t cnt=0;

    // prime initial point
    SetCurTime(0, kCalcPosOnly);
    GetPosition(&p1);
    ArcLenDeltaInfo aldi(time, 0);
    fArcLenDeltas[cnt++]=aldi;
    time += timeInc;

    bool quit=false;
    while(!quit && time<animLen+timeInc)
    {
        if (time > animLen || cnt+1 == numSamples)
        {
            time = animLen;
            quit=true;
        }

        SetCurTime(time, kCalcPosOnly);
        GetPosition(&p2);

        ArcLenDeltaInfo aldi(time, hsVector3(&p2, &p1).Magnitude());
        fArcLenDeltas[cnt++]=aldi;

        time += timeInc;
        p1 = p2;
    }
    hsAssert(fArcLenDeltas.GetCount()==numSamples, "arcLenArray size wrong?");
    hsAssert(cnt==numSamples, "arcLenArray size wrong?");
}
Beispiel #21
0
void hsMatrix44::MakeEnvMapMatrices(const hsPoint3& pos, hsMatrix44* worldToCameras, hsMatrix44* cameraToWorlds)
{
    MakeCameraMatrices(pos, hsPoint3(pos.fX - 1.f, pos.fY, pos.fZ), hsVector3(0, 0, 1.f), worldToCameras[0], cameraToWorlds[0]);

    MakeCameraMatrices(pos, hsPoint3(pos.fX + 1.f, pos.fY, pos.fZ), hsVector3(0, 0, 1.f), worldToCameras[1], cameraToWorlds[1]);

    MakeCameraMatrices(pos, hsPoint3(pos.fX, pos.fY + 1.f, pos.fZ), hsVector3(0, 0, 1.f), worldToCameras[2], cameraToWorlds[2]);

    MakeCameraMatrices(pos, hsPoint3(pos.fX, pos.fY - 1.f, pos.fZ), hsVector3(0, 0, 1.f), worldToCameras[3], cameraToWorlds[3]);

    MakeCameraMatrices(pos, hsPoint3(pos.fX, pos.fY, pos.fZ + 1.f), hsVector3(0, -1.f, 0), worldToCameras[4], cameraToWorlds[4]);

    MakeCameraMatrices(pos, hsPoint3(pos.fX, pos.fY, pos.fZ - 1.f), hsVector3(0, 1.f, 0), worldToCameras[5], cameraToWorlds[5]);
}
Beispiel #22
0
// There's actually a possibly faster way to do all this.
// The barycentric coordinate in 3-space is the same as the barycentric coordinate of the projection
// in 2-space, as long as the projection doesn't degenerate the triangle (i.e. project the tri onto
// a plane perpindicular to the tri). The tri can't be perpindicular to all three major axes, so by
// picking the right one (or just not picking the wrong one), the lengths of the cross products becomes
// just the z component (e.g. v0.x*v1.y - v0.y*v1.x), so all the square roots go away (not to mention all
// the vector math going from 3 component to 2).
plTriUtils::Bary plTriUtils::ComputeBarycentricProjection(const hsPoint3& p0, const hsPoint3& p1, const hsPoint3& p2, hsPoint3&p, hsPoint3& out)
{
    hsVector3 v12(&p1, &p2);
    hsVector3 v02(&p0, &p2);
    hsVector3 norm = Cross(v12, v02);

    float invLenSq12 = norm.MagnitudeSquared();
    if( invLenSq12 < kAlmostZero )
        return kDegenerateTri; // degenerate triangle

    invLenSq12 = 1.f / invLenSq12;

    p += norm * (hsVector3(&p2, &p).InnerProduct(norm) * invLenSq12);

    hsVector3 vp2(&p, &p2);
    hsVector3 v0 = Cross(v12, vp2);
    hsVector3 v1 = Cross(vp2, v02);

    return IComputeBarycentric(norm, invLenSq12, v0, v1, out);
}
Beispiel #23
0
bool plDynaBulletMgr::IHandleShot(plBulletMsg* bull)
{
    hsVector3 up = IRandomUp(bull->Dir());

    hsPoint3 pos = bull->From() + bull->Dir() * (bull->Range() * 0.5f);
    fCutter->SetLength(hsVector3(bull->Radius() * fScale.fX, bull->Radius() * fScale.fY, bull->Range()));
    fCutter->Set(pos, up, -bull->Dir());

    plDynaDecalInfo& info = IGetDecalInfo(uintptr_t(this), GetKey());

    if( bull->PartyTime() > 0 )
        fPartyTime = bull->PartyTime();

    double secs = hsTimer::GetSysSeconds();

    if( ICutoutTargets(secs) )
        info.fLastTime = secs;
    
    return true;
}
Beispiel #24
0
void plSwimStraightCurrentRegion::GetCurrent(plPhysicalControllerCore *physical, hsVector3 &linearResult, float &angularResult, float elapsed)
{
    angularResult = 0.f;

    if (elapsed <= 0.f || GetProperty(kDisable))
    {
        linearResult.Set(0.f, 0.f, 0.f);
        return;
    }

    hsPoint3 center, pos;
    hsVector3 current = fCurrentSO->GetLocalToWorld() * hsVector3(0.f, 1.f, 0.f);
    hsScalarTriple xlate = fCurrentSO->GetLocalToWorld().GetTranslate();
    center.Set(&xlate);
    physical->GetPositionSim(pos);

    plKey worldKey = physical->GetSubworld();
    if (worldKey)
    {
        plSceneObject* so = plSceneObject::ConvertNoRef(worldKey->ObjectIsLoaded());
        hsMatrix44 w2l = so->GetWorldToLocal();
        center = w2l * center;
        current = w2l * current;
    }

    hsVector3 pos2Center(center.fX - pos.fX, center.fY - pos.fY, 0.f);
    float dist = current.InnerProduct(pos - center);
    float pullVel;
    
    if (dist <= fNearDist)
        pullVel = fNearVel;
    else if (dist >= fFarDist)
        pullVel = fFarVel;
    else
        pullVel = fNearVel + (fFarVel - fNearVel) * (dist - fNearDist) / (fFarDist - fNearDist);

    linearResult = current * pullVel;
}   
Beispiel #25
0
static inline hsVector3 Cross(const hsScalarTriple& p0, const hsScalarTriple& p1)
{
    return hsVector3(p0.fY * p1.fZ - p0.fZ * p1.fY, 
                    p0.fZ * p1.fX - p0.fX * p1.fZ, 
                    p0.fX * p1.fY - p0.fY * p1.fX);
}
Beispiel #26
0
void plPXPhysical::ClearLinearVelocity()
{
    SetLinearVelocitySim(hsVector3(0, 0, 0));
}
void plRidingAnimatedPhysicalStrategy::Apply(float delSecs)
{
    hsVector3 LinearVelocity=fCore->GetLinearVelocity();
    hsVector3 AchievedLinearVelocity=fCore->GetAchievedLinearVelocity();
    if (fCore->IsKinematic())
    {   
        //want to make sure nothing funky happens in the sim
        IApplyKinematic();
        return;
    }
    if (!fCore->IsEnabled())
        return;

    //need to sweep ahead to see what we might hit. 
    // if we hit anything we should probably apply the force that would normally be applied in

    
    fCore->SetPushingPhysical(nil);
    fCore->SetFacingPushingPhysical( false);
    plSceneObject* so = plSceneObject::ConvertNoRef(fOwner->ObjectIsLoaded());
    hsPoint3 startPos, desiredDestination, endPos;
    fCore->GetPositionSim(startPos);
    uint32_t collideFlags =
    1<<plSimDefs::kGroupStatic |
    1<<plSimDefs::kGroupAvatarBlocker |
    1<<plSimDefs::kGroupDynamic;
    std::multiset<plControllerSweepRecord> GroundHitRecords;
    int possiblePlatformCount =fCore->SweepControllerPath(startPos, startPos + hsPoint3(0.f,0.f, -0.002f), true, true, collideFlags, GroundHitRecords);
    float maxPlatformVel = - FLT_MAX;
    int platformCount=0;
    fGroundHit = false;
    if(possiblePlatformCount)
    {
        
        std::multiset<plControllerSweepRecord>::iterator curRecord; 

        for(curRecord = GroundHitRecords.begin(); curRecord != GroundHitRecords.end(); curRecord++)
        {
            hsBool groundlike=false;
            if((curRecord->locHit.fZ - startPos.fZ)<= .2) groundlike= true;
            if(groundlike)
            {
                if(curRecord->ObjHit !=nil)
                {
                    hsVector3 vel;
                    curRecord->ObjHit->GetLinearVelocitySim(vel);
                    if(vel.fZ > maxPlatformVel)
                    {
                        maxPlatformVel= vel.fZ;
                    }
                }
                platformCount ++;
                fGroundHit = true;
            }
        }
    }
    
    
    
    bool gotGroundHit = fGroundHit;
    if (so)
    {
        
        // If we've been moved since the last physics update (somebody warped us),
        // update the physics before we apply velocity.
        const hsMatrix44& l2w = so->GetCoordinateInterface()->GetLocalToWorld();
        if (!CompareMatrices(l2w, fCore->GetLastGlobalLoc(), .0001f))
            fCore->SetGlobalLoc(l2w);

        // Convert our avatar relative velocity to subworld relative
        if (!LinearVelocity.IsEmpty())
        {
            LinearVelocity = l2w * LinearVelocity;
            const plCoordinateInterface* subworldCI = fCore->GetSubworldCI();
            if (subworldCI)
                LinearVelocity = subworldCI->GetWorldToLocal() * LinearVelocity;
        }
        
        if(!IsOnGround())
        {
            if(!fNeedVelocityOverride)
            {
                LinearVelocity.fZ= AchievedLinearVelocity.fZ;
            }
            else
            {
                LinearVelocity = fOverrideVelocity;
            }
        }
        if(fStartJump)
        {
            LinearVelocity.fZ =12.0f;
        }
        if(platformCount)
        {
            LinearVelocity.fZ = LinearVelocity.fZ + maxPlatformVel;
        }

        //probably neeed to do something with contact normals in here
        //for false ground stuff
        
        fFalseGround = false;
        hsVector3 testLength = LinearVelocity * delSecs + hsVector3(0.0, 0.0, -0.00f);
    //
        hsPoint3 desiredDestination= startPos + testLength;
        if(!IsOnGround())
        {
            if(ICheckMove(startPos, desiredDestination))
            {//we can get there soley by the LinearVelocity
                
                fNeedVelocityOverride =false;
            }
            else
            {
                
                fNeedVelocityOverride =true;
                fOverrideVelocity = LinearVelocity;
                fOverrideVelocity.fZ -=  delSecs * 32.f;
            }
        }
        else
        {
            fNeedVelocityOverride =false;
        }

        fCore->SetLinearVelocity(LinearVelocity);
    
    }
}
hsBool plDynaRippleVSMgr::IRippleFromShape(const plPrintShape* shape, hsBool force)
{
    if( !ICheckRTMat() )
        return false;

    if( !shape )
        return false;

    hsBool retVal = false;

    plDynaDecalInfo& info = IGetDecalInfo(uintptr_t(shape), shape->GetKey());

    const hsMatrix44& shapeL2W = shape->GetOwner()->GetLocalToWorld();

    plConst(float) kMinDist(2.0f);
    plConst(float) kMinTime(1.5f);
    double t = hsTimer::GetSysSeconds();
    float dt = float(t - info.fLastTime) * sRand.RandZeroToOne();
    hsBool longEnough = (dt >= kMinTime);
    hsPoint3 xlate = shapeL2W.GetTranslate();
    hsBool farEnough = (hsVector3(&info.fLastPos, &xlate).Magnitude() > kMinDist);
    if( force || longEnough || farEnough )
    {
        hsPoint3 pos = shapeL2W.GetTranslate();

        // We'll perturb the position a little so it doesn't look quite so regular,
        // but we perturb it more if we're just standing still
        hsVector3 randPert(sRand.RandMinusOneToOne(), sRand.RandMinusOneToOne(), 0);
        randPert.Normalize();
        if( !farEnough )
        {
            plConst(float) kRandPert = 0.5f;
            randPert *= kRandPert;
        }
        else
        {
            plConst(float) kRandPert = 0.15f;
            randPert *= kRandPert;
        }
        pos += randPert;

        // Are we potentially touching the water?
        float waterHeight = fWaveSetBase->GetHeight();
        if( (pos.fZ - fScale.fZ * shape->GetHeight() < waterHeight)
            &&(pos.fZ + fScale.fZ * shape->GetHeight() > waterHeight) )
        {

            hsVector3 dir(fWaveSetBase->GetWindDir());
            hsVector3 up(0.f, 0.f, 1.f);

            float wid = hsMaximum(shape->GetWidth(), shape->GetLength());
            
            plConst(float) kMaxWaterDepth(1000.f);

            hsVector3 size(wid * fScale.fX, wid * fScale.fY, kMaxWaterDepth);
            fCutter->SetLength(size);
            fCutter->Set(pos, dir, up);


            hsBool hit = ICutoutTargets(t);
            if( hit )
            {
                info.fLastTime = t;
                info.fLastPos = shapeL2W.GetTranslate();
                retVal = true;
            }
            else
            {
                retVal = false; // No-effect else just for break points.
            }
        }
    }
    return retVal;
}
bool plRidingAnimatedPhysicalStrategy::ICheckMove(const hsPoint3& startPos, const hsPoint3& desiredPos)
{
    //returns false if it believes the end result can't be obtained by pure application of velocity (collides into somthing that it can't climb up)
    //used as a way to check if it needs to hack getting there like in jumping
    
    uint32_t collideFlags =
    1<<plSimDefs::kGroupStatic |
    1<<plSimDefs::kGroupAvatarBlocker |
    1<<plSimDefs::kGroupDynamic;
    bool hitBottomOfCapsule=false;
    bool hitOther=false;
    float timeOfOtherHits = FLT_MAX;
    float timeFirstBottomHit =  -1.0;
    if(!fCore->IsSeeking())
    {
        collideFlags|=(1<<plSimDefs::kGroupExcludeRegion);
    }
    if((desiredPos.fZ - startPos.fZ) < -1.f)//we will let gravity take care of it when falling
        return true;
    fContactNormals.SetCount(0);
    std::multiset< plControllerSweepRecord > DynamicHits;
    int NumberOfHits=fCore->SweepControllerPath(startPos, desiredPos, true, true, collideFlags, DynamicHits);

    hsPoint3 stepFromPoint;
    hsVector3  movementdir(&startPos, &desiredPos);
    movementdir.Normalize();
    if(NumberOfHits)
    {
        hsPoint3 initBottomPos;
        fCore->GetPositionSim(initBottomPos);
        std::multiset< plControllerSweepRecord >::iterator cur;
        hsVector3 testLength(desiredPos - startPos);
        bool freeMove=true;
        for(cur = DynamicHits.begin();  cur != DynamicHits.end(); cur++)
        {
            if(movementdir.InnerProduct(cur->Norm)>0.01f)
            {
                hsVector3 topOfBottomHemAtTimeT=hsVector3(initBottomPos + testLength * cur->TimeHit );
                topOfBottomHemAtTimeT.fZ = topOfBottomHemAtTimeT.fZ + fCore->GetControllerWidth();
                if(cur->locHit.fZ <= (topOfBottomHemAtTimeT.fZ -.5f))
                {
                    hitBottomOfCapsule=true;
                    hsVector3 norm= hsVector3(-1*(cur->locHit-topOfBottomHemAtTimeT));
                    norm.Normalize();
                    IAddContactNormals(norm);
                }
                else
                {
                    return false;
                }
            }

        }
        return true;
    }
    else
    {
        return true;
    }
    
}
Beispiel #30
0
void plBlower::IBlow(double secs, float delSecs)
{
    hsPoint3 worldPos = fTarget->GetLocalToWorld().GetTranslate();
    hsPoint3 localPos = fTarget->GetLocalToParent().GetTranslate();

    // fast oscillation vs slow

    // Completely random walk in the rotation

    // Strength = Strength + rnd01 * (MaxStrength - Strength)

    float t = (fAccumTime += delSecs);

    float strength = 0;
    int i;
    for( i = 0; i < fOscillators.GetCount(); i++ )
    {
        float c, s;
        t *= fOscillators[i].fFrequency * fMasterFrequency;
        t += fOscillators[i].fPhase;
        hsFastMath::SinCosAppr(t, s, c);
        c += fBias;
        strength += c * fOscillators[i].fPower;
    }
    strength *= fMasterPower;

    if( strength < 0 )
        strength = 0;

    fDirection.fX += fRandom.RandMinusOneToOne() * delSecs * fDirectRate;
    fDirection.fY += fRandom.RandMinusOneToOne() * delSecs * fDirectRate;

    hsFastMath::NormalizeAppr(fDirection);

    float offDist = hsVector3(&fRestPos, &worldPos).Magnitude();
    if( offDist > fMaxOffsetDist )
        fMaxOffsetDist = offDist;

    hsVector3 force = fDirection * strength;

    static float kOffsetDistFrac = 0.5f; // make me const
    if( offDist > fMaxOffsetDist * kOffsetDistFrac )
    {
        offDist /= fMaxOffsetDist;
        offDist *= fMasterPower;

        float impulse = offDist * delSecs * fImpulseRate;

        force.fX += impulse * fRandom.RandMinusOneToOne();
        force.fY += impulse * fRandom.RandMinusOneToOne();
        force.fZ += impulse * fRandom.RandMinusOneToOne();
    }
    const float kOffsetDistDecay = 0.999f;
    fMaxOffsetDist *= kOffsetDistDecay;

    hsVector3 accel = force;
    accel += fSpringKonst * hsVector3(&fLocalRestPos, &localPos);

    hsVector3 del = accel * (delSecs * delSecs);

    fCurrDel = del;
}