mohij 0 Posted June 28, 2007 Author Report Share Posted June 28, 2007 I work since a week or so, so my time is limited. But I can surely try another task.If possible something in space would be interesting, but it's not that important. Quote Link to post Share on other sites
OrbWeaver 662 Posted June 28, 2007 Report Share Posted June 28, 2007 If possible something in space would be interesting, but it's not that important. I'd quite like to do something in space as well, but I think the lack of Internet connectivity and disorienting zero gravity might get in the way slightly. Quote DarkRadiant homepage ⋄ DarkRadiant user guide ⋄ OrbWeaver's Dark Ambients ⋄ Blender export scripts Link to post Share on other sites
Nyarlathotep 0 Posted June 29, 2007 Report Share Posted June 29, 2007 Quote Link to post Share on other sites
mohij 0 Posted June 30, 2007 Author Report Share Posted June 30, 2007 Hehe ;-)I meant something with 3d or 2d, like the clipper tool or something. Quote Link to post Share on other sites
greebo 84 Posted June 30, 2007 Report Share Posted June 30, 2007 Hm, maybe this would be something appropriate? Bounding Box Creation for models. It's currently assigned to OrbWeaver, so I don't know if he rather wants to do it himself? I think this can also be useful for models already existing in the map. A la: select a model > right-click > "Create Monster Clip Brush". Quote Link to post Share on other sites
OrbWeaver 662 Posted June 30, 2007 Report Share Posted June 30, 2007 That certainly needs doing. There are two components for that feature: 1. Ensure that there is a means for the BrushCreator (or whatever is currently responsible for creating new brushes) to generate a new brush from an arbitrary AABB. You might need a function like BrushCreator::createFromAABB(const AABB& aabb) to do this.2. Add an option to the Model Selector dialog to create a monsterclip brush using the AABB of the created model. I suggest some kind of "Advanced" section or dialog, with this option as well as the other needed model creation options such as noshadows. Greebo's menu option would also be useful. Quote DarkRadiant homepage ⋄ DarkRadiant user guide ⋄ OrbWeaver's Dark Ambients ⋄ Blender export scripts Link to post Share on other sites
mohij 0 Posted July 3, 2007 Author Report Share Posted July 3, 2007 After programming 5 hours or so I noticed that my approach on the "add bounding box" checkbox can't work out. The ModelSelector just returns a Model and a Skin name.Everything else has to be done by the caller.So a tick box "create bounding box" would have to be evaluated by the caller too. My approach was to change ModelSelector into a "normal" singleton class with a getInstance function. I also added another function that returned the state of the "create bounding box" checkbox. After changing the Ortho Menu to use the new interface and evaluate the new option I noticed that the Ortho Menu isn't the only one that uses the ModelSelector. Reimplementing the evaluation of the options everywhere the ModelSelector is used seems stupid, especially when even more options are added. Any ideas how to solve that in an elegant way? Quote Link to post Share on other sites
greebo 84 Posted July 3, 2007 Report Share Posted July 3, 2007 Here, it's probably best to leave the ModelSelector non-singleton, so that multiple clients can use it. I haven't checked how it's implemented now, but it's usually enough to add a getWidget() method to the class, so that it can be packed into any parent container. An example for this is the ShaderSelector class, which is used by the LightInspector, the Find & Replace dialog and so on. Each client which wants to feature a ModelSelector, would instantiate a separate ModelSelector class and pack it into its own dialog, adding any widgets that are necessary in addition to the pure ModelSelecor. If the instantiation of multiple ModelSelector objects is expensive in terms of loading time and memory, we could take the approach of out-sourcing the model treestore into a singleton class, so that the models have to be loaded only once. Please feel free to ask, if I didn't explain it properly or if I talked rubbish. Quote Link to post Share on other sites
OrbWeaver 662 Posted July 3, 2007 Report Share Posted July 3, 2007 It shouldn't need to be that complex, the clients don't have to worry about GTK widgets themselves. All they are interested in is a single boolean value to indicate whether the bounding box brush should be created or not. For this, I recommend expanding the ModelAndSkin struct into a more generic ModelCreationSettings object which, in addition to the skin and model name, includes a boolean value indicating the state of the checkbox. This can then be enhanced in future with whatever other ancillary options are required. Quote DarkRadiant homepage ⋄ DarkRadiant user guide ⋄ OrbWeaver's Dark Ambients ⋄ Blender export scripts Link to post Share on other sites
mohij 0 Posted July 3, 2007 Author Report Share Posted July 3, 2007 OrbWeaver: Your approach worked out very well, since it is backwards compatible (so I don't have to change all callers at once). One more question, how can I retrieve a model from a node? I guess with localAABB() I can then get it's AABB. Quote Link to post Share on other sites
greebo 84 Posted July 3, 2007 Report Share Posted July 3, 2007 You can try to cast the Node onto an EntityNode and check the spawnargs (name != model && !name.empty()). There is no ModelNode you can dynamic_cast the scene::INodePtr onto currently, I think. What do you need exactly? Quote Link to post Share on other sites
mohij 0 Posted July 3, 2007 Author Report Share Posted July 3, 2007 ModelSelectorResult ms = ui::ModelSelector::chooseModel(); // If a model was selected, create the entity and set its model key if (!ms.model.empty()) { try { scene::INodePtr node = Entity_createFromSelection(MODEL_CLASSNAME, self->_lastPoint); Node_getEntity(node)->setKeyValue("model", ms.model); Node_getEntity(node)->setKeyValue("skin", ms.skin); // If 'createClip' is ticked, create a clip Brush if (ms.createClip) { scene::INodePtr node(GlobalBrushCreator().createBrush()); Node_getTraversable(GlobalMap().findOrInsertWorldspawn())->insert(node); scene::Path brushpath(GlobalSceneGraph().root()); brushpath.push(GlobalMap().getWorldspawn()); brushpath.push(node); selectPath(brushpath, true); Scene_BrushResize_Selected(GlobalSceneGraph(), //AABB (Vector3(1,2,3),Vector3(1,1,1)), .localAABB(), "textures/common/monster_clip"); //AABB::createFromMinMax(mins, maxs), }I need to get the AABB of that model for Scene_BrushResize_Selected. btw. Is there an easier way to create a brush, I don't really understand what all those commands do, I just copied them from XYWnd.cpp. Quote Link to post Share on other sites
greebo 84 Posted July 3, 2007 Report Share Posted July 3, 2007 I see what you need now. You can call the Instance::worldAABB() method for this. Retrieving the instance from the node is not trivial, but part of the code is already there, so you can reuse it. You'll need a scene::Path to lookup the newly created Instance: scene::Path brushpath(GlobalSceneGraph().root()); brushpath.push(GlobalMap().getWorldspawn()); brushpath.push(node);This brushPath object can be used to find the instance. Try this (include scenelib.h): scene::Instance& instance = findInstance(brushPath); AABB brushAABB(instance.worldAABB());This will give you a reference to the newly created BrushInstance. Once you have the instance, you can call worldAABB() to retrieve the bounds. The brush creation code is ok. It can of course be simplified, but basically it's always this way: Create a node, insert it into the parent scene::Traversable (which triggers instantiation). Done. Quote Link to post Share on other sites
mohij 0 Posted July 3, 2007 Author Report Share Posted July 3, 2007 I sort-of understand it only a little bit better now, this IS complicated... ModelSelectorResult ms = ui::ModelSelector::chooseModel(); // If a model was selected, create the entity and set its model key if (!ms.model.empty()) { try { scene::INodePtr modelNode = Entity_createFromSelection(MODEL_CLASSNAME, self->_lastPoint); Node_getEntity(modelNode)->setKeyValue("model", ms.model); Node_getEntity(modelNode)->setKeyValue("skin", ms.skin); // If 'createClip' is ticked, create a clip Brush if (ms.createClip) { // get the model scene::Path brushPath(GlobalSceneGraph().root()); brushPath.push(GlobalMap().getWorldspawn()); brushPath.push(modelNode); scene::Instance& instance = findInstance(brushPath); // retrieve the AABB AABB brushAABB(instance.worldAABB()); scene::INodePtr brushNode(GlobalBrushCreator().createBrush()); Node_getTraversable(GlobalMap().findOrInsertWorldspawn())->insert(brushNode); Scene_BrushResize_Selected(GlobalSceneGraph(), brushAABB, "textures/common/monster_clip"); }This segfaults because findInstance finds nothing.Could it be that Scene_BrushResize_Selected only works on the Brush visually selected in the XY view? Then that function is totally misplaced there. (and that function seems not to use the first argument...) Quote Link to post Share on other sites
greebo 84 Posted July 3, 2007 Report Share Posted July 3, 2007 The modelNode is never inserted and hence never instantiated. You'll have to insert it as child of scenegraph root (which is the only valid location in the scenegraph btw, all entities have to be children of root):scene::INodePtr modelNode = Entity_createFromSelection(MODEL_CLASSNAME, self->_lastPoint); Node_getTraversable(GlobalScenegraph().root())->insert(modelNode);Does this work? Quote Link to post Share on other sites
mohij 0 Posted July 3, 2007 Author Report Share Posted July 3, 2007 Wait a moment, why did the model show up when it was never inserted into the tree? Edit: Now it shows: libs/instancelib.h:183 assertion failure: InstanceSet::insert - element already exists Quote Link to post Share on other sites
greebo 84 Posted July 3, 2007 Report Share Posted July 3, 2007 Ok, seems like the node is already inserted somewhere, probably by the Entity_createFromSelection() routine. Wait, the brushPath in the above code (which should be named modelPath btw) is not correct. It should be like this:scene::Path brushPath(GlobalSceneGraph().root()); brushPath.push(modelNode);Because the model is contained in an entity which is always child of the map root. Quote Link to post Share on other sites
mohij 0 Posted July 3, 2007 Author Report Share Posted July 3, 2007 It seems that this first part of the code works now. But no brush is created and on drag it shows Warning: removed degenerate brush! I replaced the AABB in Scene_BrushResize_Selected with a manually constructed one and it still shows the same message. So I guess that Scene_BrushResize_Selected doesn't work. I think this function is not intended for this purpose, perhaps I find a better one.I'll take a look tomorrow *yawn*. Quote Link to post Share on other sites
greebo 84 Posted July 3, 2007 Report Share Posted July 3, 2007 You might want to take a look at Brush_ConstructCuboid in brushmanip.cpp. This appears to resize an existing brush to fit the given AABB. It requires an existing brush as argument. edit: scrap that, I think I know what the problem with the above code is. The Scene_BrushResize_Selected routine requires the target brush to be selected, so you'll have to call selectPath() on the brush path (not the modelPath) first. Quote Link to post Share on other sites
mohij 0 Posted July 3, 2007 Author Report Share Posted July 3, 2007 That function is not listed in the .h file and is called by Scene_BrushResize_Selected. If changing that is fine then ConstruchtCuboid is the best choice I guess. Quote Link to post Share on other sites
mohij 0 Posted July 4, 2007 Author Report Share Posted July 4, 2007 Woho, I got it to work.Even though I wrote another function that calls ConstructCuboid more directly than Scene_BrushResize_Selected. That function was to suspicious to me, since visually selecting a brush to operate on it seems wrong. And worldAABB returned the wrong AABB for small models. childBounds produces correct results. But I have no idea what the difference is, I just did some trial-and-error. Now I'm thinking if it would make sense to add a way to hide or gray out the option, since in some cases adding a bounding box doesn't make sense (eg. when changing the model). Quote Link to post Share on other sites
greebo 84 Posted July 4, 2007 Report Share Posted July 4, 2007 If the worldAABB is not producing desirable results, you can try to cast the Instance onto a Bounded object and retrieve the bounding box via localAABB(). This is what should be happening when you call worldAABB() too, but you can never be sure with the Radiant codebase. Anyway, good to see you're making progress. Quote Link to post Share on other sites
mohij 0 Posted July 4, 2007 Author Report Share Posted July 4, 2007 As I said, the childBounds() returns the correct AABB (no idea what the difference is). In radiant/selection/algorithm/Primitives.cpp in createCMFromSelection() the ModelSelector is also used, but I have no idea where this function is actually used in DarkRadiant. Could you tell me where this feature (what ever it might be) hides? I think I will hide the "create bounding box" option when called from the ModelPropertyEditor. Quote Link to post Share on other sites
greebo 84 Posted July 4, 2007 Report Share Posted July 4, 2007 The createCMFromSelection() is the Collision Model export function. It is linked to a Command in the EventManager, which means that it can be called via the Menu items and the Toolbar buttons. The link is established here: GlobalEventManager().addCommand( "BrushExportCM", FreeCaller<selection::algorithm::createCMFromSelection>() ); This method doesn't need to display the "create monsterclip" option, if that's what you want to know. Quote Link to post Share on other sites
mohij 0 Posted July 4, 2007 Author Report Share Posted July 4, 2007 Should I grey out the options seperately (keeps them still ticked which could cause some confusion) or hide them altogether (prevents showing only some of the options)? Edit: greying them out seperately can make the function inverface quite bloated once more functions are added. Quote Link to post Share on other sites
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.