Jump to content

Josh

Staff
  • Posts

    23,140
  • Joined

  • Last visited

Blog Entries posted by Josh

  1. Josh
    A new update is available on the beta branch on Steam. I've merged the OpenGL2 and OpenGL4 graphics driver classes into a new class called simply "OpenGLGraphicsDriver". Everything should work, but let me know if you find any behavior changes between 4.2 and this new beta.
     
    OGG support has also been added, thanks to MartyJ's help. The following header search paths must be added to C++ projects:
    ..\..\Source\Libraries\libogg\include
    ..\..\Source\Libraries\\libvorbis\include
    ..\..\Source\Libraries\\libvorbis\lib

  2. Josh
    Another build is available on the beta branch on Steam.
    Fixed zip import behavior. Fixed physics swept collision bug, waiting for confirmation this fixed other reported problems. Kinematic joint rotation not fixed yet. Updated to Steamworks 1.41 Updated to latest version of OpenVR Code::Blocks C++ project not updated yet. We're getting close to release, so your reports (especially the ones with examples!) are appreciated.
    Instructions for updating C++ projects are available here:
    https://www.leadwerks.com/community/topic/16838-upgrading-44-c-projects-to-45/
     
  3. Josh
    A new build is available on the beta branch on Steam.
    Fixed Kinematic joint rotation (thanks Julio!) Fixed FlushKeys / FlushMouse not working on Linux. I'm still having trouble compiling with the latest version of Code::Blocks / GCC:
    https://www.leadwerks.com/community/topic/14663-compile-problem-on-ubuntu-1604-using-codeblocks-c
     
  4. Josh
    Version 4.5  is updated on the beta branch on Steam.
    Fixed small projection error in VR mode. Added fog settings in editor and into map file format. Fixed Workshop browser back button not working. Added VR project template. Added VR player script Added friction to hinge joint script. Added ball and slider joint scripts. Joint scripts will now use the entity parent for the other joint connection (if it exists). We've only got about 24 hours to test this out before the release and there seems to be some problems compiling on Linux, at least for some people. I will be working hard to get this resolved for the big release. Thanks for your help!
  5. Josh
    The beta branch has been updated with a new build of version 4.5 beta.  VR support is implemented and documented here:
    https://www.leadwerks.com/learn?page=API-Reference_Object_VR
    Linux C++ projects will currently not build in the beta (working on it now).
    See this thread on updating your C++ projects:
    https://www.leadwerks.com/community/topic/16838-upgrading-44-c-projects-to-45/
     
  6. Josh
    An update is available on the beta branch on Steam that adds support for multiplayer games with the following features:
    NAT punch-through with relay server fallback. Connectionless peer-to-peer UDP messages with multiple channels and optional reliable flag. Public server list of available games to play. Voice-over-IP for in-game chat (and taunts). The new multiplayer system will open up a new range of game types that can be easily created with Leadwerks Game Engine.
    These features are still being tested and are only available in the Windows build right now.
  7. Josh
    Wow! We crossed the 50% mark in less than a week. At this point, the campaign has shown enough strength that I am willing to begin allocating resources to the development of Leadwerks for Linux. (To be clear, we will only deliver a Linux product if the entire target amount is met.) Kickstarter has been fantastic because it allows us to gauge demand before we do the hard work of supporting a new operating system, so we can figure out in advance whether it's worthwhile. Fortunately, it appears there's a lot of Linux users (and people who would like to move to Linux) who want native game development tools for Linux.
     

     
    We're able to develop Leadwerks for Linux at a relatively low cost because our game engine and editor were designed from the start to be cross-platform compatible. We abstract away any OS-specific code. When porting to a new platform, we just need to replace those OS-specific bits, and past a certain point the rest of the engine will just work. The image below shows how I visualize the code base:
     

     
    It's interesting that as popular technology is becoming more locked-down, from the Windows 8 closed app store to the increasing DRM requirements of the new consoles, people are responding by showing a new interest in open systems like Linux and Valve's upcoming SteamBox. I'm a hardcore PC gamer, and it's disappointing to me how Microsoft has treated games on Windows like an unwanted child for so long. Games could be the niche Linux uses to gain greater market share. Many people have told me that Leadwerks running natively on Linux would be the last application they need to stop dual-booting and switch completely over to Linux.
     
    So let's make it happen!
  8. Josh
    In Leadwerks Engine 3, you can load a script and attach it to any entity. You can attach multiple scripts to any entity, and they will be called in the order they were attached. Right now, I am calling the script-side table "actor" because it is a little more descriptive than "object" but I'm not sure about all the syntax yet. Below is a sample script for a sliding door. When you attach this to a model, the script will control its behavior:

    ----------------------------- -- Sliding door script ----------------------------- --Attach this to any entity to turn it into a sliding door. --You can make the door move in any direction by adjusting the movement vector. --When the door opens or closes, a one-shot noise will play, along with looping --sound that will continue until the door comes to rest. --expose Sound opennoise --expose Sound closenoise --expose Sound movenoise --expose Sound stopnoise --expose Vec3 movement --expose function Open --expose function Close function actor:Start() if self.movement~=nil then self.openposition = self.entity.position + movement self.closeposition = self.entity.position end end function actor:Open() if self.openstate==0 then self.movestate=1 --Play one-shot noise, if it is set if self.opennoise~=nil then self.entity:EmitSound(self.opennoise) end --Play looping move noise if it is set if self.movenoise~=nil self.movesource = self.entity:EmitSound(self.movenoise,true) end end end function actor:Close() if self.openstate==1 then self.movestate=-1 --Play one-shot noise, if it is set if self.closenoise~=nil then self.entity:EmitSound(self.closenoise) end --Play looping move noise if it is set if self.movenoise~=nil self.movesource = self.entity:EmitSound(self.movenoise,true) end end end function actor:Update() local d local l if self.movestate~=0 --Calculate the difference between where we are and where we should be if self.openstate==1 d = self.openposition - self.entity.position else d = self.closeposition - self.entity.position end --Check to see if there is any difference l=d:Length() if l>0 then --Limit the difference if it is greater than the move speed of the door l = d:Length() if l>self.movespeed d = d:Normalize() * l end self.entity:Move(d,false) else self.movestate=0 --Disable looping noise source if it exists if self.movesource~=nil then self.movesource:Stop() --Play one-shot stop noise if it exists if self.stopnoise~=nil then self.entity:Emit(self.stopnoise) end end end
    Lua is pretty flexible, so I can make it work pretty much any way we want. When designing stuff like this, I find it's best to start with what the end user wants, and then work your way backwards to make it happen. What do you think?
  9. Josh
    Below you can see LeadwerksGUI running nicely on Ubuntu. Once we get through the window and event code, the GUI code acts exactly the same on Linux and Windows. The behavior of the widgets is reliable and double-buffered rendering makes the appearance perfectly solid. Image loading is not working yet, but you can see the vector graphics are working perfectly.
     

     
    Leadwerks GUI will provide a smoother user experience on Linux and give us cross-platform UI consistency across all operating systems.
  10. Josh

    Articles
    I've been wracking my brain trying to decide what I want to show at the upcoming conference, and decided I should get the new editor in a semi-workable state. I started laying out the interface two days ago. To my surprise, the whole process went very fast and I discovered some cool design features along the way.
    With the freedom and control I have with the new user interface system, I was able to make the side panel extend all the way to the top and bottom of the window client area. This gives you a little more vertical space to work with.
    The object bar on the left also extends higher and goes all the way down the side, so there is room for more buttons now.
    The toolbar only spans the width of the viewport area, and has only the most common buttons you will need.
    Right now, I am showing all files in the project, not just game files. If it's a model or texture file the editor will generate a rendered thumbnail, but for other files it just retrieves the thumbnail image from Windows for that file type.

    All in all I am very pleased with the design and pleasantly surprised how quickly I am able to implement editor features.
  11. Josh
    I'm starting to get terrain integrated into the Leadwerks 3 editor. For the most part, it stays pretty close to the design of the terrain tools in Leadwerks 2, and you should have no trouble figuring it out. I'm implementing the critical features first: This will be added into version 3.0 before the release of 3.1.
     

     
    As I described in my previous blog, my goal is to take all the lessons learned from Leadwerks 2 and come up with something more refined and powerful.
  12. Josh
    C++11 introduces shared pointers, a powerful language feature that provides easy memory management without the overhead of garbage collection.  The example below should look familiar to you:
    #include "Leadwerks.h" using namespace Leadwerks; int main(int argc, const char *argv[]) { shared_ptr<Leadwerks::Window> window = Leadwerks::Window::Create(); shared_ptr<Context> context = Context::Create(window); shared_ptr<World> world = World::Create(); shared_ptr<Camera> camera = Camera::Create(); camera->SetRotation(35, 0, 0); camera->Move(0, 0, -6); shared_ptr<Light> light = DirectionalLight::Create(); light->SetRotation(35, 35, 0); shared_ptr<Model> model = Model::Box(); model->SetColor(1.0, 0.0, 0.0); model->SetPosition(-4, 0, 0); while (true) { if (window->Closed() || window->KeyDown(Key::Escape)) return false; Leadwerks::Time::Update(); world->Update(); world->Render(); context->Sync(); } //Everything will get automatically deleted when we return from this function return 0; } Using the auto keyword simplifies everything (and it makes this code compatible with Leadwerks 4):
    #include "Leadwerks.h" using namespace Leadwerks; int main(int argc, const char *argv[]) { auto window = Leadwerks::Window::Create(); auto context = Context::Create(window); auto world = World::Create(); auto camera = Camera::Create(); camera->SetRotation(35, 0, 0); camera->Move(0, 0, -6); auto light = DirectionalLight::Create(); light->SetRotation(35, 35, 0); auto model = Model::Box(); model->SetColor(1.0, 0.0, 0.0); model->SetPosition(-4, 0, 0); while (true) { if (window->Closed() || window->KeyDown(Key::Escape)) return false; Leadwerks::Time::Update(); world->Update(); world->Render(); context->Sync(); } //Everything will get automatically deleted when we return from this function return 0; } Now things get interesting.  This function would normally cause a horrible memory leak, but with shared pointers everything is fine:
    void SaveTexture(shared_ptr<Texture> tex) { auto bank = Bank::Create(tex->GetMipmapSize()); tex->GetPixels(bank->buf); bank->Save("pixeldata.dat"); } Yet shared pointers can still equal nullptr:
    auto bank = Bank::Create(); bank.reset(); Debug::Assert(bank==nullptr); You can even simply set a shared pointer to nullptr, and if that was the last pointer that referenced it, it gets deleted!
    auto bank = Bank::Create(); bank = nullptr;// auto deletion here! How to Delete an Entity
    The code below will not delete the entity, because a shared pointer is still stored in the world.
    auto entity = Pivot::Create(); entity = nullptr; The entity must be have its world set to NULL, and the shared pointer must be set to NULL or go out of scope:
    entity = Pivot::Create(); entity->SetWorld(nullptr); entity = nullptr; Children use a weak pointer to the parent, so they will not cause self-referencing.
    Asset Management
    You no longer have to worry about calling Release() when loading assets:
    auto material = Material::Create(); auto texture = Texture::Load("mytex.tex"); material->SetTexture(texture); texture = nullptr; Unused assets will automatically be deleted if they go out of scope:
    auto material = Material::Create(); auto texture = Texture::Load("mytex.tex"); material->SetTexture(texture); texture = nullptr; material = nullptr; But if they are in use, they will be retained in memory:
    auto material = Material::Create(); auto texture = Texture::Load("mytex.tex"); material->SetTexture(texture); model->SetMaterial(material); texture = nullptr; material = nullptr; In conclusion, shared pointers automate many of the tasks we have been doing manually with the Leadwerks reference counting system and the AddRef and Release commands.
  13. Josh
    Previously, I talked a little bit about shared pointers in C++11.  These use automatic reference counting to track how many variables are pointing to an object.  When the object is no longer being used, it is automatically deleted.  This is similar to garbage collection, but doesn't involve the massive overhead of garbage-collected systems.  In fact, shared pointers simply automate something we were already doing with the Release() and AddRef() commands in Leadwerks 4.
    A weak pointer is like a shared pointer, but having a weak pointer to an object does not prevent the object from being deleted.  Weak pointers are a great way to handle situations that previously could have resulted in an invalid pointer.  Let's say you have an AI class for an enemy in your game that stores an entity it is attacking:
    class Monster : public Actor { int health; weak_ptr<Entity> target; virtual void UpdateWorld(); }; To make use of the weak pointer, we convert it into a shared pointer.  At that point, the temporary shared pointer will prevent the object from being deleted:
    void Monster::UpdateWorld() { shared_ptr<Entity> enemy = this->target.lock(); if (enemy != nullptr) { //do some stuff } } If something causes the monster's target entity to be deleted, the program will work just fine without having to go through and find all variables that point to that entity.
    You can check if a weak pointer's object has been deleted with the expired() command, since creating a new shared pointer involves a certain amount of overhead:
    void Monster::UpdateWorld() { if (!this->target.expired()) { shared_ptr<Entity> enemy = this->target.lock(); if (enemy != nullptr) { //do some stuff } } } However, you still need to perform the check to see if the resulting shared pointer is nullptr/NULL because theoretically another thread could have caused the object to be deleted right after the expired() call returns false.
    If you want to clean up a list of weak pointers as you discover expired pointers, you can structure it like this:
    auto it = items.begin(); while (it!=items.end()) { auto item = (*it).lock(); if (item != nullptr) { item->Update(); it++; } else { items.erase(it++); } } If we add in the optional expired() check, it gets kind of complicated, but this is not something you should really need to do much:
    auto it = items.begin(); while (it!=items.end()) { if (!(*it).expired()) { auto item = (*it).lock(); if (item != nullptr) { item->Update(); it++; } else { items.erase(it++); } } else { items.erase(it++); } } Here's a real example in the Leadwerks source code.  The LEADWERKS_5 preprocessor definition is used to modify behavior in 4/5.  In version 4 the list contains pointers, and in version 5 it contains weak pointers:  Version 4 could get complicated because the entity would have to store an iterator to remove it from this list, in case it is deleted before this routine is called inside the World::Update() function.  In version 5 we just check if the weak pointer is valid and skip it if the entity was deleted.  At the end of the routine, the whole list is cleared, so there are no worries about deleting each iterator.
    bool World::UpdateNavigation() { //Invalidate navmesh tiles that intersect moved entities for (auto it = updatenavigationlist.begin(); it != updatenavigationlist.end(); it++) { #ifdef LEADWERKS_5 auto entity = (*it).lock(); if (entity == nullptr) continue; #else auto entity = (*it); #endif entity->updatenavigationneeded = false; for (int i = 0; i<entity->relevantnavtiles.size(); i++) { entity->relevantnavtiles[i]->Invalidate(); } entity->relevantnavtiles.clear(); if (entity->navigationmode) navmesh->InvalidateTiles(entity->aabb); } updatenavigationlist.clear(); //Update the navmesh return navmesh->Update(); } Weak pointers make game programming easier and less susceptible to errors in Leadwerks Game Engine 5.
  14. Josh
    It's been an eventful year.
    A new beautiful website has been rolled out, and our community software is updated to the latest version of Invision Power Board, which allowed us to move all file storage to Amazon S3 for basically free unlimited storage space for the site. Documentation moved into a new easy to use system. The Games Showcase was created. We had a totally kick-*** Halloween Game Tournament. Announced the development of Leadwerks 5, added unicode support, 64-bit build, and smart pointers, and am almost ready to release the first alpha. Finally release The Zone with the help of @AggrorJorn Released LeadwerksGUI Released the Steamless Enterprise Edition, which NASA bought some licenses for. And of course now you can make VR games with all versions of Leadwerks. Here's where I messed up:
    Taking a year to ship out the winter game tournament posters. The process for international shipping has actually gotten a lot easier as you can fill out all the information and print a label online now, which is a lot easier. I'm not going to say anything about a new tournament this year until a couple weeks have passed so people can actually get their goodies from the last one! Behind the scenes I have been working on a big super-secret project (not Leadwerks 5), but I don't know 100% if this is going to go through or not, so at this time I can't say anything about it.
    With everything that's going on I feel like we are in an in-between state right now, between the last big thing and the next. The rollout of Leadwerks 3/4 taught me a lot of things I can use for 5. But for now, more waiting is required before I decide my next move and how I am going to go about this.
    By the way, Merry Christmas everyone!
  15. Josh
    This is a rough timeline of events I am planning in the new year. It is not complete, and may change, but this is just what I am thinking right now.
    January 15: Release Leadwerks 5 Alpha Zero subscription February 1: Launch Kickstarter campaign for development of Leadwerks 5 Alpha One February 1: Game Tournament March 3: Kickstarter campaign complete April 1: Leadwerks 4.6 released (vehicles, NAT punch-through) June 30: Summer Games Tournament June 30: Roll out Steam Workshop replacement August 1: Deliver Leadwerks 5 Alpha One One thing I really want to see is a multiplayer community project. Multiplayer games allow for much more interesting gameplay because your opponents are smart. It's easy to make fun variations of different game types. And it's easy to make contributions like a new map, a new weapon, or a new game type (as opposed to creating a whole new game).
    This is very fun for me because I actually got my start in computer software by making mods for the original Quake. You can still download "Checkered Flag - Gold Cup" mentioned here, by "Lucid Designs". I was not a programmer on this, I was a level designer. I don't see any of my maps in it though so I don't know if that exists anywhere:
    http://www.quaketerminus.com/addon.shtml

    IGN took down our old page for the mod. This is one of the reasons I want everyone to upload their games to the Games Showcase, so they will be preserved forever.
    To make networking work I am working on a NAT punch-through system right now.
  16. Josh
    Last week Valve founder and CEO Gabe Newell took to the stage at LinuxCon and proclaimed that "Linux is the future of gaming". Gabe talked about Linux gaming capabilities and promised to unveil something "on the hardware side" the following week. Today, Valve announced the upcoming release of SteamOS, a living-room operating system designed specifically to compete directly with the XBox, Playstation, and Wii console ecosystems. SteamOS will being openness to the console gaming world. This will have a lot of benefits for indie game developers:
    Console game development will no longer require expensive fees to publish and update games. If you can get your game on Steam, it can go on a console.
    Hardware manufacturers can compete to deliver better Steam-powered consoles. Gaming hardware will never again stand still for nearly ten years (as it did with the last generation of consoles).
    Steam-based game consoles will be backwards compatible and future-proof. Games you buy now on Steam will still be playable on consoles three generations in the future.

    I am very excited about this development and the future of open console gaming. Leadwerks will be available for SteamOS as soon as possible.
     

     

    Tech Progress
    The Leadwerks 3 engine has been successfully compiled for Ubuntu 13.04. However, when running the application, all I saw was a blue screen. I decided to focus on the OpenGL 4 deferred renderer for a while. While working out the depth reconstruction for the deferred renderer, I realized I was making unnecessary calls to glDepthRange(), which weren't needed at all. After removing these calls my depth reconstruction code worked correctly; this was the cause of the errors I experienced when developing a for GDC 2013. I also believe the calls to glDepthRange() were what caused the engine to not render anything when running on Ubuntu, though I won't know for sure until I try it out. 
    Leadwerks 3.1 features an OpenGL 4 deferred renderer with support for up to 32x MSAA. I was able to get this running in just a few days. I already had parts of the OpenGL 4 renderer done, and I've been working with deferred renderers since 2008, so it all came together quickly. It's easier today to write a deferred renderer for a couple of reasons.
     
    First, the state of OpenGL and driver support has gotten much better. Leadwerks 2 was written against the OpenGL 2.1 specification, which was not designed for deferred rendering. I relied on many vendor-specific extensions (some of which changed behavior halfway through the engine's life). OpenGL 4 was specifically designed for the type of things I am doing with it, so I am no longer fighting the spec. If a graphics driver has a problem, it's easier to get it fixed today than a few years ago, now that the rest of the industry has realized the benefits of deferred rendering.
     
    Second, hardware today is much more powerful than when Leadwerks 2 was developed. Leadwerk 2 was written for GEForce 8800-level hardware, and used a lot of optimizations to favor speed over quality. With modern hardware I don't have to rely on so many hacks and I can push the upper limits higher. For example, Leadwerks 2 used a random edge jitter that gave a grainy approximation of soft shadow edges. With Leadwerks 3 I can increase the blur kernel and display beautiful soft shadows that look more like an offline cg render than real-time graphics:
     

     

    Leadwerks Shwag Surfacing
    Leadwerks Shwag is beginning to appear in the real world. Post your photos of you modeling a stylish Leadwerks shirt or sticker so the rest of the community can see! 

  17. Josh
    With Luabind, it turns out we don't even need a table associated with an entity. We can just add values and functions straight to Lua's representation of that entity in the virtual machine! So instead of this:

    object.health=100 object.entity:SetPosition(1,2,3)
    You can just do this, which is much nicer!:

    entity.health=100 entity:SetPosition(1,2,3)
    So there's no object/actor nonsense, you just work directly with the entity itself.
     

    Entity Keys
    The Get/SetKey convention from Leadwerks Engine 2 is going away, to be replaced with more direct entity access functions. You can still store "keys" with strings, but this will directly set the values of the entity table in Lua, so they can be access from script more easily:
    void Entity::SetString(const std::string& name, const std::string& value); std::string Entity::GetString(const std::string& name); void Entity::SetFloat(const std::string& name, const float& value); float Entity::GetFloat(const std::string& name); void Entity::SetInt(const std::string& name, const int& value); int Entity::GetInt(const std::string& name); void Entity::SetObject(const std::string& name, Object* o); Object* GetObject(const std::string& name);
    Here's a sample "mover" script that performs simple movement and rotation each frame:

    function entity:Start() self.movespeed=Vec3(0) self.turnspeed=Vec3(0) end function entity:Update() self:Move(self.movespeed) self:Turn(self.turnspeed) end
    And this is how we would set an entity up in C++ to turn 2 degrees on the Y axis each frame:

    Entity* box = CreateBox(); box->AttachScript("Scripts/Entity/Mover.lua") box->SetObject("turnspeed",Vec3(0,2,0))

    Getters and Setters
    LuaBind does support getter and setter functions, and I decided it would be nice if we could have an object-oriented command set for the surface commands (even though vertices are NOT an object-oriented structure, at all!). If I can get vectors to be accessible in Lua, then we will be able to write code like this script, which performs a "breathing" effect on any model, ala Quake 3 Arena:
    function Entity:Start() this.speed = 1 this.amplitude = 0.1 end function Entity:Update() local n,v.d --Make sure this is a model entity before calling commands if this.class = CLASS_MODEL then --Get the distance the vertex should move d = math.sin(AppTime() * speed) * amplitude - amplitude --Apply movement to all vertices for n = 0,this.surface:length()-1 do for v = 0,this.surface[n].vertex:length()-1 do this.surface[n].vertex[v].position += d * this.surface[n].vertex[v].normal end end end end

    Multiple Script Attachments
    This is a very tricky thing to handle, because the behavior is so hard to define. Right now I have it set up so predefined functions will be called, in order of their attachment. As for user-defined functions, that's a lot hard to pin down. If two scripts contain a function called "Kill()", and the script itself calls the function, should both functions be called? It will take more time and testing to see how this should work. A big problem is if the user defines a function that returns a value, and two scripts contain the same function. If another script calls the function, what should be returned? So then I start thinking about separate spaces for each script attachment, with their own set of members and functions, and I realized how incredibly hard to understand that would be, if you were accessing this entity from an outside script.  
    In the absence of any compelling technological advantage, simple is best. For now, only the predefined functions get executed in sequence, and none of those return a value. My prediction is multiple script attachments will be used primarily by non-programmers who just want to combine a few behaviors and see results without touching any code. When you get into more complex behvior I think script programmers will generally use one script per entity that does what they want.
     
    It's still only 1:30 in the afternoon, so I am going to go get lunch and spend the rest of the day working bug reports. The model reloading issue that's active is a tough one. There's also a PHP issue uploading files to the site, so I will try to get that resolved.
  18. Josh
    I generally categorize every aspect of Leadwerks as either "absolutely required" or not necessary. If it's categorized as the latter, I don't bother with it, and if it's categorized as the first, I pursue it with a dogged determination until it is done. This has served us well in many ways, like our vegetation rendering system and character controller.
     
    However, this assumes I have full control and mastery over the product, or at least have someone working for me who does. This is almost always the case with software development. I do not have the same power over other aspects of Leadwerks like the website. Our bug reporting system, based on IP.Tracker, was an unsupported unofficial add-on offered by Invision Power Services. That means they offer it, but if anything goes wrong you are on your own. This should have steered me away from using it. I generally never use any third-party add-ons, especially free ones, but the features were nice and it was compelling. (The one exception in our system is our chat system, which has functioned wonderfully, but also came with a fairly high price tag. Correlation?)
     
    After installing IP.Board 3.2, I attempted to install the new Tracker that works with it, but the installation process would not work. I even got IPS to look at it, despite their policy of this being a non-supported product, but their "fix" was quickly done and didn't actually fix it. I could keep pestering them, but I've already spent a lot of time on it, and we're never going to get a real solution. Even if it could be installed successfully, a new problem could arise at any time, and we'd be back in the same position as before. The application hasn't been updated since August of last year even though there are outstanding bug reports. Despite all it's complexity, there's really no other forum/CMS that comes close to the features IPB offers.
     
    Anyways, the point of my long-windedness is that I'm giving up on upgrading IP.Tracker and created a bug report sub forum here:
    http://www.leadwerks.../59-bug-reports
     
    The data is all in the database still, and there's a possibility we might be able to migrate it into the forum, but I honestly wouldn't count on it. The value gained per unit effort is getting very bad if I keep going down this road.
     
    Additionally, the new IP.Gallery application is so badly designed I consider it unusable. Even before the upgrade, people frequently posted images in the Showcase forum rather than deal with the complexity of managing albums and uploading images into different categories. I have implemented a custom system here we have complete control over. I encourage you to re-post your images here where they will be safe, and I have complete control over the layout and design:
    http://www.leadwerks...ce/page/gallery
     
    I have posted a few images there to test with. If I posted one of your images and you would like to re-post it in your own name, I will gladly remove my upload. Additionally, the latest images will soon be added to the Portal page, mixed in with the latest videos thumbnails. A link to the old gallery will remain at the bottom of the Gallery page until April 1, 2012 so you can access your images.
     
    This is a complex site, and I am operating it with a minimal amount of IT support. Going forward, we are going to implement a few policies to minimize problems.
     
    1. No third-party applications or features will be utilized, with the exception of our chat bar, which is a paid third-party product that has always functioned perfectly.
     
    2. When a custom database can serve our purposes, that will be preferred over third-party applications and even some official IPS applications. For example, I implemented a custom database for the video section, articles, and replaced IP.Gallery with our own system. (I do not have any plans for any additional databases or website features in the near future.)
     
    The upgrade to the latest version of IP.Board was well worth it, in spite of those couple of problems. First, it would have been very difficult to find a designer capable of and willing to work with the old version. Second, the new system cleans up a lot of the functionality of the older version, which oould be quite chaotic in some places. Finally, it ensures we are up to date if any security issues should arise. There hasn't ever been any, and I have no reason to believe there will be, but it's best to be prepared. IPB 3.1+ was really an infant product compared to the more mature version 3.2. Further versions of the system are not expected to be such drastic changes, as the feature set and design has solidified quite a lot.
     
    Thank you for your patience and especially for generating all the great content that makes this site so fun to browse.
  19. Josh
    I'm really shocked by how fast C++ can be. iOS and Android do not support GPU skinning, so I had to implement vertex-weighted skinning on the CPU. It took about a day to get running, and then I started optimizing code.
     
    My test case was an 8400 polygon model. Each vertex could be attached to as many as four bones, but most just used two or three bones. To make it more interesting, I put the vertex weighting code inside a loop so it would be performed ten times instead of once.
     
    When I started, the process took 23 milliseconds. I replace OO math code with procedural (including some inline functions), reduce the number of dynamically allocated objects, and make looping code as small as possible.
     
    One interesting thing I did was merging four float variables in a loop into a single float array. Instead of resetting each variable to 0 in each iteration of the loop, I did a single memcpy() from an array of zeroes I created just for this purpose.
     
    Before:

    position[0]=0; position[1]=0; position[2]=0; sumweights=0;
     
    After:

    memcpy(position,nullarray,16);
     
    This actually resulted in a very big speed increase!
     
    The Result
    By the time I was done, my stress test was executing in 4-5 milliseconds. The program now renders an 8400 skinned model at 1000 FPS, which I thought was impossible with CPU skinning.
     
    We're still going to implement GPU skinning in our high-end PC renderer, but the CPU skinning will be good for mobile devices and older hardware.
     

  20. Josh
    Last week I travelled to Seattle for a few days to lay some groundwork for the future of Leadwerks Software. During the week I tried out Valve's VR hardware, visited a gassification plant, and survived a trifecta of astrological phenomenon.

    Steam VR
    Although I attended Steam Dev Days, I did not get a chance to demo Valve's virtual reality hardware. I was invited by one employee to come back and check it out, so I decided to take them up on that offer last week. 
    Valve's VR is improved over the Oculus Rift because it has higher resolution screens, lower latency, and positional tracking. The combination of these factors are enough to push the stimulus over the tipping point to where your brain accepts it as reality. Donning the headset immediately transported me to another plane of existence. If Oculus Rift felt like looking through a Viewmaster, Steam VR was like plugging into the matrix. In fact, it was so real that it felt very alarming to look down and not have a body. I was led through a series of demos that were incredible and disturbing at the same time. At one point I was looking in a mirror at a levitating box with two hemispheres for eyes that mimicked the rotation of my head. The sense of disembodiment was alarming in a very visceral way. I never experienced anything like this with Facebook's less convincing VR technology. The Oculus Rift was interesting, but never raised existential questions in my mind.
     
    Positional tracking inserts you into the scene and gives you a sense of space relative to objects. Objects in the foreground are especially real because you can move around them and see them up close from all angles. 3D modeling for virtual reality is going to be different from modeling for conventional 3D games. Small details need to be actual geometry, not just details baked into a normal map, or else they look like painted plywood. Because of the sense of space, small enclosed areas actually make a better setting for VR than large expansive fields, where your sense of position is diminished.
     
    At one point I was face to face with a massive 20-foot tall model of a robot from Portal 2, and I felt the size of it in a way I simply wouldn't from an image onscreen. The positional tracking made the scale seem absolutely real. I stared up at it from below, and I knew at that point that VR is going to be huge. I'm still convinced I was actually there. I have the memory of that experience. It was just as real as the room I'm in now as I type this.


    Gas Works
    In college I took a trip to visit some friends who moved to Seattle. (They moved there because they thought it would be fun, and we were all Nirvana / Soundgarden / Pearl Jam fans in high school.) That was my first visit to the emerald city. While there, we visited Gas Works park, the former site of a "gassification plant" where I presume they manufactured steampunk memorabilia:
     
    I was inspired by the heavy industrial structures and the name stuck with me, and it influenced the naming of Leadwerks Software. I'm starting to feel like the Joker with my explanations of where the name comes from ("Did I ever tell you how I got these scars?...") but the fact is that I remembered the park but forgot the name until I saw it on a poster last week. And then I had come full circle. Gas Works. Leadwerks. Seattle. It all made sense, and I knew this is where the company belongs.
     
    The Seattle area is home to Amazon, Microsoft, Valve, and 200 game studios. Not only are video games a major area industry, but PC gaming is very strong here. As a result, I don't have to explain to people what Steam is. I don't have to explain to them what a mod is. I attended a TechCrunch event Thursday night and my suspicions were confirmed. Conversations were easy and everyone knew right away what I was talking about. The opportunities that fit our particular strengths are to be found here. As of July, the company is relocating to Seattle.

    Friday the 13th and the Strawberry Moon
    My flight departed Seattle at 1:40 P.M., on what happened to be Friday the 13th. After an uneventful boarding we sat on the tarmac waiting to take off, when the captain announced the plane was low on hydraulic fluid. A few minutes passed and they announced the maintenance crew was checking a problem, and they would let us know if we were cleared to take off. They then announced we were returning to the boarding area and would be delayed. At this time I decided to adopt a new policy: I don't fly on planes that have known mechanical issues. I requested to reschedule my flight and took the next one home. My original flight did depart and arrive safely, as I figured it would, but in the face of incomplete information I'm not one to take stupid chances. Apparently Friday was also a full "strawberry moon" and a guy who worked at a coffee shop in the airport told me that Jupiter is doing some weird stuff. He was a barista after all, so I figured I should listen to him. I arrived safely that night on another flight. A strange end to a pivotal week.
  21. Josh
    Lighting is nearly complete. and it is ridiculously fast! There are still some visual glitches to work out, mostly with lights intersecting the camera near plane, but it's nearly perfect. I turned the voxel tree back on to see what the speed was, and to check if it was still working, and I saw this image of the level partially voxelized. The direct lighting shader I am using in the rest of the scene will be used to calculate lighting for each voxel on the GPU, and then bounces will be performed to quickly calculate approximate global illumination. This is fun stuff!

  22. Josh
    The Model class is being slightly restructured to add support for built-in LOD without the need for separate entities. Previously, a list of surfaces was included in the Model class itself:
    class Model { std::vector<shared_ptr<Surface> > surfaces; }; This is being replaced with a new LOD class, which allows multiple lists of surfaces containing less detail to be stored in the same model:
    class LOD { std::vector<shared_ptr<Surface> > surfaces; }; class Model { std::vector<LOD> lods; }; To iterate through all surfaces in the first LOD, you do this:
    for (int i = 0; i < model->lods[0].surfaces.size(); ++i) { auto surf = lods[0].surfaces[i]; } To iterate through all LODs and all surfaces, you do this:
    for (int n = 0; n < model->lods.size(); ++n) { for (int i = 0; i < model->lods[n].surfaces.size(); ++i) { auto surf = lods[n].surfaces[i]; } } In the future editor, I plan to add a feature to automatically reduce the detail of a mesh, adding the simplified mesh as an additional LOD level so you can automatically generate these.
    How this will work with our super-efficient batching system, I am not sure of yet.
×
×
  • Create New...