Jump to content
Eternal Lands Official Forums
Entropy

Special effects

Recommended Posts

Latest patch committed:

* Some potential fixes for obstructions that may potentially fix the valgrind errors. Unfortunately, valgrinding EL is just too taxing for my laptop, so I can't be sure.

Great, the messages referring to eye candy code are gone. It's taxing for my poor machine too, I get disconnected often. But it looks like its helping catch a few issues so I'm happy to try. :dry:

Share this post


Link to post
Share on other sites

Indeed indeed. Those things could have been potential crashes, given the right circumstances -- who knows?

 

While I haven't had much coding help (with the exception of Lachesis's recent work and some occasional bugfixes), I've had some great testers like you, and that's really helped speed things along. Thanks!

Share this post


Link to post
Share on other sites

Hmm I did it the outside way and I also fell back to non-eye-candy-sfx, but that may be nonsense, since the user might want to disable SFX entirely using that option. I chose the method outside the ec_* functions because that's the way it's also done with the other functions. It's more "visible" that way that the code is conditionally exectued, but of course it's also more repeated code. Additionally, it's much less error-prone putting it into eye_candy_wrapper.c, and it's also easier to get an overview what is still called if eye candy is disabled. Since you're opting for that method I think I'll reroll the code, branching inside eye_candy_wrapper.

 

About the recalling problem: do you have any documentation what that mechanism actually does? I don't understand what you mean by "recalling", why it is necessary and when it needs to be ensured.

Edited by Lachesis

Share this post


Link to post
Share on other sites

If I compile the client with eye candy I have the following problem:

Once I execute the binary (el.exe on Win XP SP2) I see the loading screen for about 1 second, then the client just closes without an error message (no entries in error_log.txt).

 

However if I compile it without eye candy everything works fine.

 

I'm not sure if this problem is actually eye_candy related or some .dll/library problem. Has anyone had the same experience?

Edited by kl4Uz

Share this post


Link to post
Share on other sites

You are probably missing some necessary files. Make sure el.ini is in the working directory, and data_dir points to the correct location of the EL data files. Also make sure syou installed the additional eye candy textures under textures/eye_candy/ in that location.

Share this post


Link to post
Share on other sites

You are probably missing some necessary files. Make sure el.ini is in the working directory, and data_dir points to the correct location of the EL data files. Also make sure syou installed the additional eye candy textures under textures/eye_candy/ in that location.

A missing texture should be logged in the error file, and probably not close the client. At a minimum that should be looked. If not, the eye_candy system needs to be enhanced to be more robust so we don't have puzzled players once it goes live.

Share this post


Link to post
Share on other sites

Lachesis:

 

There is some info in the old docs (which I'll probably move over to doxygen and expand within the next week). Basically, if you look at the wrapper, you'll find a couple things of interest:

 

* The wrapper *never* directly deletes effects. This is because the core controlling object, EyeCandy, does it. Whenever an effect's idle function is run, it will return "true" (keep on going) or "false" (I'm done; delete me). This way, an effect is never deleted while there are still particles that refer to it. If we just deleted the effect, everything that pointed to that effect would become dangling pointers, which would be asking for a crash. Also, when an effect that only lasts for a short period of time (say, picking up a bag) finishes, this method allows the effect to order itself to be deleted simply by returning false.

 

