Jump to content

  • Log In with Google      Sign In   
  • Create Account

JTippetts

Member Since 04 Jul 2003
Offline Last Active Today, 08:24 PM

#5293110 How do I create tileable 3D Perlin/Simplex noise?

Posted by JTippetts on Yesterday, 02:41 PM

The issue with the lines is a problem inherent to the calculation of the weighting factors in the 6d implementation of simplex noise. It's been several years now, so I can no longer remember the exact details of why I was unable to find weight factors that would work correctly, but the ultimate conclusion I came to was that using standard perlin noise gave much better results than simplex at higher dimensions.

Standard noise is, for me at least, easier to extend. Simplex noise is simple enough conceptually, but the implementation gets very weird in a hurry as you add dimensions. I based my simplex generator on a python n_dimensional generator I found somewhere. The python generator exhibited the same anomalous behavior.

I would say to give standard noise a try to see if results work better for you. Meantime, I might dig back into things to see if I can work out the underlying problem this time around.


#5291721 Scripting

Posted by JTippetts on 15 May 2016 - 01:31 PM

...mostly for learning purposes

...I'm looking for a way to make it easy for the end-user to create and manipulate entities.


The second one can be quite complicated. In light of the first, it might be a better idea for you to start learning the basics of integrating a scripting language, as well as all the other things you need to learn. With experience, you might gain some useful insight into the latter one.

The actual integration of a scripting language can be complex. The highest level is a straight-across, 1 for 1 binding of your API. Somebody (I think it was Hodgman) once linked a colorful article about why that might not be the best idea, but I didn't save the link. The gist of it, though, is that languages like Lua are different beasts than C++, and if all you're going to do is a 1 for 1 API binding, you're probably better off just using C++.

To go beyond 1 for 1 binding, though, takes a little bit of engine-specific ingenuity. One engine, I use, Urho3D, implements Lua and AngelScript binding using the 1 for 1 API exposure, but they also integrate a ScriptObject component that can be added to an object. This component acts as a glue layer, passing events across the Lua/C++ or AS/C++ boundary.

Still, I suggest you spend some time playing with things, rather than trying to design something easy to use by end-users right out of the gate.


#5291651 really slow software rendering on android with SDL2

Posted by JTippetts on 14 May 2016 - 09:15 PM

I just want to know the reason why on my desktop the game runs at 50fps and the same exact code runs at 18fps on the S4.


Because comparing a desktop processor side-by-side with a mobile processor using clock frequency alone is pointless. There are a lot more complicated features of a given processor that go into its overall performance. Mobile processors are very much designed with power efficiency and low heat generation in mind. They have to be, in order for the battery to last more than 30 seconds and in order for the heat output to not burn a hole in your hand.

The desktop processor cares MUCH less about power efficiency and heat dissipation, given its mains power source and the presence of on-board heatsink and cooling fans.

The way I heard it once is that clock frequency is a lot like engine RPM. Even if a 2-cycle weed eater and a turbo-charged Chevy big block 454 are pulling the same number of RPMs, that doesn't mean they're putting out the same amount of horsepower.


#5290979 Distributing a variable [0-1] logarithmically

Posted by JTippetts on 10 May 2016 - 09:50 AM

In the book Texturing and Modeling: A Procedural Approach, one of the authors (I believe it was Perlin) provided two functions he uses to re-distribute values in the unit range:

function bias(t, b) return math.pow(t, math.log(b)/math.log(0.5)) end
function gain(t, g) if t<0.5 then return bias(1.0-g, 2.0*t)/2.0 else return 1.0-bias(1.0-g, 2.0-2.0*t)/2.0 end end
The bias function is used to push values toward one end or the other; values of b less than 0.5 push values of t nearer to 0, while a bias greater than 0.5 push the values toward 1. gain uses bias, and has the effect that if g is less than 0.5, the values are pushed toward the ends, while greater than 0.5 values are pushed toward the middle. In both these functions, 0.5 for the bias or gain factor results in the linear curve. For example:

If the linear curve looks like this:

