How to modify this code to return Geopoint - class

I would like this code to return a newly constructed geopoint.
I need this,
GeoPoint prjTest=new GeoPoint(vxi+x,vyi+y);
to stick somewhere and return prjTest. I'm new to programming and I don't know well synthax.I tried many things, I can keep guessing for a long time. Please help. Thanks.
public class ProjectileTest
{
public ProjectileTest(float vi, float angle) /** renamed velocity -> vi */
{
//Starting location
double xi = 0, yi = 100;
final double gravity = -9.81;
//timeSlice declares the interval before checking the new location.
double timeSlice = 0.001; /** renamed time -> timeSlice */
double totalTime = 0; /** renamed recordedTime -> totalTime */
double vxi = vi * Math.cos(Math.toRadians(angle)); /** renamed xSpeed -> vxi */
double vyi = vi * Math.sin(Math.toRadians(angle)); /** renamed ySpeed -> vyi */
//This (secondsTillImpact) seems to give a very accurate time whenever the angle is positive.
double secondsTillImpact = Math.sqrt(2 * yi / -(gravity));
/** Not sure I agree. Does this formula take into account the upward motion
* of the projectile along its parabolic arc? My suspicion is that this
* formula only "works" when the initial theta is: 180 <= angle <= 360.
*
* Compare with the result predicted by quadratic(). Discarding the zero
* intercept which can't work for us (i.e. the negative one, because time
* only moves forward) leaves us with an expected result very close to the
* observed result.
*/
double y;
double x;/** Current position along the y-axis */
do {
// x = x + (xSpeed * time);
x = vxi * totalTime; /** Current position along the x-axis */
// y = y + (ySpeed * time);
y = yi + vyi * totalTime + .5 * gravity * (totalTime * totalTime);
// ySpeed = ySpeed + (gravity * time);
double vy = vyi + gravity * totalTime; /** Current velocity of vector y-component */
System.out.println("X: " + round2(x) + " Y: " + round2(y) + " YSpeed: " + round2(vy));
totalTime += timeSlice;
}
while (y > 0);
////////////////////////////++++++++ GeoPoint prjTest=new GeoPoint(vxi+x,vyi+y);
System.out.println("Incorrectly expected seconds: " + secondsTillImpact + "\nResult seconds: " + totalTime);
quadratic((.5 * gravity), vyi, yi);
}
public double round2(double n) {
return (int) (n * 100.0 + 0.5) / 100.0;
}
public void quadratic(double a, double b, double c) {
if (b * b - 4 * a * c < 0) {
System.out.println("No roots in R.");
} else {
double dRoot = Math.sqrt(b * b - 4 * a * c); /** root the discriminant */
double x1 = (-b + dRoot) / (2 * a); /** x-intercept 1 */
double x2 = (-b - dRoot) / (2 * a); /** x-intercept 2 */
System.out.println("x-int one: " + x1 + " x-int two: " + x2);
}
}
}

Related

cc exited with 256 while using Cairo

