Jump to content

  • Log In with Google      Sign In   
  • Create Account

Awesome job so far everyone! Please give us your feedback on how our article efforts are going. We still need more finished articles for our May contest theme: Remake the Classics

haegarr

Member Since 10 Oct 2005
Offline Last Active May 20 2013 10:45 PM
*****

#5015024 MidPoint Method implementation issues

Posted by haegarr on 28 December 2012 - 02:46 AM

To my knowledge, the midpoint integration sums up rectangles with a width equal to your stepSize (assuming homogeneous sampling) and a height equal to the function value in the middle between the 2 samples. Your code snippet, however, doesn't sum up rectangles but irregular trapezoids by splitting each interval into half and fitting a trapezoid to each of them.

I'd say that
for(int I = 0; I < steps; I++) {
    ymid = F(xn+stepSize*0.5f);
    integral += ymid*stepSize;
    xn += stepSize;
}
is all what's needed for the midpoint method integration. But perhaps this is just a naming confusion!?


#5013904 what is this code doing

Posted by haegarr on 24 December 2012 - 04:12 AM

(I would expect that GetCursorPos returns pixel indices in the range [0, nCols-1] and [0, nRows-1] for a nCols by nRows screen. If so, then the following 2 aspects are worth to be mentioned. Besides these details the posts above already stated what the snippet is good for.)

