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; }
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)); } } }