Jump to content
  • Announcements

    • AndalayBay

      Orphan Attachments   07/31/2018

      I have been doing some housekeeping lately and I've noticed that I had a lot of orphaned attachments. Attachments get orphaned when the PM or post is deleted without removing the attachment first. Deleting a PM or post does not delete the attachment and the file or image remain on the server. I'd like to ask all members to go through their attachments and delete any attachments you don't need anymore or those that have been orphaned. Where can I get a list of my attachments? Click on your display name in the upper right corner of the forums and pick "My Attachments" from the drop-down list. How can I tell an attachment is orphaned? If the PM has been deleted, you'll see a message like this in your attachment list: Unfortunately there is no message if the post has been deleted, so please check your old posts. We do purge old birthday threads every once in a while. Also some hosted projects have been shut down, so you may have orphaned attachments on one of those locations. Thanks!
Sign in to follow this  
Malonn

Question for people with math skills

Recommended Posts

Math never was something with which I excelled.  It is with my latest modding project that ran into a calculations problem.  Can someone here help?  If not a direct answer, point me to a place where I could ask and get an answer?

Me and another guy have been modifying Reneer's Interiors Mod.  Fixes, etc.  One fix needs a fix:

Exteriors are cloned and drawn to the interior.  The problem is interior cells and exterior cells don't line up in-game.  Objects are drawn relative to the position of the interior door.  Long story short, sometimes the exterior is drawn through the interior.

My question is how do I calculate what will intersect with the interior mesh?  I can get the interior, thus it's XYZ.  I can get it's rough size (GetEditorSize).  Maybe it won't come down to a formula.  But that's my question.  If I know the size and position of the mesh I want to draw around, how do I "math" skipping placing objects if they will end up being placed within the dimensions of the interior mesh?

Help doesn't have to be in the form of a complete formula.  Just some guidance.  I can Google like a champ...

Share this post


Link to post
Share on other sites

Just some thoughts.  Might help people understand, and in turn solve, my issue.

I don't uderstand the math Reneer used (we're using his--nothing's changed there) to place objects.  I can break down the code though to make changes.

I have access to the XYZ coordinate of every single object being placed.  If it crosses within the area of the interior mesh, don't place it.  Simple idea, but how do I "math" that?  I can get the editor size and scale of the interior.  The XYZ coordinates of the interior.  It seems it should all be there.

(That smell of burning bacon is just my brain)

Share this post


Link to post
Share on other sites

If the Z of the interior mesh is the same as the Z of the object to be placed, skip it.  Not 100%.  Z's can be the same but behind it.  The current error correction uses the size and Z and some arbitrary number (GBR's code) (I can post formula if it helps).  It does improve things, but a lot of large statics that should be placed don't get placed.

Share this post


Link to post
Share on other sites

Editor size returns (length + width + height) / 3

