map objects module ================== Objective: ---------- #1 Turn the md3 code into a module. That is handle all aspects of map objects in a module. This involves: - the rendering of the model (sleep mode / shader reload are associated issues) - the manipulation in the editor (moving, rotating, (scaling?)) #2 Have an API generic enough to support other formats than md3. (md1 / md2 for multiple games support, any other formats). What we have: ------------- What is the current implementation of md3 support? Were are the important features that we will need to work with? "misc_model" is the required classname for any map object entity_t::md3Class eclass_t *md3Class; This holds the actual md3 object and the rendering information (tri soup, shader etc.) entity_t also has vRotation and vScale which are particular to the model for selection of the brush (selection is preliminary step before any manipulation operation), we create a bounding box from the md3 information and use the entity's brush list as storage for it. Requirements: ------------- Some technical requirements go on top of our objective given the existing implementation. The most important one is that the changes applied to the core must remain focused around the md3 functionality, and must also lay out the basics of some wider changes. We can identify some of those changes: - introducing a more generalized way of selecting and manipulation things in the editor. - introducing a more generic way of rendering objects in the editor. More specifically, the details of rendering and manipulation: transformation translate&rotate: A transformation increment is provided The object is transformed by a specified increment. Depending on the object type, the transformations may affect the local coordinate space transformation instead of the object. This local transformation is used in selection and rendering. selection: ray: Radiant asks model for its world-relative axis-alignedbounding box. Radiant does intersection test with this bounding box. If test shows intersection, radiant gives model a ray_t, model tests for intersection with ray, model returns bool true if intersection A selection ray in world-space (origin+direction) is provided. The object must say whether or not it intersects with the ray. map objects have a special configuration to test on bounding box or trisoup this is set in preferences independently from the true/false selection tests area: radiant uses a bounding box for area selection. (bounding box can be infinite in some directions for the 'select tall' operations, in practice we just make them big enough). rendering: geometry: Radiant tells the object what combination of 4 opengl states is currently active: none - draw as wireframe fill - draw as filled alpha blend - provide an opacity value texture_2d - provide a texture and texture coordinates lighting - provide normals, enable/disable smooth shading The object uses opengl to set up its geometry and to draw itself. material: The object provides a material name and is assigned a reference to a shader that matches the name. The shader contains the texture ID and the opacity value. The shader is a reference to an external script and must be refreshed on request. Proposed implementation: ======================== changes in shared interfaces (include/ directory): -------------------------------------------------- The following new interfaces will be added: most likely those interfaces will be implemented in the module /*! something that can be selected */ class ISelect { bool TestRay(ray_t) = 0 bool TestBox(vec3_t vec_min, vec3_t vec_max) = 0; } /*! something that can be selected for edition this must be synced with entity epairs (such as origin and angles keys) */ class IEdit { void Translate(vec3_t v) = 0; void Rotate(vec3_t origin, vec3_t angles) = 0; } for rendering, the existing IGL2DWindow and IGL3DWindow APIs we can define class IRender : public IGL2DWindow, public IGL3DWindow so that we have the Render2D and Render3D on the same class entity_t will have to be modified, adding the following struct: typedef struct entity_interfaces_s { ISelect *pSelect IEdit *pEdit IRender *pRender } entity_interfaces_t; When one of the pointers inside entity_t::entity_interfaces is != we will handle the entity differently that what we are doing by default. We will rely on these APIs for rendering, manipulation etc. the AABB issue: changes in the core: -------------------- In all cases where the entity_t has to be drawn, tested for selection, manipulated (translation and rotation), add new code to go through the APIs. md3 module: ----------- static function table API - registering of "model" module need some minors? "md3" etc. - BuildEntity(entity_t) if an entity involved with models is found, core will call this entity_t::entity_interfaces will be filled with the relevant classes (NOTE:L we don't have a need right now to manipulate a model that would not be part of an entity. so let's not try to guess what it would be like) CModel stores the trisoup, local AABBs, references to shaders (CModel potentially needs a CModelManager to handle model loads and cached models queries) CModelEntity implements IRender ISelect IEdit stores an entity_t* implements the interfaces pointed to in the entity_t is reference counted obviously stores a CModel*, calls up to it with entity information for rendering