PROBLEM SOLVED =) Thanks to the idea from Mr. Green Gandalf, I am using "two" maps for my level instead of just one. The main map data is stored in the .CSM file, whereas mesh information (with normals!) is stored in a .X file that I also export from Cartography Shop.
Through much research - and Mr Gandalf's note that the geometry from the CSM map is slightly farked when it comes to normal lights - I started looking for a solution to combine the two together.
STEPS
PREFACE:
* Use Apex Now's CSM Loader to grab the data from the CSM files
* Download IanM's Cartography Shop Export Plugin and install it
CSM INSTRUCTIONS:
* Decide which objects in your map should be dynamically lighted at runtime. You must attach a pivot entity to these meshes, as well as record a flag somewhere - that you will parse in your own methods later - in that pivot stating that the mesh will be replaced later
* Save the map to a CSM as you normally would.
* Save a copy of this map to a new file. Delete all objects that won't be dynamically lighted at runtime.
* Export this map as a Matrix1 .X file.
DB PRO INSTRUCTIONS:
*Load up the .X file somewhere. Make a new object from each limb. I put rediculously high numbers here to prevent object number collisions.
REM this number holds the initial X-file.
REM child limbs from this file will be held at n+1, or default starting at 1000000
#constant CSM_X = 999999
load object "csm_map_exported.x", CSM_X
for i = 1 to get limb count(CSM_X)
make object from limb CSM_X + i, CSM_X, i, 0
calculate object bounds CSM_X + i
hide object CSM_X + i
next i
REM we no longer need this object as we've already made meshes from its limbs
delete object CSM_X
*Load up your CSM map. Parse your entities, and this is where the real magic happens.
REM this sample is based off of the CSM Import demo. Apply to your own needs.
REM "pivotTagMesh" is just the name of the property I used to determine whether or not the mesh will be replaced with one from the .X
REM loop through all of the entities
for i = 0 to nCounts(2) - 1
REM make sure that this entity is a pivot entity
If Upper$(CSM PROPERTY BY KEY( CSM_ENTITY, i, "classname" )) = "PIVOT"
REM make sure that this pivot entity's mesh needs to be dynamically lighted at runtime
If CSM PROPERTY BY KEY( CSM_ENTITY, i, "Name" ) = "pivotTagMesh"
REM get the DarkBasic Pro object media number for this mesh.
nMeshID = CSM GROUP TO OBJECT(CSM ENTITY TO GROUP(i))
REM declare local variables for doing maths
local tX#
local tY#
local tZ#
REM calculate object bounds for this mesh
REM we need to do this to figure out where it is in the map, in relation to the .X file limb
calculate object bounds nMeshID
REM as the limbs in the .X file are all positioned at 0, 0, 0, we need to figure out how put which limb to where.
REM this is where the magic starts, as the limbs in the .X file all have a position of 0, 0, 0.
REM
REM I noticed that the object collision center of a limb in an X file equals the object collision center and object position
REM from the equivelent mesh in the CSM file.
tX# = object position x(nMeshID) + object collision center x(nMeshID)
tY# = object position y(nMeshID) + object collision center y(nMeshID)
tZ# = object position z(nMeshID) + object collision center z(nMeshID)
REM loop through all object limbs we made earlier.
REM if this errors out, its because I screwed up the upper bound. Try getting rid of the -1. =3
for j = (CSM_X + 1) to (get limb count(CSM_X) - 1)
REM verify which mesh is which.
if object collision center x(j) = tX# and object collision center y(j) = tY# and object collision center Z(j) = tZ#
REM now we need to offset the selected .X limb so it matches the position and offset of the one in the CSM
tPosX# = object position x(nMeshID)
tPosY# = object position y(nMeshID)
tPosZ# = object position z(nMeshID)
REM delete the CSM object, as we're replacing it
delete object nMeshID
REM now clone - NOT INSTANCE - the .X object into the now vacant object number
clone object nMeshID, j, 0
REM now we have to offset the entire mesh. To offset and center a mesh at a point
REM offset each limb in it (pass a value of 0 through it) by the negative value of it's supposed position.
offset limb nMeshID, 0, -tPosX#, -tPosY#, -tPosZ#
REM now position the objct at its rightful spot
position object nMeshID, tPosX#, tPosY#, tPosZ#
REM show the object
show object nMeshID
REM enable dynamic lighting
set object light nMeshID, 1
REM delete the original object that we cloned this from
delete object j
endif
next j
endif
EndIf
next i
VIOLA! All of the meshes that are to be dynamically lighted are now loaded into the app, with the added benefit that you can still adjust them with the pivot entities - as you did update their offsets to match their originals. In addition, everything is cleaned up for you - you can use those same numbers, as items are deleted from memory as soon as they're used!
Once again, a BIG THANK YOU to Mr Green Gandalf for helping me with this~
EDIT: Uploaded a video showing replaced meshes being lit my a changing dynamic light