...roughly.  So math that out to get rough dimensions (no clue how--Google would answer, but haven't checked yet).

Share this post


Link to post
Share on other sites

I'm not good at maths, but wouldn't you take the XYZ + rotation of the exterior building mesh, correlate with the XYZ + rotation of the interior building mesh, and then once you have matching values for what is effectively the same "object", work out what overlaps the exterior and so exclude from the interior?

 

If you're planning on releasing, did you get permission from Reneer? Someone already released a fixed and script-optimised update to this mod back in August 2018 but it was deleted by Nexus moderators due to not having permission to use the assets from the original in their updated version. I took a look at the scripts in both versions but when my ears started to bleed I lost interest.

Share this post


Link to post
Share on other sites
Posted (edited)

Hey Vorians.  I hadn't thought of that.  The exterior and interior meshes are not the same.  Interiors are 1 mesh, exteriors are walls, columns, etc. put together.  I don't know.  The exteriors are placed correctly relative to the interiors as is now.  It clones the exterior and adjusts it relative to the XYZ and rotation of the interior door.  Just that the exteriors are drawn through interiors sometimes.

But your thoughts build on my foundation.  Everything helps.

I wasn't planning on releasing this.  The version you speak of is from the guy I'm collaborating with.  I'm just trying to fix what he has trouble with.  2 minds are better than 1.

Edited by Malonn

Share this post


Link to post
Share on other sites

In Oblivion, the majority of buildings (not dungeons and caves) have a single exterior mesh and a single interior mesh, and typically they match quite well (except that the interiors tend to be ever so slightly larger in scale). Any other meshes making up the building exterior are just clutter, not part of the building at all really.

 

Wouldn't the MODB field of the base object help? Assuming OBSE scripting can reference that data of course.

 

Speaking of the previous release which was deleted from Nexus, the assets from Reneer's original were very low detail, and should be relatively easy to recreate from scratch. If memory serves me correctly, I think TESAnnwyn can create single cell meshes, and I know CSE can create single cell textures of varying resolutions. Whether it is possible to batch-generate an entire worldspace of single cell meshes and single cell textures is another question, but if so, then the person you're collaborating with could re-release with their own assets.

Share this post


Link to post
Share on other sites

What on earth, I mean nirn, are you trying to do? I don't know anything about Reneer's mod, so a link would help, I guess. :P

I've always thought that interiors were much larger than exteriors and am surprised to hear that they are close. Anyway, don't forget about the North marker. Ideally when you design an interior, you set the first piece, if it's made up of several parts, at 0,0,0 with 0 rotation. Very few people do that and I don't think Bethesda did either. It makes dungeon construction much easier. Then you use the North marker to orientate the interior to match the exterior.

I'm good at math, but have always found Bethesda's, or Gamebryo's coordinate system upside down and backwards. However you'll find a ton of math if you check out Imperial Furniture Renovated. :P So I might be able to help here. One thing to mention, the editor size is almost useless. You can only use getEditorSize as a relative value. For one thing, it doesn't include collision.

Here's the book stacking script from IFR. This shows the factors involved, including scale:

Spoiler

scn IFRStackBooks

ref bookCase
ref item
ref pBook
ref book
short itemidx
short hasBooks
short caseidx
array_var removeBooks
array_var sortedBooks
array_var items
ref delBook
short i
short j
short bookidx
short inserted
short numStack
float posX
float posY
float posZ
float angX
float angY
float angZ
float fscale
float size
float leftGap
float bottomGap
float frontGap
short numShelves
float bookshelfFrontOffset
float bookshelfBackOffset
float bookshelfAngleOffset
array_var leftOffset
array_var shelfLength
array_var heightOffset
array_var shelfHeight
array_var spellTomes
string_var formID
short index
float curShelf
float curLeftOffset
float curDepthOffset
float curHeightOffset
float shelfWorkingHeight
float shelfWorkingHeightOffset
float maxWidth
float shelfSin
float shelfCos
float itemHeight
float itemZoffset
float itemWidth
float itemDepth
float itemAngX
float itemAngY
float itemAngZ
float itemX
float itemY
float itemZ
float ftemp
short nextShelf

Begin Function {bookCase, caseidx}

	let hasBooks := 0

	;Set defaults
	let leftGap := 0.8
	let bottomGap := 0.5
	let frontGap := 3

	; define arrays
	let leftOffset := ar_construct array
	let shelfLength := ar_construct array
	let heightOffset := ar_construct array
	let shelfHeight := ar_construct array
	let removeBooks := ar_construct array
	let sortedBooks := ar_construct array
	let spellTomes := ar_construct stringmap

	; Register Spell Tomes forms and sizes
	let spellTomes["000CE6"] := 12
	let spellTomes["00127C"] := 12
	let spellTomes["00127D"] := 12
	let spellTomes["00127E"] := 12
	let spellTomes["00127F"] := 12
	let spellTomes["001280"] := 12
	let spellTomes["001281"] := 12
	let spellTomes["001282"] := 12
	let spellTomes["001283"] := 12
	let spellTomes["001284"] := 16
	let spellTomes["001285"] := 16
	let spellTomes["001286"] := 16
	let spellTomes["001287"] := 16
	let spellTomes["001288"] := 16
	let spellTomes["001289"] := 12
	let spellTomes["00128A"] := 16
	let spellTomes["00128B"] := 20
	let spellTomes["00128C"] := 20
	let spellTomes["00128D"] := 20
	let spellTomes["00128E"] := 20
	let spellTomes["00128F"] := 20
	let spellTomes["001290"] := 20
	let spellTomes["001291"] := 20
	let spellTomes["001292"] := 20
	let spellTomes["001293"] := 20
	let spellTomes["001294"] := 20
	let spellTomes["001295"] := 20
	let spellTomes["001296"] := 20
	let spellTomes["001297"] := 20
	let spellTomes["001298"] := 20
	let spellTomes["001299"] := 20
	let spellTomes["00129A"] := 20
	let spellTomes["00129B"] := 20
	let spellTomes["00129C"] := 20
	let spellTomes["00129D"] := 20
	let spellTomes["00129E"] := 20
	let spellTomes["00129F"] := 20
	let spellTomes["0012A0"] := 20
	let spellTomes["0012A1"] := 20
	let spellTomes["0012A2"] := 20
	let spellTomes["0012A3"] := 20
	let spellTomes["0012A4"] := 20
	let spellTomes["0012A5"] := 20
	let spellTomes["0012A6"] := 20
	let spellTomes["0012A7"] := 20
	let spellTomes["0012A9"] := 20
	let spellTomes["0012AA"] := 20
	let spellTomes["0012AB"] := 20
	let spellTomes["0012AC"] := 20
	let spellTomes["0012AD"] := 20
	let spellTomes["0012AE"] := 20
	let spellTomes["0012AF"] := 20
	let spellTomes["0012B0"] := 20
	let spellTomes["0012B1"] := 20
	let spellTomes["0012B6"] := 16
	let spellTomes["0017A3"] := 12
	let spellTomes["001D88"] := 12
	let spellTomes["002280"] := 12
	let spellTomes["002281"] := 12
	let spellTomes["002282"] := 12
	let spellTomes["002283"] := 12
	let spellTomes["002284"] := 12
	let spellTomes["002285"] := 12
	let spellTomes["002286"] := 12
	let spellTomes["002287"] := 12
	let spellTomes["002288"] := 12
	let spellTomes["002289"] := 12
	let spellTomes["00228A"] := 12
	let spellTomes["00228B"] := 12
	let spellTomes["00228C"] := 12
	let spellTomes["00228D"] := 12
	let spellTomes["00228E"] := 12
	let spellTomes["00228F"] := 12
	let spellTomes["002290"] := 12
	let spellTomes["002291"] := 12
	let spellTomes["002292"] := 12
	let spellTomes["002293"] := 12
	let spellTomes["002294"] := 12
	let spellTomes["002295"] := 12
	let spellTomes["002296"] := 12
	let spellTomes["002297"] := 12
	let spellTomes["002298"] := 12
	let spellTomes["002299"] := 16
	let spellTomes["00229A"] := 16
	let spellTomes["00229B"] := 16
	let spellTomes["00229C"] := 16
	let spellTomes["00229D"] := 16
	let spellTomes["00229E"] := 16
	let spellTomes["00229F"] := 16
	let spellTomes["0022A0"] := 16
	let spellTomes["0022A1"] := 16
	let spellTomes["0022A2"] := 16
	let spellTomes["0022A3"] := 16
	let spellTomes["0022A4"] := 16
	let spellTomes["0022A5"] := 16
	let spellTomes["0022A6"] := 16
	let spellTomes["0022A7"] := 16
	let spellTomes["0022A8"] := 16
	let spellTomes["0022A9"] := 16
	let spellTomes["0022AA"] := 16
	let spellTomes["0022AB"] := 16
	let spellTomes["0022AC"] := 12
	let spellTomes["0022AD"] := 12
	let spellTomes["0022AE"] := 12
	let spellTomes["0022AF"] := 20
	let spellTomes["0022B0"] := 20
	let spellTomes["0022B1"] := 20
	let spellTomes["0022B2"] := 20
	let spellTomes["0022B3"] := 20
	let spellTomes["0022B4"] := 16
	let spellTomes["0022B5"] := 16
	let spellTomes["0022B6"] := 16
	let spellTomes["0022B7"] := 16
	let spellTomes["0022B8"] := 16
	let spellTomes["0022B9"] := 16
	let spellTomes["0022BA"] := 16
	let spellTomes["0022BB"] := 12
	let spellTomes["0022BC"] := 12
	let spellTomes["0022BD"] := 20
	let spellTomes["0022BE"] := 20
	let spellTomes["0022BF"] := 20
	let spellTomes["0022C0"] := 12
	let spellTomes["0022C1"] := 12
	let spellTomes["0022C2"] := 12
	let spellTomes["0022C3"] := 12
	let spellTomes["0022C4"] := 12
	let spellTomes["0022C5"] := 12
	let spellTomes["0022C6"] := 20
	let spellTomes["0022C7"] := 20
	let spellTomes["0022C8"] := 20
	let spellTomes["0022C9"] := 20
	let spellTomes["0022CA"] := 20
	let spellTomes["0022CB"] := 20
	let spellTomes["0022CC"] := 20
	let spellTomes["0022CD"] := 20
	let spellTomes["0022CE"] := 20
	let spellTomes["0022CF"] := 20
	let spellTomes["0022D0"] := 12
	let spellTomes["0022D1"] := 12
	let spellTomes["0022D2"] := 12
	let spellTomes["0022D3"] := 20
	let spellTomes["0022D4"] := 20
	let spellTomes["0022D6"] := 20
	let spellTomes["0022D7"] := 20
	let spellTomes["0022D8"] := 20
	let spellTomes["0022D9"] := 20
	let spellTomes["0022DA"] := 20
	let spellTomes["0022DB"] := 20
	let spellTomes["0022DC"] := 20
	let spellTomes["0022DD"] := 12
	let spellTomes["0022DE"] := 12
	let spellTomes["0022DF"] := 12
	let spellTomes["0022E0"] := 12
	let spellTomes["0022E1"] := 12
	let spellTomes["0022E2"] := 12
	let spellTomes["0022E3"] := 12
	let spellTomes["0022E4"] := 12
	let spellTomes["0022E5"] := 12
	let spellTomes["0022E6"] := 12
	let spellTomes["0022E7"] := 12
	let spellTomes["0022E8"] := 12
	let spellTomes["0022E9"] := 12
	let spellTomes["0022EA"] := 12
	let spellTomes["0022EB"] := 12
	let spellTomes["0022EC"] := 12
	let spellTomes["0022ED"] := 12
	let spellTomes["0022EE"] := 16
	let spellTomes["0022EF"] := 16
	let spellTomes["0022F0"] := 16
	let spellTomes["0022F1"] := 16
	let spellTomes["0022F2"] := 20
	let spellTomes["0022F3"] := 20
	let spellTomes["0022F4"] := 20
	let spellTomes["0022F5"] := 20
	let spellTomes["0022F6"] := 20
	let spellTomes["0022F7"] := 20
	let spellTomes["0022F8"] := 20
	let spellTomes["0022F9"] := 20
	let spellTomes["0022FA"] := 20
	let spellTomes["0022FB"] := 20
	let spellTomes["0022FC"] := 12
	let spellTomes["0022FD"] := 12
	let spellTomes["0022FE"] := 12
	let spellTomes["0022FF"] := 16
	let spellTomes["002300"] := 16
	let spellTomes["002301"] := 16
	let spellTomes["002302"] := 16
	let spellTomes["002303"] := 16
	let spellTomes["002304"] := 16
	let spellTomes["002305"] := 16
	let spellTomes["002306"] := 16
	let spellTomes["002307"] := 16
	let spellTomes["002308"] := 16
	let spellTomes["002309"] := 12
	let spellTomes["00230A"] := 12
	let spellTomes["00230B"] := 12
	let spellTomes["00230C"] := 12
	let spellTomes["00230D"] := 16
	let spellTomes["00230E"] := 16
	let spellTomes["00230F"] := 16
	let spellTomes["002310"] := 16
	let spellTomes["002311"] := 16
	let spellTomes["002312"] := 12
	let spellTomes["002313"] := 12
	let spellTomes["002314"] := 12
	let spellTomes["002315"] := 12
	let spellTomes["002316"] := 12
	let spellTomes["002317"] := 12
	let spellTomes["002318"] := 12
	let spellTomes["002319"] := 12
	let spellTomes["00231A"] := 12
	let spellTomes["00231B"] := 12
	let spellTomes["00231C"] := 12
	let spellTomes["00231D"] := 12
	let spellTomes["00231E"] := 12
	let spellTomes["00231F"] := 12
	let spellTomes["002320"] := 12
	let spellTomes["002321"] := 12
	let spellTomes["002322"] := 12
	let spellTomes["002323"] := 12
	let spellTomes["002324"] := 12
	let spellTomes["002325"] := 12
	let spellTomes["002326"] := 12
	let spellTomes["002327"] := 12
	let spellTomes["002328"] := 12
	let spellTomes["002329"] := 12
	let spellTomes["00232A"] := 20
	let spellTomes["00232B"] := 20
	let spellTomes["00232C"] := 20
	let spellTomes["00232D"] := 20
	let spellTomes["00232E"] := 20
	let spellTomes["00232F"] := 20
	let spellTomes["002330"] := 20
	let spellTomes["002331"] := 20
	let spellTomes["002332"] := 20
	let spellTomes["002333"] := 20
	let spellTomes["002334"] := 12
	let spellTomes["002335"] := 12
	let spellTomes["002336"] := 12
	let spellTomes["002337"] := 16
	let spellTomes["002338"] := 16
	let spellTomes["002339"] := 16
	let spellTomes["00233A"] := 12
	let spellTomes["00233B"] := 12
	let spellTomes["00233C"] := 12
	let spellTomes["00233D"] := 12
	let spellTomes["002824"] := 12
	let spellTomes["002825"] := 12
	let spellTomes["002826"] := 12
	let spellTomes["002827"] := 12
	let spellTomes["002828"] := 12
	let spellTomes["002829"] := 12
	let spellTomes["00282A"] := 12
	let spellTomes["00282B"] := 12
	let spellTomes["00282C"] := 12
	let spellTomes["00282D"] := 12
	let spellTomes["00282E"] := 12
	let spellTomes["00282F"] := 12
	let spellTomes["002830"] := 12
	let spellTomes["002831"] := 12
	let spellTomes["002832"] := 12
	let spellTomes["002833"] := 12
	let spellTomes["002834"] := 12
	let spellTomes["002835"] := 12
	let spellTomes["002836"] := 12
	let spellTomes["002837"] := 12
	let spellTomes["002838"] := 12
	let spellTomes["002839"] := 12
	let spellTomes["00283A"] := 12
	let spellTomes["00283B"] := 12
	let spellTomes["00283C"] := 12
	let spellTomes["00283D"] := 12
	let spellTomes["00283E"] := 12
	let spellTomes["00283F"] := 12
	let spellTomes["002840"] := 12
	let spellTomes["002844"] := 12
	let spellTomes["002845"] := 12
	let spellTomes["002846"] := 12
	let spellTomes["002847"] := 20
	let spellTomes["002848"] := 20
	let spellTomes["002849"] := 20
	let spellTomes["00284A"] := 20
	let spellTomes["00284B"] := 20
	let spellTomes["00284C"] := 12
	let spellTomes["002850"] := 12
	let spellTomes["002851"] := 12
	
	; get position info of shelf
	let posX := bookCase.getPos x
	let posY := bookCase.getPos y
	let posZ := bookCase.getPos z
	let angX := bookCase.getAngle x
	let angY := bookCase.getAngle y
	let angZ := bookCase.getAngle z
	let fscale := bookCase.getScale

	if (caseidx == 1)
		let numShelves := 2
		let bookshelfFrontOffset := -5.5
		let bookshelfBackOffset := 14.3
		let bookshelfAngleOffset := 0
		let leftOffset[0] := -29.8
		let shelfLength[0] := 59.6
		let heightOffset[0] := -1.9
		let shelfHeight[0] := 34.2
		let leftOffset[1] := -29.8
		let shelfLength[1] := 59.6
		let heightOffset[1] := -30.4
		let shelfHeight[1] := 25.8
	elseif (caseidx == 2)
		let numShelves := 6
		let bookshelfFrontOffset := -9.8
		let bookshelfBackOffset := 9.3
		let bookshelfAngleOffset := 0
		let leftOffset[0] := -28.5
		let shelfLength[0] := 57.7
		let heightOffset[0] := 36.5
		let shelfHeight[0] := 14.4
		let leftOffset[1] := -28.5
		let shelfLength[1] := 57.7
		let heightOffset[1] := 19.3
		let shelfHeight[1] := 12.9
		let leftOffset[2] := -28.5
		let shelfLength[2] := 57.7
		let heightOffset[2] := 3.0
		let shelfHeight[2] := 12.3
		let leftOffset[3] := -28.5
		let shelfLength[3] := 57.7
		let heightOffset[3] := -13.6
		let shelfHeight[3] := 12.3
		let leftOffset[4] := -28.5
		let shelfLength[4] := 57.7
		let heightOffset[4] := -30.0
		let shelfHeight[4] := 12.3
		let leftOffset[5] := -28.5
		let shelfLength[5] := 57.7
		let heightOffset[5] := -49.0
		let shelfHeight[5] := 14.8
	elseif (caseidx == 3)
		let numShelves := 4
		let bookshelfFrontOffset := -15.0
		let bookshelfBackOffset := 20.0
		let bookshelfAngleOffset := 0
		let leftOffset[0] := -26.6
		let shelfLength[0] := 53.2
		let heightOffset[0] := 56.8
		let shelfHeight[0] := 39.3
		let leftOffset[1] := -26.6
		let shelfLength[1] := 53.2
		let heightOffset[1] := 8.3
		let shelfHeight[1] := 39.1
		let leftOffset[2] := -26.6
		let shelfLength[2] := 53.2
		let heightOffset[2] := -41.5
		let shelfHeight[2] := 39.4
		let leftOffset[3] := -26.6
		let shelfLength[3] := 53.2
		let heightOffset[3] := -90.4
		let shelfHeight[3] := 39.1
	elseif (caseidx == 4)
		let numShelves := 3
		let bookshelfFrontOffset := -18.3
		let bookshelfBackOffset := 17.9
		let bookshelfAngleOffset := 0
		let leftOffset[0] := -33.0
		let shelfLength[0] := 66.0
		let heightOffset[0] := 29.7
		let shelfHeight[0] := 37.0
		let leftOffset[1] := -33.0
		let shelfLength[1] := 66.0
		let heightOffset[1] := -7.3
		let shelfHeight[1] := 33.0
		let leftOffset[2] := -33.0
		let shelfLength[2] := 66.0
		let heightOffset[2] := -37.7
		let shelfHeight[2] := 26.0
	elseif (caseidx == 5)
		let numShelves := 8
		let bookshelfFrontOffset := -18.3
		let bookshelfBackOffset := 10.5
		let bookshelfAngleOffset := 0
		let leftOffset[0] := -103.8
		let shelfLength[0] := 100.4
		let heightOffset[0] := 38.1
		let shelfHeight[0] := 33.9
		let leftOffset[1] := 2.7
		let shelfLength[1] := 101.2
		let heightOffset[1] := 38.1
		let shelfHeight[1] := 33.9
		let leftOffset[2] := -103.8
		let shelfLength[2] := 100.4
		let heightOffset[2] := 2.7
		let shelfHeight[2] := 31.3
		let leftOffset[3] := 2.7
		let shelfLength[3] := 101.2
		let heightOffset[3] := 2.7
		let shelfHeight[3] := 31.3
		let leftOffset[4] := -103.8
		let shelfLength[4] := 100.4
		let heightOffset[4] := -35.6
		let shelfHeight[4] := 34.3
		let leftOffset[5] := 2.7
		let shelfLength[5] := 101.2
		let heightOffset[5] := -35.6
		let shelfHeight[5] := 34.3
		let leftOffset[6] := -103.8
		let shelfLength[6] := 100.4
		let heightOffset[6] := -71.7
		let shelfHeight[6] := 32.1
		let leftOffset[7] := 2.7
		let shelfLength[7] := 101.2
		let heightOffset[7] := -71.7
		let shelfHeight[7] := 31.2
	elseif (caseidx == 6)
		let numShelves := 3
		let bookshelfFrontOffset := -9.5
		let bookshelfBackOffset := 9.4
		let bookshelfAngleOffset := 0
		let leftOffset[0] := -29.8
		let shelfLength[0] := 59.6
		let heightOffset[0] := 16.2
		let shelfHeight[0] := 35.1
		let leftOffset[1] := -29.8
		let shelfLength[1] := 59.6
		let heightOffset[1] := -22.2
		let shelfHeight[1] := 35.7
		let leftOffset[2] := -29.8
		let shelfLength[2] := 59.6
		let heightOffset[2] := -49.9
		let shelfHeight[2] := 25.0
	elseif (caseidx == 7)
		let numShelves := 4
		let bookshelfFrontOffset := -16.0
		let bookshelfBackOffset := 5.9
		let bookshelfAngleOffset := -90.0
		let leftOffset[0] := -89.6
		let shelfLength[0] := 179.2
		let heightOffset[0] := 56.8
		let shelfHeight[0] := 40.5
		let leftOffset[1] := -89.6
		let shelfLength[1] := 179.2
		let heightOffset[1] := 7.3
		let shelfHeight[1] := 40.7
		let leftOffset[2] := -89.6
		let shelfLength[2] := 179.2
		let heightOffset[2] := -42.0
		let shelfHeight[2] := 40.6
		let leftOffset[3] := -89.6
		let shelfLength[3] := 179.2
		let heightOffset[3] := -91.4
		let shelfHeight[3] := 40.7	
	elseif (caseidx == 8)
		let numShelves := 12
		let bookshelfFrontOffset := -15.5
		let bookshelfBackOffset := 6.4
		let bookshelfAngleOffset := -90.0
		let leftOffset[0] := -138.2
		let shelfLength[0] := 96.1
		let heightOffset[0] := 41.3
		let shelfHeight[0] := 40.7
		let leftOffset[1] := -34.7
		let shelfLength[1] := 72.5
		let heightOffset[1] := 41.3
		let shelfHeight[1] := 40.7
		let leftOffset[2] := 45.3
		let shelfLength[2] := 92.9
		let heightOffset[2] := 41.3
		let shelfHeight[2] := 40.7
		let leftOffset[3] := -138.2
		let shelfLength[3] := 96.1
		let heightOffset[3] := -8.0
		let shelfHeight[3] := 40.6
		let leftOffset[4] := -34.7
		let shelfLength[4] := 72.5
		let heightOffset[4] := -8.0
		let shelfHeight[4] := 40.6
		let leftOffset[5] := 45.3
		let shelfLength[5] := 92.9
		let heightOffset[5] := -8.0
		let shelfHeight[5] := 40.6
		let leftOffset[6] := -138.2
		let shelfLength[6] := 96.1
		let heightOffset[6] := -57.3
		let shelfHeight[6] := 40.5
		let leftOffset[7] := -34.7
		let shelfLength[7] := 72.5
		let heightOffset[7] := -57.3
		let shelfHeight[7] := 40.5
		let leftOffset[8] := 45.3
		let shelfLength[8] := 92.9
		let heightOffset[8] := -57.3
		let shelfHeight[8] := 40.5
		let leftOffset[9] := -138.2
		let shelfLength[9] := 96.1
		let heightOffset[9] := -106.8
		let shelfHeight[9] := 40.7
		let leftOffset[10] := -34.7
		let shelfLength[10] := 72.5
		let heightOffset[10] := -106.8
		let shelfHeight[10] := 40.7
		let leftOffset[11] := 45.3
		let shelfLength[11] := 92.9
		let heightOffset[11] := -106.8
		let shelfHeight[11] := 40.7
	endif
	
	; ensure that bookcase is standing upright
	if (abs angX > 5.0 || abs angY > 5.0)
		message "Shelf not level or upright"
		return
	endif

	; adjust Z rotation according to bookshelf angle offset
	let angZ := angZ + bookshelfAngleOffset
		
	let shelfSin := sin angZ
	let shelfCos := cos angZ
	let curShelf := 0
	let curLeftOffset := 0
	let nextShelf := 0

	let itemidx := 0
	let j := 0
	
	let items := player.GetItems 21

	; sort books by size, largest first. Doing this because upper shelves are larger.
	while (itemidx < ar_Size items)
		let item := items[itemidx]
		if (isBook item) && (isScroll item == 0) && (IsQuestItem item == 0)
			if (IsModLoaded "DLCSpellTomes.esp")
				let formID := GetFormIDString item
				let formID := formID[2:7]
				let index := ar_hasKey spellTomes formID
				
				if (index)
					let size := spellTomes[formID]
				else
					let size := GetEditorSize item
				endif
			else
				let size := GetEditorSize item
			endif

			if (sortedBooks)
				let i:= 0
				let inserted := 0
				while (i < ar_Size sortedBooks)
					let book := sortedBooks[i]
					if (GetEditorSize book < size)
						let numStack := player.GetItemCount item
						let j := 0
						while (j < numStack)
							ar_insert sortedBooks i item
							let j += 1
							let i += 1
						loop
						let inserted := 1
						break
					endif
					let i += 1
				loop
				if (inserted == 0)
					let numStack := player.GetItemCount item
					let j := 0
					while (j < numStack)
						let sortedBooks[i] := item
						let j += 1
						let i += 1
					loop
				endif
			else
				let sortedBooks[0] := item
			endif
		endif

		let itemidx += 1
	loop
	
	let i:= 0
	let bookidx:= 0
	while curShelf < numShelves

		;Adjust shelf dimensions for bookshelf scale
		let bookshelfFrontOffset := bookshelfFrontOffset * fscale
		let bookshelfBackOffset := bookshelfBackOffset * fscale
		let leftOffset[curShelf] := leftOffset[curShelf] * fscale
		let shelfLength[curShelf] := shelfLength[curShelf] * fscale
		let heightOffset[curShelf] := heightOffset[curShelf] * fscale
		let shelfHeight[curShelf] := shelfHeight[curShelf] * fscale

		let shelfWorkingHeight := shelfHeight[curShelf]
		let shelfWorkingHeightOffset := heightOffset[curShelf]
		let maxWidth := 0
		
		while (bookidx < ar_Size sortedBooks)
			let book := sortedBooks[bookidx]
			if (IsModLoaded "DLCSpellTomes.esp")
				let formID := GetFormIDString book
				let formID := formID[2:7]
				let index := ar_hasKey spellTomes formID
				
				if (index)
					let size := spellTomes[formID]
				else
					let size := GetEditorSize book
				endif
			else
				let size := GetEditorSize book
			endif

			; need to round that
			let size := size + 0.5
			let size := floor size

			if (size <= 12)
				let itemHeight := 20
				let itemZoffset := 10
				let itemWidth := 3.3
				let itemDepth := 13.2
				let itemAngX := 270
				let itemAngY := angZ - 90
			elseif (size > 12 && size <= 16)
				let itemHeight := 25.4
				let itemZoffset := 12.7
				let itemWidth := 4.1
				let itemDepth := 13.2
				let itemAngX := 270
				let itemAngY := angZ - 90
			elseif (size > 16 && size <= 19)
				let itemHeight := 32.2
				let itemZoffset := 16.1
				let itemWidth := 6.4
				let itemDepth := 21.3
				let itemAngX := 270
				let itemAngY := angZ - 90
			elseif (size > 19 && size <= 20)
				let itemHeight := 32.2
				let itemZoffset := 16.1
				let itemWidth := 6.1
				let itemDepth := 21.3
				let itemAngX := 270
				let itemAngY := angZ - 90
			elseif (size > 20) && (CompareModelPath "OghmaInfinium" book == 0) && (CompareModelPath "oi.nif" book == 0)
				let itemHeight := 32.2
				let itemZoffset := 16.1
				let itemWidth := 7.5
				let itemDepth := 21.3
				let itemAngX := 270
				let itemAngY := angZ - 90
			elseif (CompareModelPath "OghmaInfinium" book) || (CompareModelPath "oi.nif" book)
				let itemHeight := 35.0
				let itemZoffset := 17.5
				let itemWidth := 9.0
				let itemDepth := 25.0
				let itemAngX := 270
				let itemAngY := angZ - 90
			endif

			if (caseidx == 2)
				if eval ((curLeftOffset + leftGap + itemHeight + 2) > shelfLength[curShelf])
					;Reset shelf position
					let curLeftOffset := 0
					let shelfWorkingHeight -= maxWidth
					let shelfWorkingHeightOffset += maxWidth
					if shelfWorkingHeight < 0
						let nextShelf := 1
						Break
					else
						continue
					endif
				endif
			else
				if eval ((curLeftOffset + leftGap + (itemWidth / 2) + 2) > shelfLength[curShelf])
					;Reset shelf position
					let curLeftOffset := 0
					let nextShelf := 1
					Break
				endif
			endif

			;Check book not too tall for the shelf
			if (caseidx == 2)
				if ((itemWidth + bottomGap + 1) >= shelfWorkingHeight)
					let bookidx += 1
					continue
				endif
			else
				if eval ( itemHeight + bottomGap + 1 >= shelfHeight[curShelf] )
					let bookidx += 1
					continue
				endif
			endif

			;Check depth offset does not leave book pushing into the back of the shelf
			let curDepthOffset := frontGap + (itemDepth / 2)
		
			if ((curDepthOffset + bookshelfFrontOffset + (itemDepth/2)) >= bookshelfBackOffset)
				let curDepthOffset := bookshelfBackOffset - bookshelfFrontOffset - (itemDepth/2) - 1
			endif

			;Check depth offset will not make book fall off shelf
			if ( curDepthOffset < 0 )
				let bookidx += 1
				continue
			endif

			;Set curLeftOffset to position for the new book
			if (caseidx == 2)
				let curLeftOffset := curLeftOffset + leftGap + (itemHeight / 2)
			else
				let curLeftOffset := curLeftOffset + leftGap + (itemWidth / 2)
			endif

			;Set height offset
			if (caseidx == 2)
				let curHeightOffset := bottomGap + (itemWidth / 2)
				if ((bottomGap + itemWidth) > maxWidth)
					let maxWidth := bottomGap + itemWidth
				endif
			else
				let curHeightOffset := bottomGap + itemZoffset
			endif

			;Convert the offsets to coordinates
			let itemX := curLeftOffset + leftOffset[curShelf]				;Set book position relative to centre of bookshelf
			let itemX := itemX * shelfCos											;Adjust this position depending on the Z angle of the bookshelf
			let ftemp := curDepthOffset + bookshelfFrontOffset				;Set depth offset relative to centre of bookshelf
			let ftemp := ftemp * shelfSin											;Adjust the depth depending on Z angle of bookshelf
			let itemX := itemX + ftemp												;If bookshelf were at X=0, itemX would now be correct
			let itemX := itemX + posX												;Now itemX is an absolute coordinate

			let itemY := curLeftOffset + leftOffset[curShelf]				;Same as above but for Y coordinate
			let itemY := itemY * shelfSin * -1
			let ftemp := curDepthOffset + bookshelfFrontOffset
			let ftemp := ftemp * shelfCos
			let itemY := itemY + ftemp
			let itemY := itemY + posY

			if (caseidx == 2)
				let itemZ := curHeightOffset + shelfWorkingHeightOffset
			else
				let itemZ := curHeightOffset + heightOffset[curShelf]			;Do not need to adjust Z pos for angle
			endif
			let itemZ := itemZ + posZ

			if (caseidx == 2)
				let itemAngX := 0
				let itemAngY := 0
				let itemAngZ := angZ - 90
			else
				let itemAngZ := 0
			endif

			;Create a new book
			let pBook := player.placeAtMe book, 1
			let removeBooks[i] := book

			;Position the book
			pBook.setPos, X, itemX
			pBook.setPos, Y, itemY
			pBook.setPos, Z, itemZ
			pBook.setAngle, X, itemAngX
			pBook.setAngle, Y, itemAngY
			pBook.setAngle, Z, itemAngZ

			;Add rest of book width to current left offset
			if (caseidx == 2)
				let curLeftOffset := curLeftOffset + (itemHeight / 2)
			else
				let curLeftOffset := curLeftOffset + (itemWidth / 2)
			endif

			let hasBooks += 1
			let i += 1
			;remove book from sorted books array
			ar_erase sortedBooks bookidx
		loop

		let curShelf += 1
		let nextShelf := 0
		let bookidx := 0
	loop

	; Now remove placed books from inventory
	let i:= 0
	while (i < ar_Size removeBooks)
		let delBook := removeBooks[i]
		player.removeItemNS delBook, 1
		let i += 1
	loop

	sv_destruct formID
	ar_erase removeBooks 0
	ar_erase sortedBooks 0
	setFunctionValue hasBooks
End

 

So if you can explain what you're trying to do, we could probably take some stuff from that script to fix your problem. If I ever get the motivation, I was going to release a new book placer mod that uses that and the other stacking scripts I developed. I got Horny Quintus' permission, but it would be a lot of work. :(

Share this post


Link to post
Share on other sites
34 minutes ago, Vorians said:

In Oblivion, the majority of buildings (not dungeons and caves) have a single exterior mesh and a single interior mesh, and typically they match quite well (except that the interiors tend to be ever so slightly larger in scale). Any other meshes making up the building exterior are just clutter, not part of the building at all really.

 

Wouldn't the MODB field of the base object help? Assuming OBSE scripting can reference that data of course.

 

Speaking of the previous release which was deleted from Nexus, the assets from Reneer's original were very low detail, and should be relatively easy to recreate from scratch. If memory serves me correctly, I think TESAnnwyn can create single cell meshes, and I know CSE can create single cell textures of varying resolutions. Whether it is possible to batch-generate an entire worldspace of single cell meshes and single cell textures is another question, but if so, then the person you're collaborating with could re-release with their own assets.

I did not know that.  Good to know.  More masonry to the foundation.

Yeah, the resources my collaborator use are scaled down even more.  Looks worse, but peforms better.  Our version is quite a stark improvement from Reneer's, IM-ultra-HO :)

17 minutes ago, AndalayBay said:

What on earth, I mean nirn, are you trying to do? I don't know anything about Reneer's mod, so a link would help, I guess. :P

I've always thought that interiors were much larger than exteriors and am surprised to hear that they are close. Anyway, don't forget about the North marker. Ideally when you design an interior, you set the first piece, if it's made up of several parts, at 0,0,0 with 0 rotation. Very few people do that and I don't think Bethesda did either. It makes dungeon construction much easier. Then you use the North marker to orientate the interior to match the exterior.

I'm good at math, but have always found Bethesda's, or Gamebryo's coordinate system upside down and backwards. However you'll find a ton of math if you check out Imperial Furniture Renovated. :P So I might be able to help here. One thing to mention, the editor size is almost useless. You can only use getEditorSize as a relative value. For one thing, it doesn't include collision.

Here's the book stacking script from IFR. This shows the factors involved, including scale:

  Reveal hidden contents


scn IFRStackBooks

ref bookCase
ref item
ref pBook
ref book
short itemidx
short hasBooks
short caseidx
array_var removeBooks
array_var sortedBooks
array_var items
ref delBook
short i
short j
short bookidx
short inserted
short numStack
float posX
float posY
float posZ
float angX
float angY
float angZ
float fscale
float size
float leftGap
float bottomGap
float frontGap
short numShelves
float bookshelfFrontOffset
float bookshelfBackOffset
float bookshelfAngleOffset
array_var leftOffset
array_var shelfLength
array_var heightOffset
array_var shelfHeight
array_var spellTomes
string_var formID
short index
float curShelf
float curLeftOffset
float curDepthOffset
float curHeightOffset
float shelfWorkingHeight
float shelfWorkingHeightOffset
float maxWidth
float shelfSin
float shelfCos
float itemHeight
float itemZoffset
float itemWidth
float itemDepth
float itemAngX
float itemAngY
float itemAngZ
float itemX
float itemY
float itemZ
float ftemp
short nextShelf

Begin Function {bookCase, caseidx}

	let hasBooks := 0

	;Set defaults
	let leftGap := 0.8
	let bottomGap := 0.5
	let frontGap := 3

	; define arrays
	let leftOffset := ar_construct array
	let shelfLength := ar_construct array
	let heightOffset := ar_construct array
	let shelfHeight := ar_construct array
	let removeBooks := ar_construct array
	let sortedBooks := ar_construct array
	let spellTomes := ar_construct stringmap

	; Register Spell Tomes forms and sizes
	let spellTomes["000CE6"] := 12
	let spellTomes["00127C"] := 12
	let spellTomes["00127D"] := 12
	let spellTomes["00127E"] := 12
	let spellTomes["00127F"] := 12
	let spellTomes["001280"] := 12
	let spellTomes["001281"] := 12
	let spellTomes["001282"] := 12
	let spellTomes["001283"] := 12
	let spellTomes["001284"] := 16
	let spellTomes["001285"] := 16
	let spellTomes["001286"] := 16
	let spellTomes["001287"] := 16
	let spellTomes["001288"] := 16
	let spellTomes["001289"] := 12
	let spellTomes["00128A"] := 16
	let spellTomes["00128B"] := 20
	let spellTomes["00128C"] := 20
	let spellTomes["00128D"] := 20
	let spellTomes["00128E"] := 20
	let spellTomes["00128F"] := 20
	let spellTomes["001290"] := 20
	let spellTomes["001291"] := 20
	let spellTomes["001292"] := 20
	let spellTomes["001293"] := 20
	let spellTomes["001294"] := 20
	let spellTomes["001295"] := 20
	let spellTomes["001296"] := 20
	let spellTomes["001297"] := 20
	let spellTomes["001298"] := 20
	let spellTomes["001299"] := 20
	let spellTomes["00129A"] := 20
	let spellTomes["00129B"] := 20
	let spellTomes["00129C"] := 20
	let spellTomes["00129D"] := 20
	let spellTomes["00129E"] := 20
	let spellTomes["00129F"] := 20
	let spellTomes["0012A0"] := 20
	let spellTomes["0012A1"] := 20
	let spellTomes["0012A2"] := 20
	let spellTomes["0012A3"] := 20
	let spellTomes["0012A4"] := 20
	let spellTomes["0012A5"] := 20
	let spellTomes["0012A6"] := 20
	let spellTomes["0012A7"] := 20
	let spellTomes["0012A9"] := 20
	let spellTomes["0012AA"] := 20
	let spellTomes["0012AB"] := 20
	let spellTomes["0012AC"] := 20
	let spellTomes["0012AD"] := 20
	let spellTomes["0012AE"] := 20
	let spellTomes["0012AF"] := 20
	let spellTomes["0012B0"] := 20
	let spellTomes["0012B1"] := 20
	let spellTomes["0012B6"] := 16
	let spellTomes["0017A3"] := 12
	let spellTomes["001D88"] := 12
	let spellTomes["002280"] := 12
	let spellTomes["002281"] := 12
	let spellTomes["002282"] := 12
	let spellTomes["002283"] := 12
	let spellTomes["002284"] := 12
	let spellTomes["002285"] := 12
	let spellTomes["002286"] := 12
	let spellTomes["002287"] := 12
	let spellTomes["002288"] := 12
	let spellTomes["002289"] := 12
	let spellTomes["00228A"] := 12
	let spellTomes["00228B"] := 12
	let spellTomes["00228C"] := 12
	let spellTomes["00228D"] := 12
	let spellTomes["00228E"] := 12
	let spellTomes["00228F"] := 12
	let spellTomes["002290"] := 12
	let spellTomes["002291"] := 12
	let spellTomes["002292"] := 12
	let spellTomes["002293"] := 12
	let spellTomes["002294"] := 12
	let spellTomes["002295"] := 12
	let spellTomes["002296"] := 12
	let spellTomes["002297"] := 12
	let spellTomes["002298"] := 12
	let spellTomes["002299"] := 16
	let spellTomes["00229A"] := 16
	let spellTomes["00229B"] := 16
	let spellTomes["00229C"] := 16
	let spellTomes["00229D"] := 16
	let spellTomes["00229E"] := 16
	let spellTomes["00229F"] := 16
	let spellTomes["0022A0"] := 16
	let spellTomes["0022A1"] := 16
	let spellTomes["0022A2"] := 16
	let spellTomes["0022A3"] := 16
	let spellTomes["0022A4"] := 16
	let spellTomes["0022A5"] := 16
	let spellTomes["0022A6"] := 16
	let spellTomes["0022A7"] := 16
	let spellTomes["0022A8"] := 16
	let spellTomes["0022A9"] := 16
	let spellTomes["0022AA"] := 16
	let spellTomes["0022AB"] := 16
	let spellTomes["0022AC"] := 12
	let spellTomes["0022AD"] := 12
	let spellTomes["0022AE"] := 12
	let spellTomes["0022AF"] := 20
	let spellTomes["0022B0"] := 20
	let spellTomes["0022B1"] := 20
	let spellTomes["0022B2"] := 20
	let spellTomes["0022B3"] := 20
	let spellTomes["0022B4"] := 16
	let spellTomes["0022B5"] := 16
	let spellTomes["0022B6"] := 16
	let spellTomes["0022B7"] := 16
	let spellTomes["0022B8"] := 16
	let spellTomes["0022B9"] := 16
	let spellTomes["0022BA"] := 16
	let spellTomes["0022BB"] := 12
	let spellTomes["0022BC"] := 12
	let spellTomes["0022BD"] := 20
	let spellTomes["0022BE"] := 20
	let spellTomes["0022BF"] := 20
	let spellTomes["0022C0"] := 12
	let spellTomes["0022C1"] := 12
	let spellTomes["0022C2"] := 12
	let spellTomes["0022C3"] := 12
	let spellTomes["0022C4"] := 12
	let spellTomes["0022C5"] := 12
	let spellTomes["0022C6"] := 20
	let spellTomes["0022C7"] := 20
	let spellTomes["0022C8"] := 20
	let spellTomes["0022C9"] := 20
	let spellTomes["0022CA"] := 20
	let spellTomes["0022CB"] := 20
	let spellTomes["0022CC"] := 20
	let spellTomes["0022CD"] := 20
	let spellTomes["0022CE"] := 20
	let spellTomes["0022CF"] := 20
	let spellTomes["0022D0"] := 12
	let spellTomes["0022D1"] := 12
	let spellTomes["0022D2"] := 12
	let spellTomes["0022D3"] := 20
	let spellTomes["0022D4"] := 20
	let spellTomes["0022D6"] := 20
	let spellTomes["0022D7"] := 20
	let spellTomes["0022D8"] := 20
	let spellTomes["0022D9"] := 20
	let spellTomes["0022DA"] := 20
	let spellTomes["0022DB"] := 20
	let spellTomes["0022DC"] := 20
	let spellTomes["0022DD"] := 12
	let spellTomes["0022DE"] := 12
	let spellTomes["0022DF"] := 12
	let spellTomes["0022E0"] := 12
	let spellTomes["0022E1"] := 12
	let spellTomes["0022E2"] := 12
	let spellTomes["0022E3"] := 12
	let spellTomes["0022E4"] := 12
	let spellTomes["0022E5"] := 12
	let spellTomes["0022E6"] := 12
	let spellTomes["0022E7"] := 12
	let spellTomes["0022E8"] := 12
	let spellTomes["0022E9"] := 12
	let spellTomes["0022EA"] := 12
	let spellTomes["0022EB"] := 12
	let spellTomes["0022EC"] := 12
	let spellTomes["0022ED"] := 12
	let spellTomes["0022EE"] := 16
	let spellTomes["0022EF"] := 16
	let spellTomes["0022F0"] := 16
	let spellTomes["0022F1"] := 16
	let spellTomes["0022F2"] := 20
	let spellTomes["0022F3"] := 20
	let spellTomes["0022F4"] := 20
	let spellTomes["0022F5"] := 20
	let spellTomes["0022F6"] := 20
	let spellTomes["0022F7"] := 20
	let spellTomes["0022F8"] := 20
	let spellTomes["0022F9"] := 20
	let spellTomes["0022FA"] := 20
	let spellTomes["0022FB"] := 20
	let spellTomes["0022FC"] := 12
	let spellTomes["0022FD"] := 12
	let spellTomes["0022FE"] := 12
	let spellTomes["0022FF"] := 16
	let spellTomes["002300"] := 16
	let spellTomes["002301"] := 16
	let spellTomes["002302"] := 16
	let spellTomes["002303"] := 16
	let spellTomes["002304"] := 16
	let spellTomes["002305"] := 16
	let spellTomes["002306"] := 16
	let spellTomes["002307"] := 16
	let spellTomes["002308"] := 16
	let spellTomes["002309"] := 12
	let spellTomes["00230A"] := 12
	let spellTomes["00230B"] := 12
	let spellTomes["00230C"] := 12
	let spellTomes["00230D"] := 16
	let spellTomes["00230E"] := 16
	let spellTomes["00230F"] := 16
	let spellTomes["002310"] := 16
	let spellTomes["002311"] := 16
	let spellTomes["002312"] := 12
	let spellTomes["002313"] := 12
	let spellTomes["002314"] := 12
	let spellTomes["002315"] := 12
	let spellTomes["002316"] := 12
	let spellTomes["002317"] := 12
	let spellTomes["002318"] := 12
	let spellTomes["002319"] := 12
	let spellTomes["00231A"] := 12
	let spellTomes["00231B"] := 12
	let spellTomes["00231C"] := 12
	let spellTomes["00231D"] := 12
	let spellTomes["00231E"] := 12
	let spellTomes["00231F"] := 12
	let spellTomes["002320"] := 12
	let spellTomes["002321"] := 12
	let spellTomes["002322"] := 12
	let spellTomes["002323"] := 12
	let spellTomes["002324"] := 12
	let spellTomes["002325"] := 12
	let spellTomes["002326"] := 12
	let spellTomes["002327"] := 12
	let spellTomes["002328"] := 12
	let spellTomes["002329"] := 12
	let spellTomes["00232A"] := 20
	let spellTomes["00232B"] := 20
	let spellTomes["00232C"] := 20
	let spellTomes["00232D"] := 20
	let spellTomes["00232E"] := 20
	let spellTomes["00232F"] := 20
	let spellTomes["002330"] := 20
	let spellTomes["002331"] := 20
	let spellTomes["002332"] := 20
	let spellTomes["002333"] := 20
	let spellTomes["002334"] := 12
	let spellTomes["002335"] := 12
	let spellTomes["002336"] := 12
	let spellTomes["002337"] := 16
	let spellTomes["002338"] := 16
	let spellTomes["002339"] := 16
	let spellTomes["00233A"] := 12
	let spellTomes["00233B"] := 12
	let spellTomes["00233C"] := 12
	let spellTomes["00233D"] := 12
	let spellTomes["002824"] := 12
	let spellTomes["002825"] := 12
	let spellTomes["002826"] := 12
	let spellTomes["002827"] := 12
	let spellTomes["002828"] := 12
	let spellTomes["002829"] := 12
	let spellTomes["00282A"] := 12
	let spellTomes["00282B"] := 12
	let spellTomes["00282C"] := 12
	let spellTomes["00282D"] := 12
	let spellTomes["00282E"] := 12
	let spellTomes["00282F"] := 12
	let spellTomes["002830"] := 12
	let spellTomes["002831"] := 12
	let spellTomes["002832"] := 12
	let spellTomes["002833"] := 12
	let spellTomes["002834"] := 12
	let spellTomes["002835"] := 12
	let spellTomes["002836"] := 12
	let spellTomes["002837"] := 12
	let spellTomes["002838"] := 12
	let spellTomes["002839"] := 12
	let spellTomes["00283A"] := 12
	let spellTomes["00283B"] := 12
	let spellTomes["00283C"] := 12
	let spellTomes["00283D"] := 12
	let spellTomes["00283E"] := 12
	let spellTomes["00283F"] := 12
	let spellTomes["002840"] := 12
	let spellTomes["002844"] := 12
	let spellTomes["002845"] := 12
	let spellTomes["002846"] := 12
	let spellTomes["002847"] := 20
	let spellTomes["002848"] := 20
	let spellTomes["002849"] := 20
	let spellTomes["00284A"] := 20
	let spellTomes["00284B"] := 20
	let spellTomes["00284C"] := 12
	let spellTomes["002850"] := 12
	let spellTomes["002851"] := 12
	
	; get position info of shelf
	let posX := bookCase.getPos x
	let posY := bookCase.getPos y
	let posZ := bookCase.getPos z
	let angX := bookCase.getAngle x
	let angY := bookCase.getAngle y
	let angZ := bookCase.getAngle z
	let fscale := bookCase.getScale

	if (caseidx == 1)
		let numShelves := 2
		let bookshelfFrontOffset := -5.5
		let bookshelfBackOffset := 14.3
		let bookshelfAngleOffset := 0
		let leftOffset[0] := -29.8
		let shelfLength[0] := 59.6
		let heightOffset[0] := -1.9
		let shelfHeight[0] := 34.2
		let leftOffset[1] := -29.8
		let shelfLength[1] := 59.6
		let heightOffset[1] := -30.4
		let shelfHeight[1] := 25.8
	elseif (caseidx == 2)
		let numShelves := 6
		let bookshelfFrontOffset := -9.8
		let bookshelfBackOffset := 9.3
		let bookshelfAngleOffset := 0
		let leftOffset[0] := -28.5
		let shelfLength[0] := 57.7
		let heightOffset[0] := 36.5
		let shelfHeight[0] := 14.4
		let leftOffset[1] := -28.5
		let shelfLength[1] := 57.7
		let heightOffset[1] := 19.3
		let shelfHeight[1] := 12.9
		let leftOffset[2] := -28.5
		let shelfLength[2] := 57.7
		let heightOffset[2] := 3.0
		let shelfHeight[2] := 12.3
		let leftOffset[3] := -28.5
		let shelfLength[3] := 57.7
		let heightOffset[3] := -13.6
		let shelfHeight[3] := 12.3
		let leftOffset[4] := -28.5
		let shelfLength[4] := 57.7
		let heightOffset[4] := -30.0
		let shelfHeight[4] := 12.3
		let leftOffset[5] := -28.5
		let shelfLength[5] := 57.7
		let heightOffset[5] := -49.0
		let shelfHeight[5] := 14.8
	elseif (caseidx == 3)
		let numShelves := 4
		let bookshelfFrontOffset := -15.0
		let bookshelfBackOffset := 20.0
		let bookshelfAngleOffset := 0
		let leftOffset[0] := -26.6
		let shelfLength[0] := 53.2
		let heightOffset[0] := 56.8
		let shelfHeight[0] := 39.3
		let leftOffset[1] := -26.6
		let shelfLength[1] := 53.2
		let heightOffset[1] := 8.3
		let shelfHeight[1] := 39.1
		let leftOffset[2] := -26.6
		let shelfLength[2] := 53.2
		let heightOffset[2] := -41.5
		let shelfHeight[2] := 39.4
		let leftOffset[3] := -26.6
		let shelfLength[3] := 53.2
		let heightOffset[3] := -90.4
		let shelfHeight[3] := 39.1
	elseif (caseidx == 4)
		let numShelves := 3
		let bookshelfFrontOffset := -18.3
		let bookshelfBackOffset := 17.9
		let bookshelfAngleOffset := 0
		let leftOffset[0] := -33.0
		let shelfLength[0] := 66.0
		let heightOffset[0] := 29.7
		let shelfHeight[0] := 37.0
		let leftOffset[1] := -33.0
		let shelfLength[1] := 66.0
		let heightOffset[1] := -7.3
		let shelfHeight[1] := 33.0
		let leftOffset[2] := -33.0
		let shelfLength[2] := 66.0
		let heightOffset[2] := -37.7
		let shelfHeight[2] := 26.0
	elseif (caseidx == 5)
		let numShelves := 8
		let bookshelfFrontOffset := -18.3
		let bookshelfBackOffset := 10.5
		let bookshelfAngleOffset := 0
		let leftOffset[0] := -103.8
		let shelfLength[0] := 100.4
		let heightOffset[0] := 38.1
		let shelfHeight[0] := 33.9
		let leftOffset[1] := 2.7
		let shelfLength[1] := 101.2
		let heightOffset[1] := 38.1
		let shelfHeight[1] := 33.9
		let leftOffset[2] := -103.8
		let shelfLength[2] := 100.4
		let heightOffset[2] := 2.7
		let shelfHeight[2] := 31.3
		let leftOffset[3] := 2.7
		let shelfLength[3] := 101.2
		let heightOffset[3] := 2.7
		let shelfHeight[3] := 31.3
		let leftOffset[4] := -103.8
		let shelfLength[4] := 100.4
		let heightOffset[4] := -35.6
		let shelfHeight[4] := 34.3
		let leftOffset[5] := 2.7
		let shelfLength[5] := 101.2
		let heightOffset[5] := -35.6
		let shelfHeight[5] := 34.3
		let leftOffset[6] := -103.8
		let shelfLength[6] := 100.4
		let heightOffset[6] := -71.7
		let shelfHeight[6] := 32.1
		let leftOffset[7] := 2.7
		let shelfLength[7] := 101.2
		let heightOffset[7] := -71.7
		let shelfHeight[7] := 31.2
	elseif (caseidx == 6)
		let numShelves := 3
		let bookshelfFrontOffset := -9.5
		let bookshelfBackOffset := 9.4
		let bookshelfAngleOffset := 0
		let leftOffset[0] := -29.8
		let shelfLength[0] := 59.6
		let heightOffset[0] := 16.2
		let shelfHeight[0] := 35.1
		let leftOffset[1] := -29.8
		let shelfLength[1] := 59.6
		let heightOffset[1] := -22.2
		let shelfHeight[1] := 35.7
		let leftOffset[2] := -29.8
		let shelfLength[2] := 59.6
		let heightOffset[2] := -49.9
		let shelfHeight[2] := 25.0
	elseif (caseidx == 7)
		let numShelves := 4
		let bookshelfFrontOffset := -16.0
		let bookshelfBackOffset := 5.9
		let bookshelfAngleOffset := -90.0
		let leftOffset[0] := -89.6
		let shelfLength[0] := 179.2
		let heightOffset[0] := 56.8
		let shelfHeight[0] := 40.5
		let leftOffset[1] := -89.6
		let shelfLength[1] := 179.2
		let heightOffset[1] := 7.3
		let shelfHeight[1] := 40.7
		let leftOffset[2] := -89.6
		let shelfLength[2] := 179.2
		let heightOffset[2] := -42.0
		let shelfHeight[2] := 40.6
		let leftOffset[3] := -89.6
		let shelfLength[3] := 179.2
		let heightOffset[3] := -91.4
		let shelfHeight[3] := 40.7	
	elseif (caseidx == 8)
		let numShelves := 12
		let bookshelfFrontOffset := -15.5
		let bookshelfBackOffset := 6.4
		let bookshelfAngleOffset := -90.0
		let leftOffset[0] := -138.2
		let shelfLength[0] := 96.1
		let heightOffset[0] := 41.3
		let shelfHeight[0] := 40.7
		let leftOffset[1] := -34.7
		let shelfLength[1] := 72.5
		let heightOffset[1] := 41.3
		let shelfHeight[1] := 40.7
		let leftOffset[2] := 45.3
		let shelfLength[2] := 92.9
		let heightOffset[2] := 41.3
		let shelfHeight[2] := 40.7
		let leftOffset[3] := -138.2
		let shelfLength[3] := 96.1
		let heightOffset[3] := -8.0
		let shelfHeight[3] := 40.6
		let leftOffset[4] := -34.7
		let shelfLength[4] := 72.5
		let heightOffset[4] := -8.0
		let shelfHeight[4] := 40.6
		let leftOffset[5] := 45.3
		let shelfLength[5] := 92.9
		let heightOffset[5] := -8.0
		let shelfHeight[5] := 40.6
		let leftOffset[6] := -138.2
		let shelfLength[6] := 96.1
		let heightOffset[6] := -57.3
		let shelfHeight[6] := 40.5
		let leftOffset[7] := -34.7
		let shelfLength[7] := 72.5
		let heightOffset[7] := -57.3
		let shelfHeight[7] := 40.5
		let leftOffset[8] := 45.3
		let shelfLength[8] := 92.9
		let heightOffset[8] := -57.3
		let shelfHeight[8] := 40.5
		let leftOffset[9] := -138.2
		let shelfLength[9] := 96.1
		let heightOffset[9] := -106.8
		let shelfHeight[9] := 40.7
		let leftOffset[10] := -34.7
		let shelfLength[10] := 72.5
		let heightOffset[10] := -106.8
		let shelfHeight[10] := 40.7
		let leftOffset[11] := 45.3
		let shelfLength[11] := 92.9
		let heightOffset[11] := -106.8
		let shelfHeight[11] := 40.7
	endif
	
	; ensure that bookcase is standing upright
	if (abs angX > 5.0 || abs angY > 5.0)
		message "Shelf not level or upright"
		return
	endif

	; adjust Z rotation according to bookshelf angle offset
	let angZ := angZ + bookshelfAngleOffset
		
	let shelfSin := sin angZ
	let shelfCos := cos angZ
	let curShelf := 0
	let curLeftOffset := 0
	let nextShelf := 0

	let itemidx := 0
	let j := 0
	
	let items := player.GetItems 21

	; sort books by size, largest first. Doing this because upper shelves are larger.
	while (itemidx < ar_Size items)
		let item := items[itemidx]
		if (isBook item) && (isScroll item == 0) && (IsQuestItem item == 0)
			if (IsModLoaded "DLCSpellTomes.esp")
				let formID := GetFormIDString item
				let formID := formID[2:7]
				let index := ar_hasKey spellTomes formID
				
				if (index)
					let size := spellTomes[formID]
				else
					let size := GetEditorSize item
				endif
			else
				let size := GetEditorSize item
			endif

			if (sortedBooks)
				let i:= 0
				let inserted := 0
				while (i < ar_Size sortedBooks)
					let book := sortedBooks[i]
					if (GetEditorSize book < size)
						let numStack := player.GetItemCount item
						let j := 0
						while (j < numStack)
							ar_insert sortedBooks i item
							let j += 1
							let i += 1
						loop
						let inserted := 1
						break
					endif
					let i += 1
				loop
				if (inserted == 0)
					let numStack := player.GetItemCount item
					let j := 0
					while (j < numStack)
						let sortedBooks[i] := item
						let j += 1
						let i += 1
					loop
				endif
			else
				let sortedBooks[0] := item
			endif
		endif

		let itemidx += 1
	loop
	
	let i:= 0
	let bookidx:= 0
	while curShelf < numShelves

		;Adjust shelf dimensions for bookshelf scale
		let bookshelfFrontOffset := bookshelfFrontOffset * fscale
		let bookshelfBackOffset := bookshelfBackOffset * fscale
		let leftOffset[curShelf] := leftOffset[curShelf] * fscale
		let shelfLength[curShelf] := shelfLength[curShelf] * fscale
		let heightOffset[curShelf] := heightOffset[curShelf] * fscale
		let shelfHeight[curShelf] := shelfHeight[curShelf] * fscale

		let shelfWorkingHeight := shelfHeight[curShelf]
		let shelfWorkingHeightOffset := heightOffset[curShelf]
		let maxWidth := 0
		
		while (bookidx < ar_Size sortedBooks)
			let book := sortedBooks[bookidx]
			if (IsModLoaded "DLCSpellTomes.esp")
				let formID := GetFormIDString book
				let formID := formID[2:7]
				let index := ar_hasKey spellTomes formID
				
				if (index)
					let size := spellTomes[formID]
				else
					let size := GetEditorSize book
				endif
			else
				let size := GetEditorSize book
			endif

			; need to round that
			let size := size + 0.5
			let size := floor size

			if (size <= 12)
				let itemHeight := 20
				let itemZoffset := 10
				let itemWidth := 3.3
				let itemDepth := 13.2
				let itemAngX := 270
				let itemAngY := angZ - 90
			elseif (size > 12 && size <= 16)
				let itemHeight := 25.4
				let itemZoffset := 12.7
				let itemWidth := 4.1
				let itemDepth := 13.2
				let itemAngX := 270
				let itemAngY := angZ - 90
			elseif (size > 16 && size <= 19)
				let itemHeight := 32.2
				let itemZoffset := 16.1
				let itemWidth := 6.4
				let itemDepth := 21.3
				let itemAngX := 270
				let itemAngY := angZ - 90
			elseif (size > 19 && size <= 20)
				let itemHeight := 32.2
				let itemZoffset := 16.1
				let itemWidth := 6.1
				let itemDepth := 21.3
				let itemAngX := 270
				let itemAngY := angZ - 90
			elseif (size > 20) && (CompareModelPath "OghmaInfinium" book == 0) && (CompareModelPath "oi.nif" book == 0)
				let itemHeight := 32.2
				let itemZoffset := 16.1
				let itemWidth := 7.5
				let itemDepth := 21.3
				let itemAngX := 270
				let itemAngY := angZ - 90
			elseif (CompareModelPath "OghmaInfinium" book) || (CompareModelPath "oi.nif" book)
				let itemHeight := 35.0
				let itemZoffset := 17.5
				let itemWidth := 9.0
				let itemDepth := 25.0
				let itemAngX := 270
				let itemAngY := angZ - 90
			endif

			if (caseidx == 2)
				if eval ((curLeftOffset + leftGap + itemHeight + 2) > shelfLength[curShelf])
					;Reset shelf position
					let curLeftOffset := 0
					let shelfWorkingHeight -= maxWidth
					let shelfWorkingHeightOffset += maxWidth
					if shelfWorkingHeight < 0
						let nextShelf := 1
						Break
					else
						continue
					endif
				endif
			else
				if eval ((curLeftOffset + leftGap + (itemWidth / 2) + 2) > shelfLength[curShelf])
					;Reset shelf position
					let curLeftOffset := 0
					let nextShelf := 1
					Break
				endif
			endif

			;Check book not too tall for the shelf
			if (caseidx == 2)
				if ((itemWidth + bottomGap + 1) >= shelfWorkingHeight)
					let bookidx += 1
					continue
				endif
			else
				if eval ( itemHeight + bottomGap + 1 >= shelfHeight[curShelf] )
					let bookidx += 1
					continue
				endif
			endif

			;Check depth offset does not leave book pushing into the back of the shelf
			let curDepthOffset := frontGap + (itemDepth / 2)
		
			if ((curDepthOffset + bookshelfFrontOffset + (itemDepth/2)) >= bookshelfBackOffset)
				let curDepthOffset := bookshelfBackOffset - bookshelfFrontOffset - (itemDepth/2) - 1
			endif

			;Check depth offset will not make book fall off shelf
			if ( curDepthOffset < 0 )
				let bookidx += 1
				continue
			endif

			;Set curLeftOffset to position for the new book
			if (caseidx == 2)
				let curLeftOffset := curLeftOffset + leftGap + (itemHeight / 2)
			else
				let curLeftOffset := curLeftOffset + leftGap + (itemWidth / 2)
			endif

			;Set height offset
			if (caseidx == 2)
				let curHeightOffset := bottomGap + (itemWidth / 2)
				if ((bottomGap + itemWidth) > maxWidth)
					let maxWidth := bottomGap + itemWidth
				endif
			else
				let curHeightOffset := bottomGap + itemZoffset
			endif

			;Convert the offsets to coordinates
			let itemX := curLeftOffset + leftOffset[curShelf]				;Set book position relative to centre of bookshelf
			let itemX := itemX * shelfCos											;Adjust this position depending on the Z angle of the bookshelf
			let ftemp := curDepthOffset + bookshelfFrontOffset				;Set depth offset relative to centre of bookshelf
			let ftemp := ftemp * shelfSin											;Adjust the depth depending on Z angle of bookshelf
			let itemX := itemX + ftemp												;If bookshelf were at X=0, itemX would now be correct
			let itemX := itemX + posX												;Now itemX is an absolute coordinate

			let itemY := curLeftOffset + leftOffset[curShelf]				;Same as above but for Y coordinate
			let itemY := itemY * shelfSin * -1
			let ftemp := curDepthOffset + bookshelfFrontOffset
			let ftemp := ftemp * shelfCos
			let itemY := itemY + ftemp
			let itemY := itemY + posY

			if (caseidx == 2)
				let itemZ := curHeightOffset + shelfWorkingHeightOffset
			else
				let itemZ := curHeightOffset + heightOffset[curShelf]			;Do not need to adjust Z pos for angle
			endif
			let itemZ := itemZ + posZ

			if (caseidx == 2)
				let itemAngX := 0
				let itemAngY := 0
				let itemAngZ := angZ - 90
			else
				let itemAngZ := 0
			endif

			;Create a new book
			let pBook := player.placeAtMe book, 1
			let removeBooks[i] := book

			;Position the book
			pBook.setPos, X, itemX
			pBook.setPos, Y, itemY
			pBook.setPos, Z, itemZ
			pBook.setAngle, X, itemAngX
			pBook.setAngle, Y, itemAngY
			pBook.setAngle, Z, itemAngZ

			;Add rest of book width to current left offset
			if (caseidx == 2)
				let curLeftOffset := curLeftOffset + (itemHeight / 2)
			else
				let curLeftOffset := curLeftOffset + (itemWidth / 2)
			endif

			let hasBooks += 1
			let i += 1
			;remove book from sorted books array
			ar_erase sortedBooks bookidx
		loop

		let curShelf += 1
		let nextShelf := 0
		let bookidx := 0
	loop

	; Now remove placed books from inventory
	let i:= 0
	while (i < ar_Size removeBooks)
		let delBook := removeBooks[i]
		player.removeItemNS delBook, 1
		let i += 1
	loop

	sv_destruct formID
	ar_erase removeBooks 0
	ar_erase sortedBooks 0
	setFunctionValue hasBooks
End

 

So if you can explain what you're trying to do, we could probably take some stuff from that script to fix your problem. If I ever get the motivation, I was going to release a new book placer mod that uses that and the other stacking scripts I developed. I got Horny Quintus' permission, but it would be a lot of work. :(

Here's the mod we're modifying.  You can handle the math... good, good.  The mod is a scripted version of Immersive Interiors.  I prefer it because it is moldable.  With II you have to hand place (and remove) everything.  With this mod and a couple lines of code, you can completely prevent, for example, flora from being placed.

The business of the mod does this: Activate a door outside and it scans and gets the positions and rotations of the objects in the surrounding exterior cells(s).  It then uses the interior's door coordinates to "math" out the placement of the objects scanned in the exterior.  This is what I'm fuzzy on.  The math to place all the objects copied outside inside.  Essentially, the mod copies the exterior and places it in the interior.

All works fine except that some exterior objects get placed through the interior.  These are what I'm trying to filter out.

I'll take a look at the script you linked, I just don't know if I'll be able to gleam something helpful.  Hopefully I can.

I really hope you can hold my hand more :D

Share this post


Link to post
Share on other sites

I've checked a few cells and they all use North Markers.  It feels like that could be useful, but I'm not sure how.

Exteriors meshes are not always the same dimensions as the corresponding interiors.  Sometimes they are.  Other times they are not.  So, AB, let's say from the same starting position (the door)an interior is 10 units deep, the exterior is only 5 units deep, when copied and placed inside, the objects will cut through the middle of the interior mesh.  Which is what happens (a lot), you'll have a wall right through the middle of the interior.

Edited by Malonn

Share this post


Link to post
Share on other sites

As Vorians suggested, I can get bounding radius.  From there calculate area of sphere.  If Object to be placed coordinates fall with area, don't place.  I'll try that.  But, AB let me ask:

How do I find how far out (in coordinates) the sphere extends?  It should be possible if I know starting coordinates?

Share this post


Link to post
Share on other sites

Another question:

Every mesh has coordinates.  The interior mesh for example.  But it's (let's pretend) a cube.  Which point of the cube are the coordinates taken?

Share this post


Link to post
Share on other sites

Ok, I see what you're trying to do now. This is really going to put a lot of load on your PC. Are you using the CSE? It gives you the camera position and from that, you might be able to figure out where the origin is. I thought it was the centre of gravity, but it doesn't look like that's the case. So it's probably one of the corners of the mesh. The CS Wiki might say.

I just checked a vanilla interior and it is set to the zero origin, so that will help. I'll take a quick look at Reneer's mod, but I really don't have much time to help right now. I've got a ton of mods to work on as well as a lot of server work, as Vorians will attest to. :)

Share this post


Link to post
Share on other sites

No problem, AB.  I'm giving Google's servers a strain.  Hopefully I can turn up something.  I found a formula for if a point lies within a sphere, but it doesn't work.  It prevents the ground from being placed.  The rest of the exterior is placed except the ground.  Odd.  Something is wrong with something...

Share this post


Link to post
Share on other sites

Ok, my eyes have glazed over as well. :P There's nothing worse than trying to sort through someone else's code, especially when they've obviously had trouble with it too, given the number of debugging statements in it.

How about a completely different approach? My first suggestion is to use CODA to create Immersive Interiors Ultimate. CODA is the internal scripting language of the CSE and it can create objects. I'm not sure how you would collect all the exterior objects, but if you could find a way to load all the exterior objects, then you could use CODA to "copy" them and place them into the interior cell. I also don't know how you would only do that for interior cells with transparent windows.

My second suggestion is to scrap Reneer's code and start creating your own. Pick an interior cell and just work out how to properly position one object like a rock. Then you can start building up your own code for the rest of the stuff.

Failing those two suggestions, then I would start focusing on the objects that the current script doesn't place correctly and track down which part of the code is failing. If you can give me something specific, then I might be able to help with the math.

Share this post


Link to post
Share on other sites
4 hours ago, Malonn said:

Another question:

Every mesh has coordinates.  The interior mesh for example.  But it's (let's pretend) a cube.  Which point of the cube are the coordinates taken?