* Instead of simply deleting an effect, when it is no longer wanted we set its "recall" flag on the effect to be true. Every effect and every particle is responsible for looking at that recall flag. If it's set, whether or not the effect thinks it *should* be done, it starts killing itself off. All particles' idle functions return false (like with the effects' idle function, this means "I am ready to be deleted"), and when all of its particles are gone, the effect's idle function will return false as well, causing itself to be deleted.

 

* Now, given that the EyeCandy object deletes the effect, how can the wrapper know that this has happened? This is why I added the "dead" flag. Effects take a pointer to this dead flag. Whenever the EyeCandy object deletes an effect, it first flags that effect's dead flag as "true". Now, before the wrapper touches any effect, it first checks to see if it's dead. If it is dead, it frees its reference to that effect and deletes it from the list.

 

Does that make sense to you?

 

Learner:

 

Indeed, it should be logged. I'll put that on my TODO list; thanks. It currently just gives a message on stderr, which I imagine wouldn't help a Windows user. Just as a note, shouldn't have puzzled players when it goes live because the textures (and the whole data dir) will be updated as well.

Share this post


Link to post
Share on other sites
Indeed, it should be logged. I'll put that on my TODO list; thanks. It currently just gives a message on stderr, which I imagine wouldn't help a Windows user.
I'm not certain if it's the same info as what's normally printed when effects are added/removed, if not ignore it, but... try to make it as clear as possible to the user (the pointer address, for example, will scare some people). there are macros used for error logging, to call functions, as long as you include the header files it should be simple to convert
Just as a note, shouldn't have puzzled players when it goes live because the textures (and the whole data dir) will be updated as well.
tsk tsk, you should know people will mess it up :lipssealed: there have been a few cases where needed files have gone missing from people's installs for whatever reason, and I don't doubt it'll happen again :hiya:

other than that, happy bug-hunting, and looking forward to seeing what you come up with after the client update :ph34r:

Share this post


Link to post
Share on other sites

You are probably missing some necessary files. Make sure el.ini is in the working directory, and data_dir points to the correct location of the EL data files. Also make sure syou installed the additional eye candy textures under textures/eye_candy/ in that location.

 

Actually I have all the required textures and the el.ini. I checked all .dll files again and as Windows doesn't complain about missing ones, they should be the right ones.

 

As I said, without eye_candy the client works. With eye_candy it closes after about a second.

Share this post


Link to post
Share on other sites

Let's just verify: if you look in the directory:

 

WhateverYourELDirectoryIs\textures\eye_candy\

 

You see:

 

128x128, 16x16, 32x32, and 64x64

 

Right? And inside each of them, there's a bunch of PNG files, right?

 

If that's not the case, stop right there and remedy the situation. :lipssealed: If that is the case, can you get me a stack trace from when the program crashes?

Share this post


Link to post
Share on other sites

Learner:

 

Indeed, it should be logged. I'll put that on my TODO list; thanks. It currently just gives a message on stderr, which I imagine wouldn't help a Windows user. Just as a note, shouldn't have puzzled players when it goes live because the textures (and the whole data dir) will be updated as well.

We can never assume they have all the files even if we put it in the distribution is all I'm trying to point out. You haven't seen how many times a month either in game or in the forums people have messed up clients and have to reinstall for replace files.

Share this post


Link to post
Share on other sites

Learner:

 

That is why I just said I'd do it :P I'm aware that peoples' distributions can get messed up. Also, it's not like I didn't have any error logging -- I just didn't have as robust error logging as would be desired. This code was written before integration (i.e., when I didn't have access to EL's logger), and (as I've stated dozens of times), my only testing platform is Linux, so I always see stderr.

 

I was just stating that in the general case, this wouldn't be a significant problem. Not only would everyone except those who mess things up have the textures, but anyone who could see stderr would have seen the error message.

Edited by KarenRei

Share this post


Link to post
Share on other sites

Yes thanks Karen, that's exactly the info I needed. Learner: I talked to kl4Uz and the client really closes, it doesn't seem to be a real crash. He told me he had all the textures. May it be due to the fact that the eye candy textures are in subdirectories and slashes are not properly converted to backslashes for windows?

 

P.S. kl4Uz will be abroad next week so we may need to defer this problem if we can't spot its origin.

Edited by Lachesis

Share this post


Link to post
Share on other sites

was digging silver in MM caves when this happened (current CVS. but it happened yesterday as well, but I only got a simple backtrace, which is only enough that I know it was the same function)

<snip>
ImpactEffect (0x7cdb5b0) destroyed.
ImpactEffect (0x7b2a540) destroyed.
ImpactEffect (0x7cdb5b0) created.
ImpactEffect (0x7cdb5b0) destroyed.
ImpactEffect (0x7ba6110) created.
BagEffect (0x7b83b90) created.
BagEffect (0x7b83b90) destroyed.
ImpactEffect (0x7ba6110) destroyed.
BagEffect (0x8639a00) created.
BagEffect (0x8639a00) destroyed.
SelfMagicEffect (0x801b300) created.

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 47715039390928 (LWP 12483)]
0x00000000004f67d9 in ec::MathCache::powf_0_1_rough_close (this=0x821280, base=nan(0x400000), power=0.100000001)
at eye_candy/math_cache.cpp:2179
2179	  return (powf_map[index1][index2] * (1.0 - percent2)) + (powf_map[index1][index2 + 1] * percent2);
Current language:  auto; currently c++
(gdb) bt full
#0  0x00000000004f67d9 in ec::MathCache::powf_0_1_rough_close (this=0x821280, base=nan(0x400000),
power=0.100000001) at eye_candy/math_cache.cpp:2179
	index1 = -2147483648
	percent2 = 0.600000024
	index2 = 28
