f - 5 = f / 1.02564
-5 = f / 1.02564 - f
= f ( 1 / 1.02564 - 1 )
f = -5 / ( 1 / 1.02564 - 1 )
Although being a professional programmer for years, game development is just one of my hobbies (nearly as long as programming yet, and that is a loooong time).
Posted by haegarr on 20 June 2015 - 03:58 AM
f - 5 = f / 1.02564
-5 = f / 1.02564 - f
= f ( 1 / 1.02564 - 1 )
f = -5 / ( 1 / 1.02564 - 1 )
Posted by haegarr on 08 June 2015 - 10:57 AM
I've looked into it a bit more, and I might be onto something, but I'm not sure, and I'd like some advice please. I found a function called Transformation, which takes as inputs:
- a translation vector
- a vector for the rotation point, and a quaternion to rotate
- a vector for the point to scale around, a vector for the amount of scaling, and a quaternion for rotating the axes along which to scale (so it doesn't necessarily scale on the default axes)
This sounds like the transform function somewhat known from X3D. There are also the functions named AffineTransform with less parameters. Both can be used. It is probably so that for your use case
* the scalingCenter is (0,0,0)
* the scalingRotation is (1,0,0,0)
* the scaling is (1,1,1)
* the rotationCenter is (0,0,0)
* the rotation is (your-rotation)
* the translation is (your-translation)
However: It would be easier to just set the elements of the transform matrix from the parameters you already have. Assuming that SlimDX uses row vectors, the 1st row stores the sideways vector, the 2nd row stores the upward vector, the 3rd row stores the forward vector, and the 4th row stores the position vector. (Notice please that the rows stores homogeneous coordinate vectors, so that each of the direction vectors has a 0 as its last element, while the position vector has a 1.)
So, if you have pairwise orthogonal vectors right, up, and forward then you can use the setters Matrix.Mxx for that purpose. If they are not pairwise orthogonal then you need to apply the cross product before using the vectors.
Posted by haegarr on 02 June 2015 - 05:18 AM
Well, I'm not totally sure, but when the illustration from the OP is the basis, then the left and right parameters of frustum(….) must not be symmetrical. They probably would be symmetrical if the look-at point is chosen so
glm::lookAt(Position - eyeOffset, Position + Forward, Up); // left eye glm::lookAt(Position + eyeOffset, Position + Forward, Up); // right eye
(assuming that eyeOffset is a vector given in the correct co-ordinate space, of course). BUT then the view planes for the left eye and for the right eye would not be coincident but would be crossed a bit. Hence they would not form the shown virtual screen. So ...
Exerting trigonometry, the virtual screen has a width of
s := 2 * convergence * aspect * tan( 0.5 * fovy )
Let e be the absolute value of the eye offset. Then the irregular parallelogram build of Position, left eye, top intersection of left and right frustum, and the center of the virtual screen allows us to say that for the left eye
left := -1 * near * ( s/2 - e ) / convergence
right := +1 * near * ( s/2 + e ) / convergence
and analogously for the right eye
left := -1 * near * ( s/2 + e ) / convergence
right := +1 * near * ( s/2 - e ) / convergence
Posted by haegarr on 25 May 2015 - 03:38 AM
The OP doesn't contain exhaustive informations, so to say. In principle I would / do arguing as follows:
The navigation system is a service provider for AI (can I go there?) and the movement system (how to go there?), i.e. it is at lower level than those, and those are at a lower level than game objects (as a whole). When different navigation solutions are available and probably even need different data structures, then integrating all that into game objects would be messy. A possible solution is to use an agent attached to the game object, so that the agent utilizes the services, holds the appropriate data structures, and mediates between them and the game object.
Posted by haegarr on 22 May 2015 - 08:04 AM
There are (at least) two possible approaches:
a) The original polygon is the dark area inside the green border, and the border is additional geometry build from extending the original polygon. The additional geometry can then be colored by standard interpolation of vertex color.
b) The polygon area reaches to the outside where the green border fades out into the background, and no additional geometry is generated. Then the vertex shader is used to compute the distance of the current pixel to the edges in screen space, and the color of the pixel is chosen as function of the distance. Obviously, you need to send a vertex attribute which is used to distinguish whether or not a vertex counts to an edge that is to be highlighted. The theory can be read in several articles around the web.
Posted by haegarr on 16 May 2015 - 07:03 AM
I am self studying this
Okay, then you not should but want to solve the problem by yourself. So what is your concrete question regarding the issues I've already noted?
Debugger in dev cpp is not working on my Windows 8.1 64 bit.
Then you shall think to turn to another developer environment. You definitely will need a debugger. The given situation is only the first of many others that will come ...
Posted by haegarr on 16 May 2015 - 04:20 AM
The forum rules do not allow us to solve other peoples homework, but it allows to answer concrete questions where we can see from that you've tried hard to get a solution yourself.
Well, the program code shown in the OP has at least 10 mistakes, some of which are just flaws, some are errors, and two of them are logical mistakes regarding how a solution may work, inclusive how the correct solution may look like at all. Not wanting to discourage you, but you should restart at the problem analysis: (1) What is the goal, (2) how can it be reached with a 2D array, and (3) how can that be programmed.
As wintertime has excellently stated above, the debugger is a valuable tool. It allows you to peek into the working of computer programs, so lets you examine how statement how, how the resulting program flow is, and how variables change. Use it to your advantage!
I wanted to sort that array first and then find the lowest and the highest array.
This is possible and fine by itself, of course. But ask yourself what you get by doing so. You get the lowest and the highest temperature. The goal accordingly to (1) is to output the day and the city of two specific temperatures. With your thinking considering (2), the indices of the array are used to denote the specific days and cities, resp. You associate the belonging temperature with a specific day and city by writing the temperature value into the array place that is addressed by that indices; that is fine so far. Now, what happens to that association if you sort the array as is shown in the OP?
Posted by haegarr on 16 May 2015 - 02:39 AM
In the days back when I programmed a ray tracer (we wrote the year 2000 as I've seen in my documents), I had used a method similar to what Randy Gaul has mentioned above: Intersection computations started with transforming the problem into a normalized local object space. This puts down intersections of translated / rotated / scaled objects to their respective standard form. The transformation is applied just to the origin and direction of the parametric ray. It would appear in a full intersection formula anyway, so does not enhance the computational costs.
In case of a cylinder the standard form, as was used in my ray tracer, meant: The axis of the cylinder is is the local y axis, the basic area is circular, the height is symmetrical to the x/z plane. In this case the cylinder could be hollow if either or both of the ceiling and floor planes are omitted. The belonging code is this (please don't look too close to the coding style):
Bool RegCylinderShape::check(const Ray& aRay,SpanList& Spans) const { Bool HitExists = false; // localize ray this->applyInvToPoint(aRay.Origin,_localRay.Origin); this->applyInvToVector(aRay.Direction,_localRay.Direction); // compute parameters register Real64 T1 = _localRay.Origin.x/_Rx; register Real64 T2 = _localRay.Origin.z/_Rz; register Real64 T3 = _localRay.Direction.x/_Rx; register Real64 T4 = _localRay.Direction.z/_Rz; register Real64 C0 = T1*T1+T2*T2-1.0; register Real64 C1 = T1*T3+T2*T4; register Real64 C2 = T3*T3+T4*T4; C0 = C1*C1-C0*C2; // if C0 is greater than zero, the ray hits the infinitely long cylinder if(C0>0.0) { register Bool B1p,B1n,B2p,B2n; // compute the travel coordinates of the near and far hits C0 = sqrt(C0); T1 = (-C1-C0)/C2; T2 = (-C1+C0)/C2; // compute y components of both hits in local coordinates C1 = T1*_localRay.Direction.y+_localRay.Origin.y; C2 = T2*_localRay.Direction.y+_localRay.Origin.y; // check whether or not the ray enters/leaves through ceiling/floor planes B1p = C1<=_halfHeight; B2p = C2<=_halfHeight; B1n = C1>=-_halfHeight; B2n = C2>=-_halfHeight; // if the ray hits the finite cylinder shape ... if((B1p||B2p)&&(B1n||B2n)) { _HitCode = 0x0; // if the ray enters through the ceiling or else the floor plane, the corresponding travel // coordinate is adapted accordingly; necessity of adapting is reported in setting the hit // code bit #0 if(!B1p) { _HitCode |= 0x1; T1 = (_halfHeight-_localRay.Origin.y)/_localRay.Direction.y; } else if(!B1n) { _HitCode |= 0x1; T1 = (-_halfHeight-_localRay.Origin.y)/_localRay.Direction.y; } // if the ray leaves through the ceiling or else the floor plane, the corresponding travel // coordinate is adapted accordingly; necessity of adapting is reported in setting the hit // code bit #1 if(!B2p) { _HitCode |= 0x2; T2 = (_halfHeight-_localRay.Origin.y)/_localRay.Direction.y; } else if(!B2n) { _HitCode |= 0x2; T2 = (-_halfHeight-_localRay.Origin.y)/_localRay.Direction.y; } // if the ceiling or floor plane exists, or the ray hits the cylinder outside these planes // (either when entering or when leaving), then real hits occur which must be reported to // the span list if((_HitCode!=0x3)||_Ceiling||_Floor) { HitExists = true; // if either the ceiling or the floor plane lacks existance, but the ray hits those // plane, the corresponding travel coordinate and hit code must be adapted if(!((B1p||_Ceiling)&&(B1n||_Floor))) { T1 = T2; _HitCode &= 0x2; _HitCode |= _HitCode>>1; } else if(!((B2p||_Ceiling)&&(B2n||_Floor))) { T2 = T1; _HitCode &= 0x1; _HitCode |= _HitCode<<1; } _HitSeparation = 0.5*(T1+T2); // report hits to span list Spans.addNewSpan(*this,T1,T2); } } } return HitExists; }
Some explanations: The result of an intersection computation is a SpanList. Here a span is the distance from the ray's origin along its direction until the ray enters and then leaves a volume. If the object is hollow, then the span's enter and leave distances are the same. (This concept was chosen to allow even for multiple intersection as might occur for e.g. a torus.) The SpanList then is an ordered list of spans.
The distances along the ray are stored as multiples of the ray's direction vector. This allows to apply the distances in any space, since the ray's direction vector is not re-normalized after transforming into a local space. So the actual intersection points in e.g. world space are calculated by setting in the distances as the world space's ray parameter.
Posted by haegarr on 15 May 2015 - 01:34 AM
Since you asked for opinions: GIF as in-game format is a no-go for me. I mean … it is GIF, isn't it?
From a more technical point of view, you need to have an animation system anyway. It should work considering delta frame times which is not included in GIF animations (AFAIK). Having the own code controlling things gives the best flexibility. So, why not using this same mechanism for all instead of introducing a second mechanism for the gain of, well, nothing in the end.
Posted by haegarr on 13 May 2015 - 04:27 AM
But in this scenario it doesn't work:
Problem was that condition check: In case that (tM && tA) is true, then also (tM || tA) is true. Hence the then branch is entered and within it the checks exclude (tM && tA) from being a result. The correct code is hence (jsfiddle is also updated if you want to look at it):
if(tM || tA){ if(tM && !tA){ this.intersectPoints = [ new vector(f0,f1) ]; } if(tA && !tM){ this.intersectPoints = [ new vector(g0,g1) ]; } if(tM && tA){ this.intersectPoints = [ new vector(f0,f1), new vector(g0,g1) ]; } return true; }
Posted by haegarr on 13 May 2015 - 03:22 AM
Well, it is cumbersome to locate the problem without any hints, just by looking at code. Please construct a simple situation like a segment (0,0) to (10,0) and a circle at (5,0) with radius 1, and write out the resulting values of eDistAtoB (should be 10) and t (should be 5). Further dt should be 1, and hence tMdt == 4 and tAdt == 6. Obviously, this should result in true for both tM and tA. Where does this break, and with which values?
Posted by haegarr on 13 May 2015 - 03:01 AM
Oh, I've not considered that vector d is normalized. So t (or t-dt or t+dt) need not range from 0 to 1 but from 0 to eDistAtoB … I think at least ...
So try
var tM = tMdt >= 0 && tMdt <= eDistAtoB, tA = tAdt >= 0 && tAdt <= eDistAtoB;
instead of
var tM = tMdt >= 0 && tMdt <= 1, tA = tAdt >= 0 && tAdt <= 1;
if(t >= 0 && t <= eDistAtoB){
if(t >= 0 && t <= 1){
Posted by haegarr on 13 May 2015 - 01:59 AM
a) In case of 2 intersections: You need to check both intersections not together but on their own. Also there is an error with the condition on tAdt!
b) In case of 1 intersection: You should use t >= 0 && t <= 1 instead of t > 0 && t < 1
Posted by haegarr on 13 May 2015 - 01:32 AM
Okay now i restructured my code
Well, now you use a totally different method of computation: Before it was checking for the point on the segment that is closest to the circle's origin, now you use the implicit circle formula to check for identical points on the line. That is a replacement, not a restructuring!
The originally used method has the advantage that the distance of the intersection along the segment was computed, and that is good to judge whether the intersection is inside or outside the segment's range. The now use method does not compute that distance anywhere. So ...
a) you go back and use the original method, together with the 2 conditions I've posted above; I would suggest this way (in assumption that the original method works well for lines),
or
b) you check whether the computed intersections(s) are between the end-points of the segment. For this you can use the projection method, too.
Posted by haegarr on 13 May 2015 - 12:53 AM
AFAIS the method used above computes the relative projected length of the difference vector (between the line segment's start and the center of the circle) and the line segment. The result denotes the distance to the point on the segment and closest to the circle, and it is stored in variable t.
a) If there is just 1 intersection than t need to be between 0 and 1, because the closest point is also the intersection point.
b) If there are 2 intersections then the intersections are at distances t-dt and t+dt. Any of these need to be in the range [0,1] to be valid.
GameDev.net™, the GameDev.net logo, and GDNet™ are trademarks of GameDev.net, LLC