Jump to content

Josh

Staff
  • Posts

    23,313
  • Joined

  • Last visited

Blog Entries posted by Josh

  1. Josh
    Sometimes I run into situations where I don't really know how to structure things. I don't mind this, because it usually results in some really elegant design once I figure out what to do. I just play with ideas and try not to force anything, and when the right idea arises, I will recognize it.
     
    Explaining a problem to someone else can help facilitate that process. How many times have you solved a difficult problem right after you posted a description of it on a forum somewhere? The procedure of explaining it logically to someone else can help you think more clearly about it. And so, we have today's blog topic.
     
    Below is a very rough start to the script editor. The syntax highlighting system was written about a year ago, and works beautifully, using the native text widget on both Windows and Mac.

     
    In the Leadwerks3D source code, there is a base class called an "AssetEditor". From this class the material, model, shader, texture, font, and script editor classes are derived. Like the other asset editor windows, only one instance of the script editor window will be allowed open at any time. Unlike the other asset editor windows, which display only one asset at a time, the script editor will use tabs to display multiple files. Scripts aren't a typical asset like a material or a model, so it's fine for them to behave a little differently.
     
    Any Leadwerks3D application can have its Lua state debugged. The engine uses networking commands to communicate with a debugger on a specified port. This means the engine can communicate with a debugger whether it's part of a C++ program, C# app, or standalone Lua interpreter. The debugger can display the Lua callstack and shows all variables and values in the Lua state, including full examination of C++ objects and members!
     
    I do not intend for Leadwerks3D to "play a game" in the editor. We've tried that approach and there are a lot of problems. I want Leadwerks3D to be a very solid and stable level editor, with a visual interface to do everything you need. I also want better consistency between Lua and C++ programs. Therefore, Leadwerks3D will use a run game system more similar to 3D World Studio than the Leadwerks Engine editor. A dialog will allow you to choose the application to run, command-line parameters, and other settings. These will be saved between sessions, so you can hit a key to do a "Quick Launch" and run your game. It would be possible to hook the Lua debugger into any application as it is launched, which could be very helpful.
     
    Let's go back to the script editor now. My inclination is to have F5 launch an interpreter and call the script for the currently selected tab. However, I don't think it's a good idea to use multiple game launch modes, I already described a uniform game launch mode for both Lua and C++ applications, but that seems sort of counter-intuitive if you are working in the script editor and just want to run something really quickly.
     
    There;s also the question of whether we want to provide a standalone script editor and debugger outside of Leadwerks3D. Or should the debugger be a standalone application as well, since someone might want to use it with a C++ application? You see there are a lot of options and a lot of possible ways to set this up.
     
    What about Lua compile errors? I can print that out in the engine log, but how will the editor display it? If a compile error occurs, should the program pause and display the line it occurred at? What if the user just doesn't care, and wants the program to keep going?
     
    Alternatively, the user may want to just hit F5 in the script editor and check for basic syntax errors, which the command LuaL_LoadString() will detect.
     
    That's pretty much all my questions at this point. I don't expect anyone to come along and solve my problems, but the process of describing and discussing the issues will help me come to a resolution.
  2. Josh
    I finished the collision editor, and now came across a pretty significant design issue. The approach the main editor has always taken is that by the time assets get into it, they are finished and ready for usage. Now I am making it so the model editor can change the structure of a model, save it, and have the main editor reload all instances of it. However, the Lua class scripts cause some problems with this. If I load a model with it's script enabled, the script might delete limbs fromt he model, replace them with other entities, or add new limbs. For example, the monster truck script frees the wheel meshes and creates vehicle wheels in their place. If this is allowed, then the tree view for the model will not be the same as what the GMF file originally contains. If the model is resaved, it will overwrite the existing GMF, and no longer contain the same limbs the script looks for.
     
    I could disable the class script in the model editor, but I also want to be able to view a finished model with the script enabled. For example, if I have a street light with an added corona, I want to be able to look at that in the nice big model editor window.
     
    Probably the best I can do is just leave it up to the end user not to do anything in the script that will break the model if it is resaved. Either that, or we have two separate applications built into the editor: a model viewer, which uses script, and a model editor, which disables the script.
     
    One kind of neat thing I did was set it up so the surface tree nodes only get populated when the user opens them. You might remember early versions of the model editor were slow to load large meshes because a ton of vertex data had to be turned into tree nodes. This will allow full display of all data, but it won't slow down loading. The worst that might happen is a brief pause when a surface node is opened. I'm planning to make all the data in each vertex editable, so you can clean up meshes by brute force, if you choose to. A few options like "Update Normals" will be available on a global and per-surface basis.
  3. Josh
    I sent my mockups off to the designer to create our very own hoodie as a super tournament prize. This garment will come with not one, not two, but three separate printed graphics on a high-quality American Apparel hooded fleece. Here's roughly what it will look like:
     

     
    And here is a t-shirt design for a future production run:
     

  4. Josh
    Documentation is being organized into a built-in help browser. Documentation simply falls into two categories, "Tutorials" and "Commands". Tutorials are laid out in a linear sequence of lessons divided into subchapters. "Commands" displays the command reference, which remains pretty much the same as it is now, with the exception of additional function syntax declarations for Lua. Search and index will be added, but right now I want to focus on content.
     
    The sequence of tutorials is meant to start with zero knowledge of game development or programming, and teach everything you need to know, in the best possible order. It will start with editor usage, move on to simple gameplay without programming, then cover Lua scripting in depth, to the point where you never need to look at the Lua website, and finally end with several simple game examples. This design may change a bit before it's final, as I am not the person in charge of this.
     

     
    Research on code completion in the script editor is being conducted. I'm also getting the legal stuff set up for contracted work..
     
    As for me, I am focusing on the following items right now:
    AMD pure virtual function call. (Not really that can be done except keep hitting F5.)
    Intel FBO error when toggling reflective water on and off.
    Nvidia FBO performance reduction in latest driver.
    Model editor rendering glitch in Linux.
    Scene panel not rendering correctly in Linux with AMD cards.
    Carving.

     
    These are all slow-going items, many of which require coordination with third parties. I decided to do carving before vegetation painting because it is a simpler feature that doesn't require as much testing, whereas vegetation painting is the kind of thing that tends to lead to more feature requests.
  5. Josh
    My last NASA project is complete. There's a physics bug in Leadwerks 4.6 that will get resolved this weekend. Starting Monday I am going to focus on the new engine again and move us forward so we can release in 2020. I am really looking forward to getting back in the game.
  6. Josh
    I've been working to upgrade Leadwerks to the latest Newton Dynamics 3.14, and I want to change it so the engine imports Newton as a DLL. This will allow the Newton developer to debug some of my applications when needed.
     
    World Factions has raised an important bug / issue and this the best route to solve it.
     
    I've been tinkering with some improvements to some of the physics stuff with promising results, but it needs more work and I don't want to say anything else about it yet. If I can get it out in the next two weeks for version 4.2 I will, otherwise I will roll everything back.
  7. Josh
    I've been working on water. It's a challenge to get it to work properly with the post-effects stack and lighting, something I never did quite right in Leadwerks 2. However, the results are turning into the best implementation of water I've ever made.
    Water blends naturally with post-effects stack.
    Water reflection/refraction equation and behavior is improved over Leadwerks 2.
    Water ripples don't have an obvious direction of flow and look very realistic, without looking "wrong" when placed in certain maps (i.e. water flowing sideways against a coastline).

     
    I am not attempting to do 3D ocean waves like in Crysis and some other games. Although these techniques came close to looking real, I feel like they haven't aged well and sit in the uncanny valley and sort of look like saran wrap when in motion. They also aren't as versatile as the water I am making, and only look good in some specific types of settings.
     
    Here's a WIP image with a bunch of post-effects applied to make sure everything works right together.
     

     
    I also met with Valve and asked them to add a desktop version of the in-app purchase dialog for user items. This will allow other users to easily purchase the items you publish for use with Leadwerks.
     

  8. Josh
    Some of the Leadwerks Game Engine design was originally developed to run on PC and mobile. In order to supported multiple renderers (OpenGL and OpenGLES) I implemented a system that uses an abstract base class with an API-specific class derived from that:
    Texture OpenGLTexture All OpenGL code was contained in the OpenGLTexture class. This worked fine, and theoretically it would have allowed us to support multiple renderers within one build, like OpenGL and DirectX. In practice it's a feature that was never used, and created a lot of complicate class hierarchies, with functionality split between the base and derived classes.
    In the new engine, all rendering code is completely separated in a separate thread, and we have a separate class that is a stripped-down representation of the object the programmer interfaces with:
    Texture RenderTexture When the programmer calls a command that makes a change to the Texture object, an instruction is added to a queue of commands that is sent to the rendering thread, and their change is also made on that RenderTexture object, although not instantaneously.
    Right now I am stripping out the derived classes and turning classes that were previously abstract into full classes. It's quite a big job to restructure a complex program like this but it needs to be done. Even when we switch over to Vulkan / Metal I don't see us every supporting multiple APIs within a single build, and I am glad to get rid of this aspect of the engine.
    I'm also doing the same thing for physics. An Entity object in the main thread can have a PhysicsNode object that lives in the physics thread. However, this does not get created unless there is some physics command performed on the entity, like setting the mass or adding a collision shape.
    Other stuff I want to change:
    Get rid of GetClass() / GetClassName() method. Get rid of Object::ModelClass etc. constants. Replace all static class constants with global variables, i.e. WINDOW_FULLSCREEN instead of Window::Fullscreen. It's actually best to declare constants with enum because then they get evaluated as a constant and can be used in array declarations and switch statements. It only needs to be declared once, in the header, but unlike a macro it stays contained within the namespace it is declared in:
    enum { MAX_PHYSICS_THREADS = 32 }; The next step is to create a usable programming SDK with models, lights, scene loading, scripting, and physics. This will allow beta testers to actually start developing games. The lack of a visual editor is a challenge, but at the same time we are now using more standard file formats like DDS and GLTF, which gives us better consistency with the output of various modeling programs. I'd like to start looking at a Lua debugger for Visual Studio Code soon. There seems to be some debuggers out there already, but I have no idea how the communication between the debugger and the game is supposed to work. I invented my own network data protocol in Leadwerks and there isn't any standard I am aware of.
    2D graphics in the new engine are quite different from in Leadwerks, which used drawing commands to control what gets displayed on screen. Since the rendering all occurs asynchronously on another thread, this approach does not make sense at all. I also had a problem with the GUI in this design. The GUI system uses a script with a drawing command to redraw each widget, but we don't want any Lua code running in the rendering thread.
    The solution is to make 2D graphical elements persistent objects:
    auto window = CreateWindow(); auto context = CreateContext(window); auto world = CreateWorld(); //Create some 2D graphics auto rect = CreateRect(context,10,10,200,75,true); rect->SetColor(0,0,1); auto line = CreateLine(context,10,10,200,200); line->SetColor(1,0,0); auto text = CreateText(context,"Hello!",0,0,200,75,TEXT_CENTER); text->SetPosition(10,10) text->SetFont(LoadFont("Fonts/arial.ttf",18); while (not window->Closed()) { world->Render(context); } Just like with an entity, you can set the variable to null to stop drawing the element.
    while (not window->Closed()) { if (window->KeyHit(KEY_SPACE)) rect = nullptr; world->Render(context); } 2D elements can have a hierarchy, so you can create one element that gets drawn on top of another:
    auto rect = CreateRect(context,10,10,200,75,true); rect->SetColor(0,0,1); auto rect2 = CreateRect(rect,4,4,rect.size.x-8,rect.size.y-8,true); rect2->SetColor(1,1,1); We need the GUI working for some VR projects I want to use the new engine in soon. Once the items above are all working, that will give us everything we need to start working on the new editor.
  9. Josh
    The general GUI elements for LeadwerksGUI are more or less done, and I have turned my attention to another problem. The LeadwerksGUI system is built around the notion that GUI widgets have a discrete bounding box in which they are contained. All events and drawing occur within these bounds, which are further constrained by either their parent widget's bounds or the area of the window they are created on. However, there are three situations where this paradigm breaks down.
     
    Menus

     
    Window menus expand when clicked on, and the submenu stretches depending on the number of menu items it contains. Furthermore, the menu may extend below the bottom edge of the window. This indicates that the menu itself must be another window that is parented to and moves with the parent. However, clicking on the menu would normally deactivate the parent, which is not the desired behavior. To get around this, I made the window class process return MA_NOACTIVATEANDEAT when a WM_MOUSEACTIVATE event occurs, for this type of window.
     
    Dropdown Boxes

     
    Dropdown boxes are similar to menus. In fact I think the Windows API creates menus as a special form of dropdown boxes. The same rules apply here.
     
    Tool Tips

     
    Tool tips can appear anywhere and can extend beyond the bounds of the parent window. Furthermore, tool tips do not gain the mouse focus and allow mouse events to pass through to the underlying window. At least I think they do. In practice, the tool tip will disappear as soon as you move the mouse off the hovered widget, so it should be impossible to ever click on them anyways. However, I did find a method of allowing mouse events to pass through the tool tip window to the window below. On Windows you can make mouse events pass through a window by returning HTTRANSPARENT when an WM_NCHITTEST event occurs.
     
    So here's an unimpressive shot of a window with another window on top of it (the black rectangle on the top left). It's not visually amazing, but it is working.
     

     
    At this point I know our design will work 100% on Windows, but there is still Linux and Mac support to consider. Stay tuned.
  10. Josh
    It's nice to have my big monster computer back, and everything is just the same as I left it. I have a triple-boot machine with Windows 10 and both 32 and 64 bit versions of Ubuntu 16.04. This is easier than trying to set up multi-arch compiling on one install of the OS, though I look forward to the day I no longer have to bother with it.
    I'm running out of hard drive space on my Windows 10 500 GB SSD so I ordered a 1 TB SSD, and I plan to transfer the 500 GB SSD into my laptop to replace the small SSD it came with. The laptop also contains a terabyte HDD, which was supposed to function as an add-on storage drive, but I am going to install Ubuntu on that. Then I will be able to develop for Windows and Linux on the go, wherever I am. The only thing that would be better than this would be a triple-boot Macbook Pro (maybe someday). Actually, that wouldn't be better. A 17" screen is something I can actually work on, and a 15" screen is no good for programming. So this is the best there is.
    A 3 TB external HD is being used to back up the Amazon S3 bucket (nearly 60 GB now!), and I copied the entire contents of the 32-bit Ubuntu install onto it as a backup. There was 20 or so "special files" the system could not copy so I don't know if it a true backup, but I think I will be okay. I am attempting to do the same with the 64-bit install files running from the 32-bit OS, but so far I keep getting errors during the copy process. I know you can make an image of the disk, but the disk image is the full size of the hard drive, not just the files it contained, and frankly since it is Linux I expect something else will break in the restore process, so I am not worrying about that.
    I'm also porting our SVN repositories over to a new service that offers more storage space, although it is quite a lot more expensive.
    My local Leadwerks working copy has been reverted back to the exact version that was used to release the last build. I'm going to go through manually and re-insert the changes I want from the last six months, because most of the work done was on the new engine. I think there will be less mistakes if I do it this way, since the source got chopped up a lot with #ifdef statements before I finally broke Turbo off from Leadwerks and put it in its own repo.
    The next Leadwerks update will include bug fixes, a new vehicles system, and peer-to-peer networking through Steam.
  11. Josh
    Previously I described how I was able to save the voxel data into a sparse octree and correctly lookup the right voxel in a shader. This shot shows that each triangle is being rasterized separately, i.e. the triangle bounding box is being correctly trimmed to avoid a lot of overlapping voxels:

    Calculating direct lighting using the sparse octree was very difficult, and took me several days of debugging. I'm not 100% sure what the problem was, other than it seems GLSL code is not quite as flexible as C++. I actually had the same exact function working in GLSL and C++, and it worked perfectly in C++ but gave wrong results in GLSL! Of course I did not have a debugger for my GLSL code, so I ended up having to write a lot of if statements and outputting a pixel color base on the result. In the end I finally tracked the problem down to some data stored in an array, changed the way the routine worked, but what the exact issue was I'll never know.
    With the sparse voxel octree, we only have about 400,000 pixels to draw when we process direct lighting. Rendering all voxels in a 256x256x256 volume texture would require 16 million pixels to be drawn. So the sparse approach requires us to draw only 2% the number of pixels we would have to otherwise. Using shadow maps, on a 1920x1080 screen we would have to calculate about 2,000,000 shadow intersections. Although we are not comparing the same exact things, this does make me optimistic for the final performance results. Basically, instead of calculating shadow visibility for each pixels, we can just calculate per voxel, and your voxels are always going to be quite a bit bigger than screen pixels. So the whole issue of balancing shadow map resolution with screen resolution goes away.
    Ray traversal is very fast because it skips large chunks of empty space, instead of checking every single grid space for a voxel.
    The voxel resolution below is not very high, I am only using one octree, and there's currently no blending / filtering, but that will all come in time.

    Leadwerks 1 and 3D World Studio used lightmaps for lighting. Later versions of Leadwerks used deferred lighting and shadowmaps. Being able to roll out another cutting-edge lighting technology in Ultra Engine is icing on the cake for the new engine. I expect this will allow particle shadows and transparent glass with colored shadows, as well as real-time global illumination and reflections, all with great performance on most hardware.
  12. Josh
    We're getting to a point where we need to establish the final directory structure for the new game engine, and start using it. Here's what you see when you open "C:\Leadwerks" (or on Mac, "\Applications\Leadwerks"):

     
    The "Editor" folder contains the editor executable and support files.
     
    The "Engine" folder contains header files, compiles libraries, and BlitzMax include files.
     
    The "Help" directory contains local help files.
     
    The "Projects" directory is where your projects go, by default. Our development project is called "Darkness Awaits". Here's what the directory structure looks like:

     
    We think this design will keep things clean and organized, and be nice to work with.
  13. Josh
    It's pretty clear that constructive solid geometry modeling is a high priority for our community. I like being able to easily sketch out my ideas. In fact, when this feature went away in Leadwerks 2, that was when I just stopped making game levels. It's not that I don't know how to use 3ds Max and other programs, it's just that they're not fun. The upcoming release of Steam Workshop also fulfills my long-held dream of building a shared repository of textures and models scaled correctly to work with CSG mapping.
     
    Today I began some preparatory work, starting with some texture templates:

     
    These are important because they give us a standard template we can line solids up against:

     
    Why does this matter? Well, when we have a standard template for common features, we can design textures that match the geometry, like this plaster wall below:

     
    This is one of the tricks that makes maps look great, and it's easy to set up once you have a standard template.
     
    However, I ran into one big problem. Leadwerks 2 started using a scale of 1 unit space = 1 meter. This makes a lot of sense, because it is easy to measure physics and large distances, as Leadwerks 2 was mostly an outdoors engine. When it comes to texture mapping, however, this scale is not ideal at all! A human being is roughly 1.8 meters tall. That means that 2 meters is just a little over their head, and is too short to place a wall texture on. We can scale the texture up on the surface, as I did in the example AI map, but this will cause problems. The grid in Leadwerks is based on powers of two, and if we scale the texture up to 2.5 meters in size, it's going to be hard to line brushes up precisely against the texture pixels! What to do?!
     
    On the other hand, using a centimeter grid gives a perfect scale. 256 cm is roughly the height of a one-story building's wall, so mapping textures on that scale makes a lot of sense. I realized I could just display a grid in centimeters instead of meters, and it would totally solve this problem, without requiring any rescaling. So I added that setting in the Viewport options and it works perfectly. The door on the left was modeled with the centimeter grid while the one on the right was modeled with the grid measures in meters. Because the grid is power-of-two, the centimeter grid had major grid lines at 2.56 meters, while the meter grid had it at 2.0 meters:

     
    This will not affect your existing maps, but I recommend you start using the centimeter grid for new maps. This preliminary work will allow me to unleash our artists to produce more texture packs for you to use in your maps, and will allow the community to work together more effectively.
  14. Josh
    I spent the day manually setting entry categories in the new documentation database. This was needed to make the docs actually use the nice breadcrumb bar in the website header. Our content management system doesn't exactly support hierarchical pages, so some clever PHP scripting was used to make it work. The whole point is simply to make navigation easier, and it works well. I also wrote some PHP code that does a search and replace with class names, so class names are always links to the page for that class.
     
    Here's the list of classes and commands at this point, weighing in at just under 500 pages. There are some small errors and a couple missing commands, but it's mostly there:
    commands.txt
     
    Have a happy new year, and drive safely!
  15. Josh
    Documentation in Leadwerks 5 will start in the header files, where functions descriptions are being added directly like this:
    /// <summary> /// Sets the height of one terrain point. /// </summary> /// <param name="x">Horizontal position of the point to modify.</param> /// <param name="y">Vertical position of the point to modify.</param> /// <param name="height">Height to set, in the range -1.0 to +1.0.</param> virtual void SetHeight(const int x, const int y, const float height); This will make function descriptions appear automatically in Visual Studio, to help you write code faster and more easily:

    Visual Studio can also generate an XML file containing all of the project's function descriptions as part of the build process. The generated XML file will serve as the basis for the online documentation and Visual Studio Code extension for Lua. This is how I see it working:

    I am also moving all things private to private members. I found a cool trick that allows me to create read-only members. In the example below, you can access the "position" member to get an entity's local position, but you cannot modify it without using the SetPosition() method. This is important because modifying values often involves updating lots of things in the engine under the hood and syncing data with other threads. This also means that any method Visual Studio displays as you are typing is okay to use, and there won't be any undocumented / use-at-your-own risk types of commands like we had in Leadwerks 4.
    class Entity { private: Vec3 m_position; public: const Vec3& position; }; Entity::Entity() : position(m_position) {} It is even possible to make constructors private so that the programmer has to use the correct CreateTerrain() or whatever command, instead of trying to construct a new instance of the class, with unpredictable results. Interestingly, the constructor itself has to be added as a friend function for this to work.
    class Terrein { private: Terrain(); public: friend shared_ptr<World> CreateTerrain(shared_ptr<World>, int, int, int) }; The only difference is that inside the CreateTerrain function I have to do this:
    auto terrain = shared_ptr<Terrain>(new Terrain); instead of this, because make_shared() doesn't have access to the Terrain constructor. (If it did, you would be able to create a shared pointer to a new terrain, so we don't want that!)
    auto terrain = make_shared<Terrain>(); I have big expectations for Leadwerks 5, so it makes sense to pay a lot of attention to the coding experience you will have while using this. I hope you like it!
  16. Josh
    The new docs system is mostly working now:
    https://www.leadwerks.com/learn?page=API-Reference_Object_Entity_SetPosition
     
    Features:
    Treeview list of all tutorials and API classes and functions.
    Alphabetical index (generated automatically from the table of contents).
    Search (with autogenerated search index).
    Switch back and forth between languages, with cookies to remember your preference.
    Entire examples are automatically selected when you click on them.

    Todo:
    Table of contents doesn't yet navigate.
    I would like to pretty-up the URLs using .htaccess rewrite rules.

     
    Documentation is being loaded from XML files. I find this easier than a database, which is quite opaque to me. You can access some of the XML files being used here. MartyJ even made a cool template for the data on his site here.
     
    At this point I think I can outsource the actual content creation to Upwork. This will involve copying and formatting our existing documentation into XML files, as well as updating all the examples to work by just using a main() function instead of the old App() class that we don't really need. I will be posting the job on that site soon.
  17. Josh
    I am happy to show you a preview of the new documentation system I am working on:

    Let's take a look at what is going on here:
    It's dark, so you can stare lovingly at it for hours without going blind. You can switch between languages with the links in the header. Lots of internal cross-linking for easy access to relevant information. Extensive, all-inclusive documentation, including Enums, file formats, constructors, and public members. Data is fetched from a Github repository and allows user contributions. I am actually having a lot of fun creating this. It is very fulfilling to be able to go in and build something with total attention to detail.
  18. Josh
    I've taken your suggestions and incorporated the fixes into the new documentation system here:
    https://www.leadwerks.com/learn
     
    All classes and commands are alphabetized, with classes listed first.
     
    All pages in the API Reference should be working now.
     
    If a page does not appear in the old docs, or if a command does not have an example, it will not appear in the new docs, as I am not changing the content right now.
     
    Please let me know if the table of contents of pages have any errors.
  19. Josh
    Here is the amazing first shot of Leadwerks Engine 3. Behold not one, but TWO triangles! It's a dual display of isosceles inspiration.
     

     
    Believe it or not, this screenshot actually demonstrates a feature that's new for LE3...hardware multisampling. Look carefully at the edges of the triangle:
     

     
    This isn't the first time I've done multisampling, but until now it hasn't been possible to use with deferred rendering. It's now possible to combine these techniques with OpenGL4. You'll have our awesome lighting combined with high-quality 16x antialiasing for raytracer-like graphics. Oh yeah, multiple layers of transparency, each with proper light and shadows, will also be supported.
     
    I ran into problems getting Code::Blocks to import the glew library. Something struck me when I was Googling around for docs. I became aware that most Code::Blocks programmers are probably coding for Linux, and all the examples I read just assumed I was using MS Visual Studio. I didn't give in to the C++ monster just so I could go off on another "non-standard" (if there is such a thing) development route, so I am back on MSVC. I really don't like the poor (or complete lack of) error handling, but I am just going to have to adjust my coding style to this environment. If anyone knows if either the pro version of MSVC or the Intel compiler will stop on the first error and select the line it occurs on, I would gladly pay for that functionality.
     
    As annoying as C++ can be, there are some compelling reasons to write the next iteration of our technology in it. First, I need C++ source code to have something I can sell to professional studios. Second, it is extremely difficult to find programmers willing to work in either BlitzMax or C, and dealing with the interface between BlitzMax and C libraries can get ugly. It's not so technically difficult, but you are doing something in the world no one else is, so there's not any support for it. Having Leadwerks Engine 3 written in pure C++ code allows me to work with other programmers who can handle various tasks like networking, some special effects, and ports to other platforms. It also makes it easier to include external libraries for added features. Finally, only C++ can be used for all the platforms I want to support, including Android, iPhone, XBox, PS3, Wii, etc.
     
    C++ programmers will like this a lot because the LE3 command set allows them more power than they have had before. It's possible to write your own drivers for physics, graphics, device input, and have it all work with the core engine. You can also extends existing classes. This is particularly useful for entity programming.
     
    Should you switch to C++ for LE3? If you've already got another language you're comfortable with, I don't see any reason to. When you are programming a game, flexibility and production efficiency are more important than the raw speed of the final program. Let's say that C++ gave a 25% speed increase over another language. This is probably not realistic, but for the sake of argument let's use that number. That still doesn't mean much, if the user can get a 300% speed increase by switching the GPU or changing some quality settings. So unless you want to support a lot of extra platforms or you just like C++, I don't see any big advantage when it comes to actual game authoring. I need a C interface for use with BlitzMax, because I intend to continue making the editor with that language. Therefore, our policy of allowing you to "code the way you want", with any language you want, will continue.
     
    By the way, Khronos has done a really great job with the design of OpenGL 3.1 and onwards. A few points of interest are that immediate mode rendering is finally done away with:

    glBegin(GL_TRIANGLES); glVertex3f(1,2,3); glVertex3f(1,4,3); glVertex3f(1,2,4); glEnd();
    No more! It doesn't make sense to have three different ways of drawing primitives, and it just makes the drivers overly complicated. You should learn the one right way of doing things, from the start.
     
    Also, the shaders have all the remnants of the old fixed function pipeline cleaned out. The GPU doesn't have a "color array" or a "texcoord array". It just has vertex arrays and you decide what they are, and what format they should be in. So I can do things like compress surface normals into four bytes and not worry about needing the color array for something else.
     
    I didn't get much into it, but it looks like shaders have a nicer implementation of what used to be called "varyings". Variables are just "in" or "out" in the vertex and fragment shaders. Uniforms remain unchanged. I might have a play at geometry shaders, but two years later I am still not sure what they are for, other than something that would have been nice when stencil shadows were popular. Of course, what I am really looking forward to is the OpenGL4 hardware tessellation.
     
    Anyways, I am pretty comfortable with C++, and am happy to be back into graphics, my favorite area of technology. Thanks again to Roland Strålberg for his advice with some C++ details. Have a good week!
  20. Josh
    I got my idea working with spot lights! You can simply use a shadow mode of 2 to indicate an object or light should be considered "static". A light that has the static mode set will use two shadow maps; one for static objects and one for dynamic objects. In the image below, the walls and room are static, and the oildrum has the regular dynamic shadow mode set. As you can see, redrawing the shadow only requires 650 triangles. Without this feature, the whole room and everything in it would have to be redrawn any time something moved!
     



    Best of all, if the light moves or if any static object within the light's volume moves, both the static and dynamic shadowmaps are redrawn. The process is seamless for the end user. Dynamic lighting is usually dynamic, and baked lighting is usually static. I'm not sure what this qualifies as, but one thing is for sure...it's optimal!
     
    This will yield a huge performance increase for scenes with lots of point and spot lights, as long as those lights remain in a fixed position. You should avoid having lots of moving point and spot lights.
  21. Josh
    First, I want to apologize for the server issues we have experienced this week. With the amount of activity we have coming through the site, it is inexcusable to have any downtime.
     
    The server is reverted to the state it was about four days ago. If you have any important information from the last week you want to save, replace the domain name of the url you want to access with "69.163.255.164". For example, here is the link to the blogs on the other server:
    http://69.163.255.164/werkspace/index.php?/blogs
     
    If you click a link on the old server, you will need to change the URL again. This will be left up for a period of one week.
     
    One of the problems we have been trying to resolve has to do with large files being downloaded through the php download system. After looking into this for quite a while, the conclusion I have is it just won't work, and the php download system should not be used for this. We're going to use direct links to download those files until that changes.
     
    We also have some site improvements coming up very soon. It's not a total redesign, but it is a big improvement that maintains the overall look and feel of the site. We also have lots of dynamic content and a new spotlight section that features cool stuff the community is doing. The last step will be to have the forum reskinned to match the site completely, but I want to get the rest of the design solidified first.
     
    We'll soon be offering some additional products on the site, including tools and assets. We're also working on a community marketplace where you can buy and sell digital goods, sort of like the iPhone Appstore. We'll hold a beta of the system first so we can work it out with no real money involved.
     
    Again, I'm sorry for the recent website problems. Werkspace is your site, and we're glad the community values it, so we'll do our best to provide a good experience.
  22. Josh
    I've updated the beta branch (Lua on Windows only) with a new build that solves the DPI scaling issues I previously described. Widget creation still works the same, using the same coordinate system regardless of GUI scale. Widget scripts must use global coordinates in the drawing commands, which means calling Widget:GetPosition(true) and Widget:GetSize(true). Here's the very simple panel script, which simply draws a solid block on the screen to frame child widgets within:

    function Script:Draw(x,y,width,height) local gui = self.widget:GetGUI() local pos = self.widget:GetPosition(true) local sz = self.widget:GetSize(true) gui:SetColor(0.25,0.25,0.25,1) gui:DrawRect(pos.x,pos.y,sz.width,sz.height) end
     
    I've included this script and a simple button to help get you started.
     
    Raster images can be drawn and scaled in a manner that makes them resolution-independent. The idea of loading SVG vector images at any resolution has been floated, and I think it's a good one, though I have no experience with this format. I think it would work similarly to how we treat fonts right now, a vector format that can be loaded into a raster image at any resolution. So this is something I am interested in exploring.
     
    This would give you three tools to perform drawing in the Widget scripts: Leadwerks drawing commands, raster images, and vector images that would be resolution-independent.
     

     
    I've also added the ability to add Widget items. These would be like entries in a list view or a tabbed panel:

    virtual int AddItem(const std::string& text);//lua virtual std::string GetItemText(const int index);//lua
    virtual int CountItems();//lua
    virtual void ClearItems();//lua
  23. Josh
    I've implemented DPI scaling into Leadwerks GUI (beta branch, Lua on Windows only).
     
    To set the GUI scale you just call gui:SetScale(scalefactor). A scale factor greater than one will make it bigger, a scale factor less than one will make it smaller. There is no limit to the range you can set, but negative numbers are probably not good.
     
    Scaling causes the GUI to be drawn at a different size, but widget dimensions and mouse events are still interpreted as though they were at their original size. For example, the mouse move script function will always indicate a coordinate of (510,510) when you move the mouse into the lower-left corner of a 500x500 widget positioned at 10,10, no matter how big or small the GUI is scaled onscreen. Widget::GetWidth() will return the widget's unscaled dimensions, not the actual size it appears at. To get the actual size, you would multiply the dimensions by the GUI scale factor and round off. However, you should never need to calculate this yourself, as all numbers are made uniform for you.
     
    Scaled widget positions are still rounded to integers in order to make them appears precisely on the screen pixels. We don't want sub-pixel blurring with widgets that line up in between pixels, we want sharp clear pixel-aligned rendering. Interestingly, the mouse script functions are now receiving floating point coordinates instead of integers. For example, if you move the mouse across a widget with the GUI scaled to 200% (2.0) you will see the mouse coordinates change in 0.5 increments like 150, 150.5, 151, 151.5, 152, etc.
     
    Scaling presently does not affect text rendering, as this will take more work to figure out how to manage.
     
    Below is a simple GUI scaled at 100%:

     
    Now at 200%. Note that text scaling is not yet implemented. When it is, the text will appear bigger, proportional to the widget. However lines still appear exactly one pixel thick, as they should:

     
    And finally made smaller, at 50%: Notice that although the lines are still one pixel thick, we have lost the space between the inner and outer rectangles. This is being drawn properly, but it is possible you might run into small issues like this in various resolutions, so it's something to keep in mind.

     
    Of course images cannot be upsampled without losing precision, so any images your GUI uses should originally be at the maximum scale your GUI may use.
  24. Josh
    The various parts of the new editor are coming together. Today I got the properties list box drag and drop functionality working. I actually had to go back and rewrite some of the list control rendering code because I haven't used it in a while, but it didn't take long.
     
    I'm trying to attack known unknowns first, so we're focusing on the flow graph, AI, and game logic, and everything required to build up to support that. I've already written a CSG editor and an engine with great graphics, so I know I can do that. Gameplay support is what I want to focus on now before I cover old familiar ground.
     


     
    In other news, it has occurred to me that an OpenGL 2 renderer is needed to provide a PC/Mac equivalent of what the iPhone and Android renderer looks like. Leadwerks Engine 2 uses OpenGL 2.1, but this OpenGL 2 renderer won't be anywhere near as advanced. I'm just going to derive a bunch of classes from the OpenGLES 2 renderer, so we can get as close a match as possible to the Android / iPhone render.
×
×
  • Create New...