How to get the *exact* liquid flowing direction?

Post Reply
User avatar
Wuzzy
Member
Posts: 4803
Joined: Mon Sep 24, 2012 15:01
GitHub: Wuzzy2
IRC: Wuzzy
In-game: Wuzzy
Contact:

How to get the *exact* liquid flowing direction?

by Wuzzy » Post

Is there any easy/standard (!) way to get the flowing direction of a flowing liquid node? And how do I get it?
If you look on a flowing liquid like water, you notice a flowing animation. This flowing animation has a direction. What I want is this dircection of the animation.

Ideally I wish I could get the direction as an unit vector (x,y,z).

My current code basically just hacks around the fact that I haven't found a clean standard way yet. It only is able to distinguish between the 4 cardinal directions, it doesn't recognize it if the liquid flows diagonally.

This is the code which is supposed to do this (return value is an unit vector, possible are the 4 cardinal directions only):

Code: Select all

			local get_flowing_dir = function(self)
				local pos = self.object:getpos()
				local param2 = minetest.get_node(pos).param2
				-- Search for a liquid source, or a flowing liquid node higher than
				-- the item's position in the 4 cardinal directions
				local posses = {
					{x=-1, y=0, z=0},
					{x=1, y=0, z=0},
					{x=0, y=0, z=-1},
					{x=0, y=0, z=1},
				}
				for _, p in pairs(posses) do
					local realpos = vector.add(pos, p)
					local name = minetest.get_node(realpos).name
					local def = minetest.registered_nodes[name]
					local par2 = minetest.get_node(realpos).param2
					if def.liquidtype == "source" or (def.liquidtype == "flowing" and par2 > param2) then
						-- Node found! Since we looked upwards, the flowing
						-- direction is the *opposite* of what we've found
						return vector.multiply(p, -1)
					end
				end
			end
http://repo.or.cz/MineClone/MineClone2. ... t.lua#l376

If someone knows a standard way to get the flowing direction, that would be great, as I could get rid of some code.

User avatar
stu
Member
Posts: 923
Joined: Sat Feb 02, 2013 02:51
GitHub: stujones11
Location: United Kingdom

Re: How to get the *exact* liquid flowing direction?

by stu » Post

I am not sure if this will help but it's the closest thing i've seen. Unfortunately the videos are no longer available. viewtopic.php?f=9&t=12442

User avatar
qwertymine3
Member
Posts: 202
Joined: Wed Jun 03, 2015 14:33
GitHub: Qwertymine
In-game: qwertymine3

Re: How to get the *exact* liquid flowing direction?

by qwertymine3 » Post

stu wrote:I am not sure if this will help but it's the closest thing i've seen. Unfortunately the videos are no longer available. viewtopic.php?f=9&t=12442
I made improvements to that mod to make my first mod - in the process I re-wrote the flow direction code to be clearer and only need 5 nodes to determine the direction (all 16 directions). The flow is the logical one - sometimes the way minetest renders liquid flow is different - but is logically incorrect (e.g. minetest renders a sideways flow between two source nodes, rather than it being still). Code is WTFPL.
https://github.com/Qwertymine/water_phy ... t.lua#L102.
TenPlus1 has this code in his version of the builtin_item mod - which may or may not be better maintained than my original code. This code is MIT.
https://github.com/tenplus1/builtin_ite ... r/init.lua
Avatar by :devnko-ennekappao:

User avatar
Wuzzy
Member
Posts: 4803
Joined: Mon Sep 24, 2012 15:01
GitHub: Wuzzy2
IRC: Wuzzy
In-game: Wuzzy
Contact:

Re: How to get the *exact* liquid flowing direction?

by Wuzzy » Post

qwertymine3: Does quick_flow give me the liquid flow direction which corresponds exactly to the liquid appearance, or it it just an estimate?

Anyway, I think if it is able to support 16 directions, this is already much better than my current code which only supports 4 directions. Thank you. :-)

I wish some “liquid flow direction” code would be added straight into Minetest's builtin because I think this is a pretty useful utility function, there are many reasons why one wants to know the liquid flow direction. It would also be more standard.

User avatar
qwertymine3
Member
Posts: 202
Joined: Wed Jun 03, 2015 14:33
GitHub: Qwertymine
In-game: qwertymine3

Re: How to get the *exact* liquid flowing direction?

by qwertymine3 » Post

It is almost accurate, but not completely. There are some parts of the rendering which are directional behaviours, and
make no sense as the actual direction of the liquid flow - e.g.

Code: Select all

S - source
X - flowing

