-- ********************************* fn Thresh a b t = if (distance a b) < t then return true else return false -- ********************************* fn rndP3 p3 n = ( local mult = 10.0 ^ n nx = (floor ((p3.x * mult) + 0.5)) / mult ny = (floor ((p3.y * mult) + 0.5)) / mult nz = (floor ((p3.z * mult) + 0.5)) / mult return [nx,ny,nz] ) -- ********************************* fn copyArray a = ( b = #() for i = 1 to a.count do b[i] = a[i] return b ) -- ********************************* fn InitializeSelection = ( freeSceneBitmaps() SingleObject = false AttachedTrunk = false MagicIndex = undefined ObjArray = selection as array if ObjArray.count == 1 or ObjArray.count == 2 then ( if ObjArray.count == 1 then ( CTrunk = ObjArray[1] CBranchec = undefined ) else ( if ObjArray[1].pivot.z < ObjArray[2].pivot.z then ( CTrunk = ObjArray[1] CBranches = ObjArray[2] ) else ( CTrunk = ObjArray[2] CBranches = ObjArray[1] ) ) for i = 1 to CTrunk.name.count do if CTrunk.name[i] == "~" do MagicIndex = i -- find the area from the name of the trunk object Area = "" if MagicIndex != undefined then Area = substring CTrunk.name (Magicindex + 1) 2 else MessageBox "Please make sure you have\nthe area information defined!\n\ni.e. \"VMyPlant~IJ10-00\"" return #(CTrunk, CBranches, Area) ) else ( MessageBox "Feed this tool 1 or 2 objects only" return undefined ) ) -- ********************************* fn projectPoints p3 p r = ( -- usage: projectPoints -- project the key vertices onto a plane perpendicular to the light pp = #() V = p3 N = r.dir d = -(dot V N) for i = 1 to p.count do ( V = p[i] rPos = V + r.dir * 10.0 NRay = ray rPos r.dir t = -((d + (dot N rPos)) / (dot N r.dir)) P0 = rPos.x + r.dir.x * t P1 = rPos.y + r.dir.y * t P2 = rPos.z + r.dir.z * t Pnt = [P0, P1, P2] append pp Pnt ) return pp ) -- ********************************* fn projectObject o r = ( -- projects all the vertices in an object onto a plane normal to the direction of a supplied ray. -- usage: projectObject v = for i = 1 to o.numverts collect (getVert o i) v2 = projectPoints o.center v r for i = 1 to o.numverts do (setVert o i v2[i]) update o ) -- ********************************* fn FlattenObject o r = ( sel = (getBackFaces o r) for i = sel.count to 1 by -1 do deleteFace o sel[i] projectObject o r ) -- ********************************* fn getBackFaces o r = ( s = #() for i = 1 to o.numfaces do if (dot (getFaceNormal o i) r.dir) < 0 do append s i return s ) -- ********************************* fn CopyAndFlipFaces o = ( sel = getFaceSelection o sc = sel.count fc = o.numfaces setNumFaces o (o.numfaces + sc) true for i = 1 to sc do ( iFaceIndex = sel[i] iFace = getFace o iFaceIndex setFace o (fc + i) [iFace.x, iFace.z, iFace.y] setFaceMatID o (fc + i) (getFaceMatID o sel[i]) setFaceSmoothGroup o (fc + i) (getFaceSmoothGroup o sel[i]) ) update o for i = 1 to sc do ( iTVFace = getTVFace o sel[i] setTVFace o (fc + i) [iTVFace.x, iTVFace.z, iTVFace.y] ) addModifier o (Smooth()) convertToMesh o ) -- ********************************* fn QuickSort l r a = ( if r > l do ( i = l - 1 j = r do ( do (i += 1) while a[i] < a[r] while j > 1 do ( j -= 1 if a[j] <= a[r] do Exit ) t = a[i] a[i] = a[j] a[j] = t ) while ( i < j ) a[j] = a[i] a[i] = a[r] a[r] = t QuickSort l (i - 1) a QuickSort (i + 1) r a ) return a ) -- ********************************* fn QuickSort2 l r a b = ( if r > l do ( i = l - 1 j = r do ( do (i += 1) while a[i] < a[r] while j > 1 do ( j -= 1 if a[j] <= a[r] do Exit ) t = a[i] a[i] = a[j] a[j] = t t2 = b[i] b[i] = b[j] b[j] = t2 ) while ( i < j ) a[j] = a[i] a[i] = a[r] a[r] = t b[j] = b[i] b[i] = b[r] b[r] = t2 QuickSort2 l (i - 1) a b QuickSort2 (i + 1) r a b ) return #(a,b) ) -- ********************************* fn GetAngle p1 p2 = ( -- tan(theta) = (p2.x - p1.x) dx = (p2.x - p1.x) as float dy = (p2.y - p1.y) as float theta = atan (dx / dy) return theta ) -- ********************************* fn ccw p0 p1 p2 = ( dx1 = p1.x - p0.x dy1 = p1.y - p0.y dx2 = p2.x - p0.x dy2 = p2.y - p0.y if (dx1 * dy2) > (dy1 * dx2) do return 1 -- left turn if (dx1 * dy2) < (dy1 * dx2) do return -1 -- right turn if (dx1 * dy2) == (dy1 * dx2) do if (dx1 * dx2) < 0 or (dy1 * dy2) < 0 then return -1 else if ((dx1 * dx1) + (dy1 * dy1)) >= ((dx2 * dx2) + (dy2 * dy2)) then return 0 else return 1 ) -- ********************************* fn IdentifyEdges b i = ( local p = #() iHeight = b.height iWidth = b.width -- make sure the top point is in the array for y = 0 to (iHeight - 1) by 1 do ( CRow = getPixels b [0,y] iWidth for x = 1 to iWidth do if CRow[x].value >= 253 do (append p [x - 1,y]; Exit) if p.count >= 1 do Exit ) -- make sure the bottom point is in the array for y = (iHeight - 1) to 0 by -1 do ( CRow = getPixels b [0,y] iWidth for x = 1 to iWidth do if CRow[x].value >= 253 do (append p [x - 1,y]; Exit) if p.count >= 2 do Exit ) for y = 0 to (iHeight - 1) by i do ( CRow = getPixels b [0,y] iWidth for x = 1 to iWidth do if CRow[x].value >= 253 do (append p [x - 1,y]; Exit) for x = iWidth to 1 by -1 do if CRow[x].value >= 253 do (append p [x - 1,y]; Exit) ) return p ) fn ArrayCompare foo a b = ( same = true for i = 1 to a.count do if a[i] != b[i] do same = false return same ) -- ********************************* fn GetElement p M = ( if M <= 0 do M += p.count if M > p.count do M -= p.count return P[M] ) -- ********************************* fn rnd num = (num + 0.5) as integer -- ********************************* fn AvgPoint2 p1 p2 = [rnd ((p1.x + p2.x) as float / 2), rnd ((p1.y + p2.y) as float / 2)] -- ********************************* fn pruneClosePoints p threshold = ( n = #() local clean = true local skip = false for i = 1 to p.count do ( if skip then skip = false else ( -- get the distance between the two points d = distance (p1 = (getElement p i)) (p2 = (getElement p (i+1))) --format "d: %\n" d if d <= threshold then ( append n (AvgPoint2 p1 p2) skip = true clean = false ) else append n p1 ) ) if (ArrayCompare true p n) do return p if clean == false then ( --format "going again...\n" pruneClosePoints n threshold ) else ( return n ) ) -- ********************************* fn GrahamScanBitmap CBitmap Yi PruneDistance= ( CBitmap = (BitmapThreshold CBitmap 180) p = IdentifyEdges CBitMap Yi Hullpoints = GrahamScan p HullPoints = pruneClosePoints HullPoints PruneDistance return HullPoints ) -- ********************************* fn GrahamScan p = ( N = p.count lowPt = p[N] AnchorIndex = N local HullPoints = #(), AngleArray = #() for i = 1 to N do if (p[i].y < lowPt.y) then ( lowPt = p[i] AnchorIndex = i ) else if (p[i].y == lowPt.y) then if (p[i].x < lowPt.x) do ( lowPt = p[i] AnchorIndex = i ) -- Calculate the angles from the anchorpoint to each other point AnchorPt = p[AnchorIndex] append HullPoints AnchorPt for i = 1 to N do if i != AnchorIndex then append AngleArray (getAngle AnchorPt p[i]) else append AngleArray -360.0 -- sort the angles quickSort2 1 AngleArray.count AngleArray p p[1] = p[N] M = 3 for i = 4 to N do ( while (ccw (GetElement p M) (GetElement p (M - 1)) p[i]) <= 0 do (M -= 1) M += 1 t = p[M] p[M] = p[i] p[i] = t ) for i = 2 to M do append Hullpoints p[i] gc() return HullPoints ) -- ********************************* fn scaleColor c s = (color (c.r * s) (c.g * s) (c.b * s)) fn scaleColor2 c s = ( r = (c.r * s) g = (c.g * s) b = (c.b * s) if r > 255 do r = 255 if r < 0 do r = 0 if g > 255 do g = 255 if g < 0 do g = 0 if b > 255 do b = 255 if b < 0 do b = 0 return (color r g b) ) -- ********************************* fn CreateBitmap w h c = ( b = bitmap w h local cArray = for i = 1 to w collect c for y = 0 to (h - 1) do (SetPixels b [0, y] cArray) return b ) -- ********************************* fn PowOfLimit x y = ( if x > y then ( SclDn = 0 while x > 256 do ( x *= 0.5 SclDn += 1 ) if SClDn > 0 do for i = 1 to SClDn do y *= 0.5 ) else ( SclDn = 0 while y > 256 do ( y *= 0.5 SclDn += 1 ) if SClDn > 0 do for i = 1 to SClDn do x *= 0.5 ) if x < 8 do x = 8 if y < 8 do y = 8 return [x,y] ) -- ********************************* -- returns a power of two number based on user input of higher, lower, or nearest fn NearPowOfTwo num weight = ( -- Highest if weight == 1 do ( num2 = num counter = 0 while num >= 1.0 do ( num = (num * 0.5) counter = counter + 1 ) p2 = 2^(counter) return p2 ) -- Lowest if weight == 2 do ( num2 = num counter = 0 while num >= 1.0 do ( num = (num * 0.5) counter = counter + 1 ) p2 = 2^(counter - 1) return p2 ) -- Nearest if weight == 3 do ( num2 = num counter = 0 while num >= 1.0 do ( num = (num * 0.5) counter = counter + 1 ) p2 = 2^(counter - 1) if (num2 > p2 * 1.5) then return (p2 * 2) else return p2 ) ) -- ********************************* -- returns the index of the vertex with the lowest pos.z value fn LowestVert obj = ( local LowVertPos = obj.max.z local LowestVert = -1 nv = obj.numverts for i = 1 to nv do ( local Cvert = getvert obj i if Cvert.z < LowVertPos do ( LowVertPos = Cvert.z LowestVert = i ) ) return LowestVert ) -- ********************************* fn trunkCenter CObj thresh = ( -- first, we find the lowest vertex in the model LowVert = lowestVert CObj -- searching from the bottom BottomPoint = CObj.min.z SetVertSelection CObj #() update CObj nv = CObj.numverts Verts = for i = 1 to nv collect (getvert CObj i) -- first we find the vertex distance furthest from the center of the object FarVert = 0.0 VertexDistances = #() -- we put all the vertex distances into an array, and find the one furthest from the center of the mesh for i = 1 to nv do ( append VertexDistances Verts[i].z if VertexDistances[i] < FarVert do FarVert = VertexDistances[i] ) -- now we flag any vert within the threshold and put it into an array VertSelection = #() for i = 1 to nv do if VertexDistances[i] <= (BottomPoint + thresh) do (append VertSelection i) SetVertSelection CObj VertSelection verts = [0,0,0] for i = 1 to VertSelection.count do Verts = Verts + (getVert CObj VertSelection[i]) VertCenter = [(Verts.x / VertSelection.count), (Verts.y / VertSelection.count), (Verts.z / VertSelection.count)] return VertCenter ) -- ********************************* -- crops a bitmap to new supplied dimensions fn CropBitmap SourceImage StartPos NewImageSize = ( width = SourceImage.width height = SourceImage.height bmap = BitMap NewImageSize.x NewImageSize.y NewY = 0 for y = StartPos.y to (StartPos.y + NewImageSize.y) do ( CRow = getPixels SourceImage [StartPos.x, y] NewImageSize.x setPixels bmap [0,NewY] CRow NewY += 1 ) return bmap ) -- ********************************* -- takes a bitmap and returns an array of the following: -- [1] a new bitmap that only contains black or white (on/off transparencey) -- [2] the start point [x,y] for cropping -- [3] the area of a closest fit rectangle about the opaque area of the opacity map from the start point at [2] fn ThresholdBitmap bmap Thresh = ( local NMap = copy BMap StartPoint = [0,0] NewSize = [NMap.width, NMap.height] width = NMap.width height = NMap.height AreaArray = #() for y = 1 to height do ( AreaArray[y] = #() CRow = getpixels NMap [0, (y - 1)] width -- convert the row of color pixels to values LumRow = for i = 1 to CRow.count collect (CRow[i].value) -- convert this row based on the threshold value for i = 1 to LumRow.count do if LumRow[i] > Thresh then ( AreaArray[y][i] = true LumRow[i] = 255 ) else ( AreaArray[y][i] = false LumRow[i] = 0 ) -- convert the values back into colors for i = 1 to LumRow.count do CRow[i] = (color LumRow[i] LumRow[i] LumRow[i]) -- write the row back into the bitmap setpixels NMap [0, (y - 1)] CRow ) maxX = 0 minX = 256 maxY = 0 minY = 256 for y = 1 to AreaArray.count do ( CRow = AreaArray[y] for x = 1 to CRow.count do if CRow[x] == true do ( if x > maxX do maxX = x if y > maxY do maxY = y if x < minX do minX = x if y < minY do minY = y ) ) NewStartPoint = [(minX - 1), (minY - 1)] NewMapSize = [(maxX - minX) + 1, (maxY - minY) + 1] if NewStartPoint == [255,255] or NewMapSize == [-255,-255] do ( format "Bad OpacityMap data\n" NewStartPoint = [0,0] NewMapSize = NewSize ) return #(NMap, NewStartPoint, NewMapSize) ) -- ************************************************************************************************ -- * Start Utility -- ************************************************************************************************ Utility DetailReduction "Detail Reduction" ( local DRRollout, WorkingFolder, AttachedTrunk, SingleObject, Flt local debug = false rollout DRRollout "Detail Reduction" ( local CObj, CTrunk, CBranches, ThinkCount = 0, InterfaceState = #(), MasterObjData = #(), SunArray = #([0.163287,-0.71436,0.680461], [0.150228,-0.623607,0.767167], [0.13906,-0.522188,0.841417], [0.129977,-0.411837,0.90194], [0.123134,-0.294445,0.947703], [0.118652,-0.17202,0.977922], [0.116608,-0.0466583,0.992081], [0.11704,0.0794943,0.989941], [0.11994,0.204279,0.971537], [0.125262,0.32556,0.937187], [0.132916,0.441262,0.88748]) local DefaultInterface = #(false,\ --renderSeperate false,\ --CenterToBase, 0.5,\ -- TrunkCenterThresh 127,\ -- OpacityThresh true,\ -- RescaleBitmaps 1,\ -- sizeMaps 32,\ -- PixelsPerMeter 4,\ -- YIncrement 10.0,\ -- PrunePointsThreshold 0.24,\ -- AngleJitter true,\ -- GenTrunk false,\ -- CameraAtEyeHeight false,\ -- isPrelit 256,\ -- BitMapSize 5,\ -- NumViews 1,\ -- DRLevel false,\ -- OverRideBitmapSize 256,\ -- TrunkWidthOveride 256,\ -- TrunkHeightOveride true,\ -- GenBranches true,\ -- BranchCameraAtEyeHeight true,\ -- SplitMethod 256,\ -- BranchBitMapSize 5,\ -- BranchNumViews 1,\ -- BranchDRLevel false,\ -- BranchOverRideBitmapSize 256,\ -- BranchWidthOveride 256,\ -- BranchHeightOveride true) -- AutoDetermineMapSizes group "Batch Options" ( ListBox BatchList "Batch Processing List:" height:5 width:250 editText BatchName "Batch Name:" text:"Detail Reduction Set 1" width:250 checkbutton EditName "Edit" offset:[130,-23] height:19 highlightcolor:(color 69 163 172) width:80 button Add "Add Selection" width:80 height:32 offset:[130,-99] button Remove "Remove" width:80 height:32 offset:[130,0] label blank0 offset:[0,5] checkbox UseObjName "Use Obj Name" checked:true checkbox AutoSelect "Auto Select" offset:[130,-20] checkbox ThinkForMe "Think for Me" align:#right offset:[0,-20] ) group "Global Parameters" ( dropDownList GameArea "Game Area Lighting:" items:#("Beach", "Jungle Road", "Platation House", "Industrial Jungle", "InGEN Town", "Plains", "PineValley", "Shore", "InGEN Lab", "Ascent", "Summit") selection:2 height:12 colorpicker AmbientCol "Ambient Light: " color:(color 90 90 90) offset:[-50,0] spinner CMult "Spotlight Multiplier: " range:[0.1, 5.0, 0.5] fieldwidth:35 offset:[-20,-23] ) group "General Options" ( checkBox renderSeperate "Detail reduce branches seperate from trunk" checkbox CenterToBase "Center camera based on trunk bottom" checked:false spinner TrunkCenterThresh "Threshold:" range:[0,10,0.5] fieldWidth:45 align:#right enabled:false offset:[0,-20] spinner OpacityThresh "Opacity Map Threshold: " range:[0,255,127] type:#integer fieldwidth:45 offset:[0,0] Checkbox RescaleBitmaps "Rescale bitmaps" offset:[0,-20] checked:true radiobuttons sizeMaps labels:#("Higher power of 2", "Lower power of 2", "Nearest power of 2") default:1 columns:3 align:#left spinner PixelsPerMeter "Pixels Per Meter: " range:[1,64,32] fieldWidth:45 checkbox AutoDetermineMapSizes "Auto Determine Map Sizes" offset:[0,-20] checked:true ) group "Convex Hull Parameters" ( spinner YIncrement "Y Increment" range:[1,32,4] type:#integer fieldWidth:35 align:#left spinner PrunePointsThreshold "Pixel Threshold:" range:[1,32,10] fieldWidth:35 offset:[0,-20] align:#center spinner AngleJitter "Pixel Jitter:" range:[0,1,0.24] fieldWidth:35 align:#right offset:[0,-20] ) group "Trunk Options" ( checkbox GenTrunk "Create" checked:true checkbox CameraAtEyeHeight "Camera at eye level" align:#center offset:[0,-20] checkbox isPrelit "Trunk is Prelit" align:#right offset:[0,-20] spinner BitMapSize "Map Size:" range:[8,512,256] type:#integer align:#left fieldwidth:35 spinner NumViews "# Views: " range:[2,9,5] type:#integer fieldwidth:35 offset:[0,-21] align:#center spinner DRLevel "Detail Level: " range:[1,4,1] type:#integer fieldwidth:25 offset:[0,-21] align:#right checkbox OverRideBitmapSize "Overide Bitmap Size" spinner TrunkWidthOveride "Width:" range:[8,256,256] type:#integer fieldwidth:45 align:#left enabled:false offset:[130,-20] spinner TrunkHeightOveride "Height:" range:[8,256,256] type:#integer fieldwidth:45 offset:[230,-21] enabled:false align:#left ) group "Branch Options" ( checkbox GenBranches "Create" enabled:false checked:true checkbox BranchCameraAtEyeHeight "Camera at eye level" align:#center offset:[0,-20] enabled:false checked:true checkbox SplitMethod "Use Split Method" checked:true align:#right offset:[0,-20] enabled:false spinner BranchBitMapSize "Map Size:" range:[8,512,256] type:#integer align:#left fieldwidth:35 enabled:false spinner BranchNumViews "# Views: " range:[2,9,5] type:#integer fieldwidth:35 align:#center offset:[0,-21] enabled:false spinner BranchDRLevel "Detail Level: " range:[1,4,1] type:#integer fieldwidth:25 offset:[0,-21] align:#right enabled:false checkbox BranchOverRideBitmapSize "Overide Bitmap Size" enabled:false spinner BranchWidthOveride "Width:" range:[8,256,256] type:#integer fieldwidth:45 align:#left enabled:false offset:[130,-20] spinner BranchHeightOveride "Height:" range:[8,256,256] type:#integer fieldwidth:45 offset:[230,-21] enabled:false align:#left ) Button CreateDRObject "Create Detail Reduced Version" height:40 align:#left offset:[-10,10] width:180 Button CreateShadowObject "Create Shadow Version" width:180 height:40 align:#right offset:[10,-46] label status1 on BatchName entered text do ( if EditName.checked do ( txt = BatchName.text names = BatchList.items s = BatchList.selection names[s] = txt BatchList.items = names ) ) on EditName changed state do ( if state then ( names = BatchList.items if names.count > 0 do ( s = BatchList.selection BatchName.text = names[s] ) ) else ( names = BatchList.items BatchName.text = ("Detail Reduction Set " + (names.count + 1) as string) ) ) on ThinkForMe changed state do ( ThinkCount += 1 if ThinkCount >= 0 and ThinkCount <= 3 do messageBox "If computers were so wise...." if ThinkCount > 3 and ThinkCount < 7 do messageBox "pesky little fucker...." if ThinkCount >= 7 and ThinkCount < 10 do messageBox "just give up!" if ThinkCount >= 10 do messageBox "keep it up.....\nhere comes something really cool" ThinkForMe.checked = false ) on BatchList selected s do ( renderSeperate.checked = InterfaceState[s][1] CenterToBase.checked = InterfaceState[s][2] TrunkCenterThresh.value = InterfaceState[s][3] OpacityThresh.value = InterfaceState[s][4] RescaleBitmaps.checked = InterfaceState[s][5] sizeMaps.state = InterfaceState[s][6] PixelsPerMeter.value = InterfaceState[s][7] YIncrement.value = InterfaceState[s][8] PrunePointsThreshold.value = InterfaceState[s][9] AngleJitter.value = InterfaceState[s][10] GenTrunk.checked = InterfaceState[s][11] CameraAtEyeHeight.checked = InterfaceState[s][12] isPrelit.checked = InterfaceState[s][13] BitMapSize.value = InterfaceState[s][14] NumViews.value = InterfaceState[s][15] DRLevel.value = InterfaceState[s][16] OverRideBitmapSize.checked = InterfaceState[s][17] TrunkWidthOveride.value = InterfaceState[s][18] TrunkHeightOveride.value = InterfaceState[s][19] GenBranches.checked = InterfaceState[s][20] BranchCameraAtEyeHeight.checked = InterfaceState[s][21] SplitMethod.checked = InterfaceState[s][22] BranchBitMapSize.value = InterfaceState[s][23] BranchNumViews.value = InterfaceState[s][24] BranchDRLevel.value = InterfaceState[s][25] BranchOverRideBitmapSize.checked = InterfaceState[s][26] BranchWidthOveride.value = InterfaceState[s][27] BranchHeightOveride.value = InterfaceState[s][28] AutoDetermineMapSizes.checked = InterfaceState[s][29] if CenterToBase.checked then TrunkCenterThresh.enabled = true else TrunkCenterThresh.enabled = false if renderSeperate.checked then SplitMethod.enabled = BranchBitMapSize.enabled = BranchNumViews.enabled = BranchDRLevel.enabled = GenBranches.enabled = BranchCameraAtEyeHeight.enabled = BranchOverRideBitmapSize.enabled = true else SplitMethod.enabled = BranchBitMapSize.enabled = BranchNumViews.enabled = BranchDRLevel.enabled = GenBranches.enabled = BranchCameraAtEyeHeight.enabled = BranchOverRideBitmapSize.enabled = BranchWidthOveride.enabled = BranchHeightOveride.enabled = false if OverRideBitmapSize.checked then TrunkWidthOveride.enabled = TrunkHeightOveride .enabled = true else TrunkWidthOveride.enabled = TrunkHeightOveride .enabled = false if BranchOverRideBitmapSize.checked then BranchWidthOveride.enabled = BranchHeightOveride .enabled = true else BranchWidthOveride.enabled = BranchHeightOveride .enabled = false if AutoSelect.checked do ( select MasterObjData[s][1] if MasterObjData[s][2] != undefined do selectmore MasterObjData[s][2] ) if EditName.checked do ( names = BatchList.items if names.count > 0 do ( s = BatchList.selection BatchName.text = names[s] ) ) ) on add pressed do ( if (ObjData = InitializeSelection()) != undefined do ( format "%\n" ObjData append MasterObjData ObjData append InterfaceState (copyArray DefaultInterface) BatchListNames = BatchList.items if UseObjName.checked then ( nm = ObjData[1].name nm = (substring nm 1 (nm.count - 3)) append BatchListNames nm ) else ( append BatchListNames BatchName.text ) BatchList.items = BatchListNames BatchName.text = ("Detail Reduction Set " + (BatchListNames.count + 1) as string) ) ) on remove pressed do ( s = BatchList.selection if MasterObjData.count >= 1 do ( deleteItem MasterObjData s BatchListNames = BatchList.items deleteItem BatchListNames s BatchList.items = BatchListNames if s >= 2 then BatchList.selection = (s - 1) else BatchList.selection = 1 BatchName.text = ("Detail Reduction Set " + (BatchListNames.count + 1) as string) ) ) -- ************************************************************** -- Interface Control Modifications -- ************************************************************** -- 1 on renderSeperate changed state do ( if renderSeperate.checked then SplitMethod.enabled = BranchBitMapSize.enabled = BranchNumViews.enabled = BranchDRLevel.enabled = GenBranches.enabled = BranchCameraAtEyeHeight.enabled = BranchOverRideBitmapSize.enabled = true else SplitMethod.enabled = BranchBitMapSize.enabled = BranchNumViews.enabled = BranchDRLevel.enabled = GenBranches.enabled = BranchCameraAtEyeHeight.enabled = BranchOverRideBitmapSize.enabled = BranchWidthOveride.enabled = BranchHeightOveride.enabled = false if InterfaceState.count >= 1 do InterfaceState[BatchList.selection][1] = renderSeperate.checked ) -- 2 on CenterToBase changed state do ( if CenterToBase.checked then TrunkCenterThresh.enabled = true else TrunkCenterThresh.enabled = false if InterfaceState.count >= 1 do InterfaceState[BatchList.selection][2] = CenterToBase.checked ) -- 3 on TrunkCenterThresh changed state do if InterfaceState.count >= 1 do InterfaceState[BatchList.selection][3] = TrunkCenterThresh.value -- 4 on OpacityThresh changed state do if InterfaceState.count >= 1 do InterfaceState[BatchList.selection][4] = OpacityThresh.value -- 5 on RescaleBitmaps changed state do if InterfaceState.count >= 1 do InterfaceState[BatchList.selection][5] = RescaleBitmaps.checked -- 6 on sizeMaps changed state do if InterfaceState.count >= 1 do InterfaceState[BatchList.selection][6] = sizeMaps.state -- 7 on PixelsPerMeter changed state do if InterfaceState.count >= 1 do InterfaceState[BatchList.selection][7] = PixelsPerMeter.value -- 8 on YIncrement changed state do if InterfaceState.count >= 1 do InterfaceState[BatchList.selection][8] = YIncrement.value -- 9 on PrunePointsThreshold changed state do if InterfaceState.count >= 1 do InterfaceState[BatchList.selection][9] = PrunePointsThreshold.value -- 10 on AngleJitter changed state do if InterfaceState.count >= 1 do InterfaceState[BatchList.selection][10] = AngleJitter.value -- 11 on GenTrunk changed state do if InterfaceState.count >= 1 do InterfaceState[BatchList.selection][11] = GenTrunk.checked -- 12 on CameraAtEyeHeight changed state do if InterfaceState.count >= 1 do InterfaceState[BatchList.selection][12] = CameraAtEyeHeight.checked -- 13 on isPrelit changed state do if InterfaceState.count >= 1 do InterfaceState[BatchList.selection][13] = isPrelit.checked -- 14 on BitMapSize changed state do if InterfaceState.count >= 1 do InterfaceState[BatchList.selection][14] = BitMapSize.value -- 15 on NumViews changed state do if InterfaceState.count >= 1 do InterfaceState[BatchList.selection][15] = NumViews.value -- 16 on DRLevel changed state do ( BranchDRLevel.value = DRLevel.value if InterfaceState.count >= 1 do ( InterfaceState[BatchList.selection][16] = DRLevel.value InterfaceState[BatchList.selection][25] = BranchDRLevel.value ) ) -- 17 on OverRideBitmapSize changed state do ( if OverRideBitmapSize.checked then TrunkWidthOveride.enabled = TrunkHeightOveride .enabled = true else TrunkWidthOveride.enabled = TrunkHeightOveride .enabled = false if InterfaceState.count >= 1 do InterfaceState[BatchList.selection][17] = OverRideBitmapSize.checked ) -- 18 on TrunkWidthOveride changed state do if InterfaceState.count >= 1 do InterfaceState[BatchList.selection][18] = TrunkWidthOveride.value -- 19 on TrunkHeightOveride changed state do if InterfaceState.count >= 1 do InterfaceState[BatchList.selection][19] = TrunkHeightOveride.value -- 20 on GenBranches changed state do if InterfaceState.count >= 1 do InterfaceState[BatchList.selection][20] = GenBranches.checked -- 21 on BranchCameraAtEyeHeight changed state do if InterfaceState.count >= 1 do InterfaceState[BatchList.selection][21] = BranchCameraAtEyeHeight.checked -- 22 on SplitMethod changed state do if InterfaceState.count >= 1 do InterfaceState[BatchList.selection][22] = SplitMethod.checked -- 23 on BranchBitMapSize changed state do if InterfaceState.count >= 1 do InterfaceState[BatchList.selection][23] = BranchBitMapSize.value -- 24 on BranchNumViews changed state do if InterfaceState.count >= 1 do InterfaceState[BatchList.selection][24] = BranchNumViews.value -- 25 on BranchDRLevel changed state do ( DRLevel.value = BranchDRLevel.value if InterfaceState.count >= 1 do ( InterfaceState[BatchList.selection][16] = DRLevel.value InterfaceState[BatchList.selection][25] = BranchDRLevel.value ) ) -- 26 on BranchOverRideBitmapSize changed state do ( if BranchOverRideBitmapSize.checked then BranchWidthOveride.enabled = BranchHeightOveride .enabled = true else BranchWidthOveride.enabled = BranchHeightOveride .enabled = false if InterfaceState.count >= 1 do InterfaceState[BatchList.selection][26] = BranchOverRideBitmapSize.checked ) -- 27 on BranchWidthOveride changed state do if InterfaceState.count >= 1 do InterfaceState[BatchList.selection][27] = BranchWidthOveride.value -- 28 on BranchHeightOveride changed state do if InterfaceState.count >= 1 do InterfaceState[BatchList.selection][28] = BranchHeightOveride.value on AutoDetermineMapSizes changed state do if InterfaceState.count >= 1 do InterfaceState[BatchList.selection][29] = AutoDetermineMapSizes.checked -- ******************************************************************************************************* -- * Generate Detail Reduced version of the object -- ******************************************************************************************************* on CreateDRObject pressed do ( freeSceneBitmaps() for s = 1 to InterfaceState.count do ( if debug do format "\n\nStarting Object %\n\n" s BatchList.selection = s renderSeperate.checked = InterfaceState[s][1] CenterToBase.checked = InterfaceState[s][2] TrunkCenterThresh.value = InterfaceState[s][3] OpacityThresh.value = InterfaceState[s][4] RescaleBitmaps.checked = InterfaceState[s][5] sizeMaps.state = InterfaceState[s][6] PixelsPerMeter.value = InterfaceState[s][7] YIncrement.value = InterfaceState[s][8] PrunePointsThreshold.value = InterfaceState[s][9] AngleJitter.value = InterfaceState[s][10] GenTrunk.checked = InterfaceState[s][11] CameraAtEyeHeight.checked = InterfaceState[s][12] isPrelit.checked = InterfaceState[s][13] BitMapSize.value = InterfaceState[s][14] NumViews.value = InterfaceState[s][15] DRLevel.value = InterfaceState[s][16] OverRideBitmapSize.checked = InterfaceState[s][17] TrunkWidthOveride.value = InterfaceState[s][18] TrunkHeightOveride.value = InterfaceState[s][19] GenBranches.checked = InterfaceState[s][20] BranchCameraAtEyeHeight.checked = InterfaceState[s][21] SplitMethod.checked = InterfaceState[s][22] BranchBitMapSize.value = InterfaceState[s][23] BranchNumViews.value = InterfaceState[s][24] BranchDRLevel.value = InterfaceState[s][25] BranchOverRideBitmapSize.checked = InterfaceState[s][26] BranchWidthOveride.value = InterfaceState[s][27] BranchHeightOveride.value = InterfaceState[s][28] try ( Area = MasterObjData[s][3] if Area == "BE" do GameArea.selection = 1 if Area == "JR" do GameArea.selection = 2 if Area == "PH" do GameArea.selection = 3 if Area == "IJ" do GameArea.selection = 4 if Area == "TO" do GameArea.selection = 5 if Area == "PL" do GameArea.selection = 6 if Area == "PV" do GameArea.selection = 7 if Area == "SH" do GameArea.selection = 8 if Area == "LA" do GameArea.selection = 9 if Area == "AS" do GameArea.selection = 10 if Area == "SU" do GameArea.selection = 11 ) catch ( format "Area test failed...\n" -- GameArea.selection = 7 ) if renderSeperate.checked then ( CTrunk = MasterObjData[s][1] CBranches = MasterObjData[s][2] CTrunk = copy MasterObjData[s][1] CTrunk.wirecolor = MasterObjData[s][1].wirecolor CTrunk.mat = copy MasterObjData[s][1].mat if MasterObjData[s][2] != undefined do ( CBranches = copy MasterObjData[s][2] CBranches.wirecolor = MasterObjData[s][2].wirecolor CBranches.mat = copy CBranches.mat ) ) else ( format "MasterObjData[s]: %\n" MasterObjData[s] CTrunk = copy MasterObjData[s][1] try (CTrunk.wirecolor = MasterObjData[s][1].wirecolor) catch () CTrunk.mat = copy MasterObjData[s][1].mat SingleObject = true hide MasterObjData[s][1] --else ( -- CTrunk = copy MasterObjData[s][1] -- CTrunk.wirecolor = MasterObjData[s][1].wirecolor -- CTrunk.mat = copy CTrunk.mat -- CBranches = copy MasterObjData[s][2] -- CBranches.wirecolor = CBranches.wirecolor -- CBranches.mat = copy CBranches.mat -- hide MasterObjData[s][1] -- hide MasterObjData[s][2] -- attach CTrunk CBranches -- CBranches = undefined -- AttachedTrunk = true --) ) if CTrunk != undefined then ( for i = 1 to 2 do ( for o in objects do hide o if i == 1 do unhide CTrunk if CBranches != undefined do if i == 2 do unhide CBranches if renderSeperate.checked and i == 2 then NumVs = BranchNumViews.value as integer else NumVs = NumViews.value as integer CObj = undefined if i == 1 then if CTrunk != undefined do CObj = CTrunk else if CBranches != undefined do CObj = CBranches -- these arrays will hold the final scaled/cropped map data FinalOpacities = #() FinalTextures = #() InTexNameArray = #() OutTexNameArray = #() InOpNameArray = #() OutOpNameArray = #() if CObj != undefined then ( CWireColor = CObj.wirecolor if (GenTrunk.checked and i == 1) or (GenBranches.checked and i == 2) do ( status1.text = "Calculating object info..." OriginalMat = copy CObj.mat -- setup Area object info for tracking AreaKey = "" if GameArea.selection == 1 do (AreaKey = "BE") if GameArea.selection == 2 do (AreaKey = "JR") if GameArea.selection == 3 do (AreaKey = "PH") if GameArea.selection == 4 do (AreaKey = "IJ") if GameArea.selection == 5 do (AreaKey = "TO") if GameArea.selection == 6 do (AreaKey = "PL") if GameArea.selection == 7 do (AreaKey = "PV") if GameArea.selection == 8 do (AreaKey = "SH") if GameArea.selection == 9 do (AreaKey = "LA") if GameArea.selection == 10 do (AreaKey = "AS") if GameArea.selection == 11 do (AreaKey = "SU") -- DL is the detail level DL = (DRLevel.value as integer) as string if renderSeperate.checked and i == 2 do DL = (BranchDRLevel.value as integer) as string -- initialize some arrays BitMapArray = #() OpacityMapArray = #() DRObjectsArray = #() -- Set the Background color to black backgroundColor = (color 0 0 0) -- grab and set the Ambient light color to what's specified in the interface AmbientColor = AmbientCol.color -- setup field of vision fov = 10 CObjSize = (CObj.max - CObj.min) -- create a cricle for the camera path status1.text = "Calculating Camera..." CameraPath = circle() -- if center to base is checked, we determine the center of the lowest set of -- vertices in the mesh (the bottom of the trunk) and set the x,y center position to that. -- This way, we can make sure that the base of the trunk in each image view lies at the same position. -- Otherwise, we just use the object center if CenterToBase.checked then if i == 2 then ( ObjCenter = CObj.center ) else ( ObjCenter = trunkCenter CObj TrunkCenterThresh.value ObjCenter = [ObjCenter.x, ObjCenter.y, CObj.center.z] ) else ObjCenter = CObj.center CameraPath.pos = ObjCenter rotate CameraPath 90 Z_Axis theta = fov offsetHeight = false -- here, we find the largest distance of either the height, -- or the distance between the x,y coordinates of the .min and .max (thus the maximun diameter) if (distance [CObj.max.x,CObj.max.y] [CObj.min.x,CObj.min.y]) > (CObj.max.z - CObj.min.z) then ( d = (distance [CObj.max.x,CObj.max.y] [CObj.min.x,CObj.min.y]) offsetHeight = true if debug do format "Using objects maximum DIAMETER for largest dimension...\n" ) else ( d = (CObj.max.z - CObj.min.z) if debug do format "Using objects maximum HEIGHT for largest dimension...\n" ) -- setup the camera and it's position so that the object lies square in it's viewport h = (d / (2 * sin(theta / 2))) x = h * (cos(theta)) NewCamera = targetCamera() NewCamera.fov = fov NewCamera.target = targetObject() NewCamera.target.pos = ObjCenter NewDir = normalize (NewCamera.pos - NewCamera.target.pos) NewCamera.pos = NewCamera.target.pos + NewDir * x CameraDist = distance NewCamera.pos Newcamera.target.pos CameraPath.radius = CameraDist NewCamera.pos.controller = path() NewCamera.pos.controller.path = CameraPath BoxDimension = ((distance NewCamera.pos NewCamera.target.pos) * (tan(fov * 0.5))) * 2 -- could be used as scale factor??? fScale = [BoxDimension, BoxDimension] -- if we're using the largest diameter of the object, we need to change the object height so -- that the base of the new detail reduced object matches the base of th object itself. if (offsetHeight == true) and (i != 2) do ( Objheight = (CObj.max.z - CObj.min.z) * 0.5 ViewHeight = (((distance NewCamera.pos NewCamera.target.pos) * (tan(fov * 0.5))) * 2) * 0.5 HeightOffset = abs(Objheight - ViewHeight) CameraPath.pos = [CameraPath.pos.x, CameraPath.pos.y, CObj.center.z] --CameraPath.pos = [CameraPath.pos.x, CameraPath.pos.y, CameraPath.pos.z + HeightOffset] NewCamera.target.pos = CameraPath.pos if debug do format "Camera Offset height:%\n" HeightOffset ) -- set the camera height to be at eye level from the base of the tree -- eye level is 1.70 Meters if CameraAtEyeHeight.checked and i == 1 do ( newCameraHeight = (CObj.center.z - (CObj.max.z - CObj.min.z) * 0.5) + 1.70 CameraPath.pos = [CameraPath.pos.x, CameraPath.pos.y, newCameraHeight] ) if BranchCameraAtEyeHeight.checked and i == 2 do ( -- we base eye height for the branches off the dimensions of the trunk newCameraHeight = (CTrunk.center.z - (CTrunk.max.z - CTrunk.min.z) * 0.5) + 1.65 CameraPath.pos = [CameraPath.pos.x, CameraPath.pos.y, newCameraHeight] ) -- setup the animation of the camera about the path based on the number of views the user wants to use deletekeys NewCamera.pos.controller #allkeys c = NewCamera.pos.controller addNewKey c 0 addNewKey c NumVs animate on ( at time 0 c.percent = 0.0 at time NumVs c.percent = 100.0 ) status1.text = "Generating Light..." -- makes sure any and all lights are deleted for l in lights do delete l CLight = freespot() CLight.dir = SunArray[GameArea.selection] CLight.HotSpot = 60 CLight.color = (color 255 255 255) CLight.Multiplier = CMult.value SunDir = CLight.dir theta = CLight.HotSpot d = distance CObj.max CObj.min x = (d / (2 * sin(theta / 2))) CLight.pos = (CObj.center + SunDir * 1000) if i == 1 and isPrelit.checked do ( ambientColor = (color 255 255 255) lts = for l in lights collect l delete lts ) status1.text = "Calculating Bitmap info and Materials..." -- determine the bitmap size BitMapSizeValue = ((PixelsPerMeter.value as float) * BoxDimension) as integer if BitMapSizeValue > 300 do BitMapSizeValue = 300 if debug do format "Rendered map dimension: %\n" BitMapSizeValue status1.text = "Rendering texture maps..." -- Render all the texture maps for j = 1 to NumVs do ( Append BitMapArray (render camera:NewCamera outputwidth:BitMapSizeValue outputheight:BitMapSizeValue frame:j vfb:off) if debug do display BitMaparray[j] ) if classof CObj.mat == StandardMaterial do ( CObj.mat.diffuse = (color 255 255 255) CObj.mat.DiffuseMapEnable = false CObj.mat.BumpMapEnable = false CObj.mat.shinestrength = 0.0 CObj.mat.selfIllum = 100 ) if classof CObj.mat == multiMaterial do ( ns = CObj.mat.numsubs for j = 1 to ns do ( CObj.mat[j].diffuse = (color 255 255 255) CObj.mat[j].DiffuseMapEnable = false CObj.mat[j].BumpMapEnable = false CObj.mat[j].shinestrength = 0.0 CObj.mat[j].selfIllum = 100 ) ) status1.text = "Rendering opacity maps..." -- render all the opacity maps for j = 1 to NumVs do ( Append OpacityMapArray (render camera:NewCamera outputwidth:BitMapSizeValue outputheight:BitMapSizeValue frame:j vfb:off) if debug do display OpacityMaparray[j] ) CObj.mat = OriginalMat if classof CObj.mat == StandardMaterial do ( CObj.mat.DiffuseMapEnable = true CObj.mat.BumpMapEnable = true CObj.mat.shinestrength = 0.0 CObj.mat.selfIllum = 0.0 ) if classof CObj.mat == multiMaterial do ( ns = CObj.mat.numsubs for j = 1 to ns do ( CObj.mat[j].DiffuseMapEnable = true CObj.mat[j].BumpMapEnable = true CObj.mat[j].shinestrength = 0.0 CObj.mat[j].selfIllum = 0.0 ) ) CNamePrefix = "" CNameSuffix = "" for j = 1 to CObj.name.count do if CObj.name[j] == "~" do MagicIndex = j if MagicIndex != undefined then ( CNamePrefix = substring CObj.name 1 (MagicIndex - 1) CNameSuffix = ((substring CObj.name (MagicIndex + 1) 3) + ((DRLevel.value as integer) as string)) ) else ( for j = 1 to CObj.name.count do if CObj.name[j] == "-" do MagicIndex = j if magicIndex == undefined do MagicIndex = CObj.name.count CNamePrefix = substring CObj.name 1 (MagicIndex - 1) CNameSuffix = ((substring CObj.name (MagicIndex + 1) 3) + ((DRLevel.value as integer) as string)) ) ProgressStart "Generating Views..." for t = 1 to NumVs do ( at time t ( ProgressUpdate ((t/NumVs as float) * 100) -- ************************************************************ -- ** Process the bitmaps************************************** -- ************************************************************ if i == 2 and SplitMethod.checked do () -- process the bitmaps for size/scale status1.text = "Processing Bitmaps..." iStartWidth = OpacityMapArray[t].width iStartHeight = OpacityMapArray[t].height BitmapInfo = ThresholdBitmap OpacityMapArray[t] (OpacityThresh.value as integer) -- bitmapInfo = #(map, startpoint, new map size) if debug do ( format "%\n" BitmapInfo display OpacityMapArray[t] ) -- calculate the width and height scalar values for the geometry based on the new cropped areas WidthScalar = BitmapInfo[3].x as float / OpacityMapArray[t].width as float HeightScalar = BitmapInfo[3].y as float / OpacityMapArray[t].height as float -- crop the bitmaps OpacityMapArray[t] = CropBitmap BitmapInfo[1] BitmapInfo[2] [(BitmapInfo[3].x), BitmapInfo[3].y] BitMapArray[t] = CropBitmap BitmapArray[t] BitmapInfo[2] [(BitmapInfo[3].x), BitmapInfo[3].y] iCropWidth = OpacityMapArray[t].width iCropHeight = OpacityMapArray[t].height if i == 2 and SplitMethod.checked then ( w1o = ((iStartWidth / 2) - BitmapInfo[2].x) as integer OpacityMapArray[t] = CropBitmap OpacityMapArray[t] [w1o,0] [(iCropWidth - w1o), iCropHeight] BitMapArray[t] = CropBitmap BitMapArray[t] [w1o,0] [(iCropWidth - w1o), iCropHeight] NewBitMapWidth = (BitmapInfo[3].x / 2) NewBitMapHeight = BitmapInfo[3].y ) else ( NewBitMapWidth = BitmapInfo[3].x NewBitMapHeight = BitmapInfo[3].y ) -- Extra checking for illegal map sizes (> 256, < 8) if NewBitMapHeight > 256 do NewBitMapHeight = 256 if NewBitMapWidth > 256 do NewBitMapWidth = 256 if NewBitMapHeight < 8 do NewBitMapHeight = 8 if NewBitMapWidth < 8 do NewBitMapWidth = 8 if RescaleBitmaps.checked do ( reCalc = true if i == 1 and OverRideBitmapSize.checked do ( NewBitMapWidth = TrunkWidthOveride.value NewBitMapHeight = TrunkHeightOveride.value reCalc = false ) if i == 2 and BranchOverRideBitmapSize.checked do ( NewBitMapWidth = BranchWidthOveride.value NewBitMapHeight = BranchHeightOveride.value reCalc = false ) if reCalc == true do ( -- calculate the new bitmap dimensions to the nearest power of two size NewBitMapWidth = NearPowOfTwo NewBitMapWidth sizeMaps.state NewBitMapHeight = NearPowOfTwo NewBitMapHeight sizeMaps.state NSize = (PowOfLimit NewBitMapWidth NewBitMapHeight) NewBitMapWidth = NSize.x as integer NewBitMapHeight = NSize.y as integer ) if AutoDetermineMapSizes.checked do ( if debug do format "Auto Determining Map Sizes...\n" iHt = (CObj.max.z - CObj.min.z) -- figure out the predetermined height of the map if DRLevel.value == 1 then ( if iHt >= 0 and iHt <= 1 do NewBitMapHeight = 64 if iHt > 1 and iHt <= 5 do NewBitMapHeight = 128 if iHt > 5 do NewBitMapHeight = 256 if debug do format "DRLevel:% Bitmap height: %\n" DRLevel.value NewBitMapHeight ) else ( -- Detail Levels > 2 if iHt >= 0 and iHt <= 1 do NewBitMapHeight = 32 if iHt > 1 and iHt <= 5 do NewBitMapHeight = 64 if iHt > 5 do NewBitMapHeight = 128 if debug do format "DRLevel:% Bitmap height: %\n" DRLevel.value NewBitMapHeight ) -- now determine the width iWth = (distance [CObj.max.x, CObj.max.y] [CObj.min.x, CObj.min.y]) NewBitMapWidth = ((iWth * NewBitMapHeight) / iHt) as integer if debug do format "iHt:%\tiWd:%\tbHt:%\tbWd:%\n" iHt iWth NewBitMapHeight NewBitMapWidth NewBitMapWidth = NearPowOfTwo NewBitMapWidth 2 -- always go lower NSize = (PowOfLimit NewBitMapWidth NewBitMapHeight) NewBitMapWidth = NSize.x as integer NewBitMapHeight = NSize.y as integer if debug do format "BitMap Size calculated to be %\n" NSize ) ) if debug do format "Initial BitmapSize: %\t%\nNew Bitmap size: %\t%\n" BitmapInfo[3].x BitmapInfo[3].y NewBitMapWidth NewBitMapHeight -- set the filenames... FinalOpName = (WorkingFolder + CNamePrefix + t as string + "~" + CNameSuffix + "o8.bmp") FinalTexName = (WorkingFolder + CNamePrefix + t as string + "~" + CNameSuffix + "t2.bmp") InTexName = (WorkingFolder + "t" + t as string + ".bmp") OutTexName = (WorkingFolder + "t_" + t as string + ".bmp") InOpName = (WorkingFolder + "o" + t as string + ".bmp") OutOpName = (WorkingFolder + "o_" + t as string + ".bmp") if i == 2 and SplitMethod.checked then ( NewOp = bitmap (NewBitMapWidth / 2) NewBitMapHeight NewTex = bitmap (NewBitMapWidth / 2) NewBitMapHeight ) else ( NewOp = bitmap NewBitMapWidth NewBitMapHeight NewTex = bitmap NewBitMapWidth NewBitMapHeight ) try ( copy OpacityMapArray[t] NewOp copy BitMapArray[t] NewTex ) catch ( MessageBox "Something fucked up.\nGo get Kyle." ) -- Start the Graham's Scan -- Identify all the edge pixels status1.text = "Identifying Edges...." p = IdentifyEdges NewOp YIncrement.value -- add some random jitter to the array of points so the angle array will sort properly aj = AngleJitter.value for j = 1 to p.count do ( if p[j].x == 0 do (p[j].x += (random 0 aj)) if p[j].y == 0 do (p[j].y += (random 0 aj)) if p[j].x == NewOp.width do (p[j].x += (random -aj 0)) if p[j].y == NewOp.height do (p[j].y += (random -aj 0)) if p[j].x < NewOp.width and p[j].x > 0 do (p[j].x += (random -aj aj)) if p[j].y < NewOp.height and p[j].y > 0 do (p[j].y += (random -aj aj)) ) -- do the Graham Scan status1.text = "Calculating convex hull..." Hullpoints = GrahamScan p -- remove the jitter to the array of points are integers again for j = 1 to Hullpoints.count do (Hullpoints[j] = [(rnd Hullpoints[j].x), (rnd Hullpoints[j].y)]) status1.text = "Reducing Points..." HullPoints = pruneClosePoints HullPoints PrunePointsThreshold.value -- set the new filenames NewOp.filename = InOpName NewTex.filename = InTexName -- Delete the files (if they're already there) DeleteFile NewOp.filename DeleteFile NewTex.filename -- and save them... save NewTex save NewOp status1.text = "Starting Alchemy..." -- Process Maps via Alchemy doscommand ("alchemy -w -o -b " + InOpName + " " + OutOpName) doscommand ("alchemy -w -o " + InTexName + " " + OutTexName) -- doscommand ("alchemy -w -o -b -X" + NewBitMapWidth as string + " -Y" + NewBitMapHeight as string + " " + InOpName + " " + OutOpName) -- doscommand ("alchemy -w -o -X" + NewBitMapWidth as string + " -Y" + NewBitMapHeight as string + " " + InTexName + " " + OutTexName) if debug do format "Alchemy Done!...\nProcessing Bitmaps Finished!\n" -- Delete files that may already be there deleteFile FinalOpName deleteFile FinalTexName -- Copy the processed bitmaps to their final name/location copyFile OutOpName FinalOpName copyFile OutTexName FinalTexName -- ************************************************************ -- ** Create the new mesh ************************************* -- ************************************************************ -- calculate the new uv's for Hullpoints status1.text = "Calculating Texture Vertices..." minX = HullPoints[1].x maxX = HullPoints[1].x minY = HullPoints[1].y maxY = HullPoints[1].y for i = 1 to HullPoints.count do ( if HullPoints[i].x > maxX do maxX = HullPoints[i].x if HullPoints[i].x < minX do minX = HullPoints[i].x if HullPoints[i].y > maxY do maxY = HullPoints[i].y if HullPoints[i].y < minY do minY = HullPoints[i].y ) iWidth = maxX - minX iHeight = maxY - minY iDimension = [iWidth, iHeight] iCorner = [minX, minY] du = 1.0 / iWidth dv = 1.0 / iHeight -- flip all the y points for j = 1 to Hullpoints.count do (Hullpoints[j].y = iHeight - Hullpoints[j].y) TVertArray = #() for j = 1 to Hullpoints.count do ( Tvert = [(HullPoints[j].x * du), (HullPoints[j].y * dv),1.0] append TVertArray Tvert ) BoxDimension = ((distance NewCamera.pos NewCamera.target.pos) * (tan(fov * 0.5))) * 2 if i == 2 and SplitMethod.checked then PixelSize = (BoxDimension as float / iCropWidth) else PixelSize = (BoxDimension as float / BitMapSizeValue) -- PixelSize = (BoxDimension as float / BitMapSizeValue as float) if debug do format "PixelSize:%\n" PixelSize -- calculate the width and height offsets for the new geometry w1 = BitmapInfo[2].x w2 = BitmapInfo[1].width - (w1 + BitmapInfo[3].x) AvgFreeWidth = (BitmapInfo[1].width - BitmapInfo[3].x) * 0.5 if w2 >= w1 then ObjectOffsetW = (AvgFreeWidth - w1) * PixelSize else ObjectOffsetW = -(AvgFreeWidth - w2) * PixelSize if i == 2 and SplitMethod.checked do ObjectOffsetW = (iStartWidth - iCropWidth) * PixelSize h1 = BitmapInfo[2].y h2 = BitmapInfo[1].height - (h1 + BitmapInfo[3].y) AvgFreeHeight = (BitmapInfo[1].height - BitmapInfo[3].y) * 0.5 if h2 >= h1 then ObjectOffsetV = (AvgFreeHeight - h1) * PixelSize else ObjectOffsetV = -(AvgFreeHeight - h2) * PixelSize if debug do ( format "w1:% w2:% h1:% h2:%\n" w1 w2 h1 h2 format "Height Offset:%\nWidth Offset:%\nAvg Free: % %\n" ObjectOffsetV ObjectOffsetW AvgFreeWidth AvgFreeHeight ) -- width and height of the object in 3space NewHeight = BoxDimension as float * HeightScalar if i == 2 and SplitMethod.checked then NewWidth = (BoxDimension as float * WidthScalar) / 2 else NewWidth = (BoxDimension as float * WidthScalar) -- make the box b = box() b.width = NewWidth b.height = BoxDimension b.length = NewHeight b.pos = NewCamera.target.pos b.dir = -NewCamera.dir if debug do format "Camera Dir vector @ %: %\n" t -NewCamera.dir b.mapcoords = true convertToMesh b -- delete the verts off the box that we don't need. for j = 1 to 4 do deleteVert b b.numverts if NewCamera.dir.x < 0.0 do in coordsys local rotate b 180 z_axis in coordsys local rotate b 180 z_axis if SplitMethod.checked and i == 2 then in coordsys local move b [-(NewWidth * 0.5), -ObjectOffsetV, 0] else in coordsys local move b [ObjectOffsetW, ObjectOffsetV, 0] convertToMesh b -- Calculate the new points in 3space via the uv coordinates P0 = getVert b 2 P1 = getVert b 1 P2 = getVert b 4 P3 = getVert b 3 fVertArray = #() for j = 1 to TVertArray.count do ( Px = (P0.x + (TVertArray[j].x * (P1.x - P0.x)) + (TVertArray[j].y * (P2.x - P0.x))) Py = (P0.y + (TVertArray[j].x * (P1.y - P0.y)) + (TVertArray[j].y * (P2.y - P0.y))) Pz = (P0.z + (TVertArray[j].x * (P1.z - P0.z)) + (TVertArray[j].y * (P2.z - P0.z))) append fVertArray [Px,Py,Pz] ) iFaceArray = #([1,2,3]) for i = 3 to (Hullpoints.count - 1) do (append iFaceArray [1,i,i+1]) -- construct the mesh delete b b = mesh vertices:fVertArray faces:iFaceArray if b.numverts > 16 do (format "Warning: more than 16 verts detected in convex hull object... please check and regenerate if needed...\n") -- apply the texture coordinates addmodifier b (UVWMap()) convertToMesh b for i = 1 to b.numfaces do ( iFace = getFace b i iTFace = getTVFace b i setTvert b iTFace.x (TVertArray[iFace.x]) setTvert b iTFace.y (TVertArray[iFace.y]) setTvert b iTFace.z (TVertArray[iFace.z]) ) -- Set the Edge visibility for i = 1 to b.numfaces do ( if i == 1 do setEdgeVis b i 3 off if i == b.numfaces do setEdgeVis b i 1 off if i > 1 and i < b.numfaces do ( SetEdgeVis b i 1 off SetEdgeVis b i 3 off ) ) update b df = #() for i = 1 to b.numfaces do ( Cface = getface b i n = 4 NewX = rndP3 (getvert b Cface.x) n NewY = rndP3 (getvert b Cface.y) n NewZ = rndP3 (getvert b Cface.z) n if (Thresh NewX NewY 0.001) do if findItem df i == 0 do (append df i) if (Thresh NewX NewZ 0.001) do if findItem df i == 0 do (append df i) if (Thresh NewZ NewY 0.001) do if findItem df i == 0 do (append df i) -- check for a degenerate normal if (GetFaceNormal b i) == [0,0,0] do if findItem df i == 0 do (append df i) ) if df.count > 0 do ( format "found degenerate polygons... deleting them\n" for i = df.count to 1 by -1 do deleteFace b df[i] update b ) -- Check for Stray Vertices StrayVertArray = (for i = 1 to b.numverts collect i) UsedVerts = #() NewVertSelection = #() for i = 1 to b.numfaces do ( CFace = (getface b i) if (findItem UsedVerts CFace.x) == 0 do (append UsedVerts CFace.x) if (findItem UsedVerts CFace.y) == 0 do (append UsedVerts CFace.y) if (findItem UsedVerts CFace.z) == 0 do (append UsedVerts CFace.z) ) for i = 1 to StrayVertArray.count do if (findItem UsedVerts i) == 0 do (append NewVertSelection i) if NewVertSelection.count > 0 then ( format "Stray vertices were found... deleting them\n" for i = NewVertSelection.count to 1 by -1 do deleteVert b NewVertSelection[i] update b ) if DRLevel.value == 1 then b.wirecolor = scaleColor CWireColor 0.75 if DRLevel.value == 2 then b.wirecolor = scaleColor CWireColor 0.65 if DRLevel.value == 3 then b.wirecolor = scaleColor CWireColor 0.50 if DRLevel.value == 4 then b.wirecolor = scaleColor CWireColor 0.40 -- ************************************************************ -- ** Generate a new material ********************************* -- ************************************************************ -- make sure all face IDs are set to 1 status1.text = "Building a new material..." for j = 1 to b.numfaces do setFaceMatID b j 1 NMat = standardMaterial() -- give it a random color NMat.diffuse = random (color 20 20 20) (color 220 220 220) NMat.diffuseMap = bitmaptexture() NMat.OpacityMap = bitmaptexture() -- specify the bitmap names NMat.diffuseMap.filename = FinalTexName NMat.OpacityMap.filename = FinalOpName NMat.shinestrength = 0.0 NMat.name = substring OutTexName 1 (OutTexName.count - 3) NMat.selfIllum = 100 b.mat = NMat append DRObjectsArray b if debug do format "Finished building new material!\n" ) ) ProgressEnd() -- Attach the detail reduced objects together for j = DRObjectsArray.count to 2 by -1 do attach DRObjectsArray[1] DRObjectsArray[j] DRObject = DRObjectsArray[1] DRObject.mat.name = (CObj.name + "dr") if i == 1 then DRL = DRLevel.value as integer else DRL = BranchDRLevel.value as integer DRObject.name = ("$" + (substring CObj.name 1 (CObj.name.count - 4)) + DRL as string + "-00") DRObject.pivot = CObj.pivot f = for i = 1 to DRObject.numfaces collect i setFaceSelection DRObject f if flip != undefined do if flip then CopyAndFlipFaces DRObject try ( if (i != 1) or (isPrelit.checked == false) do ( delete CLight CLight = undefined ) ) catch () if debug != true do ( delete NewCamera NewCamera = undefined delete CameraPath CameraPath = undefined ) CObj.mat = OriginalMat ) ) else ( if renderSeperate.checked do MessageBox "No Objects Defined!" ) gc() -- collect some garbage status1.text = "" ) -- Lonnie, comment the next two lines out "--" -- if SingleObject == true do -- delete CTrunk delete CTrunk if CBranches != undefined do delete CBranches -- unhide everything at the end... for o in objects do unhide o CTrunk = CBranches = undefined status1.text = "" ) else ( MessageBox "You must initialize the objects first" ) ) messageBox "Complete" ) -- ******************************************************************************************************* -- ****************** *********************** -- ****************** Generate Shadow Object *********************** -- ****************** *********************** -- ******************************************************************************************************* on CreateShadowObject pressed do ( for s = 1 to InterfaceState.count do ( BatchList.selection = s renderSeperate.checked = InterfaceState[s][1] CenterToBase.checked = InterfaceState[s][2] TrunkCenterThresh.value = InterfaceState[s][3] OpacityThresh.value = InterfaceState[s][4] RescaleBitmaps.checked = InterfaceState[s][5] sizeMaps.state = InterfaceState[s][6] PixelsPerMeter.value = InterfaceState[s][7] YIncrement.value = InterfaceState[s][8] PrunePointsThreshold.value = InterfaceState[s][9] AngleJitter.value = InterfaceState[s][10] GenTrunk.checked = InterfaceState[s][11] CameraAtEyeHeight.checked = InterfaceState[s][12] isPrelit.checked = InterfaceState[s][13] BitMapSize.value = InterfaceState[s][14] NumViews.value = InterfaceState[s][15] DRLevel.value = InterfaceState[s][16] OverRideBitmapSize.checked = InterfaceState[s][17] TrunkWidthOveride.value = InterfaceState[s][18] TrunkHeightOveride.value = InterfaceState[s][19] GenBranches.checked = InterfaceState[s][20] BranchCameraAtEyeHeight.checked = InterfaceState[s][21] SplitMethod.checked = InterfaceState[s][22] BranchBitMapSize.value = InterfaceState[s][23] BranchNumViews.value = InterfaceState[s][24] BranchDRLevel.value = InterfaceState[s][25] BranchOverRideBitmapSize.checked = InterfaceState[s][26] BranchWidthOveride.value = InterfaceState[s][27] BranchHeightOveride.value = InterfaceState[s][28] Area = MasterObjData[s][3] if Area == "BE" do GameArea.selection = 1 if Area == "JR" do GameArea.selection = 2 if Area == "PH" do GameArea.selection = 3 if Area == "IJ" do GameArea.selection = 4 if Area == "TO" do GameArea.selection = 5 if Area == "PL" do GameArea.selection = 6 if Area == "PV" do GameArea.selection = 7 if Area == "SH" do GameArea.selection = 8 if Area == "LA" do GameArea.selection = 9 if Area == "AS" do GameArea.selection = 10 if Area == "SU" do GameArea.selection = 11 if renderSeperate.checked then ( CTrunk = MasterObjData[s][1] CTrunk.wirecolor = MasterObjData[s][1].wirecolor CBranches = MasterObjData[s][2] CTrunk = copy MasterObjData[s][1] CTrunk.mat = copy MasterObjData[s][1].mat if MasterObjData[s][2] != undefined do ( CBranches = copy MasterObjData[s][2] CBranches.wirecolor = MasterObjData[s][2].wirecolor CBranches.mat = copy CBranches.mat ) ) else ( CTrunk = MasterObjData[s][1] CTrunk.wirecolor = MasterObjData[s][1].wirecolor CBranches = MasterObjData[s][2] if CBranches == undefined then ( CTrunk = copy MasterObjData[s][1] CTrunk.wirecolor = MasterObjData[s][1].wirecolor CTrunk.mat = copy MasterObjData[s][1].mat SingleObject = true hide MasterObjData[s][1] ) else ( CTrunk = copy MasterObjData[s][1] CTrunk.wirecolor = MasterObjData[s][1].wirecolor CTrunk.mat = copy CTrunk.mat CBranches = copy MasterObjData[s][2] CBranches.wirecolor = MasterObjData[s][2].wirecolor CBranches.mat = copy CBranches.mat hide MasterObjData[s][1] hide MasterObjData[s][2] attach CTrunk CBranches CBranches = undefined AttachedTrunk = true ) ) if CTrunk != undefined then ( for i = 1 to 2 do ( for o in objects do hide o if i == 1 do unhide CTrunk if CBranches != undefined do if i == 2 do unhide CBranches if renderSeperate.checked and i == 2 then NumVs = BranchNumViews.value as integer else NumVs = NumViews.value as integer CObj = undefined if i == 1 then if CTrunk != undefined do CObj = CTrunk else if CBranches != undefined do CObj = CBranches if i == 1 and CBranches != undefined then ( -- this is for the trunk b = copy CObj r = SunArray[GameArea.selection] r = normalize [r.x, r.y, 0] r = ray [0,0,0] r FlattenObject b r addmodifier b (UVWMap()) convertToMesh b b.mat = standardMaterial() b.name = ("$" + (substring CObj.name 1 (CObj.name.count - 4)) + "5-00") ) else ( if i == 1 do (CObj = CTrunk) -- these arrays will hold the final scaled/cropped map data FinalOpacities = #() FinalTextures = #() InTexNameArray = #() OutTexNameArray = #() InOpNameArray = #() OutOpNameArray = #() if CObj != undefined then ( if (GenBranches.checked and (i == 2)) or ((i == 1) and (CObj == CTrunk)) do ( status1.text = "Calculating object information..." cw = CObj.wirecolor OriginalMat = copy CObj.mat -- setup Area object info for tracking AreaKey = "" if GameArea.selection == 1 do (AreaKey = "BE") if GameArea.selection == 2 do (AreaKey = "JR") if GameArea.selection == 3 do (AreaKey = "PH") if GameArea.selection == 4 do (AreaKey = "IJ") if GameArea.selection == 5 do (AreaKey = "TO") if GameArea.selection == 6 do (AreaKey = "PL") if GameArea.selection == 7 do (AreaKey = "PV") if GameArea.selection == 8 do (AreaKey = "SH") if GameArea.selection == 9 do (AreaKey = "LA") if GameArea.selection == 10 do (AreaKey = "AS") if GameArea.selection == 11 do (AreaKey = "SU") -- DL is the detail level DL = (DRLevel.value as integer) as string if renderSeperate.checked and i == 2 do DL = (BranchDRLevel.value as integer) as string -- initialize some arrays BitMapArray = #() OpacityMapArray = #() DRObjectsArray = #() -- Set the Background color to black backgroundColor = (color 0 0 0) -- grab and set the Ambient light color to what's specified in the interface AmbientColor = AmbientCol.color -- setup field of vision fov = 10 CObjSize = (CObj.max - CObj.min) -- if center to base is checked, we determine the center of the lowest set of -- vertices in the mesh (the bottom of the trunk) and set the x,y center position to that. -- This way, we can make sure that the base of the trunk in each image view lies at the same position. -- Otherwise, we just use the object center ObjCenter = CObj.center theta = fov offsetHeight = false -- here, we find the largest distance of either the height, -- or the distance between the x,y coordinates of the .min and .max (thus the maximun diameter) if (distance [CObj.max.x,CObj.max.y] [CObj.min.x,CObj.min.y]) > (CObj.max.z - CObj.min.z) then ( d = (distance [CObj.max.x,CObj.max.y] [CObj.min.x,CObj.min.y]) offsetHeight = true if debug do format "Using objects maximum DIAMETER for largest dimension...\n" ) else ( d = (CObj.max.z - CObj.min.z) if debug do format "Using objects maximum HEIGHT for largest dimension...\n" ) status1.text = "Calculating Camera..." -- setup the camera and it's position so that the object lies square in it's viewport h = (d / (2 * sin(theta / 2))) x = h * (cos(theta)) NewCamera = targetCamera() NewCamera.fov = fov NewCamera.target = targetObject() NewCamera.target.pos = ObjCenter -- Set the camera direction as the light direction NewDir = SunArray[GameArea.selection] -- NewDir = normalize [NewDir.x, NewDir.y,0] NewCamera.pos = NewCamera.target.pos + NewDir * x CameraDist = (distance NewCamera.pos Newcamera.target.pos) BoxDimension = ((CameraDist * (tan(fov * 0.5))) * 2) BitMapSizeValue = BitMapSize.value as integer -- generate the texturemap - this will (should) never be seen so we'll make it bright red. TMap = CreateBitmap BitMapSizeValue BitMapSizeValue (color 20 77 12) -- prep the materials for opacity map rendering if classof CObj.mat == StandardMaterial do ( CObj.mat.diffuse = (color 255 255 255) CObj.mat.DiffuseMapEnable = false CObj.mat.BumpMapEnable = false CObj.mat.shinestrength = 0.0 CObj.mat.selfIllum = 100 ) if classof CObj.mat == multiMaterial do ( ns = CObj.mat.numsubs for j = 1 to ns do ( CObj.mat[j].diffuse = (color 255 255 255) CObj.mat[j].DiffuseMapEnable = false CObj.mat[j].BumpMapEnable = false CObj.mat[j].shinestrength = 0.0 CObj.mat[j].selfIllum = 100 ) ) -- render the opacity map OpacityMap = (render camera:NewCamera outputwidth:BitMapSizeValue outputheight:BitMapSizeValue vfb:off) CObj.mat = OriginalMat if classof CObj.mat == StandardMaterial do ( CObj.mat.DiffuseMapEnable = true CObj.mat.BumpMapEnable = true CObj.mat.shinestrength = 0.0 CObj.mat.selfIllum = 0.0 ) if classof CObj.mat == multiMaterial do ( ns = CObj.mat.numsubs for j = 1 to ns do ( CObj.mat[j].DiffuseMapEnable = true CObj.mat[j].BumpMapEnable = true CObj.mat[j].shinestrength = 0.0 CObj.mat[j].selfIllum = 0.0 ) ) CNamePrefix = "" CNameSuffix = "" DetailReductionLevel = 5 for j = 1 to CObj.name.count do if CObj.name[j] == "~" do MagicIndex = j if MagicIndex != undefined then ( CNamePrefix = substring CObj.name 1 (MagicIndex - 1) CNameSuffix = ((substring CObj.name (MagicIndex + 1) 3) + (DetailReductionLevel as string)) ) else ( for j = 1 to CObj.name.count do if CObj.name[j] == "-" do MagicIndex = j if magicIndex == undefined do MagicIndex = CObj.name.count CNamePrefix = substring CObj.name 1 (MagicIndex - 1) CNameSuffix = ((substring CObj.name (MagicIndex + 1) 3) + (DetailReductionLevel as string)) ) -- ************************************************************ -- ** Process the bitmaps ************************************* -- ************************************************************ -- process the bitmaps for size/scale if debug do format "Processing Bitmaps...\n" BitmapInfo = ThresholdBitmap OpacityMap (OpacityThresh.value as integer) if debug do ( format "%\n" BitmapInfo display OpacityMap ) -- calculate the width and height scalar values for the geometry based on the new cropped areas WidthScalar = BitmapInfo[3].x as float / OpacityMap.width HeightScalar = BitmapInfo[3].y as float / OpacityMap.height -- crop the bitmaps -- OpacityMap = CropBitmap BitmapInfo[1] BitmapInfo[2] BitmapInfo[3] -- TMap = CropBitmap TMap BitmapInfo[2] BitmapInfo[3] OpacityMap = CropBitmap BitmapInfo[1] BitmapInfo[2] [(BitmapInfo[3].x), BitmapInfo[3].y] TMap = CropBitmap TMap BitmapInfo[2] [(BitmapInfo[3].x), BitmapInfo[3].y] NewBitMapHeight = BitmapInfo[3].y NewBitMapWidth = BitmapInfo[3].x -- Extra checking for illegal map sizes (> 256, < 8) if NewBitMapHeight > 256 do NewBitMapHeight = 256 if NewBitMapWidth > 256 do NewBitMapWidth = 256 if NewBitMapHeight < 8 do NewBitMapHeight = 8 if NewBitMapWidth < 8 do NewBitMapWidth = 8 if RescaleBitmaps.checked do ( reCalc = true if (i == 2 and BranchOverRideBitmapSize.checked) do ( NewBitMapWidth = BranchWidthOveride.value NewBitMapHeight = BranchHeightOveride.value reCalc = false ) if (OverRideBitmapSize.checked and (i == 1) and (CObj == CTrunk)) do ( NewBitMapWidth = TrunkWidthOveride.value NewBitMapHeight = TrunkHeightOveride.value reCalc = false ) if reCalc == true do ( -- calculate the new bitmap dimensions to the nearest power of two size NewBitMapWidth = NearPowOfTwo NewBitMapWidth sizeMaps.state NewBitMapHeight = NearPowOfTwo NewBitMapHeight sizeMaps.state NSize = (PowOfLimit NewBitMapWidth NewBitMapHeight) NewBitMapWidth = NSize.x as integer NewBitMapHeight = NSize.y as integer ) ) if debug do format "Initial BitmapSize: %\t%\nNew Bitmap size: %\t%\n" BitmapInfo[3].x BitmapInfo[3].y NewBitMapWidth NewBitMapHeight FinalOpName = (WorkingFolder + CNamePrefix + "5~" + CNameSuffix + "o8.bmp") FinalTexName = (WorkingFolder + CNamePrefix + "5~" + CNameSuffix + "t2.bmp") InTexName = (WorkingFolder + "t5.bmp") OutTexName = (WorkingFolder + "t_5.bmp") InOpName = (WorkingFolder + "o5.bmp") OutOpName = (WorkingFolder + "o_5.bmp") -- set the filenames... NewOp = bitmap NewBitMapWidth NewBitMapHeight NewTex = bitmap NewBitMapWidth NewBitMapHeight if debug do format "Bitmap Size: % %\n" NewBitMapWidth NewBitMapHeight try ( copy OpacityMap NewOp copy TMap NewTex ) catch ( MessageBox "Something fucked up.\nGo get Kyle." ) -- Start the Graham's Scan -- Identify all the edge pixels status1.text = "Identifying Edges...." p = IdentifyEdges NewOp YIncrement.value -- add some random jitter to the array of points so the angle array will sort properly aj = AngleJitter.value for j = 1 to p.count do ( if p[j].x == 0 do (p[j].x += (random 0 aj)) if p[j].y == 0 do (p[j].y += (random 0 aj)) if p[j].x == NewOp.width do (p[j].x += (random -aj 0)) if p[j].y == NewOp.height do (p[j].y += (random -aj 0)) if p[j].x < NewOp.width and p[j].x > 0 do (p[j].x += (random -aj aj)) if p[j].y < NewOp.height and p[j].y > 0 do (p[j].y += (random -aj aj)) ) -- do the Graham Scan status1.text = "Calculating convex hull..." Hullpoints = GrahamScan p -- remove the jitter to the array of points are integers again for j = 1 to Hullpoints.count do (Hullpoints[j] = [(rnd Hullpoints[j].x), (rnd Hullpoints[j].y)]) status1.text = "Reducing Points..." HullPoints = pruneClosePoints HullPoints PrunePointsThreshold.value NewOp.filename = InOpName NewTex.filename = InTexName -- Delete the files (if they're already there) DeleteFile NewOp.filename DeleteFile NewTex.filename -- and save them... save NewTex save NewOp -- if debug do format "Starting Alchemy...\n" -- Process Maps via Alchemy doscommand ("alchemy -w -o -b " + InOpName + " " + OutOpName) doscommand ("alchemy -w -o " + InTexName + " " + OutTexName) if debug do format "Alchemy Done!...\nProcessing Bitmaps Finished!\n" -- Delete files that may already be there deleteFile FinalOpName deleteFile FinalTexName -- Copy the processed bitmaps to their final name/location copyFile OutOpName FinalOpName copyFile OutTexName FinalTexName -- ************************************************************ -- ** Create the new mesh ************************************* -- ************************************************************ if debug do format "Building Geometry...\n" -- calculate the new uv's for Hullpoints status1.text = "Calculating Texture Vertices..." minX = HullPoints[1].x maxX = HullPoints[1].x minY = HullPoints[1].y maxY = HullPoints[1].y for i = 1 to HullPoints.count do ( if HullPoints[i].x > maxX do maxX = HullPoints[i].x if HullPoints[i].x < minX do minX = HullPoints[i].x if HullPoints[i].y > maxY do maxY = HullPoints[i].y if HullPoints[i].y < minY do minY = HullPoints[i].y ) iWidth = maxX - minX iHeight = maxY - minY iDimension = [iWidth, iHeight] iCorner = [minX, minY] du = 1.0 / iWidth dv = 1.0 / iHeight -- flip all the y points for j = 1 to Hullpoints.count do (Hullpoints[j].y = iHeight - Hullpoints[j].y) TVertArray = #() for j = 1 to Hullpoints.count do ( Tvert = [(HullPoints[j].x * du), (HullPoints[j].y * dv),1.0] append TVertArray Tvert ) BoxDimension = ((distance NewCamera.pos NewCamera.target.pos) * (tan(fov * 0.5))) * 2 PixelSize = (BoxDimension as float / BitMapSizeValue as float) if debug do format "PixelSize:%\n" PixelSize -- calculate the width and height offsets for the new geometry w1 = BitmapInfo[2].x w2 = BitmapInfo[1].width - (w1 + BitmapInfo[3].x) AvgFreeWidth = (BitmapInfo[1].width - BitmapInfo[3].x) * 0.5 if w2 >= w1 then ObjectOffsetW = (AvgFreeWidth - w1) * PixelSize else ObjectOffsetW = -(AvgFreeWidth - w2) * PixelSize h1 = BitmapInfo[2].y h2 = BitmapInfo[1].height - (h1 + BitmapInfo[3].y) AvgFreeHeight = (BitmapInfo[1].height - BitmapInfo[3].y) * 0.5 if h2 >= h1 then ObjectOffsetV = (AvgFreeHeight - h1) * PixelSize else ObjectOffsetV = -(AvgFreeHeight - h2) * PixelSize if debug do ( format "w1:% w2:% h1:% h2:%\n" w1 w2 h1 h2 format "Height Offset:%\nWidth Offset:%\nAvg Free: % %\n" ObjectOffsetV ObjectOffsetW AvgFreeWidth AvgFreeHeight ) NewHeight = BoxDimension as float * HeightScalar NewWidth = BoxDimension as float * WidthScalar b = box() b.width = NewWidth b.height = BoxDimension b.length = NewHeight b.pos = NewCamera.target.pos b.dir = -NewCamera.dir if debug do format "Camera Dir vector @ %: %\n" t -NewCamera.dir b.mapcoords = true convertToMesh b for j = 1 to 4 do deleteVert b b.numverts if NewCamera.dir.x < 0.0 do in coordsys local rotate b 180 z_axis in coordsys local rotate b 180 z_axis in coordsys local move b [ObjectOffsetW, ObjectOffsetV, 0] -- flip the UV's along U if (getTvert b 4).x == 0.0 do for j = 1 to b.numtverts do ( CTvert = (getTvert b j) if CTvert.x == 1.0 then CTvert.x = 0.0 else if CTvert.x == 0.0 do (CTvert.x = 1.0) setTvert b j CTvert ) update b -- Calculate the new points in 3space via the uv coordinates P0 = getVert b 2 P1 = getVert b 1 P2 = getVert b 4 P3 = getVert b 3 fVertArray = #() for j = 1 to TVertArray.count do ( Px = (P0.x + (TVertArray[j].x * (P1.x - P0.x)) + (TVertArray[j].y * (P2.x - P0.x))) Py = (P0.y + (TVertArray[j].x * (P1.y - P0.y)) + (TVertArray[j].y * (P2.y - P0.y))) Pz = (P0.z + (TVertArray[j].x * (P1.z - P0.z)) + (TVertArray[j].y * (P2.z - P0.z))) append fVertArray [Px,Py,Pz] ) iFaceArray = #([1,2,3]) for i = 3 to (Hullpoints.count - 1) do (append iFaceArray [1,i,i+1]) -- construct the mesh delete b b = mesh vertices:fVertArray faces:iFaceArray if b.numverts > 16 do (format "Warning: more than 16 verts detected in convex hull object... please check and regenerate if needed...\n") -- apply the texture coordinates addmodifier b (UVWMap()) convertToMesh b for i = 1 to b.numfaces do ( iFace = getFace b i iTFace = getTVFace b i setTvert b iTFace.x (TVertArray[iFace.x]) setTvert b iTFace.y (TVertArray[iFace.y]) setTvert b iTFace.z (TVertArray[iFace.z]) ) -- Set the Edge visibility for i = 1 to b.numfaces do ( if i == 1 do setEdgeVis b i 3 off if i == b.numfaces do setEdgeVis b i 1 off if i > 1 and i < b.numfaces do ( SetEdgeVis b i 1 off SetEdgeVis b i 3 off ) ) update b df = #() for i = 1 to b.numfaces do ( Cface = getface b i n = 4 NewX = rndP3 (getvert b Cface.x) n NewY = rndP3 (getvert b Cface.y) n NewZ = rndP3 (getvert b Cface.z) n if (Thresh NewX NewY 0.001) do if findItem df i == 0 do (append df i) if (Thresh NewX NewZ 0.001) do if findItem df i == 0 do (append df i) if (Thresh NewZ NewY 0.001) do if findItem df i == 0 do (append df i) -- check for a degenerate normal if (GetFaceNormal b i) == [0,0,0] do if findItem df i == 0 do (append df i) ) if df.count > 0 do ( format "found degenerate polygons... deleting them\n" for i = df.count to 1 by -1 do deleteFace b df[i] update b ) -- Check for Stray Vertices StrayVertArray = (for i = 1 to b.numverts collect i) UsedVerts = #() NewVertSelection = #() for i = 1 to b.numfaces do ( CFace = (getface b i) if (findItem UsedVerts CFace.x) == 0 do (append UsedVerts CFace.x) if (findItem UsedVerts CFace.y) == 0 do (append UsedVerts CFace.y) if (findItem UsedVerts CFace.z) == 0 do (append UsedVerts CFace.z) ) for i = 1 to StrayVertArray.count do if (findItem UsedVerts i) == 0 do (append NewVertSelection i) if NewVertSelection.count > 0 then ( format "Stray vertices were found... deleting them\n" for i = NewVertSelection.count to 1 by -1 do deleteVert b NewVertSelection[i] update b ) if debug do format "Geometry done!\n" -- ************************************************************ -- ** Generate a new material -- ************************************************************ -- make sure all face IDs are set to 1 if debug do format "Building new material...\n" for j = 1 to b.numfaces do setFaceMatID b j 1 NMat = standardMaterial() -- give it a random color NMat.diffuse = random (color 20 20 20) (color 220 220 220) NMat.diffuseMap = bitmaptexture() NMat.OpacityMap = bitmaptexture() -- specify the bitmap names NMat.diffuseMap.filename = FinalTexName NMat.OpacityMap.filename = FinalOpName NMat.shinestrength = 0.0 NMat.name = substring OutTexName 1 (OutTexName.count - 3) NMat.selfIllum = 100 b.mat = NMat if debug do format "Finished building new material!\n" b.wirecolor = scaleColor cw 0.3 b.name = ("$" + (substring CObj.name 1 (CObj.name.count - 4)) + "5-00") b.pivot = CObj.pivot if debug != true do ( delete NewCamera NewCamera = undefined ) CObj.mat = OriginalMat ) ) else ( if renderSeperate.checked do MessageBox "No Objects Defined!" ) gc() -- collect some garbage ) ) -- Lonnie, comment the next line out "--" -- if SingleObject == true do delete CTrunk delete CTrunk if CBranches != undefined do delete CBranches -- unhide everything at the end... for o in objects do unhide o CTrunk = CBranches = undefined ) else ( MessageBox "You must initialize the objects first" ) ) ) on DRRollout open do ( MagicIndex = undefined offsetHeight = false HeightOffset = 0.0 ) ) -- ****************************************************************************************************************************** -- * Utility Open -- ****************************************************************************************************************************** on DetailReduction open do ( if flip == undefined do global flip = false if (getfiles "C:\DR.txt").count == 0 then ( if (WorkingFolder = (GetSavePath caption:"Select the location of a temporary folder to use for keeping texturemaps")) != undefined do ( f = createfile "C:\DR.txt" openfile "DR.txt" WorkingFolder = (WorkingFolder + "\\") format ("Working Location: " + WorkingFolder) to:f close f format "Working Folder initialized to: %\n" WorkingFolder ) ) else ( f = openfile "C:\DR.txt" CLine = readline f for i = 1 to CLine.count do ( if cLine[i] == ":" do ( WorkingFolder = (substring CLine (i + 2) (CLine.count - i - 1)) if substring WorkingFolder WorkingFolder.count 1 != "\\" do WorkingFolder = WorkingFolder + "\\" format "Working Location initialized to: %\n" WorkingFolder Exit ) ) close f ) Flt = NewRolloutFloater "Detail Reduction v 1.5.2" 400 745 800 200 addrollout DRRollout Flt gc() ) on DetailReduction close do closeRolloutFloater Flt label DRLabel1 "Detail Reduction" label DRLabel2 "v 1.5.2, 7.14.98" )