Esempio n. 1
0
Matrix4 SplineBase::computeBasis() {
    // The standard Catmull-Rom spline basis (e.g., Watt & Watt p108)
    // is for [u^3 u^2 u^1 u^0] * B * [p[0] p[1] p[2] p[3]]^T.
    // We need a basis formed for:
    //
    //     U * C * [2*p'[1] p[1] p[2] 2*p'[2]]^T 
    //
    //     U * C * [p2-p0 p1 p2 p3-p1]^T 
    //
    // To make this transformation, compute the differences of columns in C:
    // For [p0 p1 p2 p3]
    Matrix4 basis =
        Matrix4( -1,  3, -3,  1,
                  2, -5,  4, -1,
                 -1,  0,  1,  0,
                  0,  2,  0,  0) * 0.5f;

    // For [-p0 p1 p2 p3]^T 
    basis.setColumn(0, -basis.column(0));

    // For [-p0 p1 p2 p3-p1]^T 
    basis.setColumn(1, basis.column(1) + basis.column(3));

    // For [p2-p0 p1 p2 p3-p1]^T 
    basis.setColumn(2, basis.column(2) - basis.column(0));

    return basis;
}
Esempio n. 2
0
Matrix4 Matrix4::inverse() const {
    // Inverse = adjoint / determinant

    Matrix4 A = adjoint();

    // Determinant is the dot product of the first row and the first row
    // of cofactors (i.e. the first col of the adjoint matrix)
    float det = A.column(0).dot(row(0));

    return A * (1.0f / det);
}
Esempio n. 3
0
Matrix4 Matrix4::inverse() const {
    

    Matrix4 A = adjoint();

    
    
	float det = A.column(0).dot(row(0));

	return A * (1.0f / det);
}
Esempio n. 4
0
void ArticulatedModel::load3DS(const Specification& specification) {
    // During loading, we make no attempt to optimize the mesh.  We leave that until the
    // Parts have been created.  The vertex arrays are therefore much larger than they
    // need to be.
    Stopwatch timer;

    Parse3DS parseData;
    {
        BinaryInput bi(specification.filename, G3D_LITTLE_ENDIAN);
        timer.after(" open file");
        parseData.parse(bi);
        timer.after(" parse");
    }

    name = FilePath::base(specification.filename);

    const std::string& path = FilePath::parent(specification.filename);

    /*
    if (specification.stripMaterials) {
        stripMaterials(parseData);
    }

    if (specification.mergeMeshesByMaterial) {
        mergeGroupsAndMeshesByMaterial(parseData);
        }*/

    for (int p = 0; p < parseData.objectArray.size(); ++p) {
        Parse3DS::Object& object = parseData.objectArray[p];

        // Create a unique name for this part
        std::string name = object.name;
        int count = 0;
        while (this->part(name) != NULL) {
            ++count;
            name = object.name + format("_#%d", count);
        }

        // Create the new part
        // All 3DS parts are promoted to the root in the current implementation.
        Part* part = addPart(name);

        // Process geometry
        part->cpuVertexArray.vertex.resize(object.vertexArray.size());
        part->cframe = object.keyframe.approxCoordinateFrame();
        debugAssert(isFinite(part->cframe.rotation.determinant()));
        debugAssert(part->cframe.rotation.isOrthonormal());

        if (! part->cframe.rotation.isRightHanded()) {
            // TODO: how will this impact other code?  I think we can't just force it like this -- Morgan
            part->cframe.rotation.setColumn(0, -part->cframe.rotation.column(0));
        }

        debugAssert(part->cframe.rotation.isRightHanded());

        //debugPrintf("%s %d %d\n", object.name.c_str(), object.hierarchyIndex, object.nodeID);

        if (part->cpuVertexArray.vertex.size() > 0) {
            // Convert vertices to object space (there is no surface normal data at this point)
            Matrix4 netXForm = part->cframe.inverse().toMatrix4();
            
            debugAssertM(netXForm.row(3) == Vector4(0,0,0,1), 
                        "3DS file loading requires that the last row of the xform matrix be 0, 0, 0, 1");

            if (object.texCoordArray.size() > 0) {
                part->m_hasTexCoord0 = true;
                part->cpuVertexArray.hasTexCoord0 = true;
            }
            
            const Matrix3& S = netXForm.upper3x3();
            const Vector3& T = netXForm.column(3).xyz();
            for (int v = 0; v < part->cpuVertexArray.vertex.size(); ++v) {
#               ifdef G3D_DEBUG
                {
                    const Vector3& vec = object.vertexArray[v];
                    debugAssert(vec.isFinite());
                }
#               endif

                CPUVertexArray::Vertex& vertex = part->cpuVertexArray.vertex[v];
                vertex.position = S * object.vertexArray[v] + T;
                vertex.tangent = Vector4::nan();
                vertex.normal  = Vector3::nan();

                if (part->m_hasTexCoord0) {
                    vertex.texCoord0 = object.texCoordArray[v];
                }

#               ifdef G3D_DEBUG
                {
                    const Vector3& vec = vertex.position;
                    debugAssert(vec.isFinite());
                }
#               endif
            }


            if (object.faceMatArray.size() == 0) {

                // Merge all geometry into one mesh since there are no materials
                Mesh* mesh = addMesh("mesh", part);
                mesh->cpuIndexArray = object.indexArray;
                debugAssert(mesh->cpuIndexArray.size() % 3 == 0);

            } else {
                for (int m = 0; m < object.faceMatArray.size(); ++m) {
                    const Parse3DS::FaceMat& faceMat = object.faceMatArray[m];

                    if (faceMat.faceIndexArray.size() > 0) {

                        Material::Ref mat;
                        bool twoSided = false;

                        const std::string& materialName = faceMat.materialName;
                        if (parseData.materialNameToIndex.containsKey(materialName)) {
                            int i = parseData.materialNameToIndex[materialName];
                            const Parse3DS::Material& material = parseData.materialArray[i];
                            
                            //if (! materialSubstitution.get(material.texture1.filename, mat)) {
                            const Material::Specification& spec = compute3DSMaterial(&material, path, specification);
                            mat = Material::create(spec);
                            //}
                            twoSided = material.twoSided || mat->hasAlphaMask();
                        } else {
                            mat = Material::create();
                            logPrintf("Referenced unknown material '%s'\n", materialName.c_str());
                        }                        

                        Mesh* mesh = addMesh(materialName, part);
                        debugAssert(isValidHeapPointer(mesh));
                        mesh->material = mat;
                        mesh->twoSided = twoSided;

                        // Construct an index array for this part
                        for (int i = 0; i < faceMat.faceIndexArray.size(); ++i) {
                            // 3*f is an index into object.indexArray
                            int f = faceMat.faceIndexArray[i];
                            debugAssert(f >= 0);
                            for (int v = 0; v < 3; ++v) {
                                mesh->cpuIndexArray.append(object.indexArray[3 * f + v]);
                            }
                        }
                        debugAssert(mesh->cpuIndexArray.size() > 0);
                        debugAssert(mesh->cpuIndexArray.size() % 3 == 0);

                    }
                } // for m
            } // if has materials 
        }
    }

    timer.after(" convert");
}
Esempio n. 5
0
Quaternion::Quaternion(const Matrix4 &src) {
    this->set(src.column(0).xyz(),src.column(1).xyz(),src.column(2).xyz());
}