warzone2100/lib/framework/vector.h

224 lines
11 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/*
This file is part of Warzone 2100.
Copyright (C) 2007-2011 Warzone 2100 Project
Warzone 2100 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.
Warzone 2100 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 Warzone 2100; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef VECTOR_H
#define VECTOR_H
#include "wzglobal.h"
#include <assert.h>
#include "fixedpoint.h"
#include "frame.h"
#include "math_ext.h"
struct Rotation;
struct Vector3i;
struct Vector2i
{
Vector2i() {}
Vector2i(int x, int y) : x(x), y(y) {}
Vector2i(Vector3i const &r); // discards the z value
int x, y;
};
struct Vector2f
{
Vector2f() {}
Vector2f(float x, float y) : x(x), y(y) {}
Vector2f(Vector2i const &v) : x(v.x), y(v.y) {}
float x, y;
};
struct Vector3i
{
Vector3i() {}
Vector3i(int x, int y, int z) : x(x), y(y), z(z) {}
Vector3i(Vector2i const &xy, int z) : x(xy.x), y(xy.y), z(z) {}
Vector3i(Rotation const &r);
int x, y, z;
};
struct Vector3f
{
Vector3f() {}
Vector3f(float x, float y, float z) : x(x), y(y), z(z) {}
Vector3f(Vector3i const &v) : x(v.x), y(v.y), z(v.z) {}
Vector3f(Vector2f const &xy, float z) : x(xy.x), y(xy.y), z(z) {}
float x, y, z;
};
struct Rotation
{
Rotation() { direction = 0; pitch = 0; roll = 0; }
Rotation(int direction, int pitch, int roll) : direction(direction), pitch(pitch), roll(roll) {}
Rotation(Vector3i xyz) : direction(xyz.x), pitch(xyz.y), roll(xyz.z) {}
uint16_t direction, pitch, roll; ///< Object rotation in 0..64k range
};
typedef Vector3i Position; ///< Map position in world coordinates
inline Vector3i::Vector3i(Rotation const &r) : x(r.direction), y(r.pitch), z(r.roll) {}
inline Vector2i::Vector2i(Vector3i const &r) : x(r.x), y(r.y) {}
// removeZ(3d_vector) -> 2d_vector
static inline WZ_DECL_PURE Vector2i removeZ(Vector3i const &a) { return Vector2i(a.x, a.y); }
static inline WZ_DECL_PURE Vector2f removeZ(Vector3f const &a) { return Vector2f(a.x, a.y); }
// vector == vector -> bool
static inline WZ_DECL_PURE bool operator ==(Vector2i const &a, Vector2i const &b) { return a.x == b.x && a.y == b.y; }
static inline WZ_DECL_PURE bool operator ==(Vector2f const &a, Vector2f const &b) { return a.x == b.x && a.y == b.y; }
static inline WZ_DECL_PURE bool operator ==(Vector3i const &a, Vector3i const &b) { return a.x == b.x && a.y == b.y && a.z == b.z; }
static inline WZ_DECL_PURE bool operator ==(Vector3f const &a, Vector3f const &b) { return a.x == b.x && a.y == b.y && a.z == b.z; }
static inline WZ_DECL_PURE bool operator ==(Rotation const &a, Rotation const &b) { return a.direction == b.direction && a.pitch == b.pitch && a.roll == b.roll; }
// vector != vector -> bool
static inline WZ_DECL_PURE bool operator !=(Vector2i const &a, Vector2i const &b) { return a.x != b.x || a.y != b.y; }
static inline WZ_DECL_PURE bool operator !=(Vector2f const &a, Vector2f const &b) { return a.x != b.x || a.y != b.y; }
static inline WZ_DECL_PURE bool operator !=(Vector3i const &a, Vector3i const &b) { return a.x != b.x || a.y != b.y || a.z != b.z; }
static inline WZ_DECL_PURE bool operator !=(Vector3f const &a, Vector3f const &b) { return a.x != b.x || a.y != b.y || a.z != b.z; }
static inline WZ_DECL_PURE bool operator !=(Rotation const &a, Rotation const &b) { return a.direction != b.direction || a.pitch != b.pitch || a.roll != b.roll; }
// vector + vector -> vector
static inline WZ_DECL_PURE Vector2i operator +(Vector2i const &a, Vector2i const &b) { return Vector2i(a.x + b.x, a.y + b.y); }
static inline WZ_DECL_PURE Vector2f operator +(Vector2f const &a, Vector2f const &b) { return Vector2f(a.x + b.x, a.y + b.y); }
static inline WZ_DECL_PURE Vector3i operator +(Vector3i const &a, Vector3i const &b) { return Vector3i(a.x + b.x, a.y + b.y, a.z + b.z); }
static inline WZ_DECL_PURE Vector3f operator +(Vector3f const &a, Vector3f const &b) { return Vector3f(a.x + b.x, a.y + b.y, a.z + b.z); }
//static inline WZ_DECL_PURE Rotation operator +(Rotation const &a, Rotation const &b) { return Rotation((int16_t)a.direction + (int16_t)b.direction, (int16_t)a.pitch + (int16_t)b.pitch, (int16_t)a.roll + (int16_t)b.roll); }
// vector - vector -> vector
static inline WZ_DECL_PURE Vector2i operator -(Vector2i const &a, Vector2i const &b) { return Vector2i(a.x - b.x, a.y - b.y); }
static inline WZ_DECL_PURE Vector2f operator -(Vector2f const &a, Vector2f const &b) { return Vector2f(a.x - b.x, a.y - b.y); }
static inline WZ_DECL_PURE Vector3i operator -(Vector3i const &a, Vector3i const &b) { return Vector3i(a.x - b.x, a.y - b.y, a.z - b.z); }
static inline WZ_DECL_PURE Vector3f operator -(Vector3f const &a, Vector3f const &b) { return Vector3f(a.x - b.x, a.y - b.y, a.z - b.z); }
//static inline WZ_DECL_PURE Rotation operator -(Rotation const &a, Rotation const &b) { return Rotation((int16_t)a.direction - (int16_t)b.direction, (int16_t)a.pitch - (int16_t)b.pitch, (int16_t)a.roll - (int16_t)b.roll); }
// -vector -> vector
static inline WZ_DECL_PURE Vector2i operator -(Vector2i const &a) { return Vector2i(-a.x, -a.y); }
static inline WZ_DECL_PURE Vector2f operator -(Vector2f const &a) { return Vector2f(-a.x, -a.y); }
static inline WZ_DECL_PURE Vector3i operator -(Vector3i const &a) { return Vector3i(-a.x, -a.y, -a.z); }
static inline WZ_DECL_PURE Vector3f operator -(Vector3f const &a) { return Vector3f(-a.x, -a.y, -a.z); }
// vector * scalar -> vector
static inline WZ_DECL_PURE Vector2i operator *(Vector2i const &a, int s) { return Vector2i(a.x*s, a.y*s); }
static inline WZ_DECL_PURE Vector2f operator *(Vector2f const &a, float s) { return Vector2f(a.x*s, a.y*s); }
static inline WZ_DECL_PURE Vector3i operator *(Vector3i const &a, int s) { return Vector3i(a.x*s, a.y*s, a.z*s); }
static inline WZ_DECL_PURE Vector3f operator *(Vector3f const &a, float s) { return Vector3f(a.x*s, a.y*s, a.z*s); }
//static inline WZ_DECL_PURE Rotation operator *(Rotation const &a, int s) { return Rotation((int16_t)a.direction*s, (int16_t)a.pitch*s, (int16_t)a.roll*s); }
// vector / scalar -> vector
static inline WZ_DECL_PURE Vector2i operator /(Vector2i const &a, int s) { return Vector2i(a.x/s, a.y/s); }
static inline WZ_DECL_PURE Vector2f operator /(Vector2f const &a, float s) { return Vector2f(a.x/s, a.y/s); }
static inline WZ_DECL_PURE Vector3i operator /(Vector3i const &a, int s) { return Vector3i(a.x/s, a.y/s, a.z/s); }
static inline WZ_DECL_PURE Vector3f operator /(Vector3f const &a, float s) { return Vector3f(a.x/s, a.y/s, a.z/s); }
//static inline WZ_DECL_PURE Rotation operator /(Rotation const &a, int s) { return Rotation((int16_t)a.direction/s, (int16_t)a.pitch/s, (int16_t)a.roll/s); }
// vector * vector -> scalar
static inline WZ_DECL_PURE int operator *(Vector2i const &a, Vector2i const &b) { return a.x*b.x + a.y*b.y; }
static inline WZ_DECL_PURE float operator *(Vector2f const &a, Vector2f const &b) { return a.x*b.x + a.y*b.y; }
static inline WZ_DECL_PURE int operator *(Vector3i const &a, Vector3i const &b) { return a.x*b.x + a.y*b.y + a.z*b.z; }
static inline WZ_DECL_PURE float operator *(Vector3f const &a, Vector3f const &b) { return a.x*b.x + a.y*b.y + a.z*b.z; }
// normalise(vector) -> scalar
static inline WZ_DECL_PURE Vector2f normalise(Vector2f const &a) { float sq = a*a; if (sq == 0.0f) return Vector2f(0.0f, 0.0f); return a / sqrtf(sq); }
static inline WZ_DECL_PURE Vector3f normalise(Vector3f const &a) { float sq = a*a; if (sq == 0.0f) return Vector3f(0.0f, 0.0f, 0.0f); return a / sqrtf(sq); }
// iSinCosR(angle, scalar) -> 2d_vector
static inline WZ_DECL_PURE Vector2i iSinCosR(uint16_t a, int32_t r) { return Vector2i(iSinR(a, r), iCosR(a, r)); }
// iAtan2(2d_vector) -> angle
static inline WZ_DECL_PURE int iAtan2(Vector2i const &a) { return iAtan2(a.x, a.y); }
// iHypot(vector) -> scalar
static inline WZ_DECL_PURE int iHypot(Vector2i const &a) { return iHypot(a.x, a.y); }
static inline WZ_DECL_PURE int iHypot(Vector3i const &a) { return iHypot3(a.x, a.y, a.z); }
// swapYZ(3d_vector) -> 3d_vector
static inline WZ_DECL_PURE Vector3i swapYZ(Vector3i a) { return Vector3i(a.x, a.z, a.y); }
static inline WZ_DECL_PURE Vector3f swapYZ(Vector3f a) { return Vector3f(a.x, a.z, a.y); }
// vector × vector -> scalar
static inline WZ_DECL_PURE Vector3i crossProduct(Vector3i const &a, Vector3i const &b) { return Vector3i(a.y*b.z - a.z*b.y, a.z*b.x - a.x*b.z, a.x*b.y - a.y*b.x); }
static inline WZ_DECL_PURE Vector3f crossProduct(Vector3f const &a, Vector3f const &b) { return Vector3f(a.y*b.z - a.z*b.y, a.z*b.x - a.x*b.z, a.x*b.y - a.y*b.x); }
// vector += vector
static inline Vector2i const &operator +=(Vector2i &a, Vector2i const &b) { return a = a + b; }
static inline Vector2f const &operator +=(Vector2f &a, Vector2f const &b) { return a = a + b; }
static inline Vector3i const &operator +=(Vector3i &a, Vector3i const &b) { return a = a + b; }
static inline Vector3f const &operator +=(Vector3f &a, Vector3f const &b) { return a = a + b; }
/*!
* Rotate v
* \param v vector to rotate
* \param angle the amount * 32768/π to rotate in counterclockwise direction
* \return Result
*/
static inline WZ_DECL_PURE Vector2f Vector2f_Rotate2f(Vector2f v, int angle)
{
Vector2f result;
result.x = (v.x*iCos(angle) - v.y*iSin(angle)) / 65536;
result.y = (v.x*iSin(angle) + v.y*iCos(angle)) / 65536;
return result;
}
/*!
* Much the same as Vector2i_InCircle except that it works in 3-axis by discarding the z-component and with
* circles.
* \param v Vector to test
* \param c Vector containing the centre of the circle
* \param r The radius of the circle
* \return If v falls within the circle
*/
static inline WZ_DECL_CONST bool Vector3i_InCircle(const Vector3i v, const Vector3i c, const unsigned int r)
{
Vector2i delta = removeZ(v - c);
// Explictily cast to "unsigned int" because this number never can be
// negative, due to the fact that these numbers are squared. Still GCC
// warns about a comparison of a comparison between an unsigned and a
// signed integer.
return (unsigned int)(delta * delta) < r * r;
}
/*!
* Much the same as Vector2i_InCircle except that it works in 3-axis and with
* spheres.
* The equation used is also ever so slightly different:
* (x - a)^2 + (y - b)^2 + (z - c)^2 = r^2. Notice how it is still squared and
* _not_ cubed!
* \param v Vector to test
* \param c Vector containing the centre of the sphere
* \param r The radius of the sphere
* \return If v falls within the sphere
*/
static inline WZ_DECL_CONST bool Vector3i_InSphere (const Vector3i v, const Vector3i c, const unsigned int r)
{
Vector3i delta = v - c;
// Explictily cast to "unsigned int" because this number never can be
// negative, due to the fact that these numbers are squared. Still GCC
// warns about a comparison of a comparison between an unsigned and a
// signed integer.
return (unsigned int)(delta * delta) < r * r;
}
#endif // VECTOR_H