Jump to content

  • Log In with Google      Sign In   
  • Create Account

Banner advertising on our site currently available from just $5!


1. Learn about the promo. 2. Sign up for GDNet+. 3. Set up your advert!


haegarr

Member Since 10 Oct 2005
Offline Last Active Today, 08:05 AM

#5181230 How to transfer/manage objects from one class to another

Posted by haegarr on 18 September 2014 - 04:27 AM

As ever: We're discussing possibilities here. You need to decide what is helpful for your game and what can be ignored for now...

 


Like I understand it: The machine is the parent and the zone is the child. So the machine does the rendering of the zone (for example sake the zone is a visible component).
But as you said earlier, an object doesn't do it's own rendering, so does the machine add it's sprite together with the zones' sprite and give it to the renderer as a 'spriteset' or so?

The mechanism of parenting does nothing more than expressing a spatial placement relative to another one. This is outside of rendering, collision detection, or anything similar. Here is why and how:

 

In 2D a placement consists of a 2D position and an orientation angle. Those parameters can be used to compute a 3x3 homogenous matrix expressing the transform of the sprite. The transform defines what to do to come from the local space (also called model space) to the parent space. I'm used to define that every model / sprite in the scene is placed globally initially, so that the transform matrix inherent to the model / sprite is a world transform matrix. In other words, each model / sprite has a world placement.

 

In the case that a model / sprite is needed to be parented, I'm used to add an explicit tool for this: The Parenting component. The attachment of a Parenting makes the model / sprite the child. The Parenting includes a reference to another model / sprite, so that those other model / sprite becomes the parent of the child. The Parenting further includes a local Placement, i.e. a Placement that expresses the spatial relation to the referenced parent model / sprite.

 

In fact the Parent component introduces a constraint on the world Placement of the child model / sprite in that its world Placement is computed as said concatenation of the local Placement with the world Placement of the parent. This is a fancy description essentially of a matrix product.

 

So ... what you can see here is that the above solution does an external coupling (external to the models / sprites, because based on the introduced Parenting class) of models / sprites on a spatial level. The coupling updates the world transform of what is made the child model / sprite. This means that if all is up-to-date, every model / sprite has a valid world transform in its Placement, regardless whether it is a static one or computed by a Parenting (or computed by another mechanism; I've something like a dozen or so, including animation, of course).

 

Now, when the collision detection or rendering comes to work, there is a couple of models / sprites each with a valid Placement in the world. That is all what the respective sub-system needs to know. "Parenting? What's that?" is said by the renderer.

 


As we are talking about doing the rendering outside the object, how does this work? Does the renderer iterate over all the objects, take their sprites and draw them on the coordinates+rotation of the object?

Yes. The renderer iterates the scene. Maybe there is a subset of scene objects that denotes all "drawables" or so. However, the renderer finds the objects, and uses the sprite as visual representation and the (as we know being valid) world placement's transform matrix. It usually does frustum / viewport culling with the help of some bounding box first.




#5180955 How to transfer/manage objects from one class to another

Posted by haegarr on 17 September 2014 - 02:57 AM


I would have two variables in my machine class:
Public Zone pickZone;
Public Zone dropZone;
Which are references to the zone objects. They are initialized when a machine is created.

This is a valid way. It does not differ significantly from using the reference Zone.machine as mentioned already. Merely the question whether the members should be public may arise.

 


Let's say the selling of a machine is done outside the machine class, how would you find out which zones to destroy together with the machine if you don't have these two variables?

Well, it isn't so that no possibilities exist:

 

a.) Indirect coupling: Classes / objects in programming can represent data about anything, e.g. also a concept or an idea or, in this case, a relation. For example, a class ProductionUnit can be used to couple a Machine and two Zone objects together.

 

b.) Reverse coupling: A simple iteration over all Zone objects can be done to look up for all zones docked to the machine in question. (This option becomes more and more unattractive the more zones there are and the more sales are done per time unit, of course. If you think "what the hell should this be good for?": Relational databases use this way to express one-to-many relations. To overcome the efficiency problem, the related rows are indexed. In Java something similar could be yielded in.)

 

However, I don't say that you should use any of the above possibilities. Using direct coupling is fine in principal. The critique I've made was with respect to the interaction between objects. E.g.: How many classes need to be adapted if you want to introduce a new kind of zone? Or does a machine need to know what a sale is? Just such things, you know.

 


I'm not familiar with this. I've been trying to Google it, but for now only results about divorcing parents :-) I keep looking! (If anyone has good sources about that you may always let me know) .

What I mean is a relation that is commonly used in rendering graphics: Placing a graphical representation (often called the "child") not directly into the world but relative to a reference object (often called the "parent"). For the actual rendering the world placement of the child is then computed by concatenation of its local placement with the world placement of the parent.

 

While "the pickZone A is docked to the machine B", perhaps expressed by a reference like

   A.machine = B;

denotes a logical relation, a parenting in the above sense means a spatial relation in that it defines e.g. on what side and how narrow the graphical representation of the zone is attached to the graphical representation of the machine. So, say when you rotate the machine then the zone will rotate with it.




#5180760 How to transfer/manage objects from one class to another

Posted by haegarr on 16 September 2014 - 11:26 AM


One thing though: should the machine and the area-objects not stay connected?
For instance let's say one of the machines is mobile and it moved around. The areas have to move along, or the player sells a machine, the areas have to be destroyed. It seems like if I write all that outside the machine class it's gonna get messy!

What do you mean with "connected"? I think it is better when zones and machines are distinct classes. This allows a different hierarchy for zones and for machines. They can logically be connected (see the members DropZone::machine and PickZone::machine in the code examples above), and they can be connected spatially if wanted (by using a 2D or 3D parenting placement mechanism).

 

Selling a machine is a procedure outside of the scope of the machine anyway. Relocating a machine it is, too. I don't see a problem ATM. However, I also don't have an overview belonging to your game design, so may be I'm too rigorous.

 


About the products: Is it better to let them only exist in the player/machine, or should I also put them in a collection of some kind. I'm not sure what is best. I'm leaning more to the first option, because it is less overhead and simpler, but then what to do when the player drops it's product, it should still exist on it's own.

Player avatar and machines are containers for products. Internally they use a collection if necessary. A more global collection of all products may be useful for the game mechanics,  but from what you've written so far I don't see a reason for that.

 

If a player drops a product it is no longer contained but an objects in the world, e.g. like a machine or something. It may become a bounding volume and collision handler, whatever fits the game design.




#5180496 Matrix Decomposition

Posted by haegarr on 15 September 2014 - 11:25 AM


The problem is that the draw call is done with a common matrix. Any suggestions? Any changes on the vertices are possible?

I don't know whether you can change the vertices directly, because you just told nothing about how the vertices are passed.

 

If you have access to them then of course you can use the CPU to do the job. For example, if all sprites are given by quads then each 4-tuple of vertices are to be used. Or if sprites are passed as 2 triangles, then each 6-tuple is to be used. Or if the vertices are passed by index, then the same goes with indices.

 

You can then compute the center of each sprite by summing the N vertex positions and divide by N. Then subtract those center position from each of the N vertex positions, half the resulting vector, and re-add the center. E.g.

for each sprite
   vec2 center(0, 0);
   for each of the N vertices of the sprite do
      center += vertex.pos;
   center /= N;
   for each of the N vertices of the sprite do
      vertex.pos = ( vertex.pos + center ) * 0.5;



#5180485 Matrix Decomposition

Posted by haegarr on 15 September 2014 - 10:54 AM


I guess that math-wise, you need to translate to each center and do the scale for each element of the group?

Yes: If p is the position of the center, then translate by -p so that the center comes to rest at 0, do the scaling, then translate back by +p.

 

Is the drawcall done with an own matrix for each sprite, or with a common matrix for all sprites?




#5180450 Matrix Decomposition

Posted by haegarr on 15 September 2014 - 07:36 AM


If I apply a scale matrix to it, the sprites disappear, they don't do the desire effect which is the scaling I want.

If you put the scale matrix on the wrong side, then you scale also the position and a sprite may disappear due to that. So, have you ensured that you've chosen the correct order of multiplication? What happens if you use scaling factors close to 1?




#5180433 Matrix Decomposition

Posted by haegarr on 15 September 2014 - 06:18 AM

Decomposing the matrix transform is perhaps not needed; it depends on how you create the original sprite transform matrix. If you just use a rotation and translation, then you can multiply with the scaling matrix, i.e.

    M * S( 0.5 )  when using column vectors

    S( 0.5 ) * M  when using row vectors

should do the job. It works by first scaling the sprite (uniformly) and then applying the original transformation. Have you tried this already?




#5180414 How to transfer/manage objects from one class to another

Posted by haegarr on 15 September 2014 - 04:05 AM

Several possibilities exist, and there is perhaps no best way. However, these are my thoughts:

 

Four objects are involved when transferring a product:

1.) the player avatar

2.) the machine

3.) the product

4.) the zone

 

A machine is a container of products with a provider and consumer behavior. The player avatar is also a container of products with a provider and consumer behavior. A zone is a collider volume with a belonging collision handler, depending on its purpose either an onEnteredDropZone or an onEnteredPickZone. The player avatar is the collidee for a zone, and a machine is fixed attached to a zone either as provider (PickZone) or as consumer (DropZone).

 

Now, if the transfer happens automatically simply because of the collision, the zone is well suited to perform the transfer:

void DropZone.onEntered( Avatar player ) {
    if ( player.providesProduct() && this.machine.acceptsProduct() ) {
        this.machine.consume( player.releaseProduct() );
    }
}
void PickZone.onEntered( Avatar player ) {
    if ( this.machine.providesProduct() && player.acceptsProduct() ) {
        player.consume( this.machine.releaseProduct() );
    }
}

Of course, it looks more natural to put the behavior into the player avatar class, but notice that above solution is fine because

a.) it does not introduce machine stuff into the player avatar class (or vice versa)

b.) allows to come up with more kinds of zones perhaps without changes to the interface of the player and/or machine classes

 

Things get slightly more complicated if the player actively triggers the transfer by some kind of input. In this case the zone has to consider whether the player wants to transfer the product. 

void DropZone.onEntered( Avatar player ) {
    if (this.input.playerAction()==Action.TransferDrop) {
        ...
    }
}

However, this seems not sufficient because it requires the input situation to be valid at the moment when the zone is entered. Here comes into play that a game usually runs its loop not based on events but continuously. I.e. the update() method of the zone calls onEntered as many times as it is itself called when the collision exists.

 

As said, the above is just one solution. I wanted to show another way than the one you already be aware of. Your current way isn't essentially wrong either. However, you should notice that letting the objects itself handle things (and I also mean rendering here) seems natural but isn't necessarily the best way. This is because it usually enforces a tighter coupling of classes (e.g. in your case the Player class needs to know Product, Machine, and perhaps Zone).




#5179874 How do you manage object pools in your engine/game?

Posted by haegarr on 12 September 2014 - 07:37 AM

The object pool pattern is about re-using objects by putting back wasted objects into the pool (perhaps up to an upper limit) instead of deleting them. So sub-sequent allocations are fed from the pool until those is depleted. The pool may be preset with a minimum of objects.

 

The pool allocation scheme is a concept where (usually fixed size) objects are allocated from a pre-allocated block of memory. Its purpose is to avoid the costs of generic new/delete or malloc/free operations in situations where the memory usage pattern is known.

 

Both concepts are independent; they can even be combined.




#5179818 2D Geometry Problem

Posted by haegarr on 12 September 2014 - 03:19 AM

The problem I'm having is getting a uniform thickness ...

Of course, Ashaman73 is right, but if "uniform thickness" is not taken literally, ...

... (the blue lines should all be the same length)

... so that differences in thickness are allowed just in corners (like in the illustration), then ray intersections can be used to determine the vertex positions. I.e.make copies of 2 consecutive edges, compute rays from them, displace them orthogonally by the wall thickness, and compute their intersection point to get the "golden vertex".

 

E.g. with the consecutive vertices v1, v2, v3 the rays would look like

   r12( k ) := v1 + w * perp( v2 - v1 ) + k * ( v2 - v1 )

   r23( k ) := v2 + w * perp( v3 - v2 ) + k * ( v3 - v2 )

where perp(v) means the (wanted) perpendicular normalized vector of v, and w denotes the wall thickness.

 

Then

   r12( k' ) = r23( k' )

gives a condition for the intersection. The condition denotes a point if the rays are not parallel, and hence solving for k' and setting back in one of the ray equations gives the vertex of interest. 




#5179375 Animation states and blend trees

Posted by haegarr on 10 September 2014 - 11:31 AM


Firstly, I obviously need some form of instance data with regard to my states, or at least the current state I'm in.  For example, I have my player character and as an entity, he has a component which is a state machine.  He is idling and so the current state in his state machine is the idle state.  In that state, i'll need to have some record of the local time for the idle animation that is playing.  That's all well and good, but if I have two players on the screen, would they each have their own state machine?  I'm wondering whether I keep the data seperate from the structure of the state machine although I'm not really sure how that would work.  A lot of the data in the state machine states would be common (fade time, fade type, animation clip name), it's only animation clip positions that would need to be stored, so copying the whole structure seems like a waste of memory.  Also, if a state uses a blend tree, there may be lerp positions that needs to be kept track of.

I also separate static and dynamic data. That is useful not only here but in general (i.e. also for skeletons).

 


Secondly, from an animation perspective, I understand the states and transitions that can occur but what should control the state machine?  I mean if it's entirely data-driven (which I intend it to be), some game logic somewhere has to know that when the player is in the idle state, he can walk or run (for example).  I know the data-driven state machine can represent this easily, but how would the game logic control that?  My initial thought was that the current state of each state machine would handle events so,  for example, when the user presses the up button on the controller, that event is fed through to the player's state machine (it's a component after all which can receive events) and the state knows (through data) that in this instance, pressing up in the idle state transitions to the walk forward state.

As mentioned by Buckshag, the state machine as well as the various blend trees are controlled by a set of variables (of course, these variables count to the dynamic data). Nothing inside the animation system should directly investigate input or observe events. Words like "button_up" in animation transition conditions hint at a design flaw.

 

Input should be decoupled because the animation system by itself is not necessarily player driven. The same animation system can perhaps be used to animate a NPC. What often is called a player controller investigates input and reacts by setting variables if a specific input situation is detected. These variables are an abstraction and have a meaning w.r.t. the character, e.g. they mean "walk forward with speed x", "jump", "pick up that object", and so on, but never "button x is pressed". This helps not only to keep the animation system clean, but also to have a dedicated place (outside the animation system, just to emphasize this once more) to deal with input configurations.

 

Regarding event observation (although not explicitly mentioned in the question): The animation system is called at one or more specific moments during looping though the game loop. When the animation system's update() is called, its the natural moment for state transitions to be checked. There is not only no need in pushing events into the state machine, it is even counterproductive to do so.




#5179346 Rendering large meshes in OpenGl

Posted by haegarr on 10 September 2014 - 09:48 AM

Some possibilities:

 

1.) Are the update rates of the vertex positions array and the normals array different? If not then put both into the same VBO and store them interleaved.

 

2.) Use an index buffer.

 

3.) Try invoking glVertexPointer as the last of all attribute set-ups. Even better, try to use a VAO if possible.

 

4.) Are the buffers allocated with GL_STATIC_DRAW (if applicable)?




#5178676 Calculating objects direction scene graph

Posted by haegarr on 07 September 2014 - 07:29 AM


... there must be a more efficient way to just reuse the parents world transformation matrix ...

If Wn is the world matrix of the model from which the viewing vector is of interest, so that

    Wn := M0 * M1 * ... * Mn

and transform the model local viewing vector with it to yield in its world space equivalent

    vn' := Wn * vn  w/  vn := (0 0 -1)t

then you effectively have picked the 3rd column of Wn and negated it (see that any influence of the 1st and 2nd columns is avoided due to the both zeros in the vector, that the 3rd element in the vector has the absolute value of 1 so does not scale the result).




#5178469 OpenGL texture array difficulties

Posted by haegarr on 06 September 2014 - 03:09 AM

I'm not aware of what your use case is, so recommending something is difficult...

 

If the clips stored within the levels of the texture array differ in size (but still fit into the texture image), you have in general 2 options:

1.) You scale the images so that they fit into the texture space, or

2.) you use adapted u,v tuples to address the clip.




#5178462 OpenGL texture array difficulties

Posted by haegarr on 06 September 2014 - 01:48 AM


And thank you for the heads up with the internalFormat, I wasn't aware that needed to be sized. This is one of those gaps in my opengl knowledge (one of oh-so-many). But, out of curiosity, what is the difference between the two? I'm totally capable of looking this up But if you have time, I'd always welcome some context for it.

AFAIK: The generic values allow the implementation to choose something that seems appropriate, what in theory may also mean a lower resolution. On the other hand, the sized formats request for a specific resolution.






PARTNERS