Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
Orzo
Sep 3, 2004

IT! IT is confusing! Say your goddamn pronouns!

Splat posted:

Are you able to run w/ variable timestep?
I could, but that's a design decision I'm not comfortable with. I think there's huge benefits to having fixed logical timesteps, notably consistency in gameplay across all machines regardless of performance, and also the ability to accurately reproduce scenarios which may only occur with certain timesteps.

Edit: bah, need quote, new page

Adbot
ADBOT LOVES YOU

Splat
Aug 22, 2002

Orzo posted:

I could, but that's a design decision I'm not comfortable with. I think there's huge benefits to having fixed logical timesteps, notably consistency in gameplay across all machines regardless of performance, and also the ability to accurately reproduce scenarios which may only occur with certain timesteps.

Edit: bah, need quote, new page


Sure there's benefits, but there's drawbacks too:

What do you plan on doing if a machine can't run at 60? Do you just run the game slow?

You can also support variable timesteps and then force fixed timesteps as a debug option.

Orzo
Sep 3, 2004

IT! IT is confusing! Say your goddamn pronouns!

Splat posted:

What do you plan on doing if a machine can't run at 60? Do you just run the game slow?
Yes.

quote:

You can also support variable timesteps and then force fixed timesteps as a debug option.
I don't understand why anyone would want to do this. Variable timesteps means different behaviors on different computers. I don't want people playing a different game depending on how fast their machine is.

What are the drawbacks exactly?

Splat
Aug 22, 2002

Orzo posted:

Yes.

I don't understand why anyone would want to do this. Variable timesteps means different behaviors on different computers. I don't want people playing a different game depending on how fast their machine is.

What are the drawbacks exactly?


Well there's one drawback above, which is that if you're on a slow machine the game will run slow. For some types of game this is acceptable, for others (action games for one) it really isn't. When you're mentioning different behaviors, do you have a specific thing that worries you?

Another drawback: do you want any slowmotion sequences in your game where you're actually updating at 333hz steps?

Mug
Apr 26, 2005
Having the game run in slow motion on a slow CPU is a pretty bad idea. Black Annex was doing that until like 3 days ago and it was just AWFUL on lovely old computers. That's why I've been doing all this frameskip stuff lately and now it runs like a dream.

edit: But I do give the player the option of "Disable frameskip" if they want.

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

Mug posted:

Having the game run in slow motion on a slow CPU is a pretty bad idea.
There is no good idea though - risking things passing through walls or quickly drifting out of orbit or whatever because you decided to do really long timesteps for a slow CPU is also a bad idea, and you basically have to pick one of those two if the CPU can't keep up with the game.

Either that or just have your game throw its hands up and say "your CPU can't cope with what's going on here, so gently caress you, get a better computer, I'm exiting now."

Skipping frames of rendering is generally fine to speed things up without making either of those compromises; that's basically what a fixed timestep uncoupled from the framerate amounts to. It becomes a problem when the physics situation is so complicated that the CPU can't even keep up with it when there's no rendering, because then you get no updates. A "maximum timesteps per frame" limit gives you a way out of that situation, at the cost of ending up with horrible jerky slow motion. But it's still better than just dying, because it means the game can still maybe make its way back to somewhere less taxing.

Edit to clarify: fixed timestep does not generally mean the game runs slow on a slow CPU - it means you get a bad framerate on a slow CPU. If the CPU is so slow that it literally can't run enough timesteps to keep up, it means the game shits its pants. This is assuming a fixed timestep that is not coupled to rendering (ie. it's not "one timestep every 60th of a second, and one render per timestep", but rather "how much time has passed? Do enough timesteps to catch up. Now render.")

roomforthetuna fucked around with this message at 23:53 on May 6, 2013

Splat
Aug 22, 2002
Sure you'll want a maximum acceptable timedelta still. I've generally found that decoupling rendering from logic leads to a bunch of mushiness that you can either deal with or not, and I generally hate mushiness.

Orzo
Sep 3, 2004

IT! IT is confusing! Say your goddamn pronouns!

Splat posted:

Well there's one drawback above, which is that if you're on a slow machine the game will run slow. For some types of game this is acceptable, for others (action games for one) it really isn't. When you're mentioning different behaviors, do you have a specific thing that worries you?

Another drawback: do you want any slowmotion sequences in your game where you're actually updating at 333hz steps?
What you're proposing is skipping logical frames for the sake of speed. Whether or not that's acceptable depends on the game, but I would argue that it's actually the worst for action games. A canonical example of a behavior that occurs with huge physical updates is skipping through walls. Sure, you can architect your entire game around using sweep collision algorithms to prevent such things, but that itself has its own drawbacks, namely it's more expensive and more complicated. Also, any behavior that involves acceleration is going to be slightly more complex to program such that results are consistent.

As for slow-motion sequences, that could be done by changing the speed of the 'accumulator' variable that counts up until the next frame. With proper visual interpolation, it would still look smooth.

Mug posted:

Having the game run in slow motion on a slow CPU is a pretty bad idea. Black Annex was doing that until like 3 days ago and it was just AWFUL on lovely old computers. That's why I've been doing all this frameskip stuff lately and now it runs like a dream.

edit: But I do give the player the option of "Disable frameskip" if they want.
If your game still runs 'correctly' at the maximum frameskip, why not just make that the default? What happens if the computer is so bad that the it still runs slow with the highest frameskip available?

Splat posted:

Sure you'll want a maximum acceptable timedelta still. I've generally found that decoupling rendering from logic leads to a bunch of mushiness that you can either deal with or not, and I generally hate mushiness.
Any examples? I have found--and I'm sure that I'm not alone here--that decoupling the two generally leads to a far more clean design.

OneEightHundred
Feb 28, 2008

Soon, we will be unstoppable!

Orzo posted:

If your game still runs 'correctly' at the maximum frameskip, why not just make that the default?
High frame drop rate = Looks choppy, less responsive.

Splat
Aug 22, 2002

Orzo posted:

What you're proposing is skipping logical frames for the sake of speed. Whether or not that's acceptable depends on the game, but I would argue that it's actually the worst for action games. A canonical example of a behavior that occurs with huge physical updates is skipping through walls. Sure, you can architect your entire game around using sweep collision algorithms to prevent such things, but that itself has its own drawbacks, namely it's more expensive and more complicated. Also, any behavior that involves acceleration is going to be slightly more complex to program such that results are consistent.

As for slow-motion sequences, that could be done by changing the speed of the 'accumulator' variable that counts up until the next frame. With proper visual interpolation, it would still look smooth.

If your game still runs 'correctly' at the maximum frameskip, why not just make that the default? What happens if the computer is so bad that the it still runs slow with the highest frameskip available?

Any examples? I have found--and I'm sure that I'm not alone here--that decoupling the two generally leads to a far more clean design.

Well, every production environment I've worked in uses swept collision. It's not simply because "I have a large timestep so I went through a wall", but "I can't support small objects moving fast". Unless everything's bounds in every dimension is at least as big as motion on that dimension can be in one timestep, you're going to run into issues.

Re: mushiness:

Let's say normally you run at 60.

You want a slowmotion sequence where you're running at 20x slow motion. If you press jump during slow motion, you'll have to wait until the next simulated (not interpolated) update, and then you'll finally see the jump motion start. This means your jump input is both delayed, and it's delayed inconsistently. This is the mushiness I was referencing that feels less than great.

But you're right in that you'll find people who are hardcore on either side of the issue. Physics/Rendering guys generally love fixed timesteps.

Orzo
Sep 3, 2004

IT! IT is confusing! Say your goddamn pronouns!

OneEightHundred posted:

High frame drop rate = Looks choppy, less responsive.
Looks choppy can be mostly mitigated with visual interpolation. Less responsive...right, that's definitely an advantage. But with my example, I think 60 physical frames a second is plenty responsive for games.

Splat posted:

Well, every production environment I've worked in uses swept collision. It's not simply because "I have a large timestep so I went through a wall", but "I can't support small objects moving fast". Unless everything's bounds in every dimension is at least as big as motion on that dimension can be in one timestep, you're going to run into issues.