using Cairo ;
using Gtk ;
using GLib ;
public class ClockWidget : DrawingArea {
private Time time ;
private int minute_offset ;
private bool dragging ;
public signal void time_changed (int hour, int minute) ;
public ClockWidget () {
add_events (Gdk.EventMask.BUTTON_PRESS_MASK
| Gdk.EventMask.BUTTON_RELEASE_MASK
| Gdk.EventMask.POINTER_MOTION_MASK);
update () ;
Timeout.add (1000, update) ;
set_size_request (100, 100) ;
}
public override bool draw (Cairo.Context cr) {
int y = get_allocated_height () / 2 ;
int x = get_allocated_width () / 2 ;
var radius = double.min (get_allocated_width () / 2,
get_allocated_height () / 2) - 5 ;
// clock back
cr.arc (x, y, radius, 0, 2 * 3.14) ;
cr.set_source_rgb (1, 1, 1) ;
cr.fill_preserve () ;
cr.set_source_rgb (0, 0, 0) ;
cr.stroke () ;
// clock ticks
for (int i = 0; i < 12; i++) {
int inset ;
cr.save () ;
if (i % 3 == 0) {
inset = (int) (0.2 * radius) ;
} else {
inset = (int) (0.1 * radius) ;
cr.set_line_width (0.5 * cr.get_line_width ()) ;
}
cr.move_to (x + (radius - inset) * Math.cos (i * Math.PI / 6),
y + (radius - inset) * Math.sin (i * Math.PI / 6));
cr.line_to (x + radius * Math.cos (i * Math.PI / 6),
y + radius * Math.sin (i * Math.PI / 6));
cr.stroke ();
cr.restore ();
}
// clock hands
var hours = this.time.hour ;
var minutes = this.time.minute + this.minute_offset ;
var seconds = this.time.second ;
/* hour hand: the hour hand is rotated 30 degrees (pi/6r) per hour + 1/2 a degree (pi/360r) per minute */
cr.save () ;
cr.set_line_width (2.5 * cr.get_line_width ()) ;
cr.move_to (x, y) ;
cr.line_to (x + radius / 2 * Math.sin (Math.PI / 6 * hours
+ Math.PI / 360 * minutes),
y + radius / 2 * -Math.cos (Math.PI / 6 * hours
+ Math.PI / 360 * minutes));
cr.stroke ();
cr.restore ();
// minute hand:
// the minute hand is rotated 6 degrees (pi/30 r) per minute
cr.move_to (x, y);
cr.line_to (x + radius * 0.75 * Math.sin (Math.PI / 30 * minutes),
y + radius * 0.75 * -Math.cos (Math.PI / 30 * minutes));
cr.stroke ();
// seconds hand:
// operates identically to the minute hand
cr.save ();
cr.set_source_rgb (1, 0, 0); // red
cr.move_to (x, y);
cr.line_to (x + radius * 0.7 * Math.sin (Math.PI / 30 * seconds),
y + radius * 0.7 * -Math.cos (Math.PI / 30 * seconds));
cr.stroke ();
cr.restore ();
return false ;
}
public override bool button_press_event (Gdk.EventButton event) {
var minutes = this.time.minute + this.minute_offset;
// From
// http://mathworld.wolfram.com/Point-LineDistance2-Dimensional.html
var px = event.x - get_allocated_width () / 2;
var py = get_allocated_height () / 2 - event.y;
var lx = Math.sin (Math.PI / 30 * minutes);
var ly = Math.cos (Math.PI / 30 * minutes);
var u = lx * px + ly * py;
// on opposite side of origin
if (u < 0) {
return false;
}
var d2 = Math.pow (px - u * lx, 2) + Math.pow (py - u * ly, 2);
if (d2 < 25) { // 5 pixels away from the line
this.dragging = true;
print ("got minute hand\n");
}
return false;
}
public override bool button_release_event (Gdk.EventButton event) {
if (this.dragging) {
this.dragging = false;
emit_time_changed_signal ((int) event.x, (int) event.y);
}
return false;
}
public override bool motion_notify_event (Gdk.EventMotion event) {
if (this.dragging) {
emit_time_changed_signal ((int) event.x, (int) event.y);
}
return false;
}
private void emit_time_changed_signal (int x, int y) {
// decode the minute hand
// normalise the coordinates around the origin
x -= get_allocated_width () / 2;
y -= get_allocated_height () / 2;
// phi is a bearing from north clockwise, use the same geometry as
// we did to position the minute hand originally
var phi = Math.atan2 (x, -y);
if (phi < 0) {
phi += Math.PI * 2;
}
var hour = this.time.hour;
var minute = (int) (phi * 30 / Math.PI);
// update the offset
this.minute_offset = minute - this.time.minute;
redraw_canvas ();
time_changed (hour, minute);
}
private bool update () {
// update the time
this.time = Time.local (time_t ());
redraw_canvas ();
return true; // keep running this event
}
private void redraw_canvas () {
var window = get_window ();
if (null == window) {
return;
}
var region = window.get_clip_region ();
// redraw the cairo canvas completely by exposing it
window.invalidate_region (region, true);
window.process_updates (true);
}
static int main (string[] args) {
Gtk.init (ref args);
var window = new Window ();
var clock = new ClockWidget ();
window.add (clock);
window.destroy.connect (Gtk.main_quit);
window.show_all ();
Gtk.main ();
return 0;
}
}
How do I solve it??
This is the error displayed:
/usr/bin/ld: /tmp/ccSTGo5z.o: undefined reference to symbol 'pow##GLIBC_2.2.5'
//lib/x86_64-linux-gnu/libm.so.6: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status
error: cc exited with status 256
Compilation failed: 1 error(s), 1 warning(s)
You need to link against libm which is the library which provides the pow() function, which you’re using.
Typically this is achieved by passing -lm in your linker flags. I can’t give a more concrete answer because you haven’t said what build system you’re using.
valac -X -lm --pkg gtk+-3.0 clock_widget.vala
I had to compile it with this code.

