Jump to content

Josh

Staff
  • Posts

    23,257
  • Joined

  • Last visited

Blog Entries posted by Josh

  1. Josh
    Here's my list of things left to do:
    Documentation
    Undo system
    Get character models for Darkness Awaits
    Prepare the super secret special surprise for deployment

     
    Undo functionality is my absolute least favorite thing to program, and I also want to get some more real-world testing done before implementing it, so it comes last. This evening I will start on the docs, in earnest.
     
    I hope everyone is having a good near-Christmas week.
  2. Josh
    I got tired of rescaling some models every time I created a new instance of them in the Leadwerks 3 editor, so I added an option to resize the model file itself to the proper dimensions. Double-click the model thumbnail in the asset browser to open it in the model editor. Then select the Tools > Resize menu item. The Resize Model dialog will appear with options to scale by a percentage, or fit to a specific size. For convenience, you can choose the units to use, including centimeters, meters, inches, and feet. Press OK, then save the model, and you will never have to rescale it in the editor again.
     

     
    You can also drag a material into the model editor and drop it on the surface you want to assign it to. When you resave the model, that material will be saved in the new model file. This makes it really simple to assign any pesky missing materials you might encounter when importing a new model.
  3. Josh
    We decided to make one last minute change to the material editor. The texture list is a bit easier to work with now:

     
    Looking pretty nice on Mac, too:

     
    We're also working on our character models for Darkness Awaits, as well as a super secret special surprise...
  4. Josh
    This is the final output of Leadwerks 3 on Windows.
     
    When you choose "Windows" in the Publish dialog, a few options appear. Press OK and your game's installer is created.

     
    The installer looks like this. You can replace the installer images with your own if you like:



  5. Josh
    I'm working on project creation, management, and publishing right now. This is necessary because it automates some steps that would otherwise be very time-consuming.
     
    When you create a project, you can choose the language and the platforms you want it to run on:

     
    You can switch between projects to reload all assets and change the working directory:

     
    You can export a project into a zip file, give it to someone else, and they can easily import it back from the zip, and have it available in the editor on their own computer:

     
    The final step is publishing, which I am still working on. On Windows, this will create a win32 installer program automatically for you, so you can export your game's installer straight from the editor! On Mac, this will create an Apple disk image (.dmg), which is the normal way Mac apps are distributed. On Android and iOS, this will copy all needed asset files to the mobile resource directories, and then give you the option to open Eclipse of Xcode. From there, you can compile the project and have it run on your mobile device right away.
     
    It's interesting that the new art pipeline provides a visual interface to go from an idea to a finished game. I think this will increase the amount of games and projects that get shared in our community, and will generally make the new engine easier and more fun to work with.
  6. Josh
    I've never coded much polygonal modeling routines, instead focusing on constructive solid geometry. I wanted to include some tools for modifying surface normals and texture coordinates. I came up with a normal calculation routine that actually uses four different algorithms, depending on the settings specified.
     
    One thing I learned right away is you want to do away with n*n routines. That is, NEVER do this:

    for (i=0; i<surface->CountVertices(); i++) { for (n=0; n<surface->CountVertices(); n++) { //Write some code here } }
    Instead, I used an std::map with a custom compare function. The comparison function below, when used together with an std::map, allows the engine to quickly find a vertex at any position, within a given tolerance:

    bool SurfaceReference::UpdateNormalsCompare(Vec3 v0, Vec3 v1) { if (v0.DistanceToPoint(v1)<UpdateNormalsLinearTolerance) return false; return v0<v1; }
    At first I was experiencing some weird results where some vertices seemed to be ignored:

     
    I realized the problem was that my map, which used Vec3 objects for the key, were not sorting properly. Here was my original Vec3 compare function:

    bool Vec3::operator<(const Vec3 v) { if (x<v.x) return true; if (y<v.y) return true; if (z<v.z) return true; return false; }
    The above function is supposed to result in any set of Vec3 objects being sorted in order. Can you see what's wrong with it? It's supposed to first sort Vec3s by the X component, then the Y, then the Z. Consider the following set of Vec3s:
    A = Vec3(1,2,3)
    B = Vec3(2,4,3)
    C = Vec3(2,1,1)
     
    When sorted, these three Vec3s should be in the following order:
    A,C,B
     
    If you look carefully at the compare function above, it doesn't give consistent results. For example, A would be less than C, but C would also be less than A.
     
    Here's the correct compare function. Notice I added a second logical operation for each element:

    bool Vec3::operator<(const Vec3 v) { if (x<v.x) return true; if (x>v.x) return false; if (y<v.y) return true; if (y>v.y) return false; if (z<v.z) return true; return false; }
    So with that issue sorted out, the resulting code using std::maps is much, MUCH faster, although it can get pretty difficult to visualize. I think I am a hardcore C++ coder now!:

    void SurfaceReference::Optimize(const float& tolerance) { int i,a,b,c,v; Vertex vertex; bool(*fn_pt)(Vertex,Vertex) = OptimizeCompare; std::map<Vertex,std::vector<Vertex>,bool(*)(Vertex,Vertex)> vertexmap (fn_pt); std::map<Vertex,std::vector<Vertex>,bool(*)(Vertex,Vertex)>::iterator it; int vertexcount = 0; std::vector<Vertex> vertexarray; Vec3 normal; OptimizeTolerance = tolerance; //Divide the surface up into clusters and remap polygon indices for (i=0; i<CountIndices(); i++) { v = GetIndiceVertex(i); vertex = Vertex(GetVertexPosition(v),GetVertexNormal(v),GetVertexTexCoords(v,0),GetVertexTexCoords(v,1),GetVertexColor(v)); if (vertexmap.find(vertex)==vertexmap.end()) { vertex.index = vertexcount; vertexcount++; } vertexmap[vertex].push_back(vertex); SetIndiceVertex(i,vertexmap[vertex][0].index); } //Resize vector to number of vertices vertexarray.resize(vertexcount); //Average all vertices within each cluster for (it=vertexmap.begin(); it!=vertexmap.end(); it++) { std::vector<Vertex> vector = (*it).second; //Reset vertex to zero vertex.position = Vec3(0); vertex.normal = Vec3(0); vertex.texcoords[0] = Vec2(0); vertex.texcoords[1] = Vec2(0); vertex.color = Vec4(0); //Get the average vertex for (i=0; i<vector.size(); i++) { vertex.position += vector[i].position; vertex.normal += vector[i].normal; vertex.texcoords[0].x += vector[i].texcoords[0].x; vertex.texcoords[0].y += vector[i].texcoords[0].y; vertex.texcoords[1].x += vector[i].texcoords[1].x; vertex.texcoords[1].y += vector[i].texcoords[1].y; vertex.color += vector[i].color; } vertex.position /= vector.size(); vertex.normal /= vector.size(); vertex.texcoords[0].x /= vector.size(); vertex.texcoords[1].x /= vector.size(); vertex.texcoords[0].y /= vector.size(); vertex.texcoords[1].y /= vector.size(); vertex.color /= vector.size(); //Add to vector vertexarray[vector[0].index] = vertex; } //Clear vertex arrays delete positionarray; delete normalarray; delete texcoordsarray[0]; delete texcoordsarray[1]; delete colorarray; delete binormalarray; delete tangentarray; positionarray = NULL; normalarray = NULL; texcoordsarray[0] = NULL; texcoordsarray[1] = NULL; colorarray = NULL; binormalarray = NULL; tangentarray = NULL; //Add new vertices into surface for (i=0; i<vertexarray.size(); i++) { vertex = vertexarray[i]; AddVertex( vertex.position.x, vertex.position.y, vertex.position.z, vertex.normal.x, vertex.normal.y, vertex.normal.z, vertex.texcoords[0].x, vertex.texcoords[0].y, vertex.texcoords[1].x, vertex.texcoords[1].y, vertex.color.x, vertex.color.y, vertex.color.z, vertex.color.w ); } UpdateTangentsAndBinormals(); }
    Below, you can see what happens when you use the angular threshhold method, with angular tolerance set to zero:

     
    And here it is with a more reasonable tolerance of 30 degrees:

     
    You can calculate texture coordinates for a model using box, plane, cylinder, and sphere texture mapping. You can also do a pure matrix transformation on the texcoords. The editor automatically calculates the bounds of the object and uses those by default, but you can translate, scale, and rotate the texture mapping shape to adjust the coordinates. Box and plane mapping were easy to figure out. Sphere and cylinder mapping were more difficult to visualize. I first cracked cylinder mapping when I realized the x component of the normalized vertex position could be used for the U texture coordinate, and then sphere mapping was just like that for both X/U and Y/V:

     
    Box mapping is good for mechanical stuff and buildings, but bad for organic shapes, as you can see from the visible seam that is created here. Good thing we have four more modes to choose from!:

     
    You also get lots of powerful commands in the surface class. Here's a little taste of the header file:

    virtual void Optimize(const float& tolerance=0.01); virtual void UpdateTexCoords(const int& mode, const Mat4& mat=Mat4(), const float& tilex=1, const float& tiley=1, const int& texcoordset=0); virtual void Transform(const Mat4& mat); virtual void Unweld(); virtual void Facet(); virtual void UpdateNormals(const int& mode, const float& distancetolerance=0.01, const float& angulartolerance=180.0);
    To conclude, here's some other random and funny images I came up with while developing these features. I think they are beautiful in their own flawed way:

     

  7. Josh
    Leadwerks3D will ship with a finished game demo to demonstrate how to use the software. Darkness Awaits is a third-person dungeon explorer with a 45 degree view. It's like a cross between Diablo and Legend of Zelda: A Link to the Past. This is an idea I had back in my very early days of game development, before I even learned to program. This was originally done in the Quake 1 engine. It didn't really go anywhere, but what we had was awesome. You could run around and shoot skeletons with flaming arrows, in a third-person view. B) My job was actually map design. My favorite part was this cozy little house you started off in with a fireplace and a warm feeling, before going outside into a snow storm to kill monsters.
     
    And so, the project is being resurrected to demonstrate game development with Leadwerks3D. Below are a few possible logo styles. Which is your favorite?
     




  8. Josh
    Apple's problems in iOS 6 aren't limited to maps. Their OpenGL drivers in iOS 6 are absolutely non-functional.
     
    First I was experiencing a BAD_EXC_ACCESS error when rendering certain surfaces. Feedback on the Apple dev forum suggests I am not alone in this. I took a guess and switched my position vertex buffers to use vec4s instead of vec3s, and it appears to have solved that problem (even though both should be fine).
     
    Second, all 3D objects just stopped appearing, completely. I've debugged it to the point of absolute barebones, and still can't get anything to show up...but only on the iPad 3 device itself. My iPhone 4 (also running iOS 6.01), the iOS simulator, and even my HTC Evo all appear fine, running the same code.
     
    My guess is that the Apple driver team was given a directive to get the speed of their graphics chip up to be competitive with the latest 12-core NVidia Tegra, and that they gained speed by fine-tuning the drivers for specific applications they were testing with, at the expense of compliance with the OpenGL ES specification.
     
    In a world where the graphics device performance between all targeted hardware can vary by 1000x, compliance with the OpenGL spec is paramount. Performance at the cost of reliability is not an option.
     
    I also have come to the conclusion that OpenGL is just a fundamentally flawed API. Programmable shaders have been around since 2003-ish, and the vendors still can't write drivers that work. I take this as an indication that the OpenGL specification is just too complicated.
     
    Anyways, this is one of my more emo blogs, and I will solve the problem, but that's where I'm at today. Considering the amount of non-working **** we deal with on both Android and iOS, it's clear to me that for most developers, cross-platform development is just infeasible. I'm glad we can figure this stuff all out for you, so you can just use our API and not worry about all the mistakes third parties make with their APIs, drivers, and tools.
  9. Josh
    In my previous blog I talked about the Android file system and APK package system. The end result was I copied all the project assets into the res/raw folder. However, I learned two additional things that changed my plan a little:
    Android files can only be lower-case.
    Any folders in the res/raw folder will not get copied...it just packs in the files in that directory, with no sub-directories!

    That's a big problem if we want Leadwerks to be able to load files the same on each operating system,but I came up with a solution. In the asset copy step, took the asset files and gave them a random name like "jfuendjhgdjkhfndlrhgjfkd". I stored their original path and their new nonsensical path in a text file. When the engine starts, it reads this text file and sets the files up in a virtual file system, so calling Model::Load("Models/Characters/Goblin.mdl") will load the gobbly-gook file behind the scenes, and the user will never know the difference.
     
    This is implemented and it works right now. I'm going to try to automate the final publishing step as much as possible to save everyone time.
     
    I also learned how to change the name of the Android application so we can just auto-generate the Eclipse project for you based on the values you enter in the project creation wizard.
  10. Josh
    Today I am working out the file system for Android applications. In the past we just manually copied all our assets to a "/Leadwerks" folder on the device itself. This approach is okay for testing, but it won't work for distributing apps in the Google Play store.
     
    Android uses APK files to store all applications in. An APK file is really just a ZIP file, and all your assets go in a /res/raw directory in the ZIP package.
     
    To access the Android file system from C++, we had to take the following steps:
     
    1. Retrieve the file path to the application APK file (with Java).
    2. Pass this file path to C++.
    3. In C++, load the APK file as a standard zip package.
    4. Change the current directory to the APK folder path + "/res/raw".
     
    All this occurs before the App::Start() function is called, so as soon as you start, you're ready to access all the files your game needs.
     
    It's nice when things work out neatly like that.
  11. Josh
    Here's my list, as it stands today:
    Lua Interpreter project for iOS and Android (iOS is done, Aria is working on Android)
    Improve flowgraph visual style (will finish today, probably)
    Documentation (Chris is filling out the syntax, then I will go in and write descriptions)
    Brush rendering batches (to make editor rendering faster)
    Brush collapse on load (in engine only)
    Undo system

  12. Josh
    Since you guys are my boss, in a way, I wanted to report to you what I spent the last few days doing.
     
    Early on in the development of Leadwerks 3, I had to figure out a way to handle the management of assets that are shared across many objects. Materials, textures, shaders, and a few other things can be used by many different objects, but they consume resources, so its important for the engine to clean them up when they are no longer needed.
     
    I decided to implement an "Asset" and "AssetReference" class. The AssetReference object contains the actual data, and the Asset object is just a handle to the AssetReference. ("AssetBase" probably would have been a more appropriate name). Each AssetReference can have multiple instances (Assets). When a new Asset is created, the AssetReference's instance count is incremented. When an Asset is deleted, its AssetReference's instance counter is decremented. When the AssetReference instance counter reaches zero, the AssetReference object itself is deleted.
     
    Each different kind of Asset had a class that extended each of these classes. For example, there was the Texture and TextureReference classes. The real OpenGL texture handle was stored in the TextureReference class.
     
    Normal usage would involve deleting extra instances of the object, as follows:

    Material* material = Material::Create(); Texture* texture = Texture::Load("myimage.tex"); material->SetTexture(texture);// This will create a new instance of the texture delete texture;
     
    This isn't a bad setup, but it creates a lot of extra classes. Remember, each of the AssetReference classes actually get extended for the graphics module, so we have the following classes:

    Asset Texture AssetReference TextureReference OpenGL2TextureReference OpenGLES2TextureReference
     
    The "Texture" class is the only class the programmer (you) needs to see or deal with, though.
     
    Anyways, this struck me as a bad design. Several months ago I decided I would redo this before the final release. I got rid of all the weird "Reference" classes and instead used reference counting built into the base Object class, from which these are all derived.
     
    The usage for you, the end user, isn't drastically different:
     

    Material* material = Material::Create(); Texture* texture = Texture::Load("myimage.tex"); material->SetTexture(texture); texture->Release();// Decrements the reference counter and deletes the object when it reaches zero
     
    In the Material's destructor, it will actually decrement each of its texture objects, so they will automatically get cleaned up if they are no longer needed. In the example below, the texture will be deleted from memory at the end of the code:

    Material* material = Material::Create(); Texture* texture = Texture::Load("myimage.tex"); material->SetTexture(texture); texture->Release(); material->Release();// texture's ref count will be decremented to zero and it will be deleted
     
    If you want to make an extra "instance" (not really) of the Asset, just increment the reference counter:
     

    Material* material = Material::Create(); Texture* texture = Texture::Load("myimage.tex"); texture->IncRefCount();// increments ref count from 1 to 2 Texture* tex2 = texture; texture->Release();// decrements ref count from 2 to 1
     
    This makes the code smaller, gets rid of a lot of classes, and I think it will be easier to explain to game studios when I am trying to sell them a source code license.
     
    Naturally any time you make systemic changes to the engine there will be some bugs here and there, but I have the engine and editor running, and mistakes are easy to find when I debug the static library.
     
    I also learned that operation overloading doesn't work with pointers, which i did not know, but had never had a need to try before. Originally, I was going to use operation overloads for the inc/dec ref count commands:

    Texture* tex = Texture::Create();//refcount=1 tex++;//refcount=2 tex--;//refcount=1 tex--;// texture would get deleted here
     
    But that just messes with the pointer! So don't do things like that.
  13. Josh
    I am going to share my tips on how to be a great programmer, or anything else for that matter.
     
    The first thing you need to do every day is eat properly. I recommend the following:
     
    Breakfast
    2 pieces of toast (whole wheat bread, the heavier the better).
    One banana or orange.
    Finally, eat pure egg whites until you can't eat anything more. They have no cholesterol, no fat, they are pure protein, and they will give you tons of energy.

    Lunch
    Get a deli sandwich. Chicken, turkey, and occasionally roast beef are good. Avoid pastrami or anything with a ton of cheese or grease.

    Dinner
    Salmon fillet. This has the Omega-3 fats you need to be smart.
    Rice for carbs.
    Salad or grilled vegetables.

    Additionally, you should take a multivitamin to make sure you get any nutrients you missed during the day.
     
    The second thing you need to do is go running every day. Two miles is good enough to get a decent workout, but short enough that it can be repeated daily. Start gradually, if needed. It will make a big difference in how you feel every day.
     
    It is perfectly possible to skip these things for a short time, but as soon as you start eating junk food like pizza and soda, you will find you won't have the energy to run. Then you will lose the energy to prepare proper meals, and start falling back on more prepackaged convenience food, which will make you more tired, and you will cycle downwards into lethargy.
     
    Are you depressed or tired? Unless you are following my regiment above, you really have no excuse. Try this for three weeks and then see how you feel. Together, we can make the Leadwerks community healthier and more productive.
  14. Josh
    It's November 1, and this is the longest summer I can remember in a while. Jokes about the seasons aside, last week I had trouble deciding what to do first, so I decided to attack the remaining tasks I was most scared of. This has been my strategy throughout the entire process, and it results in my work becoming progressively easier as we near the finish line.
     
    I finished one big task today that was holding us back. We need a file system watcher for Mac computers to detect changes to the file system. That way when files are created, deleted, modified, or renamed, the editor can detect the change and automatically reconvert and reload assets. This feature allows you to keep Photoshop open and work on a texture, while Leadwerks will display your changes instantly every time you save the file.
     
    I started by asking a few questions on the Mac developer forum on Apple's website. I found one method of doing this with an event stream, but that wasn't recursive. Finally I built some code off the Objective-C example here:
    https://developer.ap...nts/_index.html
     
    Objective-C is frightening (perfect for Halloween!), but after this experience I feel slightly less afraid of it. Once I got the code working, I found that Mac FSEventStreams only give you a folder path; they don't tell you which exact file changed, or whether it was created, deleted, renamed, or modified. Going back to the editor side of things, I added some code that reads the directory structure at startup and stores the file time for each file. Some clever code analyzes a folder when an even occurs, and then is able to emit events based on whether a file was changed, created, deleted, etc.
     
    So what's left to do? Well, here's my exact list:


    Lua Interpreter project for iOS and Android
    Improve flowgraph visual style
    Documentation
    Recursive rendering (like LE2 uses)
    Restructure asset class (I did something stupid here that can be improved)
    Brush rendering batches (to make editor rendering faster)
    Finish skinning in OpenGL ES renderer (copy and paste, mostly)
    Undo system

    And what we finished recently:
    Move project over to VS 2010 (Chris)
    FileSystemWatcher for Mac (today)

    I'm heading down to the hacker lab tonight to talk to the co-founders there. Catch me in Left 4 Dead 2 past about 9 P.M. PST if you want to kill zombies for a round.
  15. Josh
    So inexplicably, two days ago animation stopped working on all my Mac machines. I checked out the graphics module, looked in the surface class, the animation routine, and couldn't fine anything wrong. The same code ran fine on Windows, and all the animation is on the CPU, anyways, so it couldn't be a graphics issue.
     
    I noticed if I explicitly set the frame number instead of using the time as the frame, it worked fine. So I start printing out the frame number in the animation routine. The frame the user specifies gets modulated by the frame count and that final number is used to determine an upper and lower frame, which get blended in between and used as the final orientation.
     
    The final frame numbers were negative, meaning they were being read from well outside the array of animation data. This is because modf can returns a number between -n and +n, where n is the modulus. This only came up because on Windows, time is returned as a 32-bit integer, which then gets converted to a float value for the frame number, so it is always positive. Macs return a 64-bit long integer which can result in a negative float value, which then resulted in a negative frame index. (Time::GetCurrent returns a long value for this reason.)
     

     
    I fixed my own Math::Mod() function to account for negative results, and everything works fine now.
     
    Just a little bit further.
  16. Josh
    I've been doing a lot to create the final Leadwerks projects to build static libraries, and the corresponding Visual Studio, Xcode, and Eclipse projects to load those libraries and start coding with Leadwerks 3 in C++. We're also making progress with our sample game "Darkness Awaits". The community came up with an awesome logo for the game that captures the spirit and feel of the original concept, which first formed as a mod for the original Quake engine. I uploaded gamecreator's Photoshop file in the same thread, so if you have a hankering for some design feel free to play around with it.
     
    I also have a lot of small miscellaneous tasks to finish. Today I:
    Fixed bug on MacOS context switching.
    Updated mobile shader loader to match new single-file shader system.
    Fixed Mac shader error parsing on NVidia cards. Interestingly, shader output on NVidia and ATI cards on Mac mimics ATI shader output on Windows.
    Figured out how to make Xcode debug a static library in an external executable.
    Spent more time than I would like fixing some problems with the SVN repository.

    Chris has a goblin he's replacing our enemy characters with, and hopefully we'll be able to show some gameplay soon.
     
    Here's the current game running in the iOS simulator. I haven't implemented skinned animation to the mobile renderer yet, but it's pretty simple to expose now:

  17. Josh
    It's quite a challenge to get something semi-deployable to work on four platforms. I never intended to become an expert on the subject, but here are some of the interesting things I have picked up recently.
     
    Code generation mode in Visual Studio
    By default, Visual Studio builds programs in debug mode that won't run on consumer's machines. Fix it by changing the code generation mode:
    http://www.leadwerks...grams-cant-run/
     
    Static Libraries in Xcode
    Xcode has no "exclude from build" option. If you include a debug and release static library with the same name, the compiler will choose either one or the other, and cause errors in one build. The way around this is to set both to "Optional" in the "Build Phases" project settings.
    https://devforums.ap...170482?tstart=0
     
    Android NDK Path
    To relocate a project, you have to alter the NDK Builder setting "Project_Path". The NDK settings are hidden away pretty well in the Project>Android settings.
     
    And slightly unrelated, but equally maddening...
     
    Polled Input + Notifications on OSX in BlitzMax = death
    http://blitzmax.com/...php?topic=99043
  18. Josh
    I've been following Eric's progress with this idea since last spring, and it's really great to see what started as a fuzzy concept turn into reality.
     

    http://www.youtube.com/watch?v=pK_yjZpOs6w
     
    About Hacker Lab
    We believe that technology can change the world and the starting point is education. Hacker Lab aims to educate folks and seed startups with community driven resources. Collectively we can build a brighter future using lean methods in both education and business.
     
    We Provide
    Community Mentorship For Startups
    Educational Courses For Both Adults & Youth
    Networking Events
    Industry Events
    Workspace for Students and Professionals in the Software and Hardware space including Design & Business Development.

     
    Here's the local media coverage of the event:
    http://gooddaysacram...740-hacker-lab/
     
    I'll be teaching a class on OpenGL on October 24th. Check the site for details.
     
    www.hackerlab.org
     

     

  19. Josh
    I've got the editor and Lua interpreter communicating on OSX, but am having trouble creating a window...some weird Objective C problem. I've got to go get my local Xcode expert.

  20. Josh
    I borrowed Shadmar's terrain splatting shader. This is the result after fiddling around with it for a few minutes in Leadwerks 3. (No normal mapping yet, but that's easy to add.)
     
    Physics can be added by generating a physics shape from the terrain model. It doesn't allow heightmap editing in the editor, but I think this will serve as a good solution until our super uber mega streaming terrain system is built.
     
    Thanks to Shadmar for the assets.
     
    Klepto is also looking into a few OpenGL ES emulators to see if there is a way to test mobile shaders on a PC.
  21. Josh
    I recently made two small improvements that make the editor much more fun to work with.
     
    A shader consists of two pages of code, for the vertex and fragment programs. I originally designed the shader editor to use tabs to divide up the two code chunks. However, this meant the shader editor could have only one shader open at a time. This made copying and pasting from one shader to another rather tedious.
     
    To improve this, I merged the shader and script editors into a single window. Multiple shaders can be opened, and they show up in the window tabs. When a shader file is selected, a tree view appears on the left hand side of the code area. This displays the different code sections, and even lets you view the code for multiple graphics modules.
     
    When you press F5, the shader is still compiled as before. Klepto2 also told me about an OpenGL ES offline shader compiler. I set the editor up to use this to compile mobile shaders, so you can test whether they compile and fix any errors without having to try it on your mobile device.
     
    Another new feature is the Object Bar. This is a vertical stack of buttons on the left side of the program window. It contains the object selection mode buttons, followed by the most frequently used object types. Although this cannot replace the drop-down boxes with parameters like number of sides, etc., it does make development much faster. Since I added this feature I have found the editor much more enjoyable and fast. Having the most commonly pressed buttons near a corner makes it easier to find them when you are pressing them over and over. (I often had to stop when using 3D World Studio and visually scan for these buttons somewhere in the middle of the toolbar.)

     
    These are just small improvements, but they make a big difference in the speed and feel of the editor.
  22. Josh
    I picked up an Intel SSD for fairly cheap and installed the Windows 8 Release Preview on it. With this configuration boots up in about 5 seconds. I actually spend a lot longer waiting for BIOS to finish than for Windows to start, which is fantastic.
     
    Anyways, it makes sense to me to take screenshots for the docs from the newest version of Windows 8 since Windows is still the dominant operating system. I couldn't find a driver for my ATI 3850, so I swapped it out for a GEForce 480. Here's Leadwerks 3 running in Windows 8. It runs perfectly and doesn't look too bad.

     

     

  23. Josh
    I experienced some problems this week when I tried to create an executable with Visual Studio 2008 for deployment. On Windows 7 test machines I would get this error:
     
    I finally tracked the solution down to a Visual Studio project setting. In Project Settings > Configuration Properties > C/C++ > Code Generation there is a property called "Runtime Library". By default it is set to rely on external DLLs. Change these values to non-DLL settings (like MT or MTd) and they will include the runtime library in the executable. This makes for bigger executables, but they will run everywhere.

     
    Having experienced this problem with Visual Studio 2010, I guessed this was the same issue. I uninstalled the Visual C++ 2010 Redistributable Package from my Windows XP machine, then created a simple test program on another Windows 7 machine. First I made sure I could create the problem, by using the default runtime library. Ever seen this error?:

     
    I've seen this issue come up before on this forum. Now you know how to solve it and build Debug or Release executables that will run everywhere, with Visual Studio 2008 and 2010. Here is my test application from Visual Studio 2010, "testapp.MDd.bat" will only run if you have the 2010 Redistributable Package installed. "testapp.MTd.bat" will run everywhere:
    testapp.zip
     
    Since we no longer have problems creating executables for Windows XP with Visual Studio 2010, I see no reason not to move our project on to a newer version. Visual Studio 2012 currently cannot make Windows XP executables, but Microsoft claims this will be supported soon. However, even if deployment to Windows XP is supported, Visual Studio 2012 itself will never run on Windows XP. Switching to Visual Studio 2012 would mean you cannot program Leadwerks with C++ on Windows XP.
     
    What do you think? Should we make the move to 2012, 2010, or stick with 2008?
×
×
  • Create New...