Noise Library Part 2: NoiseUtils.dba by The Sab31st Oct 2010 10:11
|
---|
Summary Noise Utilities to be used with NoiseGen Description Noise Utilities Instructions Code ` This code was downloaded from The Game Creators ` It is reproduced here with full permission ` http://www.thegamecreators.com #include "Models.dba" #include "Math.dba" #constant SHAPE_PLANE 0 #constant SHAPE_CYLINDER 1 #constant SHAPE_SPHERE 2 #constant I_MAX 1.0 type gradientType pos as float color as dword endtype type noiseType shape as integer width as integer height as integer bound1 as float bound2 as float bound3 as float bound4 as float isSeamless as boolean sourceModule as integer nMap as integer endtype type rendererType sourceNoiseMap as integer destImage as integer isLightEnabled as boolean isWrapEnabled as boolean lightAzimuth as float lightBrightness as float lightColor as dword lightContrast as float lightElev as float lightIntensity as float background as integer cosAzimuth as float cosElev as float gradient as integer recalcLightValues as boolean sinAzimuth as float sinElev as float bumpHeight as float screenX as integer screenY as integer display as boolean endtype type writerType destFilename as string sourceImage as integer endtype function NoiseUtils_Setup() global gradientCount as integer global noiseMapCount as integer global renderesCount as integer global writersCount as integer global planeModel as integer global cylinderModel as integer global sphereModel as integer global dim noiseMaps() as noiseType global dim renderers() as rendererType global dim writers() as writerType global dim gradients(255, 255) as gradientType global dim gradientPointCount(255) as integer global dim noiseMap() as float gradientCount = 0 noiseMapCount = 0 renderesCount = 0 writersCount = 0 `Create the noise modules for future use planeModel = Create_Module(MOD_PLANE) cylinderModel = Create_Module(MOD_CYLINDER) sphereModel = Create_Module(MOD_SPHERE) endfunction function Gradient_Create() local result as integer if gradientCount <= 255 result = gradientCount inc gradientCount else ExceptionInvalidParam(gradientCount) endif Gradient_BuildGrayscale(result) endfunction result function Gradient_Clear(g_index as integer) for i = 0 to gradientPointCount(g_index) gradients(g_index, i).pos = 0 gradients(g_index, i).color = 0 next i gradientPointCount(g_index) = 0 endfunction function Gradient_AddPoint(g_index as integer, gradientPos as float, gradientColor as dword) `Find the insertion point for the new gradient point and insert the new `gradient point at that insertion point. The gradient point array will `remain sorted by gradient position. insertionPos = Gradient_FindInsertionPos(g_index, gradientPos) Gradient_InsertAtPos(g_index, insertionPos, gradientPos, gradientColor) endfunction function Gradient_FindInsertionPos(g_index as integer, gradientPos as float) insertionPos as integer if gradientPointCount(g_index) = 0 insertionPos = 0 exitfunction insertionPos endif insertionPos = gradientPointCount(g_index) for i = 0 to gradientPointCount(g_index) - 1 if gradientPos < gradients(g_index, i).pos `We found the array index in which to insert the new gradient point. `Exit now. insertionPos = i exitfunction insertionPos else if gradientPos = gradients(g_index, i).pos `Each gradient point is required to contain a unique gradient `position, so throw an exception. ExceptionInvalidParam(g_index) endif endif next i endfunction insertionPos function Gradient_InsertAtPos(g_index as integer, insertionPos as integer, gradientPos as float, gradientColor as dword) `Make room for the new gradient point at the specified insertion position `within the gradient point array. The insertion position is determined by `the gradient point's position; the gradient points must be sorted by `gradient position within that array. if gradientPointCount(g_index) > 0 for i = gradientPointCount(g_index) to insertionPos + 1 step -1 gradients(g_index, i).pos = gradients(g_index, i - 1).pos gradients(g_index, i).color = gradients(g_index, i - 1).color next i endif `Now that we've made room for the new gradient point within the array, add `the new gradient point. gradients(g_index, insertionPos).pos = gradientPos gradients(g_index, insertionPos).color = gradientColor inc gradientPointCount(g_index) endfunction function Gradient_GetColor(g_index as integer, gradientPos as float) local result as dword if gradientPointCount(g_index) >= 2 `Find the first element in the gradient point array that has a gradient `position larger than the gradient position passed to this method. for indexPos = 0 to gradientPointCount(g_index) - 1 if gradientPos < gradients(g_index, indexPos).pos exit endif next indexPos `Find the two nearest gradient points so that we can perform linear `interpolation on the color. index0 = ClampValue(indexPos - 1, 0, gradientPointCount(g_index) - 1) index1 = ClampValue(indexPos , 0, gradientPointCount(g_index) - 1) `If some gradient points are missing (which occurs if the gradient `position passed to this method is greater than the largest gradient `position or less than the smallest gradient position in the array), get `the corresponding gradient color of the nearest gradient point and exit `now. if index0 = index1 result = gradients(g_index, index1).color exitfunction result endif `Compute the alpha value used for linear interpolation. input0# = gradients(g_index, index0).pos input1# = gradients(g_index, index1).pos alpha# = (gradientPos - input0#) / (input1# - input0#) `Now perform the linear interpolation given the alpha value. color0 = gradients(g_index, index0).color color1 = gradients(g_index, index1).color result = LinearInterpColor(color0, color1, alpha#) else `throw exception endif endfunction result function Gradient_GetPointCount(g_index as integer) local result as integer result = gradientPointCount(g_index) endfunction result function Gradient_BuildGrayscale(g_index as integer) Gradient_Clear(g_index) Gradient_AddPoint(g_index, -1.0, rgb( 0, 0, 0)) Gradient_AddPoint(g_index, 1.0, rgb(255, 255, 255)) endfunction function Gradient_BuildTerrain(g_index as integer) Gradient_Clear(g_index) Gradient_AddPoint(g_index, -1.00, rgb( 0, 0, 128)) Gradient_AddPoint(g_index, -0.20, rgb( 32, 64, 128)) Gradient_AddPoint(g_index, -0.04, rgb( 64, 96, 192)) Gradient_AddPoint(g_index, -0.02, rgb(192, 192, 128)) Gradient_AddPoint(g_index, 0.00, rgb( 0, 192, 0)) Gradient_AddPoint(g_index, 0.25, rgb(192, 192, 0)) Gradient_AddPoint(g_index, 0.50, rgb(160, 96, 64)) Gradient_AddPoint(g_index, 0.75, rgb(128, 255, 255)) Gradient_AddPoint(g_index, 1.00, rgb(255, 255, 255)) endfunction function NoiseMap_Create(shape as integer) local result as integer array insert at bottom noiseMaps() noiseMaps(noiseMapCount).shape = shape result = noiseMapCount inc noiseMapCount NoiseMap_Setup(result) endfunction result function NoiseMap_Setup(n_index as integer) noiseMaps(n_index).width = 0 noiseMaps(n_index).height = 0 noiseMaps(n_index).bound1 = 0.0 noiseMaps(n_index).bound2 = 0.0 noiseMaps(n_index).bound3 = 0.0 noiseMaps(n_index).bound4 = 0.0 noiseMaps(n_index).isSeamless = FALSE noiseMaps(n_index).sourcemodule = -1 noiseMaps(n_index).nMap = -1 endfunction function NoiseMap_GetValue(n_index as integer, x as integer, y as integer) local result as float result = noiseMap(x, y) endfunction result function NoiseMap_GetWidth(n_index as integer) local result as integer result = noiseMaps(n_index).width endfunction result function NoiseMap_GetHeight(n_index as integer) local result as integer result = noiseMaps(n_index).height endfunction result function NoiseMap_GetLowerAngleBound(n_index as integer) local result as float result = noiseMaps(n_index).bound1 endfunction result function NoiseMap_GetLowerHeightBound(n_index as integer) local result as float result = noiseMaps(n_index).bound3 endfunction result function NoiseMap_GetUpperAngleBound(n_index as integer) local result as float result = noiseMaps(n_index).bound2 endfunction result function NoiseMap_GetUpperHeightBound(n_index as integer) local result as float result = noiseMaps(n_index).bound4 endfunction result function NoiseMap_GetLowerXBound(n_index as integer) local result as float result = noiseMaps(n_index).bound1 endfunction result function NoiseMap_GetLowerZBound(n_index as integer) local result as float result = noiseMaps(n_index).bound3 endfunction result function NoiseMap_GetUpperXBound(n_index as integer) local result as float result = noiseMaps(n_index).bound2 endfunction result function NoiseMap_GetUpperZBound(n_index as integer) local result as float result = noiseMaps(n_index).bound4 endfunction result function NoiseMap_IsSeamlessEnabled(n_index as integer) local result as boolean result = noiseMaps(n_index).isSeamless endfunction result function NoiseMap_GetEastLonBound(n_index as integer) local result as boolean result = noiseMaps(n_index).bound2 endfunction result function NoiseMap_GetNorthLatBound(n_index as integer) local result as boolean result = noiseMaps(n_index).bound3 endfunction result function NoiseMap_GetSouthLatBound(n_index as integer) local result as boolean result = noiseMaps(n_index).bound4 endfunction result function NoiseMap_GetWestLonBound(n_index as integer) local result as boolean result = noiseMaps(n_index).bound1 endfunction result function NoiseMap_SetSize(n_index as integer, width as integer, height as integer) noiseMaps(n_index).width = width noiseMaps(n_index).height = height endfunction function NoiseMap_SetBounds(n_index as integer, b1 as float, b2 as float, b3 as float, b4 as float) noiseMaps(n_index).bound1 = b1 noiseMaps(n_index).bound2 = b2 noiseMaps(n_index).bound3 = b3 noiseMaps(n_index).bound4 = b4 endfunction function NoiseMap_SetSourceModule(n_index as integer, m_index as integer) noiseMaps(n_index).sourceModule = m_index endfunction function NoiseMap_SetDestNMap(n_index as integer, nm_index as integer) noiseMaps(n_index).nMap = nm_index endfunction function NoiseMap_EnableSeamless(n_index as integer, toggle as boolean) noiseMaps(n_index).isSeamless = toggle endfunction function NoiseMap_Build(n_index as integer) select noiseMaps(n_index).shape case SHAPE_PLANE: NoiseMap_BuildPlane(n_index) endcase case SHAPE_CYLINDER: NoiseMap_BuildCylinder(n_index) endcase case SHAPE_SPHERE: NoiseMap_BuildSphere(n_index) endcase endselect endfunction function NoiseMap_BuildCylinder(n_index as integer) if noiseMaps(n_index).bound2 <= noiseMaps(n_index).bound1 or noiseMaps(n_index).bound4 <= noiseMaps(n_index).bound3 or noiseMaps(n_index).width <= 0 or noiseMaps(n_index).height <= 0 or noiseMaps(n_index).sourceModule = -1 ExceptionInvalidParam(n_index) else `Resize the destination noise map so that it can store the new output `values from the source model. width = noiseMaps(n_index).width height = noiseMaps(n_index).height dim noiseMap(width, height) as float `Load the source module into the cylinder model Set_Source0(cylinderModel, noiseMaps(n_index).sourceModule) angleExtent# = noiseMaps(n_index).bound2 - noiseMaps(n_index).bound1 heightExtent# = noiseMaps(n_index).bound4 - noiseMaps(n_index).bound3 xDelta# = angleExtent# / width yDelta# = heightExtent# / height curAngle# = noiseMaps(n_index).bound1 curHeight# = noiseMaps(n_index).bound3 `Fill every point in the noise map with the output values from the model. for y = 0 to height - 1 curAngle# = noiseMaps(n_index).bound1 for x = 0 to width - 1 noiseMap(x, y) = Cylinder_GetValue(cylinderModel, curAngle#, curHeight#) curAngle# = curAngle# + xDelta# next x curHeight# = curHeight# + yDelta# next y endif endfunction function NoiseMap_BuildPlane(n_index as integer) if noiseMaps(n_index).bound2 <= noiseMaps(n_index).bound1 or noiseMaps(n_index).bound4 <= noiseMaps(n_index).bound3 or noiseMaps(n_index).width <= 0 or noiseMaps(n_index).height <= 0 or noiseMaps(n_index).sourceModule = -1 ExceptionInvalidParam(n_index) else `Resize the destination noise map so that it can store the new output `values from the source model. width = noiseMaps(n_index).width height = noiseMaps(n_index).height dim noiseMap(width, height) as float `Load the source module into the plane model Set_Source0(planeModel, noiseMaps(n_index).sourceModule) xExtent# = noiseMaps(n_index).bound2 - noiseMaps(n_index).bound1 zExtent# = noiseMaps(n_index).bound4 - noiseMaps(n_index).bound3 xDelta# = xExtent# / width zDelta# = zExtent# / height xCur# = noiseMaps(n_index).bound1 zCur# = noiseMaps(n_index).bound3 `Fill every point in the noise map with the output values from the model. for z = 0 to height - 1 xCur# = noiseMaps(n_index).bound1 for x = 0 to width - 1 finalValue as float if not noiseMaps(n_index).isSeamless finalValue = Plane_GetValue(planeModel, xCur#, zCur#) else swValue# = Plane_GetValue(planeModel, xCur# , zCur# ) seValue# = Plane_GetValue(planeModel, xCur# + xExtent#, zCur# ) nwValue# = Plane_GetValue(planeModel, xCur# , zCur# + zExtent#) neValue# = Plane_GetValue(planeModel, xCur# + xExtent#, zCur# + zExtent#) xBlend# = 1.0 - ((xCur# - noiseMaps(n_index).bound1) / xExtent#) zBlend# = 1.0 - ((zCur# - noiseMaps(n_index).bound3) / zExtent#) z0# = LinearInterp(swValue#, seValue#, xBlend#) z1# = LinearInterp(nwValue#, neValue#, xBlend#) finalValue = LinearInterp(z0#, z1#, zBlend#) endif noiseMap(x, z) = finalValue xCur# = xCur# + xDelta# next x zCur# = zCur# + zDelta# next z endif endfunction function NoiseMap_BuildSphere(n_index as integer) if noiseMaps(n_index).bound2 <= noiseMaps(n_index).bound1 or noiseMaps(n_index).bound4 <= noiseMaps(n_index).bound3 or noiseMaps(n_index).width <= 0 or noiseMaps(n_index).height <= 0 or noiseMaps(n_index).sourceModule = -1 ExceptionInvalidParam(n_index) else `Resize the destination noise map so that it can store the new output `values from the source model. width = noiseMaps(n_index).width height = noiseMaps(n_index).height dim noiseMap(width, height) as float `Load the source module into the sphere model Set_Source0(sphereModel, noiseMaps(n_index).sourceModule) lonExtent# = noiseMaps(n_index).bound2 - noiseMaps(n_index).bound1 latExtent# = noiseMaps(n_index).bound4 - noiseMaps(n_index).bound3 xDelta# = lonExtent# / width yDelta# = latExtent# / height curLon# = noiseMaps(n_index).bound1 curLat# = noiseMaps(n_index).bound3 `Fill every point in the noise map with the output values from the model. for y = 0 to height - 1 curLon# = noiseMaps(n_index).bound1 for x = 0 to width - 1 noiseMap(x, y) = Sphere_GetValue(sphereModel, curLat#, curLon#) curLon# = curLon# + xDelta# next x curLat# = curLat# + yDelta# next y endif endfunction function Renderer_Create() local result as integer array insert at bottom renderers() result = rendererCount inc rendererCount Renderer_Setup(result) endfunction result function Renderer_Setup(r_index as integer) renderers(r_index).isLightEnabled = 0 renderers(r_index).isWrapEnabled = 0 renderers(r_index).gradient = 0 renderers(r_index).lightAzimuth = 45.0 renderers(r_index).lightBrightness = 1.0 renderers(r_index).lightColor = rgb(255, 255, 255) renderers(r_index).lightContrast = 1.0 renderers(r_index).lightElev = 45.0 renderers(r_index).lightIntensity = 1.0 renderers(r_index).background = -1 renderers(r_index).sourceNoiseMap = -1 renderers(r_index).destImage = -1 renderers(r_index).recalcLightValues = 1 renderers(r_index).bumpHeight = 1.0 renderers(r_index).screenX = 0 renderers(r_index).screenY = 0 renderers(r_index).isDisplayEnabled = 0 endfunction function Renderer_GetValue(r_index as integer, x as integer, y as integer) local result as dword endfunction result function Renderer_SetValue(r_index as integer, x as integer, y as integer, color as dword) endfunction function Renderer_EnableLight(r_index as integer, toggle as boolean) renderers(r_index).isLightEnabled = toggle endfunction function Renderer_EnableWrap(r_index as integer, toggle as boolean) renderers(r_index).isWrapEnabled = toggle endfunction function Renderer_SetGradient(r_index as integer, g_index as integer) renderers(r_index).gradient = g_index endfunction function Renderer_GetLightAzimuth(r_index as integer) local result as float result = renderers(r_index).lightAzimuth endfunction result function Renderer_GetLightBrightness(r_index as integer) local result as float result = renderers(r_index).lightBrightness endfunction result function Renderer_GetLightColor(r_index as integer) local result as dword result = renderers(r_index).lightColor endfunction result function Renderer_GetLightContrast(r_index as integer) local result as float result = renderers(r_index).lightContrast endfunction result function Renderer_GetLightElev(r_index as integer) local result as float result = renderers(r_index).lightElev endfunction result function Renderer_GetLightIntensity(r_index as integer) local result as float result = renderers(r_index).lightIntensity endfunction result function Renderer_IsLightEnabled(r_index as integer) local result as boolean result = renderers(r_index).isLightEnabled endfunction result function Renderer_IsWrapEnabled(r_index as integer) local result as boolean result = renderers(r_index).isWrapEnabled endfunction result function Renderer_GetScreenX(r_index as integer) local result as integer result = renderers(r_index).screenX endfunction result function Renderer_GetScreenY(r_index as integer) local result as integer result = renderers(r_index).screenY endfunction result function Renderer_IsDisplayEnabled(r_index as integer) local result as boolean result = renderers(r_index).isDisplayEnabled endfunction result function Renderer_Render(r_index as integer) if renderers(r_index).sourceNoiseMap = -1 or renderers(r_index).destImage = -1 or noiseMaps(renderers(r_index).sourceNoiseMap).width <= 0 or noiseMaps(renderers(r_index).sourceNoiseMap).height <= 0 or gradientPointCount(renderers(r_index).gradient) < 2 `throw exception else width = noiseMaps(renderers(r_index).sourceNoiseMap).width height = noiseMaps(renderers(r_index).sourceNoiseMap).height `Dark Basic cannot alter images directly, so we need to make a bitmap. `Find the first available empty bitmap. global bmap bmap = 0 for i = 1 to 32 if not bitmap exist(i) bmap = i exit endif next i if bmap = 0 `throw exception endif create bitmap bmap, width, height set current bitmap bmap `If a background image was provided, make sure it is the same size the `source noise map. Paste it onto the Dark Basic bitmap for processing if renderers(r_index).background <> -1 paste image renderers(r_index).background, 0, 0 endif backColor as dword destColor as dword for y = 0 to height - 1 for x = 0 to width - 1 `Get the color based on the value at the current point in the noise `map. destColor = Gradient_GetColor(renderers(r_index).gradient, noiseMap(x, y)) `If lighting is enabled, calculate the light intensity based on the `rate of change at the current point in the noise map. lightIntensity as float if renderers(r_index).isLightEnabled `Calculate the positions of the current point's four-neighbors. if renderers(r_index).isWrapEnabled if x = 0 xLeftOffset = width - 1 xRightOffset = 1 else if x = width - 1 xLeftOffset = -1 xRightOffset = width - 1 else xLeftOffset = -1 xRightOffset = 1 endif endif if y = 0 yDownOffset = 1 yUpOffset = height - 1 else if y = height - 1 yDownOffset = -(height - 1) yUpOffset = -1 else yDownOffset = 1 yUpOffset = -1 endif endif else if x = 0 xLeftOffset = 0 xRightOffset = 1 else if x = width - 1 xLeftOffset = -1 xRightOffset = 0 else xLeftOffset = -1 xRightOffset = 1 endif endif if y = 0 yDownOffset = 1 yUpOffset = 0 else if y = height - 1 yDownOffset = 0 yUpOffset = -1 else yDownOffset = 1 yUpOffset = -1 endif endif endif `yDownOffset = yDownOffset * width `yUpOffset = yUpOffset * width `Get the noise value of the current point in the source noise map `and the noise values of its four-neighbors. nc# = noisemap(x, y) nl# = noisemap(x + xLeftOffset, y) nr# = noisemap(x + xRightOffset, y) nd# = noisemap(x, y + yDownOffset) nu# = noisemap(x, y + yUpOffset) `Now we can calculate the lighting intensity. lightIntensity = Renderer_CalcLightIntensity(r_index, nc#, nl#, nr#, nd#, nu#) lightIntensity = lightIntensity * renderers(r_index).lightBrightness else `These values will apply no lighting to the destination image. lightIntensity = 1.0 endif `Get the current background color from the background image. if renderers(r_index).background <> -1 backColor = point(x, y) else backColor = 0 endif `Blend the destination color, background color, and the light `intensity together, then update the destination image with that `color. finalColor = Renderer_CalcDestColor(r_index, destColor, backColor, lightIntensity) dot x, y, finalColor if renderers(r_index).isDisplayEnabled copy bitmap bmap, 0, 0, width, height, 0, renderers(r_index).screenX, renderers(r_index).screenY, renderers(r_index).screenX + width, renderers(r_index).screenY + height endif next x next y if image exist(renderers(r_index).destImage) delete image renderers(r_index).destImage endif get image renderers(r_index).destImage, 0, 0, width, height, 1 delete bitmap bmap set current bitmap 0 endif endfunction function Renderer_SetBackground(r_index as integer, b_index as integer) renderers(r_index).background = b_index endfunction function Renderer_SetLightAzimuth(r_index as integer azimuth as float) renderers(r_index).lightAzimuth = azimuth renderers(r_index).recalcLightValues = 1 endfunction function Renderer_SetLightBrightness(r_index as integer bright as float) renderers(r_index).lightBrightness = bright endfunction function Renderer_SetLightColor(r_index as integer color as dword) renderers(r_index).lightColor = color endfunction function Renderer_SetLightContrast(r_index as integer contrast as float) renderers(r_index).lightContrast = contrast endfunction function Renderer_SetLightElev(r_index as integer elev as float) renderers(r_index).lightElev = elev renderers(r_index).recalcLightValues = 1 endfunction function Renderer_SetLightIntensity(r_index as integer intensity as float) renderers(r_index).lightIntensity = intensity endfunction function Renderer_SetSourceNoiseMap(r_index as integer n_index as integer) renderers(r_index).sourceNoiseMap = n_index endfunction function Renderer_SetDestImage(r_index as integer i_index as integer) renderers(r_index).destImage = i_index endfunction function Renderer_SetScreenCoords(r_index as integer, x as integer, y as integer) renderers(r_index).screenX = x renderers(r_index).screenY = y endfunction function Renderer_EnableDisplay(r_index as integer, toggle as boolean) renderers(r_index).isDisplayEnabled = toggle endfunction function Renderer_CalcDestColor(r_index as integer, sourceColor as dword, backgroundColor as dword, lightValue as float) `Translators note: Dark Basic colors do not carry an alpha `channel, so blending a sourceColor and a backgroundColor `can't actually happen with this implementation. I have `left the code intact from the original, but the `sourceColor will completely override the backColor. local result as dword sourceRed# = rgbr(sourceColor) / 255.0 sourceGreen# = rgbg(sourceColor) / 255.0 sourceBlue# = rgbb(sourceColor) / 255.0 sourceAlpha# = 1.0 backgroundRed# = rgbr(backgroundColor) / 255.0 backgroundGreen# = rgbg(backgroundColor) / 255.0 backgroundBlue# = rgbb(backgroundColor) / 255.0 `First, blend the source color to the background color using the alpha `of the source color. red# = LinearInterp(backgroundRed# , sourceRed# , sourceAlpha#) green# = LinearInterp(backgroundGreen#, sourceGreen#, sourceAlpha#) blue# = LinearInterp(backgroundBlue# , sourceBlue# , sourceAlpha#) if renderers(r_index).isLightEnabled `Now calculate the light color. lightRed# = lightValue * rgbr(renderers(r_index).lightColor) / 255.0 lightGreen# = lightValue * rgbg(renderers(r_index).lightColor) / 255.0 lightBlue# = lightValue * rgbb(renderers(r_index).lightColor) / 255.0 `Apply the light color to the new color. red# = red# * lightRed# green# = green# * lightGreen# blue# = blue# * lightBlue# endif `Clamp the color channels to the (0..1) range. if red# < 0.0 red# = 0.0 endif if red# > 1.0 red# = 1.0 endif if green# < 0.0 green# = 0.0 endif if green# > 1.0 green# = 1.0 endif if blue# < 0.0 blue# = 0.0 endif if blue# > 1.0 blue# = 1.0 endif `Rescale the color channels to the noise::uint8 (0..255) range and return `the new color. result = rgb(red# * 255, green# * 255, blue# * 255) endfunction result function Renderer_CalcLightIntensity(r_index as integer, center as float, left as float, right as float, down as float, up as float) local result as float `Recalculate the sine and cosine of the various light values if `necessary so it does not have to be calculated each time this method is `called. if renderers(r_index).recalcLightValues renderers(r_index).cosAzimuth = cos(renderers(r_index).lightAzimuth) renderers(r_index).sinAzimuth = sin(renderers(r_index).lightAzimuth) renderers(r_index).cosElev = cos(renderers(r_index).lightElev) renderers(r_index).sinElev = sin(renderers(r_index).lightElev) renderers(r_index).recalcLightValues = 0 endif `Now do the lighting calculations. io# = I_MAX * SQRT_2 * renderers(r_index).sinElev / 2.0 ix# = (I_MAX - io#) * renderers(r_index).lightContrast * SQRT_2 * renderers(r_index).cosElev * renderers(r_index).cosAzimuth iy# = (I_MAX - io#) * renderers(r_index).lightContrast * SQRT_2 * renderers(r_index).cosElev * renderers(r_index).sinAzimuth intensity# = (ix# * (left - right) + iy# * (up - down) + io#) if intensity# < 0.0 intensity# = 0.0 endif result = intensity# endfunction result function Renderer_RenderNormalMap(r_index as integer) if renderers(r_index).sourceNoiseMap = -1 or renderers(r_index).destImage = -1 or noiseMaps(renderers(r_index).sourceNoiseMap).width <= 0 or noiseMaps(renderers(r_index).sourceNoiseMap).height <=0 `throw exception else width = noiseMaps(renderers(r_index).sourceNoiseMap).width height = noiseMaps(renderers(r_index).sourceNoiseMap).height `Dark Basic cannot alter images directly, so we need to make a bitmap. `Find the first available empty bitmap. bmap = 0 for i = 1 to 32 if not bitmap exist(i) bmap = i exit endif next i if bmap = 0 `throw exception endif create bitmap bmap, width, height set current bitmap bmap for y = 0 to height - 1 for x = 0 to width - 1 `Calculate the positions of the current point's right and down `neighbors. if renderers(r_index).isWrapEnabled if x = width - 1 xRightOffset = -(width - 1) else xRightOffset = 1 endif if y = height - 1 yDownOffset = -(height - 1) else yDownOffset = 1 endif else if x = width - 1 xRightOffset = 0 else xRightOffset = 1 endif if y = height - 1 yDownOffset = 0 else yDownOffset = 1 endif endif `Get the noise value of the current point in the source noise map `and the noise values of its right and up neighbors. nc# = noiseMap(x, y) nr# = noiseMap(x + xRightOffset, y) nd# = noiseMap(x, y + yDownOffset) `Calculate the normal product. finalColor = Renderer_CalcNormalColor(r_index, nc#, nr#, nd#, renderers(r_index).bumpHeight) dot x, y, finalColor next x next y if image exist(renderers(r_index).destImage) delete image renderers(r_index).destImage endif get image renderers(r_index).destImage, 0, 0, width, height, 1 delete bitmap bmap set current bitmap 0 endif endfunction function Renderer_GetBumpHeight(r_index as integer) local result as float result = renderers(r_index).bumpHeight endfunction result function Renderer_SetBumpHeight(r_index as integer, bumpHeight as float) renderers(r_index).bumpHeight = bumpHeight endfunction function Renderer_CalcNormalColor(r_index as integer, nc as float, nr as float, nd as float, bumpHeight as float) local result as dword `Calculate the surface normal. nc = nc * bumpHeight nr = nr * bumpHeight nd = nd * bumpHeight ncr# = nc - nr ncd# = nc - nd d# = sqrt((ncd# ^ 2.0) + (ncr# ^ 2.0) + 1.0) vxc# = (nc - nr) / d# vyc# = (nc - nd) / d# vzc# = 1.0 / d# `Map the normal range from the (-1.0 .. +1.0) range to the (0 .. 255) `range. xc = floor(vxc# + 1.0) * 127.5 yc = floor(vyc# + 1.0) * 127.5 zc = floor(vzc# + 1.0) * 127.5 result = rgb(xc, yc, zc) endfunction result function Writer_Create() local result as integer array insert at bottom writers() result = writerCount inc writerCount Writer_Setup(result) endfunction result function Writer_Setup(w_index as integer) writers(w_index).destFilename = "" writers(w_index).sourceImage = -1 endfunction function Writer_GetDestFilename(w_index as integer) local result as string result = writers(w_index).destFilename endfunction result function Writer_SetDestFilename(w_index as integer, filename as string) writers(w_index).destFilename = filename endfunction function Writer_SetSourceImage(w_index as integer, i_index as integer) writers(w_index).sourceImage = i_index endfunction function Writer_WriteDestFile(w_index as integer) if image exist(writers(w_index).sourceImage) if file exist(writers(w_index).destFilename) delete file writers(w_index).destFilename endif save image writers(w_index).destFilename, writers(w_index).sourceImage else print "no image" wait key `throw exception endif endfunction function BlendChannel(channel0 as byte, channel1 as byte, alpha as float) local result as byte c0# = channel0 / 255.0 c1# = channel1 / 255.0 result = ((c1# * alpha) + (c0# * (1.0 - alpha))) * 255.0 endfunction result function LinearInterpColor(color0 as dword, color1 as dword, alpha as float) local result as dword outRed = BlendChannel(rgbr(color0), rgbr(color1), alpha) outGreen = BlendChannel(rgbg(color0), rgbg(color1), alpha) outBlue = BlendChannel(rgbb(color0), rgbb(color1), alpha) result = rgb(outRed, outGreen, outBlue) endfunction result |