My object is moving too fast in Unity?

I am suppose to implement a CatMull Rom Spline, and I have it implemented, but the sphere moves to the points extremely fast. I thought if I used Time.DeltaTime it would slow it down, but it moves too rapidly.
Function to compute point on curve:
Vector3 ComputePointOnCatmullRomCurve(float u, int segmentNumber)
{
// TODO - compute and return a point as a Vector3
// Points on segment number 0 start at controlPoints[0] and end at controlPoints[1]
// Points on segment number 1 start at controlPoints[1] and end at controlPoints[2]
// etc...
Vector3 point = new Vector3();
float c0 = ((-u + 2f) * u - 1f) * u * 0.5f;
float c1 = (((3f * u - 5f) * u) * u + 2f) * 0.5f;
float c2 = ((-3f * u + 4f) * u + 1f) * u * 0.5f;
float c3 = ((u - 1f) * u * u) * 0.5f;
Vector3 p0 = controlPoints[(segmentNumber - 1) % NumberOfPoints];
Vector3 p1 = controlPoints[segmentNumber % NumberOfPoints];
Vector3 p2 = controlPoints[(segmentNumber + 1) % NumberOfPoints];
Vector3 p3 = controlPoints[(segmentNumber + 2) % NumberOfPoints];
point.x = (p0.x * c0) + (p1.x * c1) + (p2.x * c2) + (p3.x * c3);
point.y = (p0.y * c0) + (p1.y * c1) + (p2.y * c2) + (p3.y * c3);
point.x = (p0.z * c0) + (p1.z * c1) + (p2.z * c2) + (p3.z * c3);
return point;
}
**Update Function: **
void Update ()
{
// TODO - use time to determine values for u and segment_number in this function call
// 0.5 Can be used as u
time += DT;
segCounter++;
Vector3 temp = ComputePointOnCatmullRomCurve(time, segCounter);
transform.position = temp;
}
Variables:
const int NumberOfPoints = 8;
Vector3[] controlPoints;
const int MinX = -5;
const int MinY = -5;
const int MinZ = 0;
const int MaxX = 5;
const int MaxY = 5;
const int MaxZ = 5;
float time = 0;
const float DT = 0.01f;
public static int segCounter = 0;
EDIT: Sorry the calculations, and all of that is correct. It's straight from the slides, I just need help with the update function :(
Using Time.deltaTime allows you to be framerate independent. This means that if the framerate drops, or a frame takes longer than the others, your object will adapt the moving distance to keep a constant speed. This is generally a good idea.
Back to your case: Basically you want to pass a position to your function. You currently pass the time. If your catmull rom considers that 0 is the start and 1 is the destination, then after exactly 1 second, you will be at the end of the spline. (Note that this is where being framerate independent is interesting: Whatever the frame rate is. you reach the end in one second). Now, how to convert from time to position. Easy
position = time*speed;
Since time is in second, speed is in units per seconds. Say your catmullrom is one unit long. If speed is two, if will take one second to travel it twice. so half a second to travel it. Since you want to lower the speed, you might want to use values below 1. Try this:
void Update ()
{
time += Time.deltaTime;
var speed = 0.1f;
var splinePos = speed * time;
segCounter++;
Vector3 temp = ComputePointOnCatmullRomCurve(splinePos, segCounter);
transform.position = temp;
}