Re: mushiness:

Let's say normally you run at 60.

You want a slowmotion sequence where you're running at 20x slow motion. If you press jump during slow motion, you'll have to wait until the next simulated (not interpolated) update, and then you'll finally see the jump motion start. This means your jump input is both delayed, and it's delayed inconsistently. This is the mushiness I was referencing that feels less than great.

But you're right in that you'll find people who are hardcore on either side of the issue. Physics/Rendering guys generally love fixed timesteps.
Ah. Well, yeah, swept collision is probably a given for larger studios. Unsurprisingly, this entire question really depends on the goals of the project. Personally, I am more comfortable with a fixed timestep for the particular game I'm making. Your thing about slowdown is interesting, but can't it also be solved with the same fixed timestep but also just slowing everything down (i.e. don't use the accumulator change that I suggested--you're right, that would cause bad response times)?

Either way I can see the appeal of the different approaches, good discussion.

Splat
Aug 22, 2002

Orzo posted:

Looks choppy can be mostly mitigated with visual interpolation. Less responsive...right, that's definitely an advantage. But with my example, I think 60 physical frames a second is plenty responsive for games.

Ah. Well, yeah, swept collision is probably a given for larger studios. Unsurprisingly, this entire question really depends on the goals of the project. Personally, I am more comfortable with a fixed timestep for the particular game I'm making. Your thing about slowdown is interesting, but can't it also be solved with the same fixed timestep but also just slowing everything down (i.e. don't use the accumulator change that I suggested--you're right, that would cause bad response times)?

Either way I can see the appeal of the different approaches, good discussion.

Well, passing in a smaller timedelta is a quick way to slow everything down :) But yeah, there is a lot depending on scope/type of project for sure and it's not that fixed stuff is wrong either, just that there's pros/cons for both sides that merit consideration.

Mug
Apr 26, 2005
I just skip frames of rendering and do the logic as fast as possible hoping the game catches up.

Unfortunately some PCs aren't fast enough to actually do the game logic at 60ticks per second so if I use autoframeskip and the game never catches up, it just locks up forever.

I have max frame skip of about 4 and if that's not good enough, the gameplay slows down instead.

DancingPenguin
Nov 27, 2012

I ish kakadu.
Thanks for the input about LÖVE.
I love it so far.
Just got one small problem, and I am not sure it is related to the LUA language.
Since I can not define variables as ints or such as I could in C++, is there any command or mathematical function to make sure that my score and time values are not displayed with decimals?
Basically my score prints to the screen right now as for instance 9.93 instead of just 9.
I would like to keep the decimals within the program since I might just add 0.07 to the score which would display 10 score, instead of it still displaying as 9.
Creating a display variable and a program variable would not be a problem, I just do not know how to make the display variable a number without decimals.

aerique
Jul 16, 2008
nevermind, stupid reply

aerique fucked around with this message at 10:05 on May 7, 2013

space kobold
Oct 3, 2009


DancingPenguin posted:

Just got one small problem, and I am not sure it is related to the LUA language.

What you're looking for is the math.floor() function, which will return the value rounded down.

http://lua-users.org/wiki/MathLibraryTutorial

edit: Looking through the doc, I just realized the Lua treats any number divided by 0 as infinity (inf), and infinity divided by infinity as not a number (nan). That's kind of awesome, or terrible, I'm not sure.

space kobold fucked around with this message at 13:51 on May 7, 2013

DancingPenguin
Nov 27, 2012

I ish kakadu.

space kobold posted:

What you're looking for is the math.floor() function, which will return the value rounded down.

http://lua-users.org/wiki/MathLibraryTutorial

Kudos to you space kobold, exactly what I was looking for.
This function works wonders.

DancingPenguin fucked around with this message at 12:37 on May 7, 2013

Winkle-Daddy
Mar 10, 2007
I hope it's okay that I do this... :ohdear:

Cross posting from the python thread as I'm using this for a game I'm working on and figured you guys might have a better idea of what I need to do.

