Ogre::DataStreamPtr ApplicationContext::openAPKFile(const Ogre::String& fileName)
{
    Ogre::MemoryDataStreamPtr stream;
    AAsset* asset = AAssetManager_open(mAAssetMgr, fileName.c_str(), AASSET_MODE_BUFFER);
    if(asset)
    {
        off_t length = AAsset_getLength(asset);
        stream.reset(new Ogre::MemoryDataStream(length, true, true));
        memcpy(stream->getPtr(), AAsset_getBuffer(asset), length);
        AAsset_close(asset);
    }
    return stream;
}
Beispiel #2
0
Ogre::Codec::DecodeResult MTGACodec::decode(Ogre::DataStreamPtr& stream) const
{
	// Read 4 character code
	mtga_header_s hdr;
	//uint32 fileType;
	stream->read(&hdr, sizeof(hdr));
	if (LodResource_Bitmap != hdr.magic)
	{
		OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, 
			"This is not a MTGA file!", "MTGACodec::decode");
	}
	
	mtga_pal_s pal[256];
	assert(stream->size() == sizeof(hdr)+hdr.uncompressedSize + sizeof(pal));

	stream->seek(sizeof(mtga_header_s)+hdr.uncompressedSize);
	stream->read(pal,sizeof(pal));

	bool isTransparent = false;
	mtga_pal_s& clr = pal[0];
	if( (clr.r == 0 && clr.g >250 && clr.b > 250) || (clr.r > 250 && clr.g ==0 && clr.b > 250))
		isTransparent = true;


	Ogre::ImageCodec::ImageData* imgData = OGRE_NEW Ogre::ImageCodec::ImageData();
	imgData->format = PF_BYTE_BGRA;
	imgData->width = hdr.width;
	imgData->height = hdr.height;
	imgData->num_mipmaps = 3;
	imgData->depth = 1;

	imgData->size = Image::calculateSize(imgData->num_mipmaps, 1, 
			imgData->width, imgData->height, imgData->depth, imgData->format);
	
	Ogre::MemoryDataStreamPtr pixelData;
	
	pixelData.bind(OGRE_NEW MemoryDataStream(imgData->size));

	// Now deal with the data
	unsigned char* destPtr = pixelData->getPtr();
	stream->seek(sizeof(mtga_header_s));
	size_t width = hdr.width;
	size_t height = hdr.height;
	for(size_t mip = 0; mip <= imgData->num_mipmaps; ++mip)
	{
			for (size_t y = 0; y < height; y ++)
			{
				for (size_t x = 0; x < width; x ++)
				{
					unsigned char idx;
					stream->read(&idx,1);
					mtga_pal_s& clr = pal[idx];
					assert(destPtr-pixelData->getPtr() < imgData->size);
					
					*destPtr++ = clr.b;
					*destPtr++ = clr.g;
					*destPtr++ = clr.r;
					*destPtr++ = (idx == 0 && isTransparent)?0:255;
				}
			}
			width /=2;
			height /=2;

	}
	


	DecodeResult ret;
	ret.first = pixelData;
	ret.second = CodecDataPtr(imgData);
	return ret;
}
void CollisionMesh::loadImpl (void)
{
    APP_ASSERT(masterShape==NULL);

    Ogre::DataStreamPtr file;
    try {
        file = Ogre::ResourceGroupManager::getSingleton().openResource(name.substr(1), "GRIT");
    } catch (Ogre::Exception &e) {
        GRIT_EXCEPT(e.getDescription());
    }

    std::string ext = name.substr(name.length()-5);

    uint32_t fourcc = 0;
    for (int i=0 ; i<4 ; ++i) {
        unsigned char c;
        file->read(&c, 1);
        fourcc |= c << (i*8);
    }
    file->seek(0);

    std::string dir = grit_dirname(name);

    const btVector3 ZV(0,0,0);
    const btQuaternion ZQ(0,0,0,1);

    bool compute_inertia = false;
    bool is_static = false;

    if (fourcc==0x4c4f4342) { //BCOL

        Ogre::MemoryDataStreamPtr mem = 
            Ogre::MemoryDataStreamPtr(OGRE_NEW Ogre::MemoryDataStream(name,file));

        BColFile &bcol = *reinterpret_cast<BColFile*>(mem->getPtr());

        is_static = bcol.mass == 0.0f; // static

        masterShape = new btCompoundShape();

        BColMaterialMap mmap(dir,name);

        for (unsigned i=0 ; i<bcol.hullNum ; ++i) {
            BColHull &p = *bcol.hulls(i);
            btConvexHullShape *s2 = new btConvexHullShape();
            s2->setMargin(p.margin);
            for (unsigned j=0 ; j<p.vertNum ; ++j) {
                BColVert &v = *p.verts(j);
                s2->addPoint(btVector3(v.x, v.y, v.z));
            }
            masterShape->addChildShape(btTransform(ZQ,ZV), s2);
            partMaterials.push_back(mmap(p.mat.name()));
        }

        for (unsigned i=0 ; i<bcol.boxNum ; ++i) {
            BColBox &p = *bcol.boxes(i);
            btBoxShape *s2 = new btBoxShape(btVector3(p.dx/2,p.dy/2,p.dz/2));
            s2->setMargin(p.margin);
            masterShape->addChildShape(btTransform(btQuaternion(p.qx,p.qy,p.qz,p.qw),
                                                   btVector3(p.px,p.py,p.pz)), s2);
            partMaterials.push_back(mmap(p.mat.name()));
        }

        for (unsigned i=0 ; i<bcol.cylNum ; ++i) {
            BColCyl &p = *bcol.cyls(i);
            btCylinderShape *s2 = new btCylinderShapeZ(btVector3(p.dx/2,p.dy/2,p.dz/2));
            s2->setMargin(p.margin);
            masterShape->addChildShape(btTransform(btQuaternion(p.qx,p.qy,p.qz,p.qw),
                                                   btVector3(p.px,p.py,p.pz)), s2);
            partMaterials.push_back(mmap(p.mat.name()));
        }

        for (unsigned i=0 ; i<bcol.coneNum ; ++i) {
            BColCone &p = *bcol.cones(i);
            btConeShape *s2 = new btConeShapeZ(p.radius,p.height);
            s2->setMargin(p.margin);
            masterShape->addChildShape(btTransform(btQuaternion(p.qx,p.qy,p.qz,p.qw),
                                                   btVector3(p.px,p.py,p.pz)), s2);
            partMaterials.push_back(mmap(p.mat.name()));
        }

        for (unsigned i=0 ; i<bcol.planeNum ; ++i) {
            BColPlane &p = *bcol.planes(i);
            btStaticPlaneShape *s2 = new btStaticPlaneShape(btVector3(p.nx,p.ny,p.nz),p.d);
            masterShape->addChildShape(btTransform(ZQ,ZV), s2);
            partMaterials.push_back(mmap(p.mat.name()));
        }

        for (unsigned i=0 ; i<bcol.sphereNum ; ++i) {
            BColSphere &p = *bcol.spheres(i);
            btSphereShape *s2 = new btSphereShape(p.radius);
            masterShape->addChildShape(btTransform(ZQ, btVector3(p.px,p.py,p.pz)), s2);
            partMaterials.push_back(mmap(p.mat.name()));
        }


        if (bcol.triMeshFaceNum > 0) {

            bcolVerts.resize(bcol.triMeshVertNum);
            bcolFaces.resize(bcol.triMeshFaceNum);

            memcpy(&bcolVerts[0], bcol.triMeshVerts(0), bcol.triMeshVertNum * sizeof(BColVert));
            memcpy(&bcolFaces[0], bcol.triMeshFaces(0), bcol.triMeshFaceNum * sizeof(BColFace));

            faceMaterials.reserve(bcol.triMeshFaceNum);

            int counter = 0;
            float accum_area = 0;
            for (unsigned i=0 ; i<bcol.triMeshFaceNum ; ++i) {
                BColFace &face = *bcol.triMeshFaces(i);
                PhysicalMaterial *mat = mmap(face.mat.name());
                faceMaterials.push_back(mat);
                CollisionMesh::ProcObjFace po_face(to_v3(bcolVerts[face.v1]), 
                                                   to_v3(bcolVerts[face.v2]),
                                                   to_v3(bcolVerts[face.v3]));
                procObjFaceDB[mat->id].faces.push_back(po_face);
                float area = (po_face.AB.cross(po_face.AC)).length();
                APP_ASSERT(area>=0);
                procObjFaceDB[mat->id].areas.push_back(area);
                procObjFaceDB[mat->id].totalArea += area;
                if (++counter = 10) {
                    counter = 0;
                    accum_area = 0;
                    procObjFaceDB[mat->id].areas10.push_back(accum_area);
                }
                accum_area += area;
                    
            }

            btTriangleIndexVertexArray *v = new btTriangleIndexVertexArray(
                bcolFaces.size(), reinterpret_cast<int*>(&(bcolFaces[0].v1)), sizeof(BColFace),
                bcolVerts.size(), &(bcolVerts[0].x), sizeof(BColVert));


            if (is_static) {
                btBvhTriangleMeshShape *tm = new btBvhTriangleMeshShape(v,true,true);
                tm->setMargin(bcol.triMeshMargin);
                btTriangleInfoMap* tri_info_map = new btTriangleInfoMap();
                tri_info_map->m_edgeDistanceThreshold = bcol.triMeshEdgeDistanceThreshold;

                btGenerateInternalEdgeInfo(tm,tri_info_map);
                masterShape->addChildShape(btTransform::getIdentity(), tm);
            } else {
                // skip over dynamic trimesh
            }
        }

        setMass(bcol.mass);
        setLinearDamping(bcol.linearDamping);
        setAngularDamping(bcol.angularDamping);
        setLinearSleepThreshold(bcol.linearSleepThreshold);
        setAngularSleepThreshold(bcol.angularSleepThreshold);
        setCCDMotionThreshold(bcol.ccdMotionThreshold);
        setCCDSweptSphereRadius(bcol.ccdSweptSphereRadius);
        setInertia(Vector3(bcol.inertia[0],bcol.inertia[1],bcol.inertia[2]));

        compute_inertia = !bcol.inertiaProvided;

    } else if (fourcc==0x4c4f4354) { //TCOL

        ProxyStreamBuf proxy(file);

        std::istream stream(&proxy);
        quex::tcol_lexer qlex(&stream);
        TColFile tcol;
        parse_tcol_1_0(name,&qlex,tcol);

        is_static = tcol.mass == 0.0f; // static

        masterShape = new btCompoundShape();

        if (tcol.usingCompound) {

            TColCompound &c = tcol.compound;

            for (size_t i=0 ; i<c.hulls.size() ; ++i) {
                const TColHull &h = c.hulls[i];
                btConvexHullShape *s2 = new btConvexHullShape();
                s2->setMargin(h.margin);
                for (unsigned j=0 ; j<h.vertexes.size() ; ++j) {
                    const Vector3 &v = h.vertexes[j];
                    s2->addPoint(to_bullet(v));
                }
                masterShape->addChildShape(btTransform(ZQ,ZV), s2);
                partMaterials.push_back(phys_mats.getMaterial(dir,name,h.material));
            }

            for (size_t i=0 ; i<c.boxes.size() ; ++i) {
                const TColBox &b = c.boxes[i];
                /* implement with hulls
                btConvexHullShape *s2 = new btConvexHullShape();
                s2->addPoint(btVector3(-b.dx/2+b.margin, -b.dy/2+b.margin, -b.dz/2+b.margin));
                s2->addPoint(btVector3(-b.dx/2+b.margin, -b.dy/2+b.margin,  b.dz/2-b.margin));
                s2->addPoint(btVector3(-b.dx/2+b.margin,  b.dy/2-b.margin, -b.dz/2+b.margin));
                s2->addPoint(btVector3(-b.dx/2+b.margin,  b.dy/2-b.margin,  b.dz/2-b.margin));
                s2->addPoint(btVector3( b.dx/2-b.margin, -b.dy/2+b.margin, -b.dz/2+b.margin));
                s2->addPoint(btVector3( b.dx/2-b.margin, -b.dy/2+b.margin,  b.dz/2-b.margin));
                s2->addPoint(btVector3( b.dx/2-b.margin,  b.dy/2-b.margin, -b.dz/2+b.margin));
                s2->addPoint(btVector3( b.dx/2-b.margin,  b.dy/2-b.margin,  b.dz/2-b.margin));
                */
                btBoxShape *s2 =new btBoxShape(btVector3(b.dx/2,b.dy/2,b.dz/2));
                s2->setMargin(b.margin);
                masterShape->addChildShape(btTransform(btQuaternion(b.qx,b.qy,b.qz,b.qw),
                                 btVector3(b.px,b.py,b.pz)), s2);
                partMaterials.push_back(phys_mats.getMaterial(dir,name,b.material));
            }

            for (size_t i=0 ; i<c.cylinders.size() ; ++i) {
                const TColCylinder &cyl = c.cylinders[i];
                btCylinderShape *s2 =
                    new btCylinderShapeZ(btVector3(cyl.dx/2,cyl.dy/2,cyl.dz/2));
                s2->setMargin(cyl.margin);
                masterShape->addChildShape(
                    btTransform(btQuaternion(cyl.qx,cyl.qy,cyl.qz,cyl.qw),
                            btVector3(cyl.px,cyl.py,cyl.pz)), s2);
                partMaterials.push_back(phys_mats.getMaterial(dir,name,cyl.material));
            }

            for (size_t i=0 ; i<c.cones.size() ; ++i) {
                const TColCone &cone = c.cones[i];
                btConeShapeZ *s2 = new btConeShapeZ(cone.radius,cone.height);
                s2->setMargin(cone.margin);
                masterShape->addChildShape(
                      btTransform(btQuaternion(cone.qx,cone.qy,cone.qz,cone.qw),
                          btVector3(cone.px,cone.py,cone.pz)), s2);
                partMaterials.push_back(phys_mats.getMaterial(dir,name,cone.material));
            }

            for (size_t i=0 ; i<c.planes.size() ; ++i) {
                const TColPlane &p = c.planes[i];
                btStaticPlaneShape *s2 =
                    new btStaticPlaneShape(btVector3(p.nx,p.ny,p.nz),p.d);
                masterShape->addChildShape(btTransform(ZQ,ZV), s2);
                partMaterials.push_back(phys_mats.getMaterial(dir,name,p.material));
            }

            for (size_t i=0 ; i<c.spheres.size() ; ++i) {
                const TColSphere &sp = c.spheres[i];
                btSphereShape *s2 = new btSphereShape(sp.radius);
                masterShape->addChildShape(btTransform(ZQ,
                                 btVector3(sp.px,sp.py,sp.pz)), s2);
                partMaterials.push_back(phys_mats.getMaterial(dir,name,sp.material));
            }
        }

        if (tcol.usingTriMesh) {

            TColTriMesh &t = tcol.triMesh;

            std::swap(verts, t.vertexes);
            std::swap(faces, t.faces);


            faceMaterials.reserve(faces.size());
            int counter = 0;
            float accum_area = 0;
            for (TColFaces::const_iterator i=faces.begin(), i_=faces.end() ; i!=i_ ; ++i) {
                //optimisation possible here by changing the TCol struct to be more liek what
                //bullet wants, and then re-using memory
                PhysicalMaterial *mat = phys_mats.getMaterial(dir,name,i->material);
                faceMaterials.push_back(mat);
                CollisionMesh::ProcObjFace po_face(verts[i->v1], verts[i->v2], verts[i->v3]);
                procObjFaceDB[mat->id].faces.push_back(po_face);
                float area = (po_face.AB.cross(po_face.AC)).length();
                APP_ASSERT(area>=0);
                procObjFaceDB[mat->id].areas.push_back(area);
                procObjFaceDB[mat->id].totalArea += area;
                if (++counter = 10) {
                    counter = 0;
                    accum_area = 0;
                    procObjFaceDB[mat->id].areas10.push_back(accum_area);
                }
                accum_area += area;
                    
            }

            btTriangleIndexVertexArray *v = new btTriangleIndexVertexArray(
                faces.size(), &(faces[0].v1), sizeof(TColFace),
                verts.size(), &(verts[0].x), sizeof(Vector3));

            if (is_static) {
                btBvhTriangleMeshShape *tm = new btBvhTriangleMeshShape(v,true,true);
                tm->setMargin(t.margin);
                btTriangleInfoMap* tri_info_map = new btTriangleInfoMap();
                tri_info_map->m_edgeDistanceThreshold = t.edgeDistanceThreshold;

                btGenerateInternalEdgeInfo(tm,tri_info_map);
                masterShape->addChildShape(btTransform::getIdentity(), tm);
            } else {
                // Skip over dynamic trimesh
            }

        }

        setMass(tcol.mass);
        setInertia(Vector3(tcol.inertia_x,tcol.inertia_y,tcol.inertia_z));
        setLinearDamping(tcol.linearDamping);
        setAngularDamping(tcol.angularDamping);
        setLinearSleepThreshold(tcol.linearSleepThreshold);
        setAngularSleepThreshold(tcol.angularSleepThreshold);
        setCCDMotionThreshold(tcol.ccdMotionThreshold);
        setCCDSweptSphereRadius(tcol.ccdSweptSphereRadius);

        compute_inertia = !tcol.hasInertia;

    } else {
        GRIT_EXCEPT("Collision mesh \""+name+"\" seems to be corrupt.");
    }


    if (is_static) {
        setInertia(Vector3(0,0,0));
    } else {
        if (faceMaterials.size() > 0) {
            CERR << "While loading \"" + name + "\": Dynamic trimesh not supported." << std::endl;
        }
        if (compute_inertia) {
            btVector3 i;
            masterShape->calculateLocalInertia(mass,i);
            setInertia(from_bullet(i));
        }
    }
}