nuclear@1: #include nuclear@7: #include nuclear@1: #include "opengl.h" nuclear@7: #include nuclear@7: #include nuclear@7: #include nuclear@1: #include "tile.h" nuclear@11: #include "tileset.h" nuclear@1: nuclear@7: using std::map; nuclear@7: nuclear@7: static void build_nodemap(map *nmap, const aiScene *scn, aiNode *node); nuclear@21: static PointLight *mesh_to_light(Mesh *m); nuclear@7: nuclear@11: Tile::Tile(TileSet *tileset) nuclear@11: { nuclear@11: tset = tileset; nuclear@11: } nuclear@7: nuclear@1: bool Tile::load(const char *fname) nuclear@1: { nuclear@5: if(!fname) { nuclear@5: return false; nuclear@5: } nuclear@5: nuclear@14: char *saved_fname = (char*)alloca(strlen(fname) + 1); nuclear@14: strcpy(saved_fname, fname); nuclear@14: nuclear@3: unsigned int proc_flags = aiProcess_JoinIdenticalVertices | nuclear@7: aiProcess_Triangulate | nuclear@7: aiProcess_SortByPType | nuclear@7: aiProcess_FlipUVs; nuclear@4: nuclear@3: const aiScene *scn = aiImportFile(fname, proc_flags); nuclear@3: if(!scn) { nuclear@3: fprintf(stderr, "failed to load tile: %s\n", fname); nuclear@3: return -1; nuclear@3: } nuclear@3: nuclear@7: map nodemap; nuclear@7: build_nodemap(&nodemap, scn, scn->mRootNode); nuclear@7: nuclear@21: //load_lights(scn); nuclear@7: load_meshes(scn, nodemap); nuclear@3: nuclear@22: printf("loaded tile %s: %d meshes, %d lights\n", saved_fname, (int)meshes.size(), (int)lights.size()); nuclear@1: return true; nuclear@1: } nuclear@1: nuclear@5: void Tile::draw(unsigned int draw_mask) const nuclear@1: { nuclear@4: for(size_t i=0; idraw(); nuclear@4: } nuclear@4: } nuclear@4: } nuclear@1: nuclear@23: void Tile::draw_lights(unsigned int draw_mask) const nuclear@23: { nuclear@23: for(size_t i=0; idraw(); nuclear@23: } nuclear@23: } nuclear@23: } nuclear@23: nuclear@21: /* nuclear@4: int Tile::load_lights(const aiScene *scn) nuclear@4: { nuclear@4: int count = 0; nuclear@4: nuclear@4: for(int i=0; i<(int)scn->mNumLights; i++) { nuclear@4: Light *lt; nuclear@4: aiLight *ailt = scn->mLights[i]; nuclear@4: nuclear@4: switch(ailt->mType) { nuclear@4: case aiLightSource_POINT: nuclear@4: lt = new PointLight(Vector3(ailt->mPosition.x, ailt->mPosition.y, ailt->mPosition.z)); nuclear@4: ((PointLight*)lt)->set_attenuation(ailt->mAttenuationConstant, ailt->mAttenuationLinear, nuclear@4: ailt->mAttenuationQuadratic); nuclear@4: break; nuclear@4: nuclear@4: case aiLightSource_DIRECTIONAL: nuclear@4: lt = new PointLight(Vector3(ailt->mDirection.x, ailt->mDirection.y, ailt->mDirection.z)); nuclear@4: break; nuclear@4: nuclear@4: default: nuclear@4: continue; nuclear@4: } nuclear@4: nuclear@4: lt->set_color(Color(ailt->mColorDiffuse.r, ailt->mColorDiffuse.g, ailt->mColorDiffuse.b, 1.0)); nuclear@4: nuclear@4: lights.push_back(lt); nuclear@4: count++; nuclear@4: } nuclear@4: nuclear@4: return count; nuclear@1: } nuclear@21: */ nuclear@4: nuclear@7: int Tile::load_meshes(const aiScene *scn, const std::map &nmap) nuclear@4: { nuclear@4: int count = 0; nuclear@4: nuclear@4: for(int i=0; i<(int)scn->mNumMeshes; i++) { nuclear@4: Mesh *mesh = new Mesh; nuclear@4: if(!mesh->create(scn, scn->mMeshes[i])) { nuclear@4: delete mesh; nuclear@4: continue; nuclear@4: } nuclear@4: nuclear@11: Material mat; nuclear@11: mat.load(scn->mMaterials[scn->mMeshes[i]->mMaterialIndex], tset->get_textures()); nuclear@11: mesh->set_material(mat); nuclear@11: nuclear@7: // retrieve the node pointer nuclear@7: const char *name = ""; nuclear@7: nuclear@7: auto iter = nmap.find(scn->mMeshes[i]); nuclear@7: if(iter != nmap.end()) { nuclear@7: aiNode *node = iter->second; nuclear@7: nuclear@7: Matrix4x4 xform; nuclear@7: //xform.rotate(Vector3(-M_PI / 2.0, 0, 0)); nuclear@7: xform = *(Matrix4x4*)&node->mTransformation; nuclear@7: mesh->set_xform(xform); nuclear@7: nuclear@7: name = node->mName.data; nuclear@7: mesh->set_name(name); nuclear@7: } nuclear@7: nuclear@4: // find which side is this mesh on nuclear@7: unsigned int side = 0; nuclear@7: if(strstr(name, "NORTH")) { nuclear@7: side |= TILE_NORTH; nuclear@7: } nuclear@7: if(strstr(name, "SOUTH")) { nuclear@7: side |= TILE_SOUTH; nuclear@7: } nuclear@7: if(strstr(name, "EAST")) { nuclear@7: side |= TILE_EAST; nuclear@7: } nuclear@7: if(strstr(name, "WEST")) { nuclear@7: side |= TILE_WEST; nuclear@7: } nuclear@7: if(!side) { nuclear@4: side = TILE_ALL; nuclear@4: } nuclear@4: nuclear@21: // what a sordid hack... if the name contains "LIGHT", then make a light out of this nuclear@21: // and destroy the mesh... nuclear@21: if(strstr(name, "LIGHT")) { nuclear@21: PointLight *lt = mesh_to_light(mesh); nuclear@21: if(!lt) { nuclear@21: fprintf(stderr, "failed to convert mesh %s to light\n", name); nuclear@21: } else { nuclear@21: lights.push_back(lt); nuclear@21: light_side.push_back(side); nuclear@21: } nuclear@21: delete mesh; nuclear@21: nuclear@21: } else { nuclear@21: meshes.push_back(mesh); nuclear@21: mesh_side.push_back(side); nuclear@21: count++; nuclear@21: } nuclear@4: } nuclear@4: return count; nuclear@4: } nuclear@7: nuclear@7: static void build_nodemap(map *nmap, const aiScene *scn, aiNode *node) nuclear@7: { nuclear@7: unsigned int i; nuclear@7: nuclear@7: for(i=0; imNumMeshes; i++) { nuclear@7: aiMesh *m = scn->mMeshes[node->mMeshes[i]]; nuclear@7: nuclear@7: (*nmap)[m] = node; nuclear@7: } nuclear@7: nuclear@7: for(i=0; imNumChildren; i++) { nuclear@7: build_nodemap(nmap, scn, node->mChildren[i]); nuclear@7: } nuclear@7: } nuclear@21: nuclear@21: static PointLight *mesh_to_light(Mesh *m) nuclear@21: { nuclear@21: Vector3 center = m->get_bsph_center(); nuclear@21: float rad = m->get_bsph_radius(); nuclear@21: nuclear@21: PointLight *lt = new PointLight(center); nuclear@21: lt->set_radius(rad); nuclear@21: nuclear@21: lt->set_color(m->get_material().kd); nuclear@21: nuclear@21: return lt; nuclear@21: }