Jump to content

Ykkrosh

WFG Retired
  • Posts

    4.928
  • Joined

  • Last visited

  • Days Won

    6

Everything posted by Ykkrosh

  1. It's not possible to incrementally update the installer .exe files (or equivalents on other platforms) - they're compressed so their content becomes completely different whenever a single byte is changed. Any kind of patching system would need to be slightly more integrated with the post-installation game, so it can use the old installed public.zip as the base for the new version.
  2. Day 14 Slow continued pathfinding work. In particular, trying to get all the parts of the game to interact correctly with the new navcell-passability concept. It's important for the design to be clear on what its concepts actually are, so this is my attempt at describing the conceptual details of what I'm trying to implement now. (I'll probably copy this as documentation on the wiki when it's cleaned up and implemented properly.) First we start with a map like this: (click image for larger and higher quality version) There's some small units, a large unit (the siege tower), a building, a fence, and some water (with steep terrain around its edges). Units are "dynamic obstructions" - they move around frequently, and they need to perform pathfinding operations, and they generally can't pass through each other. Buildings and fences are "static obstructions" - they don't move, and units can't pass through them. Dynamic obstructions have a "footprint radius", measured in high-precision units (i.e. not quantised to tiles), corresponding loosely to the graphical size of the unit. Dynamic footprints don't have a separate width vs height, nor an orientation. They don't have a precise shape - they're sort of squares, or sort of circles, or sort of neither, depending on how you look at them. Static obstructions have a square footprint with width, height, and orientation; or a circular footprint with radius. Terrain can also block units. Terrain is split into fairly large tiles, and each tile might be passable or impassable, depending on water depth, steepness, etc. Each unit belongs to a "passability class", which defines the exact limits on water depth, steepness, etc, that should be used for that unit's movement. The pathfinder uses a "navcell grid", which stores a boolean passability value for every navcell on the map, per passability class. Navcells are smaller than terrain tiles (currently there's 4x4 navcells per tile). ("Navcell" is just a term for the tiles used for navigation, to distinguish them from terrain tiles). The navcell grid is computed from terrain passability and static obstructions, like so: (click for bigger and better) Here the thin dark blue lines indicate the footprints of all obstructions. Note that the impassable cells from the large building are strictly inside its footprint shape; we take a conservative approach so that if you tell a (zero-sized) unit to walk to the building, it can walk all the way up to the footprint edge without stepping onto any impassable tiles. Unfortunately this mean the fence is invisible to the navcell grid, since it's too narrow to strictly contain any cells. We should enforce that no static obstruction footprints should be that narrow (i.e. narrower than 2*sqrt(2) navcells). The navcell grid only blocks a unit if that unit's central point enters an impassable tile (regardless of the unit's size). To cope sensibly with large units, each passability class defines a "clearance" value. Navcells within that distance of an obstruction are considered impassable. For standard units with a clearance of 1 navcell we get: For large units with a clearance of 4 navcells we get: This stops the large unit moving too close to the buildings or water. (Note that the fence now blocks some navcells. We expand the footprint shape by the clearance, and then compute which navcells are strictly contained within the expanded footprint. In contrast, terrain passability is computed with a kind of blur filter to expand the initial grid outwards by the clearance distance.) The navcell grid ignores dynamic obstructions entirely. The long-range pathfinder finds paths across the navcell grid. It allows moves from one passable navcell to another if they're horizontally or vertically adjacent (not if there's only a diagonal connection). The short-range points-of-visibility (POV) pathfinder is based on high-precision (i.e. not navcell-aligned) horizontal/vertical obstruction edges, and finds paths at arbitrary angles. It goes like: The cyan lines are the obstruction edges that the POV pathfinder will not cross. The green/yellow tiles are the long-range pathfinder's output, and the thin red line is the POV pathfinder's output, for the cavalry unit to move eastwards. For terrain and static obstructions, the POV pathfinder uses the navcell grid: it adds cyan edges around the red cells. That means a unit can move so that its central point is right up to the impassable cells, regardless of the unit's size. The clearance (used when computing the navcell grid) is what stops the unit walking too close to a building. Dynamic obstructions are not on the navcell grid, so the POV pathfinder adds a cyan square around each dynamic obstruction's footprint. To prevent units' footprints overlapping, each of those squares is expanded by the footprint radius of the unit that's moving. (When the cavalry unit moves up to the cyan line around an archer, the cavalry's footprint will touch the archer's footprint (dark blue square).) One slightly dodgy thing here is that a unit's clearance and footprint radius may not be the same. If the footprint is larger than the clearance, the unit might be able to get close enough to a static obstruction that their footprints overlap. I think that's probably not a problem, but I'm not certain yet and will need to clarify. Given those concepts, the rest of the passability-related code can (mostly) be derived: * Whenever a unit moves by a step, we have to check for collisions in case the pathfinder returned an invalid path (e.g. because the world changed since it computed the path). That means checking the movement is along a sequence of passable navcells; and that it doesn't intersect any dynamic obstruction footprints expanded by the moving unit's radius. * When a unit is spawned (e.g. from training in a building), we have to pick a valid spawn point that is on a passable navcell and isn't inside an expanded dynamic obstruction. * When deciding whether it's valid to place a new building, it doesn't really matter what we do. It's easiest to just verify that the new building's navcell shape doesn't touch any already-impassable navcells (computed with a clearance of 0) - that'll prevent it intersecting existing buildings or invalid terrain. When telling an AI where it can place a new building, we can give it a conservative approximation of that navcell grid. * When placing a building on top of units, we need to tell those units to get out of the way before starting construction. To find precisely which units are affected, we need to look at the new building's navcell shape, expanded by the clearance of each unit that might be in the way, and tell any unit standing on a to-be-impassable tile to move away. But that sounds kind of nasty to implement - ought to find a better way... * When a unit moves to a static obstruction (to gather resources, or to melee-attack, etc), we can tell the POV pathfinder to stop when it reaches the edge of a high-precision oriented square or a circle, corresponding to the building's footprint. (That avoids the problem when you tell a load of units to attack an enemy building, of having them line up in an ugly stairstep pattern corresponding to the navcell outline). But we need to guarantee that square/circle is not inside the building's impassable tiles, else units will never quite reach it. So we need to expand the static obstruction's footprint by at least the unit's clearance value to guarantee it will be reachable. (Maybe we should actually compute the unit's footprint radius plus its specified minimum attack/gather/etc range, and use that value if it's larger than the clearance, to allow more control over the behaviour without breaking that guarantee.) Hmm, I think that's about all for now.
  3. It will still need to compile all of the source files, since it needs most of the definitions of classes and methods etc even if they're not working yet, else it'll fail later with linker errors. Generally just small sections of code inside the methods should be disabled, like this. The source files aren't actually listed anywhere - build/premake/premake4.lua lists directories, and it searches for all *.cpp inside them.
  4. r11039/r11040 should have fixed the build errors in source/gui/. (At least they work for me with Mesa's GL ES on Linux). I still need to add GLSL versions of the GUI shaders, but that probably should be enough to get the GUI displaying. I think the rest of the GL code can get either fixed easily (translating to the new shader API) or temporarily #if'd out, but that'll depend on the precise details of each case.
  5. I think the best approach is probably to create a new C++ component, so that it can call other C++ and can be called from scripts (or from C++). The documentation here should be relevant: create something like an ICmpCinematicCameraManager in C++, use DEFINE_INTERFACE_METHOD_* to specify which methods can be called by scripts, create a CCmpCinematicCameraManager that implements those methods by passing the data along to the other parts of the engine that need it, etc, as documented there. Then add CID_CinematicCameraManager to the list of SYSTEM_ENTITY components in simulation2/Simulation2.cpp ResetComponentState so that it automatically creates a single instance of that component. Then you can either have scripts call the component directly ("var cmp = Engine.QueryInterface(SYSTEM_ENTITY, IID_CinematicCameraManager); cmp.DoWhatever(stuff);"), or have the component subscribe to messages that the gameplay code is already sending (as here; e.g. subscribe globally to the PositionChanged message to get notified when any entity moves, without having to insert any new code into CCmpPosition).
  6. Changing the standard global objects is generally a very bad idea in JS, so don't do that . It's particularly problematic in our GUI system since we have a separate global scope per GUI page, with some magic to resolve properties on the real global object when necessary, and SpiderMonkey's JIT optimisations interact in complex ways with global objects too, so it gets confusing and fragile. Just use a normal function instead.
  7. Thanks, I hadn't seen that one before. Brief summary: Dragon Age's hierarchical pathfinding over 8x8-tile sectors was slow because the graph of sectors was too large, so they added another 16x16-tile sector graph on top of it. (They couldn't simply increase the first-level sector size because their approach produces non-optimal paths (with various hacks to minimise the problem), and bigger sectors make the paths much less optimal). Then the paper considers Contraction Hierarchies as an alternative to that second-level graph, which involves taking the first-level graph and heuristically removing nodes and adding edges to minimise the size of the graph without changing shortest path weights, and concludes that CH is slightly faster than the second-level graph for very long paths and slightly slower for short paths (and more complex, and hard to update dynamically). I think the basic problem is that they got stuck with small 8x8-tile (sometimes 16x16-tile) sectors at the start - it seems it would be better to avoid that limit (and support a more efficient, larger sector size) rather than adding an extra abstraction on top of the first not-quite-adequate abstraction, if possible within the various constraints. As far as I can tell from the documentation and published code, this is currently just a very basic implementation of steering behaviours. (Units have a 1/exp(dist) force away from each other, 1/exp(dist) force away from the nearest obstacle, some perpendicular 'look-ahead' force to avoid running into other units, and some force to the next waypoint, and that's it). The web site makes it look much more interesting than it is It stores a width*height bitmap per 'passability class' (where every unit belongs to one class, and the class is defined with max slope and min/max water depth and min distance from static obstacles, which fully determines passability of a tile/cell). (Actually it stores them all in a single array of uint16_t, but they're effectively bitmaps.) Yeah, might help to do something like that to remove unnecessary trees/rocks/etc from the graph and simplify the search. Not quite sure what that would be useful for, though for JPS I'm precomputing the distance to the next jump point in each horizontal/vertical direction from each cell, which helps significantly on large empty maps.
  8. My test code didn't work on real hardware either since I had the SDL 2.0 init code wrong and it was defaulting to GLES1, but it worked after I fixed that. (Then the emulator fails on application startup because it can't find a usable surface type). The Java code in android-project needs modification to support useful things like 24-bit RGB output (instead of default 16-bit) and antialiasing (4xAA is "nearly free on Mali hardware (around 2% performance drop)"), but that's easy enough.
  9. Where does it do that? libraries/spidermonkey/build.sh only mentions --with-system-nspr in a commented-out line. That's in a "#if defined(CROSS_COMPILE) && !defined(FORCE_BIG_ENDIAN) && !defined(FORCE_LITTLE_ENDIAN)" section. I presume CROSS_COMPILE is being defined when building for Android, triggering the error. It looks like defining FORCE_LITTLE_ENDIAN (simplest hack is probably to stick it at the top of jscpucfg.cpp) should avoid that dependency on NSPR, hopefully.
  10. Hmm, I've still not done a lot with this, but I updated the CPU capability data here to give details of exactly which CPUs do/don't support each feature, in a hopefully not incredibly unreadable fashion. (Does anyone happen to know what the "eax=8...1h ecx[...]" bits (i.e. bits 18/23/24 of ECX after running CPUID with EAX=80000001h) are meant to signify?)
  11. I think the important goal is that building the game should be easy and automatic, not that it should be fast. For first-time developers, the time-consuming part will be downloading the game's code and data, and waiting extra tens of minutes for building won't be a major issue. For repeat developers, they'll only need to rebuild the libraries every few months when changes are made, so slowness won't matter. On Windows we provide prebuilt libraries because there's no easy automatic way to compile them on the user's machine, and because Windows allows prebuilt libraries to be portable, but it's a bit of a mess since we end up with outdated libraries and mismatched compiler versions. On Linux we build from source because that can be easy and automatic, and prebuilt libraries wouldn't be portable. OS X seems much more like Linux in this.
  12. They're not quite 1MHz - their resolutions are different from around the 13th significant figure. Does this work better? (Data is grouped by OS and frequency; "CPUs" is the CPU identifiers of everyone in that row, skipping the Linux row because there's loads. The OS "Unix" is a non-Linux Unix, presumably BSD.) We probably need a larger sample size before drawing any reliable conclusions, in which case your influence will be negligible
  13. If the only thing missing from the official NDK is the definition of the std::wstring type, then we could easily define the type ourselves (exactly like source/ps/utf16string.h except with wchar_t). But it sounds like the NDK is probably missing most of the functions for operating on wchar_t too, in which case that won't be sufficient. Changing the game to not use wstring/wchar_t should be hypothetically feasible (it may be best to store everything as UTF-8 encoded strings internally, and just convert to/from UTF-16 when interacting with Win32 APIs) but probably a huge amount of work - I expect it'd be much easier to sort out the build system issues instead of changing all the code.
  14. Preliminary data from SVN users: Frequency | Users ----------------|------ 3656.000000 MHz | 1 3635.000000 MHz | 1 3392.000000 MHz | 1 3013.000000 MHz | 1 2194.000000 MHz | 1 2100.000000 MHz | 1 2094.000000 MHz | 1 1995.000000 MHz | 1 1495.000000 MHz | 1 1000.000000 MHz | 47 14.318180 MHz | 3 14.285714 MHz | 1 3.579545 MHz | 2 3.092138 MHz | 1 3.092119 MHz | 1 2.441416 MHz | 1 1.948281 MHz | 1 1.000000 MHz | 1 1.000000 MHz | 1 1.000000 MHz | 2 0.000500 MHz | 2 (If a single user reports different frequencies each time they run the game, they'll be counted once for each value reported; I don't know if that's occurring in this data.)
  15. Fixed a few more things. There's now some logs of the IRC channels here (separate file per day per channel) since several people have asked for them. The Doxygen output here should be updated automatically every day. The revision log on the 0 A.D. web site no longer works, and doesn't seem worth fixing since you can subscribe to Trac's RSS feeds if you want to follow updates. Trac recommends upgrading the workflow (from 0.10's default to the new "basic workflow"), which I haven't done yet - does anyone think it would be a worthwhile change?
  16. Have you seen this? I guess something similar should work for us, though I don't know whether the 1.8.5 release is compatible enough or whether we should use a newer Hg revision. With 1.8.5 we don't need --enable-threadsafe or --with-nspr-* (and don't need to compile NSPR); don't know about newer revisions. Also I presume we can target android-10 (2.3.3+), not android-8 (2.2+), but I guess that won't matter much.
  17. Or e.g. Tools -> Preferences -> Advanced -> History -> Empty Now in Opera, or wait until the cache naturally expires. Should work eventually
  18. That means it expected a <variant> in the XML file at a certain point, and found something else instead. In this case the problem is you've put a <group> inside another <group>. You shouldn't need an extra group or variant at all - just put the <texture> line right after the <mesh> line, inside the first group/variant.
  19. I've moved some stuff (SVN/Trac/feedback/etc) to a less outdated server (moved from Ubuntu 8.04 to 10.04; Trac 0.10.4 to 0.12.2; SVN 1.5.1 to 1.7.2). I think it's working now, but if anyone sees any problems then please complain (One known temporary problem is that you probably can't log in to Trac or SVN until the DNS changes have propagated, but that should only take a few hours.)
  20. Maybe it needs a texture? One danger is that the PMD/PAE cache isn't keyed on the contents of skeletons.xml, i.e. if you edit skeletons.xml but not the mesh/animation then it won't notice the change. (You have to delete %appdata%\0ad\cache\ or ~/.cache/0ad to empty the cache, or modify the mesh/animation so it won't be found in the cache). (That bug used to not matter since nobody edited skeletons.xml much, but now it seems everyone is at it )
  21. I think a possibly sensibly plan would be to focus on getting just the GUI to work for now (plus the build system and anything else required), and #ifdef out any problematic non-GUI code, so we can have a runnable starting point before porting all the other graphics code. (I was attempting to start with the GUI here, getting rid of some of the fixed-function code). That will probably involve more changes to the CShaderProgram API so that it can use glVertexAttribPointer instead of the not-in-GLES2 glColorPointer etc, and the rest is probably just tedious rearrangement of code to use the new APIs. I know very little about ndk-build and ant, but that sounds reasonable... If I understand correctly we could probably use SDL's normal ndk-build step, with its jni/src/Android.mk's YourSourceHere.c just being a simple file that defines SDL_main() to load libpyrogenesis.so and call a startup function inside that shared library, and then we can build libpyrogenesis.so independently using the game's build system, and then get ant to work as with normal SDL but copy libpyrogenesis.so into the package too, or something like that. Incidentally, about the libraries bundled with the game: there's probably no point porting NVTT to Android, since it's used for S3TC texture compression and most mobile GPUs don't support S3TC; I think we should disable that code and load uncompressed textures instead. (Then, if not everybody has got fed up with Android, experiment with ETC1 to save VRAM, and/or JPEG to save download size, etc.)
  22. About SDL: since a few days, the Hg version of SDL 1.3 is now called SDL2 instead, and has removed compatibility with the SDL1.2 API. I guess we need to either use 1.2, or a slightly older Hg version of 1.3, or update our code to be compatible with SDL2 (probably better in the long term but I haven't tested it to see how much we'd have to change). Incidentally, don't remember if this has been mentioned before, but it's impossible (or at least discouraged and unportable and seemingly undocumented) to use GLES with pure C++ - you have to use some Java to set up EGL windows before the C++ can render into it. SDL provides the necessary Java code, and SDL's android-project can build it: when you run "ndk-build" it builds libSDL2.so and libmain.so, and when you run "ant debug" it compiles the Java code and packages everything into an .apk file. (Then you do an "adb push whatever.apk /data/app" to install it onto the device). I imagine it would be easier to write a custom script to perform those build steps, instead of trying to integrate our existing code into ndk-build, but I don't know exactly what's required. Unfortunately the Android emulator doesn't seem to do GLES2 - I can compile and run a simple SDL test application but it just prints "E/libEGL ( 504): called unimplemented OpenGL ES API" to logcat. At least it's possible to test that the application starts up without linker errors or Java exceptions etc, but for any graphical output it'll need to be run on real hardware.
  23. I think that's a problem with SDL's default handling of fullscreen on Linux - I'm not sure whether there's anything we can do to make it work better in more cases. As an alternative, you can switch to windowed mode (press alt+enter) then maximise the window on one monitor.
  24. Yeah, anything available now will be totally obsolete within six months . But it seems nice enough for now, and relatively good value ('free' with £24/month * 24 month contract, via O2), so I think I'll be adequately happy
  25. There needs to be some new code added, equivalent to lib/sysdep/os/unix/x/x.cpp (should be mostly trivial), and lib/sysdep/arch/x86_x64/x86_x64.h and lib/sysdep/arch/ia32/ia32.cpp (probably not too hard). I suppose that's not really a lot, and linker errors will point out exactly which functions are missing, so it shouldn't be a big problem.
×
×
  • Create New...