#1  0x00000000004db08e in ec::Particle::flare (this=0x7578ca0) at eye_candy/eye_candy.cpp:700
	offset = 123178196
	flare_val = 1.07812536
	__PRETTY_FUNCTION__ = "virtual coord_t ec::Particle::flare() const"
#2  0x00000000004db94b in ec::Particle::draw (this=0x7578ca0, usec=36549) at eye_candy/eye_candy.cpp:658
	tempsize = 0.339803189
	texture = 0
#3  0x00000000004d9f84 in ec::EyeCandy::draw (this=0x820b20) at eye_candy/eye_candy.cpp:1404
	p = (class ec::Particle *) 0x7578ca0
	iter2 = {_M_node = 0x7578d40}
	e = (class ec::Effect *) 0x801b300
	iter = {_M_current = 0x87d4988}
#4  0x00000000004c7be1 in ec_draw () at eye_candy_wrapper.cpp:237
No locals.
#5  0x000000000044ad85 in display_game_handler (win=0x399ea70) at gamewin.c:691
	str = "�\223\003\000\000\000\000;e�204e+\000\000\002", '\0' <repeats 11 times>, "e+\000\000\000 \000@\000\000\000\000\000 \000@", '\0' <repeats 12 times>, "H�223\003\000\000\000\000\000 \000@\000\000\000\000�032\202e+\000\000\000 \000@\000\000\000\000=\204e+\000\000\000 \000@\000\000\000\000 U\000\000\000\000\000P\f)\177", '\0' <repeats 19 times>, " \000@\000\000\000\000\200\f)\000\000\000\000p�231\003\000\000\000\000\000 \000@\000\000\000\000=\000\000\000\000>"
	i = 1
---Type <return> to continue, or q <return> to quit---
	any_reflection = 0
	mouse_rate = 2
	main_count = 5815
	times_FPS_below_3 = 0
	fps = {26, 25, 26, 26, 26}
	shadows_were_disabled = 0
#6  0x000000000043de0a in draw_window (win=0x399ea70) at elwindows.c:1059
	ret_val = 0
	W = (widget_list *) 0x399d1b0
#7  0x000000000043e43a in display_window (win_id=0) at elwindows.c:1207
No locals.
#8  0x000000000043b6ea in display_windows (level=1) at elwindows.c:57
	id = -1
	next_id = -9999
	i = 0
#9  0x0000000000434ea7 in draw_scene () at draw_scene.c:101
No locals.
#10 0x0000000000464533 in start_rendering () at main.c:123
	event = {type = 24 '\030', active = {type = 24 '\030', gain = 81 'Q', state = 136 '\210'}, key = {
type = 24 '\030', which = 81 'Q', state = 136 '\210', keysym = {scancode = 2 '\002', sym = 2176124094,
  mod = 11109, unicode = 60992}}, motion = {type = 24 '\030', which = 81 'Q', state = 136 '\210', x = 2,
y = 0, xrel = 1214, yrel = -32331}, button = {type = 24 '\030', which = 81 'Q', button = 136 '\210',
state = 64 '@', x = 2, y = 0}, jaxis = {type = 24 '\030', which = 81 'Q', axis = 136 '\210', value = 2},
 jball = {type = 24 '\030', which = 81 'Q', ball = 136 '\210', xrel = 2, yrel = 0}, jhat = {type = 24 '\030',
which = 81 'Q', hat = 136 '\210', value = 64 '@'}, jbutton = {type = 24 '\030', which = 81 'Q',
button = 136 '\210', state = 64 '@'}, resize = {type = 24 '\030', w = 2, h = -2118843202}, expose = {
---Type <return> to continue, or q <return> to quit---
type = 24 '\030'}, quit = {type = 24 '\030'}, user = {type = 24 '\030', code = 2, data1 = 0x2b6581b504be,
data2 = 0x460cee40}, syswm = {type = 24 '\030', msg = 0x2b6581b504be}}
	network_thread = (SDL_Thread *) 0x75ff430
	message_queue = (queue_t *) 0x764ae40
	done = 0
	network_thread_data = {0x764ae40, 0x81ee20}
#11 0x0000000000464813 in main (argc=2, argv=0x7fff290ca758) at main.c:235
No locals.

Share this post


Link to post
Share on other sites

Apparently something went wrong when evaluating the formula in eye_candy.cpp:700 (it returned NAN) and the powf approximation isn't prepared for that.