yPwMxMI.png

then the same curve with bias(0.2) applies looks like this:

ggSo82N.png

bias(0.8) looks like:

5mMhzhR.png

gain(0.2) looks like:

GYu25Pl.png

and gain(0.8) looks like:

EFPJXyv.png

In all cases, if t is in the range 0,1 then the output will also be in the range 0,1.


#5290196 How do I create tileable 3D Perlin/Simplex noise?

Posted by JTippetts on 04 May 2016 - 09:49 PM

Some years back, when I was implementing my own higher orders of simplex, I found an implementation of N-dimensional simplex noise in Python: https://github.com/Craig-Macomber/N-dimensional-simplex-noise/blob/master/simplex.py Converting it from Python would take a little bit of work, but you could probably work it out in time.

You might be able to find more by googling for "n dimensional simplex noise". The simplest variant to convert to higher dimensions is the original Perlin noise, as it simply deals with interpolating the corners of an N-dimensional hypercube. Conceptually it's simple, but algorithmically it gets complex in an exponential fashion. You can decompose the recursive structure of standard Perlin noise into polynomial form, but the higher orders get pretty sticky. I talk about my efforts to write polynomial versions of 6D noise at http://www.gamedev.net/blog/33/entry-2254250-derivative-noise/

The code posted by vinterberg demonstrates the blending method which is the simplest method, mathematically. For basic cloud noise, it's probably suitable. However, for high-contrast functions, or functions with strongly defined patterns, it might result in blending artifacts, as this image shows:

cellular_seamless.jpg

The variant on the left uses the blending scheme. 4 areas of 2D cellular noise are generated, then blended together to create the seamless pattern. At the edges, the pattern achieves a clarity that the center lacks, due to the center being a near-equal blend of 4 different noise sets, while the edges are more strongly weighted toward one of the 4 areas. Expanded out across a grid, the pattern becomes unmistakeable:

1wJ3lJw.png

The one on the right uses 4 dimensional noise and the clifford torus mapping to generate the seamless pattern, and while the curvature of the domain space is apparent in the curvy distortion of the shapes (in standard 2D cellular noise, these shapes are convex polygons with straight edges) the overall contrast of the pattern is preserved throughout the image, as is apparent when the image is tiled:

KcbQyP4.png


#5289965 How do I create tileable 3D Perlin/Simplex noise?

Posted by JTippetts on 03 May 2016 - 04:38 PM

If you don't need it to tile in 3 dimensions, then 5-D noise can do it. If you need it to tile in 3 dimensions, then 6 D will work.

I wrote a journal entry on this topic some time back: http://www.gamedev.net/blog/33/entry-2138456-seamless-noise/

If you don't want to use higher orders of noise, then you can use the blending method, or you can use lattice wrapping, such as one of the answers in that stackexchange thred suggest. Assuming your noise is a simple, vanilla Perlin or simplex fractal, and not anything more complex than that or including domain rotations.