SXS
The engine will always render the flowing liquid as flowing towards +X (as it doesn't have a still image to use for the flowing node). My mod will always say that the flowing liquid is still.

Also my mod treats liquids flowing into vertical colomns of liquid differently to the engine - the engine renders the final liquid node of the stream as flowing away from the colomn, while this mod says that the liquid is flowing into the vertical colomn. (you may remove this when fixing my mod though - making it more accurate). e.g

Code: Select all

y   S
|   X
|   X v
|   X X X X S
|   X

The flow at v would be rendered as >, my mod returns <. This is the direction which I think makes more sense, and made the mod I was making with it more fun. This can't be done in general for all liquid_ranges though - so the code will have to be changed to make it more like the way it is rendered. (See below)
That said - I wrote this code quite a long time ago, and it was before river sources were added - so I don't think that the code is designed to handle anything other than liquid range 7, so it may not be adequate for your use in it's current form.
The code which is affected are lines 91 and 85 - which (I think) determine whether the stream is flowing into a vertical colomn which should not affect it (although the engine thinks it does - see above).

Just remove the if branch of these to conditionals and leave the else branch, and that should make the flow direction more accurate to minetest and not reliant on the liquid_range.

After this I think the only difference to minetest will be the as stated in the first example.
Avatar by :devnko-ennekappao:

User avatar
Wuzzy
Member
Posts: 4803
Joined: Mon Sep 24, 2012 15:01
GitHub: Wuzzy2
IRC: Wuzzy
In-game: Wuzzy
Contact:

Re: How to get the *exact* liquid flowing direction?

by Wuzzy » Post

Awesome! This flowlib looks like it is exactly what I needed.
For MineClone 2, I needed to know the flowing direction so I can make items flow around on water.
Luckily, the only liquid I need to care about here is water, which has a flowing distance of 7. :-)

It works pretty good already! I actually was able to include flowlib and call flowlib.quick_flow in my item entity code to get the direction. Now dropped items flow on water around in a much more precise manner. Great!

If the flowing of the items does not 100% match the graphics, this is probably okay for my purposes. Item flowing is not perfect yet, so I still have to do some work here on my own. But it was an important step nonetheless.

If you should ever improve your flowlib in future, please let me know.

Some comments about flowlib itself:
Please document the API functions (a short explanation of purpose, return value and parameters is enough).
And a hint: You don't need to_unit_vector. You can replace it with vector.normalize, this function is in the Lua API and apparently it does exactly the same thing.

User avatar
qwertymine3
Member
Posts: 202
Joined: Wed Jun 03, 2015 14:33
GitHub: Qwertymine
In-game: qwertymine3

Re: How to get the *exact* liquid flowing direction?

by qwertymine3 » Post

Wuzzy wrote: Some comments about flowlib itself:
Please document the API functions (a short explanation of purpose, return value and parameters is enough).
Tell me from 2 years ago that API documentaion is a good idea ; ).
I'll probably do so if I get around to re-working my boat_test mod. Works quite well singleplayer, but is a glitchy mess on servers.
Currrently working on a few other mods, so this may take a while.
Wuzzy wrote: And a hint: You don't need to_unit_vector. You can replace it with vector.normalize, this function is in the Lua API and apparently it does exactly the same thing.
Pointless micro-optimisation indeed. That said, I'll try to profile it to see if my inexperienced self was onto something (before almost certainly removing it).
Avatar by :devnko-ennekappao:

neoh4x0r
Member
Posts: 82
Joined: Wed Aug 29, 2018 20:16
GitHub: neoh4x0r

Re: How to get the *exact* liquid flowing direction?

by neoh4x0r » Post

qwertymine3 wrote:
Wuzzy wrote: Some comments about flowlib itself:
Please document the API functions (a short explanation of purpose, return value and parameters is enough).
Tell me from 2 years ago that API documentaion is a good idea ; ).
I'll probably do so if I get around to re-working my boat_test mod. Works quite well singleplayer, but is a glitchy mess on servers.
Currrently working on a few other mods, so this may take a while.
Wuzzy wrote: And a hint: You don't need to_unit_vector. You can replace it with vector.normalize, this function is in the Lua API and apparently it does exactly the same thing.
Pointless micro-optimisation indeed. That said, I'll try to profile it to see if my inexperienced self was onto something (before almost certainly removing it).
Actually, the function to_unit_vector, is ...well... a lie.

It is not actually returning a unit vector, but, rather a scaled vector in a given direction.

A unit vector is vector where each component has been divided by the length of the vector -- in other words, the components are converted into percentage ratios.

EG (1,2,3) : len=sqrt(x^2+y^2+z^2)=sqrt(1+4+9)=sqrt(14)=3.74165
||(1,2,3)|| = (1/3.74, 2/3.74,3/3.74) = ~ (0.267, 0.535, 0.802)

That being said, it seems that inv_roots is being used a constant scalar and selected by x^2+z^2 (noting that x and z are left/right, forward/backward (ie 2-d).

EG: when you have a direction vector (which must be normalized to work) and then multiple it by a scalar -- you are actually generating a point that lies on a line in the given direction.
That is the vector equation of a line is: point = origin + scale * direction ; y = b+ mx

As I stated, to_unit_vector does not really describe what this function actually does, because it isn't generating a normalized unit vector -- and as such it cannot be replaced with vector.normalize.

Code: Select all

--sum of direction vectors must match an array index
local function to_unit_vector(dir_vector)
	--(sum,root)
	-- (0,1), (1,1+0=1), (2,1+1=2), (3,1+2^2=5), (4,2^2+2^2=8)
	local inv_roots = {[0] = 1, [1] = 1, [2] = 0.70710678118655, [4] = 0.5
		, [5] = 0.44721359549996, [8] = 0.35355339059327}
	local sum = dir_vector.x*dir_vector.x + dir_vector.z*dir_vector.z
	return {x=dir_vector.x*inv_roots[sum],y=dir_vector.y
		,z=dir_vector.z*inv_roots[sum]}
end

function vector.normalize(v)
	local len = vector.length(v)
	if len == 0 then
		return {x=0, y=0, z=0}
	else
		return vector.divide(v, len)
	end
end

Post Reply

Who is online

Users browsing this forum: No registered users and 8 guests