Btw, it seems to me that you use sin(b*(x + y + z +a)) as a 3D noise function, is that correct? If so it may not work as intended, because it will be constant in all directions perpendicular to (1,1,1), that is all linear combinations of (1, 0, -1) and (0,1,-1). If you want a simple formula, you can avoid the linear constantness using a nonlinear combination of x, y, z, however, every smooth such function f will be constant over smooth (topologically) two-dimensional manifolds, given by the equations

 

f(x,y,z) = const.,

 

you can only tweak the complexity of their shape.

 

P.S. A popular simple and fast 3D/4D noise function is the perlin noise [1]. There's probably lots of ready-to-use implementations out there.

 

[1] http://mrl.nyu.edu/~perlin/noise/

Share this post


Link to post
Share on other sites

Ttlanhil: Now that's what I call a stacktrace! I love the inclusion of local variables. :D Too bad it only includes local ones, though. Class member variables are more important here.

 

Lachesis: Indeed, the pow cache doesn't know how to handle NaN. In fact, it's only valid when the base is between 0 and 1 (hence the 0_1 in the function name). Indeed, the sin is for a 3d noise function. That Perlin noise function looks pretty CPU intensive, though -- branch statements, countless floating point multiplies and adds, etc. I'm certainly not opposed to giving a better noise function, but not at the cost of more CPU usage; it already looks pretty good since I factor the particle's memory address in there. Do you know of any faster ones?

 

The bug: The only option that seems plausible here is that the argument to sin produces NaN. sin(inf)? Just checking... yes, that seems to be the case. So, it seems we're looking at a flare frequency of zero, most likely. But this would make no sense -- I had put an assert statement at the top of the function specifically to make that impossible to happen in debug mode without catching it, and I've never had that assert statement fire (and apparently, neither did you). We know what offset is (thanks to the detailed stack trace), and that's fine. So, if it's not offset or flare_frequency, it seems it would have to be pos -- but how a particle would get an imaginary position, that's hard to say without more debugging info.

 

What effect was running? Hmm, I shut the debugging statements that listed what effects were going off since we're getting ready for release, but I was probably too hasty. We should probably leave those on, right up until release. We could verify the Inf or NaN particle position theory by adding in an assert statement. How reproducible is this? Possible info that would be useful if pos was Inf or NaN: Is velocity Inf or NaN? What mover was the particle created with (depends on what effect was spawned, and sometimes what subcategory of effect)? If this was a harvesting effect (seems most likely, given what you were doing, no?), its mover would either be a basic particle mover (no acceleration -- very doubtful the problem), a spiral mover, or a gravity mover. We could trace it back from there.

 

Slashes: I don't know, will SDL image loading on windows fail out if the slashes are in the wrong direction? I didn't even think of that possibility. Could some windows user verify this?

Edited by KarenRei

Share this post


Link to post
Share on other sites

as far as slashes are concerned... windows' libs generally don't care which direction they go. it matters in a shell, but not when using calls like open() or chdir() (there are examples of this in the code)

I guess they wanted to be different, but knew that being different could annoy a lot of people so left the functionality for *nix-style path seperators

Share this post


Link to post
Share on other sites

Perlin noise is about the fastest (real) noise function out there, particularily because it can be implemented using shaders. Most of the multiplications can be reduced to additions and subtractions, too (because one factor is a small integer number). I's basicly just interpolating between precalculated random gradients. Some speed can be gained by using a third- instead of a fifth-degree polynomial for interpolation. Some multiplications cannot be avoided because with additions & subtractions you only get linear combinations. If you look for something simpler, you could try using a nonlinear function on each of the coordinates, and combine them afterwards, which can already give fairly complex results with some fiddling. Here's something I got by a little experimenting, not sure whether it's faster than perlin, though:

 

simplenoise.png

 

Note the relatively complex shape and arrangement of the isolevel contours at the bottom. The formula is

 

sin(x + cos(y)) + sin(y + cos(x))

It's relatively easy to extend this formula to 3D, but I cant plot a 3D version in gnuplot :laugh: For comparison, here's your current noise function:

 

linearnoise.png

Edited by Lachesis

Share this post


Link to post
Share on other sites

That's only kind of the 3d function for the current one. The key which makes the current one look nice is that each particle is out of phase with the others. The point of flare() is to make particles flash or swell in different ways. When they all do it at different places, it tricks your eyes; your eyes have trouble keeping track of a single particle in order to notice that it's pattern isn't that great. Your formula uses four times the sines, and I don't think that would be fast enough. This code gets run for every particle, every idle cycle, so I can't afford for it to be slow. Does that make sense?

 

