quaternion rotations ..

Oct 11, 2010 at 2:13 PM

Hi in order to overcome problems with mouse rotation, i.e. when flipping object, mouse drag orientation goes into reverse

i tryed to implemenent a solution depending on quaternions  this way:

              double mouseAngle = 0;
                if (dx != 0 && dy != 0)
                    mouseAngle = Math.Acos(Math.Abs(dy) / Math.Sqrt(Math.Pow(dx, 2) + Math.Pow(dy, 2)));
                    if (dx < 0 && dy > 0) mouseAngle += Math.PI / 2;
                    else if (dx < 0 && dy < 0) mouseAngle += Math.PI;
                    else if (dx > 0 && dy < 0) mouseAngle += Math.PI * 1.5;
                else if (dx == 0 && dy != 0) mouseAngle = Math.Sign(dy) > 0 ? Math.PI / 2 : Math.PI * 1.5;
                else if (dx != 0 && dy == 0) mouseAngle = Math.Sign(dx) > 0 ? 0 : Math.PI;

                double axisAngle = mouseAngle + Math.PI / 2;

                Balder.Math.Vector axis = new Balder.Math.Vector((float)Math.Cos(mouseAngle), (float)Math.Sin(mouseAngle), 0);
                double rotation = 0.001 * Math.Sqrt(Math.Pow(dx, 2) + Math.Pow(dy, 2));

                if (true)
                    if (_geometryObject != null)
                            var quaternionAxisAngle = new Balder.Math.Quaternion(axis, (float)rotation );// * (180 / Math.PI))


                            quaternionMatrix = (Balder.Math.Matrix)quaternionAxisAngle;

                            _geometryObject.World = _geometryObject.World * quaternionMatrix;
basically making quaternions from pre defined mouse axes, and use the corresponding matrix on world, 
but the geometryObject moves in mysterious ways.. each mouse move event makes a mirrored view of preceding geometryObject view
concurrently with the rotation around the axis !! 
could this version dating to 2010-09-24_10:47 be brokken ? 
or is this way of exploiting quaternions just not right for this kind of problem ? 
is balder shipped with another solution to rotation with out reversion of mouse drag movements ?? 
thanks in advance 
Oct 11, 2010 at 9:36 PM

Which mouse events are you using? 

There is also the Manipulation events in Balder, might be useful.

Oct 12, 2010 at 7:48 AM

i'm using a combination of mouse_move and  mouse_left_button_down and mouse_left_button_up, in order to distinguish double and single clicks

when single click - geometryObject should move in a intuitive way, meaning horizontal mouse move should rotate around y-axis

and vertical should rotate around x-axis, but 90 degrees rotation around y-axis should not reverse the  x-axis rotation ! 

the first part of the above code is a hack from a wpf implementation  exploiting  wpf QuaternionRotation3d class.

unfortunately i have never understood the Manipulation events, but i have resently discovered they can be accesed from Geometry class

so i'll have a look at it immediately , thanks

Oct 15, 2010 at 1:30 PM


Do you have regular Silverlight objects floating on top of the Balder Game ?  

If so, that might be the problem why you're getting strange Mouse behavior. Problem is that the elements you place on top will not route the mouse events back to the Game, since it is not in the same VisualTree, but in a parallel tree. 


Oct 18, 2010 at 1:42 PM
Edited Oct 18, 2010 at 1:44 PM

Argh haven't thought of that !

yes i have textblocks floating around as labels for each vertex !

but they didn't impact upon setting geometry.Rotation property, with mouse_move event coords,

and i really need those labels, but thank for pointing this out, i will try investigate if they are the course.


Oct 18, 2010 at 2:23 PM

I have an idea of how we might be able to make this work, even if you have things floating on top. So all hope is not lost. :)

Oct 18, 2010 at 4:23 PM
Edited Oct 18, 2010 at 7:20 PM

Hi boandersen,

