Jump to content

Script: Snap objects to ground


Recommended Posts

I was looking for a way to automate a bit my workflow and I wrote these two functions that some might find useful.

So I decided to share them:

This function returns the "ground point" of the given position:

function getGroundPoint(%pos,%terrainOnly) 
	%mask = ($TypeMasks::GameBaseObjectType | $TypeMasks::PlayerObjectType | $TypeMasks::TerrainObjectType |
		$TypeMasks::StaticTSObjectType | $TypeMasks::StaticObjectType 
       | $TypeMasks::WaterObjectType |  $TypeMasks::DynamicObjectType
       |  $TypeMasks::RigidObjectType );
		%mask = $TypeMasks::TerrainObjectType ;
	%endPos = %pos;
	%endPos.z = -10000;
	%result = 0;
	%result = containerRayCast(%pos, %endPos, %mask);
		%endPos.z = 10000;
		%result = containerRayCast(%pos, %endPos, %mask);
	   %retval = %pos.x SPC %pos.y SPC getWord(%result,3);
		warn("getGroundPoint(): RayCast can't find any object in range! Returning original position.");
		%retval = %pos;
	return %retval;


And this one snaps a given object to the ground respecting its scale and preserving rotation:


function putOnGround(%obj)
	%transform = %obj.getTransform();
	%pos = getWords(%transform, 0, 2);
	%rot = getWords(%transform, 3, 6);
	%groundPos = getGroundPoint(%pos);
	%groundPos.z += %pos.z - getWord(%obj.getWorldBox(),2);
	%newTransform = %groundPos SPC %rot;


here's some images to show the result:

The code is called from the console and is as simple as









and here with scale and rotated along an axis:





Link to comment
Share on other sites

I'm glad you like it!

Technically it could also stack an object over another to make building blocks(see the rayCast mask).

Personally, I'll use it to spawn aircrafts directly on the carrier deck etc..

Link to comment
Share on other sites

So you can snap objects of different sizes proper to the terrain and onto each other?

This sounds to me like the missing proper snapping function, if it works I would suggest to add it to the main repo as additional snapping option.

Link to comment
Share on other sites

Not to throw water on your fireworks, but terrain snapping for general object creation has been there forever:

T3D 1.2 -


Just click that button to toggle this mode.

The part about snapping objects down on other objects is very nice, though. If the current snap were updated with that it would make things like placing objects on top of cave entrance geometry very easy.

All of that said - thank you for sharing! This script gives one the option of binding a key so that only the objects one wants to snap can be handled individually instead of wholesale based on editor snap mode.

Edited by rlranft
Link to comment
Share on other sites

@rlranft I already knew about the editor snapping function, but I wasn't sure if it would snap also in non-editor mode and/or on other shapes that are not a terrain. The point of the functions is to help me spawn (in my case)aircrafts over stuff like rigidShapes etc. by script and at random places.

For the cave I'd suggest to try by giving to castray a negative value and also change here:

groundPos.z += getWord(%obj.getWorldBox(),2) - %pos.z; //inverted the order to snap to top

to make it snap from top(otherwise it would snap inside the shape).

I'm not sure tho if it wold work..

Link to comment
Share on other sites

Ah - no, I don't think the snap works outside of the editor.

But for the cave - I wasn't thinking inside as much as outside. When covering the hole in the terrain for the cave I usually use a model or collection of them, and because this script will snap to other objects it should be able to place "flavor" objects on top of this stuff.

As far as inside of a cave, that can be tricky - if your raycast starts from the "snapping" object's origin then it should work as is as long as you're inside the cave (because the object should be created by default at or near the camera) when you create the object. It would then be picking up the next object correctly (the cave) but you would then want to set the snapping object's position to the intersection point. Optionally, you could set the up vector to the face normal at the intersection point as well.

As I said - it's definitely a handy script, thanks for sharing.

Link to comment
Share on other sites

I was wondering about what @rlranft suggested..picking up the raycast contact point normal could also add the correct rotation to the object. Tomorrow I'll try to make some experiments but I'm not sure if I have the math to get the object rotation from the contact point normal..

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Create New...