adambeer Posted February 16, 2015 Share Posted February 16, 2015 Im trying to align a building properly on a sphere surface and am having trouble with the code behind it. I know the ProxMine does something like this when its deployed, but thats in source code. I looked there and cant seem to figure out the script conversion. Heres whats in source: // Align to deployed surface normal MatrixF mat( true ); MathUtils::getMatrixFromUpVector( normal, &mat ); mat.setPosition( pos + normal * mObjBox.minExtents.z ); delta.pos = pos; delta.posVec.set(0, 0, 0); ShapeBase::setTransform( mat ); Anyone have any ideas on how to do this? Quote Link to comment Share on other sites More sharing options...
rlranft Posted February 17, 2015 Share Posted February 17, 2015 Alright - in theory, you could raycast and get the surface normal of the point of intersection like this:%ray = VectorScale(%ray, 1000); %end = VectorAdd(%start, %ray); // only care about the following object types %searchMasks = $TypeMasks::TerrainObjectType | $TypeMasks::StaticTSObjectType | $TypeMasks::InteriorObjectType | $TypeMasks::ShapeBaseObjectType | $TypeMasks::StaticObjectType; // search! %scanTarg = ContainerRayCast( %start, %end, %searchMasks); if (%scanTarg) { %obj = getWord(%scanTarg, 0); while (%obj.class $= "barrier") { // Get the X,Y,Z position of where we clicked %pos = getWords(%scanTarg, 1, 3); %restart = VectorNormalize(VectorSub(%end, %pos)); %pos = VectorAdd(%pos, %restart); %scanTarg = ContainerRayCast( %pos, %end, %searchMasks); %obj = getWord(%scanTarg, 0); } // Get the X,Y,Z position of where we clicked %pos = getWords(%scanTarg, 1, 3); // Get the normal of the location we clicked on %norm = getWords(%scanTarg, 4, 6); // do something with normal data }This works for placing decals - as seen in the RTS Prototype. I guess you'd have to translate the normal into some sort of rotation and apply it to your model..... Quote Link to comment Share on other sites More sharing options...
adambeer Posted February 17, 2015 Author Share Posted February 17, 2015 The translation from the surface normal to the shapes rotation is the part I dont understand how to do. Im glad that ive started correctly though, thanks! Quote Link to comment Share on other sites More sharing options...
rlranft Posted February 17, 2015 Share Posted February 17, 2015 Oh, well, hell - I think there's a helper function in the console interface somewhere - I'll try to remember to look it up when I get home. Quote Link to comment Share on other sites More sharing options...
adambeer Posted February 20, 2015 Author Share Posted February 20, 2015 Any luck finding that helper function? Quote Link to comment Share on other sites More sharing options...
rlranft Posted February 20, 2015 Share Posted February 20, 2015 No, but in engine/math/mathUtils.cpp there is a getMatrixFromUpVector() that might be a good start. In that same file there is a getAnglesFromVector() function that might be helpful too.Have to expose them to the console, then figure out how to convert either the matrix or the angles to a transform..... Quote Link to comment Share on other sites More sharing options...
Atomic Walrus Posted February 24, 2015 Share Posted February 24, 2015 Stick this at the end of mathTypes.cpp (for some reason all the mathutil console function hooks are here so you won't need to add any headers): DefineConsoleFunction( VectorGetMatrixFromUpVector, TransformF, ( VectorF vec ),, "@Create a matrix from the up vector.\n\n" "@param VectorF (x,y,z) up vector.\n" "@return TransformF.\n" "@ingroup Vectors" ) { MatrixF outMat; MathUtils::getMatrixFromUpVector(vec, &outMat); return outMat; } The data that comes back will be in the "TransformF" format which means words 0-2 are position and 3-6 are rotation (axis angle). In script you can do something like this: %mat = VectorGetMatrixFromUpVector(%normal) %outTrans = %object.getPosition() SPC getWords(%mat, 3, 6); %object.setTransform(%outTrans); All of your placed objects will have 0 rotation around the normal (because the normal vector obviously contains no info about that rotation) like the mines. If you want to rotate about the normal it should be a simple matrix multiplication like this: void WorldEditorSelection::rotate(const EulerF &rot) { for( iterator iter = begin(); iter != end(); ++ iter ) { SceneObject* object = dynamic_cast< SceneObject* >( *iter ); if( !object ) continue; MatrixF mat = object->getTransform(); MatrixF transform(rot); mat.mul(transform); object->setTransform(mat); } } But again you need to expose some math helpers to script (or just attach a function like this to sceneobject and expose THAT to script).The script-end handling of object rotation isn't very good in general. I'd like to have euler angles exposed (along site the current axis angle interface) and some rotation functions that can do both of the relative rotations the editor handles (world and local yaw/pitch/roll). Quote Link to comment Share on other sites More sharing options...
adambeer Posted February 25, 2015 Author Share Posted February 25, 2015 Thank you very much for that! Currently Im using this code: %normal = getWords(%building.getTransform(), 0, 2); %normalN = vectorNormalize(%normal); %axis = VectorCross(%normalN, "0 0 1"); %angle = mACos(vectorDot(%normalN, "0 0 1")); %rot = %axis SPC %angle; // get the world position of the click %pos = getWords(%building.getTransform(), 0, 2); // Reposition the building %building.setTransform(%pos SPC %rot); The first line I have with the normal just using the position is because the object im trying to align to is a sphere at 0 0 0, so I thought it was safe to assume that the vector from 0 0 0 to the building position would be just the position.My code seems to work fine for the most part but the alignment is a bit off and when a building is closer to the bottom of the sphere it seems to get squished and disfigured. Not sure whats causing that but Ill try using your method above to see if it works better and fixes that issue. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.