From e9751a0e0b2031f5eedb37b7e5e6052e3566104f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Lemaire?= Date: Sat, 9 Nov 2013 18:46:34 +0100 Subject: [PATCH] WIP on fluid medium traversal --- src/basics/SpaceCoordinates.cpp | 1 + src/basics/SpaceCoordinates.h | 25 +++ src/basics/Vector3.cpp | 156 ++++++++++++++++++ src/basics/Vector3.h | 78 +++++++++ src/basics/basics.pro | 8 +- src/basics/basics_global.h | 2 +- src/paysages.pro | 1 + src/render/software/SoftwareRenderer.cpp | 14 ++ src/render/software/SoftwareRenderer.h | 35 ++++ .../software/global/FluidMediumTraversal.cpp | 6 + .../software/global/FluidMediumTraversal.h | 42 +++++ src/render/software/software.pro | 52 ++++++ src/render/software/software_global.h | 22 +++ src/rendering/tools/euclid.cpp | 121 -------------- src/rendering/tools/euclid.h | 71 +------- 15 files changed, 442 insertions(+), 192 deletions(-) create mode 100644 src/basics/SpaceCoordinates.cpp create mode 100644 src/basics/SpaceCoordinates.h create mode 100644 src/basics/Vector3.cpp create mode 100644 src/basics/Vector3.h create mode 100644 src/render/software/SoftwareRenderer.cpp create mode 100644 src/render/software/SoftwareRenderer.h create mode 100644 src/render/software/global/FluidMediumTraversal.cpp create mode 100644 src/render/software/global/FluidMediumTraversal.h create mode 100644 src/render/software/software.pro create mode 100644 src/render/software/software_global.h diff --git a/src/basics/SpaceCoordinates.cpp b/src/basics/SpaceCoordinates.cpp new file mode 100644 index 0000000..49820f2 --- /dev/null +++ b/src/basics/SpaceCoordinates.cpp @@ -0,0 +1 @@ +#include "SpaceCoordinates.h" diff --git a/src/basics/SpaceCoordinates.h b/src/basics/SpaceCoordinates.h new file mode 100644 index 0000000..2b6dc44 --- /dev/null +++ b/src/basics/SpaceCoordinates.h @@ -0,0 +1,25 @@ +#ifndef SPACECOORDINATES_H +#define SPACECOORDINATES_H + +#include "basics_global.h" + +#include "Vector3.h" + +namespace paysages { +namespace basics { + +/*! + * \brief Space 3D coordinates. + * + * These coordinates allow to work on very large scenes, regardless of the 'double' type precision. + */ +class SpaceCoordinates:public Vector3 +{ +/*public: + SpaceCoordinates();*/ +}; + +} +} + +#endif // SPACECOORDINATES_H diff --git a/src/basics/Vector3.cpp b/src/basics/Vector3.cpp new file mode 100644 index 0000000..19d626b --- /dev/null +++ b/src/basics/Vector3.cpp @@ -0,0 +1,156 @@ +#include "Vector3.h" + +#include +#include "PackStream.h" + +Vector3 VECTOR_ZERO = {0.0, 0.0, 0.0}; +Vector3 VECTOR_DOWN = {0.0, -1.0, 0.0}; +Vector3 VECTOR_UP = {0.0, 1.0, 0.0}; +Vector3 VECTOR_NORTH = {0.0, 0.0, -1.0}; +Vector3 VECTOR_SOUTH = {0.0, 0.0, 1.0}; +Vector3 VECTOR_WEST = {-1.0, 0.0, 0.0}; +Vector3 VECTOR_EAST = {1.0, 0.0, 0.0}; + +static inline double _euclidGet2DAngle(double x, double y) +{ + // TEMP Copy of old euclid.c + double nx, ny, d, ret; + + if (x == 0.0) + { + if (y == 0.0) + { + return 0.0; + } + else if (y < 0.0) + { + return 3.0 * M_PI_2; + } + else + { + return M_PI_2; + } + } + + d = sqrt(x * x + y * y); + nx = x / d; + ny = y / d; + + ret = asin(ny); + if (nx < 0.0) + { + ret = M_PI - ret; + } + return ret < 0.0 ? ret + 2.0 * M_PI : ret; +} +void v3Save(PackStream* stream, Vector3* v) +{ + stream->write(&v->x); + stream->write(&v->y); + stream->write(&v->z); +} + +void v3Load(PackStream* stream, Vector3* v) +{ + stream->read(&v->x); + stream->read(&v->y); + stream->read(&v->z); +} + +Vector3 v3Translate(Vector3 v1, double x, double y, double z) +{ + Vector3 result; + result.x = v1.x + x; + result.y = v1.y + y; + result.z = v1.z + z; + return result; +} + +Vector3 v3Add(Vector3 v1, Vector3 v2) +{ + Vector3 result; + result.x = v1.x + v2.x; + result.y = v1.y + v2.y; + result.z = v1.z + v2.z; + return result; +} + +Vector3 v3Sub(Vector3 v1, Vector3 v2) +{ + Vector3 result; + result.x = v1.x - v2.x; + result.y = v1.y - v2.y; + result.z = v1.z - v2.z; + return result; +} + +Vector3 v3Neg(Vector3 v) +{ + Vector3 result; + result.x = -v.x; + result.y = -v.y; + result.z = -v.z; + return result; +} + +Vector3 v3Scale(Vector3 v, double scale) +{ + Vector3 result; + result.x = v.x * scale; + result.y = v.y * scale; + result.z = v.z * scale; + return result; +} + +double v3Norm(Vector3 v) +{ + return sqrt(v.x * v.x + v.y * v.y + v.z * v.z); +} + +Vector3 v3Normalize(Vector3 v) +{ + double norm = v3Norm(v); + if (norm == 0.0) + { + return VECTOR_ZERO; + } + else + { + return v3Scale(v, 1.0 / norm); + } +} + +double v3Dot(Vector3 v1, Vector3 v2) +{ + return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z; +} + +Vector3 v3Cross(Vector3 v1, Vector3 v2) +{ + Vector3 result; + result.x = v1.y * v2.z - v1.z * v2.y; + result.y = v1.z * v2.x - v1.x * v2.z; + result.z = v1.x * v2.y - v1.y * v2.x; + return result; +} + +VectorSpherical v3ToSpherical(Vector3 v) +{ + VectorSpherical result; + + result.phi = _euclidGet2DAngle(v.x, -v.z); + result.theta = _euclidGet2DAngle(sqrt(v.x * v.x + v.z * v.z), v.y); + if (v.y < 0.0) + { + result.theta -= 2.0 * M_PI; + } + result.r = v3Norm(v); + + return result; +} + +Vector3 v3FromSpherical(VectorSpherical v) +{ + Vector3 result = {v.r * cos(v.phi) * cos(v.theta), v.r * sin(v.theta), -v.r * sin(v.phi) * cos(v.theta)}; + return result; +} diff --git a/src/basics/Vector3.h b/src/basics/Vector3.h new file mode 100644 index 0000000..c7bac1b --- /dev/null +++ b/src/basics/Vector3.h @@ -0,0 +1,78 @@ +#ifndef VECTOR3_H +#define VECTOR3_H + +#include "basics_global.h" + +/* + * Cartesian coordinates (X, Y, Z) - right handed : + * + * Y (up) + * | + * | + * +----X + * / + * / + * Z + * + * Spherical coordinates (R, PHI, THETA) : + * + * R is the distance to origin + * PHI is typical azimuth + * THETA is elevation angle (not polar angle!) + * + * X=1 Y=0 Z=0 => PHI=0 + * X=0 Y=0 Z=-1 => PHI=PI/2 + * X=-1 Y=0 Z=0 => PHI=PI + * X=0 Y=0 Z=1 => PHI=3*PI/2 + * + * X=1 Y=0 Z=0 => THETA=0 + * X=0 Y=1 Z=0 => THETA=PI/2 + * X=0 Y=-1 Z=0 => THETA=-PI/2 + */ + +namespace paysages { +namespace system {class PackStream;} +} + +typedef struct +{ + double x; + double y; + double z; +} Vector3; + +typedef struct +{ + double r; + double theta; + double phi; +} VectorSpherical; + +BASICSSHARED_EXPORT extern Vector3 VECTOR_ZERO; +BASICSSHARED_EXPORT extern Vector3 VECTOR_DOWN; +BASICSSHARED_EXPORT extern Vector3 VECTOR_UP; +BASICSSHARED_EXPORT extern Vector3 VECTOR_NORTH; +BASICSSHARED_EXPORT extern Vector3 VECTOR_SOUTH; +BASICSSHARED_EXPORT extern Vector3 VECTOR_EAST; +BASICSSHARED_EXPORT extern Vector3 VECTOR_WEST; + +static inline Vector3 v3(double x, double y, double z) +{ + Vector3 result = {x, y, z}; + return result; +} +BASICSSHARED_EXPORT void v3Save(PackStream* stream, Vector3* v); +BASICSSHARED_EXPORT void v3Load(PackStream* stream, Vector3* v); +BASICSSHARED_EXPORT Vector3 v3Translate(Vector3 v1, double x, double y, double z); +BASICSSHARED_EXPORT Vector3 v3Add(Vector3 v1, Vector3 v2); +BASICSSHARED_EXPORT Vector3 v3Sub(Vector3 v1, Vector3 v2); +BASICSSHARED_EXPORT Vector3 v3Neg(Vector3 v); +BASICSSHARED_EXPORT Vector3 v3Scale(Vector3 v, double scale); +BASICSSHARED_EXPORT double v3Norm(Vector3 v); +BASICSSHARED_EXPORT Vector3 v3Normalize(Vector3 v); +BASICSSHARED_EXPORT double v3Dot(Vector3 v1, Vector3 v2); +BASICSSHARED_EXPORT Vector3 v3Cross(Vector3 v1, Vector3 v2); +BASICSSHARED_EXPORT VectorSpherical v3ToSpherical(Vector3 v); +BASICSSHARED_EXPORT Vector3 v3FromSpherical(VectorSpherical v); + +#endif // VECTOR3_H diff --git a/src/basics/basics.pro b/src/basics/basics.pro index 6cc300a..3870692 100644 --- a/src/basics/basics.pro +++ b/src/basics/basics.pro @@ -16,7 +16,9 @@ SOURCES += \ NoiseFunctionNaive.cpp \ NoiseFunctionPerlin.cpp \ NoiseFunctionSimplex.cpp \ - Interpolation.cpp + Interpolation.cpp \ + SpaceCoordinates.cpp \ + Vector3.cpp HEADERS +=\ basics_global.h \ @@ -24,7 +26,9 @@ HEADERS +=\ NoiseFunctionNaive.h \ NoiseFunctionPerlin.h \ NoiseFunctionSimplex.h \ - Interpolation.h + Interpolation.h \ + SpaceCoordinates.h \ + Vector3.h unix:!symbian { maemo5 { diff --git a/src/basics/basics_global.h b/src/basics/basics_global.h index 9c05c66..adf85df 100644 --- a/src/basics/basics_global.h +++ b/src/basics/basics_global.h @@ -3,7 +3,7 @@ /* Shared object helpers */ #include -#if defined(DEFINITION_LIBRARY) +#if defined(BASICS_LIBRARY) # define BASICSSHARED_EXPORT Q_DECL_EXPORT #else # define BASICSSHARED_EXPORT Q_DECL_IMPORT diff --git a/src/paysages.pro b/src/paysages.pro index 706ec48..e02f0b5 100644 --- a/src/paysages.pro +++ b/src/paysages.pro @@ -6,6 +6,7 @@ SUBDIRS = \ basics \ definition \ rendering \ + render/software \ render/opengl \ editing \ controlling diff --git a/src/render/software/SoftwareRenderer.cpp b/src/render/software/SoftwareRenderer.cpp new file mode 100644 index 0000000..b246a4c --- /dev/null +++ b/src/render/software/SoftwareRenderer.cpp @@ -0,0 +1,14 @@ +#include "SoftwareRenderer.h" + +#include "global/FluidMediumTraversal.h" + +SoftwareRenderer::SoftwareRenderer(Scenery* scenery): + scenery(scenery) +{ + fluid_medium = new FluidMediumTraversal(this); +} + +SoftwareRenderer::~SoftwareRenderer() +{ + delete fluid_medium; +} diff --git a/src/render/software/SoftwareRenderer.h b/src/render/software/SoftwareRenderer.h new file mode 100644 index 0000000..fa204ec --- /dev/null +++ b/src/render/software/SoftwareRenderer.h @@ -0,0 +1,35 @@ +#ifndef SOFTWARERENDERER_H +#define SOFTWARERENDERER_H + +#include "software_global.h" + +#include "renderer.h" + +class Scenery; + +namespace paysages { +namespace software { + +class FluidMediumTraversal; + +/*! + * \brief This class renders a defined scenery in sotware mode (using only standard CPU computations). + */ +class SOFTWARESHARED_EXPORT SoftwareRenderer: public Renderer +{ + +public: + SoftwareRenderer(Scenery* scenery); + virtual ~SoftwareRenderer(); + + inline Scenery* getScenery() const {return scenery;} + +private: + Scenery* scenery; + FluidMediumTraversal* fluid_medium; +}; + +} +} + +#endif // SOFTWARERENDERER_H diff --git a/src/render/software/global/FluidMediumTraversal.cpp b/src/render/software/global/FluidMediumTraversal.cpp new file mode 100644 index 0000000..7c8bb30 --- /dev/null +++ b/src/render/software/global/FluidMediumTraversal.cpp @@ -0,0 +1,6 @@ +#include "FluidMediumTraversal.h" + +FluidMediumTraversal::FluidMediumTraversal(SoftwareRenderer* renderer): + renderer(renderer) +{ +} diff --git a/src/render/software/global/FluidMediumTraversal.h b/src/render/software/global/FluidMediumTraversal.h new file mode 100644 index 0000000..6ef2ca9 --- /dev/null +++ b/src/render/software/global/FluidMediumTraversal.h @@ -0,0 +1,42 @@ +#ifndef FLUIDMEDIUMTRAVERSAL_H +#define FLUIDMEDIUMTRAVERSAL_H + +#include "software_global.h" + +#include +#include "SpaceCoordinates.h" + +namespace paysages { +namespace software { + +class SoftwareRenderer; +class FluidMediumCollector; +class FluidMediumInterface; + +/*! + * \brief Global object to interact with fluid medium (air, water, clouds...) + * + * This object handles the traversal of fluid medium and the collecting of + * medium density and properties. + * It is mainly used to compute the alteration made by such media on light. + */ +class SOFTWARESHARED_EXPORT FluidMediumTraversal +{ +public: + FluidMediumTraversal(SoftwareRenderer *renderer); + + void setCollector(FluidMediumCollector *collector); + + virtual void getTraversedMedia(std::vector &media); + + void collectHalfLine(const SpaceCoordinates &start, const Vector3 &direction); + void collectSegment(const SpaceCoordinates &start, const SpaceCoordinates &end); + +private: + SoftwareRenderer* renderer; +}; + +} +} + +#endif // FLUIDMEDIUMTRAVERSAL_H diff --git a/src/render/software/software.pro b/src/render/software/software.pro new file mode 100644 index 0000000..67c3c01 --- /dev/null +++ b/src/render/software/software.pro @@ -0,0 +1,52 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2013-11-09T15:13:23 +# +#------------------------------------------------- + +QT -= gui + +TARGET = software +TEMPLATE = lib + +DEFINES += SOFTWARE_LIBRARY + +SOURCES += SoftwareRenderer.cpp \ + global/FluidMediumTraversal.cpp + +HEADERS += SoftwareRenderer.h\ + software_global.h \ + global/FluidMediumTraversal.h + +unix:!symbian { + maemo5 { + target.path = /opt/usr/lib + } else { + target.path = /usr/lib + } + INSTALLS += target +} + +win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../../system/release/ -lpaysages_system +else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../../system/debug/ -lpaysages_system +else:unix: LIBS += -L$$OUT_PWD/../../system/ -lpaysages_system +INCLUDEPATH += $$PWD/../../system +DEPENDPATH += $$PWD/../../system + +win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../../basics/release/ -lpaysages_basics +else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../../basics/debug/ -lpaysages_basics +else:unix: LIBS += -L$$OUT_PWD/../../basics/ -lpaysages_basics +INCLUDEPATH += $$PWD/../../basics +DEPENDPATH += $$PWD/../../basics + +win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../../definition/release/ -lpaysages_definition +else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../../definition/debug/ -lpaysages_definition +else:unix: LIBS += -L$$OUT_PWD/../../definition/ -lpaysages_definition +INCLUDEPATH += $$PWD/../../definition +DEPENDPATH += $$PWD/../../definition + +win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../../rendering/release/ -lpaysages_rendering +else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../../rendering/debug/ -lpaysages_rendering +else:unix: LIBS += -L$$OUT_PWD/../../rendering/ -lpaysages_rendering +INCLUDEPATH += $$PWD/../../rendering +DEPENDPATH += $$PWD/../../rendering diff --git a/src/render/software/software_global.h b/src/render/software/software_global.h new file mode 100644 index 0000000..44b36a6 --- /dev/null +++ b/src/render/software/software_global.h @@ -0,0 +1,22 @@ +#ifndef SOFTWARE_GLOBAL_H +#define SOFTWARE_GLOBAL_H + +#include + +#if defined(SOFTWARE_LIBRARY) +# define SOFTWARESHARED_EXPORT Q_DECL_EXPORT +#else +# define SOFTWARESHARED_EXPORT Q_DECL_IMPORT +#endif + +namespace paysages { +namespace basics {} +namespace definition {} +namespace software {} +} + +using namespace paysages::basics; +using namespace paysages::definition; +using namespace paysages::software; + +#endif // SOFTWARE_GLOBAL_H diff --git a/src/rendering/tools/euclid.cpp b/src/rendering/tools/euclid.cpp index 5ed1b08..0bb1a8b 100644 --- a/src/rendering/tools/euclid.cpp +++ b/src/rendering/tools/euclid.cpp @@ -1,129 +1,8 @@ #include "euclid.h" #include -#include "../tools.h" #include "PackStream.h" -Vector3 VECTOR_ZERO = {0.0, 0.0, 0.0}; -Vector3 VECTOR_DOWN = {0.0, -1.0, 0.0}; -Vector3 VECTOR_UP = {0.0, 1.0, 0.0}; -Vector3 VECTOR_NORTH = {0.0, 0.0, -1.0}; -Vector3 VECTOR_SOUTH = {0.0, 0.0, 1.0}; -Vector3 VECTOR_WEST = {-1.0, 0.0, 0.0}; -Vector3 VECTOR_EAST = {1.0, 0.0, 0.0}; - -void v3Save(PackStream* stream, Vector3* v) -{ - stream->write(&v->x); - stream->write(&v->y); - stream->write(&v->z); -} - -void v3Load(PackStream* stream, Vector3* v) -{ - stream->read(&v->x); - stream->read(&v->y); - stream->read(&v->z); -} - -Vector3 v3Translate(Vector3 v1, double x, double y, double z) -{ - Vector3 result; - result.x = v1.x + x; - result.y = v1.y + y; - result.z = v1.z + z; - return result; -} - -Vector3 v3Add(Vector3 v1, Vector3 v2) -{ - Vector3 result; - result.x = v1.x + v2.x; - result.y = v1.y + v2.y; - result.z = v1.z + v2.z; - return result; -} - -Vector3 v3Sub(Vector3 v1, Vector3 v2) -{ - Vector3 result; - result.x = v1.x - v2.x; - result.y = v1.y - v2.y; - result.z = v1.z - v2.z; - return result; -} - -Vector3 v3Neg(Vector3 v) -{ - Vector3 result; - result.x = -v.x; - result.y = -v.y; - result.z = -v.z; - return result; -} - -Vector3 v3Scale(Vector3 v, double scale) -{ - Vector3 result; - result.x = v.x * scale; - result.y = v.y * scale; - result.z = v.z * scale; - return result; -} - -double v3Norm(Vector3 v) -{ - return sqrt(v.x * v.x + v.y * v.y + v.z * v.z); -} - -Vector3 v3Normalize(Vector3 v) -{ - double norm = v3Norm(v); - if (norm == 0.0) - { - return VECTOR_ZERO; - } - else - { - return v3Scale(v, 1.0 / norm); - } -} - -double v3Dot(Vector3 v1, Vector3 v2) -{ - return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z; -} - -Vector3 v3Cross(Vector3 v1, Vector3 v2) -{ - Vector3 result; - result.x = v1.y * v2.z - v1.z * v2.y; - result.y = v1.z * v2.x - v1.x * v2.z; - result.z = v1.x * v2.y - v1.y * v2.x; - return result; -} - -VectorSpherical v3ToSpherical(Vector3 v) -{ - VectorSpherical result; - - result.phi = euclidGet2DAngle(v.x, -v.z); - result.theta = euclidGet2DAngle(sqrt(v.x * v.x + v.z * v.z), v.y); - if (v.y < 0.0) - { - result.theta -= 2.0 * M_PI; - } - result.r = v3Norm(v); - - return result; -} - -Vector3 v3FromSpherical(VectorSpherical v) -{ - Vector3 result = {v.r * cos(v.phi) * cos(v.theta), v.r * sin(v.theta), -v.r * sin(v.phi) * cos(v.theta)}; - return result; -} - void m4Save(PackStream* stream, Matrix4* m) { stream->write(&m->a); diff --git a/src/rendering/tools/euclid.h b/src/rendering/tools/euclid.h index febdcb7..d9cae41 100644 --- a/src/rendering/tools/euclid.h +++ b/src/rendering/tools/euclid.h @@ -3,51 +3,13 @@ #include "../rendering_global.h" +// TEMP +#include "Vector3.h" + namespace paysages { namespace system {class PackStream;} } -/* - * Cartesian coordinates (X, Y, Z) - right handed : - * - * Y (up) - * | - * | - * +----X - * / - * / - * Z - * - * Spherical coordinates (R, PHI, THETA) : - * - * R is the distance to origin - * PHI is typical azimuth - * THETA is elevation angle (not polar angle!) - * - * X=1 Y=0 Z=0 => PHI=0 - * X=0 Y=0 Z=-1 => PHI=PI/2 - * X=-1 Y=0 Z=0 => PHI=PI - * X=0 Y=0 Z=1 => PHI=3*PI/2 - * - * X=1 Y=0 Z=0 => THETA=0 - * X=0 Y=1 Z=0 => THETA=PI/2 - * X=0 Y=-1 Z=0 => THETA=-PI/2 - */ - -typedef struct -{ - double x; - double y; - double z; -} Vector3; - -typedef struct -{ - double r; - double theta; - double phi; -} VectorSpherical; - typedef struct { double a; @@ -68,33 +30,6 @@ typedef struct double p; } Matrix4; -RENDERINGSHARED_EXPORT extern Vector3 VECTOR_ZERO; -RENDERINGSHARED_EXPORT extern Vector3 VECTOR_DOWN; -RENDERINGSHARED_EXPORT extern Vector3 VECTOR_UP; -RENDERINGSHARED_EXPORT extern Vector3 VECTOR_NORTH; -RENDERINGSHARED_EXPORT extern Vector3 VECTOR_SOUTH; -RENDERINGSHARED_EXPORT extern Vector3 VECTOR_EAST; -RENDERINGSHARED_EXPORT extern Vector3 VECTOR_WEST; - -static inline Vector3 v3(double x, double y, double z) -{ - Vector3 result = {x, y, z}; - return result; -}; -RENDERINGSHARED_EXPORT void v3Save(PackStream* stream, Vector3* v); -RENDERINGSHARED_EXPORT void v3Load(PackStream* stream, Vector3* v); -RENDERINGSHARED_EXPORT Vector3 v3Translate(Vector3 v1, double x, double y, double z); -RENDERINGSHARED_EXPORT Vector3 v3Add(Vector3 v1, Vector3 v2); -RENDERINGSHARED_EXPORT Vector3 v3Sub(Vector3 v1, Vector3 v2); -RENDERINGSHARED_EXPORT Vector3 v3Neg(Vector3 v); -RENDERINGSHARED_EXPORT Vector3 v3Scale(Vector3 v, double scale); -RENDERINGSHARED_EXPORT double v3Norm(Vector3 v); -RENDERINGSHARED_EXPORT Vector3 v3Normalize(Vector3 v); -RENDERINGSHARED_EXPORT double v3Dot(Vector3 v1, Vector3 v2); -RENDERINGSHARED_EXPORT Vector3 v3Cross(Vector3 v1, Vector3 v2); -RENDERINGSHARED_EXPORT VectorSpherical v3ToSpherical(Vector3 v); -RENDERINGSHARED_EXPORT Vector3 v3FromSpherical(VectorSpherical v); - RENDERINGSHARED_EXPORT void m4Save(PackStream* stream, Matrix4* m); RENDERINGSHARED_EXPORT void m4Load(PackStream* stream, Matrix4* m); RENDERINGSHARED_EXPORT Matrix4 m4NewIdentity();