I hope I'm not disturbing here, but I'd really like to know how you made those floating labels. Did you place TextBlocks with Canvas.Top and Canvas.Left on top of the Game? What method did you use to determine the right 2D coordinates with respect to your 3D objects?

Oct 19, 2010 at 2:28 PM

i used code like this :

 private void DrawNodeLabels(SVSGeometryNode node)
            if (!_labelNodeMap.ContainsKey(node.Node))
                // calc screencoords
                actualCoords.X = (float)node.Pos.X;
                actualCoords.Y = (float)node.Pos.Y;
                actualCoords.Z = (float)node.Pos.Z;
                screenCords = theGame.Viewport.Project(actualCoords, geometryToLabelize.ActualWorld);
                if (Double.IsNaN(screenCords.X) || Double.IsNaN(screenCords.Y) || Double.IsNaN(screenCords.Z))

                txtBlk = new TextBlock();
                if (_isToolTipped)// _tooltipped
                    txtBlk.Text = " ";
                    txtBlk.SetValue(ToolTipService.ToolTipProperty, node.Node.ToString());
                    // move triggering textblock into node center
                    screenCords.X *= 0.99f;
                    screenCords.Y *= 0.99f;
                    txtBlk.Text = node.Node.ToString();
                txtBlk.Foreground = new SolidColorBrush(System.Windows.Media.Colors.Black);
                txtBlk.TextAlignment = TextAlignment.Left;
                txtBlk.FontSize = _fontSize;
                txtBlk.Height = txtBlk.ActualHeight;
                txtBlk.Width = txtBlk.ActualWidth;
                TextOptions.SetTextHintingMode(txtBlk, TextHintingMode.Animated);

                _labelNodeMap[node.Node] = txtBlk;

                _labelNodeMap[node.Node].SetValue(Canvas.LeftProperty, screenCords.X + dxPaningOffset);
                _labelNodeMap[node.Node].SetValue(Canvas.TopProperty, screenCords.Y + dyPaningOffset);


            //else throw new Exception("fejl: metode:DrawTextBlock - ingen værdi til nodenummer : " + label);

 this method draws one label each node / vertex in mesh, in order to get 2d coords balder offers viewport project method.

each corresponding textblock is referenced in dictionary  and the attached properties canvas.left n top are invoked with new cords each game_update event (not showed).

the dx- dypaningOffset is used when user is paning/draging geometry around !

good coding

Oct 19, 2010 at 2:53 PM

thanks adept, i have tryed out the solution without the textblocks and also tryed to use a fixed angle vector (1,0,0) but the problem with the quaternion solution remains !

the rotation is very incoherent ! but another solution will certainly also do


Oct 19, 2010 at 3:00 PM

oh i forgot to mention, i have also tried another solution to the problem.

something like using an zRotationMatrix because this seems to fix the reversing of axis problem in a very easy and

elegant way.

rotationMatrix = Balder.Math.Matrix.CreateRotationZ(Balder.Math.MathHelper.ToDegrees((float)-dx))
but even when only adjusting Z and X orientation this way, the Y axis (slowly) gets distorted / influenced !!
is there any easy way to avoid this corruption ? 
Oct 19, 2010 at 8:56 PM

Is it possible for you to extract these problems into a small project that reproduces it and send it to me? Would help a lot for me to understand the problem and find a solution.

Oct 20, 2010 at 10:27 AM

Hi again, i have extracted  a compressed vs solution called 'ShowProject' to download from  ftp://ftp.netic.dk/Upload/Balder/   (you may have to use username = svibs-anon password = svibs ) 

there's an blue cube object with a  red side  that gets rotated with quaternions / matrix on Mouse_Move event.

also theres an OuterBox / bounding box even thoug this doesn't influence the rotation in my experience !


it's also possible to set a property _showWireFrameVisibleProblem  on MainPage object

when set to true an inner box with wireframe show that wireframes, rendered in another geometry object, penetrade surfaces on outer box geometry, but i admit that i'm still using old balder version

