1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
|
/*
This file is part of Warzone 2100.
Copyright (C) 2007-2020 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
#if defined(WZ_CC_MSVC)
#pragma warning( disable : 4201)
#endif
#define GLM_FORCE_SWIZZLE
#define GLM_FORCE_SILENT_WARNINGS
#include <stdint.h>
#include "wzglobal.h"
#include "frame.h"
#include "lib/framework/types.h"
#include <glm/vec2.hpp>
#include <glm/vec3.hpp>
using Vector3i = glm::ivec3;
using Vector2i = glm::ivec2;
using Vector2f = glm::vec2;
using Vector3f = glm::vec3;
struct Rotation
{
Rotation()
{
direction = 0;
pitch = 0;
roll = 0;
}
Rotation(int direction, int pitch, int roll) : direction((uint16_t)direction), pitch((uint16_t)pitch), roll((uint16_t)roll) {}
Rotation(Vector3i xyz) : direction((uint16_t)xyz.x), pitch((uint16_t)xyz.y), roll((uint16_t)xyz.z) {}
uint16_t direction, pitch, roll; ///< Object rotation in 0..64k range
};
typedef Vector3i Position; ///< Map position in world coordinates
static inline Vector3i toVector(Rotation const &r)
{
return Vector3i(r.direction, r.pitch, r.roll);
}
// vector * vector -> scalar
// Note: glm doesn't provide dot operator for integral vector.
static inline WZ_DECL_PURE int dot(Vector2i const &a, Vector2i const &b)
{
return a.x * b.x + a.y * b.y;
}
static inline WZ_DECL_PURE int dot(Vector3i const &a, Vector3i const &b)
{
return a.x * b.x + a.y * b.y + a.z * b.z;
}
// 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);
}
/*!
* 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((uint16_t)angle) - v.y * iSin((uint16_t)angle)) / 65536;
result.y = (v.x * iSin((uint16_t)angle) + v.y * iCos((uint16_t)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 bool WZ_DECL_PURE Vector3i_InCircle(Vector3i v, Vector3i c, unsigned r)
{
Vector2i delta = Vector3i(v - c).xy();
// 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)dot(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 bool WZ_DECL_PURE Vector3i_InSphere(Vector3i v, Vector3i c, unsigned 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)dot(delta, delta) < r * r;
}
// Round direction to nearest axis-aligned direction.
static inline uint16_t snapDirection(uint16_t direction)
{
return (direction + 0x2000) & 0xC000;
}
#endif // VECTOR_H
|