openmohaa/code/fgame/spline.h

281 lines
6.4 KiB
C
Raw Normal View History

2016-03-27 11:49:47 +02:00
/*
===========================================================================
Copyright (C) 2015 the OpenMoHAA team
This file is part of OpenMoHAA source code.
OpenMoHAA source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
OpenMoHAA source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenMoHAA source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
// spline.h: Spline paths.
//
2023-11-05 19:09:29 +01:00
#pragma once
2016-03-27 11:49:47 +02:00
#include "g_local.h"
#include <class.h>
2023-11-05 19:09:29 +01:00
template<unsigned int cGrids, unsigned int cPoints>
2016-03-27 11:49:47 +02:00
class cSpline : public Class
{
public:
2023-11-05 19:09:29 +01:00
int m_iPoints;
float m_vPoints[cPoints][cGrids];
int m_iPointFlags[cPoints];
cSpline();
2023-11-05 19:09:29 +01:00
void Reset(void);
int Add(float *fAdd, int flags);
void Modify(int, float *, int);
void UniformAdd(float *pos);
void Remove(class cSpline<cGrids, cPoints> *, int);
void RemoveRange(int, int);
int Right(float x);
float *Get(float x, int *flags);
float *GetByNode(float x, int *flags);
int Append(cSpline<cGrids, cPoints> *pNew);
void Archive(Archiver& arc);
2016-03-27 11:49:47 +02:00
};
template<unsigned int cGrids, unsigned int cPoints>
cSpline<cGrids, cPoints>::cSpline()
{
m_iPoints = 0;
}
2023-11-05 19:09:29 +01:00
template<unsigned int cGrids, unsigned int cPoints>
void cSpline<cGrids, cPoints>::Archive(Archiver& arc)
2016-03-27 11:49:47 +02:00
{
2023-11-05 19:09:29 +01:00
arc.ArchiveInteger(&m_iPoints);
2016-03-27 11:49:47 +02:00
2023-11-05 19:09:29 +01:00
for (int i = 0; i < cPoints; i++) {
2023-11-27 20:35:23 +01:00
for (int j = 0; j < cGrids; j++) {
2023-11-05 19:09:29 +01:00
arc.ArchiveFloat(&m_vPoints[i][j]);
}
2016-03-27 11:49:47 +02:00
2023-11-05 19:09:29 +01:00
arc.ArchiveInteger(&m_iPointFlags[i]);
}
2016-03-27 11:49:47 +02:00
}
2023-11-05 19:09:29 +01:00
template<unsigned int cGrids, unsigned int cPoints>
void cSpline<cGrids, cPoints>::Reset(void)
2016-03-27 11:49:47 +02:00
{
2023-11-05 19:09:29 +01:00
m_iPoints = 0;
2016-03-27 11:49:47 +02:00
}
2023-11-05 19:09:29 +01:00
template<unsigned int cGrids, unsigned int cPoints>
int cSpline<cGrids, cPoints>::Add(float *fAdd, int flags)
2016-03-27 11:49:47 +02:00
{
2023-11-05 19:09:29 +01:00
int i;
int ii;
int insertIndex;
2016-03-27 11:49:47 +02:00
2024-01-25 21:55:21 +01:00
if (m_iPoints + 1 > cPoints) {
2023-11-05 19:09:29 +01:00
return -1;
}
2016-03-27 11:49:47 +02:00
2023-11-05 19:09:29 +01:00
insertIndex = Right(*fAdd);
2016-03-27 11:49:47 +02:00
2023-11-05 19:09:29 +01:00
for (i = m_iPoints; i > insertIndex; i--) {
for (ii = 0; ii < cGrids; ii++) {
m_vPoints[i][ii] = m_vPoints[i - 1][ii];
}
2016-03-27 11:49:47 +02:00
2023-11-05 19:09:29 +01:00
m_iPointFlags[i] = m_iPointFlags[i - 1];
}
2016-03-27 11:49:47 +02:00
2023-11-05 19:09:29 +01:00
for (i = 0; i < cGrids; i++) {
m_vPoints[insertIndex][i] = fAdd[i];
}
2016-03-27 11:49:47 +02:00
2023-11-05 19:09:29 +01:00
m_iPointFlags[insertIndex] = flags;
m_iPoints++;
2016-03-27 11:49:47 +02:00
2023-11-05 19:09:29 +01:00
return insertIndex;
2016-03-27 11:49:47 +02:00
}
2023-11-05 19:09:29 +01:00
template<unsigned int cGrids, unsigned int cPoints>
void cSpline<cGrids, cPoints>::UniformAdd(float *pos)
2016-03-27 11:49:47 +02:00
{
2023-11-05 19:09:29 +01:00
int i;
int ii;
2024-01-25 21:55:21 +01:00
for (i = 0; i < m_iPoints; i++) {
for (ii = 0; ii < cGrids; ii++) {
2023-11-05 19:09:29 +01:00
m_vPoints[i][ii] += pos[ii];
}
}
2016-03-27 11:49:47 +02:00
}
2023-11-05 19:09:29 +01:00
template<unsigned int cGrids, unsigned int cPoints>
int cSpline<cGrids, cPoints>::Right(float x)
2016-03-27 11:49:47 +02:00
{
2023-11-05 19:09:29 +01:00
int i;
2016-03-27 11:49:47 +02:00
2023-11-05 19:09:29 +01:00
for (i = 0; i < m_iPoints; i++) {
if (m_vPoints[i][0] > x) {
break;
}
}
2016-03-27 11:49:47 +02:00
2023-11-05 19:09:29 +01:00
return i;
2016-03-27 11:49:47 +02:00
}
2023-11-05 19:09:29 +01:00
template<unsigned int cGrids, unsigned int cPoints>
float *cSpline<cGrids, cPoints>::Get(float x, int *flags)
2016-03-27 11:49:47 +02:00
{
2023-11-05 19:09:29 +01:00
if (!m_iPoints) {
return NULL;
}
int rp;
int i;
static float r[cGrids];
double delta[cGrids];
rp = Right(x);
if (rp) {
if (rp == m_iPoints) {
if (flags) {
*flags = m_iPointFlags[rp - 1];
}
for (i = 0; i < cGrids; i++) {
r[i] = m_vPoints[rp - 1][i];
}
} else {
if (flags) {
*flags = m_iPointFlags[rp - 1];
}
for (i = 0; i < cGrids; i++) {
delta[i] = m_vPoints[rp][i] - m_vPoints[rp - 1][i];
}
for (i = 0; i < cGrids; i++) {
r[i] = (x - m_vPoints[rp - 1][0]) / delta[0] * delta[i] + m_vPoints[rp - 1][i];
}
}
} else {
if (flags) {
*flags = m_iPointFlags[0];
}
for (i = 0; i < cGrids; i++) {
2023-11-05 19:09:29 +01:00
r[i] = m_vPoints[0][i];
}
}
return r;
2016-03-27 11:49:47 +02:00
}
2023-11-05 19:09:29 +01:00
template<unsigned int cGrids, unsigned int cPoints>
float *cSpline<cGrids, cPoints>::GetByNode(float x, int *flags)
2016-03-27 11:49:47 +02:00
{
2023-11-05 19:09:29 +01:00
if (!m_iPoints) {
return NULL;
}
int rp;
int i;
static float r[cGrids];
double delta[cGrids];
2024-03-04 22:25:31 +01:00
rp = (int)(floor(x) + 1.0);
2023-11-05 19:09:29 +01:00
if (rp <= 0) {
if (flags) {
*flags = m_iPointFlags[0];
}
for (i = 0; i < cGrids; i++) {
r[i] = m_vPoints[0][i];
}
} else if (rp < m_iPoints) {
if (flags) {
*flags = m_iPointFlags[rp - 1];
}
for (i = 0; i < cGrids; i++) {
delta[i] = m_vPoints[rp][i] - m_vPoints[rp - 1][i];
}
for (i = 0; i < cGrids; i++) {
r[i] = (x - (rp - 1)) * delta[i] + m_vPoints[rp - 1][i];
}
} else {
if (flags) {
2024-01-25 21:55:21 +01:00
*flags = m_iPointFlags[m_iPoints - 1];
2023-11-05 19:09:29 +01:00
}
for (i = 0; i < cGrids; i++) {
2024-01-25 21:55:21 +01:00
r[i] = m_vPoints[m_iPoints - 1][i];
2023-11-05 19:09:29 +01:00
}
}
return r;
2016-03-27 11:49:47 +02:00
}
2023-11-05 19:09:29 +01:00
template<unsigned int cGrids, unsigned int cPoints>
int cSpline<cGrids, cPoints>::Append(cSpline<cGrids, cPoints> *pNew)
2016-03-27 11:49:47 +02:00
{
2023-11-05 19:09:29 +01:00
float *i_fTmp;
float o_fTmp[4];
float fIndexAdd;
int i;
int ii;
2024-01-25 21:55:21 +01:00
int iFlags = 0;
2023-11-05 19:09:29 +01:00
if (!pNew || pNew->m_iPoints == 0) {
return -1;
}
if (m_iPoints) {
int points;
points = m_iPoints;
2023-11-05 19:09:29 +01:00
fIndexAdd = *GetByNode(m_iPoints, NULL);
for (i = 0; i < pNew->m_iPoints; i++) {
i_fTmp = pNew->GetByNode(i, &iFlags);
for (ii = 0; ii < cGrids; ii++) {
o_fTmp[ii] = i_fTmp[ii];
}
2016-03-27 11:49:47 +02:00
2023-11-05 19:09:29 +01:00
o_fTmp[0] += fIndexAdd;
Add(o_fTmp, iFlags);
}
return points;
2023-11-05 19:09:29 +01:00
} else {
for (i = 0; i < pNew->m_iPoints; i++) {
i_fTmp = pNew->GetByNode(i, &iFlags);
for (ii = 0; ii < cGrids; ii++) {
o_fTmp[ii] = i_fTmp[ii];
}
Add(o_fTmp, iFlags);
}
return 0;
}
}