-
Posts
7,936 -
Joined
-
Last visited
Content Type
Blogs
Forums
Store
Gallery
Videos
Downloads
Everything posted by Rick
-
Here is another C++ function called from Javascript where from the UI a person clicked on which map to load. Might be helpful in understanding as well. // called from Javascript void App::Client_LoadMap(WebView* caller, const JSArray& args) { WebString map = args[0].ToString(); string _map = ToString(map); std::string mapname = "Maps/" + _map; Map::Load(mapname); webView->LoadURL(WebURL(WSLit("file:///UI//HUD.html"))); // used to let the page load before we show anything while (webView->IsLoading()) webCore->Update(); Sleep(300); webCore->Update(); // draw awesomium BitmapSurface* surface = (BitmapSurface*)webView->surface(); if (surface->is_dirty()) webTexture->SetPixels((const char*)surface->buffer()); Material* mat = Material::Create(); mat->SetTexture(webTexture); Shader* shader = Shader::Load("Shaders/Dynamic/diffuse.shader"); mat->SetShader(shader); Entity* console = world->FindEntity("Console"); console->SetMaterial(mat); //webTexture }
-
I've gotten this working before. A couple things. 1. In my main loop the way I get the data to an LE texture is slightly different than what you have: // draw awesomium BitmapSurface* surface = (BitmapSurface*)webView->surface(); if (surface->is_dirty()) webTexture->SetPixels((const char*)surface->buffer()); context->DrawImage(webTexture, 0, 0); webTexture is an LE Texture object. 2. Here is my UI Input function for the mouse (I haven't figured out keyboard but if you do that would be nice to share with everyone) void App::UIInput() { webView->Focus(); Vec3 mpos = window->GetMousePosition(); webView->InjectMouseMove(mpos.x, mpos.y); if (window->MouseDown(1) && leftMouseDown == false) { webView->InjectMouseDown(kMouseButton_Left); leftMouseDown = true; } else if (window->MouseDown(1) == false && leftMouseDown == true) { webView->InjectMouseUp(kMouseButton_Left); leftMouseDown = false; } if (window->MouseDown(2) && rightMouseDown == false) { webView->InjectMouseDown(kMouseButton_Right); rightMouseDown = true; } else if (window->MouseDown(2) == false && rightMouseDown == true) { webView->InjectMouseUp(kMouseButton_Right); rightMouseDown = false; } } 3. Here is how you link javascript functions to C++ functions so when these functions are called in Javascript they will call the C++ function. MethodDispatcher dispatcher; // bind functions JSValue result = webView->CreateGlobalJavascriptObject(WSLit("app")); if (result.IsObject()) { JSObject& app = result.ToObject(); //dispatcher.Bind(app, WSLit("sayHello"), JSDelegate(this, &App::Client_SayHello)); // this C++ function must have a return type of JSValue //dispatcher.BindWithRetval(app, WSLit("test"), JSDelegateWithRetval(this, &App::Client_Test)); dispatcher.Bind(app, WSLit("exitGame"), JSDelegate(this, &App::Client_ExitGame)); dispatcher.Bind(app, WSLit("loadMap"), JSDelegate(this, &App::Client_LoadMap)); } webView->set_js_method_handler(&dispatcher); C++ The function itself looks like (must have these exact params): void App::Client_ExitGame(WebView* caller, const JSArray& args) { quit = false; } If you have arguments passed into the C++ from javascript then: void App::Client_SayHello(WebView* caller, const JSArray& args) { WebString name = args[0].ToString(); WebString msg = args[1].ToString(); int value = args[2].ToInteger(); string _name = ToString(name); string _msg = ToString(msg); } I'm using JQuery so in javascript the way you could call these would be: $(function(){ $("#exit").click(function(){ clicksound.playclip(); app.exitGame(); }); // passing a param $("#newGame").click(function(){ clicksound.playclip(); // tell C++ what map to load app.loadMap($("#maps").val()); }); }); 4. If you want to call a javascript function from C++ then: Javascript side: / this is getting called from C++ function helloWorld(e) { // add each map to the select list for(var i in e){ $('#maps').append($('<option>', { value: e[i], text: e[i] })); } // this is calling a C++ function with a return value //var value = app.test(); // this is calling a C++ function with no return value //app.sayHello(name, msg, value); // this function that C++ called also returns a value return e[1]; } The C++ side: // call a javascript function with args and a return value JSValue window = webView->ExecuteJavascriptWithResult(WSLit("window"), WSLit("")); if (window.IsObject()) { JSArray args; JSArray e; vector<string> files; FileSystem::LoadDir("maps", files); for(auto f : files) { string ext = FileSystem::ExtractExt(f); if (ext == "map") { e.Push(WSLit(f.c_str())); } } args.Push(e); JSValue v = window.ToObject().Invoke(WSLit("helloWorld"), args); string t = ToString(v.ToString()); } I do extra things for testing purposes. Like returning from this helloWorld() function doesn't make much sense but I was just testing how that's done. As a side note, I needed to start from Lua and tell the UI information (in our game Dead Anyway hunger would tick away every few seconds and that was done in Lua, but the UI was obviously in html). So I linked a lua function to a C function and then the C function called a C++ function which then called a Javascript function to update the UI. Note I had to call this lua registering stuff at the top of App:Start(). Anywhere else and it wouldn't work. bool App::Start() { // must call this before calling lua functions for some reason int size = Interpreter::GetStackSize(); // register lua to c++ functions lua_pushcfunction(Interpreter::L, UpdateStat); lua_setglobal(Interpreter::L, "UpdateStat"); } The UpdateStat C function looks like: static int UpdateStat(lua_State* L) { string statName = lua_tostring(L, 1); double value = lua_tonumber(L, 2); app->OnStatUpdate(statName, value); return 0; } Then I just had it call the App objects OnStatUpdate function because I prefer to do things in objects instead of normal C functions but this is the easy way to link C++ & Lua. Then in my OnStatUpdate method I tell Javascript what happened. void App::OnStatUpdate(string statName, int value) { // call the javascript function that will update the html UI JSValue window = webView->ExecuteJavascriptWithResult(WSLit("window"), WSLit("")); if (window.IsObject()) { JSArray args; JSValue stat = JSValue(WSLit(statName.c_str())); JSValue v = JSValue(value); args.Push(stat); args.Push(v); JSValue v1 = window.ToObject().Invoke(WSLit("updateStat"), args); bool r = v1.ToBoolean(); //string t = ToString(v1.ToString()); } } Then my javascript function: // event from C++ which ultimately is coming from lua which is tracking the decay of these stats function updateStat(stat, value){ // change the value of the stat if($("#" + stat).length){ $("#" + stat).text(value); return true; } return false; } There is a ton of information here I know so if you need anything clarified just let me know and we can work through it. Again, if you can get the keyboard events working that would be great to share, and if you can think of any way to package this entire thing up in a nice system where it's maybe a class that people can just use instead of a bunch of embedded parts that would be good for the community I think. I'm still a strong believer that this is how UI's should be, but like you I just don't know HTML/CSS to make any cool UI's that work well on every aspect ratio/screen res.
-
I'd just like the navigation system to not go back and forth when it reaches it's destination and instead stop cleanly.
-
Yeah that's works if you go the route of matching visual to physics. For things like trees having physics on them to near and visual to far would give good performance.
-
Yeah, the hacky part about it is not being able to assign a physics view range in the editor like we do visual view range. So if that's a setting you want each entity to have then each entity would require a script attached to it or a more hardcoded way to set such a key value. Not ideal, but can be worked around. Would just be a nice to have setting. Ideally, when you take this far enough, it's one of those things where if we could have a generic way to set entity key values it could solve this and some other custom settings for other systems we the users wanted to make. Should just be a tab for Key Values that is a list we can set for whatever we want. The benefit is that it wouldn't require a script since all it's really doing is setting a key value in the map format that gets loaded on map load without having the overhead of a script attached to every object. This is something that has been asked a few times and would be very useful.
-
That's a good find! Don't even need to hide models now with something like that. Could make a system where it enables close by physics to the player and disables as the player moves away making physics only apply around the player which should be very efficient if you did it with a grid system to tell what entities to enable/disable. I'd like to explore the idea of disabling physics outside of the view range. Maybe there could be a physics "view range" where there is an infinite option to keep physics running on that thing no matter what. That would work great for ground and actors. I mean how many games are going to do some non actor/ground physics thing when the models themselves are outside the players vision? The entire point of doing something cool with physics would be so the player can see it. Movement is based on a navmesh anyway that is pre-generated so during run-time it shouldn't matter to remove physics on obstacles that aren't even visible. I mean what would be the issues with a system like this? I see good benefits in performance with something like this. If you are stacking things that need physics and you're worried about the bottom thing getting disabled which could have the top entity fall down, then make the bottom one infinite in physics view and that'll solve that. By default have all physics in infinite view so it's backwards compatible but having this option does give us options for performance enhancements at seemingly little work. I mean you'd just duplicate the view range idea but for physics bodies.
-
I don't agree with that. The performance gain's look very large to me. The idea we are exploring here is that it can be designed to. The thing holding it back is hidden objects still calculating physics when it's not needed. It's a waste of cycles and only gets worse as maps get more populated. This is what we're trying to find out. Is it because there is no way to do it or because you don't want to entertain the idea? We don't know the details of how LE is handling this. The veg system, while nice, is still limited in that those are not real entities and cannot be treated as real entities. The recent trend of survival games almost always allows people to cut trees down for resources. This system doesn't allow that. It's because the systems always have a drawback. This is why every time you make a new system my first question is, "What is the draw back". These being "fake" entities is the draw back. It's OK to acknowledge limitations of systems. Everything has limitations and there is nothing wrong with exploring ideas around them. It doesn't mean you have to do them even if you find a reasonable change. It's just getting the creative juices flowing for everyone. You seem to take this stuff so personal and get offended. I'm not trying to do that just trying to get ideas flowing. If you were to say "I agree that hidden entities still calculating physics is wasteful" we're not going to slam you for sticking with it. We are just happy that you are aware and maybe somewhere down the line this sparks an idea in you.
-
We would want collision on it, but these things may be far far away from the player or not accessible at a given time and have no reason to check collision on it until the player is coming up on it. Think of Vectronic having 30 "areas" in 1 map because he doesn't want loading times to load another map or prefab. A lot of the models may be reused so the one map loads fast because it's mostly loading instances. 1 area is used at a time but all 30 need physics and creating these at the time of need (run-time) will cause a noticeable slowdown. However all 30 are causing a FPS hit when they shouldn't. Instead, he can hide all the rest (and if the physics wasn't taking up cycles when entities where hidden) and he would get great FPS. Via triggers he can show/hide the next/previous area. Now he can get very detailed with his areas physics wise and not affect the overall FPS. Today, he can't do that. This idea extends to a lot of different games. This let's us control a level of optimization of these things via showing and hiding entities as our games see fit (and from a logical perspective when an entity is hidden it just makes sense it shouldn't have to care about physics). When I remove physics from the tree and I have 146,691 trees/grass in my scene I get a solid 60FPS. However, things are so dense that I don't need all those trees to be visible. I could cut that number by a lot by hiding trees outside a certain range and it would look the same to my player and would save on the physics calcs if it worked this way. On the other side, in a situation like trees, and I think you do this in your veg system, physics is only needed around moving objects. That physics body on a tree 30 steps in front of me isn't needed until I get close to it. An option like this for us to control would be even better! We don't even need the veg system if we had this on the entity level. It seems it's really the physics that is killing almost all performance with this stuff. Bodies on things that don't need it yet. I mean I could make a system that creates 10 bodies for these trees and I just dynamically attach/detatch them to trees that are just around the player/actors as they move around and I would get the same great performance I'm seeing of having no bodies on anything but have the added benefit of getting collision.
-
But this incurs the run-time cost of creation/deletion of the physics body which is not good and can kill FPS too. So can we nix the callback from being ran if the entity itself is hidden so it doesn't make a call that's not needed? I'm assuming the newton library is calling an LE function for each intersected body. No way to tap into a pre-check before this function call? Is that callback call really the slowdown? How is Newton deciding on what body to make the callback on? I would assume internally there is a list? Are you assigning the callback to each body? Maybe if an entity is hidden you can remove the callback for that specific entity and then add it back when shown. This shouldn't incur any performance hit if this is the way it works. So my bigger example wasn't all at the origin, but the trees were touching the ground (and they are spread all over the place not stack on top of each other) which has collision. So you are saying if they trees were not intersecting with the ground (maybe 1 smallest unit above the ground body) the performance should be the same as if it were just the model itself? [EDIT] From my tests when the trees intersect with the ground it starts at about 6 FPS and just gets worse and worse. So yes, this is probably the callback issue. However, when I raise the trees from the ground (and they interest with nothing) I get a consistent 6 FPS if they are all shown and 15 FPS if they ALL are hidden. It doesn't get worse, so I see the effect of what you are saying but Newton must still be iterating over all these bodies itself even if they aren't intersecting with anything. They have to be iterating over an internal list to see if they should be calling the LE function callback right? That iteration is what has to be killing performance.
-
I think the question really is, can a physics body exist but not be looped over. Much like how you keep entities existing if hidden they just aren't looped over, the physics engine should have the same functionality so it does not incur this creation/removal penalty with hiding/showing. I mean this would make sense wouldn't it? If the entity is hidden the physics body should not be considered in any calculations either. The memory of these rigid bodies is seemingly not the issue here. Memory isn't what's killing the FPS, it's the physics engine looping over these rigid bodies when it doesn't need to.
-
I'm not inclined to do this based on view range but instead on hidden (from us calling Hide() on it). If we explicitly hide an entity it shouldn't be considered in physics. This gives us fine control over things. We can make our own systems based on grid's or triggers to show hide things. However, the idea of only doing physics in an area around a moving physics thing would be great. I think Josh does this for the veg system right now.
-
Survival games like Hayden's generally give functionality to vegetation (cutting trees, picking berries, etc). With my test I found that I was able to populate a 256x256 meter area with 90% grass and 60% trees and still get 60fps! This was like 8000 entities and it handled it just fine. The problem is when we went beyond that there was a steep drop off to areas of the map I was testing that were hidden because they were far away and shouldn't have affected the area the player was in in any way. I'd say the real culprit to these issues is the physics system. If I recall correctly you seemed to be able to limit physics in your vegetation system in an area around moving entities or something like that? Well, combine with billboard and that type of physics logic the entity system should be able to perform similarly and allow functionality. The veg system as it is still has a place for various grass and bushes, and even the trees if the game in question doesn't allow interaction with the tree, but games these days are just different than they were 5 years ago. When I think back on it this was most likely the issue with Dead Anyway when we were looking a a very modular approach. It most likely didn't have anything to do with the model entity count or polys but the physics entity count that existed on the map when they were hidden (because we managed hiding/showing things in code). The code you have for the veg system for dynamic physics around moving objects would be brilliant to have in the normal entity system and should increase performance even more.
-
I guess the point is that this affects all of our maps performance when entities with physics aren't visible. When I think of a game like Vectronic that has clear different areas in 1 map those areas are effecting the performance of the entire map when they don't need to be if he did triggers to show/hide entities and manage the physics in those areas. Hayden's game can be more involved and populated if he's able to control this stuff. We can have highly dense forests where we still have control over each entity to do things with it this way. This just allows for finer control and much better performance from the LE engine. Once of the common knocks I hear of LE is that it's just not very optimized and this can help fight that negative. These are limitations to the number of entities we can have in a map not because of the polycount but because of physics that isn't even being used anyway. This is a limitation that doesn't need to exist. Larger LE maps have been shown to be poor performance by various people over the years and this must be the reason. When these limitations get hit there are no options for people and they get discouraged to continue. If we have this control we now have options.
-
Can't suspend from the physics system? I mean it's hidden it shouldn't be looped over in any system then right? Just seems a little dismissive seeing as this is something that hinders maps with a large amount of entities in it even when they aren't visible from being possible.
-
When I do the below in main.lua I get 16fps for about a second before it crashes. 100k didn't even show me the text of FPS it just froze. local m = Model:Load("Models/Trees/pine01.mdl") for n=0,20000 do local n = m:Instance() n:Hide() end I also did it the below and same thing: for n=0,20000 do local m = Model:Load("Models/Trees/pine01.mdl") m:Hide() end Both methods should be the same, making instances, but wanted to double check with both approaches. Your example with just Model:Create() works just fine, but clearly something else is going on with other models. Even those that come with LE by default.
-
They are the tree entities that come with LE. No scripts but prefabs with view range set. Not sure on physics, it's whatever the tree model has on it. Guessing it does, but not sure why that would matter since it's hidden and shouldn't be iterated over right?
-
So I'm curious why when I load 88,000 entities and hide them all, why I get 0 FPS. 156 polygons on screen, 0 shadow polygons, 1 light, 1 shadow rendered and 86MB used and I get 0 FPS. The less entiites loaded (and still hidden) the higher the FPS. What else besides iterating over more entities could cause this slowdown?
-
Couldn't you break the world into a logical grid? Each "tile" in this grid is a certain width/depth. When entities are added to the scene they are figured out what tile they would be on and added to a list inside that tile that stores entities in that tile. Finding out what tile is easy an division operation. Then every frame or every x ms you find the tile the camera is on, again easy arithmetic, and then based on that tile row/col you can loop over ONLY tiles that surround the camera and ONLY over entities in those tiles. You save that list off each time and each new time you compare the 2 lists to see what is on both and what isn't to tell you what changed and what you need to hide/show for that iteration. Now this wouldn't really allow each entity to define the view range but more of a view range around the camera/player, but it seems like it would be far more efficient when you end up with a ton of entities in the scene that aren't visible because of view range. To make it work on a per entity basis maybe infinite view ranges are left out and always iterated over (which should be far less or none) and the tile radius to check is the max view range and then as we iterate over the entities in these tiles we check their view range to see where they would fall and if they should be visible or not. Again, all of this would make things more efficient when there are a lot of entities. I feel like right now the easy way of iterating over the entities was taken instead of possible more efficient ways. More efficient ways for view range would be to do these things on another thread over multiple frames. With view range stuff I think it's fine if it's not instantly shown when entering view range. A few ms late seems perfectly acceptable I would think. Entities with scripts attached and not hidden would need to be iterated over each frame but again this will be much fewer than just scenery in general. So the point here is that there are more efficient ways to iterate over the entities in the map than just iterating over all of them on the main thread all the time. Imagine the grid system I talk about. If each grid is 100mx100m and you have a 5x5 grid around the camera tile you are iterating 25 times and then sub-iterating over the lists in each tile. That could be a TON less iterations each time you need to do it. Moving items change the tile lists they are on when they switch tiles. The player would also only need to iterate over this 5x5 grid IF they move tiles. So if your main tiles are fairly large that wouldn't be each frame but only when they move from tile to tile. Checking what tile they were on last frame vs this frame is a much cheaper operation than iterating over all entities each time. There just seems to be far better ways to handle this and I feel like what is in there is probably just the cheap and easy coding way of things which introduce these entity count limitations to LE that aren't needed.
-
If an entity is hidden does it somewhere get iterated over behind the scenes in LE still? It seems like it does but I wouldn't think it should. Also if it's not in view range it must still get iterated over.
-
All your 2D drawing needs to be AFTER your 3D rendering. 3D rendering is rendered to a buffer and then that buffer is drawn on the screen, and then when you do your 2D drawing it'll get draw on top of that. It has to be in this order to work. What's happening with your screenshot is the buffer with the 3D drawing on it is drawing on top of your 2D drawings. So after Render() but before Sync()
-
Bone count? I think each bone becomes an entity and LE doesn't seem to do well with a ton of entities.
-
Be careful wiht the "include only used assets" as it' pretty basic in nature. If you are loading something ONLY in code it won't pick it up. Your best bet, I think, is to work in new/empty projects if you think you'll publish anything and bring over the scripts you want from another proejct so your end result isn't so large.
-
You know I thought Josh mentioned there were some big editor changes that someone else was working on for him. Was the auto-complete those changes or are there more to come? The auto-complete is fairly nice but it doesn't work exactly like most auto-completes do and I'm hitting escape or tab or whatever (i've turned it off so can't recall example) to escape the auto-complete at times. It just doesn't seem as fluid as VS's auto-complete.
-
I assume you have an entity script attached to this piston entity? If so then you can handle the states of the piston inside the UpdateWorld() function. By this I mean you can determine if you have to wait and if so you do some timer logic to wait. if state == "waiting" then if Time:GetCurrent() >= self.lastTime + self.interval then state = "fall_back" end end