The Accidental Noise Library ( https://github.com/JTippetts/accidental-noise-library ) uses the 6d method, if you care to check it out. The implementation of 3D noise mapping of various seamless modes is at https://github.com/JTippetts/accidental-noise-library

Note that the seamless method using higher orders of noise operates using some interesting domain transformation (a later poster to my journal called it a Clifford torus ( https://en.wikipedia.org/wiki/Clifford_torus ); you learn something new every day ) and so it can have consequences if you are, for example, using repeating patterns as part of your pipeline. For cloud noise it works well, but the domain transformation will skew any pattern functions beyond recognition.


#5289798 Creating the game world.

Posted by JTippetts on 02 May 2016 - 05:45 PM

Okay thanx for telling me how. But for real. Im only 14 so I have time, i dont see why we shouldn't shoot for perfect. We have time. I want to figure out how to join the process to make this a more real goa because i think once we can replicate every speck of dust i most certainly think we will be able to hack into the brain at that point. Let me pitch one more way and tell me if it is at all different from what i have been saying. I want a machine that can copy evolution of everything from the beggining of that universe. Now of course it would neeed too much processing power but by computer magic i meant the concept of magic. Instead of each cell going through every process magic can replace stuff to make stuff faster. Then a magical game would be able to use that world.


a) You don't have as much time as you think you do.
b) It's difficult to perfectly simulate something that you have an imperfect understanding of. The reason scientists are still digging in the dirt and smashing particles together underground is because they still do not yet fully understand the universe, the evolution of things, or the essence of the most basic processes that drive everything we see. All that stuff you want to simulate, you have to have the math for it, and right now our models are imperfect at best.
c) If you want to simulate all the atoms in the universe, you would need enough storage to store information about all the atoms in the universe. Technically, that's impossible. You would need more atoms than are in existence to provide the computational framework.
d) If dust simulations are your thing, you could certainly model a fairly realistic simulation on a smaller scale. Can't say how interesting it would be, but you could definitely do it.
e) They're already hacking the brain.
f) Magic is not a magical answer to magically doing anything.
g) There is a philosophical theory that posits that we ARE a simulation. Theoretically, if you could simulate the behavior of each and every particle and sub-atomic particle, using a consistent set of math, you could do it one instruction at a time and though a single "frame" of universe time, for you subjectively, might take a thousand thousand thousand years, for the entities being modeled, it would be the tiniest increment of time. It's a fairly windy theory, suitable mostly for alcohol- or drug-fueled navelgazing at best, imo, and to the people outside of the simulation (assuming they live long enough to see any significant chunk of it) it's probably not all that interesting most of the time.


#5288989 directx volume terrain

Posted by JTippetts on 27 April 2016 - 02:45 PM

Wow, nice idea.  Maybe i dont have to recalculate all triangles but I still have to create dynamic buffer for each chunk :/


Probably, yes.
 

And I need to store a lot of volume data. What is the best way to increse speed? Binary files?


Well, binary files are usually more quickly loaded than text files, yes. Other than that, you'll need to profile to find where your bottlenecks are, and try to apply optimizations as needed.


#5288958 directx volume terrain

Posted by JTippetts on 27 April 2016 - 12:45 PM

You will need to recalculate triangles only when a value is changed. You can also reduce the amount of recalculation that is performed by splitting your volume up into 'chunks', where each chunk is some arbitrary dimension of cells, and running marching cubes on a per-chunk basis. Then you only need to regenerate the chunks that are actually affected by the edit, rather than the entire landscape mesh.


#5288917 directx volume terrain

Posted by JTippetts on 27 April 2016 - 08:54 AM

If you store your terrain as a 3D grid of values, then you can edit the terrain by changing the value stored at a particular location. You can generate your mesh using marching cubes, using the 3D grid as the density function. Each cell of the 3D grid would be interpreted as a corner point for a set of cubes. Editing operations could be either binary (set a particular array location to either 1 or 0) or smooth (add or subtract a small increment). Smooth editing would result in smoother mesh generation.

As for isolevel, you just pretty much determine what you want that to be when you start. Set it at, say, 0.5 and then you don't usually change that again. That's simply the arbitrarily-chosen value of where you locate your iso surface.


#5288785 directx volume terrain

Posted by JTippetts on 26 April 2016 - 12:09 PM

Yes and I read http://paulbourke.net/geometry/polygonise/
 
but I cant imagine how it exacly works :/
 
Any examples in directx?
 
Marching cube is this black cube on video, but what is isosurface?


The black cube in the video is not "marching cube". That's just the guy's editing cursor, a visual marker to show the location he's looking at to edit.

Marching cube is an algorithm, or set of steps, that can convert a density field function to a mesh.

An isosurface can be described as the set of all points where the density function is equal to some value, this value being the "isolevel".

To start with, you need to understand that your volume terrain is going to basically be a mathematical function that for some input (x,y,z) will return a value, or density, at that location. This output value is typically a floating point value in the range of 0 to 1. So any given coordinate location within the bounds of your world or level will have a corresponding density value. The iso-level parameter determines where the boundary between "solid" and "open" lies. If you set iso-level to 0.5, then any (x,y,z) location whose density value is less than or equal to 0.5 is considered "solid", while everywhere else is considered open.