If you had a version that didn't use conditionals, didn't use any sines, and used less than a dozen pieces of floating point math, then it would probably be faster than the current version. But I can't imagine what sort of noise function would work well with so few ops.

Edited by KarenRei

Share this post


Link to post
Share on other sites

Check out CVS tonight and gave it a shot, but this time I can't even get it to compile:

 

 

g++ -march=i686 -Wall -O0 -ggdb -pipe -DLINUX -DELC -DAFK_FIX -DAUTO_UPDATE -DBUG_FIX_3D_OBJECTS_MIN_MAX -DCOUNTERS -DCUSTOM_LOOK -DCUSTOM_UPDATE -DDEBUG -DEXTRA_DEBUG -D_EXTRA_SOUND_DEBUG -DEYE_CANDY -DFONTS_FIX -DMEMORY_DEBUG -DMUTEX_DEBUG -DNEW_ACTOR_ANIMATION -DNEW_FRUSTUM -DNEW_TEX -DNOTEPAD -DOPTIONS_I18N -DPNG_SCREENSHOT -DSFX -DSIMPLE_LOD -DUSE_INLINE -I/usr/include/SDL -D_REENTRANT -I/usr/include/libxml2 -fno-strict-aliasing -c -o eye_candy_wrapper.o eye_candy_wrapper.cpp

In file included from global.h:190,

from eye_candy_wrapper.h:17,

from eye_candy_wrapper.cpp:3:

bbox_tree.h: In function `unsigned int is_blend_3d_object(unsigned int)':

bbox_tree.h:394: error: invalid conversion from `const char*' to `const Uint8*'

bbox_tree.h:394: error: invalid conversion from `const char*' to `const Uint8*'

bbox_tree.h:394: error: invalid conversion from `const char*' to `const Uint8*'

bbox_tree.h: In function `unsigned int is_ground_3d_object(unsigned int)':

bbox_tree.h:422: error: invalid conversion from `const char*' to `const Uint8*'

bbox_tree.h:422: error: invalid conversion from `const char*' to `const Uint8*'

bbox_tree.h:422: error: invalid conversion from `const char*' to `const Uint8*'

bbox_tree.h: In function `unsigned int is_alpha_3d_object(unsigned int)':

bbox_tree.h:450: error: invalid conversion from `const char*' to `const Uint8*'

bbox_tree.h:450: error: invalid conversion from `const char*' to `const Uint8*'

bbox_tree.h:450: error: invalid conversion from `const char*' to `const Uint8*'

bbox_tree.h: In function `unsigned int is_self_lit_3d_object(unsigned int)':

bbox_tree.h:478: error: invalid conversion from `const char*' to `const Uint8*'

bbox_tree.h:478: error: invalid conversion from `const char*' to `const Uint8*'

bbox_tree.h:478: error: invalid conversion from `const char*' to `const Uint8*'

bbox_tree.h: In function `unsigned int get_type_mask_from_type(unsigned int)':

bbox_tree.h:536: error: invalid conversion from `const char*' to `const Uint8*'

bbox_tree.h:536: error: invalid conversion from `const char*' to `const Uint8*'

bbox_tree.h:536: error: invalid conversion from `const char*' to `const Uint8*'

make: *** [eye_candy_wrapper.o] Error 1

Share this post


Link to post
Share on other sites

If it makes you feel any better, whoever changed what, it broke things for me, too (in a different way -- it wasn't building minimap, but was calling functions from it. Also, minimap.h was breaking a cardinal rule and was creating a non-static/const global variable inside a .h ).

 

Your error is because, for some reason, your client doesn't have _MSC_VER defined. Consequently, it's using LOG_ERROR_DETAILED, which expects a uint8* instead of a char*. Try defining _MSC_VER. I'll be checking in a fix for the minimap issues shortly.

Share this post


Link to post
Share on other sites

I'm not sure if you want this here, or in another thread, but the neat sword effects are at peculiar angles for me.

swordsrf3.jpg

I know you had to compromise because figuring where the sword ends is tricky. Fixing this is not a big deal and I understand you have a lot on your plate right now. I just thought I'd mention it. system specs: gcc 3.4.5 mingw special, win2k sp4, gf4 ti4600 with forceware 91.47, athlon 64 3200+. Let me know if there's anything else you need.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×