First, a given screen of 800 x 600 pixels has pixel indices ranging from 0 to 799 and from 0 to 599. Cursor positions are usually given by the pixel indices the hot spot is over, so the maximums should IMHO be limited to 799 and 599 instead of 800 and 600. (Also I'm not sure why the given code snippet needs to limit the cursor position at all.)

Second, a pixel is a tiny area, but nevertheless an area, while a D3DXVECTOR denotes an infinitesimal small, well, point in this case. To map from the one to the other, one has to decide what location on a pixel should be hit. If nothing "special" is done (as in the given solution), then the lower left corner will be hit. This causes the following asymmetry: The left lower pixel will result in (x,y) = (-0.5, -0.5), while the upper right pixel will result in (x,y) = (0.49875, 0.49833). If, on the other hand, the center should be hit (for symmetrical results), then half the extent of a pixel has to be considered.

Another consequence is that with the solution "as is" the (x,y) = (0,0) results for the pixel to the right and top of the real center of the screen. Actually the screen's center is not covered by a pixel, because it lies at the corners of 4 surrounding pixels, so you can't address it with the pointer device.


#5013369 Move look vector along terrain up and downs

Posted by haegarr on 22 December 2012 - 03:45 AM

Not using the pitch but the method similar to "look-at" has a reason: It avoids to concatenate a rotation but instead is in itself a full-blown solution, i.e. it computes the end result instead of a delta that has to be applied. You can find parallels in some dozen threads about the look-at computation here in GDnet everywhere.

 

Looking at the original code snippet

 

XMVECTOR incline = XMVector3Dot(mCam.GetLookXM(), mTerrain.GetNormal(camPos.x, camPos.z));
...

then mCam.GetLookXM() gives the vector m, and mTerrain.GetNormal(camPos.x, camPos.z) gives the vector n. You can compute all the mRight, mUp, and mLook from them.

 

 

Of course, also computing the matrix directly as above suffers from abrupt changes when the camera crosses edges of adjacent triangles with noticeably different normals. If you want smoothness in those situations, a possibility may be what I've described in the previous post: Assume that the height field is spaced 10 by 10 length units. Assume further that you use a forward vector with a length of 2 length units (i.e. a scaled mCam.getLookXM() vector). Then compute the position (inclusive height) of the camera as well as of the point at the end of the forward vector but again projected onto the terrain. Then use the difference vector as new look-along vector. As long as the camera is more or less in the middle of a triangle, the result will be the same as with the other methods of computation. But when the end of the forward vector falls beyond an edge of the triangle (i.e. in the given example it is closer than 2 length units to the edge), then the other triangle influences the result, and that the more the camera gets closer to the edge. Just after crossing the edge, the new triangle has 100% influence on the result. If you are heading the camera to look back than the just left triangles gets most of its influence back.




#5013212 Move look vector along terrain up and downs

Posted by haegarr on 21 December 2012 - 12:50 PM

A variation of the standard way to compute a look-at matrix works here as well: If m denotes the movement direction (e.g. projected onto the x-z plane) and n the terrain normal at the current position, then
r := m cross n
denotes the side vector perpendicular to both m and n. Then
f := n cross r
denotes the forward vector that can be used as look-along vector as requested. It usually need to be normalized, though.

If, on the other hand, the normal isn't available because you're working with a height map, then this topic may help you. (Please notice that my first posts therein haven't considered triangulation correctly, but down from post #15 inclusive things are done well). After computing the height at the current position and the height a bit in direction of the movement vector, then the normalized difference vector is the result.

BTW: To be pedantic: A bi-normal is a construct that can be computed at locations on a line. In case of a surface the correct term is bi-tangent.


#4997126 Quaternion rotation

Posted by haegarr on 04 November 2012 - 04:22 AM

Co-ordinates are to be interpreted w.r.t. to a space to give a sense. E.g. if you ever pick (0,1,0) as rotation axis for heading, then you probably mean to rotate in the ship's local space. However, it doesn't work this way. A concatenated transformation is applied in the most global space.

So you need to take explicit steps to first fit the space as you want it, i.e. you to transform it so that the local axes are coincident to the global ones. You do this by first applying the inverse of the current orientation before applying the new rotation. Because you don't want to loose the former orientation, you then have to re-apply a rotation to reconstruct it.

Now, when you think on this further (try it with e.g. 3 rotations on paper), you'll see that the order of all the rotations applied over time is simply reversed. That is probably the reasoning behind SiCrane's post, and it makes sense w.r.t. your problem.


#4987631 [Answered] Matrix create from XYZ rotation: scale problem

Posted by haegarr on 07 October 2012 - 03:05 AM

Mistakes are at least in the formulas of m21 and m22 (both showing 3 summands), because their format has to be the same as those of m31 and m32 (both showing 2 summands).

As a hint: The length of each column vector and each row vector in a pure rotation matrix is 1. If the length differs from 1 then scaling will occur.


#4969572 Rotate flat surface in 3D space

Posted by haegarr on 14 August 2012 - 01:11 PM

If you use glVertex2(x,y) then it is equivalent to the use of glVertex3(x,y,0) what is itself equivalent to glVertex(x,y,0,1). It has no effect on the dimensionality of the space or what. Whether or not perspective can be seen is a question of the projection matrix. E.g. using glOrtho defines an orthogonal projection, while glFrustum defines a perspective projection. There are perhaps some utility functions for projection, too.


#4968078 Normal of sine

Posted by haegarr on 10 August 2012 - 07:44 AM

The way you compute wave1(x,z) uses dir_vertex, which itself is a function of (x,z). The way you compute tan1 and bitan1 neglect this fact! Notice that alvaro hinted at computing the derivates dF(x,z)/dx and dF(x,z)/dz.

In fact, the formula you use is something like
wave1(x,z) := ( sin( fs * ( dirx * x + dirz * z ) + ft * t + p ) )2
where fs denoting a spatial frequency, ft denoting a temporal frequency, and p denoting a phase.

For the purpose of spatial derivative the term ft * t + p =: ct is a constant, and fx := fs * dirx, fz := fs * dirz can be used for simplicity. Then IIRC the derivatives are
tan1 := d wave(x,z) / d x = ( sin( fx * x + fz * z + ct ) )2 / d x = 2 sin( fx * x + fz * z + ct ) * cos( fx * x + fz * z + ct ) * fx
and
bitan1 := d wave(x,z) / d z = ( sin( fx * x + fz * z + ct ) )2 / d z = 2 sin( fx * x + fz * z + ct ) * cos( fx * x + fz * z + ct ) * fz
due to the chain rule. Please check this twice.


#4950840 Random Encounters: How To Keep Them Fresh.

Posted by haegarr on 19 June 2012 - 11:26 PM

I never played the games mentioned, so I throw in some ideas without the knowledge whether or not they fit...

...
How would do you think this could be implemented without saying "This was is long but less to fight, this way is shorter with more to fight!" directly to the player?

Informations can be gathered from several impersonal and personal sources like
* maps (especially length of way)
* road signs (length of way, like "15 miles to Somewhere City")
* giving ways talking names (like "canyon of hairy monsters")
* travelogues (length of way as well as risks on the way)
* warnings on bulletin boards in cities (especially the risks)
* assignments of chasing monsters, available from public places in cities (especially the risks; side effect: can be interpreted as side quest)
* rumors, gossip, myths (if NPC interaction includes "speaking")
* explicit interrogation (if NPC interaction includes "speaking"), especially city guards, travelers, ...


#4943434 OpenGL and 3D Math

Posted by haegarr on 26 May 2012 - 03:30 AM

The opengl projection matrix is about defining the viewing frustum and perspective or orthopraphic projection...  so... are the clipped coordinates the coordinates that lay in the viewing frustum? Which is definied by the projection matrix? That would explain why to get the clipped coordinate one has to multiply the projection matrix and the eye coordinate.

The modelview matrix is a combinaton of the model and the view matrix. It is used for doing transformations to a given vertex (scale, rotate and position). OpenGL doesn't use a "camera" or it can be thought of as the camera always being at (0,0,0) looking down the -Z axis. In order to change one's view, they need to transform all the objects positions so it's as if the world is moving around the "camera" not the "camera" moving around the world.

You have a viewing volume in general. Before normalization it is a "frustum" in case of perspective projection but a cuboid in case of orthographic projection. The projection matrix is responsible to squeeze the viewing volume into the normalized viewing volume which is in fact a cube ranging from -1 to +1 in each dimension. However, you need more to described than how to squeeze the volume: you need to describe where in the space the volume is located and how it is orientated. The both standard projection matrices are defined in a way that the viewing volume has an origin at 0 and OpenGL's standard viewing orientation. I other words, the projection expects to be applied in a local space that is called the viewing space.

You can relate a space to another space by giving a transformation matrix. (In this sense also the projection transforms from one space into another one.) There isn't really a dominant space; each space is in principle as good as another one, but some tasks are more convenient to be done in the one than in the other space. The viewing space, for example, is convenient for doing projection. However, it isn't convenient for placing models. This is because when wandering around we would need to alter each model's co-ordinates. Instead we define a common space where we relate both the models as well as the viewing volume. We usually call this space the global space or "world".

When we relate a model to the world, we'll see that defining a model's shape (by its vertices, of course) in global space isn't convenient, because we have to adapt each and every vertex when we want to shift or rotate the model. It is more convenient to have a space where the vertices have fixed co-ordinates regardless how the model is placed in the world. Such a space is called a local space or "model space", and the transformation that relates the model space to the global space is called the MODEL matrix in OpenGL's nomenclature. It is a transformation that computes the vertex co-ordinates given in model space now in global space, and hence is a local-to-global transformation.

We've said that the viewing volume is related to the global space as well. Hence the belonging matrix "as is" describes also a local-to-global transformation. In analogy to "model" we call the belonging object in the world the "camera" also it is even more "virtual" than a model, because we never see the camera itself but only the subspace it picks out of the world.

Now we can relate the models to the world and the viewing volume (or camera) to the world as well. But to apply the projection (and further steps) we need to work the models in the view space. Transformation from model space to global space to view space hence requires to concatenate the model's local-to-global transformation and the camera's global-to-local-transformation, where the latter one is obviously the inverse of the camera's local-to-global transformation. This inverse one is called the VIEW transformation in OpenGL's nomenclature, and the concatenation logically the MODELVIEW transformation.

Mathematically we speak of
P * V * M = P * C-1 * M
where P means the projection matrix, V the VIEW matrix (global-to-local), M the MODEL matrix (local-to-global), and C the camera (local-to-global). Due to the way OpenGL expects the matrices (at least legacy OpenGL), it computes
P * ( V * M )
but this is mathematically equivalent to
P * ( V * M ) = ( P * V ) * M


That said, the concept of a camera is actually existing in OpenGL, but mathematically it plays no role whether you move models or a camera around. It is just a question of efficiency: It is more efficient to let the GPU transform the vertices and deal with dynamic models plus the camera by the CPU instead of letting the CPU transform all vertices.


#4942010 Help with rotations in 2D around a particular point, using a scene graph

Posted by haegarr on 21 May 2012 - 03:20 PM

Quick question, why are scene graphs deprecated ?

Scene graphs are an example of violating the principle of single responsibility. It is used for logical grouping, assembling models, defining parent-child transformation hierarchies, doing spatial partitioning, ... all at once.

However, a single structure cannot do all this without enforcing restrictions. E.g. a scene graph naturally introduces a hierarchical bounding volume scheme. But what if you want to use a binary space partitioning scheme instead? Just an example. You'll find dozen of threads about this theme in GDnet as well as some articles on the internet.

I don't say that scene graphs are senseless, but IMHO using a single structure for each kind of job is the way to go today.


#4941463 Help with rotations in 2D around a particular point, using a scene graph

Posted by haegarr on 19 May 2012 - 10:53 AM

First of all, using a scene graph is, well, deprecated, but using it and ignoring its natural parenting seems me strange. Why do you want to rotate around grand-parent nodes?

However, here is the solution:

1. Every node has a position relative to its parent node and expressed as translation matrix Ti for the i-th node. Every node has an orientation relative to its parent node and expressed as rotation matrix Ri for the i-th node. Then the local transformation matrix of the i-th node is given by (using row vectors here)
Li := Ri * Ti

2. The belonging global matrix, i.e. the transformation matrix relative to the overall common reference space (a.k.a. "the world") is computed as
Wi := Li * Wi-1 =  Li * Li-1 * Li-2 * ... *  L1
where Wi-1 denotes the global transformation matrix of the parent node. Please notice the recursive definition.

3. The center of rotation should be given by a node above the current one, e.g. Wj with 0 < j < i. As your internet source correctly stated, you have to make this temporarily the origin. You do this by applying the inverse matrix, because you go from global to local space. Hence
Wi * Wj-1 = Li * Li-1 * ... *  Lj+1
would do the trick. Now apply the rotation
Wi * Wj-1 * R
and finally shift the temporary center back to its original position:
Wi' := Wi * Wj-1 * R * Wj

4. If you want to know the local transformation, then do
Li' = Wi' * Wi-1-1

Comparing this with the prescription given in the OP, you'll see the going from the current node up to the grand-parent node in the index sequence i-1 ... j+1 in the formulas above. Of course, you don't really need to compute Wj and Wj-1 to just yield in the desired result Li', because of
Wi' * Wi-1-1 = Wi * Wj-1 * R * Wj * Wi-1-1 = ( Li * Li-1 * ... *  Lj+1 ) * R * ( Lj+1-1 * ... * Li-1-1 )
where the parentheses are only used for clarity (i.e. there is no mathematical necessity). However, due to the parenting mechanism you'll have to implement the computation of W anyway.


EDIT: Please check the formulas twice before using it, because mistaking an index is done quickly ;(


#4941427 Rotating camera around player origin

Posted by haegarr on 19 May 2012 - 07:20 AM

Use parenting so that the player's avatar model is the parent of the camera. Then the camera's world transformation CW is
CW = CL * PW
where CL means the camera's local position and orientation w.r.t. the avatar's model, and PW means the model's position and orientation in the world. Hence, if you alter the model, the camera will follow automatically.

You may want to use variations, e.g. a constant height of the camera above the ground. This can be done by setting the respective component manually.

If you want to change the camera's relation to the model, i.e. CL, then use orbiting. In orbiting you rotate both the orientation as well as the position of the camera. That means
CL' = CL * R
perhaps using negated angles when computing R.

It may be that the origin of the model shouldn't be exactly the center of rotation / orbiting, e.g. in the models's head instead of the center of body. In that case you may want to have a distant rotational center O (also relative to the model's space) and hence will do orbiting like so:
CL' = CL * O-1 * R * O
Herein O is simply the translation matrix from the model's origin to the center of rotation.

If you want to compute the direction where the model should move, please avoid the use of angles. It is much more convenient and efficient to use the forward vector of the model (or perhaps the camera) instead. You can use a projection of it if you want the movement vector parallel to the ground. You can further apply a small rotation for curved movement.


#4941241 heading to position transform angle in C++

Posted by haegarr on 18 May 2012 - 12:32 PM

Errr ...

Yes, for now I only do alike also for the listener:
   alListener3f(AL_POSITION, cH/10,cY/10,(lZ/10)+disX);
cH is the heading degree and disX the distance.


You are setting an angle as the value of a position component! That means that your listener wanders around and suddenly jumps in space in dependence on an orientation. That is definitely a mistake.

Set the AL_POSITION like the camera's position (or like the object's position in case of the source), and set the AL_ORIENTATION using sine and cosine on the heading to compute a direction vector from the angle(s).

(If you want an attenuation effect that is not given by the normal operation of AL then try some volume computation but don't try to misuse the position for that because it will not work properly.)


#4941131 OpenGL Handles

Posted by haegarr on 18 May 2012 - 01:30 AM

In OpenGL, the "handles" are just unsigned integer numbers. This means that there is no type based distinctions between names (as the "handles" are called correctly in OpenGL) for e.g. textures and names for e.g. VBOs. So it is principally possible to pass a name allocated for a VBO to glIsTexture, as an example.

Moreover, the values returned by OpenGL resource allocators are usually small numbers, increased by a small amount compared to former allocations. Strictly speaking, a value need to be unique only in the specific context of use as a texture, VBO, or whatever. Hence it is not exclusionary that a call to e.g. glGenTextures returns the same value as a call to e.g. glGenBuffers.

At the end I would say that it is implementation specific (I haven't found something concrete in the specs). As a conclusion I'd say that it is possible that a name of a texture can be passed to any glIsXyz and return with a "true". However, this doesn't mean that the named object is actually of the Xyz type. Passing a texture name as VBO name is simply a programming error not detectable by OpenGL.




PARTNERS