-
Posts
399 -
Joined
-
Last visited
Content Type
Profiles
Forums
Blogs
Articles
Docs
Gallery
Everything posted by chriscalef
-
Crash in current development branch, on MatInstance::isInstanced()
chriscalef replied to chriscalef's topic in C++
Whoops, correction! I did two things at once and assumed that the friendlier, happier one was the fix, but it turns out I was wrong. The crash I'm getting happens in renderPrePassManager.cpp, _initShaders(), and the "fix" (kluge) I used was simply to ditch early when the shader we're looking for isn't found. Change is the return after "if (!mClearGBufferShader )": void RenderPrePassMgr::_initShaders() { if ( mClearGBufferShader ) return; // Find ShaderData ShaderData *shaderData; mClearGBufferShader = Sim::findObject( "ClearGBufferShader", shaderData ) ? shaderData->getShader() : NULL; if ( !mClearGBufferShader ) { Con::errorf( "RenderPrePassMgr::_initShaders - could not find ClearGBufferShader" ); return;//Crash below if we don't return here. Thought it was just a missing shader, but I guess not. } // Create StateBlocks GFXStateBlockDesc desc; desc.setCullMode( GFXCullNone ); desc.setBlend( true ); ... This probably leaves some critical shader initialization tasks undone, but the game comes up anyway. :-P -
Crash in current development branch, on MatInstance::isInstanced()
chriscalef replied to chriscalef's topic in C++
Just for the record: I found the cause of the my second Empty Template crash, it was some missing shaders in shaders/lighting/advanced, there were five of them. Winmerge fixed me right up. I also found that there are quite a few file differences in there. I don't really mess with the shader department myself, but does anyone know if there should be differences between empty and full in this area? Or could I just assume Full has been more recently updated and overwrite the whole folder from there? Or, is the new template system ready to make these ones irrelevant? -
Very cool, thanks for sharing it!
-
openSimEarth gets statics, and goes back to decal roads.
chriscalef replied to chriscalef's topic in Show-off
Good lord, how time flies! Sorry I somehow missed your comment from MONTHS ago, @JackStone, but thanks! To answer your question, my terrain doesn't deal with the earth as a sphere, except in the sense of getting data that comes from the spherical earth... ie, since I'm focused on primarily a first person view, with some perhaps generally low elevation flying, I'm only planning to load a reasonable amount of 3D terrain at a time, not enough to justify messing around with the slight curvature that would be present at this scale. If you were to keep walking, you would eventually loop around (assuming the game didn't crash before you got there, lol) but at any given place, the heightfields are assumed to be coplanar. Good luck with your project, look forward to hearing more about it! -
Yeah, I've used containers, but what I really wanted was control vs control resolution, because inside the container when you have a wall of buttons, it still sucks to try to insert one. And it doesn't help that I'm somehow allergic to using the GUI editor, dunno why but I always just end up back in the script files, manually editing them. :-P An XML version could be useful, but it would be quite a bit of a rewrite and quite a bit less efficient than what I'm doing now, due to the fact that I'm actively querying things as I need them (recursively grabbing children for each element as I go through) and sharing data among tables. The bitmap table makes it possible for many elements to share the same image path, and all of them can be changed by just changing the one entry. Similar things could be accomplished with XML I'm sure but it would start to feel like I was rewriting sqlite. I'm so far down the SQL path at this point that there's no turning back, but that's why I published the code, if anyone is so inspired knock yourself out! Be warned though that the above code isn't perfect, I found a crash bug when I started moving things around too radically. Gotta get back to real work now but I'll clean it up next time. Thanks for the feedback though! Was a fun week, definitely takes a load off my mind re: how to proceed forward.
-
Just a quick update, about to have to put this down for a bit but I got well along the way toward making my first actual GUI with the new system. Coincidentally enough, it's going to be a form for making more forms. :-) http://opensimearth.com/images/screenshots/uiElement02.jpg
-
So... I had a very exciting week! Although it was entirely unplanned, a few days ago I came up with one of those ideas that just changes everything, and MUST be done immediately! The problem: With countless hours behind me of twiddling and twaddling Torque GUI elements in pursuit of my old Ecstasy Motion application, I've been flipping and flopping on how to move this work forward into my new build, as well as how to proceed with all the new GUIs I'm going to need for so many things. My issues are twofold: 1) First, I'm just plain reluctant to sink another thousand hours into TorqueScript GUIs. I've been frustrated so many times by limitations of the system, and wooed so many times by the other sexy options, like an HTML-based solution, or one of the many other well defined third party UI systems, that I just hate to see myself digging in again and doing it all the hard way, in a format that leaves all my work in a giant pile of plain text script files. If I ever change my mind, there it sits, needing to be manually ported over, one button / text field / checkbox at a time. 2) Second, and even more importantly: in my day job, I've been working a lot with Cocos2d recently, and a very simple concept from their system really stuck in my head. Namely, the concept of anchors. In Cocos2d, you can define an anchor layout and set each control to base its position on the position of another control, thereby enabling one to move a whole block of UI elements around just by moving the base element. Now, maybe you can already do that easily somehow in Torque, in which case I run the risk of feeling pretty stupid for the way I've spent a lot of past hours, but I must confess: many of those hours were spent simply fudging the positions of a whole group of UI elements over a little bit, because I had to insert a new control somewhere into the upper left of my form, and everything else had to move to make room. Hence, this week's blinding flash of brilliance, killing two birds with one great beautiful all purpose stone named: SQL Please allow me to introduce you to the newest table in my database: http://opensimearth.com/images/screenshots/uiElementSql.jpg And its small companion table for storing bitmap paths: http://opensimearth.com/images/screenshots/uiBitmapSql.jpg So basically, what's going on here is I wrote a little system in Torque Script which queries all the UI elements in a particular form (which itself is in the table as just another UI element). All it took was three functions (look for code at the bottom of this post): makeSqlGuiForm(%control_id) - starts the process, and reads the relevant data about the parent container for the new form, identified by %control_id. makeSqlGuiChildren(...) - the core of the system, this is a function which calls itself recursively to allow subcontainers within the form. These can be either actual Torque Gui containers, or they can be "Virtual" containers, meaning I use their properties to determine final positions of all of their children, but the container itself doesn't exist as a gui object. makeUndefChildren() - this was necessary in order to deal with the possibility of controls being anchored to other controls that come later in the query, and hence don't exist yet when we're trying to use them. I store all such "undefined" controls in a list when I go through the first pass, and then run down the list in this function until everything has been happily sorted. The great thing about this, in addition to ease of layout, is that if/when I ever do make the jump into another GUI system, all I have to do now is rewrite those functions to export whatever syntax the new system requires. As long as I'm dealing with 2D positions and extents, the numbers will be the same. Also useful is the fact that when I want to adjust elements on my form, I can see practically all the relevant information compressed into one screen. To give you a glimpse of the actual data, here's a couple of snapshots: http://opensimearth.com/images/screenshots/uiElementData.jpg http://opensimearth.com/images/screenshots/uiBitmapData.jpg One thing you'll immediately note is the "type" column, eg "GuiBitmapCtrl" - by leaving that as plain text, the system is able to support any new GUI control type. What's in that field goes directly into the script. The left_anchor / right_anchor / top_anchor / bottom_anchor fields contain IDs of other uiElements in the same table. It's pretty straightforward except for one sneaky little convention I slipped in to avoid a bunch of complexity. My initial assumption was that if I had a control with a left_anchor to another control, that meant that the left edge of this control matches up to the right edge of the anchor control, minus whatever horizontal padding comes into play from the parent or from this element. (Parent containers provide edge padding and internal padding, and then individual controls can use their own horizontal or vertical padding numbers to fine tune themselves as desired.) However, it quickly became apparent that I was also going to need to align the left edge of this control with the left edge of another control, when I'm doing things like stacking a set of controls in a column, or lining up the bottoms to make an even horizontal row. So, to avoid a bunch of work, I just threw in the convention that a negative number in an anchor column means we use the same edge, bottom to bottom, instead of opposite edges. So, long story short, here's the end result. This is just a dummy form, obviously, but it shows off some of the features of my little system: http://opensimearth.com/images/screenshots/TestWindow.jpg The top two rows are simply three controls each, with the first ones anchored to the left edge of the parent window, and then the others anchored to the one in front of them in the row. If I make one of them a little wider, the rest of the row automatically moves over. The bottom left container is a GuiWindow control, which can be moved around or maximized. The bottom right set of buttons were created with my Virtual container type, which allows all of them to be moved just by moving the container, in the database, but once they are created they are just simple children of the parent window, and the container doesn't exist. From here, I will probably have to add a number of additional fields to my main table, as I come across more members of different GUI element types that I haven't supported yet. However, this feels like a solid start. Oh yeah, almost forgot to mention - I stuck a FileObject in at the end, and made it save out the finished gui, so if you want to you can run with that once it's been created. Here's what the above GUI looks like in script: %guiContent = new GuiWindowCtrl(TestWindow) { position = "153 187"; extent = "480 320"; text = "TestWindow"; new GuiTextCtrl() { position = "10 30"; extent = "55 20"; text = "SceneSet"; internalName = "SceneSetLabel"; tooltip = "This is just a label."; tooltipprofile = "GuiToolTipProfile"; }; new GuiPopUpMenuCtrl() { position = "70 30"; extent = "120 20"; internalName = "SceneSetList"; command = "loadScene(ScenesList.getSelected());"; tooltip = "Choose a scene to load."; tooltipprofile = "GuiToolTipProfile"; }; new GuiTextCtrl() { position = "10 53"; extent = "55 20"; text = "Scene"; internalName = "SceneLabel"; command = ""; tooltip = ""; tooltipprofile = "GuiToolTipProfile"; bitmap = "tools/worldEditor/images/toolbar/world"; }; new GuiBitmapButtonCtrl() { position = "195 30"; extent = "20 20"; text = ""; internalName = "TestButton"; command = "echo(\"button does THIS.\");"; tooltip = "This button will do something else."; tooltipprofile = "GuiToolTipProfile"; bitmap = "tools/worldEditor/images/toolbar/world"; }; new GuiPopUpMenuCtrl() { position = "70 53"; extent = "120 20"; text = ""; internalName = "SceneList"; command = ""; tooltip = "This is just a label."; tooltipprofile = "GuiToolTipProfile"; }; new GuiBitmapButtonCtrl() { position = "375 215"; extent = "30 30"; command = "echo(\"button does THIS.\");"; tooltip = "Button in a subcontainer."; tooltipprofile = "GuiToolTipProfile"; bitmap = "tools/worldEditor/images/toolbar/world"; }; new GuiBitmapButtonCtrl() { position = "407 215"; extent = "30 30"; text = ""; internalName = ""; command = "echo(\"button does THIS.\");"; tooltip = "Button in a subcontainer."; tooltipprofile = "GuiToolTipProfile"; bitmap = "tools/worldEditor/images/toolbar/softCurve"; }; new GuiBitmapButtonCtrl() { position = "439 215"; extent = "30 30"; text = ""; internalName = ""; command = "echo(\"button does THIS.\");"; tooltip = "Button in a subcontainer."; tooltipprofile = "GuiToolTipProfile"; bitmap = "tools/worldEditor/images/toolbar/world"; }; new GuiBitmapButtonCtrl() { position = "375 247"; extent = "30 30"; text = ""; internalName = ""; command = "echo(\"button does THIS.\");"; tooltip = "Button in a subcontainer."; tooltipprofile = "GuiToolTipProfile"; bitmap = "tools/worldEditor/images/toolbar/lowerHeight"; }; new GuiBitmapButtonCtrl() { position = "407 247"; extent = "30 30"; text = ""; internalName = ""; command = "echo(\"button does THIS.\");"; tooltip = "Button in a subcontainer."; tooltipprofile = "GuiToolTipProfile"; bitmap = "tools/worldEditor/images/toolbar/world"; }; new GuiBitmapButtonCtrl() { position = "439 247"; extent = "30 30"; text = ""; internalName = ""; command = "echo(\"button does THIS.\");"; tooltip = "Button in a subcontainer."; tooltipprofile = "GuiToolTipProfile"; bitmap = "tools/worldEditor/images/toolbar/setEmpty"; }; new GuiBitmapButtonCtrl() { position = "375 279"; extent = "30 30"; text = ""; internalName = ""; command = "echo(\"button does THIS.\");"; tooltip = "Button in a subcontainer."; tooltipprofile = "GuiToolTipProfile"; bitmap = "tools/worldEditor/images/toolbar/world"; }; new GuiBitmapButtonCtrl() { position = "407 279"; extent = "30 30"; text = ""; internalName = ""; command = "echo(\"button does THIS.\");"; tooltip = "Button in a subcontainer."; tooltipprofile = "GuiToolTipProfile"; bitmap = "tools/worldEditor/images/toolbar/brushAdjustHeight"; }; new GuiBitmapButtonCtrl() { position = "439 279"; extent = "30 30"; text = ""; internalName = ""; command = "echo(\"button does THIS.\");"; tooltip = "Button in a subcontainer."; tooltipprofile = "GuiToolTipProfile"; bitmap = "tools/worldEditor/images/toolbar/world"; }; new GuiWindowCtrl() { position = "12 188"; extent = "98 120"; text = ""; internalName = ""; command = ""; tooltip = ""; tooltipprofile = "GuiToolTipProfile"; new GuiBitmapButtonCtrl() { position = "2 27"; extent = "30 30"; text = ""; internalName = ""; command = "echo(\"button does THIS.\");"; tooltip = "Button in a subcontainer."; tooltipprofile = "GuiToolTipProfile"; bitmap = "tools/worldEditor/images/toolbar/softCurve"; }; new GuiBitmapButtonCtrl() { position = "34 27"; extent = "30 30"; text = ""; internalName = ""; command = "echo(\"button does THIS.\");"; tooltip = "Button in a subcontainer."; tooltipprofile = "GuiToolTipProfile"; bitmap = "tools/worldEditor/images/toolbar/world"; }; new GuiBitmapButtonCtrl() { position = "66 27"; extent = "30 30"; text = ""; internalName = ""; command = "echo(\"button does THIS.\");"; tooltip = "Button in a subcontainer."; tooltipprofile = "GuiToolTipProfile"; bitmap = "tools/worldEditor/images/toolbar/softCurve"; }; new GuiBitmapButtonCtrl() { position = "2 59"; extent = "30 30"; text = ""; internalName = ""; command = "echo(\"button does THIS.\");"; tooltip = "Button in a subcontainer."; tooltipprofile = "GuiToolTipProfile"; bitmap = "tools/worldEditor/images/toolbar/world"; }; new GuiBitmapButtonCtrl() { position = "34 59"; extent = "30 30"; text = ""; internalName = ""; command = "echo(\"button does THIS.\");"; tooltip = "Button in a subcontainer."; tooltipprofile = "GuiToolTipProfile"; bitmap = "tools/worldEditor/images/toolbar/softCurve"; }; new GuiBitmapButtonCtrl() { position = "66 59"; extent = "30 30"; text = ""; internalName = ""; command = "echo(\"button does THIS.\");"; tooltip = "Button in a subcontainer."; tooltipprofile = "GuiToolTipProfile"; bitmap = "tools/worldEditor/images/toolbar/world"; }; new GuiBitmapButtonCtrl() { position = "2 91"; extent = "30 30"; text = ""; internalName = ""; command = "echo(\"button does THIS.\");"; tooltip = "Button in a subcontainer."; tooltipprofile = "GuiToolTipProfile"; bitmap = "tools/worldEditor/images/toolbar/softCurve"; }; new GuiBitmapButtonCtrl() { position = "34 91"; extent = "30 30"; text = ""; internalName = ""; command = "echo(\"button does THIS.\");"; tooltip = "Button in a subcontainer."; tooltipprofile = "GuiToolTipProfile"; bitmap = "tools/worldEditor/images/toolbar/world"; }; new GuiBitmapButtonCtrl() { position = "66 91"; extent = "30 30"; text = ""; internalName = ""; command = "echo(\"button does THIS.\");"; tooltip = "Button in a subcontainer."; tooltipprofile = "GuiToolTipProfile"; bitmap = "tools/worldEditor/images/toolbar/softCurve"; }; }; new GuiBitmapCtrl() { position = "373 213"; extent = "2 99"; bitmap = "core/art/gui/images/separator-h"; }; new GuiBitmapCtrl() { position = "374 213"; extent = "98 2"; bitmap = "core/art/gui/images/separator-v"; }; new GuiBitmapCtrl() { position = "373 310"; extent = "99 2"; bitmap = "core/art/gui/images/separator-v"; }; new GuiBitmapCtrl() { position = "470 213"; extent = "2 98"; bitmap = "core/art/gui/images/separator-h"; }; new GuiBitmapButtonCtrl() { position = "195 53"; extent = "20 20"; internalName = "TestButton"; command = "echo(\"button does something else.\");"; tooltip = "This button will do something else."; tooltipprofile = "GuiToolTipProfile"; bitmap = "tools/worldEditor/images/toolbar/brushPaintNoise"; }; }; And finally, as promised, here's all my code to make this work. It is based on the sqlite3 resource that's been floating around, not sure if I have a ready link to that but if you're interested and can't find it, let me know. My apologies for the massive repetition between the makeSqlGuiChildren function and the makeUndefChildren function, it would have been much prettier to break off the repetitive chunk into its own function but I haven't gotten there yet. function makeSqlGuiForm(%control_id) { echo("trying to load gui! " @ %control_id); $controlCount = 0; $undefinedCount = 0; //This keeps track of controls that need $undefinedList = ""; //anchors which have not been created yet. //Note: remember that TorqueScript arrays are just variables, so there is no way to clear //the whole array in one line like it looks like I'm doing here. Shouldn't matter because //we'll be refilling it with only what we need and accessing only those values every time. %script = ""; %indent = " ";//Three-space indents, increment and decrement this as we go down the tree. //SO, first we need to select the parent control, with control_id. Then, we need a //recursive algorithm to select all the children of this parent, and then all the children of //those children, until we come up with no children. Would be snazzy to fit this all into //one query, but reality is the speed gain will probably be totally undetectable, as long as //we're not doing this every frame on resize. %query = "SELECT * FROM uiElement e " @ "LEFT JOIN uiBitmap b ON b.id=e.bitmap_id " @ "WHERE e.id=" @ %control_id @ ";"; %result = sqlite.query(%query, 0); echo( "Query: " @ %query ); if (%result) { %bitmap_path = sqlite.getColumn(%result, "path"); %type = sqlite.getColumn(%result, "type"); %name = sqlite.getColumn(%result, "name"); %width = sqlite.getColumn(%result, "width"); %height = sqlite.getColumn(%result, "height"); %horiz_align = sqlite.getColumn(%result, "horiz_align"); %vert_align = sqlite.getColumn(%result, "vert_align"); %pos_x = sqlite.getColumn(%result, "pos_x"); %pos_y = sqlite.getColumn(%result, "pos_y"); %horiz_padding = sqlite.getColumn(%result, "horiz_padding"); %vert_padding = sqlite.getColumn(%result, "vert_padding"); %horiz_edge_padding = sqlite.getColumn(%result, "horiz_edge_padding"); %vert_edge_padding = sqlite.getColumn(%result, "vert_edge_padding"); } if (strlen(%type)>0) //New way: to hell with a massive table of types, I'm just going to {//use the actual Torque names of the classes here. //Advantage: I can add new ones just by typing them in. And browsing the DB is informative. //Disadvantage: I am locking myself to Torque names. But, later for other systems I can convert from // them in a table just like I would with ints. %script = %script @ "%guiContent = new " @ %type @ "(" @ %name @ ") {\n"; } else return; %editorExtents = EWorldEditor.getExtent(); %editorWidth = getWord(%editorExtents,0); %editorHeight = getWord(%editorExtents,1); %pos_x = %pos_x * %editorWidth; %pos_y = %pos_y * %editorHeight; %script = %script @ " position = \"" @ mFloor(%pos_x) @ " " @ mFloor(%pos_y) @ "\";\n"; %script = %script @ " extent = \"" @ %width @ " " @ %height @ "\";\n"; %script = %script @ " text = \"" @ %name @ "\";\n\n"; $controls[$controlCount,0] = %control_id; $controls[$controlCount,1] = %pos_x; $controls[$controlCount,2] = %pos_y; $controls[$controlCount,3] = %width; $controls[$controlCount,4] = %height; $controls[$controlCount,5] = false;//Base window can't be virtual. $controlCount++; %script = %script @ makeSqlGuiChildren(%control_id,%width,%height,%horiz_padding,%vert_padding,%horiz_edge_padding,%vert_edge_padding,%indent); if ($undefinedCount > 0) %script = %script @ makeUndefChildren(%indent); %script = %script @ "};\n"; ////////////////////////////// eval(%script); //echo(%script); ////////////////////////////// %filename = "testWindow.gui"; %fileObject = new FileObject(); %fileObject.openForWrite( %filename ); %fileObject.writeLine(%script); %fileObject.close(); %fileObject.delete(); EWorldEditor.add(%name); } function makeSqlGuiChildren(%parent_id,%parent_width,%parent_height,%parent_horiz_padding, %parent_vert_padding,%parent_horiz_edge_padding,%parent_vert_edge_padding,%indent) {//RECURSIVE - so make sure we don't use any globals. %script = ""; %query = "SELECT * FROM uiElement e " @ "LEFT JOIN uiBitmap b ON b.id=e.bitmap_id " @ "WHERE e.parent_id=" @ %parent_id @ ";"; %result = sqlite.query(%query, 0); if (%result) { echo("makeSqlGuiChildren found " @ sqlite.numRows(%result) @ " children for parent " @ %parent_id ); while (!sqlite.endOfResult(%result)) { %undefined = false; %horiz_anchor_flip = false;//These track whether either of our anchors are "flipped" - e.g. a negative sign %vert_anchor_flip = false;//in the left_anchor means we use the _left_ edge of the anchor control to align //the left edge of this control, instead of aligning the left edge of this control to the right edge of the anchor. %control_id = sqlite.getColumn(%result, "id"); %bitmap_path = sqlite.getColumn(%result, "path"); %left_anchor = sqlite.getColumn(%result, "left_anchor"); %right_anchor = sqlite.getColumn(%result, "right_anchor"); %top_anchor = sqlite.getColumn(%result, "top_anchor"); %bottom_anchor = sqlite.getColumn(%result, "bottom_anchor"); %type = sqlite.getColumn(%result, "type"); %content = sqlite.getColumn(%result, "content"); %name = sqlite.getColumn(%result, "name"); %width = sqlite.getColumn(%result, "width"); %height = sqlite.getColumn(%result, "height"); %command = sqlite.getColumn(%result, "command"); %tooltip = sqlite.getColumn(%result, "tooltip"); %horiz_align = sqlite.getColumn(%result, "horiz_align"); %vert_align = sqlite.getColumn(%result, "vert_align"); %pos_x = sqlite.getColumn(%result, "pos_x"); %pos_y = sqlite.getColumn(%result, "pos_y"); %horiz_padding = sqlite.getColumn(%result, "horiz_padding"); %vert_padding = sqlite.getColumn(%result, "vert_padding"); %horiz_edge_padding = sqlite.getColumn(%result, "horiz_edge_padding"); %vert_edge_padding = sqlite.getColumn(%result, "vert_edge_padding"); %variable = sqlite.getColumn(%result, "variable"); %button_type = sqlite.getColumn(%result, "button_type"); %group_num = sqlite.getColumn(%result, "group_num"); %profile = sqlite.getColumn(%result, "profile"); if (strlen(%type)>0) { ////// left/right anchors ////////////// if (%left_anchor < 0) { %horiz_anchor_flip = true; %left_anchor *= -1; } if (%right_anchor < 0) { %horiz_anchor_flip = true; %right_anchor *= -1; } if (%left_anchor == %parent_id) //check for left anchor first, then right. {//AH, oops! If parent is Virtual, then we need to use it's position, we can't start with zero. %i = 0; %foundVirtual = false; while (%i < $controlCount) { if ($controls[%i,0] == %parent_id) { if ($controls[%i,5]) { %pos_x = $controls[%i,1] + %parent_horiz_edge_padding + %horiz_padding; echo("found virtual parent! pos_x " @ %pos_x ); %foundVirtual = true; } } %i++; } if (!%foundVirtual) %pos_x = %parent_horiz_edge_padding + %horiz_padding; } else if (%left_anchor > %parent_id)//Parents and previous siblings MUST be ahead in database order. { %i = 0; %found = false; while (%i < $controlCount) { if ($controls[%i,0] == %left_anchor) { if (%horiz_anchor_flip == false) %pos_x = $controls[%i,1] + $controls[%i,3] + %parent_horiz_padding + %horiz_padding; else %pos_x = $controls[%i,1] + %horiz_padding; %found = true; } %i++; } if ( !%found && !%undefined ) { $undefinedList[$undefinedCount,0] = %control_id; $undefinedList[$undefinedCount,1] = %indent; $undefinedCount++; %undefined = true; } } else if (%right_anchor == %parent_id) { %i = 0; %foundVirtual = false; while (%i < $controlCount) { if ($controls[%i,0] == %parent_id) { if ($controls[%i,5]) { %pos_x = $controls[%i,1] + $controls[%i,3] - %width - %parent_horiz_edge_padding - %horiz_padding; %foundVirtual = true; } } %i++; } if (!%foundVirtual) %pos_x = %parent_width - %width - %parent_horiz_edge_padding - %horiz_padding; } else if (%right_anchor > %parent_id) { %i = 0; %found = false; while (%i < $controlCount) { if ($controls[%i,0] == %right_anchor) { if (%horiz_anchor_flip == false) %pos_x = $controls[%i,1] - %width - %parent_horiz_padding - %horiz_padding; else %pos_x = $controls[%i,1] + $controls[%i,3] - %width - %horiz_padding; %found = true; } %i++; } if ( !%found && !%undefined ) { $undefinedList[$undefinedCount,0] = %control_id; $undefinedList[$undefinedCount,1] = %indent; $undefinedCount++; %undefined = true; } } ////// top/bottom anchors ////////////// if (%top_anchor < 0) { %vert_anchor_flip = true; %top_anchor *= -1; } if (%bottom_anchor < 0) { %vert_anchor_flip = true; %bottom_anchor *= -1; } if (%top_anchor == %parent_id) //check for top anchor first, then bottom. { %i = 0; %foundVirtual = false; while (%i < $controlCount) { if ($controls[%i,0] == %parent_id) { if ($controls[%i,5]) { %pos_y = $controls[%i,2] + %parent_vert_edge_padding + %vert_padding; %foundVirtual = true; } } %i++; } if (!%foundVirtual) %pos_y = %parent_vert_edge_padding + %vert_padding; } else if (%top_anchor > %parent_id) { %i = 0; %found = false; while (%i < $controlCount) { if ($controls[%i,0] == %top_anchor) { if (%vert_anchor_flip == false) %pos_y = $controls[%i,2] + $controls[%i,4] + %parent_vert_padding + %vert_padding; else %pos_y = $controls[%i,2] + %vert_padding; %found = true; } %i++; } if ( !%found && !%undefined ) { $undefinedList[$undefinedCount,0] = %control_id; $undefinedList[$undefinedCount,1] = %indent; $undefinedCount++; %undefined = true; } } else if (%bottom_anchor == %parent_id) { %i = 0; %foundVirtual = false; while (%i < $controlCount) { if ($controls[%i,0] == %parent_id) { if ($controls[%i,5]) { %pos_y = $controls[%i,2] + $controls[%i,4] - %height - %parent_vert_edge_padding - %vert_padding; %foundVirtual = true; } } %i++; } if (!%foundVirtual) %pos_y = %parent_height - %height - %parent_vert_edge_padding - %vert_padding; } else if (%bottom_anchor > %parent_id) { %i = 0; %found = false; while (%i < $controlCount) { if ($controls[%i,0] == %bottom_anchor) { if (%vert_anchor_flip == false) %pos_y = $controls[%i,2] - %height - %parent_vert_padding - %vert_padding; else %pos_y = $controls[%i,2] + $controls[%i,4] - %height - %vert_padding; %found = true; } %i++; } if ( !%found && !%undefined ) { $undefinedList[$undefinedCount,0] = %control_id; $undefinedList[$undefinedCount,1] = %indent; $undefinedCount++; %undefined = true; } } if (%undefined == false) { //Now, write it to the script buffer. if (%type !$= "Virtual") { %script = %script @ %indent @ "new " @ %type @ "() {\n"; %script = %script @ %indent @ " position = \"" @ mFloor(%pos_x) @ " " @ mFloor(%pos_y) @ "\";\n"; %script = %script @ %indent @ " extent = \"" @ %width @ " " @ %height @ "\";\n"; if (%content !$= "NULL") %script = %script @ %indent @ " text = \"" @ %content @ "\";\n"; if (%name !$= "NULL") %script = %script @ %indent @ " internalName = \"" @ %name @ "\";\n"; if (%command !$= "NULL") %script = %script @ %indent @ " command = \"" @ %command @ "\";\n"; if (%tooltip !$= "NULL") %script = %script @ %indent @ " tooltip = \"" @ %tooltip @ "\";\n"; if (%tooltip !$= "NULL") %script = %script @ %indent @ " tooltipprofile = \"GuiToolTipProfile\";\n"; if (%bitmap_path !$= "NULL") %script = %script @ %indent @ " bitmap = \"" @ %bitmap_path @ "\";\n"; if (%variable !$= "NULL") %script = %script @ %indent @ " variable = \"" @ %variable @ "\";\n"; if (%button_type !$= "NULL") %script = %script @ %indent @ " buttonType = \"" @ %button_type @ "\";\n"; if (%group_num !$= "NULL") %script = %script @ %indent @ " groupNum = \"" @ %group_num @ "\";\n"; if (%profile !$= "NULL") %script = %script @ %indent @ " profile = \"" @ %profile @ "\";\n"; } //Next, store position/extent info in a 2d array, for positioning other elements. $controls[$controlCount,0] = %control_id; $controls[$controlCount,1] = %pos_x; $controls[$controlCount,2] = %pos_y; $controls[$controlCount,3] = %width; $controls[$controlCount,4] = %height; if (%type !$= "Virtual") $controls[$controlCount,5] = false; else $controls[$controlCount,5] = true; $controlCount++; ////// Now, take care of the children. /////// if (%type !$= "Virtual") { %prev_indent = %indent; %indent = %indent @ " ";//Make it three spaces deeper before we go to the children... } //And... RECURSE! %script = %script @ makeSqlGuiChildren(%control_id,%width,%height,%horiz_padding,%vert_padding,%horiz_edge_padding,%vert_edge_padding,%indent); if (%type !$= "Virtual") { %indent = %prev_indent;//... and then take them away when we come back. %script = %script @ %indent @ "};\n"; } } /////////////////////////////////////////////// } sqlite.nextRow(%result); } } return %script; } function makeUndefChildren(%indent) { //Now, the interesting part. We have to keep looping through the undefinedList, skipping over anything that //still can't be anchored, but instantiating and removing anything that now has valid anchors. %sanityCount = 0; %script = ""; echo("makeUndefChildren, count " @ $undefinedCount); while (($undefinedCount > 0)&&(%sanityCount<500)) { %sanityCount++;//(Just in case something goes haywire and we end up looping here forever.) //This could totally happen, if the user for instance accidentally makes two controls dependent //on each other, or parents of each other. for (%k=0;%k<$undefinedCount;%k++) { %control_id = $undefinedList[%k,0]; %query = "SELECT * FROM uiElement e " @ "LEFT JOIN uiBitmap b ON b.id=e.bitmap_id " @ "WHERE e.id=" @ %control_id @ ";"; %result = sqlite.query(%query, 0); if (%result) { %undefined = false; %parent_id = sqlite.getColumn(%result, "parent_id"); %bitmap_path = sqlite.getColumn(%result, "path"); %left_anchor = sqlite.getColumn(%result, "left_anchor"); %right_anchor = sqlite.getColumn(%result, "right_anchor"); %top_anchor = sqlite.getColumn(%result, "top_anchor"); %bottom_anchor = sqlite.getColumn(%result, "bottom_anchor"); %type = sqlite.getColumn(%result, "type"); %content = sqlite.getColumn(%result, "content"); %name = sqlite.getColumn(%result, "name"); %width = sqlite.getColumn(%result, "width"); %height = sqlite.getColumn(%result, "height"); %command = sqlite.getColumn(%result, "command"); %tooltip = sqlite.getColumn(%result, "tooltip"); %horiz_align = sqlite.getColumn(%result, "horiz_align"); %vert_align = sqlite.getColumn(%result, "vert_align"); %pos_x = sqlite.getColumn(%result, "pos_x"); %pos_y = sqlite.getColumn(%result, "pos_y"); %horiz_padding = sqlite.getColumn(%result, "horiz_padding"); %vert_padding = sqlite.getColumn(%result, "vert_padding"); %horiz_edge_padding = sqlite.getColumn(%result, "horiz_edge_padding"); %vert_edge_padding = sqlite.getColumn(%result, "vert_edge_padding"); if (strlen(%type)>0) { ////// left/right anchors ////////////// if (%left_anchor < 0) { %horiz_anchor_flip = true; %left_anchor *= -1; } if (%right_anchor < 0) { %horiz_anchor_flip = true; %right_anchor *= -1; } if (%left_anchor == %parent_id) //check for left anchor first, then right. { %i = 0; %foundVirtual = false; while (%i < $controlCount) { if ($controls[%i,0] == %parent_id) { if ($controls[%i,5]) { %pos_x = $controls[%i,1] + %parent_horiz_edge_padding + %horiz_padding; %foundVirtual = true; } } %i++; } if (!%foundVirtual) %pos_x = %parent_horiz_edge_padding + %horiz_padding; } else if (%left_anchor > %parent_id)//Parents and previous siblings MUST be ahead in database order. { %i = 0; %found = false; while (%i < $controlCount) { if ($controls[%i,0] == %left_anchor) { if (%horiz_anchor_flip == false) %pos_x = $controls[%i,1] + $controls[%i,3] + %parent_horiz_padding + %horiz_padding; else %pos_x = $controls[%i,1] + %horiz_padding; %found = true; } %i++; } if (!%found) { %undefined = true; } } else if (%right_anchor == %parent_id) { %i = 0; %foundVirtual = false; while (%i < $controlCount) { if ($controls[%i,0] == %parent_id) { if ($controls[%i,5]) { %pos_x = $controls[%i,1] + $controls[%i,3] - %width - %parent_horiz_edge_padding - %horiz_padding; %foundVirtual = true; } } %i++; } if (!%foundVirtual) %pos_x = %parent_width - %width - %parent_horiz_edge_padding - %horiz_padding; } else if (%right_anchor > %parent_id) { %i = 0; %found = false; while (%i < $controlCount) { if ($controls[%i,0] == %right_anchor) { if (%horiz_anchor_flip == false) %pos_x = $controls[%i,1] - %width - %parent_horiz_padding - %horiz_padding; else %pos_x = $controls[%i,1] + $controls[%i,3] - %width - %horiz_padding; %found = true; } %i++; } if (!%found) { %undefined = true; } } ////// top/bottom anchors ////////////// if (%top_anchor < 0) { %vert_anchor_flip = true; %top_anchor *= -1; } if (%bottom_anchor < 0) { %vert_anchor_flip = true; %bottom_anchor *= -1; } if (%top_anchor == %parent_id) //check for top anchor first, then bottom. { %i = 0; %foundVirtual = false; while (%i < $controlCount) { if ($controls[%i,0] == %parent_id) { if ($controls[%i,5]) { %pos_y = $controls[%i,2] + %parent_vert_edge_padding + %vert_padding; %foundVirtual = true; } } %i++; } if (!%foundVirtual) %pos_y = %parent_vert_edge_padding + %vert_padding; } else if (%top_anchor > %parent_id) { %i = 0; %found = false; while (%i < $controlCount) { if ($controls[%i,0] == %top_anchor) { if (%vert_anchor_flip == false) %pos_y = $controls[%i,2] + $controls[%i,4] + %parent_vert_padding + %vert_padding; else %pos_y = $controls[%i,2] + %vert_padding; %found = true; } %i++; } if (!%found) { %undefined = true; } } else if (%bottom_anchor == %parent_id) { %i = 0; %foundVirtual = false; while (%i < $controlCount) { if ($controls[%i,0] == %parent_id) { if ($controls[%i,5]) { %pos_y = $controls[%i,2] + $controls[%i,4] - %height - %parent_vert_edge_padding - %vert_padding; %foundVirtual = true; } } %i++; } if (!%foundVirtual) %pos_y = %parent_height - %height - %parent_vert_edge_padding - %vert_padding; } else if (%bottom_anchor > %parent_id) { %i = 0; %found = false; while (%i < $controlCount) { if ($controls[%i,0] == %bottom_anchor) { if (%vert_anchor_flip == false) %pos_y = $controls[%i,2] - %parent_vert_padding - %height - %vert_padding; else %pos_y = $controls[%i,2] + $controls[%i,4] - %height - %vert_padding; %found = true; } %i++; } if (!%found) { %undefined = true; } } if (%undefined == false) //Yay, we found our anchors this time! { %indent = $undefinedList[%k,1]; //Now, write it to the script buffer. if (%type !$= "Virtual") { %script = %script @ %indent @ "new " @ %type @ "() {\n"; %script = %script @ %indent @ " position = \"" @ mFloor(%pos_x) @ " " @ mFloor(%pos_y) @ "\";\n"; %script = %script @ %indent @ " extent = \"" @ %width @ " " @ %height @ "\";\n"; if (strlen(%content)>0) %script = %script @ %indent @ " text = \"" @ %content @ "\";\n"; if (strlen(%name)>0) %script = %script @ %indent @ " internalName = \"" @ %name @ "\";\n"; if (strlen(%command)>0) %script = %script @ %indent @ " command = \"" @ %command @ "\";\n"; if (strlen(%tooltip)>0) %script = %script @ %indent @ " tooltip = \"" @ %tooltip @ "\";\n"; if (strlen(%tooltip)>0) %script = %script @ %indent @ " tooltipprofile = \"GuiToolTipProfile\";\n"; if (strlen(%bitmap_path)>0) %script = %script @ %indent @ " bitmap = \"" @ %bitmap_path @ "\";\n"; if (strlen(%variable)>0) %script = %script @ %indent @ " variable = \"" @ %variable @ "\";\n"; if (strlen(%button_type)>0) %script = %script @ %indent @ " buttonType = \"" @ %button_type @ "\";\n"; if (strlen(%group_num)>0) %script = %script @ %indent @ " groupNum = \"" @ %group_num @ "\";\n"; if (strlen(%profile)>0) %script = %script @ %indent @ " profile = \"" @ %profile @ "\";\n"; } //Next, store position/extent info in a 2d array, for positioning other elements. $controls[$controlCount,0] = %control_id; $controls[$controlCount,1] = %pos_x; $controls[$controlCount,2] = %pos_y; $controls[$controlCount,3] = %width; $controls[$controlCount,4] = %height; if (%type !$= "Virtual") $controls[$controlCount,5] = false; else $controls[$controlCount,5] = true; $controlCount++; ////// Now, take care of the children. /////// if (%type !$= "Virtual") { %prev_indent = %indent; %indent = %indent @ " ";//Make it three spaces deeper before we go to the children... } //And... RECURSE! %script = %script @ makeSqlGuiChildren(%control_id,%width,%height,%horiz_padding,%vert_padding,%horiz_edge_padding,%vert_edge_padding,%indent); if (%type !$= "Virtual") { %indent = %prev_indent;//... and then take them away when we come back. %script = %script @ %indent @ "};\n"; } //Now, since we found one, we need to delete this one from the list and advance the rest of the //list forward one, then break and restart. for (%j=%k;%j<$undefinedCount;%j++) { $undefinedList[%j,0] = $undefinedList[(%j+1),0];//I do hope "(%j+1)" doesn't get interpreted $undefinedList[%j,1] = $undefinedList[(%j+1),1];// as a new array entry... } $undefinedCount--; break; //break out of "for (%i=0;%i<undefinedCount;%i++)" loop } } } } } return %script; } So anyway, there you have it! My week in a nutshell. Hope it provides some amusement and/or inspiration to somebody out there!
-
Crash in current development branch, on MatInstance::isInstanced()
chriscalef replied to chriscalef's topic in C++
Yeah, some more safety checks in there might be in order. No time pressure for me, like I said I added one safety check and when that didn't work just backed out since I didn't have time for a new wormhole at the moment. But I can totally wait till the new template goes in and see if it fixes itself. -
Crash in current development branch, on MatInstance::isInstanced()
chriscalef replied to chriscalef's topic in C++
Ah, thanks for that info, didn't know it was just the empty template. -
Is anyone else having this problem? I've tried twice, in two different repo copies just to make sure, and when I run a fresh empty template build, on load level I get a crash where MatInstance::isInstanced() is trying to refer to a null mProcessedMaterial. I tried adding a check there to make sure mProcessedMaterial is valid but it just crashed somewhere else. Working fine for everybody else? (Build environment: Win7, VS 2010)
-
If you search around on garagegames.com's forums, you might find some information, although everything I found was very old and it didn't seem like they ever worked all that well. Here's a link to something by Adam DeGrandis that might be useful. I used the term "vertex morphing" to get some results, for some reason the simple word "morph" returned nothing. http://www.garagegames.com/community/blogs/view/11087
-
Torque is supposed to have vertex morphing, although I haven't used it or thought about in a long time, so I can't guarantee it still works. It was definitely in there back in the day though.
-
mySQL support in T3D 3.6, Windows 10, VS Studio 2015 Express
chriscalef replied to JackStone's topic in C++
Hey, right on, glad you figured it out, and thanks for sharing! Yeah, I didn't think SQLite would help, because you're right, it's mainly for local data, that's what I use it for. I guess in a pinch you could run it embedded in your dedicated server build... but mysql is clearly much better, and yeah it would help T3D a lot to have a ready resource for it. Good luck with your game, look forward to hearing about it! -
mySQL support in T3D 3.6, Windows 10, VS Studio 2015 Express
chriscalef replied to JackStone's topic in C++
I can't help you at the moment with mysql, but on the off chance you just want an SQL database and don't really care about all the powerful features of mysql in particular, it's very easy to get SQLite 3 going in T3D. I have a T3D branch on my github (github.com/ChrisCalef/T3D - sqlite) with only the files you need (look in source/console, or check the commit history). But by all means keep us informed if you get an up to date mysql working, that would sure be nice! -
You can do it without creating a serverCmd function... I'm not totally sure of the best way to make the script know which vehicle you're referring to, but there are a lot of ways to hack it together. Basically, in your default.binds you could bind the key to a script function, and in that script function figure out what vehicle your player is mounted to, and call your shift function for that vehicle. Re: whether the server needs to know, if you're making a typical multiplayer game the player and vehicle movement is handled by the server and pushed down to the clients to prevent cheating, so yeah, you'd probably want to run it through the server. Here's an example of something similar I'm doing with default binds, in my case I have a SimGroup called SceneShapes that I've put all of my physics shapes into, and I'm calling each of them to do something. Your specifics will be different but the mechanism of calling a script function from default binds should be the same. If you can store a $myPlayer variable or something when you make your player, or store a reference to the vehicle when you create or mount it, then you should be good to go. GlobalActionMap.bindCmd(keyboard, "alt g", "shapesAct();",""); function shapesAct() { for (%i=0;%i<SceneShapes.getCount();%i++) { %shape = SceneShapes.getObject(%i); %shape.setHasGravity(false); %shape.setDynamic(1); } }
-
Hey, no worries about making promises or anything, I'm just throwing feelers out there. But yeah, projects like your D-Day beach are *exactly* what I envision openSimEarth being used for! But before I forget, I had an aside to @Duion, since he showed up here: I guess the whole point of open source is that legally I don't even need to ask, but I'd like to ask your permission anyway: would you mind if I borrowed art or code content from Ubergame to use in openSimEarth? I wouldn't want to steal your thunder, and would certainly reference Ubergame as a source, but you've done a lot of awesome work over there! Same goes in reverse, of course, for anything I've published so far under openSimEarth - it's all free on my github. Now, back to your questions. And re: messaging, feel free to message me anytime, but for general descriptions of the openSimEarth project, I might as leave them public, I have every interest in more people reading about it! (I will move all this to my own thread at some point, but I'm still practicing my pitch, so I hope you don't mind if I practice on you.) Yes, it is exactly like that. While it is easy enough to import a heightmap into Torque and start painting textures on it and distributing models, my goal is to make a baseline textured terrain available for the entire planet, so the average user can just go there and start walking around without doing any development work at all. What makes this possible, of course, is FlightGear. I have designed a simple network protocol based on a class I called dataSource, and I use this class to facilitate communication of terrain data and dynamic skybox images from FlightGear to Torque. (I know, I could have / should have downloaded a networking library, but I couldn't find one lightweight enough, easy enough to learn, with a liberal enough open source license, so I just wrote my own and it only took a few days, so hate away, haters!) :-) What this gives me is a very, very low resolution terrain, which is textured with a very broad brush according to GIS data assembled by the FlightGear terrain team. To be perfectly honest, it looks terrible from a first person perspective when you just use it as is, but it is a starting point, and you can literally go anywhere in the entire world, so there is that. To raise the quality level in particular areas, though, FlightGear provides a full set of command line terrain generation tools, called TerraGear, as well as a GUI to ease the process of using them. (It's still pretty complicated, however.) Using these tools, and downloading your own data, you can fairly easily replace any given area of flightgear terrain with much better terrain. You can also feed them your own GIS data to provide higher resolution, or historical or fictional, map data. On the Torque end of things, I've written a terrain pager class which first checks to see if we have terrains already created before asking FG to make any more. This way, I'm envisioning developers running the connection to FG as a one time thing, creating all their terrains, and then distributing them so that users won't have to deal with the FG connection at all. At the same time, though, I'm of course trying to make the FG connection more efficient and more invisible, so that people can use it all the time without noticing. Right now it's very slow and very noticeable, but I've done some very stupid things that I haven't had time to go back and fix yet, so there is a lot of low hanging fruit in terms of optimization. Anyway, in Torque, I'm treating the terrain textures received from FlightGear as landcover suggestions, and using them to potentially pick from an array of Torque textures, as well as make choices about tree and grass cover. As an example, where in FlightGear I might have a single forest texture, in Torque I would use that to choose from a set of different ground textures, as well as applying trees and ground covers from specific sets, via predefined rules. (A lot of this is aspirational at the moment, but just starting to work. Much more to be done.) In addition to terrain textures, I've written an OpenStreetMap XML reader that does a decent job of sucking in streetmaps and reproducing them as decal or mesh roads in Torque. (All of this stored in an sqlite database.) In addition, I've set up the World Editor to save TSStatics to the database instead of to the mission file, and then hooked them up to page in and out as the player moves. In this way it should be possible for users to run around and design anything they want, and simply by sharing the database with friends they will be able to reproduce their creations. Sorry for going on and on, but the last important point here is that ultimately I am really hoping to use this project for real world applications and not only for entertainment. I will leave that to your imagination for now. EDIT: Oh yeah, before I forget: the unfortunate point that makes this whole project vaporware at the moment is the fact that I still need to do a massive data reducing job on the gig or more of FlightGear data that you currently need to have to run the program. I guess I could just hand out my modified executable and make people download the whole FG data repository, but I'd really prefer to release a local-to-my-region build that would get people started using it without requiring the full world textures download. Maybe bandwidth and hard drives being what they are today, though, I shouldn't even worry about it...
-
Well hey, @Mud-H, since we're throwing caution to the wind and talking about things that we're not really prepared to talk about formally yet... do you have a moment to talk about openSimEarth? I'm sure you've seen my various postings on the project here recently, but I have yet to make an official public announcement about it yet, due to the fact that it still lacks the basic tier of gameplay elements I'm hoping to include right out of the gate. However, since you seem to be in a long term search for T3D collaborators, without being locked into a specific game you're trying to make, it seems that perhaps you might be fair game... Basically, the giant mouthful I've bitten off here can be described in a nutshell like this: I'm a game developer who really can't be tied down to spending years and years only to make one game, that will subsequently be discarded onto the trash heap of history when I ultimately start working on the next game. I got into working for Garage Games on the basic engine technology because I would rather put my time toward tools to make games, instead of toward a particular single game. However, I've now come to a place where I want to assemble many more high level game components that do not belong in the engine itself, but IMHO are common enough that they also should not have to be recreated every time for each individual T3D game. This will sound familiar, of course, because we've tossed around the idea of "starter packs" or "genre kits" for years. However, I'm taking a slightly different course with this. First, I'm only interested in assembling content that makes sense within a virtual Earth environment (although historical or futuristic scenarios are in scope), so I would like to assemble all kinds of first person shooter and realtime strategy logic, as well as wildlife simulation, weather modeling, farming, and also flight simulation, wheeled vehicle simulation, and many, many other potentially interesting bits of sim logic. But I am not particularly interested in dungeon crawlers, space games, or many other genres that do not fall within the (already enormous) scope I've settled on. Second, while the scope of the project appears insanely huge, if you've followed any of my blogs or posts you will know that the magic ticket for making it reasonable is FlightGear - I'm creating an unholy bastard child of Torque and FlightGear, with the result that I already have a complete world map (albeit low resolution, it's meant to be a sandbox rather than a finished simEarth), and I already have a vast array of extremely realistic flying vehicles available to me. Third, my largest area of professional expertise in game programming involves playing with PhysX, and I intend to use it for wheeled vehicles, in addition to ragdolls and many other things. My goal is to make an environment that will bring new users much, much closer to being able to make their own games, just by picking a location on the planet, shuffling the parts of openSimEarth around, and picking the features they want. I'd like it to cross into the zone where "making a game" with openSimEarth is more like making a game in Second Life, where you don't have to finish it and publish it as much as just make your content available to other users of openSimEarth. I'm ultimately envisioning running my own servers, but before that to allow people to run head to head multiplayer at home or set up their own dedicated servers. My goal is more to create a gaming/simulation ecosystem than to create a particular game or app. So anyway, I don't want to hijack your thread too far here, but although this plan may sound farfetched, I've already completed or at least significantly started all of the most technically challenging components on my list. I have a lot of optimization to do, and a lot of art time, and scripting logic, but I'm quite confident that everything I'm discussing here is very much achievable. And re: the problem of fly by night wannabe developers, I have recently taken a new contract programming position for which I specifically required a half time schedule, so that I would actually be able to spend whole days working on this. I am very committed to finishing it. If you, or anyone else in the community reading this, is interested in helping in any way with this project, please let me know, I'll be here!
-
This is probably a very stupid question, but does this work put us any closer to getting T3D working on iOS? Or is that just an entirely different beast and not even on the table?
-
Ah, haha, thank you both very much! I knew if I ignored that terrain edge bug long enough, somebody would come along and fix it for me! :D
-
If you just want two terrains to sit next to each other, you can just put them next to each other and it will mostly work. There is a known lighting bug at the borders, which is most visible on terrains with significant height difference from one side to the other, but in general you can just put terrains next to each other and most things work as expected. I have written a much more in depth terrain pager, but it's not really a standalone solution at this point, all the current work on it is in my openSimEarth build which has a lot of other things you probably don't want. However, the TerrainPager class in there might get you started anyway. The torque code is in github.com/ChrisCalef/Torque3D, branch openSimEarth.
-
I'm in favor! For both code plugins/enhancements and art assets, as well as finished games, a working and active store system would be nothing but beneficial, if someone has the gumption to take it on. I would imagine there would have to be some kind of vetting for quality assurance though, which could turn into a major time commitment. But if it benefited lots of people then hopefully there would also be enough volunteer energy to make it work.
-
If you're already planning on having ragdolls, then it makes the most sense IMHO to raycast for the physics bodies making up your ragdoll. I do this in PhysX, but bullet would be similar. I can't speak for stock Torque on the subject, however. This also brings up an issue of whether you have physics bodies on your characters all the time, or only instantiate them when they die. I use the former method, but might be forced to implement more restrictive rules when I start having very high numbers of characters in the scene, such as only instantiating physics bodies on characters within a certain distance of the player, or in the camera view area if zoomed. I'm sure it will take lots of trial and error to get it fully optimized, but so far at least I've found physx raycasts to be a quite inexpensive way to obtain not only a hit body, but the exact position, direction, surface normal and velocity of the projectile.
-
It looks like the Open Tissue project might not be a bad place to start, here's a link to someone who's hooked up IK in Ogre using it: http://www.ogre3d.org/forums/viewtopic.php?f=5&t=47172 From following the comments on that post I also came across this, which seems to be a potentially slimmer solution for just IK: http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?p=&f=6&t=2952
-
I know the Sickhead guys did some work on IK years back, with a dinosaur sim they were making for a museum. I don't think they've been working with Torque for years now but it might possibly be worth chasing down Tom Spilman and bugging him about it. Maybe. He might just laugh at you though. It would be seriously cool to get it working though, and given the number of IK solutions out there it doesn't seem like adapting one of them to Torque would be that difficult of a job... not that I'm volunteering at the moment. One thing I am intending to do in the very near future though is bring in more a lot of work from Ecstasy Motion that could help do things like changing node orientations from script - even though for IK you would definitely not want to do it in script, this would certainly be an engine side project.
-
Wow, that's very interesting, thanks for the research @Timmy! Open source or not, compiling it ourselves certainly could help a bit with tracking down some of those weird bugs that crop up...