I just installed the python noise plug-in. I tried the example 2dtexture.py, but am not sure how the hell to re-use the pgm format it saves the output to. Ideally, I'd like to use it the exact same way I used the panda3D implementation. Anyone able to help clarify my stupidity with a small example?

For clarity, the panda3D implementation works like:

code:
world = PerlinNoise3(100,100,100)
print(world(2,5,3))
Which will return a value between 0 and 1, where 0 is black, and 1 is white, everything in between are a float in between those two values. It makes it really convenient to procedurally generate some levels when I can just create a sprite sheet, then apply the correct texture index based on the value of the perlin noise location in 3D space. Unfortunately, I need to use an engine other than Panda3D for this project and have moved on to pyglet which does not seem to have a similar function built in.


I'm still trying to use this drat noise module, but I'm not getting any value out of it except 0. If anyone has used this before, can you tell me what I'm doing wrong?

code:
>>> from noise import pnoise2
>>> world = pnoise2(10,10,1)
>>> print(world)
0.0
>>> from noise import pnoise3
>>> x = pnoise3(10, 10, 10, octaves=1, persistence=0.5, repeatx=1024, repeaty=1024, repeatz=1024, base=0)
>>> print(x)
0.0
>>> x = pnoise3(100, 100, 150, octaves=1, persistence=0.5, repeatx=1024, repeaty=1024, repeatz=1024, base=0)
>>> print(x)
0.0
>>> x = pnoise3(100, 100, 150, octaves=1, persistence=0.5, repeatx=1024, repeaty=1024, repeatz=1024, base=125834)
>>> print(x)
0.0
>>> y = pnoise2(15, 10, octaves=1, persistence=0.5, repeatx=100, repeaty=100, base=125834)
>>> print(y)
0.0
>>> y = int(pnoise2(15, 10, octaves=1, persistence=0.5, repeatx=100, repeaty=100, base=1))
>>> print(y)
0
>>> y = int(pnoise2(15, 10, octaves=1, persistence=1, repeatx=100, repeaty=100, base=1))
>>> print(y)
0
>>> y = int(pnoise2(50, 30, octaves=1, persistence=1, repeatx=100, repeaty=100, base=1))
>>> print(y)
0
Nothing I try seems to work as I would expect it to. FWIW here is the help page for pnoise3:

code:
noise3(...)
    noise3(x, y, z, octaves=1, persistence=0.5, repeatx=1024, repeaty=1024, repeatz=1024, base=0.0)

    return perlin "improved" noise value for specified coordinate

    octaves -- specifies the number of passes for generating fBm noise,
    defaults to 1 (simple noise).

    persistence -- specifies the amplitude of each successive octave relative
    to the one below it. Defaults to 0.5 (each higher octave's amplitude
    is halved). Note the amplitude of the first pass is always 1.0.

    repeatx, repeaty, repeatz -- specifies the interval along each axis when
    the noise values repeat. This can be used as the tile size for creating
    tileable textures

    base -- specifies a fixed offset for the input coordinates. Useful for
    generating different noise textures with the same repeat interval
I'm reading "base" to basically be what would commonly be called the "seed" value, though I'm not actually sure that's correct. I'm also not entirely sure what persistence is, but it does lead me to believe I should get return values of at least 1.0 for any given coordinate and not 0.

Please help me with my dumb.

SlightlyMadman
Jan 14, 2005

I was up all night last night, working on breaking up continents for my Risk-like. It's simple enough to detect landmasses, and join small islands to their neighboring continents, but breaking up a large continent proved to be a fairly tricky problem. I ended up determining the longest route between two nodes (by simply brute-force comparing each node against each other, which works fine on such small maps), then splitting the cells up so those closer to the left end of the line become a new continent. This works pretty well, takes geography into account to an extent, and keeps a fairly even split:



The only problem is in blobbier landmasses, it can create border areas of several cells between continents, instead of cutting them off at logical and easily defensible choke points. I think if that becomes an issue, Ill do a choke-point check that calculates paths between all nodes on the island, and tracks the frequency any given node is passed through. Order the nodes by the number of times they're passed through, and check if they're along the longest path line. If they are, calculate how many nodes are on the left vs. the right. If it creates regions large enough to be continents, split there. If not, move on to the next.

That's the best solution I can come up with. It's a surprisingly more difficult problem than I expected.

edit: cleaned the borders up a bit:

SlightlyMadman fucked around with this message at 23:48 on May 7, 2013

aerique
Jul 16, 2008

Winkle-Daddy posted:

I'm still trying to use this drat noise module, but I'm not getting any value out of it except 0. If anyone has used this before, can you tell me what I'm doing wrong?

It's been a while but try some float values instead of the integers you're using now, so instead of 15 try for example 15.35. Or just stay between 0 and 1.

From what I recall from perlin noise is that it is made to wrap around so 0 and 1 it will indeed always return 0.

poemdexter
Feb 18, 2005

Hooray Indie Games!

College Slice
Edit: Not the Dota 2 thread. hurf.

poemdexter fucked around with this message at 15:36 on May 8, 2013

seiken
Feb 7, 2005

hah ha ha
Well that post was somewhat out of left field. Embarrassingly, I think I sort of know what you're talking about.

Joda
Apr 24, 2010

When I'm off, I just like to really let go and have fun, y'know?

Fun Shoe
Does anyone have any good tutorials on how to make sidescrollers using linear algebra if all you have is a basic games library that essentially just does rendering and collision detection? Any language will do, but I'd prefer Java or one that explains it abstractly.

I already have a fairly decent knowledge of linear algebra, so it doesn't have to explain these concepts in-depth, but I wouldn't mind if it does.

Thanks in advance.

No Safe Word
Feb 26, 2005

poemdexter posted:

Dota 2 stuff

You made me think I was in the wrong thread

Orzo
Sep 3, 2004

IT! IT is confusing! Say your goddamn pronouns!

Joda posted:

Does anyone have any good tutorials on how to make sidescrollers using linear algebra if all you have is a basic games library that essentially just does rendering and collision detection? Any language will do, but I'd prefer Java or one that explains it abstractly.

I already have a fairly decent knowledge of linear algebra, so it doesn't have to explain these concepts in-depth, but I wouldn't mind if it does.

Thanks in advance.
I'm not quite sure I follow what you're asking. Sure, algebra and lots of other math will probably come into play with *any* game programming, but what aspect in particular are you looking for tutorials about? Player movement? Scrolling the camera? I'm sure there are tutorials out there for any of these components--and there's probably plenty that go over sidescrollers as a whole, too--but I don't understand what you mean by 'sidescrollers using linear algebra.'

seiken
Feb 7, 2005

hah ha ha

Orzo posted:

I'm not quite sure I follow what you're asking. Sure, algebra and lots of other math will probably come into play with *any* game programming, but what aspect in particular are you looking for tutorials about? Player movement? Scrolling the camera? I'm sure there are tutorials out there for any of these components--and there's probably plenty that go over sidescrollers as a whole, too--but I don't understand what you mean by 'sidescrollers using linear algebra.'

Yeah, if you already have collision done for you then you shouldn't need much more than knowing about vectors and trigonometry for the rest. I guess you could use matrices to do rotated rendering or what have you, depending on how the rendering library you're using is set up, but your question is way general.

seiken fucked around with this message at 15:27 on May 8, 2013

Joda
Apr 24, 2010

When I'm off, I just like to really let go and have fun, y'know?

Fun Shoe

Orzo posted:

I'm not quite sure I follow what you're asking. Sure, algebra and lots of other math will probably come into play with *any* game programming, but what aspect in particular are you looking for tutorials about? Player movement? Scrolling the camera? I'm sure there are tutorials out there for any of these components--and there's probably plenty that go over sidescrollers as a whole, too--but I don't understand what you mean by 'sidescrollers using linear algebra.'

Well to my understanding the most cost-effective and dynamic way to make rendering and camera movement is using linear algebra (linear transformations/transformation matrices specifically,) and while I do have some ideas on how to implement it, I think a tutorial would help me get started properly.

