Skip to content

Commit

Permalink
#5576: A StaticModelSurface has to be constructed with non-empty vert…
Browse files Browse the repository at this point in the history
…ex and index data.

Add a new constructor accepting the rvalue-refs of the vertex and index vectors, and move the PicoModel-specific conversion code to PicoModelLoader which will create the suitable data structures before passing them to the move constructor. Prepare the AseModelLoader to use the same pattern.
  • Loading branch information
codereader committed Apr 4, 2021
1 parent 80391e4 commit 142122d
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 69 deletions.
68 changes: 13 additions & 55 deletions radiantcore/model/StaticModelSurface.cpp
Expand Up @@ -13,53 +13,21 @@
namespace model
{

// Constructor. Copy the provided picoSurface_t structure into this object
StaticModelSurface::StaticModelSurface(picoSurface_t* surf)
: _defaultMaterial(""),
_dlRegular(0),
_dlProgramVcol(0),
_dlProgramNoVCol(0)
StaticModelSurface::StaticModelSurface(std::vector<ArbitraryMeshVertex>&& vertices, std::vector<unsigned int>&& indices) :
_vertices(vertices),
_indices(indices),
_dlRegular(0),
_dlProgramVcol(0),
_dlProgramNoVCol(0)
{
// Capturing the shader happens later on when we have a RenderSystem reference

// Get the number of vertices and indices, and reserve capacity in our
// vectors in advance by populating them with empty structs.
int nVerts = PicoGetSurfaceNumVertexes(surf);
_nIndices = PicoGetSurfaceNumIndexes(surf);
_vertices.resize(nVerts);
_indices.resize(_nIndices);

// Stream in the vertex data from the raw struct, expanding the local AABB
// to include each vertex.
for (int vNum = 0; vNum < nVerts; ++vNum) {

// Get the vertex position and colour
Vertex3f vertex(PicoGetSurfaceXYZ(surf, vNum));

Normal3f normal = PicoGetSurfaceNormal(surf, vNum);

// Expand the AABB to include this new vertex
_localAABB.includePoint(vertex);

_vertices[vNum].vertex = vertex;
_vertices[vNum].normal = normal;
_vertices[vNum].texcoord = TexCoord2f(PicoGetSurfaceST(surf, 0, vNum));
_vertices[vNum].colour =
getColourVector(PicoGetSurfaceColor(surf, 0, vNum));
}

// Stream in the index data
picoIndex_t* ind = PicoGetSurfaceIndexes(surf, 0);
for (unsigned int i = 0; i < _nIndices; i++)
// Expand the local AABB to include all vertices
for (const auto& vertex : _vertices)
{
_indices[i] = ind[i];
_localAABB.includePoint(vertex.vertex);
}

// Calculate the tangent and bitangent vectors
calculateTangents();

// Construct the DLs
createDisplayLists();
calculateTangents();
createDisplayLists();
}

StaticModelSurface::StaticModelSurface(const StaticModelSurface& other) :
Expand All @@ -83,19 +51,9 @@ StaticModelSurface::~StaticModelSurface()
glDeleteLists(_dlProgramVcol, 1);
}

// Convert byte pointers to colour vector
Vector3 StaticModelSurface::getColourVector(unsigned char* array) {
if (array) {
return Vector3(array[0] / 255.0f, array[1] / 255.0f, array[2] / 255.0f);
}
else {
return Vector3(1.0f, 1.0f, 1.0f); // white
}
}