Every mesh has a pivot point, the "centre" however it does not have to be in the actual centre of the object. In the CSE, if you were to place an object at coordinates 0,0,0 in an interior cell, the actual part of that object at 0,0,0 is the pivot point for that mesh. Sometimes a mesh is intended to be connected to another mesh (such as a grand door frame being separate but designed specifically for use with a single building mesh) - in that example the building mesh may have its pivot point in the centre of the object, however the door frame mesh has its pivot point in the exact same place as the building mesh, relative to its intended placement, instead of being in its centre. An actual Oblivion example I know off the top of my head would be the Imperial City building blocks. Each district contains four blocks of buildings, and each block is made up of four objects. But the pivot point for each of those objects is centred on the pavement mesh which they are all meant to fit into in specific slots.

In the CSE's Render window, the pivot point is displayed as a yellow 3D cross or target when an object is selected - and when you select any placed object, press "C" to centre view on it, and zoom in, you will zoom toward that pivot point.

Usage of the words "mesh" and "object" are getting a bit muddled I know, but effectively they mean the same thing here.

 

The updated version of Reneer's mod which was deleted from Nexus has altered scripting doesn't it? So if Andalay is intending to help by referencing the existing code, she will need a copy of the updated mod.

 

I also thought about CSE's CODA instead (no clue how to use it so don't know if it's even possible) however the drawback would be that you'd end up with a perfect result for a vanilla game, but it would not take into account mod-altered exteriors - I first took an interest in regards to Better Cities back when the update was released, which of course has massive alterations to the city exteriors - for the interiors actually included in the Reneer mod, it accounted for BC's changes, so I was impressed with that.