I know I don't actually have to do it like that, but the more intuitive method of just using vectors and vector addition means things like zooming and camera rotation will have to be implemented separately.

That Turkey Story
Mar 30, 2003

I've been working on a little game development library in C++ for a while and I've recently gotten some cool, high-level transformation code working. The idea of the following part of the library is that it's a level of abstraction that rests over other linear algebra libraries, but it adds support for units, "named dimensions," and named parameter passing. I'm trying to make the code as intuitive as possible for someone to use even if they do not have much background in the domain. The following is a brief example (most comments intentionally removed):

C++ code:
// Include all of the library (prefer more fine-grained headers in practice).
#include <nuts/sl.hpp>
#include <boost/units/systems/si/length.hpp> // For the meters unit

int main()
{
  using namespace nuts::sl;
  using namespace nuts::sl::direction;
  using boost::units::si::meters;

  auto const position
    = point( right = 4.0 * meters, up = 3.5 * meters, forward = 6.0 * meters );

  auto const transformed_point
    = transform( scale( width = 2.0, height = 4.0 )
               , translation( left = 0.5 * meters )
               , rotation( roll = 60.0 * degrees )
               , position                           // What to transform
               );
}
Before reading the spoiler below, I'm curious what someone would think it does if they'd never seen the library before (I assume at least some familiarity with the language, though). Try to think about it and then tell me if it corresponds to my explanation.

What this does underneath the hood is the equivalent of creating a 3-component point at the location (4, 3.5, 6) with the dimensions and units that were specified. I don't expect much confusion here. The names "right/left," "up/down," "forward/back," and user-created dimension kinds are supported and points with any number of dimensions can be generated from this template (the result is a statically-sized point with the corresponding amount of dimensions, not a dynamically-sized point).

After the point is created, the program then accumulates a transformation by combining any number of simpler transformations, and finally applies that accumulated transformation to our position, yielding a new position. It's an abstraction over matrix multiplication in a homogeneous coordinate system.

For example, here it will double the width and quadruple the height, leaving the depth unchanged. It will then translate within that new reference frame (so the translation effectively would go left by 1 meter, not 0.5 meters, which is the main "tricky" part that I'd like to better convey directly within the code). Finally it will roll by 60 degrees (you can also specify this as "right_to_up = 60 * degrees" or "up_to_right = 60 * degrees," or via any combination of one of each up/down and left/right so there is no confusion between clockwise and counter-clockwise roll).

Just like matrix multiplication, the order is not commutative. If you want the translation to not be affected by the scale, for instance, you do it before the scale parameter.


This is ultimately the functionality that ends up being the most useful in practice, so rather than change how this code behaves, assuming it doesn't correspond to intuition, I'm mostly interested in hearing alternate names for dimensions/dimension magnitudes/rotations/functions to better match this functionality. In particular it might be confusing which dimensions "width" affects (though height seems pretty clear). The remaining named dimension magnitude that I provide is "depth," which I'm worried may be the most confusing as it could potentially be mixed up with "height," though the alternative "length" seems equally confusing to me with respect to "width." I'm sure there are alternatives here that are a bit more clear.

I'd really like to stick to named identifiers for the reasons mentioned above, but at the same time I don't want the vocabulary involved to be too difficult to remember or too verbose.

Suspicious Dish
Sep 24, 2011

2020 is the year of linux on the desktop, bro
Fun Shoe
Stop being clever. Just write code.

That Turkey Story
Mar 30, 2003

Suspicious Dish posted:

Stop being clever. Just write code.

That's what work is for.

Suspicious Dish
Sep 24, 2011

2020 is the year of linux on the desktop, bro
Fun Shoe
What you are doing is not a good idea. I don't want to have to debug this poo poo when things go haywire.

Bizarro Buddha
Feb 11, 2007
Making no judgements about the sanity of the library you are writing (because it is insane) for the three words to pair with up/right/forward you could try vertical/horizontal/depth. Or just reusing up/right/forward in the context of scaling.

But you are insane.

Suspicious Dish
Sep 24, 2011

2020 is the year of linux on the desktop, bro
Fun Shoe
Do not give an insane man ideas. Give him shame.

That Turkey Story
Mar 30, 2003

Suspicious Dish posted:

What you are doing is not a good idea. I don't want to have to debug this poo poo when things go haywire.
Noted.

Bizarro Buddha posted:

Making no judgements about the sanity of the library you are writing (because it is insane) for the three words to pair with up/right/forward you could try vertical/horizontal/depth. Or just reusing up/right/forward in the context of scaling.
Yeah, I've considered just using left/right with scale, but I'm worried it might be confusing to scale a "right" component by "left," but perhaps it is not. Ultimately a scale by "left" and by "right" should be the same thing. Using "vertical" is a good idea, but "height" wasn't really the confusing part. I think the main thing I want to do is just replace the word "depth."

Suspicious Dish posted:

Do not give an insane man ideas. Give him shame.
Serious question -- are you saying that because you think it's not useful, or are you just against the types of tricks that necessarily go on behind the scenes to do this? If you just don't like that magic, then that's fine, just don't use the library then. The whole reason for me venturing off for this is because of real-world problems I've run into from jumping between different projects with different teams and different libraries and coordinate systems. I mostly am doing it for my own sanity to see what an actual high-level library in the domain would be like (not that the game industry would ever touch a template let alone the voodoo I'm doing here). I want to be able to do things like write generic model loaders that work with arbitrary, user-defined vertex types, etc. so that I can simply write the code once and easily use it in multiple projects. I don't want to have to be concerned about vertex representation, different coordinate systems, unit transformations, or whatever. This library is the backbone of that.

