1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229
|
#pragma once
#include "iundo.h"
#include "imodel.h"
#include "math/AABB.h"
#include "imodelsurface.h"
#include <memory>
class Ray;
/* FORWARD DECLS */
namespace model
{
class StaticModelSurface;
typedef std::shared_ptr<StaticModelSurface> StaticModelSurfacePtr;
}
class IRenderableCollector;
class RendererLight;
class SelectionTest;
class Selector;
namespace model
{
/**
* \brief
* IModel implementing class representing a static model
*
* A StaticModel is made up of one or more StaticModelSurface
* objects, each of which contains a number of polygons with the same texture.
* Rendering a StaticModel involves rendering all of its surfaces,
* submitting their geometry via OpenGL calls.
*/
class StaticModel :
public IModel,
public IUndoable
{
private:
// greebo: StaticModelSurfaces are shared objects, the actual shaders
// and the model skin handling are managed by the nodes/imodels referencing them
struct Surface
{
// The (shared) surface object
StaticModelSurfacePtr surface;
// The (unmodified) surface object
StaticModelSurfacePtr originalSurface;
// The shader this surface is using
ShaderPtr shader;
Surface()
{}
// Constructor
Surface(const StaticModelSurfacePtr& surface_) :
surface(surface_),
originalSurface(surface)
{}
};
typedef std::vector<Surface> SurfaceList;
// Vector of renderable surfaces for this model
SurfaceList _surfaces;
// The current working scale
Vector3 _scaleTransformed;
// The scale for this model (is 1,1,1 for an unmodified one)
Vector3 _scale;
// Local AABB for this model
AABB _localAABB;
// Vector of materials used by this model (one for each surface)
mutable std::vector<std::string> _materialList;
// The filename this model was loaded from
std::string _filename;
// The VFS path to this model
std::string _modelPath;
// We need to keep a reference for skin swapping
RenderSystemWeakPtr _renderSystem;
// Undoable stuff
IUndoStateSaver* _undoStateSaver;
sigc::signal<void> _sigShadersChanged;
sigc::signal<void> _sigSurfaceScaleApplied;
private:
// Update the list of materials by querying each surface for its current
// material.
void updateMaterialList() const;
// Ensure all shaders for the active materials
void captureShaders();
void undoSave();
void applyScaleToSurfaces();
void foreachVisibleSurface(const std::function<void(const Surface& s)>& func) const;
public:
/**
* Construct a StaticModel with the given set of surfaces.
*/
StaticModel(const std::vector<StaticModelSurfacePtr>& surfaces);
/**
* Copy constructor: re-use the surfaces from the other model
* but make it possible to assign custom skins to the surfaces.
*/
StaticModel(const StaticModel& other);
void connectUndoSystem(IUndoSystem& undoSystem);
void disconnectUndoSystem(IUndoSystem& undoSystem);
void setRenderSystem(const RenderSystemPtr& renderSystem);
// A signal that is emitted after the captured shaders have been changed (or cleared)
sigc::signal<void>& signal_ShadersChanged();
// Signal emitted when any surface scale has been changed
sigc::signal<void>& signal_SurfaceScaleApplied();
/**
* Return the number of surfaces in this model.
*/
int getSurfaceCount() const override
{
return static_cast<int>(_surfaces.size());
}
/**
* Return the number of vertices in this model, by summing the vertex
* counts for each surface.
*/
int getVertexCount() const override;
/** Return the polycount (tricount) of this model by summing the surface
* polycounts.
*/
int getPolyCount() const override;
const IModelSurface& getSurface(unsigned surfaceNum) const override;
/**
* Return the enclosing AABB for this model.
*/
const AABB& localAABB() const override
{
return _localAABB;
}
/** Return the list of active materials for this model.
*/
const std::vector<std::string>& getActiveMaterials() const override;
// Sets the filename this model was loaded from
void setFilename(const std::string& name);
// Returns the filename this model was loaded from
virtual std::string getFilename() const override;
// Returns the VFS path to the model file
virtual std::string getModelPath() const override;
void setModelPath(const std::string& modelPath);
/** Apply the given skin to this model.
*/
void applySkin(const decl::ISkin::Ptr& skin) override;
/**
* Selection test. Test each surface against the SelectionTest object and
* if the surface is selected, add it to the selector.
*
* @param selector
* Selector object which builds a list of selectables.
*
* @param test
* The SelectionTest object defining the 3D properties of the selection.
*
* @param localToWorld
* Object to world space transform.
*/
void testSelect(Selector& selector,
SelectionTest& test,
const Matrix4& localToWorld);
// Returns true if the given ray intersects this model geometry and fills in
// the exact point in the given Vector3, returns false if no intersection was found.
bool getIntersection(const Ray& ray, Vector3& intersection, const Matrix4& localToWorld);
/**
* Return the list of StaticModelSurface objects.
*/
const SurfaceList& getSurfaces() const;
// Revert to base scale (returns true if the scale was actually changed by this call)
bool revertScale();
// TransformationChanged, apply the given scale to the "working copy"
void evaluateScale(const Vector3& scale);
// Freeze transform, store new base scale
void freezeScale();
// Undoable implementation
IUndoMementoPtr exportState() const override;
void importState(const IUndoMementoPtr& state) override;
// Returns the current base scale of this model
const Vector3& getScale() const;
void foreachSurface(const std::function<void(const StaticModelSurface&)>& func) const;
};
typedef std::shared_ptr<StaticModel> StaticModelPtr;
}
|