CatmullRomSpline does not accept type arguement

I am looking to create smooth paths for my 2D game. Looking at CatmullRomSpline it is just the thing i need. Every post, even here on SE is giving it a type and passing all the control points and a Boolean with the constructor. This seems to be obsolete now, CatmullRomSpline does not accept any type parameters anymore and without it it can only work with V3 paths. Neither does the constructor accept a list of control points.
cp = new Vector2[]
{
new Vector2(0,100), new Vector2(100,600), new Vector2(300,300), new Vector2(600, 400)
};
CatmullRomSpline<Vector2> path = new CatmullRomSpline<Vector2>(cp, true);
This gives the following error: The type CatmullRomSpline is not generic; it cannot be parameterized with arguments <Vector2>.
Am i missing something or does CatmullRomSpline work differently nowadays, and how?
This is the CatmullRomSpline Class from badlogic. It surely looks like things changed, i am getting this class from "import com.badlogic.gdx.math.CatmullRomSpline;"
public class CatmullRomSpline implements Serializable { private
static final long serialVersionUID = -3290464799289771451L; private
List controlPoints = new ArrayList(); Vector3 T1 =
new Vector3(); Vector3 T2 = new Vector3();
/** Adds a new control point * * #param point the point */
public void add (Vector3 point) { controlPoints.add(point); }
/** #return all control points */ public List
getControlPoints () { return controlPoints; }
/** Returns a path, between every two control points numPoints are
generated and the control points themselves are added too. * The
first and the last controlpoint are omitted. if there's less than 4
controlpoints an empty path is returned. * * #param numPoints
number of points returned for a segment * #return the path */
public List getPath (int numPoints) { ArrayList
points = new ArrayList();
if (controlPoints.size() < 4) return points;
Vector3 T1 = new Vector3(); Vector3 T2 = new Vector3();
for (int i = 1; i <= controlPoints.size() - 3; i++) {
points.add(controlPoints.get(i)); float increment = 1.0f /
(numPoints + 1); float t = increment;
T1.set(controlPoints.get(i + 1)).sub(controlPoints.get(i -
1)).mul(0.5f); T2.set(controlPoints.get(i +
2)).sub(controlPoints.get(i)).mul(0.5f);
for (int j = 0; j < numPoints; j++) {
float h1 = 2 * t * t * t - 3 * t * t + 1; // calculate basis
// function 1
float h2 = -2 * t * t * t + 3 * t * t; // calculate basis
// function 2
float h3 = t * t * t - 2 * t * t + t; // calculate basis
// function 3
float h4 = t * t * t - t * t; // calculate basis function 4
Vector3 point = new Vector3(controlPoints.get(i)).mul(h1);
point.add(controlPoints.get(i + 1).tmp().mul(h2));
point.add(T1.tmp().mul(h3));
point.add(T2.tmp().mul(h4));
points.add(point);
t += increment; } }
if (controlPoints.size() >= 4)
points.add(controlPoints.get(controlPoints.size() - 2));
return points; }
/** Returns a path, between every two control points numPoints are
generated and the control points themselves are added too. * The
first and the last controlpoint are omitted. if there's less than 4
controlpoints an empty path is returned. * * #param points the
array of Vector3 instances to store the path in * #param numPoints
number of points returned for a segment */ public void getPath
(Vector3[] points, int numPoints) { int idx = 0; if
(controlPoints.size() < 4) return;
for (int i = 1; i <= controlPoints.size() - 3; i++) {
points[idx++].set(controlPoints.get(i)); float increment = 1.0f
/ (numPoints + 1); float t = increment;
T1.set(controlPoints.get(i + 1)).sub(controlPoints.get(i -
1)).mul(0.5f); T2.set(controlPoints.get(i +
2)).sub(controlPoints.get(i)).mul(0.5f);
for (int j = 0; j < numPoints; j++) {
float h1 = 2 * t * t * t - 3 * t * t + 1; // calculate basis
// function 1
float h2 = -2 * t * t * t + 3 * t * t; // calculate basis
// function 2
float h3 = t * t * t - 2 * t * t + t; // calculate basis
// function 3
float h4 = t * t * t - t * t; // calculate basis function 4
Vector3 point = points[idx++].set(controlPoints.get(i)).mul(h1);
point.add(controlPoints.get(i + 1).tmp().mul(h2));
point.add(T1.tmp().mul(h3));
point.add(T2.tmp().mul(h4));
t += increment; } }
points[idx].set(controlPoints.get(controlPoints.size() - 2)); }
/** Returns all tangents for the points in a path. Same semantics as
getPath. * * #param numPoints number of points returned for a
segment * #return the tangents of the points in the path */ public
List getTangents (int numPoints) { ArrayList
tangents = new ArrayList();
if (controlPoints.size() < 4) return tangents;
Vector3 T1 = new Vector3(); Vector3 T2 = new Vector3();
for (int i = 1; i <= controlPoints.size() - 3; i++) { float
increment = 1.0f / (numPoints + 1); float t = increment;
T1.set(controlPoints.get(i + 1)).sub(controlPoints.get(i -
1)).mul(0.5f); T2.set(controlPoints.get(i +
2)).sub(controlPoints.get(i)).mul(0.5f);
tangents.add(new Vector3(T1).nor());
for (int j = 0; j < numPoints; j++) {
float h1 = 6 * t * t - 6 * t; // calculate basis function 1
float h2 = -6 * t * t + 6 * t; // calculate basis function 2
float h3 = 3 * t * t - 4 * t + 1; // calculate basis function 3
float h4 = 3 * t * t - 2 * t; // calculate basis function 4
Vector3 point = new Vector3(controlPoints.get(i)).mul(h1);
point.add(controlPoints.get(i + 1).tmp().mul(h2));
point.add(T1.tmp().mul(h3));
point.add(T2.tmp().mul(h4));
tangents.add(point.nor());
t += increment; } }
if (controlPoints.size() >= 4)
tangents.add(T1.set(controlPoints.get(controlPoints.size() -
1)).sub(controlPoints.get(controlPoints.size() - 3))
.mul(0.5f).cpy().nor());
return tangents; }
/** Returns all tangent's normals in 2D space for the points in a
path. The controlpoints have to lie in the x/y plane for this * to
work. Same semantics as getPath. * * #param numPoints number of
points returned for a segment * #return the tangents of the points
in the path */ public List getTangentNormals2D (int
numPoints) { ArrayList tangents = new ArrayList();
if (controlPoints.size() < 4) return tangents;
Vector3 T1 = new Vector3(); Vector3 T2 = new Vector3();
for (int i = 1; i <= controlPoints.size() - 3; i++) { float
increment = 1.0f / (numPoints + 1); float t = increment;
T1.set(controlPoints.get(i + 1)).sub(controlPoints.get(i -
1)).mul(0.5f); T2.set(controlPoints.get(i +
2)).sub(controlPoints.get(i)).mul(0.5f);
Vector3 normal = new Vector3(T1).nor(); float x = normal.x;
normal.x = normal.y; normal.y = -x; tangents.add(normal);
for (int j = 0; j < numPoints; j++) {
float h1 = 6 * t * t - 6 * t; // calculate basis function 1
float h2 = -6 * t * t + 6 * t; // calculate basis function 2
float h3 = 3 * t * t - 4 * t + 1; // calculate basis function 3
float h4 = 3 * t * t - 2 * t; // calculate basis function 4
Vector3 point = new Vector3(controlPoints.get(i)).mul(h1);
point.add(controlPoints.get(i + 1).tmp().mul(h2));
point.add(T1.tmp().mul(h3));
point.add(T2.tmp().mul(h4));
point.nor();
x = point.x;
point.x = point.y;
point.y = -x;
tangents.add(point);
t += increment; } }
return tangents; }
/** Returns the tangent's normals using the tangent and provided up
vector doing a cross product. * * #param numPoints number of
points per segment * #param up up vector * #return a list of
tangent normals */ public List getTangentNormals (int
numPoints, Vector3 up) { List tangents =
getTangents(numPoints); ArrayList normals = new
ArrayList();
for (Vector3 tangent : tangents) normals.add(new
Vector3(tangent).crs(up).nor());
return normals; }
public List getTangentNormals (int numPoints, List
up) { List tangents = getTangents(numPoints);
ArrayList normals = new ArrayList();
int i = 0; for (Vector3 tangent : tangents) normals.add(new
Vector3(tangent).crs(up.get(i++)).nor());
return normals; } }
Your code should work fine according to the api and the source.
The class IS generic. You must be using some old version of the class.
Update to the latest version and the error should be solved.
Hope this helps.

