Funfair ride multiple angles problem

Started by
4 comments, last by jkanters 14 years, 8 months ago
Hello, as you see I'm new here. I registered because I have and a question and ofcourse help other people on the forums whenever possible. I'm working on a funfair ride simulation which requires more math than I thouht at first. The movement is based on this ride:
(see from 1:00 for a clear view) Mine however will have free-swinging vehicles (like http://www.kermisworld.nl/snowjet4.jpg) In a 3d program i made a quick simulation of the movements and the moving parts, this will help alot. http://www.jefrome.nl/01.avi. I loaded the seperate models into a 3d engine and now the position of those models has to be defined by some math. So the situation of the moving parts is this: (see video) Arm01 is the main arm. (the bottom yellow one) -it is positioned at zeropoint -length=400 Arm02 is the lifting arm (the red arm that can angle to 55 degrees) -it is attached to the end of Arm01 -can angle up to 55 degrees -lenght=600 Cross01 is the circular frame where the vehicles are attached to -attached to the end of Arm02 -radius = 560 Vehicle01 is one of the swinging vehicles (colored cubes in the video) -It is attached to Cross01 Until the point of lifting up arm02, things went very well: --- //mechanics //arm02 tot arm01 Arm02Position.X = Arm01Position.X - (float)(Math.Cos(Arm01RotationY) * 400); Arm02Position.Z = Arm01Position.Z + (float)(Math.Sin(Arm01RotationY) * 400); Arm02Position.Y = Arm01Position.Y + 50; Arm02RotationY = Arm01RotationY; //move along with arm01 Arm02RotationZ = MathHelper.ToRadians(Arm02Angle); //lifting angle //kcross01 tot arm01 Cross01Position.X = Arm02Position.X + ((float)(Math.Cos(Arm02RotationY)*600)))); Cross01Position.Z = Arm02Position.Z - ((float)(Math.Sin(Arm02RotationY)*600)))); Vehicle01RotationY = Cross01RotationY + Arm01RotationY; Vehicle01Position.X = Cross01Position.X - (float)(Math.Cos(Vehicle01RotationY) * 560); Vehicle01Position.Z = Cross01Position.Z + (float)(Math.Sin(Vehicle01RotationY) * 560); -- When the ride lifts up(arm02angle increases) things get difficult. For example the Vehicle01 follows a 'horizontal' radius of 560(radius of the cross01). When the Cross01 is under for example 45 degrees, this horizontal radius is smaller, and a 'vertical' radius is added. Maybe hard to explain, but I'm trying. What it comes down to: What combination of formulas do I need to use, to let met Vehicle follow the Cross? Thanks for any help! Jeroen
Advertisement
Maybe this is an easier approach which illustrates my problem too:

http://www.jefrome.nl/02.jpg

The red box follow the black circle using this code:

box_pos.X -= (float)(Math.Cos(rotation_angle) * circle_radius);
box_pos.Z += (float)(Math.Sin(rotation_angle) * circle_radius);

The grey circles are in fact the black circle under a certain angle.

What should my coding be like to let the box follow the circle when it's under an angle?

Thanks for your time,

Jeroen
This would be a terrible system to have to write out in longhand. As a product of transformations, however, it's not that difficult.

Assuming:
* a right-handed Z-up coordinate system,
* the center-bottom of your ride is at the origin,
* a base elevation hinge at a radius b, located by default in the positive X axis,
* a hinge angle of φ,
* a bottom rotation angle of θ1, and
* a top rotation angle of θ2,

the transformation from world space to the top gimbal (around which all the cars are spinning at a fixed radius) can be given as G = Rz(θ1)T(b,0,0)Ry(-φ)T(-b,0,0)Rz(θ2). From there, given that cars are at a radius r from the top gimbal, an individual car at base angle θ3 and current swing angle γ will have world transformation G*Rz(θ3)T(r,0,0)Ry(γ).

Building up these transformations piece-by-piece is much easier than deriving the equivalent trigonometric equations, and has the additional advantage of having the math done for you by any 3D graphics library out there.

[Edited by - Sneftel on August 25, 2009 11:37:53 AM]
if you have a square (centered on the origin) with vertices v1, v2, v3, v4 then you can rotate them about the y axis (y bein g up) like so:

Matrix rotation1;
rotation1.LoadFromAxisAngle(0, 1, 0, angle);

v1 = rotation1 * v1;
v2 = rotation1 * v2;
v3 = rotation1 * v3;
v4 = rotation1 * v4;

Now what if you wanted to rotate it 90 degrees about the z axis (so its its side) and still have it keep rotating.

First you rotate it as before, then you rotate in 90 degrees about the z axis

Matrix rotation2;
rotation2.LoadFromAxisAngle(0, 0, 0, 90);

finalRotation = rotation2*rotation1;

v1 = finalRotation*v1
v2 = finalRotation*v2
v3 = finalRotation*v3
v4 = finalRotation*v4

That would rotate about the y axis then rotate onto its side (only work once thoguh).

I think that was probably a bit confusing :P. Again, a square lies flat, it spins around its y axis then the entire thing rotates on its z axis

[/source]
Matrix spin, zAxisRot, final;

zAxisRot.CreateFromAxisAngle(0, 0, 1, 45);

float spinAngle = 0;
loop:
spin.LoadFromAxisAngle(0, 1, 0, spinAngle);
final = zAxisRot*spin;

Apply matrix
draw square
spinAngle+=;[/source]

If you coded that you should get a square spinning around at a 45 degree angle.

You need to do your rotations as either quaternions or matrices and you need to do a hierachial thing.
Base is parent of the arm
arm is parent of the spinning disc on top

spinning disc on top has a local rotation (as if it was flat)
arm has a slight rotation (relative to it being flat)
Base also has its own rotation

What are you using to render?

Apply Base rotation
Draw Base
Apply arm rotation (which should multiply by the current transform)
Draw Arm
Apply disc rotation (which should multiply by previous transforms)
Draw Top

It should be fairly straight forward once you get some transformations sorted.

First I suggest you use a nicer way to represent your rotations (and translations). I'd suggest you make a matrix class. It will make everything so much easier.

Interested in Fractals? Check out my App, Fractal Scout, free on the Google Play store.

Ok I found this idea kinda interesting and had a quick go myself. Nothing fancy but perhaps it'll give you some ideas. Its opengl:

http://www.scurvy-sea-dog.com/Fair.wmv

class	Transform{public:	Transform()	{		m_Transform.LoadIdentity();	}	void Update()	{		m_Transform.LoadFromTransRot(m_Position, m_Rotation);		// need tot ranspose the matrix for opengl		m_Transform.Transpose();	}	Engine::Vector		m_Position;	Engine::Quaternion	m_Rotation;	Engine::Matrix4x4	m_Transform;};class Model{	Transform	m_Base;	Transform	m_Arm;	Transform	m_Top;	float		m_ArmAngle;	bool Model::Initialise()	{		m_Base.m_Position.Set(0, 0, 0.25, 1);		m_Base.Update();				m_Arm.m_Position.Set(0, 0.05f, -1, 1);		m_Arm.Update();			m_Top.m_Position.Set(0, 0.05f, 1, 1);		m_Top.Update();			return true;	}	void Model::Render()	{		// rotate base position		Quaternion r;		r.CreateFromAxisAngle(0, 1, 0, DegToRad(-2));		m_Base.m_Position = r*m_Base.m_Position;			// rotate base		r.CreateFromAxisAngle(0, 1, 0, DegToRad(1));		m_Base.m_Rotation = r*m_Base.m_Rotation;		m_Base.Update();			// move arm up and down		static float angle = 0;		angle+= 0.05f;		m_ArmAngle = 0.75f*(sin(angle)+1)*0.5f;		m_Arm.m_Rotation.CreateFromAxisAngle(-1, 0, 0, m_ArmAngle);		m_Arm.Update();			// rotate top		r.CreateFromAxisAngle(0, 1, 0, DegToRad(-5.0f));		m_Top.m_Rotation = r*m_Top.m_Rotation;		m_Top.Update();			m_Camera->SetPosition(m_Center);		Vector position = m_Camera->GetPosition();		Vector target = position + m_Camera->GetView();		Vector up = m_Camera->GetUp();			glPushMatrix();			// scale so near plane doens't clip so easily		glScalef(10, 10, 10);			gluLookAt(VectorSplit3(position), 			VectorSplit3(target), 				VectorSplit3(up));			glColor3f(1, 0, 0);		glPushMatrix();		glMultMatrixf(m_Base.m_Transform[0]);		DrawSquare(2, 2);		glColor3f(0, 0, 1);		glMultMatrixf(m_Arm.m_Transform[0]);		DrawRect(0.2f, 1);		glColor3f(0, 1, 0);		glMultMatrixf(m_Top.m_Transform[0]);		DrawSquare(0.5, 0.5);		glPopMatrix();		DrawAxis();		glPopMatrix();	}};void DrawSquare(float x, float y){	x /= 2;	y /= 2;	glBegin(GL_QUADS);	glVertex3f(-x, 0, -y);	glVertex3f(-x, 0, y);	glVertex3f(x, 0, y);	glVertex3f(x, 0, -y);	glEnd();}void DrawRect(float w, float l){	w /= 2;	glBegin(GL_QUADS);	glVertex3f(-w, 0, 0);	glVertex3f(-w, 0, l);	glVertex3f(w, 0, l);	glVertex3f(w, 0, 0);	glEnd();}


Obviously is a rushed job :P

Interested in Fractals? Check out my App, Fractal Scout, free on the Google Play store.

Thank you all for your suggestions! I managed to get it work properly now with the matrix translations. I should have thought of this myself before.

The only thing left now is the swing of the vehicles. Lot of gravity math is included with that.

The angle increases when the disc rotates faster. But when the main arm(arm01) rotates there's some kind of exenter so the vehicles angle changes a bit.

Also ofcourse when the disc tilts there should be change, and also when the disc is tilt and the rest of the arms is still. I'm trying to figure out how to implement all these movements in a formula but it's hard.

Maybe someone hass a suggestion for this?

This topic is closed to new replies.

Advertisement