// Assumes a MacOS Pascal string; the resulting string will have // a null byte at the end. void StringSet::Add(size_t Index, unsigned char *String) { if (Index < 0) return; // Replace string list with longer one if necessary size_t NewNumStrings = NumStrings; while (Index >= NewNumStrings) {NewNumStrings <<= 1;} if (NewNumStrings > NumStrings) { unsigned char **NewStrings = new unsigned char *[NewNumStrings]; objlist_clear(NewStrings+NumStrings,(NewNumStrings-NumStrings)); objlist_copy(NewStrings,Strings,NumStrings); delete []Strings; Strings = NewStrings; NumStrings = NewNumStrings; } // Delete the old string if necessary if (Strings[Index]) delete []Strings[Index]; unsigned short Length = String[0]; unsigned char *_String = new unsigned char[Length+2]; memcpy(_String,String,Length+2); _String[Length+1] = 0; // for making an in-place C string Strings[Index] = _String; }
bool XML_DynLimParser::End() { // Resize and clear the arrays of objects, monsters, effects, and projectiles EffectList.resize(MAXIMUM_EFFECTS_PER_MAP); ObjectList.resize(MAXIMUM_OBJECTS_PER_MAP); MonsterList.resize(MAXIMUM_MONSTERS_PER_MAP); ProjectileList.resize(MAXIMUM_PROJECTILES_PER_MAP); #if 0 objlist_clear(effects, EffectList.size()); objlist_clear(projectiles, ProjectileList.size()); objlist_clear(monsters, MonsterList.size()); objlist_clear(objects, ObjectList.size()); #endif // Resize the array of paths also allocate_pathfinding_memory(); return true; }
StringSet::StringSet(short _ID) { // Of course ID = _ID; NumStrings = 16; // Reasonable starting number; what Sun uses in Java Strings = new unsigned char *[NumStrings]; // Set all the string pointers to NULL objlist_clear(Strings,NumStrings); // Last, but not least: Next = NULL; }
// From the position data void Model3D::FindBoundingBox() { size_t NumVertices = Positions.size()/3; if (NumVertices > 0) { // Find the min and max of the positions: VecCopy(&Positions[0],BoundingBox[0]); VecCopy(&Positions[0],BoundingBox[1]); for (size_t i=1; i<NumVertices; i++) { GLfloat *Pos = &Positions[3*i]; for (int ib=0; ib<3; ib++) { BoundingBox[0][ib] = MIN(BoundingBox[0][ib],Pos[ib]); BoundingBox[1][ib] = MAX(BoundingBox[1][ib],Pos[ib]); } } } else { // Clear the bounding box objlist_clear(BoundingBox[0],3); objlist_clear(BoundingBox[1],3); } }
void OGL_SkinManager::Reset(bool Clear_OGL_Txtrs) { if (Clear_OGL_Txtrs) { for (int k=0; k<NUMBER_OF_OPENGL_BITMAP_SETS; k++) for (int l=0; l<NUMBER_OF_TEXTURES; l++) { if (IDsInUse[k][l]) { glDeleteTextures(1,&IDs[k][l]); } } } // Mass clearing objlist_clear(IDsInUse[0],NUMBER_OF_OPENGL_BITMAP_SETS*NUMBER_OF_TEXTURES); }
void Model3D::BuildInverseVSIndices() { if (VtxSrcIndices.empty()) { return; } InverseVSIndices.resize(VtxSrcIndices.size()); InvVSIPointers.resize(VtxSources.size()+1); // One extra member // Use the pointers as temporary storage for the count objlist_clear(InvVSIPtrBase(),InvVSIPointers.size()); for (vector<GLushort>::iterator VSI_Iter = VtxSrcIndices.begin(); VSI_Iter < VtxSrcIndices.end(); VSI_Iter++) InvVSIPointers[*VSI_Iter]++; // Find the positions from the counts GLushort PtrSum = 0; for (vector<GLushort>::iterator IVP_Iter = InvVSIPointers.begin(); IVP_Iter < InvVSIPointers.end(); IVP_Iter++) { GLushort NewPtrSum = PtrSum + *IVP_Iter; *IVP_Iter = PtrSum; PtrSum = NewPtrSum; } // Place the inverse indices for (unsigned k = 0; k<VtxSrcIndices.size(); k++) InverseVSIndices[InvVSIPointers[VtxSrcIndices[k]]++] = k; // Push the pointer values forward in the list // since they'd become their next values in it. // The reverse iteration is necessary to avoid overwriting for (vector<GLushort>::iterator IVP_Iter = InvVSIPointers.end()-1; IVP_Iter > InvVSIPointers.begin(); IVP_Iter--) { *IVP_Iter = *(IVP_Iter - 1); } InvVSIPointers[0] = 0; }
// Normalize the normals void Model3D::AdjustNormals(int NormalType, float SmoothThreshold) { // Copy in normal sources for processing if (!NormSources.empty()) { Normals.resize(NormSources.size()); objlist_copy(NormBase(),NormSrcBase(),NormSources.size()); } // Which kind of special processing? switch(NormalType) { case None: Normals.clear(); break; case Original: case Reversed: default: // Normalize for (unsigned k=0; k<Normals.size()/3; k++) NormalizeNormal(&Normals[3*k]); break; case ClockwiseSide: case CounterclockwiseSide: // The really interesting stuff { // First, create a list of per-polygon normals size_t NumPolys = NumVI()/3; vector<FlaggedVector> PerPolygonNormalList(NumPolys); GLushort *IndxPtr = VIBase(); for (unsigned k=0; k<NumPolys; k++) { // The three vertices: GLfloat *P0 = &Positions[3*(*(IndxPtr++))]; GLfloat *P1 = &Positions[3*(*(IndxPtr++))]; GLfloat *P2 = &Positions[3*(*(IndxPtr++))]; // The two in-polygon vectors: GLfloat P01[3]; P01[0] = P1[0] - P0[0]; P01[1] = P1[1] - P0[1]; P01[2] = P1[2] - P0[2]; GLfloat P02[3]; P02[0] = P2[0] - P0[0]; P02[1] = P2[1] - P0[1]; P02[2] = P2[2] - P0[2]; // Those vectors' normal: FlaggedVector& PPN = PerPolygonNormalList[k]; PPN.Vec[0] = P01[1]*P02[2] - P01[2]*P02[1]; PPN.Vec[1] = P01[2]*P02[0] - P01[0]*P02[2]; PPN.Vec[2] = P01[0]*P02[1] - P01[1]*P02[0]; PPN.Flag = NormalizeNormal(PPN.Vec); } // Create a list of per-vertex normals size_t NumVerts = Positions.size()/3; vector<FlaggedVector> PerVertexNormalList(NumVerts); objlist_clear(&PerVertexNormalList[0],NumVerts); IndxPtr = VIBase(); for (unsigned k=0; k<NumPolys; k++) { FlaggedVector& PPN = PerPolygonNormalList[k]; for (unsigned c=0; c<3; c++) { GLushort VertIndx = *(IndxPtr++); GLfloat *V = PerVertexNormalList[VertIndx].Vec; *(V++) += PPN.Vec[0]; *(V++) += PPN.Vec[1]; *(V++) += PPN.Vec[2]; } } // Normalize the per-vertex normals for (unsigned k=0; k<NumVerts; k++) { FlaggedVector& PVN = PerVertexNormalList[k]; PVN.Flag = NormalizeNormal(PVN.Vec); } // Find the variance of each of the per-vertex normals; // use that to decide whether to keep them unsplit; // this also needs counting up the number of polygons per vertex. vector<GLfloat> Variances(NumVerts); objlist_clear(&Variances[0],NumVerts); vector<short> NumPolysPerVert(NumVerts); objlist_clear(&NumPolysPerVert[0],NumVerts); IndxPtr = VIBase(); for (unsigned k=0; k<NumPolys; k++) { FlaggedVector& PPN = PerPolygonNormalList[k]; for (unsigned c=0; c<3; c++) { GLushort VertIndx = *(IndxPtr++); FlaggedVector& PVN = PerVertexNormalList[VertIndx]; if (PVN.Flag) { GLfloat *V = PVN.Vec; GLfloat D0 = *(V++) - PPN.Vec[0]; GLfloat D1 = *(V++) - PPN.Vec[1]; GLfloat D2 = *(V++) - PPN.Vec[2]; Variances[VertIndx] += (D0*D0 + D1*D1 + D2*D2); NumPolysPerVert[VertIndx]++; } } } // Decide whether to split each vertex; // if the flag is "true", a vertex is not to be split for (unsigned k=0; k<NumVerts; k++) { // Vertices without contributions will automatically have // their flags be false, as a result of NormalizeNormal() unsigned NumVertPolys = NumPolysPerVert[k]; if (NumVertPolys > 0 && PerVertexNormalList[k].Flag) { PerVertexNormalList[k].Flag = sqrt(Variances[k]/NumVertPolys) <= SmoothThreshold; } } // The vertex flags are now set for whether to use that vertex's normal; // re-count the number of polygons per vertex. // Use NONE for unsplit ones objlist_clear(&NumPolysPerVert[0],NumVerts); IndxPtr = VIBase(); for (unsigned k=0; k<NumPolys; k++) { for (unsigned c=0; c<3; c++) { GLushort VertIndx = *(IndxPtr++); FlaggedVector& PVN = PerVertexNormalList[VertIndx]; if (PVN.Flag) { NumPolysPerVert[VertIndx] = NONE; } else{ NumPolysPerVert[VertIndx]++; } } } // Construct a polygon-association list; this will indicate // which polygons are associated with each of the resulting instances // of a split vertex (unsplit: NONE). // NumPolysPerVert will be recycled as a counter list, // after being used to construct a cumulative index-in-list array. // Finding that list will be used to find how many new vertices there are. vector<short> IndicesInList(NumVerts); short IndxInList = 0; for (unsigned k=0; k<NumVerts; k++) { IndicesInList[k] = IndxInList; FlaggedVector& PVN = PerVertexNormalList[k]; IndxInList += PVN.Flag ? 1 : NumPolysPerVert[k]; } GLushort NewNumVerts = IndxInList; vector<short> VertexPolygons(NewNumVerts); objlist_clear(&NumPolysPerVert[0],NumVerts); // In creating that list, also remap the triangles' vertices GLushort *VIPtr = VIBase(); for (unsigned k=0; k<NumPolys; k++) { for (unsigned c=0; c<3; c++) { GLushort VertIndx = *VIPtr; GLushort NewVertIndx = IndicesInList[VertIndx]; FlaggedVector& PVN = PerVertexNormalList[VertIndx]; if (PVN.Flag) { NumPolysPerVert[VertIndx] = NONE; VertexPolygons[NewVertIndx] = NONE; } else { NewVertIndx += (NumPolysPerVert[VertIndx]++); VertexPolygons[NewVertIndx] = k; } *VIPtr = NewVertIndx; VIPtr++; } } // Split the vertices vector<GLfloat> NewPositions(3*NewNumVerts); vector<GLfloat> NewTxtrCoords; vector<GLfloat> NewNormals(3*NewNumVerts); vector<GLfloat> NewColors; vector<GLushort> NewVtxSrcIndices; bool TCPresent = !TxtrCoords.empty(); if (TCPresent) { NewTxtrCoords.resize(2*NewNumVerts); } bool ColPresent = !Colors.empty(); if (ColPresent) { NewColors.resize(3*NewNumVerts); } bool VSPresent = !VtxSrcIndices.empty(); if (VSPresent) { NewVtxSrcIndices.resize(NewNumVerts); } // Use marching pointers to speed up the copy-over GLfloat *OldP = &Positions[0]; GLfloat *NewP = &NewPositions[0]; GLfloat *OldT = &TxtrCoords[0]; GLfloat *NewT = &NewTxtrCoords[0]; GLfloat *OldC = &Colors[0]; GLfloat *NewC = &NewColors[0]; GLushort *OldS = &VtxSrcIndices[0]; GLushort *NewS = &NewVtxSrcIndices[0]; GLfloat *NewN = &NewNormals[0]; for (unsigned k=0; k<NumVerts; k++) { FlaggedVector& PVN = PerVertexNormalList[k]; unsigned NumVertPolys = PVN.Flag ? 1 : NumPolysPerVert[k]; for (unsigned c=0; c<NumVertPolys; c++) { GLfloat *OldPP = OldP; *(NewP++) = *(OldPP++); *(NewP++) = *(OldPP++); *(NewP++) = *(OldPP++); } if (TCPresent) { for (unsigned c=0; c<NumVertPolys; c++) { GLfloat *OldTP = OldT; *(NewT++) = *(OldTP++); *(NewT++) = *(OldTP++); } } if (ColPresent) { for (unsigned c=0; c<NumVertPolys; c++) { GLfloat *OldCP = OldC; *(NewC++) = *(OldCP++); *(NewC++) = *(OldCP++); *(NewC++) = *(OldCP++); } } if (VSPresent) { for (unsigned c=0; c<NumVertPolys; c++) *(NewS++) = *OldS; } if (PVN.Flag) { GLfloat *VP = PVN.Vec; *(NewN++) = *(VP++); *(NewN++) = *(VP++); *(NewN++) = *(VP++); } else { // A reference so that the incrementing can work on it short& IndxInList = IndicesInList[k]; for (unsigned c=0; c<NumVertPolys; c++) { GLfloat *VP = PerPolygonNormalList[VertexPolygons[IndxInList++]].Vec; *(NewN++) = *(VP++); *(NewN++) = *(VP++); *(NewN++) = *(VP++); } } // Advance! OldP += 3; if (TCPresent) { OldT += 2; } if (ColPresent) { OldC += 3; } if (VSPresent) { OldS++; } } assert(OldP == &Positions[3*NumVerts]); assert(NewP == &NewPositions[3*NewNumVerts]); if (TCPresent) { assert(OldT == &TxtrCoords[2*NumVerts]); assert(NewT == &NewTxtrCoords[2*NewNumVerts]); } if (ColPresent) { assert(OldC == &Colors[3*NumVerts]); assert(NewC == &NewColors[3*NewNumVerts]); } if (VSPresent) { assert(OldS == &VtxSrcIndices[NumVerts]); assert(NewS == &NewVtxSrcIndices[NewNumVerts]); } assert(NewN == &NewNormals[3*NewNumVerts]); // Accept the new vectors Positions.swap(NewPositions); TxtrCoords.swap(NewTxtrCoords); Normals.swap(NewNormals); Colors.swap(NewColors); VtxSrcIndices.swap(NewVtxSrcIndices); } break; } // Now flip switch(NormalType) { case Reversed: case CounterclockwiseSide: { GLfloat *NormalPtr = NormBase(); for (unsigned k=0; k<Normals.size(); k++) *(NormalPtr++) *= -1; } } // Copy back out to the normal sources; // do the copying out if the vertices have sources, // which is the case for boned models. if (!VtxSources.empty()) { size_t NormSize = Normals.size(); if (NormSize > 0) { NormSources.resize(NormSize); objlist_copy(NormSrcBase(),NormBase(),NormSize); } else{ NormSources.clear(); } } else{ NormSources.clear(); } }
/* origin,origin_polygon_index,yaw,pitch,roll,etc. have probably changed since last call */ void render_view( struct view_data *view, struct bitmap_definition *destination) { update_view_data(view); /* clear the render flags */ objlist_clear(render_flags, RENDER_FLAGS_BUFFER_SIZE); ResetOverheadMap(); /* #ifdef AUTOMAP_DEBUG memset(automap_lines, 0, (dynamic_world->line_count/8+((dynamic_world->line_count%8)?1:0)*sizeof(byte))); memset(automap_polygons, 0, (dynamic_world->polygon_count/8+((dynamic_world->polygon_count%8)?1:0)*sizeof(byte))); #endif */ if(view->terminal_mode_active) { /* Render the computer interface. */ render_computer_interface(view); } else { // LP: the render objects have a pointer to the current view in them, // so that one can get rid of redundant references to it in them. // LP: now from the visibility-tree class /* build the render tree, regardless of map mode, so the automap updates while active */ RenderVisTree.view = view; RenderVisTree.build_render_tree(); /* do something complicated and difficult to explain */ if (!view->overhead_map_active || map_is_translucent()) { // LP: now from the polygon-sorter class /* sort the render tree (so we have a depth-ordering of polygons) and accumulate clipping information for each polygon */ RenderSortPoly.view = view; RenderSortPoly.sort_render_tree(); // LP: now from the object-placement class /* build the render object list by looking at the sorted render tree */ RenderPlaceObjs.view = view; RenderPlaceObjs.build_render_object_list(); // LP addition: set the current rasterizer to whichever is appropriate here RasterizerClass *RasPtr; #ifdef HAVE_OPENGL if (OGL_IsActive()) RasPtr = (graphics_preferences->screen_mode.acceleration == _shader_acceleration) ? &Rasterizer_Shader : &Rasterizer_OGL; else { #endif // The software renderer needs this but the OpenGL one doesn't... Rasterizer_SW.screen = destination; RasPtr = &Rasterizer_SW; #ifdef HAVE_OPENGL } #endif // Set its view: RasPtr->SetView(*view); // Start rendering main view RasPtr->Begin(); // LP: now from the clipping/rasterizer class #ifdef HAVE_OPENGL RenderRasterizerClass *RenPtr = (graphics_preferences->screen_mode.acceleration == _shader_acceleration) ? &Render_Shader : &Render_Classic; #else RenderRasterizerClass *RenPtr = &Render_Classic; #endif /* render the object list, back to front, doing clipping on each surface before passing it to the texture-mapping code */ RenPtr->view = view; RenPtr->RasPtr = RasPtr; RenPtr->render_tree(); // LP: won't put this into a separate class /* render the playerÕs weapons, etc. */ render_viewer_sprite_layer(view, RasPtr); // Finish rendering main view RasPtr->End(); } if (view->overhead_map_active) { /* if the overhead map is active, render it */ render_overhead_map(view); } } }