2021SC@SDUSC
catalogue
1. Structure and Deconstruction
2.GetBoundingSphere and ComputeBoundingSphere
The modelloader class was mentioned in the previous sections. This section will formally describe the content of the Model class.
Model
Like Shader and Texture, the model takes its own loader as a friend class at the beginning. At the same time, we can see that the so-called model is the combination of a series of meshes.
namespace Loaders { class ModelLoader; } /** * A model is a combinaison of meshes */ class Model { friend class Loaders::ModelLoader; public: /** * Returns the meshes */ const std::vector<Mesh*>& GetMeshes() const; /** * Returns the material names */ const std::vector<std::string>& GetMaterialNames() const; /** * Returns the bounding sphere of the model */ const OvRendering::Geometry::BoundingSphere& GetBoundingSphere() const; private: Model(const std::string& p_path); ~Model(); void ComputeBoundingSphere(); public: const std::string path; private: std::vector<Mesh*> m_meshes; std::vector<std::string> m_materialNames; Geometry::BoundingSphere m_boundingSphere; };
A model object needs to include the following important information: meshes, material s, and bounding sphere. In addition, as a tool class, it also needs the storage path path of the model.
In order to store the model mesh, we need a vector of type mesh pointer and a vector of type string to store the name of the material.
1. Structure and Deconstruction
OvRendering::Resources::Model::Model(const std::string & p_path) : path(p_path) { } OvRendering::Resources::Model::~Model() { for (auto mesh : m_meshes) delete mesh; }
The constructor of model is very simple. You only need to assign the model storage path to its own path variable; The main function of the destructor is to destroy each grid pointer. Here, use the variable mesh to traverse the grid vector, take out the pointer of each grid object and delete it.
2.GetBoundingSphere and ComputeBoundingSphere
const OvRendering::Geometry::BoundingSphere& OvRendering::Resources::Model::GetBoundingSphere() const { return m_boundingSphere; }
The function to obtain the collision ball object returns its own collision ball object. To obtain this object, you need to call its own private function ComputeBoundingSphere (). Next, let's take a look at its details.
void OvRendering::Resources::Model::ComputeBoundingSphere() { if (m_meshes.size() == 1) { m_boundingSphere = m_meshes[0]->GetBoundingSphere(); }
At first, it is necessary to judge the number of meshes, because a patch model composed of a single mesh may appear. If the size of the mesh vector is 1, then m_boundingSphere is directly assigned to the collision ball object of the first mesh.
In other cases, we need to carry out more complex processing, first for our own M_ The boundingsphere is given an initial value, the position of the center point is equal to the zero vector, and the radius is 0.
else { m_boundingSphere.position = OvMaths::FVector3::Zero; m_boundingSphere.radius = 0.0f;
Then judge whether the grid vector is empty, and do not process when the vector is empty; Otherwise, start the calculation. The steps here are similar to those in calculating the collision box of mesh mesh. First, assign the maximum and minimum values of floating-point numbers limited by std to the minimum vertex coordinates and the maximum vertex coordinates respectively. Note that here, assign the minimum to the maximum and the maximum to the minimum.
if (!m_meshes.empty()) { float minX = std::numeric_limits<float>::max(); float minY = std::numeric_limits<float>::max(); float minZ = std::numeric_limits<float>::max(); float maxX = std::numeric_limits<float>::min(); float maxY = std::numeric_limits<float>::min(); float maxZ = std::numeric_limits<float>::min();
Then traverse all grids, first obtain the collision box information of the current grid, then subtract the center coordinate of the collision box from the radius, compare it with the above minimum coordinate to get the minimum value, and update the minimum coordinate with the final result; The update of maximum coordinates is similar, but subtraction needs to be changed to addition, and the maximum value is taken during comparison.
for (const auto& mesh : m_meshes) { const auto& boundingSphere = mesh->GetBoundingSphere(); minX = std::min(minX, boundingSphere.position.x - boundingSphere.radius); minY = std::min(minY, boundingSphere.position.y - boundingSphere.radius); minZ = std::min(minZ, boundingSphere.position.z - boundingSphere.radius); maxX = std::max(maxX, boundingSphere.position.x + boundingSphere.radius); maxY = std::max(maxY, boundingSphere.position.y + boundingSphere.radius); maxZ = std::max(maxZ, boundingSphere.position.z + boundingSphere.radius); } m_boundingSphere.position = OvMaths::FVector3{ minX + maxX, minY + maxY, minZ + maxZ } / 2.0f; m_boundingSphere.radius = OvMaths::FVector3::Distance(m_boundingSphere.position, { minX, minY, minZ }); } } }
After traversing all meshes, min will become the collision ball surface vertex closest to the coordinate origin, and max will become the collision ball surface vertex far from the coordinate origin. With this information, we construct a collision ball containing all meshes. The coordinate of its center point is equal to (max+min)/2, and the radius is equal to the distance between the center point and the minimum coordinate (or the maximum coordinate).
There is less content in this section, and more content loaded by the model has been described earlier [Overload game engine] source code analysis 8: OvRendering function library (6) As described in ModelLoader, you can read the details.