Share this post


Link to post
Share on other sites
9 hours ago, AndalayBay said:

Ok, my eyes have glazed over as well. :P There's nothing worse than trying to sort through someone else's code, especially when they've obviously had trouble with it too, given the number of debugging statements in it.

How about a completely different approach? My first suggestion is to use CODA to create Immersive Interiors Ultimate. CODA is the internal scripting language of the CSE and it can create objects. I'm not sure how you would collect all the exterior objects, but if you could find a way to load all the exterior objects, then you could use CODA to "copy" them and place them into the interior cell. I also don't know how you would only do that for interior cells with transparent windows.

My second suggestion is to scrap Reneer's code and start creating your own. Pick an interior cell and just work out how to properly position one object like a rock. Then you can start building up your own code for the rest of the stuff.

Failing those two suggestions, then I would start focusing on the objects that the current script doesn't place correctly and track down which part of the code is failing. If you can give me something specific, then I might be able to help with the math.

Yeah, the code is a mess.  It took me a day to understand it, and I still don't understand the math that is involved in placing the objects.

I appreciate the CODA suggestion, but I'm set on doing this via scripting at runtime.  It's easier, has good control, and, like Vorians said, it can account for third-party exteriors/interiors.

I may have to gain more control/understanding over each placed object.  If I find math problems I'll ask you.  Google first so as to not bug you.