so this is hardly not relevant .

thanks in advance

Oct 20, 2010 at 9:21 PM


I didn't find the project on your FTP, only the Wireframe_problem.jpg.

PS: You might want to limit that user to that folder only, since you're giving the credentials away in a public forum. Or just drop the solution in a public Dropbox folder and share the URL for that instead. I could browse around the FTP (don't worry I didn't peek at anything, just wanted to see if you'd placed the project in a different folder).

Oct 21, 2010 at 7:50 AM

Oh sorry about that, is see that you are quite right !

now it's checked and ready to fetch.

Yes this approach  to sharing isn't the safest, but it's ok with my boss and it was the most easy one

and now wi'll have to change the credentials - lol

Oct 21, 2010 at 7:40 PM


You can change the credentials now. I've got the file.

I'm going away for the weekend, but will start looking at it on Monday. Sorry its taking so much time to get it done. 

Oct 22, 2010 at 12:07 PM

thanks anyway, we all, here at SVS thinks it,s a great 3d engine

so it's worth wayting  a little  :-)

Oct 27, 2010 at 10:25 AM


    I have just started using Balder 3D engine, reading the above post it seems that every silverlight object has to be rendered through Balder programming only, else it gives co-ordinate problem.

    I was wondering if that is worth the pain? I have done rotating element around a particular axis with Matrix class can you tell me how to drag that to some other position ?

Oct 27, 2010 at 6:26 PM

I'm not sure I understand your question; but I'll try. Regular Silverlight objects does not and can't be rendered through Balder. Its only Balder objects that need to be within Balder and rendered by Balder. 

You can easily have objects under the rendered surface of Balder, and on top of it as well. 


As for moving an object around in 3D. I would need to get back to you, I don't have a great answer at this point. What I'm looking into is to create a Behavior that you can just attach to any object - or even the game itself and objects will be possible to directly interact with. 

Oct 27, 2010 at 6:58 PM

boandersen: I'm still investigating your problem. I think I ignored a vital piece of information from you; Windows XP + Silverlight 3. I'm on Windows 7 + Silverlight 4. So I'm setting up a dev environment on Windows XP right now to see if I can see your problems. 

Oct 27, 2010 at 8:27 PM


Not quite understanding whats going on here. I think its a combination of several things.
First of all, the manipulation events - the node picking seems to be quite off when the objects are scaled. So I need to investigate that a bit more.

Secondly, I think there is something going on in your algorithm. I scaled things to 1 and moved the camera and disabled your events and just set the InteractionEnabled to true for the objects and interaction was as expected.

Btw: this is a general problem, not related to WinXP + SL3. I completely forgot about your project and tried reproducing the problem myself - so much for taking some days off, goldfish memory kicks in pretty fast.  

Oct 27, 2010 at 8:28 PM
This discussion has been copied to a work item. Click here to go to the work item and continue the discussion.
Nov 1, 2010 at 12:36 PM
autivrushali : 

I have implemented an working solution to this problem by just

using geometry.position to move object an holding current x,y position in floats

Nov 1, 2010 at 1:07 PM
Edited Nov 1, 2010 at 2:09 PM
adept :

sorry i haven't replyed for a long time, but have been away for doing some urgent reporting stuff

When i try do the same things nothing seems to happen over here !

i just removed the scalefactor, this makes the visible cube very small though

but i can't change the camera distance in anyway that changes the viewable cube size !! not even the coords 

new Coordinate(0, 1, -2) make a change in viewable size ! 
InteractionEnabled property seems to be working for a very limited range of camera distances 
when i size the cube by setting dimensionAsVector to (50,50,50  in order to see anything ), it seems like interaction works correct when camera distance at 
the edge of cube, and thereby culling some faces !  but is there a way of calculating working camera distance ? 
or even better could i get a copy of your changed and working source ? 
you could just use the existing //ftp.netic.dk/Upload/Balder/  to upload to cause i still haven't changed the credentials ?