void CPUSkinningAlgorithm::transformGeometry(
    SkinnedGeometry           *skinGeo,
    Skeleton                  *skel,
    CPUSkinningDataAttachment *data)
{
    const SkinnedGeometry::MFPropIndicesType *mfOrigIdx   =
        skinGeo->getMFPropIndices();
    const SkinnedGeometry::MFPropertiesType  *mfOrigProps =
        skinGeo->getMFProperties();
    SkinnedGeometry::MFPropertiesType        *mfProps     =
        data->editMFProperties();

    const GeoVec4fProperty *jointIdxProp    =
        dynamic_cast<const GeoVec4fProperty *>(
            (*mfOrigProps)[skinGeo->getJointIndexProperty()]);
    const GeoVec4fProperty *jointWeightProp =
        dynamic_cast<const GeoVec4fProperty *>(
            (*mfOrigProps)[skinGeo->getJointWeightProperty()]);

    if(skinGeo->getIndex(skinGeo->getJointIndexProperty ()) !=
       skinGeo->getIndex(skinGeo->getJointWeightProperty())   )
    {
        SWARNING << "CPUSkinningAlgorithm::transformGeometry: "
                 << "Multi indexed geometry not supported!"
                 << std::endl;
        return;
    }

    mfProps->resize(mfOrigProps->size(), NULL);

    const MFMatrix *mfJointMat       = NULL;
    const MFMatrix *mfJointNormalMat = NULL;

    // if the geometry has a non-identity bind shape matrix
    // premultiply joint matrices with bind shape matrix and store in data
    // attachment
    if(skinGeo->getBindShapeMatrix().equals(Matrix::identity(), Eps) == false)
    {
        mfJointMat               = skel->getMFJointMatrices ();
        MFMatrix *mfJointBindMat = data->editMFJointMatrices();

        mfJointBindMat->resize(mfJointMat->size());

        for(UInt32 i = 0; i < mfJointMat->size(); ++i)
        {
            (*mfJointBindMat)[i] = (*mfJointMat)[i];
            (*mfJointBindMat)[i].mult(skinGeo->getBindShapeMatrix());
        }

        mfJointMat = data->getMFJointMatrices();

        if(skel->getCalcNormalMatrices() == true)
        {
            mfJointNormalMat               = skel->getMFJointNormalMatrices ();
            MFMatrix *mfJointNormalBindMat = data->editMFJointNormalMatrices();

            mfJointNormalBindMat->resize(mfJointNormalMat->size());

            for(UInt32 i = 0; i < mfJointNormalMat->size(); ++i)
            {
                (*mfJointNormalBindMat)[i] = (*mfJointNormalMat)[i];
                (*mfJointNormalBindMat)[i].mult(skinGeo->getBindShapeMatrix());
            }

            mfJointNormalMat = data->getMFJointNormalMatrices();
        }
        else
        {
            mfJointNormalMat = data->getMFJointMatrices();
        }
    }
    else
    {
        mfJointMat = skel->getMFJointMatrices();

        if(skel->getCalcNormalMatrices() == true)
        {
            mfJointNormalMat = skel->getMFJointNormalMatrices();
        }
        else
        {
            mfJointNormalMat = skel->getMFJointMatrices();
        }
    }

    // transform all properties

    for(UInt16 i = 0; i < mfProps->size(); ++i)
    {
        // do not transform the vertex joint indices/weights
        if(i == skinGeo->getJointIndexProperty () ||
           i == skinGeo->getJointWeightProperty()   )
        {
            continue;
        }

        GeoIntegralProperty *origPropIdx = (*mfOrigIdx  )[i];
        GeoVectorProperty   *origProp    = (*mfOrigProps)[i];
        GeoVectorProperty   *prop        = (*mfProps    )[i];

        if(origProp == NULL)
            continue;

        if(prop == NULL)
        {
            GeoVectorPropertyUnrecPtr newProp =
                dynamic_pointer_cast<GeoVectorProperty>(origProp->clone());

            mfProps->replace(i, newProp);
            prop = newProp;
        }
        else if(prop->size() != origProp->size())
        {
            prop->resize(origProp->size());
        }

        switch(origProp->getUsage() & GeoProperty::UsageSpaceMask)
        {
        case GeoProperty::UsageObjectSpace:
        {
             transformObjectSpaceProperty(
                 mfJointMat,
                 jointIdxProp, jointWeightProp,
                 origPropIdx, origProp, prop);
        }
        break;

        case GeoProperty::UsageTangentSpace:
        {
            transformTangentSpaceProperty(
                mfJointNormalMat,
                jointIdxProp, jointWeightProp,
                origPropIdx, origProp, prop);
        }
        break;

        default:
            // only need to transform object/tangent space properties
            break;
        }
    }
}
Example #2
0
void Geometry::fill(DrawableStatsAttachment *pStat)
{
    if(pStat == NULL)
    {
        FINFO(("Geometry::fill(DrawableStatsAttachment *): "
               "No attachment given.\n"));

        return;
    }

    // Att Bytes
    UInt32 storedAttBytes    = 0;
    UInt32 attBytesPerVertex = 0;

    for(UInt16 i = 0; i < Geometry::MaxAttribs; ++i)
    {
        if(this->getProperty(i) == NULL)
            continue;

        attBytesPerVertex += this->getProperty(i)->getFormatSize() *
                             this->getProperty(i)->getDimension();
        storedAttBytes    += this->getProperty(i)->getFormatSize() *
                             this->getProperty(i)->getDimension()  *
                             this->getProperty(i)->size();
    }


    GeoIntegralProperty *geoTypePtr = this->getTypes();
    GeoIntegralProperty *lensPtr    = this->getLengths();

    UInt32 lN, tN, len, type;

    lN = (lensPtr    == NULL) ? 0 : lensPtr   ->getSize();
    tN = (geoTypePtr == NULL) ? 0 : geoTypePtr->getSize();

    if((tN == 0) || (lN != 0 && tN != lN) || (lN == 0 && tN != 1))
    {
        FINFO(("GeoStatsAttachment::calc: "
               "Lengths and Types information mismatch.\n"));
        return;
    }

    UInt32 triangle = 0, line = 0, point = 0, vertices = 0,
           procAttBytes = 0;

    for(UInt32 i = 0; i < tN; ++i)
    {
        geoTypePtr->getValue(type, i);

        if(lN != 0)
        {
            lensPtr->getValue(len, i);
        }
        else
        {
            GeoVectorProperty *pos = this->getPositions();

            if(pos == NULL)
            {
                FINFO(("GeoStatsAttachment::calc: No Positions!\n"));
                return;
            }

            len = pos->size();
        }

        vertices     += len;
        procAttBytes += len * attBytesPerVertex;

        switch(type)
        {
            case GL_POINTS:
                point += len;
                break;
            case GL_LINES:
                line += len / 2;
                break;
            case GL_LINE_LOOP:
                line += len;
                break;
            case GL_LINE_STRIP:
                line += len - 1;
                break;
            case GL_TRIANGLES:
                triangle += len / 3;
                break;
            case GL_TRIANGLE_STRIP:
                triangle += len - 2;
                break;
            case GL_TRIANGLE_FAN:
                triangle += len - 2;
                break;
            case GL_QUADS:
                triangle += len / 2;
                break;
            case GL_QUAD_STRIP:
                triangle += len - 2;
                break;
            case GL_POLYGON:
                triangle += len - 2;
                break;
            default:
                FWARNING(("GeoStatsAttachment::calc: Invalid geoType: %d\n",
                          type));
                break;
        }
    }

    pStat->setVertices(vertices);
    pStat->setPoints(point);
    pStat->setLines(line);
    pStat->setTriangles(triangle);
    pStat->setStoredAttributeBytes(storedAttBytes);
    pStat->setProcessedAttributeBytes(procAttBytes);
    pStat->setValid(true);
}