8 hours ago, Vorians said:

Every mesh has a pivot point, the "centre" however it does not have to be in the actual centre of the object. In the CSE, if you were to place an object at coordinates 0,0,0 in an interior cell, the actual part of that object at 0,0,0 is the pivot point for that mesh. Sometimes a mesh is intended to be connected to another mesh (such as a grand door frame being separate but designed specifically for use with a single building mesh) - in that example the building mesh may have its pivot point in the centre of the object, however the door frame mesh has its pivot point in the exact same place as the building mesh, relative to its intended placement, instead of being in its centre. An actual Oblivion example I know off the top of my head would be the Imperial City building blocks. Each district contains four blocks of buildings, and each block is made up of four objects. But the pivot point for each of those objects is centred on the pavement mesh which they are all meant to fit into in specific slots.

In the CSE's Render window, the pivot point is displayed as a yellow 3D cross or target when an object is selected - and when you select any placed object, press "C" to centre view on it, and zoom in, you will zoom toward that pivot point.

Usage of the words "mesh" and "object" are getting a bit muddled I know, but effectively they mean the same thing here.

 

The updated version of Reneer's mod which was deleted from Nexus has altered scripting doesn't it? So if Andalay is intending to help by referencing the existing code, she will need a copy of the updated mod.

 

I also thought about CSE's CODA instead (no clue how to use it so don't know if it's even possible) however the drawback would be that you'd end up with a perfect result for a vanilla game, but it would not take into account mod-altered exteriors - I first took an interest in regards to Better Cities back when the update was released, which of course has massive alterations to the city exteriors - for the interiors actually included in the Reneer mod, it accounted for BC's changes, so I was impressed with that.

