//------------------------------------------------------------------------------ // gso_Shaper class -- // (C) Piero Giubilato 2008-2010, Berkeley Lab -- //------------------------------------------------------------------------------ //______________________________________________________________________________ // {Trace} // [File name] "gso_Renderer.cpp" // [Author] "Piero Giubilato" // [Version] "1.1" // [Modified by] "Piero Giubilato" // [Last revision] "07 Apr 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, bool extra) { // ******************************************************************** // *** WARNING: the array dimension MUST be [width + 1][height + 1] *** // ******************************************************************** // Creates a 3D button shape dbg_Print("gso_Shaper::shape_Tile:(default)", DBG_LVL_FLOW); // Uses real dimensions UInt_t srf_W = width + 1; UInt_t srf_H = height + 1; // Clears map & 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 < srf_W - bR; x++) { map[x + (bR - b - 1) * srf_W] = h; map[x + (srf_H - bR + b) * srf_W] = h; //if (x < width && y < height) { 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 < srf_H - bR; y++) { map[(bR - b - 1) + y * srf_W] = h; map[srf_W - bR + b + y * srf_W] = h; //if (x < width && y < height) { 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 * srf_W] = h; map[srf_W - x - 1 + y * srf_W] = h; map[x + (srf_H - 1 - y) * srf_W] = h; map[srf_W - x - 1 + (srf_H - 1 - y) * srf_W] = h; // Mask //if (x < width && y < height) { 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 < srf_H - bR; y++) { for (UInt_t x = bR; x < srf_W - bR; x++) { map[x + y * srf_W] = bB + (bR - 1) * bF; if (x < width && y < height) mask[x + y * width] = mask_Def; } } // Perform a general cylindrica (hor dir) smoot if (extra) { for (UInt_t y = 0; y < srf_H; y++) { for (UInt_t x = 0; x < srf_W; x++) { map[x + y * srf_W] *= (Float_t)0.8 * (pow(float(2 * ((float)y / srf_H) - 1), 2)); } } } } //______________________________________________________________________________ void gso_Shaper::shape_Dome(Float_t* map, UChar_t* mask, UInt_t width, UInt_t height, Float_t radius, Float_t flatness) { // ******************************************************************** // *** WARNING: the array dimension MUST be [width + 1][height + 1] *** // ******************************************************************** // Creates an exponential funnel dbg_Print("gso_Shaper::shape_Dome:(default)", DBG_LVL_FLOW); // Uses real dimensions UInt_t srf_W = width + 1; UInt_t srf_H = height + 1; // Pivot vars Double_t cX, cY; Double_t r2, R2; UChar_t mask_Def = 255; // Presets cX = srf_W / 2; cY = srf_H / 2; R2 = pow(radius, 2); // Dome for (UInt_t y = 0; y < srf_H; y++) { for (UInt_t x = 0; x < srf_W; x++) { // Point r2 = pow(cX - (Double_t)x, 2) + pow(cY - (Double_t)y, 2); // Dome if (r2 < R2) { map[x + y * srf_W] = flatness * (Float_t)sqrt(R2 - r2); if (x < width && y < height) mask[x + y * width] = mask_Def; } else { map[x + y * srf_W] = 0; if (x < width && y < height) mask[x + y * width] = 0; } } } } //______________________________________________________________________________ void gso_Shaper::shape_Funnel(Float_t* map, UChar_t* mask, UInt_t width, UInt_t height, Float_t radius, Float_t flatness) { // ******************************************************************** // *** WARNING: the array dimension MUST be [width + 1][height + 1] *** // ******************************************************************** // Creates an exponential funnel dbg_Print("gso_Shaper::shape_Funnel:(default)", DBG_LVL_FLOW); // Uses real dimensions UInt_t srf_W = width + 1; UInt_t srf_H = height + 1; // Pivot vars Double_t r2; UChar_t mask_Def = 255; // Presets Double_t cX = srf_W / 2; Double_t cY = srf_H / 2; Double_t R2 = radius; // pow(radius, 2); // Dome for (UInt_t y = 0; y < srf_H; y++) { for (UInt_t x = 0; x < srf_W; x++) { // Point r2 = sqrt(pow(cX - (Double_t)x, 2) + pow(cY - (Double_t)y, 2)); // Funnel if (r2 <= R2) { map[srf_W * y + x] = (Float_t)(-flatness * pow(R2 - r2, 2)) / 10; if (x < width && y < height) mask[width * y + x] = mask_Def; } else { map[srf_W * y + x] = 0; if (x < width && y < height) mask[width * y + x] = 0; } } } } //______________________________________________________________________________ void gso_Shaper::shape_Ring(Float_t* map, UChar_t* mask, UInt_t width, UInt_t height, Float_t rIn, Float_t rOut, Float_t flatness, bool fill) { // ******************************************************************** // *** WARNING: the array dimension MUST be [width + 1][height + 1] *** // ******************************************************************** // Creates a ring notch. The fill parameter set if the associated mask will // have all the pixels inside rOut checked, or just the pixel between // rIn and rOut. dbg_Print("gso_Shaper::shape_Ring:(default)", DBG_LVL_FLOW); // Uses real dimensions UInt_t srf_W = width + 1; UInt_t srf_H = height + 1; // Presets Double_t r; Double_t cX = srf_W / 2; Double_t cY = srf_H / 2; Double_t rIn2 = pow(rIn, 2); Double_t rOut2 = pow(rOut, 2); Double_t d2 = pow((rOut - rIn) / 2, 2); Double_t dC = (rOut + rIn) / 2; UChar_t mask_Def = 255; // Notch ring for (UInt_t y = 0; y < srf_H; y++) { for (UInt_t x = 0; x < srf_W; x++) { // Radius r = sqrt(pow(cX - (Double_t)x, 2) + pow(cY - (Double_t)y, 2)); // Circular notch if (r >= rIn && r <= rOut) { map[srf_W * y + x] = (Float_t) sqrt(d2 - pow(r - dC ,2)) * flatness; } else { map[srf_W * y + x] = 0; } // Inner mask (notch + inner radius) if (x < width && y < height) { if (fill) (r <= rOut) ? mask[width * y + x] = mask_Def : mask[width * y + x] = 0; else (r <= rOut && r >= rIn) ? mask[width * y + x] = mask_Def : mask[width * y + x] = 0; } } } } //______________________________________________________________________________ void gso_Shaper::shape_Notch(Float_t* map, UChar_t* mask, UInt_t width, UInt_t height, UInt_t direction, Float_t rIn, Float_t rOut, Float_t flatness, bool fill) { // ******************************************************************** // *** WARNING: the array dimension MUST be [width + 1][height + 1] *** // ******************************************************************** // Creates a linear notch // 0 = Horizontal left // 1 = Vertical top // 2 = Horizontal right // 3 = Vertical bottom dbg_Print("gso_Shaper::shape_Notch:(default)", DBG_LVL_FLOW); // Uses real dimensions UInt_t srf_W = width + 1; UInt_t srf_H = height + 1; // Presets Double_t cX = srf_W / 2; Double_t cY = srf_H / 2; Double_t rIn2 = pow(rIn, 2); Double_t rOut2 = pow(rOut, 2); Double_t d2 = pow((rOut - rIn) / 2, 2); Double_t dC = (rOut + rIn) / 2; UChar_t mask_Def = 255; // Linear notch for (UInt_t y = 0; y < srf_H; y++) { for (UInt_t x = 0; x < srf_W; x++) { // Surface map switch (direction) { case 0: (x >= rIn && x <= rOut) ? map[srf_W * y + x] = (Float_t) sqrt(d2 - pow(x - dC ,2)) * flatness: map[srf_W * y + x] = 0; break; case 1: (y >= rIn && y <= rOut) ? map[srf_W * y + x] = (Float_t) sqrt(d2 - pow(y - dC ,2)) * flatness: map[srf_W * y + x] = 0; break; case 2: (x >= rIn && x <= rOut) ? map[srf_W * y + x] = (Float_t) sqrt(d2 - pow(x - dC ,2)) * flatness: map[srf_W * y + x] = 0; break; case 3: (y >= rIn && y <= rOut) ? map[srf_W * y + x] = (Float_t) sqrt(d2 - pow(y - dC ,2)) * flatness: map[srf_W * y + x] = 0; break; } // Mask if (x < width && y < height) { if (fill) { switch (direction) { case 0: (x > rIn) ? mask[width * y + x] = mask_Def : mask[width * y + x] = 0; break; case 1: (y < rOut) ? mask[width * y + x] = mask_Def : mask[width * y + x] = 0; break; case 2: (x < rOut) ? mask[width * y + x] = mask_Def : mask[width * y + x] = 0; break; case 3: (y > rIn) ? mask[width * y + x] = mask_Def : mask[width * y + x] = 0; break; } } else { switch (direction % 2) { case 0: (x > rIn && x < rOut) ? mask[width * y + x] = mask_Def : mask[width * y + x] = 0; break; case 1: (y > rIn && y < rOut) ? mask[width * y + x] = mask_Def : mask[width * y + x] = 0; break; } } } } } } //______________________________________________________________________________ void gso_Shaper::shape_Exp(Float_t* map, UChar_t* mask, UInt_t width, UInt_t height, UInt_t direction, Float_t flatness) { // ******************************************************************** // *** WARNING: the array dimension MUST be [width + 1][height + 1] *** // ******************************************************************** // Creates an exponential rampe, where direction is: // 0 = Horizontal left // 1 = Vertical top // 2 = Horizontal right // 3 = Vertical bottom dbg_Print("gso_Shaper::shape_Exp:(default)", DBG_LVL_FLOW); // Uses real dimensions UInt_t srf_W = width + 1; UInt_t srf_H = height + 1; Float_t srf_W2 = (Float_t)pow((Double_t)srf_W ,2); Float_t srf_H2 = (Float_t)pow((Double_t)srf_H ,2); // Pivot vars UChar_t mask_Def = 255; // Exp ramp for (UInt_t y = 0; y < srf_H; y++) { for (UInt_t x = 0; x < srf_W; x++) { // Map (pow) switch (direction) { case 0: map[srf_W * y + x] = -flatness * pow((float)x, 2) / 10; break; case 1: map[srf_W * y + x] = -flatness * pow((float)(srf_H - y - 1), 2) / 10; break; case 2: map[srf_W * y + x] = -flatness * pow((float)(srf_W - x - 1), 2) / 10; break; case 3: map[srf_W * y + x] = -flatness * pow((float)y, 2) / 10; break; } // Mask ramp if (x < width && y < height) mask[width * y + x] = mask_Def; } } } //______________________________________________________________________________ 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) { // ******************************************************************** // *** WARNING: the array dimension MUST be [width + 1][height + 1] *** // ******************************************************************** // 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 and shift a map in the Z axis dbg_Print("gso_Shaper::shape_ss_Z:(source != target)", DBG_LVL_FLOW); // Uses real dimensions width++; height++; // 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); // Pivot mask 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[9] = {0, 0, 0, 0, 0, 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 a flat map with the given color 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) { // Copy 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_Copy(UChar_t* t_Map, UInt_t t_Width, UInt_t t_Height, UInt_t t_Left, UInt_t t_Top, UChar_t* s_Map, UInt_t s_Width, UInt_t s_Height) { // Copy two color (char array * 4) maps, allowing for relative shifting //dbg_Print("gso_Shaper::map_Copy:(shifted)", DBG_LVL_FLOW); // Copy! UInt_t sL, tL; for (UInt_t y = 0; y < s_Height; y++) { sL = y * s_Width * 4; tL = (t_Left + (y + t_Top) * t_Width) * 4; for (UInt_t x = 0; x < s_Width * 4; x++) { t_Map[tL + x] = s_Map[sL + x]; } } } //Gli Dei, se sono giusti nella loro ingiustizia, //ci conservino i sogni anche quando sono impossibili. //Come il mare che prevede una tempesta, //un pigro dolore e un'inquietudine fanno di me //il mormorio di un incalzante stormo. //______________________________________________________________________________ void gso_Shaper::map_From(UChar_t* t_Map, UInt_t t_Width, UInt_t t_Height, UChar_t* s_Map, UInt_t s_Width, UInt_t s_Height, UInt_t s_Left, UInt_t s_Top) { // Creates a map from an area of another map dbg_Print("gso_Shaper::map_From:()", DBG_LVL_FLOW); // Copy! UInt_t sL, tL; for (UInt_t y = 0; y < t_Height; y++) { tL = y * t_Width * 4; sL = (s_Left + (s_Top + y) * s_Width) * 4; for (UInt_t x = 0; x < t_Width * 4; x++) { t_Map[tL + x] = s_Map[sL + x]; } } } //______________________________________________________________________________ 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])); } } }