iOS OpenGL ES 2.0 Quaternion Rotation Slerp to XYZ Position

I am following the quaternion tutorial: http://www.raywenderlich.com/12667/how-to-rotate-a-3d-object-using-touches-with-opengl and am trying to rotate a globe to some XYZ location. I have an initial quaternion and generate a random XYZ location on the surface of the globe. I pass that XYZ location into the following function. The idea was to generate a lookAt vector with GLKMatrix4MakeLookAt and define the end Quaternion for the slerp step from the lookAt matrix.
- (void)rotateToLocationX:(float)x andY:(float)y andZ:(float)z {
// Turn on the interpolation for smooth rotation
_slerping = YES; // Begin auto rotating to this location
_slerpCur = 0;
_slerpMax = 1.0;
_slerpStart = _quat;
// The eye location is defined by the look at location multiplied by this modifier
float modifier = 1.0;
// Create a look at vector for which we will create a GLK4Matrix from
float xEye = x;
float yEye = y;
float zEye = z;
//NSLog(#"%f %f %f %f %f %f",xEye, yEye, zEye, x, y, z);
_currentSatelliteLocation = GLKMatrix4MakeLookAt(xEye, yEye, zEye, 0, 0, 0, 0, 1, 0);
_currentSatelliteLocation = GLKMatrix4Multiply(_currentSatelliteLocation,self.effect.transform.modelviewMatrix);
// Turn our 4x4 matrix into a quat and use it to mark the end point of our interpolation
//_currentSatelliteLocation = GLKMatrix4Translate(_currentSatelliteLocation, 0.0f, 0.0f, GLOBAL_EARTH_Z_LOCATION);
_slerpEnd = GLKQuaternionMakeWithMatrix4(_currentSatelliteLocation);
// Print info on the quat
GLKVector3 vec = GLKQuaternionAxis(_slerpEnd);
float angle = GLKQuaternionAngle(_slerpEnd);
//NSLog(#"%f %f %f %f",vec.x,vec.y,vec.z,angle);
NSLog(#"Quat end:");
[self printMatrix:_currentSatelliteLocation];
//[self printMatrix:self.effect.transform.modelviewMatrix];
}
The interpolation works, I get a smooth rotation, however the ending location is never the XYZ I input - I know this because my globe is a sphere and I am calculating XYZ from Lat Lon. I want to look directly down the 'lookAt' vector toward the center of the earth from that lat/lon location on the surface of the globe after the rotation. I think it may have something to do with the up vector but I've tried everything that made sense.
What am I doing wrong - How can I define a final quaternion that when I finish rotating, looks down a vector to the XYZ on the surface of the globe? Thanks!
Is the following your meaning:
Your globe center is (0, 0, 0), radius is R, the start position is (0, 0, R), your final position is (0, R, 0), so rotate the globe 90 degrees around X-asix?
If so, just set lookat function eye position to your final position, the look at parameters to the globe center.
m_target.x = 0.0f;
m_target.y = 0.0f;
m_target.z = 1.0f;
m_right.x = 1.0f;
m_right.y = 0.0f;
m_right.z = 0.0f;
m_up.x = 0.0f;
m_up.y = 1.0f;
m_up.z = 0.0f;
void CCamera::RotateX( float amount )
{
Point3D target = m_target;
Point3D up = m_up;
amount = amount / 180 * PI;
m_target.x = (cos(PI / 2 - amount) * up.x) + (cos(amount) * target.x);
m_target.y = (cos(PI / 2 - amount) * up.y) + (cos(amount) * target.y);
m_target.z = (cos(PI / 2 - amount) * up.z) + (cos(amount) * target.z);
m_up.x = (cos(amount) * up.x) + (cos(PI / 2 + amount) * target.x);
m_up.y = (cos(amount) * up.y) + (cos(PI / 2 + amount) * target.y);
m_up.z = (cos(amount) * up.z) + (cos(PI / 2 + amount) * target.z);
Normalize(m_target);
Normalize(m_up);
}
void CCamera::RotateY( float amount )
{
Point3D target = m_target;
Point3D right = m_right;
amount = amount / 180 * PI;
m_target.x = (cos(PI / 2 + amount) * right.x) + (cos(amount) * target.x);
m_target.y = (cos(PI / 2 + amount) * right.y) + (cos(amount) * target.y);
m_target.z = (cos(PI / 2 + amount) * right.z) + (cos(amount) * target.z);
m_right.x = (cos(amount) * right.x) + (cos(PI / 2 - amount) * target.x);
m_right.y = (cos(amount) * right.y) + (cos(PI / 2 - amount) * target.y);
m_right.z = (cos(amount) * right.z) + (cos(PI / 2 - amount) * target.z);
Normalize(m_target);
Normalize(m_right);
}
void CCamera::RotateZ( float amount )
{
Point3D right = m_right;
Point3D up = m_up;
amount = amount / 180 * PI;
m_up.x = (cos(amount) * up.x) + (cos(PI / 2 - amount) * right.x);
m_up.y = (cos(amount) * up.y) + (cos(PI / 2 - amount) * right.y);
m_up.z = (cos(amount) * up.z) + (cos(PI / 2 - amount) * right.z);
m_right.x = (cos(PI / 2 + amount) * up.x) + (cos(amount) * right.x);
m_right.y = (cos(PI / 2 + amount) * up.y) + (cos(amount) * right.y);
m_right.z = (cos(PI / 2 + amount) * up.z) + (cos(amount) * right.z);
Normalize(m_right);
Normalize(m_up);
}
void CCamera::Normalize( Point3D &p )
{
float length = sqrt(p.x * p.x + p.y * p.y + p.z * p.z);
if (1 == length || 0 == length)
{
return;
}
float scaleFactor = 1.0 / length;
p.x *= scaleFactor;
p.y *= scaleFactor;
p.z *= scaleFactor;
}
The answer to this question is a combination of the following rotateTo function and a change to the code from Ray's tutorial at ( http://www.raywenderlich.com/12667/how-to-rotate-a-3d-object-using-touches-with-opengl ). As one of the comments on that article says there is an arbitrary factor of 2.0 being multiplied in GLKQuaternion Q_rot = GLKQuaternionMakeWithAngleAndVector3Axis(angle * 2.0, axis);. Remove that "2" and use the following function to create the _slerpEnd - after that the globe will rotate smoothly to XYZ specified.
// Rotate the globe using Slerp interpolation to an XYZ coordinate
- (void)rotateToLocationX:(float)x andY:(float)y andZ:(float)z {
// Turn on the interpolation for smooth rotation
_slerping = YES; // Begin auto rotating to this location
_slerpCur = 0;
_slerpMax = 1.0;
_slerpStart = _quat;
// Create a look at vector for which we will create a GLK4Matrix from
float xEye = x;
float yEye = y;
float zEye = z;
_currentSatelliteLocation = GLKMatrix4MakeLookAt(xEye, yEye, zEye, 0, 0, 0, 0, 1, 0);
// Turn our 4x4 matrix into a quat and use it to mark the end point of our interpolation
_slerpEnd = GLKQuaternionMakeWithMatrix4(_currentSatelliteLocation);
}

Transform screen coordinates to model coordinates

I've got some sort of newbie question.
In my application (processingjs) i use scale() and translate() to allow the user to zoom and scroll through the scene. As long as i keep the scale set to 1.0 i've got no issues. BUT whenever i use the scale (i.e. scale(0.5)) i'm lost...
I need the mouseX and mouseY translated to the scene coordinates, which i use to determine the mouseOver state of the object I draw on the scene.
Can anybody help me how to translate these coordinates?
Thanks in advance!
/Richard
Unfortunately for me this required a code modification. I'll look at submitting this to the Processing.JS code repository at some point, but here's what I did.
First, you'll want to use modelX() and modelY() to get the coordinates of the mouse in world view. That will look like this:
float model_x = modelX(mouseX, mouseY);
float model_y = modelY(mouseX, mouseY);
Unfortunately Processing.JS doesn't seem to calculate the modelX() and modelY() values correctly in a 2D environment. To correct that I changed the functions to be as follows. Note the test for mv.length == 16 and the section at the end for 2D:
p.modelX = function(x, y, z) {
var mv = modelView.array();
if (mv.length == 16) {
var ci = cameraInv.array();
var ax = mv[0] * x + mv[1] * y + mv[2] * z + mv[3];
var ay = mv[4] * x + mv[5] * y + mv[6] * z + mv[7];
var az = mv[8] * x + mv[9] * y + mv[10] * z + mv[11];
var aw = mv[12] * x + mv[13] * y + mv[14] * z + mv[15];
var ox = 0, ow = 0;
var ox = ci[0] * ax + ci[1] * ay + ci[2] * az + ci[3] * aw;
var ow = ci[12] * ax + ci[13] * ay + ci[14] * az + ci[15] * aw;
return ow !== 0 ? ox / ow : ox
}
// We assume that we're in 2D
var mvi = modelView.get();
// NOTE that the modelViewInv doesn't seem to be correct in this case, so
// having to re-derive the inverse
mvi.invert();
return mvi.multX(x, y);
};
p.modelY = function(x, y, z) {
var mv = modelView.array();
if (mv.length == 16) {
var ci = cameraInv.array();
var ax = mv[0] * x + mv[1] * y + mv[2] * z + mv[3];
var ay = mv[4] * x + mv[5] * y + mv[6] * z + mv[7];
var az = mv[8] * x + mv[9] * y + mv[10] * z + mv[11];
var aw = mv[12] * x + mv[13] * y + mv[14] * z + mv[15];
var oy = ci[4] * ax + ci[5] * ay + ci[6] * az + ci[7] * aw;
var ow = ci[12] * ax + ci[13] * ay + ci[14] * az + ci[15] * aw;
return ow !== 0 ? oy / ow : oy
}
// We assume that we're in 2D
var mvi = modelView.get();
// NOTE that the modelViewInv doesn't seem to be correct in this case, so
// having to re-derive the inverse
mvi.invert();
return mvi.multY(x, y);
};
I hope that helps someone else who is having this problem.
Have you tried another method?
For example, assume that you are in a 2D environment, you can "map" all the frame in a sort of matrix.
Something like this:
int fWidth = 30;
int fHeight = 20;
float objWidth = 10;
float objHeight = 10;
void setup(){
fWidth = 30;
fHeight = 20;
objWidth = 10;
objHeight = 10;
size(fWidth * objWidth, fHeight * objHeight);
}
In this case you will have a 300*200 frame, but divided in 30*20 sections.
This allows you to move in somewhat ordered way your objects.
When you draw an object you have to give his sizes, so you can use objWidth and objHeight.
Here's the deal: you can make a "zoom-method" that edit the value of the object sizes.
In this way you drew a smaller/bigger object without editing any frame property.
This is a simple example because of your inaccurate question.
You can do it [in more complex ways], in a 3D environment too.