Good info.  It would be nice if it was at the exact center of the mesh.

CODA is more "clunky" than runtime scripting.  Both use a script for the magic, but CODA is more permanent.  And the big one, like you said (which I forgot), is that it won't account for mod added exteriors.  LO changes, etc.

 

On a you-could-care-less sidenote, I took a step away last night and went to bed and got the idea of getting a rough estimate of the size of interior mesh by checking the distance that the furthest reference from the door is placed.  That should give a number to check against.  I just need to check that it's in the right direction.  And Z position.

Google time...

Share this post


Link to post
Share on other sites

My thoughts:  most interiors with windows have a second (or more) door.  If it has an upstairs door I can get that with Z values.  That gives an estimate of height.  Then get something straight across from the outside load door and maybe draw a plane?  If objects being drawn would cross the plane don't place them?

Googling turns up tons of plane math; equations of a plane; vectors; shit I don't understand.  What do I need to test my hypothesis?

Let's tax Google's servers...

AB, I have math (and code) for if a point falls on a line between two points.  Can you figure out how to give a wider margin of error?  A point between two points is too precise.  I need if a point falls inside a cube more than if the point falls on a line.

Here's the link to the source.  Do you understand that?  I think a guy posts what I'm looking for but I don't get it.

The only option I have is to try shit and test in-game.  I can't nail the math down from the get-go.

