#include "mungal4.h" #pragma hdrstop #include "..\munga\fileutil.h" #include "l4gauima.h" #include "l4app.h" #include "..\munga\notation.h" #include "..\munga\namelist.h" // #define LOCAL_TEST #if defined(LOCAL_TEST) # define Test_Tell(n) std::cout << n << std::flush #else # define Test_Tell(n) #endif //############################################################################ // GroupAttribute // - this is a private class used nowhere else. // It is initialized from a .GAT notation file, after which it // holds a list of attribute group names with associated color and // attribute fields. It may then be searched to find the values for // that attribute group. //############################################################################ class GroupAttribute SIGNATURED { public: enum { nameLength=64 }; int color; int attribute; char name[nameLength]; GroupAttribute *next; GroupAttribute(const char *new_name, int new_color, int new_attrib); ~GroupAttribute() {} Logical TestInstance() const { return True; } static Logical Initialize(const char *gat_file_name); static void Terminate(); static Logical Search(const char *name, int *color, int *attribute); protected: static GroupAttribute *head; }; GroupAttribute *GroupAttribute::head; GroupAttribute::GroupAttribute( const char *new_name, int new_color, int new_attrib ) { Test_Tell( "GroupAttribute::GroupAttribute(" << new_name << ", " << new_color << ", " << new_attrib << ")\n" ); Check_Pointer(this); Check_Pointer(new_name); name[0] = '\0'; // safety check Str_Copy(name, new_name, nameLength-1); name[nameLength-1] = '\0'; color = new_color; attribute = new_attrib; next = head; head = this; Check_Fpu(); } Logical GroupAttribute::Initialize(const char *gat_filename) { Test_Tell("GroupAttribute::Initialize(" << gat_filename << ")\n"); Check_Pointer(gat_filename); Logical result = False; //------------------------------------------------------------- // Open the associated .GAT file //------------------------------------------------------------- NotationFile *gat_file = new NotationFile(gat_filename); Check(gat_file); Register_Object(gat_file); //------------------------------------------------------------- // Create group, attribute, color name lists //------------------------------------------------------------- NameList *color_namelist = gat_file->MakeEntryList("colors"); if (color_namelist == NULL) { DEBUG_STREAM << gat_filename << " has no 'colors' page!" << std::endl; } NameList *attribute_namelist = gat_file->MakeEntryList("attributes"); if (attribute_namelist == NULL) { DEBUG_STREAM << gat_filename << " has no 'attributes' page!" << std::endl; } NameList *group_namelist = gat_file->MakeEntryList("groups"); if (group_namelist == NULL) { DEBUG_STREAM << gat_filename << " has no 'groups' page!" << std::endl; } if ( (attribute_namelist != NULL) && (color_namelist != NULL) && (group_namelist != NULL) ) { //------------------------------------------------------------- // Register the name lists //------------------------------------------------------------- Register_Object(color_namelist); Register_Object(attribute_namelist); Register_Object(group_namelist); //------------------------------------------------------------- // Clear the chain header //------------------------------------------------------------- head = NULL; //------------------------------------------------------------- // For all group names, build a GroupAttribute object //------------------------------------------------------------- NameList::Entry *group_entry, *color_entry, *attribute_entry; int i, new_attribute, new_color; Logical found; for ( group_entry = group_namelist->GetFirstEntry(); group_entry != NULL; group_entry = group_entry->GetNextEntry() ) { Check(group_entry); char buffer[256]; char *dest, *text = group_entry->GetChar(); new_attribute = 0; new_color = 0; if (text == NULL) { DEBUG_STREAM << text << " is an empty .GAT group!" << std::endl; } else { //------------------------------------------------------------- // Skip white space //------------------------------------------------------------- while (*text != '\0') { while (isspace(*text)) { ++text; } //------------------------------------------------------------- // Parse out one name //------------------------------------------------------------- for ( i=0,dest=buffer; i<(sizeof(buffer)-1); ++i,++dest,++text ) { if (!isalnum(*text)) { break; } *dest = *text; } *dest = '\0'; Test_Tell("attribute item= <" << buffer << ">\n"); //------------------------------------------------------------- // Search color list for name //------------------------------------------------------------- found = False; for ( color_entry = color_namelist->GetFirstEntry(); color_entry != NULL; color_entry = color_entry->GetNextEntry() ) { Check(color_entry); if (strcmp(color_entry->GetName(), buffer) == 0) { Check_Pointer(color_entry->GetData()); new_color = color_entry->GetAtoi(); Test_Tell("color=" << new_color << "\n"); found = True; break; } } if (! found) { //---------------------------------------------------------- // Search attribute list for name //---------------------------------------------------------- found = False; for ( attribute_entry =attribute_namelist->GetFirstEntry(); attribute_entry != NULL; attribute_entry = attribute_entry->GetNextEntry() ) { Check(attribute_entry); if (strcmp(attribute_entry->GetName(), buffer) == 0) { Check_Pointer(attribute_entry->GetData()); new_attribute |= attribute_entry->GetAtoi(); Test_Tell( "attribute=" << std::hex << new_attribute << std::dec << ">\n" ); found = True; break; } } if (! found) { DEBUG_STREAM << "Attribute '" << buffer << "' not found!" << std::endl; } } } } Check(group_entry); Check_Pointer(group_entry->GetName()); # if DEBUG_LEVEL == 0 new GroupAttribute( group_entry->GetName(), new_color, new_attribute ); # else GroupAttribute *group_attribute = new GroupAttribute( group_entry->GetName(), new_color, new_attribute ); Check(group_attribute); Register_Object(group_attribute); Test_Tell("object created\n"); # endif } //------------------------------------------------------------- // Release the name lists //------------------------------------------------------------- Test_Tell("loop finished, deleting namelists\n"); Check(color_namelist); Unregister_Object(color_namelist); delete color_namelist; Check(attribute_namelist); Unregister_Object(attribute_namelist); delete attribute_namelist; Check(group_namelist); Unregister_Object(group_namelist); delete group_namelist; result = True; } //------------------------------------------------------------- // Release the notation file //------------------------------------------------------------- Test_Tell("deleting .GAT notation file\n"); Check(gat_file); Unregister_Object(gat_file); delete gat_file; Test_Tell("returning " << result <<"\n"); Check_Fpu(); return result; } void GroupAttribute::Terminate() { Test_Tell("GroupAttribute::Terminate\n"); GroupAttribute *group_attribute, *next; for( group_attribute= head; group_attribute != NULL; group_attribute = next ) { Check(group_attribute); next = group_attribute->next; Unregister_Object(group_attribute); delete group_attribute; } head = NULL; Test_Tell("Termination completed\n"); Check_Fpu(); } Logical GroupAttribute::Search(const char *name, int *color_dest, int *attrib_dest) { Test_Tell("GroupAttribute::Search("<< name <<")\n"); GroupAttribute *group_attribute; for( group_attribute= head; group_attribute != NULL; group_attribute = group_attribute->next ) { Check(group_attribute); if ( strncmp( name, group_attribute->name, GroupAttribute::nameLength ) == 0 ) { Test_Tell("Found!\n"); *color_dest = group_attribute->color; *attrib_dest = group_attribute->attribute; Check_Fpu(); return True; } } Check_Fpu(); return False; } //############################################################################ // L4GaugeImage //############################################################################ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Construction and Destruction // L4GaugeImage * L4GaugeImage::Make(const char */*file_name*/) { return NULL; // Gauge images come exclusively from resources } L4GaugeImage * L4GaugeImage::Make(ResourceDescription::ResourceID new_resource_id) { Check(application); Check(application->GetResourceFile()); L4GaugeImage *image = NULL; //------------------------------------------- // Attempt to find the specified resource //------------------------------------------- ResourceDescription *stream_resource_description = application->GetResourceFile()->SearchList( new_resource_id, ResourceDescription::GaugeImageStreamResourceType ); if (stream_resource_description == NULL) { Tell( "L4GaugeImage::Make: resource ID '" << new_resource_id << "' does not exist\n" ); } else { //------------------------------------------- // Found it, open a DynamicMemoryStream //------------------------------------------- Check(stream_resource_description); stream_resource_description->Lock(); MemoryStream memory_stream( stream_resource_description->resourceAddress, stream_resource_description->resourceSize ); if (stream_resource_description->resourceAddress == NULL) { Tell("L4GaugeImage::Make: couldn't open stream\n"); } else { //------------------------------------------- // Create the object //------------------------------------------- image = new L4GaugeImage(&memory_stream); } stream_resource_description->Unlock(); } Check_Fpu(); return image; } L4GaugeImage::L4GaugeImage(MemoryStream *mem_stream) { Test_Tell("L4GaugeImage::L4GaugeImage\n"); Check_Pointer(this); Check(mem_stream); int i; //------------------------------------------------------------- // Read the number of vertices //------------------------------------------------------------- MemoryStream_Read(mem_stream, &vertexCount); Verify(vertexCount > 0); //------------------------------------------------------------- // Allocate the vertex array //------------------------------------------------------------- vertexArray = new Point3D[vertexCount]; Check_Pointer(vertexArray); Register_Pointer(vertexArray); //------------------------------------------------------------- // Read in the vertex values //------------------------------------------------------------- for(i=0; i 0); //------------------------------------------------------------- // Allocate the LOD scales //------------------------------------------------------------- LODScales = new Scalar[LODCount]; Check_Pointer(LODScales); Register_Pointer(LODScales); //------------------------------------------------------------- // Read the LOD scales //------------------------------------------------------------- for(i=0; iGetEntry("gauge", "image", &gauge_filename) != 0) { //------------------------------------------------------------- // It does, attempt to open the given notation file //------------------------------------------------------------- Tell("Opening gauge image " << gauge_filename << "\n"); char *gim_filename = MakePathedFilename(directories->gaugeDirectory, gauge_filename); Register_Pointer(gim_filename); NotationFile *gim_file = new NotationFile(gim_filename); Check(gim_file); Register_Object(gim_file); //-------------------------------------------------------- // Search for the name of the .GAT file //-------------------------------------------------------- const char *gat_entry; if (gim_file->GetEntry("object", "gatfile", &gat_entry) == 0) { DEBUG_STREAM << "Missing .gat specification!" << std::endl; } else { //------------------------------------------------------------- // Create the GroupAttribute data //------------------------------------------------------------- char *gat_filename = MakePathedFilename(directories->gaugeDirectory, gat_entry); Register_Pointer(gat_filename); if (GroupAttribute::Initialize(gat_filename)) { //------------------------------------------------------------- // Create a dynamic memory stream, write out the data // (note: the call to L4GaugeImage::DynamicMemoryStreamWrite() // internally calls the dynamic stream writes for all of the // 'owned' sub-parts as well) //------------------------------------------------------------- DynamicMemoryStream *gim_stream = new DynamicMemoryStream(); Check(gim_stream); Register_Object(gim_stream); if ( L4GaugeImage::MemoryStreamWrite( gim_stream, gim_file ) == True ) { //------------------------------------------------------------- // Create the resource description, assign an ID //------------------------------------------------------------- ResourceDescription *res_desc_stream = resource_file->ResourceFile::AddResourceMemoryStream( model_name, ResourceDescription::GaugeImageStreamResourceType, 1, ResourceDescription::Preload, gim_stream ); Check(res_desc_stream); res_id = res_desc_stream->resourceID; } //------------------------------------------------------------- // Release the GroupAttribute data //------------------------------------------------------------- GroupAttribute::Terminate(); Check(gim_stream); Unregister_Object(gim_stream); delete gim_stream; } Check_Pointer(gat_filename); Unregister_Pointer(gat_filename); delete gat_filename; } //------------------------------------------------------------- // Release variables //------------------------------------------------------------- Check(gim_file); Unregister_Object(gim_file); delete gim_file; Check_Pointer(gim_filename); Unregister_Pointer(gim_filename); delete gim_filename; Tell("Closed gauge image\n" << std::flush); } //------------------------------------------------------------- // Return the new ResourceID //------------------------------------------------------------- Test_Tell("res_id = " << res_id << "\n"); Check_Fpu(); return res_id; } Logical L4GaugeImage::MemoryStreamWrite( MemoryStream *mem_stream, NotationFile *gim_file ) { Test_Tell(" L4GaugeImage::MemoryStreamWrite(" << mem_stream << ", " << gim_file << ")\n" ); Check(mem_stream); Check(gim_file); int i; //------------------------------------------------------------- // 'result' is set to False if an error occurs. //------------------------------------------------------------- Logical result = True; //------------------------------------------------------------- // Write the vertices //------------------------------------------------------------- NameList *vertex_list = gim_file->MakeEntryList("vertices"); if (vertex_list == NULL) { DEBUG_STREAM << "No 'vertices' page in the .GIM file!" << std::endl; result = False; } else { Check(vertex_list); Register_Object(vertex_list); //------------------------------------------------------------- // Get the number of vertices //------------------------------------------------------------- int vertex_count = vertex_list->EntryCount(); Test_Tell("vertex_count = " << vertex_count << "\n"); if (vertex_count <= 0) { DEBUG_STREAM << "The 'vertices' page in the .GIM file has no entries!" <GetFirstEntry(); for (int i=0; iGetChar(), &point_3d); Test_Tell(" " << point_3d << "\n"); MemoryStream_Write(mem_stream, &point_3d); vertex_entry = vertex_entry->GetNextEntry(); } } //------------------------------------------------------------- // Delete the vertex list //------------------------------------------------------------- Check(vertex_list); Unregister_Object(vertex_list); delete vertex_list; } //------------------------------------------------------------- // Write the levels of detail //------------------------------------------------------------- if (result == True) { NameList *lod_namelist = gim_file->MakeEntryList("lods"); if (lod_namelist == NULL) { DEBUG_STREAM << "No 'lods' page in the .GIM file!" << std::endl; result = False; } else { Check(lod_namelist); Register_Object(lod_namelist); //------------------------------------------------------------- // Get the number of LOD's //------------------------------------------------------------- int lod_count = lod_namelist->EntryCount(); Test_Tell("lod_count = " << lod_count << "\n"); if (lod_count <= 0) { DEBUG_STREAM << "The 'lod' page in the .GIM file has no entries!" << std::endl; result = False; } else { //------------------------------------------------------------- // Write the number of LOD's to the stream //------------------------------------------------------------- MemoryStream_Write(mem_stream, &lod_count); //------------------------------------------------------------- // Write the LOD scales //------------------------------------------------------------- NameList::Entry *scale_entry; Scalar scale; const char *text; scale_entry = lod_namelist->GetFirstEntry(); for (i=0; iGetChar(); if (text == NULL) { DEBUG_STREAM << "Missing scale value!" << std::endl; result = False; break; } scale = (Scalar) atof(text); Test_Tell(" " << scale << "\n"); MemoryStream_Write(mem_stream, &scale); scale_entry = scale_entry->GetNextEntry(); } //------------------------------------------------------------- // Write the LOD lists //------------------------------------------------------------- scale_entry = lod_namelist->GetFirstEntry(); for (i=0; iGetName() ); if (result == False) { break; } scale_entry = scale_entry->GetNextEntry(); } } } //------------------------------------------------------------- // Delete the LOD list //------------------------------------------------------------- Check(lod_namelist); Unregister_Object(lod_namelist); delete lod_namelist; } Check_Fpu(); return result; } void L4GaugeImage::Draw( Scalar LOD_value, // smaller = more detail (1.0 = 'normal') Scalar scale_value, // metersPerPixel GraphicsView *graphics_view, int default_color, AffineMatrix &localToView, int boxed_color ) { Test_Tell( "L4GaugeImage::Draw(" << scale_value << ", " << graphics_view << ", " << default_color << ", " << localToView << ", " << boxed_color << ")\n" ); Check(this); Check(graphics_view); // localToView allowed to be NULL Check_Pointer(LODScales); Check_Pointer(LODList); # define VERTEX_ALLOTMENT 100 // HACK - I'm guessing this is big enough. Verify(vertexCount <= VERTEX_ALLOTMENT); static Point3D local_vertex_array[VERTEX_ALLOTMENT]; static Logical local_flag_array[VERTEX_ALLOTMENT]; int lod_index; if (localToView == NULL) { return; } //------------------------------------------------------------- // Find LOD index //------------------------------------------------------------- for(lod_index=0; lod_indexDraw( graphics_view, default_color, localToView, vertexArray, local_vertex_array, local_flag_array, scale_value, boxed_color ); } Check_Fpu(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Test Instance // Logical L4GaugeImage::TestInstance() const { return True; } //############################################################################ // L4GaugeImageList //############################################################################ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Construction and Destruction // L4GaugeImageList::L4GaugeImageList(MemoryStream *mem_stream) { Test_Tell("L4GaugeImageList::L4GaugeImageList\n"); Check_Pointer(this); Check(mem_stream); int i; //------------------------------------------------------------- // Read the number of primitives from the stream //------------------------------------------------------------- MemoryStream_Read(mem_stream, &primitiveCount); Verify(primitiveCount > 0); //------------------------------------------------------------- // Allocate the primitive list //------------------------------------------------------------- primitiveList = new L4GaugeImagePrimitive*[primitiveCount]; Check_Pointer(primitiveList); Register_Pointer(primitiveList); //------------------------------------------------------------- // Read the primitives //------------------------------------------------------------- for(i=0; iMakeEntryList(page_name); if (primitive_list == NULL) { DEBUG_STREAM << "Can't find the '" << page_name << "' page in the .GIM file!" << std::endl; result = False; } else { Check(primitive_list); Register_Object(primitive_list); //------------------------------------------------------------- // Get the number of primitives //------------------------------------------------------------- int primitive_count = primitive_list->EntryCount(); Test_Tell(" primitive_count = " << primitive_count << "\n"); if (primitive_count <= 0) { DEBUG_STREAM << "The '"<GetFirstEntry(); for (i=0; iGetName(), primitive_entry->GetChar() ); if (result == False) { break; } primitive_entry = primitive_entry->GetNextEntry(); } } //------------------------------------------------------------- // Delete the primitive list //------------------------------------------------------------- Check(primitive_list); Unregister_Object(primitive_list); delete primitive_list; } Check_Fpu(); return result; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Test Support // Logical L4GaugeImageList::TestInstance() const { return True; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void L4GaugeImageList::Draw( GraphicsView *graphics_view, int default_color, AffineMatrix &localToView, Point3D *untransformed_vertex_array, Point3D *transformed_vertex_array, Logical *transformed_flag_array, Scalar scale_factor, int boxed_color ) { Test_Tell( "L4GaugeImageList::Draw(" << graphics_view << ", " << default_color << ", " << localToView << ", " << untransformed_vertex_array << ", " << transformed_vertex_array << ", " << transformed_flag_array << ", " << scale_factor << ", " << boxed_color << ")\n" ); Check(this); Check(graphics_view); Check(&localToView); Check_Pointer(untransformed_vertex_array); Check_Pointer(transformed_vertex_array); Check_Pointer(transformed_flag_array); Check_Pointer(primitiveList); int i; L4GaugeImagePrimitive **array_pointer = primitiveList; if (boxed_color != 0) { //-------------------------------------------------------- // Initialize bounding box //-------------------------------------------------------- Rectangle2D bounds(9999,9999,-9999,-9999); //-------------------------------------------------------- // Draw primitives, collect bounding data //-------------------------------------------------------- for(i=0; iDraw( graphics_view, default_color, localToView, untransformed_vertex_array, transformed_vertex_array, transformed_flag_array, scale_factor, &bounds ); } //-------------------------------------------------------- // Draw the bounding box //-------------------------------------------------------- graphics_view->SetColor(boxed_color); graphics_view->MoveToAbsolute( bounds.bottomLeft.x-4, bounds.bottomLeft.y-4 ); graphics_view->DrawRectangleToAbsolute( bounds.topRight.x+4, bounds.topRight.y+4 ); } else { //-------------------------------------------------------- // Just draw it //-------------------------------------------------------- for(i=0; iDraw( graphics_view, default_color, localToView, untransformed_vertex_array, transformed_vertex_array, transformed_flag_array, scale_factor, NULL ); } } Check_Fpu(); } //############################################################################ // L4GaugeImagePrimitive //############################################################################ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Construction and Destruction // L4GaugeImagePrimitive::L4GaugeImagePrimitive(MemoryStream *mem_stream) { Test_Tell("L4GaugeImagePrimitive::L4GaugeImagePrimitive\n"); Check_Pointer(this); Check(mem_stream); int i, n; //-------------------------------------------------------------- // Read the primitive type ID, use the input stream accordingly //-------------------------------------------------------------- MemoryStream_Read(mem_stream, &n); type = (primitiveType) n; switch(type) { case primitiveVector: Test_Tell(" primitiveVector\n"); //-------------------------------------------------------- // Read the attribute and color //-------------------------------------------------------- MemoryStream_Read(mem_stream, &color); MemoryStream_Read(mem_stream, &attributes); Test_Tell(" color = " << color << "\n"); Test_Tell(" attributes = " << std::hex << attributes << std::dec << "\n"); //-------------------------------------------------------- // Read the vertex index count //-------------------------------------------------------- MemoryStream_Read(mem_stream, &data.vector.indexCount); Test_Tell(" indexCount = " << data.vector.indexCount << "\n"); Verify(data.vector.indexCount > 0); //-------------------------------------------------------- // Allocate the index table //-------------------------------------------------------- data.vector.indexList = new int[data.vector.indexCount]; Check_Pointer(data.vector.indexList); Register_Pointer(data.vector.indexList); //-------------------------------------------------------- // Read the indices //-------------------------------------------------------- for(i=0; i 0) int check_length = strlen(data)+1; # endif while(*scan != '\0') { Verify((scan-data) < check_length); //-------------------------------------------------------- // Skip white space //-------------------------------------------------------- while (isspace(*scan)) { ++scan; } //-------------------------------------------------------- // Parse non-space string //-------------------------------------------------------- if (*scan == 'v') { int n; //-------------------------------------------------------- // Convert to value, save in array //-------------------------------------------------------- ++scan; // ignore 'v' for(n=0; isdigit(*scan); ++scan) { n = (n*10) + (*scan - '0'); } Test_Tell(" " << n << "\n"); if (index_count < MAX_INDICES) { index[index_count++] = n; } } else if (*scan == 'a') { char buffer[64], *dest; //-------------------------------------------------------- // Collect the name //-------------------------------------------------------- for( i=0, dest=buffer; i<(sizeof(buffer)-1); ++i,++scan,++dest ) { if (isspace(*scan)) { break; } if (*scan == '\0') { break; } *dest = *scan; } *dest = '\0'; //-------------------------------------------------------- // Search for the name //-------------------------------------------------------- if ( GroupAttribute::Search( buffer, &color_value, &attribute_value ) == False ) { DEBUG_STREAM << "Couldn't find attribute group '" << buffer << "'!" << std::endl; } } } //-------------------------------------------------------- // Write the attributes //-------------------------------------------------------- Test_Tell(" color=" << color_value << "\n"); MemoryStream_Write(mem_stream, &color_value); Test_Tell(" attribute=" << attribute_value << "\n"); MemoryStream_Write(mem_stream, &attribute_value); //-------------------------------------------------------- // Write the vertex index count //-------------------------------------------------------- if (index_count == 0) { DEBUG_STREAM << "No vertex indices in primitive!" << std::endl; result = False; } else { Test_Tell(" index_count=" << index_count << "\n"); MemoryStream_Write(mem_stream, &index_count); //-------------------------------------------------------- // Write the indices //-------------------------------------------------------- for(i=0; i < index_count; ++i) { MemoryStream_Write(mem_stream, &index[i]); } } } else { DEBUG_STREAM << "Unsupported primitive ("<< type_name << ") in .GIM file!" << std::endl; result = False; } Check_Fpu(); return result; } //============================================================================ // TestInstance //============================================================================ Logical L4GaugeImagePrimitive::TestInstance() const { return True; } //============================================================================ // Draw //============================================================================ void L4GaugeImagePrimitive::Draw( GraphicsView *graphics_view, int default_color, AffineMatrix &localToView, Point3D *untransformed_vertex_array, Point3D *transformed_vertex_array, Logical *transformed_flag_array, Scalar scale_factor, Rectangle2D *bounds ) { Test_Tell( "L4GaugeImagePrimitive::Draw(" << graphics_view << ", " << default_color << ", " << localToView << ", " << untransformed_vertex_array << ", " << transformed_vertex_array << ", " << transformed_flag_array << ", " << scale_factor << ", " << bounds << ")\n" ); Check(this); Check(graphics_view); Check(&localToView); Check_Pointer(untransformed_vertex_array); Check_Pointer(transformed_vertex_array); Check_Pointer(transformed_flag_array); //----------------------------------------------- // Draw primitive //----------------------------------------------- switch(type) { case primitiveVector: if (data.vector.indexCount > 1) { //----------------------------------------------- // Set color //----------------------------------------------- if (color != 0) { default_color = color; } graphics_view->SetColor(default_color); int i, *index_pointer(data.vector.indexList), index; Point3D *dest; //----------------------------------------------- // Move to starting point //----------------------------------------------- index = *index_pointer++; dest = &transformed_vertex_array[index]; TransformVertex( localToView, untransformed_vertex_array[index], dest, transformed_flag_array[index], scale_factor, bounds ); Test_Tell("Start at " << index << "=" << *dest << "\n"); graphics_view->MoveToAbsolute((int)dest->x,(int)dest->z); //----------------------------------------------- // Draw subsequent lines //----------------------------------------------- for(i=data.vector.indexCount-1; i>0; --i) { index = *index_pointer++; dest = &transformed_vertex_array[index]; TransformVertex( localToView, untransformed_vertex_array[index], dest, transformed_flag_array[index], scale_factor, bounds ); Test_Tell("Draw to " << index << "=" << *dest << "\n"); graphics_view->DrawLineToAbsolute((int)(dest->x),(int)(dest->z)); } } break; default: Warn("L4GaugeImagePrimitive::Draw: Evil type_id!"); break; } Check_Fpu(); } void L4GaugeImagePrimitive::TransformVertex( AffineMatrix &local_to_view, Point3D &untransformed_vertex, Point3D *transformed_vertex, Logical &transformed_flag, Scalar scale_factor, Rectangle2D *bounds ) { Check(this); Check_Pointer(transformed_vertex); //----------------------------------------- // Transform only if not already done //----------------------------------------- if (! transformed_flag) { if (attributes & attributeUnscaled) { //----------------------------------------- // Unscaled: pre-multiply by scaling factor //----------------------------------------- Point3D temp; temp = untransformed_vertex; temp *= scale_factor; Check_Fpu(); transformed_vertex->Multiply( temp, local_to_view ); Check_Fpu(); } else { //----------------------------------------- // Normally scaled: transform the vertex //----------------------------------------- transformed_vertex->Multiply( untransformed_vertex, local_to_view ); Check_Fpu(); } //----------------------------------------- // Round, and fix 'y' sign //----------------------------------------- transformed_vertex->x += .5; transformed_vertex->z = -transformed_vertex->z + .5; //----------------------------------------------- // Set the 'transformed' flag //----------------------------------------------- transformed_flag = True; } //----------------------------------------------- // Accumulate bounds //----------------------------------------------- if (bounds != NULL) { if (transformed_vertex->x < bounds->bottomLeft.x) { bounds->bottomLeft.x = transformed_vertex->x; } if (transformed_vertex->x > bounds->topRight.x) { bounds->topRight.x = transformed_vertex->x; } if (transformed_vertex->z < bounds->bottomLeft.y) { bounds->bottomLeft.y = transformed_vertex->z; } if (transformed_vertex->z > bounds->topRight.y) { bounds->topRight.y = transformed_vertex->z; } } Check_Fpu(); }