Metric CalcRandomMetric (CCodeChain &CC, ICCItem *pItem) // CalcRandomMetric // // Parses an item to generate a Metric. The item may have one of the following // formats: // // integer // We treat as a distance in light-seconds. // // ('gaussian min center max) // We return a random distance between min and max with center as the // average, using a Gaussian random distribution. All values are expressed // in light-seconds, but we can return random numbers anywhere in between. { if (pItem == NULL || pItem->IsNil()) return 0.0; else if (pItem->IsList()) { if (pItem->GetCount() >= 4 && strEquals(pItem->GetElement(0)->GetStringValue(), FIELD_GAUSSIAN)) { // Get the parameters double rLow = pItem->GetElement(1)->GetIntegerValue(); double rMid = pItem->GetElement(2)->GetIntegerValue(); double rHigh = pItem->GetElement(3)->GetIntegerValue(); if (rLow >= rMid || rLow >= rHigh || rMid >= rHigh) return 0.0; // Compute some ranges double rHighRange = rHigh - rMid; double rLowRange = rMid - rLow; // Generate a gaussian, but clip out after 3 standard deviations double rMaxStdDev = 3.0; double rValue; do { rValue = mathRandomGaussian(); } while (rValue > rMaxStdDev || rValue < -rMaxStdDev); rValue = rValue / rMaxStdDev; // Scale to proper value if (rValue >= 0.0) return (rMid + rValue * rHighRange) * LIGHT_SECOND; else return (rMid + rValue * rLowRange) * LIGHT_SECOND; } else return 0.0; } else return (pItem->GetIntegerValue() * LIGHT_SECOND); }
DWORD CCrewPsyche::GenerateNormalLevel (void) // GenerateNormalLevel // // Generates a random level that clusters around neutral. { double rValue = SCrewMetrics::NEUTRAL_LEVEL + (mathRandomGaussian() * (SCrewMetrics::NEUTRAL_HIGH_LEVEL - SCrewMetrics::NEUTRAL_LOW_LEVEL)); if (rValue <= (double)SCrewMetrics::MIN_LEVEL) return 0; else if (rValue >= (double)SCrewMetrics::MAX_LEVEL) return SCrewMetrics::MAX_LEVEL; else return (DWORD)rValue; }
void CRayEffectPainter::CalcIntermediates (void) // CalcIntermediates // // Calculate intermediate values used for painting. { int i, v, w; if (!m_bInitialized) { enum EColorTypes { colorNone, colorGlow, }; enum EOpacityTypes { opacityNone, opacityGlow, opacityGrainy, opacityTaperedGlow, }; enum EWidthAdjTypes { widthAdjNone, widthAdjBlob, widthAdjDiamond, widthAdjJagged, widthAdjOval, widthAdjTapered, widthAdjCone, }; EColorTypes iColorTypes = colorNone; EOpacityTypes iOpacityTypes = opacityNone; EWidthAdjTypes iWidthAdjType = widthAdjNone; EWidthAdjTypes iReshape = widthAdjNone; EOpacityTypes iTexture = opacityNone; m_iWidthCount = m_iWidth; m_iLengthCount = 2 * m_iLength; // Every combination requires a slightly different set up switch (m_iShape) { case shapeCone: switch (m_iStyle) { case styleBlob: iColorTypes = colorGlow; iOpacityTypes = opacityTaperedGlow; iWidthAdjType = widthAdjBlob; iReshape = widthAdjCone; break; case styleGlow: iColorTypes = colorGlow; iOpacityTypes = opacityTaperedGlow; iWidthAdjType = widthAdjCone; break; case styleGrainy: iColorTypes = colorGlow; iOpacityTypes = opacityTaperedGlow; iWidthAdjType = widthAdjCone; iTexture = opacityGrainy; break; case styleJagged: iColorTypes = colorGlow; iOpacityTypes = opacityTaperedGlow; iWidthAdjType = widthAdjJagged; iReshape = widthAdjCone; break; } break; case shapeDiamond: switch (m_iStyle) { case styleBlob: iColorTypes = colorGlow; iOpacityTypes = opacityTaperedGlow; iWidthAdjType = widthAdjBlob; iReshape = widthAdjDiamond; break; case styleGlow: iColorTypes = colorGlow; iOpacityTypes = opacityTaperedGlow; iWidthAdjType = widthAdjDiamond; break; case styleGrainy: iColorTypes = colorGlow; iOpacityTypes = opacityTaperedGlow; iWidthAdjType = widthAdjDiamond; iTexture = opacityGrainy; break; case styleJagged: iColorTypes = colorGlow; iOpacityTypes = opacityTaperedGlow; iWidthAdjType = widthAdjJagged; iReshape = widthAdjDiamond; break; } break; case shapeOval: switch (m_iStyle) { case styleBlob: iColorTypes = colorGlow; iOpacityTypes = opacityTaperedGlow; iWidthAdjType = widthAdjBlob; iReshape = widthAdjOval; break; case styleGlow: iColorTypes = colorGlow; iOpacityTypes = opacityTaperedGlow; iWidthAdjType = widthAdjOval; break; case styleGrainy: iColorTypes = colorGlow; iOpacityTypes = opacityTaperedGlow; iWidthAdjType = widthAdjOval; iTexture = opacityGrainy; break; case styleJagged: iColorTypes = colorGlow; iOpacityTypes = opacityTaperedGlow; iWidthAdjType = widthAdjJagged; iReshape = widthAdjOval; break; } break; case shapeStraight: switch (m_iStyle) { case styleBlob: iColorTypes = colorGlow; iOpacityTypes = opacityGlow; iWidthAdjType = widthAdjBlob; break; case styleGlow: iColorTypes = colorGlow; iOpacityTypes = opacityGlow; break; case styleGrainy: iColorTypes = colorGlow; iOpacityTypes = opacityGlow; iTexture = opacityGrainy; break; case styleJagged: iColorTypes = colorGlow; iOpacityTypes = opacityGlow; iWidthAdjType = widthAdjJagged; break; } break; case shapeTapered: switch (m_iStyle) { case styleBlob: iColorTypes = colorGlow; iOpacityTypes = opacityTaperedGlow; iWidthAdjType = widthAdjBlob; iReshape = widthAdjTapered; break; case styleGlow: iColorTypes = colorGlow; iOpacityTypes = opacityTaperedGlow; iWidthAdjType = widthAdjTapered; break; case styleGrainy: iColorTypes = colorGlow; iOpacityTypes = opacityTaperedGlow; iWidthAdjType = widthAdjTapered; iTexture = opacityGrainy; break; case styleJagged: iColorTypes = colorGlow; iOpacityTypes = opacityTaperedGlow; iWidthAdjType = widthAdjJagged; iReshape = widthAdjTapered; break; } break; } // Full color map switch (iColorTypes) { case colorGlow: { m_ColorMap.InsertEmpty(1); m_ColorMap[0].InsertEmpty(m_iWidthCount); // The center blends towards white WORD wCenter = CG16bitImage::BlendPixel(m_wPrimaryColor, CG16bitImage::RGBValue(255, 255, 255), (DWORD)(255.0 * Min(50, m_iIntensity) / 50.0)); int iBrightPoint = (int)(BRIGHT_FACTOR * m_iWidthCount * m_iIntensity); for (i = 0; i < iBrightPoint; i++) m_ColorMap[0][i] = wCenter; // The rest fades (linearly) from primary color to secondary color Metric rFadeInc = (m_iWidthCount > 0 ? (1.0 / (m_iWidthCount - iBrightPoint)) : 0.0); Metric rFade = 1.0; for (i = iBrightPoint; i < m_iWidthCount; i++, rFade -= rFadeInc) m_ColorMap[0][i] = CG16bitImage::BlendPixel(m_wSecondaryColor, m_wPrimaryColor, (DWORD)(255.0 * rFade)); break; } } // Full opacity switch (iOpacityTypes) { case opacityGlow: { m_OpacityMap.InsertEmpty(1); m_OpacityMap[0].InsertEmpty(m_iWidthCount); // From center to peak we have solid opacity int iPeakPoint = (int)(SOLID_FACTOR * m_iIntensity * m_iWidthCount); for (i = 0; i < iPeakPoint; i++) m_OpacityMap[0][i] = 255; // We decay exponentially to edge Metric rGlowLevel = MIN_GLOW_LEVEL + (m_iIntensity * GLOW_FACTOR); Metric rGlowInc = (m_iWidthCount > 0 ? (1.0 / (m_iWidthCount - iPeakPoint)) : 0.0); Metric rGlow = 1.0; for (i = iPeakPoint; i < m_iWidthCount; i++, rGlow -= rGlowInc) m_OpacityMap[0][i] = (int)(255.0 * rGlowLevel * rGlow * rGlow); break; } case opacityTaperedGlow: { m_OpacityMap.InsertEmpty(m_iLengthCount); for (i = 0; i < m_iLengthCount; i++) m_OpacityMap[i].InsertEmpty(m_iWidthCount); // From center to peak we have solid opacity int iPeakPoint = (int)(SOLID_FACTOR * m_iIntensity * m_iWidthCount); // After the 1/3 point start fading out (linearly) int iFadePoint = m_iLengthCount / TAPER_FRACTION; Metric rTaperInc = (m_iLengthCount > 0 ? (1.0 / (m_iLengthCount - iFadePoint)) : 0.0); // From center to peak we have solid opacity plus taper for (w = 0; w < iPeakPoint; w++) { for (v = 0; v < iFadePoint; v++) m_OpacityMap[v][w] = 255; Metric rTaper = 1.0; for (v = iFadePoint; v < m_iLengthCount; v++, rTaper -= rTaperInc) m_OpacityMap[v][w] = (int)(255.0 * rTaper); } // The glow around the peak decays exponentially Metric rGlowLevel = MIN_GLOW_LEVEL + (m_iIntensity * GLOW_FACTOR); Metric rGlowInc = (m_iWidthCount > 0 ? (1.0 / (m_iWidthCount - iPeakPoint)) : 0.0); Metric rGlow = 1.0; for (w = iPeakPoint; w < m_iWidthCount; w++, rGlow -= rGlowInc) { Metric rGlowPart = rGlowLevel * rGlow * rGlow; for (v = 0; v < iFadePoint; v++) m_OpacityMap[v][w] = (int)(255.0 * rGlowPart); Metric rTaper = 1.0; for (v = iFadePoint; v < m_iLengthCount; v++, rTaper -= rTaperInc) m_OpacityMap[v][w] = (int)(255.0 * rGlowPart * rTaper); } break; } } // Width adjustments switch (iWidthAdjType) { case widthAdjBlob: { m_WidthAdjTop.InsertEmpty(m_iLengthCount); m_WidthAdjBottom.InsertEmpty(m_iLengthCount); // Initialize jagged envelope CalcWaves(m_WidthAdjTop, BLOB_WAVE_SIZE, m_iWidth * WAVY_WAVELENGTH_FACTOR); CalcWaves(m_WidthAdjBottom, BLOB_WAVE_SIZE, m_iWidth * WAVY_WAVELENGTH_FACTOR); break; } case widthAdjCone: { m_WidthAdjTop.InsertEmpty(m_iLengthCount); CalcCone(m_WidthAdjTop); m_WidthAdjBottom = m_WidthAdjTop; break; } case widthAdjDiamond: { m_WidthAdjTop.InsertEmpty(m_iLengthCount); CalcDiamond(m_WidthAdjTop); m_WidthAdjBottom = m_WidthAdjTop; break; } case widthAdjJagged: { m_WidthAdjTop.InsertEmpty(m_iLengthCount); m_WidthAdjBottom.InsertEmpty(m_iLengthCount); // Initialize jagged envelope CalcWaves(m_WidthAdjTop, JAGGED_AMPLITUDE, m_iWidth * JAGGED_WAVELENGTH_FACTOR); CalcWaves(m_WidthAdjBottom, JAGGED_AMPLITUDE, m_iWidth * JAGGED_WAVELENGTH_FACTOR); break; } case widthAdjOval: { m_WidthAdjTop.InsertEmpty(m_iLengthCount); CalcOval(m_WidthAdjTop); m_WidthAdjBottom = m_WidthAdjTop; break; } case widthAdjTapered: { m_WidthAdjTop.InsertEmpty(m_iLengthCount); CalcTaper(m_WidthAdjTop); m_WidthAdjBottom = m_WidthAdjTop; break; } } // Adjust shape switch (iReshape) { case widthAdjCone: { TArray<Metric> TaperAdj; TaperAdj.InsertEmpty(m_iLengthCount); CalcCone(TaperAdj); for (i = 0; i < m_iLengthCount; i++) { m_WidthAdjTop[i] *= TaperAdj[i]; m_WidthAdjBottom[i] *= TaperAdj[i]; } break; } case widthAdjDiamond: { TArray<Metric> TaperAdj; TaperAdj.InsertEmpty(m_iLengthCount); CalcDiamond(TaperAdj); for (i = 0; i < m_iLengthCount; i++) { m_WidthAdjTop[i] *= TaperAdj[i]; m_WidthAdjBottom[i] *= TaperAdj[i]; } break; } case widthAdjOval: { TArray<Metric> TaperAdj; TaperAdj.InsertEmpty(m_iLengthCount); CalcOval(TaperAdj); for (i = 0; i < m_iLengthCount; i++) { m_WidthAdjTop[i] *= TaperAdj[i]; m_WidthAdjBottom[i] *= TaperAdj[i]; } break; } case widthAdjTapered: { TArray<Metric> TaperAdj; TaperAdj.InsertEmpty(m_iLengthCount); CalcTaper(TaperAdj); for (i = 0; i < m_iLengthCount; i++) { m_WidthAdjTop[i] *= TaperAdj[i]; m_WidthAdjBottom[i] *= TaperAdj[i]; } break; } } // Apply texture switch (iTexture) { case opacityGrainy: { const int DIAMETER = 11; const int START = -(DIAMETER / 2); const int CENTER_X = (DIAMETER / 2); const int CENTER_Y = (DIAMETER / 2); const Metric RADIUS = (DIAMETER / 2.0); Metric Adj[DIAMETER][DIAMETER]; for (v = 0; v < DIAMETER; v++) for (w = 0; w < DIAMETER; w++) { int vDiff = v - CENTER_X; int wDiff = w - CENTER_Y; Metric rDist = sqrt((Metric)(vDiff * vDiff + wDiff * wDiff)) / RADIUS; Adj[v][w] = Max(0.0, 1.0 - rDist); } int iPeakPoint = (int)(SOLID_FACTOR * m_iIntensity * m_iWidthCount); int iGrainCount = (int)(4 * sqrt((Metric)m_iLength * m_iWidth)); for (i = 0; i < iGrainCount; i++) { int vCount = m_OpacityMap.GetCount(); int wCount = m_OpacityMap[0].GetCount(); int vCenter = mathRandom(0, vCount - 1); int wCenter = mathRandom(0, wCount - 1); Metric rCenter = GRAINY_SIGMA * mathRandomGaussian(); for (v = 0; v < DIAMETER; v++) { int vPos = START + vCenter + v; if (vPos < 0 || vPos >= vCount) continue; for (w = 0; w < DIAMETER; w++) { int wPos = START + wCenter + w; if (wPos < iPeakPoint || wPos >= wCount) continue; m_OpacityMap[vPos][wPos] = (BYTE)Min(Max(0, (int)((Metric)m_OpacityMap[vPos][wPos] * (1.0 + rCenter * Adj[v][w]))), 255); } } } break; } } // Done m_bInitialized = true; } }