Edited by Malonn

Share this post


Link to post
Share on other sites

Personally, when I am struggling to make sense of another modders' work and I need to understand it, I just tear it to pieces. As in, I strip out all the content I fully understand so that it doesn't get in the way and confuse me, leaving just the part that I don't understand. Then I start disabling bits of it to see what the results are. Whatever breaks, and how it breaks as a result of that disabled bit, helps to understand what that disabled bit does.

Share this post


Link to post
Share on other sites

That's kind of what I did to get to where I am.  You saw Reneer's code: confusing.  Maybe I need to break down the formula.  I don't know if I'll see the big picture though.

I know the XYZ of the objects being placed via Reneers code.  It's proper and works.  It's just a matter of finding if they intersect with the dimensions of the interior mesh.  But, I don't have the dimensions.  I have editor size (that's what my collaborator--GBRPluss--used to fight this battle), but the CSWiki says it's L + W + H / 3.  What the hell is that?  If I had volume I could get dimensions, but that's not volume.  I guess I just have to ballpark it.  That's what GBRPluss did.  And his code helps but is not accurate.  He error corrects the error correction.  I want to hone it in some more.

Share this post


Link to post
Share on other sites

Here's a better source of that code you found. The code you found used C++ functions, which won't help you at all. In terms of the math, it has been... fuck over 30 years since I did that stuff. You can click on the links in that article to get the definitions. The key to the math is the fact that the line drawn from the point to the other line, or plane, is 90 degrees. Do you know Pythagoras Theorem? Don't worry about all the rectangles. The point is that you can calculate the length of any side of a right-angled triangle if you know the length of the other two sides. That is the key to the math in the point-line distance calculations from the first link I posted in this message. I'll call that link Wolfram.

In the Wolfram calculation, the object you're trying to place would be the point at x0. The interior mesh would be represented by the line between x1 and x2. However when you're placing the object, you won't know where the intersection point will be so that the angle is 90 deg. That's where sine and cosine come in. They allow you to calculate lengths for any angle. Here's the definition of sine from Wolfram. Don't worry about all the math - we don't care about that. We only care about the fact that sine gives you the length of the side opposite to the angle. Cosine gives you the length of the side adjacent to the angle. Honestly when I've been messing with this stuff in Oblivion script, I often don't know whether to use sin or cos, so you try both and see which gives you the correct result.

In terms of editor size, it's not really a size as I said. It's only a number that you can use for comparative purposes. I use it in the script I posted above to determine the relative size of books being stacked. The only way you could use it is if you catalogued all the interior meshes, like I did with the books. Those are the arrays my script uses. If you could use the editor size to be able to define default values for L, W and H then it might be useful, but I would think there would be too much variance for that to help. In other words, two interior meshes would have the same editor sizes, but the individual dimensions would be drastically different.

Share this post


Link to post
Share on other sites

Have a look at the latest OBSE documentation. There's a function called GetBoundingSphere that might help. I also notice there are matrix and vector functions that might help.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×