//------------------------------------------------------------------------------ // gso_Shaper class -- // (C) Piero Giubilato 2009, Berkeley Lab -- //------------------------------------------------------------------------------ //______________________________________________________________________________ // {Trace} // [File name] "gso_Renderer.cpp" // [Author] "Piero Giubilato" // [Version] "0.1" // [Modified by] "Piero Giubilato" // [Last revision] "21 Jan 2009" // [Language] "C++" // [Compiler] "Visual C++ 9.x" // [Member of] "Cool SEAL" // [Project] "SEAL" // [Description] "Source for the gso_Shaper class" // [Key documentation] // "Visual C++ Reference Help" // "Root reference guide" // {Trace} //______________________________________________________________________________ // This class members build geometrical, semi 3D shapes and derives // the corresponding pxMap accordingly to the renderer settings // Standard component #include // Application component #include "global.h" #include "gso_Shaper.h" // ***************************************************************************** // ** SHAPEs ** // ***************************************************************************** //______________________________________________________________________________ void gso_Shaper::shape_Button(Float_t* map, UChar_t* mask, UInt_t width, UInt_t height, Float_t roundness, Float_t flatness) { // Creates a 3D tile dbg_Print("gso_Shaper::shape_Tile:(default)", DBG_LVL_FLOW); // Clears mask for (UInt_t i = 0; i < width * height; i++) { map[i] = 0; mask[i] = 0; } // Pivot drawing vars Float_t h = 0; UInt_t bR = (UInt_t)floor(roundness); Float_t bF = flatness; Float_t bB = 0; Float_t bR2 = pow((Float_t)(bR - 1), 2);; UChar_t mask_Def = 255; // Side Bevel for (UInt_t b = 0; b < bR; b++) { h = bB + sqrt(bR2 - pow((Float_t)b ,2)) * bF; for (UInt_t x = bR; x < width - bR; x++) { map[x + (bR - b - 1) * width] = h; map[x + (height - bR + b) * width] = h; if (h) { mask[x + (bR - b - 1) * width] = mask_Def; mask[x + (height - bR + b) * width] = mask_Def; } else { mask[x + (bR - b - 1) * width] = 0; mask[x + (height - bR + b) * width] = 0; } } for (UInt_t y = bR; y < height - bR; y++) { map[(bR - b - 1) + y * width] = h; map[width - bR + b + y * width] = h; if (h) { mask[(bR - b - 1) + y * width] = mask_Def; mask[width - bR + b + y * width] = mask_Def; } else { mask[(bR - b - 1) + y * width] = 0; mask[width - bR + b + y * width] = 0; } } } // Corner bevel for (UInt_t y = 0; y < bR; y++) { for (UInt_t x = 0; x < bR; x++) { // Compute Float_t r2 = pow((Float_t)(bR - 1 - x), 2) + pow((Float_t)(bR - 1 - y), 2); (r2 <= bR2) ? h = bB + sqrt(bR2 - r2) * bF : h = bB; // Map map[x + y * width] = h; map[width - x - 1 + y * width] = h; map[x + (height - 1 - y) * width] = h; map[width - x - 1 + (height - 1 - y) * width] = h; // Mask if (h) { mask[x + y * width] = mask_Def; mask[width - x - 1 + y * width] = mask_Def; mask[x + (height - 1 - y) * width] = mask_Def; mask[width - x - 1 + (height - 1 - y) * width] = mask_Def; } else { mask[x + y * width] = 0; mask[width - x - 1 + y * width] = 0; mask[x + (height - 1 - y) * width] = 0; mask[width - x - 1 + (height - 1 - y) * width] = 0; } } } // Inner face for (UInt_t y = bR; y < height - bR; y++) { for (UInt_t x = bR; x < width - bR; x++) { map[x + y * width] = bB + (bR - 1) * bF; mask[x + y * width] = mask_Def; } } } //______________________________________________________________________________ void gso_Shaper::shape_Dome(Float_t* map, UChar_t* mask, UInt_t width, UInt_t height, Float_t radius, Float_t flatness) { // Creates an exponential funnel dbg_Print("gso_Shaper::shape_Dome:(default)", DBG_LVL_FLOW); // Pivot vars UInt_t Idx; Double_t cX, cY; Double_t r2, R2; UChar_t mask_Def = 255; // Presets cX = width / 2; cY = height / 2; R2 = pow(radius, 2); // Dome for (UInt_t y = 0; y < height; y++) { for (UInt_t x = 0; x < width; x++) { // Point Idx = x + y * width; r2 = pow(cX - (Double_t)x, 2) + pow(cY - (Double_t)y, 2); // Dome if (r2 <= R2) { map[Idx] = flatness * (Float_t)sqrt(R2 - r2); mask[Idx] = mask_Def; } else { map[Idx] = 0; mask[Idx] = 0; } } } } //______________________________________________________________________________ void gso_Shaper::shape_Funnel(Float_t* map, UChar_t* mask, UInt_t width, UInt_t height, Float_t radius, Float_t flatness) { // Creates an exponential funnel dbg_Print("gso_Shaper::shape_Funnel:(default)", DBG_LVL_FLOW); // Pivot vars UInt_t Idx; Double_t cX, cY; Double_t r2, R2; UChar_t mask_Def = 255; // Presets cX = width / 2; cY = height / 2; R2 = radius; // pow(radius, 2); // Dome for (UInt_t y = 0; y < height; y++) { for (UInt_t x = 0; x < width; x++) { // Point Idx = x + y * width; r2 = sqrt(pow(cX - (Double_t)x, 2) + pow(cY - (Double_t)y, 2)); // Dome if (r2 <= R2) { //map[Idx] = (Float_t)(-flatness * (R2 - r2)); map[Idx] = (Float_t)(-flatness * pow(R2 - r2, 2)) / 10; mask[Idx] = mask_Def; } else { map[Idx] = 0; mask[Idx] = 0; } } } } //______________________________________________________________________________ void gso_Shaper::shape_Render(UChar_t* col_Map, Float_t* shape_Map, UChar_t* mask, UInt_t width, UInt_t height, gso_Material* mat, UInt_t backColor) { // Renders a shape map dbg_Print("gso_Shaper::shape_Render:(default)", DBG_LVL_FLOW); // Sets the renderer material properties gso_Renderer::m_Set(mat->k_Amb, mat->k_Diff, mat->k_Spec, mat->k_Shine); // Generate the lightmap Float_t* light_Map = new Float_t[width * height]; gso_Renderer::light_Map(light_Map, shape_Map, width, height); // Colors compose UChar_t colF[3] = {mat->k_Color & 0xFF, (mat->k_Color >> 8) & 0xFF, (mat->k_Color >> 16) & 0xFF}; UChar_t colB[3] = {backColor & 0xFF, (backColor >> 8) & 0xFF, (backColor >> 16) & 0xFF}; // Creates the color map UInt_t Idx = 0; UInt_t px_Col; for (UInt_t y = 0; y < height; y++) { for (UInt_t x = 0; x < width; x++) { // Index Idx = x + y * width; // For each color channel for (UInt_t col = 0; col < 3; col++) { px_Col = (UInt_t) (light_Map[Idx] * colF[col] * mask[Idx] + colB[col] * (255 - mask[Idx])) / 255; if (px_Col < 0) px_Col = 0; if (px_Col > 255) px_Col = 255; col_Map[Idx * 4 + col] = (UChar_t)px_Col; } } } // Delete the light map delete light_Map; } //______________________________________________________________________________ void gso_Shaper::shape_scale_Z(Float_t* map, UInt_t width, UInt_t height, Float_t scale) { // Call the appropriate ss function dbg_Print("gso_Shaper::shape_scale_Z:(source = target)", DBG_LVL_FLOW); shape_ss_Z(map, map, width, height, scale, 0); } //______________________________________________________________________________ void gso_Shaper::shape_scale_Z(Float_t* target_Map, Float_t* source_Map, UInt_t width, UInt_t height, Float_t scale) { // Call the appropriate ss function dbg_Print("gso_Shaper::shape_scale_Z:(source != target)", DBG_LVL_FLOW); shape_ss_Z(target_Map, source_Map, width, height, scale, 0); } //______________________________________________________________________________ void gso_Shaper::shape_shift_Z(Float_t* map, UInt_t width, UInt_t height, Float_t shift) { // Call the appropriate ss function dbg_Print("gso_Shaper::shape_shift_Z:(source = target)", DBG_LVL_FLOW); shape_ss_Z(map, map, width, height, 1, shift); } //______________________________________________________________________________ void gso_Shaper::shape_shift_Z(Float_t* target_Map, Float_t* source_Map, UInt_t width, UInt_t height, Float_t shift) { // Call the appropriate ss function dbg_Print("gso_Shaper::shape_shift_Z:(source != target)", DBG_LVL_FLOW); shape_ss_Z(target_Map, source_Map, width, height, 1, shift); } //______________________________________________________________________________ void gso_Shaper::shape_ss_Z(Float_t* target_Map, Float_t* source_Map, UInt_t width, UInt_t height, Float_t scale, Float_t shift) { // Scales a map in the Z axis dbg_Print("gso_Shaper::shape_ss_Z:(source != target)", DBG_LVL_FLOW); // Scales for (UInt_t y = 0; y < height; y++) { for (UInt_t x = 0; x < width; x++) { target_Map[x + y * width] = source_Map[x + y * width] * scale + shift; } } } // ***************************************************************************** // ** MASKs ** // ***************************************************************************** //______________________________________________________________________________ void gso_Shaper::mask_Invert(UChar_t* mask, UInt_t width, UInt_t height) { // Calls dbg_Print("gso_Shaper::mask_Invert:(source = target)", DBG_LVL_FLOW); mask_Invert(mask, mask, width, height); } //______________________________________________________________________________ void gso_Shaper::mask_Invert(UChar_t* target_Mask, UChar_t* source_Mask, UInt_t width, UInt_t height) { // Scales a map in the Z axis dbg_Print("gso_Shaper::mask_Invert:(source != target)", DBG_LVL_FLOW); // Invert for (UInt_t x = 0; x < width; x++) { for (UInt_t y = 0; y < height; y++) { target_Mask[x + y * width] = 255 - source_Mask[x + y * width]; } } } //______________________________________________________________________________ void gso_Shaper::mask_Grow(UChar_t* mask, UInt_t width, UInt_t height) { // Grows the mask by one pixel dbg_Print("gso_Shaper::mask_Grow:(default)", DBG_LVL_FLOW); UChar_t* newMask = new UChar_t[width * height]; // Grows the mask by one pixel int aStart, bStart, aStop, bStop; for (UInt_t y = 0; y < height; y++) { // Set b limits (y == 0) ? bStart = 0 : bStart = -1; (y == (height - 1)) ? bStop = 1 : bStop = 2; for (UInt_t x = 0; x < width; x++) { // Set a limits (x == 0) ? aStart = 0 : aStart = -1; (x == (width - 1)) ? aStop = 1 : aStop = 2; // Check neighborhood pixels newMask[x + y * width] = 0; for (int b = -1; b < 2; b++) { for (int a = aStart; a < aStop; a++) { if (mask[x + a + (y + b) * width]) { newMask[x + y * width] = mask[x + a + (y + b) * width]; } } } } } // Move the new mask for (UInt_t i = 0; i < width * height; i++) mask[i] = newMask[i]; delete newMask; } // ***************************************************************************** // ** MAPSs ** // ***************************************************************************** //______________________________________________________________________________ void gso_Shaper::map_Pixel(UInt_t* pixel_Color, UInt_t color) { // Creates 1 pixel with the color of the rendered desk dbg_Print("gso_Shaper::map_Pixel:(UInt)", DBG_LVL_FLOW); // Set and compute dummy pixel UChar_t pixel[4]; map_Pixel(pixel, color); // Sum up the colors! *pixel_Color = pixel[0] + (pixel[1] << 8) + (pixel[2] << 16); } //______________________________________________________________________________ void gso_Shaper::map_Pixel(UChar_t* pixel, UInt_t color) { // Creates 1 pixel with the color of the rendered desk dbg_Print("gso_Shaper::map_Pixel:(UChar)", DBG_LVL_FLOW); // Consider the color under the current illumination Float_t ref_Square[4] = {0, 0, 0, 0}; Float_t light_Map[4] = {0, 0, 0, 0}; // Consider the color under the default illumination gso_Renderer::m_Set(&gso_Renderer::k_Material); gso_Renderer::l_Strenght(gso_Renderer::kl_Default); gso_Renderer::light_Map(light_Map, ref_Square, 2, 2); // Computes the resulting surface color pixel[0] = (UInt_t)(light_Map[0] * (color & 0xFF)); pixel[1] = ((UChar_t)(light_Map[0] * ((color >> 8) & 0xFF))); pixel[2] = ((UChar_t)(light_Map[0] * ((color >> 16) & 0xFF))); } //______________________________________________________________________________ void gso_Shaper::map_Flat(UChar_t* map, UInt_t width, UInt_t height, UInt_t color) { // Creates 1 pixel with the color of the rendered desk dbg_Print("gso_Shaper::map_Flat:(default)", DBG_LVL_FLOW); // Derives RGB UChar_t B = color & 0xFF; UChar_t G = (color >> 8) & 0xFF; UChar_t R = (color >> 16) & 0xFF; // Fill the map! for (UInt_t i = 0 ; i < width * height * 4; i+=4) { map[i] = B; map[i + 1] = G; map[i + 2] = R; } } //______________________________________________________________________________ void gso_Shaper::map_Copy(UChar_t* target_Map, UChar_t* source_Map, UInt_t width, UInt_t height) { // Sum two color (char array * 4) maps dbg_Print("gso_Shaper::map_Copy:(default)", DBG_LVL_FLOW); // Copy! for (UInt_t i = 0; i < width * height * 4; i++) target_Map[i] = source_Map[i]; } //______________________________________________________________________________ void gso_Shaper::map_Sum(UChar_t* target_Map, UChar_t* target_Mask, UChar_t* sum_Map, UChar_t* sum_Mask, UInt_t width, UInt_t height, Float_t scale) { // Sum two color (char array * 4) maps dbg_Print("gso_Shaper::map_Sum:(source = target)", DBG_LVL_FLOW); map_Sum(target_Map, target_Map, target_Mask, sum_Map, sum_Mask, width, height, scale); } //______________________________________________________________________________ void gso_Shaper::map_Sum(UChar_t* target_Map, UChar_t* sum_MapA, UChar_t* sum_MaskA, UChar_t* sum_MapB, UChar_t* sum_MaskB, UInt_t width, UInt_t height, Float_t scale) { // Sum two color (char array * 4) maps dbg_Print("gso_Shaper::map_Sum:(source != target)", DBG_LVL_FLOW); // Summ accordingly to the masks UInt_t Idx = 0, Idx4 = 0; for (UInt_t y = 0; y < height; y++) { for (UInt_t x = 0; x < width; x++) { // Different indexes for the map and the mask Idx = x + y * width; Idx4 = Idx * 4; // Sum over the three color channel target_Map[Idx4] = (UChar_t)(scale * ((sum_MapA[Idx4] * sum_MaskA[Idx] + sum_MapB[Idx4] * sum_MaskB[Idx]) / 255)); target_Map[Idx4 + 1] = (UChar_t)(scale * ((sum_MapA[Idx4 + 1] * sum_MaskA[Idx] + sum_MapB[Idx4 + 1] * sum_MaskB[Idx]) / 255)); target_Map[Idx4 + 2] = (UChar_t)(scale * ((sum_MapA[Idx4 + 2] * sum_MaskA[Idx] + sum_MapB[Idx4 + 2] * sum_MaskB[Idx]) / 255)); // No alpha channel operation at the moment //target_Map[Idx4] = (UChar_t)(scale * (sum_MapA[Idx4] * sum_MaskA[Idx] + sum_MapB[Idx4] * sum_MaskB[Idx])); } } }