Shalinor
Jun 10, 2002

Can I buy you a rootbeer?

That Turkey Story posted:

The whole reason for me venturing off for this is because of real-world problems I've run into from jumping between different projects with different teams and different libraries and coordinate systems. I mostly am doing it for my own sanity to see what an actual high-level library in the domain would be like (not that the game industry would ever touch a template let alone the voodoo I'm doing here). I want to be able to do things like write generic model loaders that work with arbitrary, user-defined vertex types, etc. so that I can simply write the code once and easily use it in multiple projects. I don't want to have to be concerned about vertex representation, different coordinate systems, unit transformations, or whatever. This library is the backbone of that.
So long as you realize that no one would let a library like this within 100 feet of their production code, you'll be fine. This has applications in tools. But when you presented it, I assumed you were thinking this would form up the transformational basis of entities in a world, which was very... uh. :stare:

It looks like the kind of thing a graduate student would build while making a hyper-generic high-level engine, that has zero application outside of the experimental environment said generic engine was built for.

Orzo
Sep 3, 2004

IT! IT is confusing! Say your goddamn pronouns!
To be fair, I don't think abstracting lower level operations into higher level operations is a bad idea. Defining the types of high-level operations that your game-code (not engine code) actually use, and then actually using them, is a good idea. That being said, I would ditch the left/right up/down notation and just use positive and negative values for X, Y, and Z already. There is literally no advantage to using 'left/right' instead of -X/+X, and you will confuse anyone who tries to use your library with 'left/right' notation.

That Turkey Story
Mar 30, 2003

Shalinor posted:

So long as you realize that no one would let a library like this within 100 feet of their production code, you'll be fine. This has applications in tools. But when you presented it, I assumed you were thinking this would form up the transformational basis of entities in a world, which was very... uh. :stare:

It could, but yeah, it's mostly intended as a glue that allows people to write code that is re-usable between projects without being intrusive at all. You are able to pick off one or two little algorithms without adopting a specific linear algebra library or graphics library. For instance, I'm using the "point" function and passing an instance of it to transform, but the way that transform is written, it works with arbitrary user-defined types (it's based around concepts). So, let's say you want to use a pre-written model loader for some common model format -- what you do is you provide a little bit of compile-time metadata that describes your point/matrix/vertex types so that the library understands it (i.e. so it knows that the third component of the point goes "up" rather than "back" or "forward"). The loader, and the rest of the library, now can work directly with your types. You don't have to load into some separate format and then convert it to yours, etc. On pretty much every project I've worked on I've seen different versions of this type of code, handwritten loaders, wasted time, and lots of bugs.

Orzo posted:

To be fair, I don't think abstracting lower level operations into higher level operations is a bad idea. Defining the types of high-level operations that your game-code (not engine code) actually use, and then actually using them, is a good idea. That being said, I would ditch the left/right up/down notation and just use positive and negative values for X, Y, and Z already. There is literally no advantage to using 'left/right' instead of -X/+X, and you will confuse anyone who tries to use your library with 'left/right' notation.
Actually, that's sort of the motivating case for the library. The distinction between left/right and a vague "x" really is important in practice and is one of the reasons why it's difficult to find truly generic, reusable components for games. It's okay if you are dealing with exactly one project and you stick to a convention, but it makes it difficult to pull in code from other sources.

That Turkey Story fucked around with this message at 18:18 on May 8, 2013

Orzo
Sep 3, 2004

IT! IT is confusing! Say your goddamn pronouns!
I don't follow. What would be an example of something that doesn't use 'x/y' or 'x/y/z'?

Suspicious Dish
Sep 24, 2011

2020 is the year of linux on the desktop, bro
Fun Shoe

That Turkey Story posted:

If you just don't like that magic, then that's fine, just don't use the library then.

This is the reasoning that bugs me. I'm certainly not going to use this library, but it's possible that a colleague does, or a former colleague does. My programming philosophies are aimed at designing APIs and making code that's simple to understand, even if it means it's a bit verbose. And if something goes wrong, I have to step through template madness in my breakpoint debugger, cursing at whoever did this.

C++ code:
  auto const transformed_point
    = transform( scale( width = 2.0, height = 4.0 )
               , translation( left = 0.5 * meters )
               , rotation( roll = 60.0 * degrees )
               , position                           // What to transform
               );
There's lots of assumptions here, like what space we're working in, and what order the transformations are being applied in (the source is at the end, so does that mean we work backwards?)

Compare with:

C++ code:
  auto const transformed_point = position;
  transformed_point.scale(2.0, 4.0, 0); // I'm assuming width = X and height = Y, but who knows.
  transformed_point.translate(-0.5 * meters, 0, 0); // left = negative X
  transformed_point.roll(60.0 * degrees);
The first thing I want to point out is that it's less lines of code to use. It's a bit more verbose, but I think it's a lot more explicit. There's subtle things in that API too, like that I'm passing three parameters in the scale and transform -- one or two is ambiguous, and with a method name like "scaleX" or "transformX", it's easy to miss.

And now that all the transformations are independent methods, I can inspect the intermediate result without understanding the internals of the API -- if I get a wrong result, I have a clear debug path that's not delving into a metasystem.

It's probably also faster, given that the compiler might be able to inline the calls to simple math methods rather than a generic system.

Note that this isn't a *new* API. I've seen it done a thousand times over, since 1996. There's a reason it's *the* API for this.

I kept the units system in there because I didn't really care enough to remove it. It's not my main concern.

Suspicious Dish fucked around with this message at 18:42 on May 8, 2013

Adbot
ADBOT LOVES YOU

Suspicious Dish
Sep 24, 2011

2020 is the year of linux on the desktop, bro
Fun Shoe

That Turkey Story posted:

Actually, that's sort of the motivating case for the library. The distinction between left/right and a vague "x" really is important in practice and is one of the reasons why it's difficult to find truly generic, reusable components for games. It's okay if you are dealing with exactly one project and you stick to a convention, but it makes it difficult to pull in code from other sources.

"left" is a relative thing. What space is it relative to? Who decides that? The user of the library? Where?

If, for instance, your model format has a different understanding of X/Y/Z than your engine, you can fix that once, on model load. Making something where everything is generic at runtime is a recipe for disaster. Will you generate your vertex shaders with different coordinate systems, too? Will you correct before you do the upload?

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply