Jump to content

Josh

Staff
  • Posts

    23,219
  • Joined

  • Last visited

Blog Entries posted by Josh

  1. Josh
    Leadwerks3D has built-in project management features that assist the user to create, share, and publish projects. When you first start editor for the first time, the New Project wizard is displayed. You can select a programming language and choose which platforms you want the project to support. It is possible to add project templates for new languages, too.

     
    Once a project exists, you can go into the project manager and switch projects. This will cause the editor to use the project directory as the path to load all assets from. All files will be displayed relative to the project directory. You can drag an image into the icon box to add it to the project. (Xcode users will probably notice the influence here.) The +/- buttons will allow you to import a project or remove one from the list, with an option to delete the directory (iTunes much?).

     
    I want to add more features like exporting projects into a folder or .zip file, or maybe a .werk project package the editor recognizes. The editor will have options to skip asset source files like .psd, .max, etc., and only copies relevant files, so all the hundreds of files the C++ compilers generate will be skipped. We might eventually even add integration with SVN repositories, backup systems, and team management features, but that's beyond what we need to worry about right now.
     
    A "project" in Leadwerks3D is a game or other program, and will typically contain many maps (scenes). Since this kind of defies a conventional design around file requestors and files and folders, we might not even use a traditional "Open Map" dialog. All the project's maps will be available in the "Maps" directory in the Asset Browser. I can even save a thumbnail of each map when the file is saved. To add a new map to a project, you would simply drag it into the Asset Browser, preferably in the "Maps" directory. Or maybe we will also include an "Open File" file requestor that can be used to import any map, material, texture, etc. into the project. The current design of the editor is the result of a lot of experimentation and testing, so I'll continue to play around with it as I add features.
     
    Michael Betke and I have traded a lot of projects back and forth, and this system is designed to make that task easier so we can all exchange self-contained projects. If you have any suggestions to add, post in the comments below, or in the feature requests forum.
     
    --Update--
    And here's the export screen. This is similar to the "publish" step. I need to write a parser that goes through source code to determine what files are actually needed in the project. The project template defines what file extensions to scan for used files:

  2. Josh
    All difficult technical challenges for the completion of Leadwerks3D are solved. This includes navmesh pathfinding, cross-platform support, Lua and C# integration, OpenGLES rendering, the abstract driver model, etc., etc., etc. Basically, all the scary stuff is done, and the only thing that remains is hard work. I'll be turning my attention back to the editor shortly, but first I wanted to address a different kind of challenge: Documentation and the website.
     
    The present appearance of the website took a long time to develop, and is the result of four or five different people's work. It was difficult to find him, but I finally came across the one who is the master of the forum software and CMS we use. He was able to fix a few small issues I had, but he did not design the site. Now he has bee recruited to create a new website theme using the good elements of our current design, in a Web 2.0-ish style. We're also planning on an improved image and video gallery, and a better display for community articles. Professional web design services will be used to create product pages for Leadwerks3D that truly reflect how awesome the software is. I'm not a web designer, and I am happily surrendering that responsibility to someone who has instructions to develop Web 2,0-style product pages with my content.
     
    Last summer we launched a lot of new website features including a chat bar, video gallery, and embedded documentation. The first two were a success that I feel really add to the site experience. The third I consider somewhat of a failure. The documentation search is not very good, the pages take too long to load, and the organization is too categorical. I installed a temporary Wiki where I have been jotting down docs and ideas, but I wasn't committed to the idea of using it for the Leadwerks3D documentation. Then I found the documentation system we're going to use.
     
    Leadwerks3D documentation will be available in a two-panel searchable HTML page, which is pretty standard. However, the same docs can also be exported in PDF and even EPub format, which is what iBooks uses:

     
    So, with the documentation system decided and web design out of my hands, I now turn back to the Leadwerks3D editor...
  3. Josh
    A few people have asked me about this, so now seems like a good time to talk about my experience with Mac computers. My first computer was actually an old Macintosh SE30, but of course in the 1990's Windows took over and I forgot about Mac. When I started developing Leadwerks3D I invested in a 27" iMac. It includes a 3.2 ghz quad core i3 CPU and an ATI Radeon 5750.
     
    At the most minimal, the computer needs one cord for power, and that's it. The keyboard and mouse are wireless, and a built-in wifi receiver is convenient before you string a cable over from your router.
     
    It took a while for me to adjust to it, and I didn't have a big motivation to because it was just a dev machine. However, I started noticing the way it integrated really nicely with my iPhone and iPad (which I also only bought for development). Xcode 4 is a great IDE, and since it uses GCC build times are very quick. I think the build time for Leadwerks3D is about 1-2 minutes, compared to five on Windows. iOS provisioning profiles, which you need to run your app on a iOS device, are a pain but you can run the iOS simulator with no iOS dev account, and it does a good job.
     
    OSX Lion supports OpenGL 3.2. I had some early problems getting it to work, but Apple actually analyzed my application and told me what I was doing wrong. In a situation where a lot of new developers are working with OpenGL in a way that wasn't previously supported on Mac, I think it's understandable that they would need to provide a little extra support. So with that resolved, I don't see any problems with rendering on Mac, EXCEPT:
    -Even thought the hardware supports it, you can't do hardware tessellation, since OpenGL 4 isn't supported.
    -Deferred rendering with MSAA isn't supported. Well, technically it is supported, but the maximum number of samples is one. So it isn't.
     
    As for the OpenGL 2 renderer we use to match mobile device rendering, there's no disadvantage there.
     
    iCloud is a new part of iOS 5, and it's great because my bookmarks are always synced. I know there are various plugins that do this for other browsers, but with Apple it just always works, without requiring any effort on your part.
     
    Mail through me.com, which you can get a free account for, is always synced. I've tried setting up IMAP mail systems, and they just never really work properly. iCloud mail is by far the best email syncing I have ever seen. It's as instantaneous as GMail, but uses a local client so it is fast and responsive. The Mac Mail app itself is both simple and sophisticated. It doesn't have nearly the number of features as Outlook, yet somehow it does exactly what I want. Email search is near-instant, and it separates accounts so I can look at all mail, or easily select a single account and only view email for that address.
     
    There's a lot of good third-party apps available in the Mac App Store. Transmit is a solid FTP client, and Cornerstone is a great SVN client. The iWork suite provides an adequate replacement for Office. You can even install Steam, although the only games I have that run on Mac are Valve's library and Amnesia: The Dark Descent.
     
    iCal, the calendar app, syncs wirelessly through iCloud. This is the first time in my life I have ever actually used a calendar program for real life. It can send out alerts before an event, and everything is synced across my iPhone, iPad, and Mac. There does seem to be a bug right now where events created on my Mac don't go out to the mobile devices.
     
    Mostly due to the strength of the Mail app and Xcode, I now consider the Mac my "main" machine. For me, Windows is just a platform to run Steam on and compile builds for Windows.
     
    The purpose of this blog entry isn't to convince you one OS is better than any other. I would not be able to get by without my PC for some things. If you're thinking about getting into iOS or OSX development, Mac computers now have my seal of approval. Of course, you can install Windows with Boot Camp, so it doesn't have to be an either/or choice. The only reason I still have a physical PC is because mine has hardware that isn't available on Mac, like a Blu-Ray burner and a massive GEForce 480 GPU. I'd have a hard time giving up the infinite upgradability of a PC, but I do like my Mac.
  4. Josh
    The development of Leadwerks3D seemed like an impossible task at first. Not only did I need to write a new 3D engine entirely in C++ mostly by myself, but I had to make it run on four platforms (Android, iOS, Windows, and Mac), with a scalability all the way from the fixed-function pipeline up to the very latest hardware tessellation features. All logical sense told me this was impossible. Even large companies with 100 programmers or more haven't yet been able to put out a 3D engine with the range of platforms and scalability I am targeting. What makes me think I can do it?
     
    As we approach the initial release of Leadwerks3D, what I thought was impossible seems much more feasible now. During the course of development of Leadwerks3D, I've learned some important ideas that give a lot of hope to me and to indie game developers everywhere.
     

    Systemic Interdependence
    When managing complex tasks there's something called systemic interdependence. This refers to the idea that when you have many people working on one project, they are rarely isolated from one another. They often have to stop and wait for another person's job to be done before they can continue with their own, and programmers often end up stepping on each other's toes when they work together. 
    Even though only Aria and I are working on the source right now, we have experienced this. It's very important we keep busy with separate aspects of the engine. Aria works on platform implementation issues, I work on the core engine design, and we try our best to keep the source code repository in sync. So far this works well for us, but I could easily see a lot of problems arising if we had more people working on parts of the engine that aren't so easily compartmentalized.
     
    Think about your own game. What if I told you I was willing to give you as much money as you wanted to hire programmers, (as long as your final project gave me a big return on my money). Sound great, right? So you go out and hire ten programmers. They come in every weekday, 9 to 5. They're willing to work, but you have to instruct them and keep them busy and productive. Don't have anything for them to do at the moment while you finish one little part? Too bad, they're still on the clock and you still have to pay them.
     
    With ten programmers, would your game get done ten times faster? Almost certainly not. In fact, as you add programmers, your work output will probably look something like the graph below. With one programmer, we have an output of 100 arbitrary units. We gain efficiency with the first few programmers, but the effect lessens with each additional worker. They have to wait for another person to finish something. Now the code repository is conflicted, and you have to figure out how who added what code. You also have an increasing number of relationships and communication between individuals.
     

     
    Once we get past five programmers, additional programmers actually have a detrimental effect to our output. If we continue adding more workers, we can reach levels of output that are below even that of a single programmer. Imagine if 30 people were working on your game. It would be chaos, and that whole time you would be burning money as they came in every day. Meanwhile, your investors would be sitting impatiently, expecting you to get back a lot more money than they put in.
     
    My chart above isn't precise, and the number of programmers a project can support will vary based on its ease of compartmentalization, but the overall idea stands: Software development does not scale very well with additional manpower. This is why small companies are continually springing up and outmaneuvering larger ones. Android came from a small company. It was bought by Google, but only after a small team had built the foundation. Minecraft came from a very small company. Kinect originally came from a small company. Small companies with focused goals are able to compete with much larger companies because of the effect of diminishing returns.
     

    Performance and Motivation
    Another problem big companies have is motivation. In a professional software development environment, managers like to have measurable performance metrics to evaluate employee efficiency. These are used for performance evaluations, and are the basis for salary increases, promotions, and disciplinary actions. Managers set goals and milestones that can be easily measured after a period of time. Workers respond to this by doing exactly what management tells them because they get rewarded for it. If a worker has an idea for a new technique that might or might not work, they're not as likely to spend time on it in this environment. If it works, the company gets to keep their idea and they get nothing. If it fails, they've wasted time on something that doesn't fit into their manager's ideas of measurable performance. Now, a lot of tech companies do try to encourage innovation, but if a worker has an idea for something they really believe in, they are more likely to form their own company where they can be in complete control of their vision. The professional software development environment does not encourage risk-taking and innovation the same way small companies do, because they need easily measurable metrics to assess performance. They only get out of employees what they reward, and it's hard to measure the value of new ideas and attention to detail. 

    Conclusion
    These ideas I've learned during the development of Leadwerks3D are directly applicable to your own game projects. Don't get discouraged when you run into a tough problem. Even if you had more help, you would still have to figure out a solution, one way or another, and you wouldn't be able to shift that responsibility off onto employees. You can do it, just be wise about where you focus your efforts and plan carefully. 
    --Edit--
     
    I posted this article on GameDev.net and got a few interesting responses:
     
  5. Josh
    I spent most of today getting the Android library more polished, especially when handling application switching. It's a little tricky because Android doesn't automatically manage your sound channels and OpenGL resources, so these need to be reloaded when an app regains focus. Here's a video, which I obviously had way too much fun with in iMovie:


  6. Josh
    The windows class on OSX has been a bit neglected, so i spent some time getting it ready for the final release. Creating a full-screen window on Mac is a little funny. There's a fullscreen mode that's been around a while, but it locks the system so that CMD+TAB doesn't work. That means if your application crashes, or you don't program it to close with the escape key, you'll be stuck in fullscreen mode, with no way out but a computer restart!
     
    You can create a window on top of everything else, and CMD+TAB will still work, but the borderless style you use for this makes it so no keyboard input is recognized! If you press escape, the system just beeps and the window doesn't catch an event. :o
     
    There's also a new full-screen mode for apps in OSX Lion, but it's for GUI apps, and I wanted this to work on Snow Leopard. I knew it was possible because Left 4 Dead 2 on Mac does this. Using the Google, I was finally able to find the information I needed. I had to create a new subclasses NSWindow class to get keyboard input working.
     
    Another problem I had was that when a window was resized, the NSOpenGLContext wasn't sizing with it. Many, many search queries later I found what I needed, and added a couple of methods to my OpenGL view class.
     
    Objective-C may be the greatest thing in the world for writing GUI applications for Mac, but I found it very complex for simply creating a window. It takes about 700 lines of code to create a window that has OpenGL rendering and keyboard and mouse input. Out of all that code, you guys end up with one or two functions that do exactly what you need to create a window and get events. B)

     
    Let's talk events. Event queues are the most compatible with all languages, but a callback is really better. When a window is being resized, the application loses control and doesn't get it back until the user lets up the mouse. That means an event queue system doesn't allow the window to be re-rendered as it is sized, and you get ugly artifacts as it is sizing. Therefore, I think we need a hook system where you can add your own hooks like this:

    System::AddHook(int hookid, char* funcptr, Object* extra) System::AddHook(HOOK_EVENT, myfunction, NULL)
    I think we're also going to set up the App class so that it has a ProcessEvent method, which automatically gets added as a hook:

    App::ProcessEvent(int eventid, int data, iVec2 position) { switch (eventid) { case EVENT_WINDOWSIZE: world->Render(); context->Sync(); } }
    Your thoughts?
  7. Josh
    Well, we're through the "OMG will this even work" phase. Aria got FreeType to build on all platforms, so you can load TTF files directly on Windows, Mac, Android, and iOS devices. I set up the accelerometer input on iOS today, so you can call Device::GetAcceleration() and retrieve a Vec3 telling you which way is down. Acceleration is returned relative to the screen orientation, so you don't have to worry about which way the device is rotated. This isn't my proudest screenshot, but it demonstrates that it works. Gravity is pointing in the negative Y direction, relative to the landscape screen orientation.

     
    Multitouch is working on iOS and Android. I am not 100% happy with the way events are handled at this point, but the hard parts are done.
     
    I also got cross-platform threads working. I like the Windows implementation of threads better than POSIX, but our Thread and Mutex classes work the same on everything. I use these internally to optimize routines in the engine, and you are welcome to try them, but be warned! Multithreaded programming is not for the faint of heart, and there's a lot of ways you can hurt yourself! I generally avoid use of mutexes at all, and just try to design my routines so that I send a bunch of data to get processed, then get the results. Otherwise it's just too complicated.
     
    I had an interesting discussion last week with one developer here, and it led to the decision to start using static class functions for creation and loading commands. For example, instead of CreateThread(), you will call Thread::Create() in C++, Lua, and C#. This gives us a uniform API across all three languages, and it resolves the problems that arise from C#'s lack of global functions.
     
    The goal right now is to get all the platform-specific stuff totally resolved and 100% tested so that we can move on and be totally platform-agnostic. That means from now on I can just write code without worrying about whether it's running on Android, Mac, Windows, or whatever. Not much else to say at the moment. Here's a screenshot of the code log to show what we've been working on:

  8. Josh
    I implemented direct WAV file loading, and will add OGG as well. The MP3 file format has licensing issues, and we are not going to support it. However, if you use a third-party MP3 converter, the editor will detect whatever converters you add and use them (see more below). We're using OpenAL for sound, but have a more in-depth implementation than in the past. Sound source management is important because you only get so many sound channels on most cards, and this is handled automatically, based on sound range. It's actually quite elegant because sounds are stored in the world octree, and only sounds that intersect the listener are evaluated. This makes it very very fast, and sounds can have any arbitrary range value. You can also get the length of a sample and skip to a certain time.
     
    I decided it was important to be able to load TTF files directly. The FreeType library is quite large and isn't set up to compile for ARM processors. Aria has been working on that, which is good because dealing with compiling issues and other people's code is not my strength. I just got word that it was working on the last platform, so I will check it out tomorrow.
     
    The direct loading of WAV, OGG, and TTF files got me thinking about textures...could we justifiably load images files directly, instead of automatically converting them in the background? I wrote a BMP texture loader, and although I got the loading and mipmap generation down to 28 milliseconds for a 1024x1024 BGR image, I don't think it's the right way to do things. Textures and models are complex files, and it's best to have the editor automatically convert them to our own TEX texture format when a change on the hard drive is detected. The only disadvantage is that if you are coding and working in Photoshop, you have to either leave the editor running or open and close it, if you want your TEX files updated. Or you could drag the image file onto the appropriate converter, but we know from experience that is unacceptable. I think automatic conversion of these files is best because:

    Not all conversion code can be included in the engine library. The Autodesk FBX SDK, for example, isn't even available for ARM systems.
    Some libraries like FreeImage, which is needed to load PSD files, are enormous. FreeImage compiled as a static library is 17 mb! That is way too much bloat for a mobile app.
    Automatic conversion means you can add support for new file formats just by dropping a converter in the "Tools" folder.
    I want to show you how the directories are laid out in the Leadwerks3D installation folder. Instead of switching your asset path around in the options whenever you want to load assets from a directory, we're going to use a concept of "projects". When you select a project, Leadwerks3D starts loading all assets from that directory, and sets the project's "Maps" folder as the default open/save directory for maps. When you are ready to make a distributable game, Leadwerks3D will read all the maps and scan source code files for asset files, and copy only the asset files you use into your final distributable game.
     
    Root directory:

     
    Templates for all supported languages:

     
    A sample C++ project:

     
    C++ and C# project files for Visual Studio, Xcode, and Eclipse are stored in a "Build" directory, each with a subfolder for the platform. This is how we manage the Leadwerks3D source code, because all those compilers can create a ton of extra files you wouldn't want residing in your main project folder:

     
    Finally, I started the OpenGL2 renderer tonight, which is aimed to be identical to the OpenGLES2 renderer. This is my primary focus for now, as it is important to have one uniform renderer that looks the same on all platforms. Of course advanced graphics is our specialty, and I have already done all the research for new effects when I finish the OpenGL 3.2 and 4 renderers. Deferred rendering will work on OSX Lion, multisampled deferred rendering is already working on Windows, and other stuff like per-pixel motion blur is done.
     
    We're nearly to the point of having a usable game programming library for four platforms, and only have one more library to compile for mobile. It's coming along nicely! B)
  9. Josh
    Crowd navigation is built into Leadwerks3D. You just set a destination, and your characters will automatically travel wherever you tell them to go. I think having navigation built into the engine will give us better results than a third party add-on would. We can automatically recalculate sections of the map that change, AI script functions can be called when certain events occur, and the code to control characters is extremely simple.
     


  10. Josh
    As I was implementing the collision commands for Leadwerks3D, I noticed a few things that illustrate the differences between the design philosophies of Leadwerks Engine and Leadwerks3D.
     
    You'll easily recognize the new collision commands, although they have been named in a more verbose but logical manner:

    void ClearCollisionResponses(); void SetCollisionResponse(const int& collisiontype0, const int& collisiontype1, const int& response); int GetCollisionResponse(const int& collisiontype0, const int& collisiontype1);
    In Leadwerks Engine, the collisions were left to the end user to define however they wished. In Leadwerks3D, we have some built-in collision types that are declared in the engine source code:

    const int COLLISION_SCENE = 1; const int COLLISION_CHARACTER = 2; const int COLLISION_PROP = 3; const int COLLISION_DEBRIS = 4;
    By default, the following collision responses are created automatically:

    SetCollisionResponse(COLLISION_SCENE,COLLISION_CHARACTER,COLLISION_COLLIDE); SetCollisionResponse(COLLISION_CHARACTER,COLLISION_CHARACTER,COLLISION_COLLIDE); SetCollisionResponse(COLLISION_PROP,COLLISION_CHARACTER,COLLISION_COLLIDE); SetCollisionResponse(COLLISION_DEBRIS,COLLISION_SCENE,COLLISION_COLLIDE); SetCollisionResponse(COLLISION_PROP,COLLISION_PROP,COLLISION_COLLIDE); SetCollisionResponse(COLLISION_DEBRIS,COLLISION_PROP,COLLISION_COLLIDE);
    Each entity's default collision type is COLLISION_PROP, which means that without specifying any collision responses, all entities collide with one another.
     
    Of course if you want to scrap all my suggested collision responses and define your own, you can just call ClearCollisionResponses() at the start of your program. The main difference in design is that Leadwerks3D assumes the user wants some default behavior already specified, instead of being a completely blank slate. That's a design decision that is being implemented across all aspects of the engine to make it easier to get started with.
  11. Josh
    Happy Halloween! The free Justine add-on for Amnesia: The Dark Descent is available. Just don't get too scared! B)
     
    Leave a comment telling us how you are celebrating Halloween this year.
     


  12. Josh
    The Leadwerks.com server started acting up earlier today, and I had no idea why. Database errors were occurring, and I had not made any changes to the site. I called our server site in Chicago. First they restored the full site from a backup from 2 A.M. yesterday morning. The matter was still not solved, though. A couple hours later, they determined that an automatic CPanel upgrade had caused PHP extensions to be loaded multiple times. This was fixed, and now we are back to normal. If you've been around a while, you know I have a big fear of data loss but it appears our procedures were able to solve the problem on our dedicated server. You get what you pay for. B)
  13. Josh
    Leadwerks Engine 2 is single-threaded. The engine performs one task at a time. The engine updates physics, then performs some other tasks, then renders the scene, waiting until each task if finished before moving onto the next one:

     
    I have experience programming threads in BlitzMax, and it works pretty much the same way in C++. Leadwerks3D is taking full advantage of threads and multicore CPUs, splitting off any expensive tasks that can be run on separate threads.
     
    Multithread programming is a little different than linear programming, and you just have to design things carefully. It's okay for two threads to read a variable at the same time, but if they both try to write to the same variable, or one writes while another reads, you will have major problems. This is made harder by the unrestricted nature of Leadwerks, because the end user might call any function at any given time, and I don't want to make arbitrary rules like "You can't modify surfaces during the main game loop".
     
    Mutexes (short for mutually exclusive) are a way around this, as they lock sections of the code to prevent multiple threads from accessing them at the same time, but I try to avoid using them. It's extremely difficult to find all the parts of your code that might need a mutex locked. Also, when you start using mutexes liberally, you lose all the benefits of concurrency, because the threads have to stop and wait for each other. I prefer a design where you gather data for a thread, run the thread without interacting with any other parts of the program, and then get the results a few frames later, or whenever the thread finishes processing.
     
    Multithreading has some big benefits for the new engine.
     
    Physics
    Physics in Leadwerks3D are asynchronous, meaning that while the engine renders the scene and executes your game code, it's already calculating the next frame of physics on a separate thread! The diagram below shows how the physics get split off onto its own thread, then split into many threads by the solver, and the two threads meet again the next frame. (It's actually more complicated than that, the engine just keeps running until 16.667 milliseconds have passed, then it waits for the physics thread to finish, if it hasn't already.)

     
    Let's say our ideal framerate is 60 FPS, which means our target frame time is 16.667 milliseconds (=1000/60). Whereas before a physics processing time on a single thread of 10 milliseconds would eat up 2/3 of your ideal frame time, now you can have physics that take up to 16 milliseconds, and have no performance cost for a program that is otherwise running at 60 FPS. Below you can see 5000 bodies falling at near real-time speeds:

     
    NavMeshes
    Navmesh generation is a slow process. However, it does not need to be instantaneous. This makes navmesh recalculation perfect for multithreading. As you can see in this video, the obstacles can move around and the AI navigation will react dynamically to the environment. I've never seen a game with dynamic environments like this, so we are breaking totally new ground. As CPU core counts rise the engine will be able to use those cores to handle more complex maps and greater numbers of characters. In the meantime, it will perform well on any dual-core mobile device!


     
    Rendering
    Rendering in Leadwerks3D will split culling up among threads to take advantage of multiple CPU cores. This is not yet implemented, but it's a little easier than physics and navmesh threading, since it doesn't run concurrently to the main engine thread.
     
    Below is a diagram showing the complete threading design for the engine:

     
    Multithreading in Leadwerks3D is all done automatically behind the scenes, so you can still program however you want, without fear of interfering with other threads.
  14. Josh
    I was at a shopping center this afternoon wasting time, and came across a hobby shop. I can't quite articulate what it is about stuff like this that I like, but this is what I want game development with Leadwerks3D to be like. This is why I set up the Leadwerks Asset Store and make the effort to make nice thumbnails with transparency to show off items in 3D. I want more game development to be a process of producing reusable components, and then at the design level, of picking and choosing which components to utilize.
     
    This is the kind of stuff I used to do as a kid, which undoubtedly paved the way for my future work in 3D graphics. I particularly like the packaging on the box in the first image: "You can do it!" I should use that. B)
     
    Post your thoughts below.
     

     

     

     

  15. Josh
    I was thinking this morning how Apple has influenced my life and the company Leadwerks. You might ask why I am talking about this, since we are only now coming out with our first product for any Apple operating system. Well, before Windows existed, back in the 1980's, this was my first computer:
     

     
    The first "game" I ever made was in Macintosh Paint. I drew a road from a top-down view, with barriers randomly placed on either side. I drew a race car, zoomed in the image, and used the selection lasso to cut it from the page. By dragging the selected pixels to the top of the screen, I could make the image scroll, causing the road to move beneath my car, and I had to move the mouse left and right to avoid the barriers. (I tried to forget the order I had placed them in.)
     
    I also used this machine to paint my first textures, before texture mapping was invented. I drew sides of buildings with variations with windows and doors. Although the monitor displayed only two colors, black and white, you could approximate gray by stippling pixels. There was also the option to use colored pencils once you printed out the images. I would print these on paper and then construct buildings out of paper with them, a precursor to the work we would do later with CSG modeling.
     
    My uncle also wrote some of the early Mac games, including "Save the Farm", and "Hot Air Balloon". I actually have the original apps and amazingly they run on my 2010 iMac with an emulator.
     

     
    Last year, as we began development of Leadwerks3D, I bought my first Apple products in my adult life, including a 27" iMac, iPhone 4, and iPad 2. I've been really impressed with the quality and design of these products, and although I am not quite sure their OpenGL 3.2 drivers are there yet, I think high-end graphics on Mac has a good future. (I had it confirmed from another developer that OpenGL 3.2 MRTs do work on Mac, so I still have some experimentation to do. I suspect the multisampled texture format I am using may be causing a problem...) Ever since I started putting out videos of our new engine running on mobile devices, there has been a tremendous response from developers, both inside the Leadwerks community and beyond.
     
    I think the rise of the iPhone as a gaming device was sort of accidental. They had a device that could run apps, then they discovered people were playing games more and more on them. However, all indie game developers should be grateful Apple developed a thriving ecosystem for third party developers, because without them I don't think we would see the resurgence of indie game development like we have. Even if you are developing primarily for Android, you have to admit that platform would not be as good as it is without the influence of iOS.
     

     
    In a sea of mediocrity, one man cared about his work enough to make sure that everything his company put out was a cohesive reflection of his tastes and standards. I don't agree with every decision Apple has made, but I have a great deal of respect for the way Steve Jobs had a coherent vision and brought it to life, instead of just blindly reacting to what he thought would make money. He rejected the "low quality, low confidence, low price, low effort" approach the rest of the tech industry has taken, and won. Without him I think Leadwerks would be without what I think will be our most successful platforms, and indie game developers would not have the same opportunities that are present today. We should all be grateful for that.
     


     

    http://www.youtube.com/watch?v=uwOjsYNcUW0
  16. Josh
    So after about three weeks of pain and frustration, I have successfully calculated my first path using Recast navigation. This has been a new experience for me. I've implemented half a dozen low-level C++ libraries, and never had any serious trouble, but Recast Navigation is something else.
     
    The technology underlying Recast is impressive. First they take triangle geometry, convert it to voxels, then calculate navigation, and convert it back into rough polygons. You can read about the process in more detail here:
    https://sites.google.com/site/recastnavigation/MikkoMononen_RecastSlides.pdf
     
    The results seem pretty reliable, and although the speed of regenerating a tile is slow, it can be done on a separate thread and doesn't have to be updated all that often. I have two criticisms of the library.
     
    First, the code is a total mess. I can't complain too much since it's a free library, and I definitely appreciate Mikko putting it out there, but integrating it into the engine was a hellish process. I wouldn't even call Recast a code library so much as it is an open-source program. The amount of work it took to figure out what was going on was far beyond any library I have worked with, and it could have been wrapped up into a set of much simpler commands (which is what my end result was).
     
    Second, I believe converting polygons to voxels and back is the technically wrong way to go about this. Constructive solid geometry is perfect for navmeshes, autogenerated or otherwise. It would be very fast to generate. It could be dynamically updated quickly. The results would also be 100% accurate virtually all the time. However, it would require all navigation geometry to be modeled with CSG, and although I would be fine with that, I know others will want to use arbitrary polygonal geometry. So that's one thing I would do different if I were making an engine for just myself. There's an example of why you need to be flexible with your goals sometimes.
     
    Still, it's great to be able to build navigation data for any scene and make a character walk around in it without any waypoints or ray casts. Below is my very first result with Recast. There's some obvious strange results with the path, but the point is that it's working, to some extent. It's a minor miracle I am able to plot any kind of path at all. The hard part is done, and I'm sure I'll get any remaining issues ironed out pretty quickly:

     
    Building AI features right into the engine will give us better integration than using a third-party add-on, or trying to build it on top of the engine. First example, we can use physics geometry instead of visual polygons, and make the engine automatically invalidate and update sections of a map when objects move. This will give you powerful AI features that work perfectly with the rest of the engine, so you can control characters with just a few lines of script code. When this is done, it's reasonable to expect to be able to program something like Left 4 Dead in just a couple hundred lines of script (or less, if you just feel dragging some premade scripts around and attaching them to entities).
     
    Once the pathfinding is all tidied up, it will be a big moment, because it means at that point I will know everything I need to finish Leadwerks3D! When setting out with Leadwerks3D, the things I hadn't done before were what I was most worried about. I attacked the unknown issues first. Now that we are coming to the end of this long research and development phase, all that remains is a lot of hard work. It's all stuff I have done before, so I expect the remaining tasks to go pretty quickly. It's also pretty awesome to have a clear picture of how this massive piece of technology all works...four platforms, with rendering technology stretching from fixed-function graphics all the way to Shader Model 5 hardware tessellation...plus the easiest art pipeline ever and a script and flowgraph system that no one has ever done. The scope of this engine is just so much bigger than anything I have ever done, and it actually works! B)
  17. Josh
    I fixed our AI navigation problems and got pathfinding to work using navmeshes. Now you can easily make a horde of zombies chase after the player without setting up any waypoints. Which is the whole point of this, of course.
     
    The problem had to do with a polygon filter, and I am still not sure what is going on, so I disabled it for now.
     


  18. Josh
    I'm testing the Leadwerks3D AI navigation and getting some interesting results. I'm not sure why it's acting this way, but we'll get it figured out soon. It seems like the navigation gets "stuck" on corners, fails to enter some tiles, and likes to take the scenic route to some destinations. B)
     


  19. Josh
    I got touch input and text rendering working on Android. Happily, I have not encountered any issues with different behavior on any tested OpenGLES devices, including iOS. The framerate on my HTC Evo jumps around quite a bit, which appears to be an issue with the Java garbage collector. Framerate on iOS is a solid 60 FPS, so we should be able to get this sorted out.
     
    Here's a video:
    http://www.leadwerks.com/werkspace/page/videos/_/leadwerks-engine-3/android-progress-r100
     
    I also discovered that LuaJIT for ARM processors was recently released. This is fantastic because it means Lua script will run on Android and iOS at about the same speed as C# and Java. I knew this would eventually be supported, but I didn't know until yesterday it was released about a month ago.
     
    We've had a surprisingly strong positive response from developers over our support for mobile platforms, especially Android. This feedback has been coming from both the Leadwerks community, as well as other places like Google+. My estimation is there's probably ten times as many people interested in mobile game development as there are interested in PC development. Since Android especially is going to be an important platform for us to support, I've decided to implement an OpenGL 2.0 renderer, and make that a higher priority than the OpenGL 1 fallback I originally planned. Leadwerks Engine 2 used OpenGL 2.1, but this will be a much simpler renderer that just matches the functionality of the mobile renderer, so you can get the exact same pixel output across all supported platforms. Expect to see something about as capable as the Half-Life 2 engine.
     
    Of course, the OpenGL 3.2/4 renderer will still be available on Windows. At this time, Apple's OpenGL 3.2 drivers are not functional, but when they are it will be no problem to enable the OpenGL 3 renderer for Mac computers as well. (Tim Cook: Please see bug report #9896622.)
  20. Josh
    I've implemented multitouch input on iOS, and gave Aria the information he needs to do the same for Android devices. Multitouch is an interesting input method. Each "touch" has a beginning, some movement, and an end. To handle multiple touches, they need to be persistent; you need to keep track of which touch is which. This is a little weird if you're coming from a mouse and keyboard paradigm.
     
    On iOS, you have a pointer to a UITouch object, and on Android it's a jObject object (I think). I opted to make touches correspond to fingers...the first touch is touch 0, the second is 1, and so on. I set it to handle up to five touch inputs simultaneously. (Interestingly, there doesn't seem to be any limit on the number of touches a device can handle at once. At least, I tried ten, and ran out of fingers to test any further.)
     
    Touches emit an event which you can get through the event queue, or you can supply an event callback hook. Alternatively, you can just call GetTouchDown(), GetTouchHit(), GetTouchX(), etc., which work the same as mouse input. The only difference is you need to supply an index for the finger number.
     
    To implement zooming, I just checked to see if finger 0 and 1 are touched, then found the distance between the two fingers. I'll have to write some detailed tutorials about this, but until then here's my code:

    while (PeekEvent()) { Event event = WaitEvent(); Print(event.Debug()); switch (event.id) { case EVENT_KEY_DOWN: if ((event.data)==KEY_ESCAPE) { return false; } break; case EVENT_WINDOW_CLOSE: if (window==event.source) return false; break; case EVENT_TOUCH_UP: numTouches--; break; case EVENT_TOUCH_DOWN: numTouches++; Print("Event.data = "+String(event.data)); Print("Event.X = "+String(event.x)); Print("Event.Y = "+String(event.y)); Print(""); touchposition[event.data].x = event.x; touchposition[event.data].y = event.y; dx = touchposition[0].x - touchposition[1].x; dy = touchposition[0].y - touchposition[1].y; touchdistance = sqrt(dx*dx+dy*dy); break; case EVENT_TOUCH_MOVE: if (event.data==0) { if (numTouches==3) camera->Move(-(event.x - touchposition[0].x)*0.01,(event.y - touchposition[0].y)*0.01,0); touchposition[0].x = event.x; touchposition[0].y = event.y; dx = touchposition[0].x - touchposition[1].x; dy = touchposition[0].y - touchposition[1].y; d = sqrt(dx*dx+dy*dy); if (numTouches==2) camera->Move(0,0,-(touchdistance - d)*0.01); touchdistance = d; //Print(touchdistance); } if (event.data==1) { touchposition[1].x = event.x; touchposition[1].y = event.y; dx = touchposition[0].x - touchposition[1].x; dy = touchposition[0].y - touchposition[1].y; d = sqrt(dx*dx+dy*dy); if (numTouches==2) camera->Move(0,0,-(touchdistance - d)*0.01); touchdistance = d; // Print(touchdistance); } break; } }
    And here's the result in action:


  21. Josh
    After some initial difficulty, Leadwerks3D is now running on Android, with the exact same code that runs on iPhone, iPad, Windows, and Mac. A big thanks for Aria for all his help and expertise with the Android platform. This means Leadwerks3D is now running on all platforms we intend to support at launch, and it can be easily extended to support new ones.
     


     
    To celebrate, here's another cartoon I drew:

  22. Josh
    Here's the code:

    Print("context = "+GetObjectAddress(context)); Print("Graphicsdriver: "+GetObjectAddress(graphicsdriver)); Print("GetGraphicsdriver: "+GetObjectAddress(GetGraphicsDriver())); Print("ActiveGraphicsDriver: "+GetObjectAddress(ActiveGraphicsDriver)); Print("context->graphicsdriver: "+GetObjectAddress(context->graphicsdriver)); Print("context = "+GetObjectAddress(context));
    Here's the output, running on an iPhone 4:

    context = 0x06921400 Graphicsdriver: 0x0694e800 GetGraphicsdriver: 0x0694e800 ActiveGraphicsDriver: 0x0694e800 context->graphicsdriver: 0x0694e800 context = 0x06921400
    Here's the output, running on an HTC Evo 4G:

    08-30 11:34:02.319: INFO/LEAndroid(8250): context = 0x00270168 08-30 11:34:02.319: INFO/LEAndroid(8250): Graphicsdriver: 0x0026f0d8 08-30 11:34:02.319: INFO/LEAndroid(8250): GetGraphicsdriver: 0x0026f0d8 08-30 11:34:02.329: INFO/LEAndroid(8250): ActiveGraphicsDriver: 0x0026f0d8 08-30 11:34:02.329: INFO/LEAndroid(8250): context->graphicsdriver: 0x30203a72 08-30 11:34:02.329: INFO/LEAndroid(8250): context = 0x002704dc
    On the Evo, even printing out the object hex address twice will result in two different values:

    Print("context = "+GetObjectAddress(context)); Print("context = "+GetObjectAddress(context));
    Nothing else to say at the moment. Will let you know when I find out what is going on. B)
  23. Josh
    Lately I've been talking a lot about making non-programmers happy, so here's something for the coders. B)
     
    For Leadwerks3D documentation, I considered three possibilities:
    -IPB-based docs
    -Wiki
    -Offline CHM files
     
    Each has their own strengths and weaknesses, as always seems to be the case.
     
    IPB
    A bit slower, harder to organize, harder to edit, looks really good and consistent with the site, search requires quite a few clicks to get where you want to go, missing table of contents is a bummer for long pages.
     
    Wiki
    A target for spam, doesn't match the main website, user-written docs cause fragmention and a mix of official and unnofficlal information, nice table of contents, good searchability.
     
    Offline CHM
    Fast, doesn't require internet connection, easy to edit, Windows-only.
     
    I dismissed offline docs simply because we wouldn't be able to post a link to refer people to a certain page. I decided on a wiki because of the better search functionality, table of contents, and ease of editing.
     
    Here's what I have in mind for the docs. Because Leadwerks3D is written in C++, we're able to document members, constructors, operators, and other stuff we haven't had access to in the past. Best of all, almost everything works exactly the same in Lua, including function and operator overloading.
    http://www.leadwerks.com/newwiki/index.php?title=Vec3
     
    I'm also a big fan of the ease with which we can add internal links. For example, the Vec3 members in the AABB class documentation link straight to the Vec3 class page:
    http://www.leadwerks.com/newwiki/index.php?title=AABB#Members
     
    To avoid spam, and to make sure I can answer any questions about the contents of the wiki, it's going to be read-only. Community tutorials have been very useful in the past, and we're going to continue that going forward, either through a subforum or database for Leadwerks3D tutorials.
     
    I think having one page per command and an example for every single command has been more redundant and time-consuming that we have needed. I want to list the syntax for each command only once, like this:
    http://www.leadwerks.com/newwiki/index.php?title=Entity#SetPosition
     
    Instead of making a lot of redundant examples (Do we really need a page of code for Entity::SetPosition() AND Entity::SetRotation()?) I hope to provide more comprehensive examples showing how to actually do something, and how the functions can be used together to do interesting things.
     
    In general, I want to go into much more depth with the Leadwerks3D documentation, on all aspects of using the program, because I plan for this iteration of our technology to have a pretty long life. If you have any suggestions, just let me know.
  24. Josh
    It doesn't happen to me much anymore but when I get stuck on a difficult problem, I get very restless and short-tempered. I guess that's the point where most programmers give up on a project. Since I can't physically wrestle code to the ground and give it a good beating Billy Batts style, the fight or flight response probably is not conducive to sitting in front of a piece of glass and figuring out code. On the other hand, I have a tendency to get difficult things done, no matter how hard they are. Maybe a more patient programmer in the same situation would be too patient to produce useful output under his own volition.
     
    My understanding of how recast works is it turns upwards-facing triangles into a grid, then uses that grid to construct a navigation mesh. The results seem very robust, but the fundamental approach is an approximation. It is possible to construct a perfectly accurate navigation mesh out of CSG solids, because they have volumetric properties an arbitrary polygon soup does not. On the other hand, my instinct says people will prefer an approximation that works with any arbitrary geometry over a mathematically correct solution that requires constructive solid geometry.
     
    Another approach is to simply let the user construct the navigation mesh in the editor. Since the pieces need to be convex, a CSG editor is ideal for this. This also has the possibility of adding more advanced functionality like climbing up walls and jumping. (This is how Left 4 Dead 2 works.) Still, I know people will value a pretty-good solution that works with arbitrary polygon geometry more, and that gets into a land of approximations I don't really have any experience with. I suspect it would involve a lot of adjustments and fine-tuning to get the desired results.
     
    You can see here, the results are definitely an approximation, but they're a pretty good one:

     
    So here are the options I am looking at:
    1. Hire someone with existing knowledge of recast to write the implementation.
    2. Find someone with existing knowledge of recast and work off their knowledge to write the implementation myself.
    3. Stare at incomprehensible code for days on end and hope that somehow imparts knowledge of how to use the library. Maybe other people can understand this, but I am awful at deciphering other people's code.
    4. Write my own polygon-based solution.
    5. Write my own CSG-based solution.
     
    I think the CSG-based solution is the best technical choice, but I think it would cause a lot of complaints. It's fine for Valve, but I think a lot of people would just get mad if I tried to explain why arbitrary triangle meshes have no volumetric properties.
     
    Another frightening thing about recast is that from what I am reading, a lot of people are using the demo application as a tool to generate their navmesh data, and just loading the saved files that produces in their own game. That's completely unacceptable. We need to be able to generate this data in our own editor. I know it's possible, but the lack of people able to do this is an indication of the difficulty of the task.
     
    The pathfinding stuff is actually the last bit of research I have to complete before I know how everything in Leadwerks3D works. The rest is just a matter of hard work, but all the unknown factors we started with will be resolved.
     

  25. Josh
    To make an entity in Leadwerrks3D behave, you can drag a script from the asset browser to the actors list in the entity properties editor. Each entity can have multiple scripts attached to it. Each script can have different variables exposed, with control for the GUI they are displayed in. For example, you can specify upper and lower limits of a spinner or a list of choices for a drop down box. Each script attached to an entity, along with its set of properties, is called an "actor" because...it acts.
     
    To handle the interaction of different actors, a flowgraph is used. You can drag actors from the entity properties editor into the flowgraph editor. Each actor has inputs and outputs defined in its script. You can connect the output of one actor to the input of another. For example, you can connect the "tick" output of a timer script to the "Resume" output of a mover script, to make the mover translate and rotate an entity at regular intervals when the timer ticks:


     
    I hope this makes it more clear how entity interactions can be handled in Leadwerrks3D, even without programming. With this system, we're all working on one big game together, and we can share functional objects without any difficulty.
×
×
  • Create New...