440 lines
13 KiB
Plaintext
Executable File
440 lines
13 KiB
Plaintext
Executable File
--
|
|
-- File:: rockstar/helpers/environmentmap.ms
|
|
-- Description:: Rockstar Cubic Reflection Map Generator
|
|
-- Render a cubic reflection map for the selected object. Also includes functionality for previewing a
|
|
-- render of any the of the sides of the "cube".
|
|
--
|
|
-- Author:: Luke Openshaw <luke.openshaw@rockstarnorth.com
|
|
-- Date:: 14/10/2005
|
|
--
|
|
-----------------------------------------------------------------------------
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- Uses
|
|
-----------------------------------------------------------------------------
|
|
filein "pipeline/util/file.ms"
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- Rollout
|
|
-----------------------------------------------------------------------------
|
|
rollout RsReflMapRoll "Cubic Reflection Map"
|
|
(
|
|
--////////////////////////////////////////////////////////////
|
|
-- interface
|
|
--////////////////////////////////////////////////////////////
|
|
hyperlink lnkHelp "Help?" address:"https://devstar.rockstargames.com/wiki/index.php/Environment_Map_Generator" align:#right color:(color 0 0 255) hoverColor:(color 0 0 255) visitedColor:(color 0 0 255)
|
|
|
|
spinner spnFOV "Field of View" pos:[190,30] width:80 range:[0,180,90]
|
|
spinner spnMult "Z Position" pos:[190,60] width:80 range:[0,1,0]
|
|
dropdownlist lstResol "Resolution:" pos:[40,10] items:#("256", "128") width:80
|
|
groupBox grp5 "Preview" pos:[10,90] width:290 height:91
|
|
dropdownlist lstAxis "Axis:" pos:[45,110] items:#("X-Pos", "X-Neg", "Y-Pos", "Y-Neg", "Z-Pos", "Z-Neg") width:100
|
|
button btnPreview "Preview Axis" pos:[160,125] width:110 height:30
|
|
groupBox grp6 "Generate" pos:[10,190] width:290 height:91
|
|
edittext edtOutPath "Output Directory:" pos:[15,210] text:"x:\\"
|
|
button btnRender "Generate Cubic Map" pos:[90,240] width:110 height:30
|
|
|
|
|
|
|
|
|
|
--////////////////////////////////////////////////////////////
|
|
-- methods
|
|
--////////////////////////////////////////////////////////////
|
|
|
|
--------------------------------------------------------------
|
|
-- Create the script to be passed to dxops.exe
|
|
--------------------------------------------------------------
|
|
fn WriteCubeScript inPath mapRes = (
|
|
|
|
|
|
ddsFileName = inPath + "cubeScript.txt"
|
|
|
|
ddsFile = openfile ddsFileName mode:"w+"
|
|
|
|
format ("load '" + inPath + "*.bmp';\n") to:ddsFile
|
|
format ("newtexcube dst:newEnvironmentMap format:DXT5 size:" + mapRes as string + " Mips:1 srcXP:XPositive srcXM:XNegative srcYP:YPositive srcYM:YNegative srcZP:ZPositive srcZM:ZNegative;\n") to:ddsFile
|
|
format ("save src:newEnvironmentMap filename:'" + inPath + "cubemap.dds';\n") to:ddsFile
|
|
|
|
close ddsFile
|
|
|
|
return true
|
|
)
|
|
|
|
--------------------------------------------------------------
|
|
-- Calculate the geometric aveage of the selected object
|
|
--------------------------------------------------------------
|
|
fn CalcGeoAvg obj = (
|
|
|
|
numFace = getNumFaces obj.mesh
|
|
|
|
geoAvg = [0,0,0]
|
|
curVec = [0,0,0]
|
|
|
|
|
|
-- Find the geometric average of all vertices in the selected object
|
|
for i = 1 to numFace do (
|
|
curFace = getface obj.mesh i
|
|
for j = 1 to 3 do (
|
|
curVec = obj.mesh.verts[curFace[j]].pos * obj.transform
|
|
geoAvg += curVec
|
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
|
|
geoAvg = geoAvg / (numFace * 3)
|
|
|
|
return geoAvg
|
|
)
|
|
|
|
fn CalcZPos obj multiplier = (
|
|
numFace = getNumFaces obj.mesh
|
|
|
|
|
|
zMin = 1000000
|
|
zMax = -1000000
|
|
|
|
-- Find the geometric average of all vertices in the selected object
|
|
for i = 1 to numFace do (
|
|
curFace = getface obj.mesh i
|
|
for j = 1 to 3 do (
|
|
curVec = obj.mesh.verts[curFace[j]].pos * obj.transform
|
|
|
|
if curVec.z < zMin then zMin = curVec.z
|
|
if curVec.z > zMax then zMax = curVec.z
|
|
)
|
|
)
|
|
|
|
print zMin
|
|
print zMax
|
|
print multiplier
|
|
|
|
return (zMin + ((zMax - zMin) * multiplier))
|
|
|
|
)
|
|
|
|
--------------------------------------------------------------
|
|
-- Create the render camera
|
|
--------------------------------------------------------------
|
|
fn CreateCamera geoAvg = (
|
|
tempObj = box length:1 width:1 height:1
|
|
hide tempObj
|
|
|
|
fovVal = spnFOV.value as float
|
|
|
|
newCam = targetCamera pos:[0,0,0] target:tempObj fov:fovVal
|
|
newcam.name = "renderCam"
|
|
newCam.pos = geoAvg
|
|
|
|
return true
|
|
)
|
|
|
|
--------------------------------------------------------------
|
|
-- Delete the render camera
|
|
--------------------------------------------------------------
|
|
fn DeleteCamera = (
|
|
|
|
delete $renderCam
|
|
return true
|
|
)
|
|
|
|
--------------------------------------------------------------
|
|
-- Render an image from the render camera
|
|
--------------------------------------------------------------
|
|
fn RenderOutput geoAvg dirVec mapRes vfbVal preCamRot postCamRot= (
|
|
$renderCam.target.pos = geoAvg + dirVec
|
|
rotate $renderCam preCamRot
|
|
renderObj = render camera:$renderCam outputwidth:mapRes outputheight:mapRes mapping:true shadows:false vfb:vfbVal
|
|
rotate $renderCam postCamRot
|
|
|
|
return renderObj
|
|
)
|
|
|
|
--------------------------------------------------------------
|
|
-- Ensure one and only one object has been selected.
|
|
--------------------------------------------------------------
|
|
fn ValidateSelection = (
|
|
|
|
sel = selection as array
|
|
|
|
if sel.count == 0 then (
|
|
messagebox "No object has been selected"
|
|
return false
|
|
)
|
|
|
|
if sel.count > 1 then (
|
|
messagebox "More than one object is selected"
|
|
return false
|
|
)
|
|
|
|
if outPath == "" then (
|
|
messagebox "Please provide an output path"
|
|
return false
|
|
)
|
|
|
|
return true
|
|
)
|
|
|
|
--------------------------------------------------------------
|
|
-- Render the preview for the selected axis
|
|
--------------------------------------------------------------
|
|
fn RenderPreview = (
|
|
|
|
sel = selection as array
|
|
|
|
obj = sel[1]
|
|
|
|
axis = lstAxis.selected
|
|
mapRes = lstResol.selected as integer
|
|
|
|
preCamRot = eulerangles 0 0 0
|
|
postCamRot = eulerangles 0 0 0
|
|
|
|
multiplier = spnMult.value as float
|
|
|
|
geoAvg = CalcGeoAvg obj
|
|
zPos = CalcZPos obj multiplier
|
|
geoAvg.z = zPos
|
|
hide obj
|
|
|
|
if CreateCamera geoAvg == false then return false
|
|
|
|
|
|
if axis == "X-Pos" then (
|
|
RenderOutput geoAvg [10,0,0] mapRes true preCamRot postCamRot
|
|
)
|
|
else if axis == "X-Neg" then (
|
|
RenderOutput geoAvg [-10,0,0] mapRes true preCamRot postCamRot
|
|
)
|
|
else if axis == "Y-Pos" then (
|
|
RenderOutput geoAvg [0,10,0] mapRes true preCamRot postCamRot
|
|
)
|
|
else if axis == "Y-Neg" then (
|
|
RenderOutput geoAvg [0,-10,0] mapRes true preCamRot postCamRot
|
|
)
|
|
else if axis == "Z-Pos" then (
|
|
RenderOutput geoAvg [0,0,10] mapRes true preCamRot postCamRot
|
|
)
|
|
else if axis == "Z-Neg" then (
|
|
RenderOutput geoAvg [0,0,-10] mapRes true preCamRot postCamRot
|
|
)
|
|
|
|
unhide obj
|
|
|
|
if DeleteCamera() == false then return false
|
|
return true
|
|
)
|
|
|
|
--------------------------------------------------------------
|
|
-- Function for reversing the contents of an array
|
|
--------------------------------------------------------------
|
|
fn ReverseArray bitmapArr res = (
|
|
arrRev = #()
|
|
for i = 1 to res do (
|
|
arrRev[i] = bitmapArr[res-(i-1)]
|
|
)
|
|
|
|
|
|
return arrRev
|
|
)
|
|
|
|
--------------------------------------------------------------
|
|
-- Flip the bitmap provided horizontally
|
|
--------------------------------------------------------------
|
|
fn FlipBitmapHoriz bitmapPath res = (
|
|
|
|
bitmapObj = openBitmap bitmapPath
|
|
bitmapObjW = bitmap 256 256
|
|
for i = 1 to 256 do (
|
|
|
|
|
|
bitmapArr = #()
|
|
bitmapArr = getPixels bitmapObj [0,i-1] res
|
|
|
|
--if i==256 then print bitmapArr
|
|
bitmapRev = ReverseArray bitmapArr res
|
|
--print bitmapRev[1]
|
|
|
|
|
|
setPixels bitmapObjW [0,i-1] bitmapRev
|
|
|
|
|
|
)
|
|
|
|
bitmapObjW.filename = bitmapPath
|
|
save bitmapObjW
|
|
close bitmapObjW
|
|
|
|
return true
|
|
)
|
|
|
|
--------------------------------------------------------------
|
|
-- Flip the bitmap provided vertically
|
|
--------------------------------------------------------------
|
|
|
|
fn FlipBitmapVert bitmapPath res = (
|
|
bitmapObj = openBitmap bitmapPath
|
|
bitmapObjW = bitmap 256 256
|
|
for i = 1 to 256 do (
|
|
|
|
|
|
bitmapArr = #()
|
|
bitmapArr = getPixels bitmapObj [0,i-1] res
|
|
|
|
|
|
|
|
setPixels bitmapObjW [0,res-(i-1)] bitmapArr
|
|
|
|
|
|
)
|
|
|
|
bitmapObjW.filename = bitmapPath
|
|
save bitmapObjW
|
|
close bitmapObjW
|
|
|
|
return true
|
|
|
|
)
|
|
|
|
--------------------------------------------------------------
|
|
-- Render the six views that make up the cubemap.
|
|
--------------------------------------------------------------
|
|
fn RenderViews = (
|
|
|
|
|
|
outPath = edtOutpath.text
|
|
fovVal = spnFOV.value as float
|
|
outPath = outPath + "\\"
|
|
RsMakeSurePathExists outPath
|
|
|
|
sel = selection as array
|
|
|
|
|
|
obj = sel[1]
|
|
numFace = getNumFaces obj.mesh
|
|
mapRes = lstResol.selected as integer
|
|
|
|
geoAvg = CalcGeoAvg obj
|
|
|
|
CreateCamera geoAvg
|
|
|
|
hide obj
|
|
|
|
-- Positive X-axis render
|
|
preCamRot = eulerangles -90 0 0
|
|
postCamRot = eulerangles 90 0 0
|
|
renderObj = RenderOutput geoAvg [10,0,0] mapRes false preCamRot postCamRot
|
|
renderObj.filename = outPath + "XPositive.bmp"
|
|
save renderObj
|
|
if FlipBitmapVert renderObj.filename mapRes == false then return false
|
|
|
|
-- Negative X-axis render
|
|
preCamRot = eulerangles -90 0 0
|
|
postCamRot = eulerangles 90 0 0
|
|
renderObj = RenderOutput geoAvg [-10,0,0] mapRes false preCamRot postCamRot
|
|
renderObj.filename = outPath + "XNegative.bmp"
|
|
save renderObj
|
|
if FlipBitmapVert renderObj.filename mapRes == false then return false
|
|
|
|
|
|
-- Positive Y-axis render
|
|
preCamRot = eulerangles 0 180 0
|
|
postCamRot = eulerangles 0 -180 0
|
|
renderObj = RenderOutput geoAvg [0,10,0] mapRes false preCamRot postCamRot
|
|
renderObj.filename = outPath + "YPositive.bmp"
|
|
save renderObj
|
|
if FlipBitmapHoriz renderObj.filename mapRes == false then return false
|
|
|
|
-- Negative Y-axis render
|
|
preCamRot = eulerangles 0 0 0
|
|
postCamRot = eulerangles 0 0 0
|
|
renderObj = RenderOutput geoAvg [0,-10,0] mapRes false preCamRot postCamRot
|
|
renderObj.filename = outPath + "YNegative.bmp"
|
|
save renderObj
|
|
if FlipBitmapHoriz renderObj.filename mapRes == false then return false
|
|
|
|
-- Positive Z-axis render
|
|
preCamRot = eulerangles 0 0 180
|
|
postCamRot = eulerangles 0 0 -180
|
|
renderObj = RenderOutput geoAvg [0,0,10] mapRes false preCamRot postCamRot
|
|
renderObj.filename = outPath + "ZPositive.bmp"
|
|
save renderObj
|
|
if FlipBitmapHoriz renderObj.filename mapRes == false then return false
|
|
|
|
-- Negative Z-axis render
|
|
preCamRot = eulerangles 0 0 0
|
|
postCamRot = eulerangles 0 0 0
|
|
renderObj = RenderOutput geoAvg [0,0,-10] mapRes false preCamRot postCamRot
|
|
renderObj.filename = outPath + "ZNegative.bmp"
|
|
save renderObj
|
|
if FlipBitmapHoriz renderObj.filename mapRes == false then return false
|
|
|
|
-- This also deletes the tempObj object used
|
|
-- for providing the camera an initial target object
|
|
DeleteCamera()
|
|
|
|
unhide obj
|
|
|
|
|
|
|
|
if WriteCubeScript outPath mapRes == false then return false
|
|
|
|
dosString = "-f \"" + outPath + "cubeScript.txt\""
|
|
--ShellLaunch "C:\\Program Files\\Microsoft DirectX 9.0 SDK (October 2005)\\Utilities\\Bin\\x86\\dxops.exe" dosString
|
|
dosString = "dxops.exe " + dosString
|
|
DOSCommand dosString
|
|
--DOSCommand ("C:\\Program Files\\Microsoft DirectX 9.0 SDK (October 2005)\\Utilities\\Bin\\x86\\dxops.exe " + dosString)
|
|
|
|
dosString = "del " + outPath + "*p"
|
|
DOSCommand dosString
|
|
dosString = "del " + outPath + "*t"
|
|
DOSCommand dosString
|
|
|
|
|
|
return true
|
|
)
|
|
|
|
|
|
|
|
|
|
--////////////////////////////////////////////////////////////
|
|
-- events
|
|
--////////////////////////////////////////////////////////////
|
|
|
|
--------------------------------------------------------------
|
|
-- Render Cubemap button pressed.
|
|
--------------------------------------------------------------
|
|
on btnRender pressed do (
|
|
|
|
if edtOutpath.text == "" then (
|
|
messagebox "Please enter a directory for output"
|
|
return false
|
|
)
|
|
if ValidateSelection() == false then return false
|
|
if RenderViews() == false then return false
|
|
|
|
return true
|
|
)
|
|
|
|
--------------------------------------------------------------
|
|
-- Render Preview.
|
|
--------------------------------------------------------------
|
|
on btnPreview pressed do (
|
|
|
|
|
|
--if ValidateSelection() == false then return false
|
|
if RenderPreview() == false then return false
|
|
|
|
return true
|
|
)
|
|
|
|
)
|
|
|
|
--------------------------------------------------------------
|
|
-- beginning of execution
|
|
--------------------------------------------------------------
|
|
try CloseRolloutFloater RsReflMap catch()
|
|
RsReflMap = newRolloutFloater "Environment Map Generator" 320 320 100 206
|
|
addRollout RsReflMapRoll RsReflMap |