Move morph_data::morph_times into a trailing allocation

Initially, this just makes the code more complicated.  In the end, it
will allow choosing the array size dynamically.
This commit is contained in:
Kp 2020-02-26 05:07:34 +00:00
parent 00df407381
commit 74f8fd0d4d
3 changed files with 62 additions and 7 deletions

View file

@ -0,0 +1,46 @@
/*
* This file is part of the DXX-Rebirth project <https://www.dxx-rebirth.com/>.
* It is copyright by its individual contributors, as recorded in the
* project's Git history. See COPYING.txt at the top level for license
* terms and a link to the Git history.
*/
#pragma once
#include <cstddef>
/* Partial implementation of std::span (C++20) for pre-C++20 compilers.
* As of this writing, there are no released compilers with C++20
* support, so this implementation is always used.
*
* This implementation covers only the minimal functionality used by
* Rebirth. It is not intended as a drop-in replacement for arbitrary
* use of std::span.
*/
template <typename T>
class span
{
std::size_t extent;
T *ptr;
public:
span(T *p, std::size_t l) :
extent(l), ptr(p)
{
}
T *begin() const
{
return ptr;
}
T *end() const
{
return ptr + extent;
}
std::size_t size() const
{
return extent;
}
T &operator[](std::size_t i) const
{
return *(ptr + i);
}
};

View file

@ -35,6 +35,7 @@ COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
#include "compiler-array.h"
#ifdef dsx
#include "compiler-span.h"
#include "fwd-object.h"
#include <memory>
@ -74,11 +75,11 @@ struct morph_data : prohibit_void_ptr<morph_data>
physics_info morph_save_phys_info;
array<submodel_state, MAX_SUBMODELS> submodel_active; // which submodels are active
array<vms_vector, MAX_VECS> morph_vecs, morph_deltas;
array<fix, MAX_VECS> morph_times;
array<int, MAX_SUBMODELS>
n_morphing_points, // how many active points in each part
submodel_startpoints; // first point for each submodel
static ptr create(object_base &);
span<fix> get_morph_times();
private:
static void *operator new(std::size_t bytes, max_vectors);
explicit morph_data(object_base &o);

View file

@ -99,8 +99,7 @@ submodel_data parse_model_data_header(const polymodel &pm, const unsigned submod
void *morph_data::operator new(std::size_t, const max_vectors max_vecs)
{
(void)max_vecs;
return ::operator new(sizeof(morph_data));
return ::operator new(sizeof(morph_data) + (max_vecs.count * sizeof(fix)));
}
morph_data::ptr morph_data::create(object_base &o)
@ -114,11 +113,17 @@ morph_data::morph_data(object_base &o) :
DXX_POISON_VAR(submodel_active, 0xcc);
DXX_POISON_VAR(morph_vecs, 0xcc);
DXX_POISON_VAR(morph_deltas, 0xcc);
DXX_POISON_VAR(morph_times, 0xcc);
const auto morph_times = get_morph_times();
DXX_POISON_MEMORY(morph_times.begin(), morph_times.end(), 0xcc);
DXX_POISON_VAR(n_morphing_points, 0xcc);
DXX_POISON_VAR(submodel_startpoints, 0xcc);
}
span<fix> morph_data::get_morph_times()
{
return {reinterpret_cast<fix *>(this + 1), MAX_VECS};
}
d_level_unique_morph_object_state::~d_level_unique_morph_object_state() = default;
//returns ptr to data for this object, or NULL if none
@ -214,11 +219,12 @@ static void init_points(const polymodel &pm, const vms_vector *const box_size, c
md->n_morphing_points[submodel_num] = 0;
md->submodel_startpoints[submodel_num] = startpoint;
const auto morph_times = md->get_morph_times();
auto &&zr = zip(
unchecked_partial_range(reinterpret_cast<const vms_vector *>(sd.body), sd.nverts),
partial_range(md->morph_vecs, startpoint, endpoint),
partial_range(md->morph_deltas, startpoint, endpoint),
partial_range(md->morph_times, startpoint, endpoint)
partial_range(morph_times, startpoint, endpoint)
);
range_for (auto &&z, zr)
{
@ -249,11 +255,12 @@ static void update_points(const polymodel &pm, const unsigned submodel_num, morp
const unsigned startpoint = sd.startpoint;
const unsigned endpoint = startpoint + sd.nverts;
const auto morph_times = md->get_morph_times();
auto &&zr = zip(
unchecked_partial_range(reinterpret_cast<const vms_vector *>(sd.body), sd.nverts),
partial_range(md->morph_vecs, startpoint, endpoint),
partial_range(md->morph_deltas, startpoint, endpoint),
partial_range(md->morph_times, startpoint, endpoint)
partial_range(morph_times, startpoint, endpoint)
);
range_for (auto &&z, zr)
{
@ -384,7 +391,8 @@ void morph_start(d_level_unique_morph_object_state &LevelUniqueMorphObjectState,
box_size.z = max(-pmmin.z,pmmax.z) / 2;
//clear all points
md->morph_times = {};
const auto morph_times = md->get_morph_times();
std::fill(morph_times.begin(), morph_times.end(), fix());
//clear all parts
md->submodel_active = {};