The tricky part in this type of thing is generating a mesh that follows the iso-surface of the density function at the threshold of iso-level. The Marching Cubes algorithm is one such technique. It operates by splitting the volume up into discrete cubical cells, and evaluating the density function at each corner of each cell. Cells where some of the points are "solid" and others are "open" are considered to be parts of the iso-surface, and the algorithm will generate a small bit of mesh geometry for this cell, representing a divide between the solid and open cells. Once all surface cells are evaluated, the resulting pieces of geometry are consolidated to form the surface mesh of the volume.

The term "marching cubes" comes from the mental metaphor of cubes "marching" across the surface of the volume, since an optimization in the algorithm includes starting at a known surface cell and recursing out to neighbors of that cell that are ALSO surface cells.


#5287328 Trying to understand normalize() and tex2D() with normal maps

Posted by JTippetts on 17 April 2016 - 11:33 AM

why is ( 0, 0.7071, 0 ) not unit length? Is it because this value is < 1?[/size]

Linearly interpolating unit-length vectors (which is what the pixel color interpolation is doing) rarely results in a unit-length vector. Consider the following image:

8fUkAyi.png

Say you have the normals Green and Blue, and you want to interpret the normal halfway between them. Linearly interpolating them will result in the portion of the cyan vector that ends at the white line, since linear interpolation will interpolate the values along the white line between the endpoints of the two vectors. In order to obtain a unit-length vector, you have to re-normalize it, which will restore it to the full unit-length it needs to be for proper lighting calculation.


#5287248 Trying to understand normalize() and tex2D() with normal maps

Posted by JTippetts on 16 April 2016 - 08:20 PM

tex2D(NormalSampler, input.mUV) samples a color from the normal map texture. The NormalSampler is a sampler associated with the texture, the provides the sampling state. input.mUV provide the texture coordinates to sample from.

A normal stored in a normal map must be "decoded" before it can be used. R and G channels encode the X and Y values of the normal (tangent to the face) while the blue channel encodes the Z value, and is typically simply set to the same value (255) for all values for simplicity, hence the nice cool blue color of a normal map texture.
A color channel holds values from 0 to 1, but the X and Y components of the normal can be values from -1 to 1, hence the need to decode. Inside the call to normalize, the normal sample is multiplied by 2, then 1 is subtracted from it. This has the effect of converting the R and G channels from the range 0,1 to -1,1.

Since most normalmap generation software uses a constant color for the blue channel, the resulting vector is not of unit length. A proper normal needs to be unit length (meaning that sqrt(x^2 + y^2 + z^2) = 1) That is what normalize() does: it takes a vector of arbitrary length and converts it to a vector of unit length.


#5286344 Game concept

Posted by JTippetts on 11 April 2016 - 12:49 PM

Wait, wait, let me guess.

Shooter McGuy is a grizzled veteran of the Ubiquitous Space Marines, Shooting Division. Aliens have invaded! Shooter must don his space suit and do what he does best in order to save the galaxy. After years in retirement he must attempt to match up at least 3 of the same color of gem in a row, in order to destroy those gems and make room for the ever-falling cascade of gems from above. He can destroy special gems in order to gain access to combos and score additional points.

No, wait. I think it's more like this: Blink is a young boy from the far-off mystical land of Spherule. One day, his uncle gives him a sword and, with his dying breath, pulls the young boy closer and says, "Blink. You must go forth and save the land. You can do so by collecting cards that grant your units powerful attacks and spells, but you can only move 12 times per day. But Blink, there is a secret! If you pull up the Shop screen, and enter your dad's credit card number, you can purchase Droopies that allow you to extend your daily turn limit beyond 12. Blink, to save the kingdom, you NEED MORE DROOPIES!."