// Tangent calculation
void StaticModelSurface::calculateTangents() {

void StaticModelSurface::calculateTangents()
{
// Calculate the tangents and bitangents using the indices into the vertex
// array.
for (Indices::iterator i = _indices.begin();
Expand Down
5 changes: 3 additions & 2 deletions radiantcore/model/StaticModelSurface.h
@@ -1,7 +1,6 @@
#pragma once

#include "GLProgramAttributes.h"
#include "picomodel/lib/picomodel.h"
#include "render.h"
#include "math/AABB.h"

Expand Down Expand Up @@ -31,6 +30,7 @@ class StaticModelSurface :
public IIndexedModelSurface,
public OpenGLRenderable
{
private:
// Name of the material this surface is using by default (without any skins)
std::string _defaultMaterial;

Expand Down Expand Up @@ -74,7 +74,8 @@ class StaticModelSurface :
std::string cleanupShaderName(const std::string& mapName);

public:
StaticModelSurface(picoSurface_t* surf);
// Move-construct this static model surface from the given vertex- and index array
StaticModelSurface(std::vector<ArbitraryMeshVertex>&& vertices, std::vector<unsigned int>&& indices);

// Copy-constructor.
StaticModelSurface(const StaticModelSurface& other);
Expand Down
8 changes: 3 additions & 5 deletions radiantcore/model/import/AseModel.cpp
Expand Up @@ -548,14 +548,12 @@ static void shadername_convert(char* shaderName)
namespace model
{

#if 0
StaticModelSurface& AseModel::addSurface()
AseModel::Surface& AseModel::addSurface()
{
return *_surfaces.emplace_back(std::make_shared<StaticModelSurface>());
return _surfaces.emplace_back();
}
#endif

const std::vector<StaticModelSurfacePtr>& AseModel::getSurfaces() const
std::vector<AseModel::Surface>& AseModel::getSurfaces()
{
return _surfaces;
}
Expand Down
16 changes: 13 additions & 3 deletions radiantcore/model/import/AseModel.h
Expand Up @@ -8,13 +8,23 @@ namespace model

class AseModel
{
public:
struct Surface
{
std::string material;

std::vector<ArbitraryMeshVertex> vertices;
std::vector<unsigned int> indices;
};

private:
std::vector<StaticModelSurfacePtr> _surfaces;
std::vector<Surface> _surfaces;

public:
StaticModelSurface& addSurface();
Surface& addSurface();

const std::vector<StaticModelSurfacePtr>& getSurfaces() const;
// Read/Write access
std::vector<Surface>& getSurfaces();

static std::shared_ptr<AseModel> CreateFromStream(std::istream& stream);
};
Expand Down
15 changes: 14 additions & 1 deletion radiantcore/model/import/AseModelLoader.cpp
Expand Up @@ -28,10 +28,23 @@ IModelPtr AseModelLoader::loadModelFromPath(const std::string& path)
return IModelPtr();
}

// Parse the ASE model data from the given stream
std::istream stream(&(file->getInputStream()));
auto model = AseModel::CreateFromStream(stream);

auto staticModel = std::make_shared<StaticModel>(model->getSurfaces());
// Convert the AseModel to StaticModelSurfaces, destructing it during the process
std::vector<StaticModelSurfacePtr> staticSurfaces;

for (auto& aseSurface : model->getSurfaces())
{
// Move the vertex and index data to construct the StaticModelSurface
auto& staticSurface = staticSurfaces.emplace_back(std::make_shared<StaticModelSurface>(
std::move(aseSurface.vertices), std::move(aseSurface.indices)));

staticSurface->setDefaultMaterial(aseSurface.material);
}

auto staticModel = std::make_shared<StaticModel>(staticSurfaces);

// Set the filename
staticModel->setFilename(os::getFilename(file->getName()));
Expand Down
55 changes: 52 additions & 3 deletions radiantcore/model/picomodel/PicoModelLoader.cpp
Expand Up @@ -19,9 +19,21 @@ namespace model {

namespace
{
size_t picoInputStreamReam(void* inputStream, unsigned char* buffer, size_t length) {
size_t picoInputStreamReam(void* inputStream, unsigned char* buffer, size_t length)
{
return reinterpret_cast<InputStream*>(inputStream)->read(buffer, length);
}

// Convert byte pointers to colour vector
inline Vector3 getColourVector(unsigned char* array)
{
if (array)
{
return Vector3(array[0] / 255.0f, array[1] / 255.0f, array[2] / 255.0f);
}

return Vector3(1.0f, 1.0f, 1.0f); // white
}
} // namespace

PicoModelLoader::PicoModelLoader(const picoModule_t* module, const std::string& extension) :
Expand Down Expand Up @@ -197,8 +209,45 @@ StaticModelSurfacePtr PicoModelLoader::CreateSurface(picoSurface_t* picoSurface,
// Fix the normals of the surface (?)
PicoFixSurfaceNormals(picoSurface);

// Create the StaticModelSurface object and add it to the vector
auto staticSurface = std::make_shared<StaticModelSurface>(picoSurface);
// Convert the pico vertex data to the types we need to construct a StaticModelSurface

// Get the number of vertices and indices, and reserve capacity in our
// vectors in advance by populating them with empty structs.
auto numVertices = PicoGetSurfaceNumVertexes(picoSurface);
unsigned int numIndices = PicoGetSurfaceNumIndexes(picoSurface);

std::shared_ptr<StaticModelSurface> staticSurface;

{
// Allocate the vectors that will be moved to the surface at end of scope
std::vector<ArbitraryMeshVertex> vertices(numVertices);
std::vector<unsigned int> indices(numIndices);

// Stream in the vertex data from the raw struct, expanding the local AABB
// to include each vertex.
for (int vNum = 0; vNum < numVertices; ++vNum) {

// Get the vertex position and colour
Vertex3f vertex(PicoGetSurfaceXYZ(picoSurface, vNum));

Normal3f normal = PicoGetSurfaceNormal(picoSurface, vNum);

vertices[vNum].vertex = vertex;
vertices[vNum].normal = normal;
vertices[vNum].texcoord = TexCoord2f(PicoGetSurfaceST(picoSurface, 0, vNum));
vertices[vNum].colour = getColourVector(PicoGetSurfaceColor(picoSurface, 0, vNum));
}

// Stream in the index data
picoIndex_t* ind = PicoGetSurfaceIndexes(picoSurface, 0);

for (unsigned int i = 0; i < numIndices; i++)
{
indices[i] = ind[i];
}

staticSurface = std::make_shared<StaticModelSurface>(std::move(vertices), std::move(indices));
}

staticSurface->setDefaultMaterial(DetermineDefaultMaterial(picoSurface, extension));

Expand Down

0 comments on commit 142122d

Please sign in to comment.