void RenderSortnorm(unsigned int offset, unsigned char *data, vector3d obj_center) { BSP_BlockHeader blkhdr; BSP_SortNorm snorm; unsigned char *curpos = data + offset; blkhdr.Read((char *) curpos); snorm.Read((char *) curpos + blkhdr.MySize(), blkhdr); // draw a cube defined by the bounding region glColor3f(1.0, 0.0, 0.0); OpenGL_RenderBox(POFTranslate(snorm.min_bounding_box_point), POFTranslate(snorm.max_bounding_box_point)); // continue traversal if (snorm.front_offset) RenderBSP(offset + snorm.front_offset, data, obj_center); // continue traversal if (snorm.back_offset) RenderBSP(offset + snorm.back_offset, data, obj_center); // continue traversal if (snorm.prelist_offset) RenderBSP(offset + snorm.prelist_offset, data, obj_center); // continue traversal if (snorm.postlist_offset) RenderBSP(offset + snorm.postlist_offset, data, obj_center); // continue traversal if (snorm.online_offset) RenderBSP(offset + snorm.online_offset, data, obj_center); // continue traversal // No tail recursion on sortnorms }
void RenderTextured(unsigned int offset, unsigned char *data, vector3d obj_center) { BSP_BlockHeader blkhdr; unsigned char *curpos = data + offset; blkhdr.Read((char *) curpos); #if defined(__BSP_DEBUG_DRAWNORMS_) BSP_TmapPoly tpoly; tpoly.Read((char *) curpos + blkhdr.MySize(), blkhdr); // just rendering a point a line along the norm for now - just need center and normal glColor3f(0.5, 0.5, 1.0); vector3d point = POFTranslate(tpoly.center); vector3d norm = point+(POFTranslate(tpoly.normal)*5); glBegin(GL_POINTS); glVertex3fv((float *)&point); glEnd(); glBegin(GL_LINE_STRIP); glVertex3fv((float *)&point); glVertex3fv((float *)&norm); glEnd(); // tail recurse tpoly.Destroy(); #endif RenderBSP(offset + blkhdr.size, data, obj_center); }
void TranslateTPoly(unsigned int offset, unsigned char *data, BSP_DefPoints &points, std::vector<pcs_polygon> &polygons, unsigned int &upolys) { BSP_BlockHeader blkhdr; unsigned char *curpos = data + offset; blkhdr.Read((char *) curpos); vector3d point, norm; BSP_TmapPoly tpoly; pcs_polygon temp_poly; tpoly.Read((char *) curpos + blkhdr.MySize(), blkhdr); // 2^32-1 = 4294967295 // 2^8-1 = 255 temp_poly.norm = POFTranslate(tpoly.normal); temp_poly.texture_id = tpoly.tmap_num; temp_poly.verts.resize(tpoly.nverts); //norm = tpoly.normal for (int i = 0; i < tpoly.nverts; i++) { temp_poly.verts[i].point = POFTranslate(points.vertex_data[tpoly.verts[i].vertnum].vertex); temp_poly.verts[i].norm = POFTranslate(points.normals[tpoly.verts[i].normnum]); temp_poly.verts[i].u = tpoly.verts[i].u; temp_poly.verts[i].v = tpoly.verts[i].v; } if (upolys >= polygons.size()) { polygons.resize(polygons.size() * 2); } polygons[upolys] = temp_poly; upolys++; BSPTransPMF(offset + blkhdr.size, data, points, polygons, upolys); // continue traversal }
void RenderBBox(unsigned int offset, unsigned char *data, vector3d obj_center) { BSP_BlockHeader blkhdr; BSP_BoundBox bbox; unsigned char *curpos = data + offset; blkhdr.Read((char *) curpos); bbox.Read((char *) curpos + blkhdr.MySize(), blkhdr); if (blkhdr.id != 5) return; glColor3f(0.0, 1.0, 0.0); OpenGL_RenderBox(POFTranslate(bbox.min_point), POFTranslate(bbox.max_point)); // tail recurse RenderBSP(offset + blkhdr.size, data, obj_center); }
void TranslateFPoly(unsigned int offset, unsigned char *data, BSP_DefPoints &points, std::vector<pcs_polygon> &polygons, unsigned int &upolys) { BSP_BlockHeader blkhdr; unsigned char *curpos = data + offset; blkhdr.Read((char *) curpos); vector3d point, norm; pcs_polygon temp_poly; BSP_FlatPoly fpoly; fpoly.Read((char *) curpos + blkhdr.MySize(), blkhdr); temp_poly.norm = POFTranslate(fpoly.normal); temp_poly.texture_id = -1; temp_poly.verts.resize(fpoly.nverts); for (int i = 0; i < fpoly.nverts; i++) { temp_poly.verts[i].point = POFTranslate(points.vertex_data[fpoly.verts[i].vertnum].vertex); temp_poly.verts[i].norm = POFTranslate(points.normals[fpoly.verts[i].normnum]); temp_poly.verts[i].u = 0; temp_poly.verts[i].v = 0; } if (upolys >= polygons.size()) { polygons.resize(polygons.size() * 2); } polygons[upolys] = temp_poly; upolys++; BSPTransPMF(offset + blkhdr.size, data, points, polygons, upolys); // continue traversal }
void wxGL_PMFCanvas::Render() { if (FreezeRender) return; IsRendering = true; this->SetCurrent(); glEnable(GL_CULL_FACE); glFrontFace(GL_CW); glClearColor(0, 0, 0, 1.0f); // Black Background glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear Screen And Depth Buffer glMatrixMode(GL_PROJECTION); glLoadIdentity(); if(GetSize().GetHeight()){ //more division by zero-Bobboau float asp = (float)GetSize().GetWidth()/(float)GetSize().GetHeight(); if(proj_mode == PROJ_ORTHO){ float z = (position.z+log(abs(position.z)+1.0f))/1.25f; glOrtho((asp+position.x/1000.0f)*z, (-asp+position.x/1000.0f)*z, (1.0f+position.y/1000.0f)*z, (-1.0f+position.y/1000.0f)*z, -500.0, 50000.0); }else{ gluPerspective( 75.0f, asp, 1.0f, 250000.0f ); } } glMatrixMode(GL_MODELVIEW); glLoadIdentity(); float radius; //position = vector3d(0,0,-(model.SOBJ(0).radius * 2.0)); //rotation = vector3d(33,-66,0); if (model.GetSOBJCount()) { radius = model.GetMaxRadius(); // -------------------------------------------------------- glTranslatef(position.x, position.y, position.z); // translate by autocentering point vector3d acen = model.GetAutoCenter(); //glRotatef(GlobalRotation.z, 0, 0, 1); glTranslatef(acen.x, acen.y, acen.z); // -------------------------------------------------------- // Setup Lighting glEnable(GL_LIGHTING); GLfloat ambientLight[4]; ambientLight[0] = ambient_light[0]; ambientLight[1] = ambient_light[1]; ambientLight[2] = ambient_light[2]; ambientLight[3] = ambient_light[3]; GLfloat diffuseLight[4]; diffuseLight[0] = diffuse_light[0]; diffuseLight[1] = diffuse_light[1]; diffuseLight[2] = diffuse_light[2]; diffuseLight[3] = diffuse_light[3]; GLfloat specular[]={ 1.0f, 1.0f, 1.0f, 1.0f}; GLfloat lightPos[]={ 0.0f, radius+350.0f, (radius+350.0f), 1.0f}; //GLfloat specref[]= { 1.0f, 1.0f, 1.0f, 1.0f}; // Setup and enable light 0 glLightfv(GL_LIGHT0,GL_AMBIENT,ambientLight); glLightfv(GL_LIGHT0,GL_DIFFUSE,diffuseLight); glLightfv(GL_LIGHT0,GL_SPECULAR,specular); glLightfv(GL_LIGHT0,GL_POSITION,lightPos); glEnable(GL_LIGHT0); // Enable color tracking //glEnable(GL_COLOR_MATERIAL); // Render Geometry glRotatef(rotation.x, 1, 0, 0); glRotatef(rotation.y, 0, 1, 0); glRotatef(rotation.z, 0, 0, 1); if(active_chunk == TXTR) model.set_active_texture(omni_selected_item); else model.set_active_texture(-1); if (omni.lod > -1 && omni.lod < model.GetLODCount()) { model.set_active_model(model.LOD(omni.lod)); } model.Render(tex_ctrl, UseVBOs, active_chunk == SOBJ); glTranslatef(-acen.x, -acen.y, -acen.z); if(active_chunk == SHLD) model.draw_shields(); if(active_chunk == INSG) model.draw_insignia(omni.lod, omni); glDisable(GL_TEXTURE_2D); draw_omnipoints(); glDisable(GL_LIGHTING); if(draw_the_grid){ vector3d grid_point = acen; if(omni_selected_list >-1 && omni_selected_item >-1)//active_chunk == GPNT || active_chunk == MPNT || active_chunk == DOCK || active_chunk == FUEL || active_chunk == GLOW || active_chunk == SPCL || active_chunk == TGUN || active_chunk == EYE || active_chunk == ACEN) grid_point = omni.point[omni_selected_list][omni_selected_item].pos+model.get_model_offset(omni.point[omni_selected_list][omni_selected_item].model); vector3d POFTranslate(vector3d); draw_grid(POFTranslate(model.GetMinBounding())+acen, POFTranslate(model.GetMaxBounding())+acen, grid_point); } } /* vector3d V = get_eye_pos(); vector3d U = get_eye_uvec(); vector3d R = get_eye_rvec(); vector3d F = get_eye_fvec(); wxPoint pt = ScreenToClient(wxGetMousePosition()); vector3d r = ray_cast(pt.x, pt.y); */ // gr_debug->set_text(wxString::Format("Camera Position:%0.2f, %0.2f, %0.2f\nCamera Rvec: %0.2f, %0.2f, %0.2f\nCamera Uvec: %0.2f, %0.2f, %0.2f\nCamera Fvec: %0.2f, %0.2f, %0.2f\n\n\nMouse Point Ray: %0.2f, %0.2f, %0.2f",V.x,V.y,V.z ,R.x,R.y,R.z ,U.x,U.y,U.z ,F.x,F.y,F.z ,r.x,r.y,r.z)); this->SwapBuffers(); IsRendering = false; }
int PCS_Model::LoadFromPOF(std::string filename, AsyncProgress* progress) { this->Reset(); char cstringtemp[256]; progress->setMessage("Opening and Reading POF"); progress->Notify(); std::ifstream infile(filename.c_str(), std::ios::in | std::ios::binary); if (!infile) return 1; POF poffile(infile); progress->setTarget(4 + poffile.SPCL_Count() + poffile.GPNT_SlotCount() + poffile.MPNT_SlotCount() + poffile.TGUN_Count_Banks() + poffile.TMIS_Count_Banks() + poffile.DOCK_Count_Docks() + poffile.FUEL_Count_Thrusters() + poffile.INSG_Count_Insignia() + poffile.PATH_Count_Paths() + poffile.GLOW_Count_LightGroups() + poffile.OBJ2_Count()); // Update Progress progress->incrementWithMessage("Getting Header"); header.max_radius = poffile.HDR2_Get_MaxRadius(); header.max_radius_override = header.max_radius; header.min_bounding = poffile.HDR2_Get_MinBound(); header.max_bounding = poffile.HDR2_Get_MaxBound(); POFTranslateBoundingBoxes(header.min_bounding, header.max_bounding); header.min_bounding_override = header.min_bounding; header.max_bounding_override = header.max_bounding; unsigned int i, j, k; int scratch; // useless variable - for legacy remnant argument poffile.HDR2_Get_Details(scratch, header.detail_levels); poffile.HDR2_Get_Debris(scratch, header.debris_pieces); header.mass = poffile.HDR2_Get_Mass(); header.mass_center = POFTranslate(poffile.HDR2_Get_MassCenter()); poffile.HDR2_Get_MomentInertia(header.MOI); // --------- convert cross sections --------- std::vector<cross_section> sections; poffile.HDR2_Get_CrossSections(scratch, sections); if (scratch != -1) { header.cross_sections.resize(scratch); for (i = 0; i < header.cross_sections.size(); i++) { header.cross_sections[i].depth = sections[i].depth; header.cross_sections[i].radius = sections[i].radius; } } // --------- ACEN --------- // Update Progress progress->incrementWithMessage("Getting ACEN, TXTR, PINF, EYE"); autocentering = POFTranslate(poffile.ACEN_Get_acen()); // --------- TXTR --------- textures.resize(poffile.TXTR_Count_Textures()); std::string tmp_test; for (i = 0; i < textures.size(); i++) { tmp_test = poffile.TXTR_GetTextures(i); textures[i] = tmp_test; } // --------- ---------------------- --------- model_info = poffile.PINF_Get(); can_bsp_cache = false; for (i = 0; i < model_info.size(); i++) { if ( //strstr(model_info[i].c_str(), "BSPGEN") || // Volition's Compiler - caching revoked 2008-02-11 by Kazan because cannot gaurantee that tagged models actually game from V's compiler //strstr(model_info[i].c_str(), "POF-CS Compiler v1.3.4") || // removed PCS1 from recognized cacheable list 2008-01-10 - Kazan strstr(model_info[i].c_str(), PCS2_COMP_VERSION.mb_str())) { can_bsp_cache = true; break; } } // --------- EYE --------- eyes.resize(poffile.EYE_Count_Eyes()); for (i = 0; i < eyes.size(); i++) { poffile.EYE_Get_Eye(i, eyes[i].sobj_number, eyes[i].sobj_offset, eyes[i].normal); eyes[i].sobj_offset = POFTranslate(eyes[i].sobj_offset); eyes[i].normal = POFTranslate(eyes[i].normal); } // --------- SPCL --------- special.resize(poffile.SPCL_Count()); for (i = 0; i < special.size(); i++) { // Update Progress sprintf(cstringtemp, "Getting Special %d", i); progress->incrementWithMessage(cstringtemp); poffile.SPCL_Get_Special(i, special[i].name, special[i].properties, special[i].point, special[i].radius); special[i].point = POFTranslate(special[i].point); } // --------- weapons (GPNT/MPNT) --------- weapons.resize(poffile.GPNT_SlotCount() + poffile.MPNT_SlotCount()); for (i = 0; i < poffile.GPNT_SlotCount(); i++) { // Update Progress sprintf(cstringtemp, "Getting Gun Point %d", i); progress->incrementWithMessage(cstringtemp); weapons[i].type = GUN; weapons[i].muzzles.resize(poffile.GPNT_PointCount(i)); for (j = 0; j < poffile.GPNT_PointCount(i); j++) { poffile.GPNT_GetPoint(i, j, weapons[i].muzzles[j].point, weapons[i].muzzles[j].norm); weapons[i].muzzles[j].point = POFTranslate(weapons[i].muzzles[j].point); weapons[i].muzzles[j].norm = POFTranslate(weapons[i].muzzles[j].norm); } } k = poffile.GPNT_SlotCount(); for (i = 0; i < poffile.MPNT_SlotCount(); i++) { // Update Progress sprintf(cstringtemp, "Getting Missile Point %d", i); progress->incrementWithMessage(cstringtemp); weapons[i+k].type = MISSILE; weapons[i+k].muzzles.resize(poffile.MPNT_PointCount(i)); for (j = 0; j < poffile.MPNT_PointCount(i); j++) { poffile.MPNT_GetPoint(i, j, weapons[i+k].muzzles[j].point, weapons[i+k].muzzles[j].norm); weapons[i+k].muzzles[j].point = POFTranslate(weapons[i+k].muzzles[j].point); weapons[i+k].muzzles[j].norm = POFTranslate(weapons[i+k].muzzles[j].norm); } } // --------- turrets TGUN/TMIS --------- turrets.resize(poffile.TGUN_Count_Banks() + poffile.TMIS_Count_Banks()); for (i = 0; i < poffile.TGUN_Count_Banks(); i++) { // Update Progress sprintf(cstringtemp, "Getting Gun Turret %d", i); progress->incrementWithMessage(cstringtemp); turrets[i].type = GUN; poffile.TGUN_Get_Bank(i, turrets[i].sobj_parent, turrets[i].sobj_par_phys, turrets[i].turret_normal); turrets[i].turret_normal = POFTranslate(turrets[i].turret_normal); turrets[i].fire_points.resize(poffile.TGUN_Count_Points(i)); for (j = 0; j < poffile.TGUN_Count_Points(i); j++) { poffile.TGUN_Get_FirePoint(i, j, turrets[i].fire_points[j]); turrets[i].fire_points[j] = POFTranslate(turrets[i].fire_points[j]); } } k = poffile.TGUN_Count_Banks(); for (i = 0; i < poffile.TMIS_Count_Banks(); i++) { // Update Progress sprintf(cstringtemp, "Getting Missile Turret %d", i); progress->incrementWithMessage(cstringtemp); turrets[i+k].type = GUN; poffile.TMIS_Get_Bank(i, turrets[i+k].sobj_parent, turrets[i+k].sobj_par_phys, turrets[i+k].turret_normal); turrets[i+k].turret_normal = POFTranslate(turrets[i+k].turret_normal); turrets[i+k].fire_points.resize(poffile.TMIS_Count_Points(i)); for (j = 0; j < poffile.TMIS_Count_Points(i); j++) { poffile.TMIS_Get_FirePoint(i, j, turrets[i+k].fire_points[j]); turrets[i+k].fire_points[j] = POFTranslate(turrets[i+k].fire_points[j]); } } // --------- docking --------- docking.resize(poffile.DOCK_Count_Docks()); for (i = 0; i < poffile.DOCK_Count_Docks(); i++) { // Update Progress sprintf(cstringtemp, "Getting Docking Point %d", i); progress->incrementWithMessage(cstringtemp); poffile.DOCK_Get_DockProps(i, docking[i].properties); docking[i].dockpoints.resize(poffile.DOCK_Count_Points(i)); for (j = 0; j < poffile.DOCK_Count_Points(i); j++) { poffile.DOCK_Get_Point(i, j, docking[i].dockpoints[j].point, docking[i].dockpoints[j].norm); docking[i].dockpoints[j].point = POFTranslate(docking[i].dockpoints[j].point); docking[i].dockpoints[j].norm = POFTranslate(docking[i].dockpoints[j].norm); } docking[i].paths.resize(poffile.DOCK_Count_SplinePaths(i)); for (j = 0; j < poffile.DOCK_Count_SplinePaths(i); j++) { poffile.DOCK_Get_SplinePath(i, j, docking[i].paths[j]); } } // --------- thrusters --------- thrusters.resize(poffile.FUEL_Count_Thrusters()); for (i = 0; i < poffile.FUEL_Count_Thrusters(); i++) { // Update Progress sprintf(cstringtemp, "Getting Thruster %d", i); progress->incrementWithMessage(cstringtemp); poffile.FUEL_Get_ThrusterProps(i, thrusters[i].properties); thrusters[i].points.resize(poffile.FUEL_Count_Glows(i)); for (j = 0; j < poffile.FUEL_Count_Glows(i); j++) { poffile.FUEL_Get_GlowPoint(i, j, thrusters[i].points[j].radius, thrusters[i].points[j].pos, thrusters[i].points[j].norm); thrusters[i].points[j].pos = POFTranslate(thrusters[i].points[j].pos); thrusters[i].points[j].norm = POFTranslate(thrusters[i].points[j].norm); } } // --------- shield_mesh --------- // Update Progress progress->incrementWithMessage("Getting Shields"); shield_mesh.resize(poffile.SHLD_Count_Faces()); int fcs[3], nbs[3]; for (i = 0; i < shield_mesh.size(); i++) { poffile.SHLD_Get_Face(i, shield_mesh[i].face_normal, fcs, nbs); shield_mesh[i].face_normal = POFTranslate(shield_mesh[i].face_normal);\ for (j = 0; j < 3; j++) { poffile.SHLD_Get_Vertex(fcs[j], shield_mesh[i].corners[j]); shield_mesh[i].corners[j] = POFTranslate(shield_mesh[i].corners[j]); } } // --------- insignia --------- insignia.resize(poffile.INSG_Count_Insignia()); vector3d uv, vv; float *u = (float *)&uv, *v = (float *)&vv; for (i = 0; i < poffile.INSG_Count_Insignia(); i++) { // Update Progress sprintf(cstringtemp, "Getting Insignia %d", i); progress->incrementWithMessage(cstringtemp); poffile.INSG_Get_Insignia(i, insignia[i].lod, insignia[i].offset); insignia[i].offset = POFTranslate(insignia[i].offset); insignia[i].faces.resize(poffile.INSG_Count_Faces(i)); for (j = 0; j < poffile.INSG_Count_Faces(i); j++) { poffile.INSG_Get_Insig_Face(i, j, fcs, uv, vv); for (k = 0; k < 3; k++) { poffile.INSG_Get_Insig_Vertex(i, fcs[k], insignia[i].faces[j].verts[k]); insignia[i].faces[j].verts[k] = POFTranslate(insignia[i].faces[j].verts[k]); insignia[i].faces[j].u[k] = u[k]; insignia[i].faces[j].v[k] = v[k]; } } } // --------- ai_paths --------- ai_paths.resize(poffile.PATH_Count_Paths()); for (i = 0; i < poffile.PATH_Count_Paths(); i++) { // Update Progress sprintf(cstringtemp, "Getting Path %d", i); progress->incrementWithMessage(cstringtemp); poffile.PATH_Get_Path(i, ai_paths[i].name, ai_paths[i].parent); ai_paths[i].verts.resize(poffile.PATH_Count_Verts(i)); for (j = 0; j < poffile.PATH_Count_Verts(i); j++) { poffile.PATH_Get_Vert(i, j, ai_paths[i].verts[j].pos, ai_paths[i].verts[j].radius); ai_paths[i].verts[j].pos = POFTranslate(ai_paths[i].verts[j].pos); } } // --------- light arrays --------- light_arrays.resize(poffile.GLOW_Count_LightGroups()); pcs_glow_array *gla; for (i = 0; i < poffile.GLOW_Count_LightGroups(); i++) { // Update Progress sprintf(cstringtemp, "Getting Glow Array %d", i); progress->incrementWithMessage(cstringtemp); gla = &light_arrays[i]; poffile.GLOW_Get_Group(i, gla->disp_time, gla->on_time, gla->off_time, gla->obj_parent, gla->LOD, gla->type, gla->properties); gla->lights.resize(poffile.GLOW_Count_Glows(i)); for (j = 0; j < poffile.GLOW_Count_Glows(i); j++) { poffile.GLOW_Get_GlowPoint(i, j, gla->lights[j].radius, gla->lights[j].pos, gla->lights[j].norm); gla->lights[j].pos = POFTranslate(gla->lights[j].pos); gla->lights[j].norm = POFTranslate(gla->lights[j].norm); } } // --------- Sub object Consversion --------- subobjects.resize(poffile.OBJ2_Count()); if (can_bsp_cache) bsp_cache.resize(poffile.OBJ2_Count()); for (i = 0; i < poffile.OBJ2_Count(); i++) { // Update Progress sprintf(cstringtemp, "Getting Object %d", i); progress->incrementWithMessage(cstringtemp); pcs_sobj* obj = &subobjects[i]; poffile.OBJ2_Get_Parent(i, obj->parent_sobj); poffile.OBJ2_Get_Radius(i, obj->radius); obj->radius_override = obj->radius; poffile.OBJ2_Get_Offset(i, obj->offset); obj->offset = POFTranslate(obj->offset); poffile.OBJ2_Get_GeoCenter(i, obj->geometric_center); obj->geometric_center = POFTranslate(obj->geometric_center); poffile.OBJ2_Get_BoundingMin(i, obj->bounding_box_min_point); poffile.OBJ2_Get_BoundingMax(i, obj->bounding_box_max_point); POFTranslateBoundingBoxes(obj->bounding_box_min_point, obj->bounding_box_max_point); obj->bounding_box_min_point_override = obj->bounding_box_min_point; obj->bounding_box_max_point_override = obj->bounding_box_max_point; poffile.OBJ2_Get_Name(i, obj->name); poffile.OBJ2_Get_Props(i, obj->properties); int type; poffile.OBJ2_Get_MoveType(i, type); // -1 = none, 1 = rotate switch (type) { case 1: obj->movement_type = ROTATE; break; default: obj->movement_type = MNONE; } poffile.OBJ2_Get_MoveAxis(i, type); // -1 = none, 1 = X, 2 = Z, 3 = Y switch (type) { case 0: obj->movement_axis = MV_X; break; case 1: obj->movement_axis = MV_Z; break; case 2: obj->movement_axis = MV_Y; break; default: obj->movement_axis = ANONE; } // fast method int bspsz; char *bspdata = NULL; poffile.OBJ2_Get_BSPDataPtr(i, bspsz, bspdata); //OBJ2_Get_BSPData obj->polygons.resize(100); // good starting size; unsigned int used_polygons = 0; BSP_DefPoints points; BSPTransPMF(0, (unsigned char *)bspdata, points, obj->polygons, used_polygons); obj->polygons.resize(used_polygons); // resize to exact size if (can_bsp_cache) poffile.OBJ2_Get_BSPData(i, bsp_cache[i].bsp_data); //if (bspdata) // delete[] bspdata; //bspdata = NULL; } Transform(matrix(), vector3d()); header.max_radius_overridden = std::fabs(header.max_radius - header.max_radius_override) > 0.0001f; header.max_bounding_overridden = header.max_bounding != header.max_bounding_override; header.min_bounding_overridden = header.min_bounding != header.min_bounding_override; for (auto& sobj : subobjects) { sobj.radius_overridden = std::fabs(sobj.radius - sobj.radius_override) > 0.0001f; sobj.bounding_box_min_point_overridden = sobj.bounding_box_min_point != sobj.bounding_box_min_point_override; sobj.bounding_box_max_point_overridden = sobj.bounding_box_max_point != sobj.bounding_box_max_point_override; } return 0; }
int PCS_Model::SaveToPOF(std::string filename, AsyncProgress* progress) { PCS_Model::BSP_MAX_DEPTH = 0; PCS_Model::BSP_NODE_POLYS = 1; PCS_Model::BSP_TREE_TIME = 0; PCS_Model::BSP_COMPILE_ERROR = false; POF poffile; unsigned int i,j,k,l; progress->setTarget(6 + light_arrays.size() + ai_paths.size() + insignia.size() + shield_mesh.size() + thrusters.size() + docking.size() + turrets.size() + weapons.size() + special.size() + eyes.size() + model_info.size() + subobjects.size() + textures.size()); char cstringtemp[256]; // Update Progress progress->incrementWithMessage("Writing Header Pt1"); // --------- convert cross sections --------- std::vector<cross_section> sections; sections.resize(header.cross_sections.size()); for (i = 0; i < header.cross_sections.size(); i++) { sections[i].depth = header.cross_sections[i].depth; sections[i].radius = header.cross_sections[i].radius; } poffile.HDR2_Set_CrossSections(header.cross_sections.size(), sections); // Update Progress progress->incrementWithMessage("Writing Header Pt2"); // --------- ACEN --------- poffile.ACEN_Set_acen(POFTranslate(autocentering)); // Update Progress progress->incrementWithMessage("Writing Acen"); // --------- TXTR --------- // Update Progress progress->incrementWithMessage("Writing Textures"); for (i = 0; i < textures.size(); i++) poffile.TXTR_AddTexture(textures[i]); // --------- Sub object Consversion --------- wxLongLong time = wxGetLocalTimeMillis(); bool bsp_compiled = false; header.max_radius = 0.0f; for (i = 0; i < subobjects.size(); i++) { // Update Progress //if (subobjects[i].name == "debris08") // sprintf(cstringtemp, "Submodel %d: %s SENTINAL!", i, subobjects[i].name.c_str()); //else sprintf(cstringtemp, "Submodel %d: %s", i, subobjects[i].name.c_str()); progress->incrementWithMessage(cstringtemp); //memset((char *)&obj, 0, sizeof(OBJ2)); this is NO LONGER ALLOWED - obj2 now contains an class w/ vtable boost::scoped_ptr<OBJ2> obj(new OBJ2); obj->submodel_number = i; if (!PMFObj_to_POFObj2(i, *obj, bsp_compiled, header.max_radius)) { return 2; // error occured in bsp splitting! } poffile.OBJ2_Add(*obj); // takes over object management - including pointers } time = wxGetLocalTimeMillis() - time; // we succeeded in compiling - let's cache the result can_bsp_cache = true; bsp_cache.resize(subobjects.size()); for (i = 0; i < subobjects.size(); i++) poffile.OBJ2_Get_BSPData(i, bsp_cache[i].bsp_data); // --------- ---------------------- --------- int idx = GetModelInfoCount(); char cstrtmp[256]; wxString strtmp = PCS2_VERSION; sprintf(cstrtmp, "PMFSaveToPOF: Compiled on %s with %s\nmax BSP depth was %d\nmost polys in a single node was %d\nTotal Compile time was %ldms, tree generation time was %ldms", std::string(strtmp.mb_str()).c_str(), std::string(PCS2_COMP_VERSION.mb_str()).c_str(), PCS_Model::BSP_MAX_DEPTH,PCS_Model::BSP_NODE_POLYS, time.ToLong(), PCS_Model::BSP_TREE_TIME.ToLong()); bool found = false; for (i = 0; i < model_info.size() && !found; i++) { if (strstr(model_info[i].c_str(), "PMFSaveToPOF") != NULL) { found = true; if (bsp_compiled) // update the string model_info[i] = cstrtmp; } } if (!found) AddModelInfo(cstrtmp); j = 0; for (i = 0; i < model_info.size(); i++) j += model_info[i].length() + 1; boost::scoped_ptr<char> pinf(new char[j]); memset(pinf.get(), 0, j); j = 0; for (i = 0; i < model_info.size(); i++) { // Update Progress sprintf(cstringtemp, "Writing String %d", i); progress->incrementWithMessage(cstringtemp); strncpy(pinf.get()+j, model_info[i].c_str(), model_info[i].length()); j+= model_info[i].length() + 1; } poffile.PINF_Set(pinf.get(), j); if (found) model_info.resize(idx); // back down to size // --------- EYE --------- for (i = 0; i < eyes.size(); i++) { // Update Progress sprintf(cstringtemp, "Writing Eye %d", i); progress->incrementWithMessage(cstringtemp); poffile.EYE_Add_Eye(eyes[i].sobj_number, POFTranslate(eyes[i].sobj_offset), POFTranslate(eyes[i].normal)); } // --------- SPCL --------- for (i = 0; i < special.size(); i++) { // Update Progress sprintf(cstringtemp, "Writing Special %d", i); progress->incrementWithMessage(cstringtemp); poffile.SPCL_AddSpecial(special[i].name, special[i].properties, POFTranslate(special[i].point), special[i].radius); } k = l = 0; // --------- weapons (GPNT/MPNT) --------- for (i = 0; i < weapons.size(); i++) { // Update Progress sprintf(cstringtemp, "Writing Weapon %d", i); progress->incrementWithMessage(cstringtemp); if (weapons[i].type == GUN) { poffile.GPNT_AddSlot(); for (j = 0; j < weapons[i].muzzles.size(); j++) { poffile.GPNT_AddPoint(k, POFTranslate(weapons[i].muzzles[j].point), POFTranslate(weapons[i].muzzles[j].norm)); } k++; } else { poffile.MPNT_AddSlot(); for (j = 0; j < weapons[i].muzzles.size(); j++) { poffile.MPNT_AddPoint(l, POFTranslate(weapons[i].muzzles[j].point), POFTranslate(weapons[i].muzzles[j].norm)); } l++; } } // --------- turrets TGUN/TMIS --------- k = l = 0; for (i = 0; i < turrets.size(); i++) { // Update Progress sprintf(cstringtemp, "Writing Turret %d", i); progress->incrementWithMessage(cstringtemp); if (turrets[i].type == GUN) { poffile.TGUN_Add_Bank(turrets[i].sobj_parent, turrets[i].sobj_par_phys, POFTranslate(turrets[i].turret_normal)); for (j = 0; j < turrets[i].fire_points.size(); j++) { poffile.TGUN_Add_FirePoint(k, POFTranslate(turrets[i].fire_points[j])); } k++; } else { poffile.TMIS_Add_Bank(turrets[i].sobj_parent, turrets[i].sobj_par_phys, POFTranslate(turrets[i].turret_normal)); for (j = 0; j < turrets[i].fire_points.size(); j++) { poffile.TMIS_Add_FirePoint(l, POFTranslate(turrets[i].fire_points[j])); } l++; } } // --------- docking --------- for (i = 0; i < docking.size(); i++) { // Update Progress sprintf(cstringtemp, "Writing Docking %d", i); progress->incrementWithMessage(cstringtemp); poffile.DOCK_Add_Dock(docking[i].properties); for (j = 0; j < docking[i].dockpoints.size(); j++) { poffile.DOCK_Add_Point(i, POFTranslate(docking[i].dockpoints[j].point), POFTranslate(docking[i].dockpoints[j].norm)); } for (j = 0; j < docking[i].paths.size(); j++) { poffile.DOCK_Add_SplinePath(i, docking[i].paths[j]); } } // --------- thrusters --------- for (i = 0; i < thrusters.size(); i++) { // Update Progress sprintf(cstringtemp, "Writing Thruster %d", i); progress->incrementWithMessage(cstringtemp); poffile.FUEL_Add_Thruster(thrusters[i].properties); for (j = 0; j < thrusters[i].points.size(); j++) { poffile.FUEL_Add_GlowPoint(i, thrusters[i].points[j].radius, POFTranslate(thrusters[i].points[j].pos), POFTranslate(thrusters[i].points[j].norm)); } } // --------- shield_mesh --------- int fcs[3], nbs[3]; std::vector<vector3d> points(shield_mesh.size()*3); vector3d shldtvect; // make points list l = 0; for (i = 0; i < shield_mesh.size(); i++) { for (j = 0; j < 3; j++) { bool found_corner = false; for (auto& p : points) { if (p == POFTranslate(shield_mesh[i].corners[j])) { found_corner = true; break; } } if (!found_corner) { if (l >= points.size()) points.resize(points.size()*2); points[l] = POFTranslate(shield_mesh[i].corners[j]); l++; } } } points.resize(l); // translate shield mesh for (i = 0; i < shield_mesh.size(); i++) { // Update Progress sprintf(cstringtemp, "Writing Shield Tri %d", i); progress->incrementWithMessage(cstringtemp); // adds points to list if need, determine fcs[] for (j = 0; j < 3; j++) { shldtvect = POFTranslate(shield_mesh[i].corners[j]); fcs[j] = FindInList(points, shldtvect); } // determine neighbors (nbs[]) j=0; for (k = 0; k < shield_mesh.size() && j < 3; k++) { if (Neighbor(shield_mesh[i], shield_mesh[k]) && i != k) { nbs[j] = k; j++; } } // add poffile.SHLD_Add_Face(POFTranslate(shield_mesh[i].face_normal), fcs, nbs); } // add points // Update Progress progress->incrementWithMessage("Writing Shield Points"); for (i = 0; i < points.size(); i++) poffile.SHLD_Add_Vertex(points[i]); progress->incrementWithMessage("Writing Shield Collision Tree"); // --------------- generate shield collision tree ---------------- if (poffile.SHLD_Count_Faces() > 0) { std::vector<pcs_polygon> shldmesh(poffile.SHLD_Count_Faces()); // make a pcs_polygon mesh from the shields for (i = 0; i < shldmesh.size(); i++) { shldmesh[i].verts.resize(3); poffile.SHLD_Get_Face(i, shldmesh[i].norm, fcs, nbs); for (j = 0; j < 3; j++) { poffile.SHLD_Get_Vertex(fcs[j], shldmesh[i].verts[j].point); shldmesh[i].verts[j].norm = shldmesh[i].norm; } shldmesh[i].centeroid = PolygonCenter(shldmesh[i]); } // make the tree vector3d smin, smax; std::unique_ptr<bsp_tree_node> shld_root = MakeTree(shldmesh, smax, smin); // pack the tree int sldc_size = CalcSLDCTreeSize(shld_root.get()); std::vector<char> sldc; sldc.resize(sldc_size); PackTreeInSLDC(shld_root.get(), 0, &sldc.front(), sldc_size); poffile.SLDC_SetTree(std::move(sldc)); // POFHandler will steal our copy of the buffer } // --------- insignia --------- vector3d uv, vv; float *u = (float *)&uv, *v = (float *)&vv; for (i = 0; i < insignia.size(); i++) { // Update Progress sprintf(cstringtemp, "Writing Insignia %d", i); progress->incrementWithMessage(cstringtemp); poffile.INSG_Add_insignia(insignia[i].lod, POFTranslate(insignia[i].offset)); for (j = 0; j < insignia[i].faces.size(); j++) { for (k = 0; k < 3; k++) { while ((l = poffile.INST_Find_Vert(i, POFTranslate(insignia[i].faces[j].verts[k]))) == (unsigned)-1) { poffile.INSG_Add_Insig_Vertex(i, POFTranslate(insignia[i].faces[j].verts[k])); } fcs[k] = l; u[k] = insignia[i].faces[j].u[k]; v[k] = insignia[i].faces[j].v[k]; } poffile.INSG_Add_Insig_Face(i, fcs, uv, vv); } } // --------- ai_paths --------- for (i = 0; i < ai_paths.size(); i++) { // Update Progress sprintf(cstringtemp, "Writing Path %d", i); progress->incrementWithMessage(cstringtemp); poffile.PATH_Add_Path(ai_paths[i].name, ai_paths[i].parent); for (j = 0; j < ai_paths[i].verts.size(); j++) { poffile.PATH_Add_Vert(i, POFTranslate(ai_paths[i].verts[j].pos), ai_paths[i].verts[j].radius); } } // --------- light arrays --------- pcs_glow_array *gla; for (i = 0; i < light_arrays.size(); i++) { // Update Progress sprintf(cstringtemp, "Writing Glow %d", i); progress->incrementWithMessage(cstringtemp); gla = &light_arrays[i]; poffile.GLOW_Add_LightGroup(gla->disp_time, gla->on_time, gla->off_time, gla->obj_parent, gla->LOD, gla->type, gla->properties); for (j = 0; j < gla->lights.size(); j++) { poffile.GLOW_Add_GlowPoint(i, gla->lights[j].radius, POFTranslate(gla->lights[j].pos), POFTranslate(gla->lights[j].norm)); } } // --------- HDR2 --------- // let's make new BBoxes based on the subobjects vector3d minbox, maxbox, tmpmin, tmpmax; poffile.OBJ2_Get_BoundingMax(0, maxbox); poffile.OBJ2_Get_BoundingMin(0, minbox); for (i = 1; i < poffile.OBJ2_Count(); i++) { vector3d sobj_offset(POFTranslate(OffsetFromParent(i))); poffile.OBJ2_Get_BoundingMax(i, tmpmax); poffile.OBJ2_Get_BoundingMin(i, tmpmin); ExpandBoundingBoxes(maxbox, minbox, tmpmax + sobj_offset); ExpandBoundingBoxes(maxbox, minbox, tmpmin + sobj_offset); } for (i = 0; i < poffile.SHLD_Count_Vertices(); i++) { poffile.SHLD_Get_Vertex(i, tmpmax); ExpandBoundingBoxes(maxbox, minbox, tmpmax); } // update our bounding boxes //axis doesn't matter on the bounding boxes - it's all negative/positive values! i'm a faqing moron poffile.HDR2_Set_MinBound(header.min_bounding_overridden ? header.min_bounding_override : minbox); poffile.HDR2_Set_MaxBound(header.max_bounding_overridden ? header.max_bounding_override : maxbox); this->header.max_bounding = minbox; this->header.min_bounding = maxbox; poffile.HDR2_Set_MaxRadius(header.max_radius_overridden ? header.max_radius_override : header.max_radius); poffile.HDR2_Set_Details(header.detail_levels.size(), header.detail_levels); poffile.HDR2_Set_Debris(header.debris_pieces.size(), header.debris_pieces); poffile.HDR2_Set_Mass(header.mass); poffile.HDR2_Set_MassCenter(POFTranslate(header.mass_center)); poffile.HDR2_Set_MomentInertia(header.MOI); poffile.HDR2_Set_SOBJCount(GetSOBJCount()); std::ofstream out(filename.c_str(), std::ios::out | std::ios::binary); if (!poffile.SavePOF(out)) return 1; return 0; }
bool PCS_Model::PMFObj_to_POFObj2(int src_num, OBJ2 &dst, bool &bsp_compiled, float& model_radius) { pcs_sobj &src = subobjects[src_num]; dst.submodel_parent = src.parent_sobj; dst.offset = POFTranslate(src.offset); dst.geometric_center = POFTranslate(src.geometric_center); dst.submodel_name = APStoString(src.name); dst.properties = APStoString(src.properties); switch (src.movement_type) { case ROTATE: dst.movement_type = 1; break; default: dst.movement_type = -1; } switch (src.movement_axis) { case MV_X: dst.movement_axis = 0; break; case MV_Z: dst.movement_axis = 1; break; case MV_Y: dst.movement_axis = 2; break; default: dst.movement_axis = -1; } dst.reserved = 0; if(!can_bsp_cache || bsp_cache[src_num].changed) { // convert them to POF axis std::vector<pcs_polygon> clean_list = src.polygons; for (size_t i = 0; i < clean_list.size(); i++) { clean_list[i].norm = POFTranslate(clean_list[i].norm); for (size_t j = 0; j < clean_list[i].verts.size(); j++) { clean_list[i].verts[j].point = POFTranslate(clean_list[i].verts[j].point); clean_list[i].verts[j].norm = POFTranslate(clean_list[i].verts[j].norm); } clean_list[i].centeroid = PolygonCenter(clean_list[i]); } // BSP Compilation! // assemble points list std::vector<bsp_vert> points_list; std::vector<vector3d> pnts; std::unordered_map<vector3d, int> point_to_index; std::unordered_map<vector3d, int> normal_to_index; for (size_t i = 0; i < pnts.size(); i++) { point_to_index.insert(std::make_pair(pnts[i], i)); } bsp_vert temp; points_list.reserve(clean_list.size()); for (size_t i = 0; i < clean_list.size(); i++) { for (size_t j = 0; j < clean_list[i].verts.size(); j++) { auto point = point_to_index.find(clean_list[i].verts[j].point); if (point == point_to_index.end()) { point_to_index.insert(std::make_pair(clean_list[i].verts[j].point, points_list.size())); points_list.emplace_back(); points_list.back().point = clean_list[i].verts[j].point; pnts.push_back(points_list.back().point); } auto normal = normal_to_index.find(clean_list[i].verts[j].norm); if (normal == normal_to_index.end()) { points_list[normal_to_index.size() / 128].norms.push_back(clean_list[i].verts[j].norm); normal_to_index.insert(std::make_pair(clean_list[i].verts[j].norm, normal_to_index.size())); } } } // create our defpoints BSP_DefPoints points; MakeDefPoints(points, points_list); vector3d AvgNormal; // create tree std::unique_ptr<bsp_tree_node> root = MakeTree(clean_list, dst.bounding_box_max_point, dst.bounding_box_min_point); // allocate buffer and write the defpoints dst.bsp_data.resize(points.head.size + CalculateTreeSize(root.get(), clean_list)); if (points.Write(&dst.bsp_data.front()) != points.head.size) return false; // calculation error //std::ofstream bsp_debug("c:\\bsp.txt"); //DebugPrintTree(root, bsp_debug); // pack the tree int error_flags = 0; PackTreeInBSP(root.get(), points.head.size, &dst.bsp_data.front(), clean_list, normal_to_index, point_to_index, points, dst.geometric_center, dst.bsp_data.size(), error_flags); // we got errors! if (error_flags != BSP_NOERRORS) return false; // update the bsp_compiled to be true bsp_compiled = true; // update the BSP cache with the new result if (can_bsp_cache) { // clear the saved - stale cache bsp_cache[src_num].decache(); bsp_cache[src_num].bsp_data = dst.bsp_data; bsp_cache[src_num].changed = false; } } else // Used cached copy! { dst.bsp_data = bsp_cache[src_num].bsp_data; } dst.radius = 0.0f; dst.bounding_box_max_point = vector3d(FLT_MIN, FLT_MIN, FLT_MIN); dst.bounding_box_min_point = vector3d(FLT_MAX, FLT_MAX, FLT_MAX); vector3d global_offset(OffsetFromParent(src_num)); for(unsigned int i = 0; i<src.polygons.size(); i++){ for(unsigned int j = 0; j<src.polygons[i].verts.size(); j++){ ExpandBoundingBoxes(dst.bounding_box_max_point, dst.bounding_box_min_point, src.polygons[i].verts[j].point); float norm = Magnitude(src.polygons[i].verts[j].point); if (norm > dst.radius) { dst.radius = norm; } float global_norm = Magnitude(src.polygons[i].verts[j].point + global_offset); if (global_norm > model_radius) { model_radius = global_norm; } } } if (dst.radius == 0.0f) { dst.bounding_box_max_point = vector3d(); dst.bounding_box_min_point = vector3d(); } if (src.radius_overridden) { dst.radius = src.radius_override; } if (src.bounding_box_min_point_overridden) { dst.bounding_box_min_point = src.bounding_box_min_point_override; } if (src.bounding_box_max_point_overridden) { dst.bounding_box_max_point = src.bounding_box_max_point_override; } POFTranslateBoundingBoxes(dst.bounding_box_min_point, dst.bounding_box_max_point); return true; }