Although, when I see the road with the fence, I think it might be more like: Cleve is a miner, lost in a hostile world of block-shaped chunks of stone and dirt, cows made out of cubes, and a layer of burning hot lava lurking deep below. In order to survive, Cleve must delve and craft. And craft, and craft some more. He must grind 4000 linen bandages, gathering the cloth from an unending supply of mobs haunting the Cubic Castle ruins. He must gather 36 piles of steaming spider guts to make Red-rash Goulash. And if he raises his Tailoring skill high enough, he can even craft a frozen-weave burlap sack of glamour to wear on raids.


#5286093 Event-Listener with Lua and C++

Posted by JTippetts on 09 April 2016 - 11:05 PM

For an interesting take on how one project has integrated Lua and C++, I suggest you take a look at Urho3D. Urho3D provides a component-based framework with event passing, and provides a structure such that a component can be added to an object that wraps a Lua object. The component handles the sending and receiving of events, and the Lua script code can subscribe to listen for events or send events as needed. It's quite an elegant system, but the underpinnings of it is a little complex. The github repo is here, you can navigate to the Source/Urho3D/LuaScript folder to get a peek at how scripting is done.

As an example from my own game, I have a Lua class called FloatingCombatText. This is a class implemented in Lua, which subscribes to listen for certain events, such as Damage Taken, Low Life, etc... events that happen to an object during the course of combat. In response to the events it is listening for, it will create floating combat text objects and queue them to a list, and these objects are then displayed as numbers or alerts animating above the entity's head. Simply by adding this script object component to any combat-enabled object, that object then will display floating combat text. A truncated version of the FloatingCombatText code:
 
FloatingCombatText=ScriptObject()

function FloatingCombatText:Start()
	self:SubscribeToEvent("AlertAll", "FloatingCombatText:HandleAlert")
	self:SubscribeToEvent("Update", "FloatingCombatText:HandleUpdate")
	self:SubscribeToEvent(self.node, "AddResources", "FloatingCombatText:HandleAddResources")
	self:SubscribeToEvent(self.node, "SpendResources", "FloatingCombatText:HandleSpendResources")
	self:SubscribeToEvent(self.node, "DamageTaken", "FloatingCombatText:HandleDamageTaken")
	self:SubscribeToEvent(self.node, "HealingTaken", "FloatingCombatText:HandleHealingTaken")
	self:SubscribeToEvent(self.node, "LifeLow", "FloatingCombatText:HandleLifeLow")
	self:SubscribeToEvent(self.node, "PrepareToDie", "FloatingCombatText:HandlePrepareToDie")
	self.offsetheight=1
	self.timetoupdate=0
	self.updaterate=0.25
	self.velocity=2
	self.ttl=1
	self.list=LinkedList()
end

function FloatingCombatText:HandleLifeLow(eventType, eventData)
	self.list:push_back({text="Life low!!", color={r=1,g=0,b=0}})
end

function FloatingCombatText:HandlePrepareToDie(eventType, eventData)
	self.list:push_back({text="Dying!!!", color={r=1,g=1,b=0}})
end

function FloatingCombatText:HandleDamageTaken(eventType, eventData)
	local total=eventData["total"]:Get()
	if total>0 then
		self.list:push_back({text=tostring(total), color={r=1,g=0.15, b=0.15}})
	end
end

function FloatingCombatText:HandleHealingTaken(eventType, eventData)
	local total=eventData["healing"]:Get()
	if total>0 then
		self.list:push_back({text=tostring(total), color={r=0.15,g=0.15, b=1}})
	end
end
The Urho3D framework provides ScriptObject as a base 'class' from which all script classes inherit. The Start method is called when the object is created, and it subscribes to the various events from its owning node (to distinguish from events originating with another node.)

The Urho3D framework provides the ability to work with Lua how you see fit. You can write the majority of your game in C++, implementing only certain scriptable components in Lua, or you can implement the entirety of your game code in Lua, using the bound API to implement scriptable components as well as base game logic.

Sorry for the pimping post, it's just that I really do look at Urho3D as an interesting and elegant way in which Lua can be bound to your framework, going beyond the simple call-for-call API binding you typically see.




PARTNERS