Beta release 1.9.8b

Information and change log about the latest ZGameEditor release.

Moderator: Moderators

User avatar
Kjell
Posts: 1876
Joined: Sat Feb 23, 2008 11:15 pm

Post by Kjell »

Hejsan ~

The translation is done in local space yes, but not the scaling ( I should have mentioned this more explicitly ). When you have your basic Accumulation setup using 8 loops of a plane with a 45 degree ( 0.125 rad ) Rotation over Z each pass, and a Scale of 2 over X on the first pass ( the rest has a scale of 1 ), you can see that each individual shape has been scaled in World-Space instead of using the Accumulated Matrix. This results in a stretched cog-like mesh, while it should be round obviously.

Attached is the mesh I described.

K
Attachments
Mesh.zgeproj
(936 Bytes) Downloaded 721 times
User avatar
VilleK
Site Admin
Posts: 2274
Joined: Mon Jan 15, 2007 4:50 pm
Location: Stockholm, Sweden
Contact:

Post by VilleK »

Thanks for the example. I could see that scale needs to be done before rotation. I've checked in this change to the repository.

However your example still won't be round. Instead it becomes identical to the corresponding example using RenderTransform:

Code: Select all

ZZDC<?xml version="1.0" encoding="iso-8859-1" ?>
<Model Name="Model1">
  <OnRender>
    <Repeat Count="8">
      <OnIteration>
        <RenderTransform Name="Trans2" Translate="1 0 0" Rotate="0 0 0.125"/>
        <RenderSprite/>
      </OnIteration>
      <WhileExp>
<![CDATA[//this.Iteration=current iteration nr. Return false to end loop.

if(this.Iteration==0) {
  Trans2.Scale.X=2;
} else {
  Trans2.Scale.X=1;
}

return this.Iteration<8;]]>
      </WhileExp>
    </Repeat>
  </OnRender>
</Model>
And since this is the behavior of OpenGL accumulating matrices I wonder if this can be avoided?

But if I change the order of matrices like this:

Code: Select all

  //Meshes.pas line 1745
  Self.Matrix := MatrixMultiply(Self.Matrix,CreateTransform(Self.Rotation,Self.Scale,Self.Position));
Then, success, your example is round! But then my translation of the structuresynth-project does not work anymore so this probably means that the way parameters are set in that program is not compatible with our code. I need to look into this some more. Let me know if you can provide additional help because this is making my head hurt slightly :)
User avatar
Kjell
Posts: 1876
Joined: Sat Feb 23, 2008 11:15 pm

Post by Kjell »

Ehm,

At least we have the RenderTransformGroup for rendering :wink:

Code: Select all

ZZDC<?xml version="1.0" encoding="iso-8859-1" ?>
<Model Name="Model">
  <OnRender>
    <Repeat Count="8">
      <OnIteration>
        <RenderTransform Translate="2 0 0" Rotate="0 0 0.125"/>
        <RenderTransformGroup Scale="2 1 1" Translate="1 0 0">
          <Children>
            <RenderSprite/>
          </Children>
        </RenderTransformGroup>
      </OnIteration>
    </Repeat>
  </OnRender>
</Model>
But since there is no way to Push / Pop / Sequentially modify the Matrix when using MeshTransform, it should cater for the most desirable situation ( as you mentioned ). I guess this is why OpenGL has individual matrix operations for translate / rotate / scale.

I'm in the IRC channel if you need me.

K
kattle87
Posts: 402
Joined: Wed Sep 26, 2007 9:06 am
Location: Italy

Post by kattle87 »

Ok guys I think we should get instead of a single meshtransform matrix a stack of matrices to be coherent with the OpenGL transform stack. I hope this is easy to implement... I know how to use templates in C++. I don't have any idea about how to do this with Object Pascal.
In the fall of 1972 President Nixon announced that the rate of increase of inflation was decreasing. This was the first time a sitting president used the third derivative to advance his case for reelection.
-=Hugo Rossi=-
User avatar
VilleK
Site Admin
Posts: 2274
Joined: Mon Jan 15, 2007 4:50 pm
Location: Stockholm, Sweden
Contact:

Post by VilleK »

Templates are called generics in Pascal but they are not available in Delphi 2007. They are a new feature in Delphi 2009. I will probably migrate ZGE to Delphi 2009 later this year, but even then it is unlikely that generics are well suited to be used in the ZGE runtime because of code bloat.

Are you suggesting that instead of a MeshTransform with a single matrix it should hold a stack of matrices? I think this idea is interesting but I'm not sure how the component should be designed. Maybe instead of a single Accumulate-checkbox we could have PushMatrix/PopMatrix-checkboxes also? So each time MeshTransform is executed it could examine its properties and perform the relevant matrix stack operation.

To comment on jph's post I think that the idea of a BitmapTransform-component is interesting and should be investigated if we can make such a component that is both powerful and easy to use. Lets solve this for meshes first and see what we can do for bitmaps later.

Kjell: These kind of components do not take much exe-space because they only make calls to existing code in the math-units. And because matrix type in expressions is much more difficult to implement (and slightly more difficult for the end-user to use) I'd rather evaluate the component approach first.
User avatar
VilleK
Site Admin
Posts: 2274
Joined: Mon Jan 15, 2007 4:50 pm
Location: Stockholm, Sweden
Contact:

Post by VilleK »

I read in an article that when transforming normals only the rotation should be taken in account so I updated the MeshTransform component to maintain a separate matrix for the normals.
kattle87
Posts: 402
Joined: Wed Sep 26, 2007 9:06 am
Location: Italy

Post by kattle87 »

I was just thinking about getting 2 transform producers:
-Mesh transform: dunno about accumulation checkbox
-Mesh Transform group: similar to render transform, but for meshes :P

I would love to see a separated component that works in a similar way a loop component works, and it would be dedicated to mesh production. I don't know why but I don't like the current implementation, I feel like lots of people might just be scared and never use it.
In the fall of 1972 President Nixon announced that the rate of increase of inflation was decreasing. This was the first time a sitting president used the third derivative to advance his case for reelection.
-=Hugo Rossi=-
User avatar
VilleK
Site Admin
Posts: 2274
Joined: Mon Jan 15, 2007 4:50 pm
Location: Stockholm, Sweden
Contact:

Post by VilleK »

I agree with you, we should keep it easy to use. I'm not too fond of the Accumulate-property either but I found no other way to reset the matrix.

MeshTransformGroup would work. But since the matrix is reset after execution we still need a way to accumulate transforms. And if MeshTransform cannot accumulate then it leaves much more work for the user because they need to update the properties of MeshTransform for each iteration, for example setting Position.Y to 1,2,3,4 etc instead of just leaving it as 1 and let it accumulate automatically.

Your loop-idea is interesting. Perhaps something like a MeshTransformIterator with properties similar to the Repeat-component? It would automatically reset the matrix before the first iteration and then accumulate the other iterations.
kattle87
Posts: 402
Joined: Wed Sep 26, 2007 9:06 am
Location: Italy

Post by kattle87 »

I am starting to delineate such a component: I would like to see it done this way:
-Main iterator, possibly containing a visible counter and a rotation/scale/position property. When those values are modified, the matrix corresponding to the current iteration is modified. Otherwise, the matrix remains unchanged.
-mesh components "internal to the loop" are added to the mesh at every step.
Easiest way (to me) for doing this is:
-At every iteration the existing mesh is modified by applying the "inverse transform matrix" to the whole mesh.
-The other meshes are added as usual. (no need to transform the single points)
-At the end of the last cycle, all the transform matrices are applied in the "correct order (from last to first)" so every vertex should now be in the position you wanted. Note that applying several transform matrices is equivalent to get all the matrices and multiply them, so in the end this is not so much expensive (CPU time)
This *should just work* in theory. It will be possible to read the counter and use "if-statements" to get splitting (EG: leaves on the tree) (or even add other similar components).
Tell me what do you think about this.
In the fall of 1972 President Nixon announced that the rate of increase of inflation was decreasing. This was the first time a sitting president used the third derivative to advance his case for reelection.
-=Hugo Rossi=-
User avatar
Kjell
Posts: 1876
Joined: Sat Feb 23, 2008 11:15 pm

Post by Kjell »

:?

Reading, multiplying and writing all the existing vertices each pass is probably significantly slower then just doing this with the to be added ones.

K
kattle87
Posts: 402
Joined: Wed Sep 26, 2007 9:06 am
Location: Italy

Post by kattle87 »

We are speaking about a component made for creating a mesh not in real-time, and it doesn't really have to work this way! Of course you can do it in a different way but I do think this is the easier to be programmed. Maybe the whole can be done with a recursive function in an easy way, too, but that's how the internals should work and it is not so much important right now. But what about the component I described? I mean, do you think it being user friendly and effective?
In the fall of 1972 President Nixon announced that the rate of increase of inflation was decreasing. This was the first time a sitting president used the third derivative to advance his case for reelection.
-=Hugo Rossi=-
User avatar
VilleK
Site Admin
Posts: 2274
Joined: Mon Jan 15, 2007 4:50 pm
Location: Stockholm, Sweden
Contact:

Post by VilleK »

kattle87 wrote:Easiest way (to me) for doing this is:
[three steps]
I'm not quite following the math here. Is what you are describing the "correct" way instead of just transforming each new mesh after each iteration? It will be quite a lot of code to maintain a list of matrices and apply them in reverse order after all iterations.

There could also be some problems involved with having a list of mesh-producers inside another producer. I could try to write the basic component and then we can evaluate different approaches to the transformation together?
kattle87
Posts: 402
Joined: Wed Sep 26, 2007 9:06 am
Location: Italy

Post by kattle87 »

This is not the "correct" way of doing it, it's just different one. What I am describing here is an "intelligent loop" component (I will call it MeshLoop from now on) that automatically transforms the meshes you add inside it (So you still have to use a MeshCombine component, but you can also use IFs, ZExpressions and so on).
I don't know if we are speaking about a similar component, or you just want some kind of "iterator" that takes a mesh as a parameter and just outputs the correct result. It might be easier but less useful.
I can't figure out an easy way of achieving the same of a MeshLoop component that just transform the new added meshes without the need of an accumulation property to be set by the end user... This is the real reason for me thinking about this "a bit expensive" way of doing it. I agree a better way does exist, but I can't find it.

EDIT: I attach an explanation about how it works (mathematically-wise). Don't bother to understand it unless we find no other nice solution. The only important thing here is that we need nothing like a stack because "the inverse order multiplication" is just about making the right multiplication at every step.
Attachments
rotation matrix aproach.zip
(876 Bytes) Downloaded 669 times
In the fall of 1972 President Nixon announced that the rate of increase of inflation was decreasing. This was the first time a sitting president used the third derivative to advance his case for reelection.
-=Hugo Rossi=-
User avatar
VilleK
Site Admin
Posts: 2274
Joined: Mon Jan 15, 2007 4:50 pm
Location: Stockholm, Sweden
Contact:

Post by VilleK »

Yes, I was thinking something like:

MeshLoop
- Count
- Scale/Translate/Rotate
- OnIteration
-- MeshBox
-- MeshExpression
-- ...

When MeshLoop is executed, it resets the internal matrix. It then executes OnIteration-list Count times. After each iteration it takes the mesh last added to the stack and applies the transform onto the vertices. It then takes the next mesh from the stack, combines the meshes, and pushes the result.

As I said, I don't know if this will work. But I can try it out. Maybe we can do separate MeshLoop_Kattle and MeshLoop_Ville and compare different styles :)
kattle87
Posts: 402
Joined: Wed Sep 26, 2007 9:06 am
Location: Italy

Post by kattle87 »

I was now thinking about this approach again.
The only big difference is that in the your implementation one must set the parameter "the way the mesh is combined" and it can't be changed. Since right now we have only one way of combining the meshes this is not big deal. And we can still add such a parameter in no-time. So I bet it's better if we go with your approach. Just one idea running through my head:
maybe counter should go from the set number towards zero and be read-only? This way the number "1" always means "end of mesh/leaf" and it should be easier to use with IFs and other stuff.
Still, both the approaches don't let you "split" the mesh in an easy way. For doing this, we can "pop" the matrices and I have some ideas about how to do this code-wise, but no ideas about how we can work this out in the interface. One nice component would be something making recursive meshes easy, like a "SubLoop" that creates a mesh similar to the main "MeshLoop" one.
In the fall of 1972 President Nixon announced that the rate of increase of inflation was decreasing. This was the first time a sitting president used the third derivative to advance his case for reelection.
-=Hugo Rossi=-
Post Reply