Merge branch 'master' into develop

This commit is contained in:
Wang.Renzhu 2022-07-19 15:07:29 +08:00
commit 8bbc58faea
34 changed files with 6170 additions and 0 deletions

6
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,6 @@
{
"files.associations": {
"chrono": "cpp",
"ios": "cpp"
}
}

View File

@ -0,0 +1,86 @@
load("@build_bazel_rules_apple//apple:ios.bzl", "ios_framework")
cc_library(
name = "ios_olarender",
srcs = [
"util.cpp",
"image_queue.cpp",
"image.cpp",
"OlaRender.cpp",
"OlaRenderIMP.cpp",
],
hdrs = [
"util.h",
"macros.h",
"image_queue.h",
"image.h",
"LockFreeQueue.h",
"OlaRender.h",
"OlaRenderIMP.h",
],
# Use -Dverbose=-1 to turn off zlib's trace logging. (#3280)
linkstatic = True,
includes = ["."],
visibility = ["//visibility:public"],
deps = [
"//mediapipe/modules/render_queue/math:math",
],
copts = select({
"//mediapipe:apple": [
"-x objective-c++",
"-fobjc-arc", # enable reference-counting
],
"//conditions:default": [],
}),
alwayslink = True,
)
objc_library(
name = "OlaRenderLibrary",
visibility = ["//visibility:public"],
deps = [
"//mediapipe/modules/render_queue:ios_olarender",
],
copts = select({
"//mediapipe:apple": [
"-x objective-c++",
"-fobjc-arc", # enable reference-counting
],
"//conditions:default": [],
}),
sdk_frameworks = [
"AVFoundation",
"CoreGraphics",
"CoreMedia",
"OpenGLES",
"CoreVideo",
"IOSurface",
"Foundation",
"UIKit",
],
alwayslink = True,
)
ios_framework(
name = "OlaRenderFramework",
hdrs = [
"image.h",
"image_queue.h",
"LockFreeQueue.h",
"util.h",
"macros.h",
"OlaRender.h",
"OlaRenderIMP.h",
],
# alwayslink=True,
infoplists = ["Info.plist"],
bundle_id = "com.ola.dartrenderplugin",
families = ["iphone", "ipad"],
minimum_os_version = "10.0",
deps = [
"//mediapipe/modules/render_queue:OlaRenderLibrary",
],
)

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1.0</string>
</dict>
</plist>

View File

@ -0,0 +1,122 @@
//
// Created by Felix Wang on 2022/7/7.
//
#pragma once
#include <atomic>
#ifdef ANDROID
#include <android/log.h>
#define TAG "LockFreeQueue" // 这个是自定义的LOG的标识
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,TAG,__VA_ARGS__) // 定义LOGI类型
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,TAG,__VA_ARGS__) // 定义LOGE类型
#else
#define LOGI(...) fprintf(stdout, __VA_ARGS__)
#define LOGE(...) fprintf(stderr, __VA_ARGS__)
#endif
template<typename T>
class LockFreeQueue {
public:
LockFreeQueue(size_t capacity) {
_capacityMask = capacity - 1;
for (size_t i = 1; i <= sizeof(void *) * 4; i <<= 1)
_capacityMask |= _capacityMask >> i;
_capacity = _capacityMask + 1;
_queue = (Node * )
new char[sizeof(Node) * _capacity];
for (size_t i = 0; i < _capacity; ++i) {
_queue[i].tail.store(i, std::memory_order_relaxed);
_queue[i].head.store(-1, std::memory_order_relaxed);
}
_tail.store(0, std::memory_order_relaxed);
_head.store(0, std::memory_order_relaxed);
}
~LockFreeQueue() {
rawRelease();
}
void releaseNode(T &data) {
LOGE("~~~~~~~~~~releaseNode data: %ld", reinterpret_cast<int64_t>(data.data));
if (data.data)
free(data.data);
}
void rawRelease() {
size_t head = _head.load(std::memory_order_acquire);
for (size_t i = head; i != _tail; ++i)
(&_queue[i & _capacityMask].data)->~T();
delete[] (char *) _queue;
}
size_t rawCapacity() const { return _capacity; }
size_t rawSize() const {
size_t head = _head.load(std::memory_order_acquire);
return _tail.load(std::memory_order_relaxed) - head;
}
bool rawPush(const T &data) {
Node *node;
size_t tail = _tail.load(std::memory_order_relaxed);
for (;;) {
node = &_queue[tail & _capacityMask];
if (node->tail.load(std::memory_order_relaxed) != tail)
return false;
if ((_tail.compare_exchange_weak(tail, tail + 1, std::memory_order_relaxed)))
break;
}
new(&node->data)T(data);
LOGE("~~~~~~~~~~rawPush data: %ld", reinterpret_cast<int64_t>(node->data.data));
node->head.store(tail, std::memory_order_release);
return true;
}
bool rawPop(T &result, bool exportFlag) {
LOGE("~~~~~~~~~~33");
Node *node;
size_t head = _head.load(std::memory_order_acquire);
for (;;) {
node = &_queue[head & _capacityMask];
if (node->data.len == 0) {
LOGE("~~~~~~~~~~33 len == 0 ");
continue;
} else {
LOGE("~~~~~~~~~~33 node->data.len == %d ", node->data.len);
}
if (node->head.load(std::memory_order_relaxed) != head) {
LOGE("~~~~~~~~~~33 return false ");
return false;
}
if (_head.compare_exchange_weak(head, head + 1, std::memory_order_relaxed))
break;
}
result = node->data;
// if (() > 1)
// (&node->data)->~T();
node->tail.store(head + _capacity, std::memory_order_release);
return true;
}
private:
struct Node {
T data;
std::atomic<size_t> tail;
std::atomic<size_t> head;
};
private:
size_t _capacityMask;
Node *_queue;
size_t _capacity;
std::atomic<size_t> _tail;
std::atomic<size_t> _head;
};

View File

@ -0,0 +1,39 @@
//
// OlaRender.cpp
// OlaRender
//
// Created by 王韧竹 on 2022/6/17.
//
#include "OlaRender.h"
#if USE_OLARENDER
#include <Context.hpp>
#include <OlaDispatch.hpp>
#endif
#include "OlaRenderIMP.h"
NS_OLA_BEGIN
OlaRender::~OlaRender() {
}
OlaRender::OlaRender() {
}
#if USE_OLARENDER
OlaRender* OlaRender::create(void *env, void *context) {
return nullptr;
}
#endif
OlaRender* OlaRender::create() {
OLARenderIMP *instance = new OLARenderIMP();
return instance;
}
NS_OLA_END

View File

@ -0,0 +1,94 @@
//
// OlaRender.hpp
// OlaRender
//
// Created by 王韧竹 on 2022/6/17.
//
#ifndef OlaRender_hpp
#define OlaRender_hpp
#define USE_OLARENDER 0
// 是否开启多上下文渲染
#define USE_MULTICONTEXT 0
// 是否直接覆盖srcTexture
#define USE_TEXImage2D 0
// 是否要直接渲染到srcTexture上
#define USE_RENDER_TO_SRCTEXTURE 0
// 结束后是否需要还原fbo
#define USE_RESTORE_FBO 0
// 每次渲染结束之后重新创建
#define USE_NEED_RECREATE 0
#include <stdio.h>
#include "macros.h"
#if USE_OLARENDER
#include <target/TargetView.h>
#if PLATFORM == PLATFORM_IOS
#include "OLARenderView.h"
#endif
#endif
#if PLATFORM == PLATFORM_IOS
#import <OpenGLES/ES3/gl.h>
#import <OpenGLES/ES3/glext.h>
#elif PLATFORM == PLATFORM_ANDROID
#include <GLES3/gl3.h>
#include <GLES3/gl3ext.h>
#endif
NS_OLA_BEGIN
typedef struct {
int width;
int height;
int textureId;
int ioSurfaceId; // iOS 专属
int64_t frameTime;
} TextureInfo;
class Source;
class OlaRender {
public:
~OlaRender();
OlaRender();
#if USE_OLARENDER
// Android
static OlaRender* create(void *env, void *context);
#endif
static OlaRender *create();
/// 加载测试图 初次使用或者release后需要重新Load
virtual int loadGraph() = 0;
virtual int release() = 0;
virtual TextureInfo render(TextureInfo inputTexture, bool exportFlag) = 0;
#if USE_OLARENDER
#if PLATFORM == PLATFORM_IOS
virtual void setDisplayView(OLARenderView *target) = 0;
#else
virtual void setDisplayView(TargetView *target) = 0;
#endif
virtual void removeRenderTarget() = 0;
virtual Source* getTerminalSource() = 0;
#endif
};
NS_OLA_END
#endif /* OlaRender_hpp */

View File

@ -0,0 +1,603 @@
//
// OlaRenderIMP.cpp
// OlaRender
//
// Created by 王韧竹 on 2022/6/20.
//
#include "OlaRenderIMP.h"
#include "image_queue.h"
#if USE_OLARENDER
#include <OlaDispatch.hpp>
#endif
#if USE_OLARENDER
#else
const std::string TransformFragmentShaderString = SHADER_STRING
(
uniform
sampler2D colorMap;
varying highp
vec2 vTexCoord;
void main() {
highp
vec4 textureColor;
highp
vec2 uv = vTexCoord;
textureColor = texture2D(colorMap, uv);
gl_FragColor = vec4(textureColor.rgb, textureColor.a);
// gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
);
const std::string TransformVertexShaderString = SHADER_STRING
(
attribute
vec4 position;
attribute vec4
texCoord;
uniform mat4
mvp;
varying vec2
vTexCoord;
void main() {
gl_Position = mvp * position;
vTexCoord = texCoord.xy;
}
);
const std::string VertexShaderString = SHADER_STRING
(
attribute
vec4 position;
attribute vec4
texCoord;
attribute vec4
texCoord1;
varying vec2
vTexCoord;
varying vec2
vTexCoord1;
void main() {
gl_Position = position;
vTexCoord = texCoord.xy;
vTexCoord1 = texCoord1.xy;
}
);
const std::string FragmentShaderString = SHADER_STRING
(
varying
highp vec2
vTexCoord;
varying highp
vec2 vTexCoord1;
uniform sampler2D
colorMap;
uniform sampler2D
colorMap1;
void main() {
lowp
vec4 textureColor = texture2D(colorMap, vTexCoord);
lowp
vec4 textureColor2 = texture2D(colorMap1, vTexCoord1);
gl_FragColor = vec4(textureColor2 + textureColor * (1.0 - textureColor2.a));
}
);
#endif
NS_OLA_BEGIN
static GLfloat
positionCoords[] = {
-1.0f, -1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
-1.0f, 1.0f, 0.0f,
1.0f, 1.0f, 0.0f,
};
static GLfloat textureCoords[] = {
0.0f, 0.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
};
static GLfloat textureCoords1[] = {
0.0f, 1.0f,
1.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f,
};
OLARenderIMP::OLARenderIMP() {
}
OLARenderIMP::~OLARenderIMP() {
// imageData = nil;
ImageQueue::getInstance()->dispose();
_mvp_matrix.set_identity();
}
int OLARenderIMP::release() {
#if USE_OLARENDER
if (_sobelFilter) {
_sobelFilter->removeAllTargets();
_sobelFilter->release();
_sobelFilter = nullptr;
}
if (_brightFilter) {
_brightFilter->removeAllTargets();
_brightFilter->release();
_brightFilter = nullptr;
}
if (_inputFramebuffer) {
_inputFramebuffer->setExternalTexture(-1);
_inputFramebuffer->release(false);
_inputFramebuffer = nullptr;
}
if (_bridgeFilter) {
_bridgeFilter->release();
_bridgeFilter = nullptr;
}
_terminalFilter = nullptr;
Filter::releaseVBOBuffers();
Context::getInstance()->getFramebufferCache()->purge();
Context::destroy();
#else
if (_outputTexture > 0) {
glDeleteTextures(1, &_outputTexture);
_outputTexture = -1;
}
if (_outputFramebuffer > 0) {
glDeleteFramebuffers(1, &_outputFramebuffer);
_outputFramebuffer = -1;
}
if (_blendProgram > 0) {
glDeleteProgram(_blendProgram);
_blendProgram = -1;
}
if (_blendTexture > 0) {
glDeleteTextures(1, &_blendTexture);
_blendTexture = -1;
}
if (_blendFbo) {
glDeleteFramebuffers(1, &_blendFbo);
_blendFbo = -1;
}
if (_transformProgram) {
glDeleteProgram(_transformProgram);
_transformProgram = -1;
}
if (_transformTexture > 0) {
glDeleteTextures(1, &_transformTexture);
_transformTexture = -1;
}
#endif
_isInit = false;
return 1;
}
int OLARenderIMP::loadGraph() {
if (!_isInit) {
#if USE_OLARENDER
#if USE_MULTICONTEXT
OlaDispatch::getSharedInstance()->runSync([&] {
#endif
_brightFilter = BrightnessFilter::create();
_bridgeFilter = OlaBridgeTextureFilter::create(-1, -1, -1);
_sobelFilter = SobelEdgeDetectionFilter::create();
_sobelFilter->addTarget(_brightFilter)->addTarget(_bridgeFilter);
_terminalFilter = _bridgeFilter;
#if USE_MULTICONTEXT
}, Context::ContextType::IOContext);
#endif
#else
#endif
_isInit = true;
}
return 1;
}
TextureInfo OLARenderIMP::render(TextureInfo inputTexture, bool exportFlag) {
#if USE_NEED_RECREATE
release();
#endif
_renderWidth = inputTexture.width;
_renderHeight = inputTexture.height;
loadGraph();
TextureInfo outputTexture;
outputTexture.textureId = inputTexture.textureId;
#if USE_OLARENDER
#if USE_RESTORE_FBO
GLint curFbo;
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &curFbo);
#endif
#if USE_MULTICONTEXT
GLsync sync;
OlaDispatch::getSharedInstance()->runSync([&] {
#endif
if (_terminalFilter) {
if (_inputFramebuffer == nullptr || _inputFramebuffer->getTexture() != inputTexture.textureId) {
if (_inputFramebuffer) {
_inputFramebuffer->release(false);
_inputFramebuffer = nullptr;
}
_inputFramebuffer = new Framebuffer(inputTexture.width, inputTexture.height,
(GLuint)inputTexture.textureId, false);
_inputFramebuffer->setNoCacheFramebuffer();
}
_inputFramebuffer->setExternalTexture(inputTexture.textureId);
if (_bridgeFilter) {
//这是我们内部创建一个纹理id
#if USE_RENDER_TO_SRCTEXTURE
_bridgeFilter->updateTargetTexture(inputTexture.textureId, inputTexture.width,
inputTexture.height, -1);
#else
_bridgeFilter->updateTargetTexture(-1, inputTexture.width,
inputTexture.height, -1);
#endif
}
/**
*/
if (_brightFilter && _sobelFilter) {
_sobelFilter->unPrepear();
_sobelFilter->setInputFramebuffer(_inputFramebuffer);
_brightFilter->setBrightness(0.5);
if (_tempFactor > 1.0) {
_tempFactor = 0.0;
} else {
_tempFactor += 1.0 / 120.0;
}
_sobelFilter->setProperty("edgeStrength", _tempFactor);
_sobelFilter->update(inputTexture.frameTime); //测试渲染
}
auto *framebuffer = _terminalFilter->getFramebuffer();
if (framebuffer) {
outputTexture.textureId = framebuffer->getTexture();
outputTexture.width = framebuffer->getWidth();
outputTexture.height = framebuffer->getHeight();
outputTexture.ioSurfaceId = framebuffer->getSurfaceID();
}
}
#if USE_MULTICONTEXT
sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
glFlush();
}, Context::ContextType::IOContext);
glWaitSync(sync, 0, GL_TIMEOUT_IGNORED);
glDeleteSync(sync);
#endif
#if USE_TEXImage2D
IOSurfaceRef surface = IOSurfaceLookup(outputTexture.ioSurfaceId);
IOSurfaceLock(surface, kIOSurfaceLockReadOnly, 0);
void *pixels = IOSurfaceGetBaseAddress(surface);
glBindTexture(GL_TEXTURE_2D, inputTexture.textureId);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, outputTexture.width, outputTexture.height, 0, GL_BGRA, GL_UNSIGNED_BYTE, pixels);
IOSurfaceUnlock(surface, kIOSurfaceLockReadOnly, 0);
glBindTexture(GL_TEXTURE_2D, 0);
outputTexture.textureId = inputTexture.textureId;
#endif
#if USE_RESTORE_FBO
glBindFramebuffer(GL_FRAMEBUFFER, curFbo);
#endif
#else
_loadProgram();
_loadOutputTexture(inputTexture.width, inputTexture.height);
ImageInfo rs;
ImageQueue::getInstance()->pop(rs, exportFlag);
Log("OlaRender", "aaa");
// while (exportFlag && rs.len == 0);
if (rs.len > 0) {
int width = rs.width;
int height = rs.height;
setCanvasPixels(width, height, rs.data, inputTexture.frameTime,
Vec4(rs.startX, rs.startY, rs.normalWidth, rs.normalHeight));
Log("OlaRender", "bbb");
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glUseProgram(_blendProgram);
glBindFramebuffer(GL_FRAMEBUFFER, _outputFramebuffer);
glViewport(0, 0, inputTexture.width, inputTexture.height);
glClearColor(0, 0, 0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, inputTexture.textureId);
glUniform1i(_inputTextureSlot, 0);
glActiveTexture(GL_TEXTURE1);
CHECK_GL(glBindTexture(GL_TEXTURE_2D, _blendTexture));
CHECK_GL(glUniform1i(_inputTextureSlot1, 1));
glVertexAttribPointer(_texCoordSlot, 2, GL_FLOAT, 0, 0, textureCoords);
glEnableVertexAttribArray(_texCoordSlot);
glVertexAttribPointer(_texCoordSlot1, 2, GL_FLOAT, 0, 0, textureCoords1);
glEnableVertexAttribArray(_texCoordSlot1);
glVertexAttribPointer(_positionSlot, 3, GL_FLOAT, 0, 0, positionCoords);
glEnableVertexAttribArray(_positionSlot);
CHECK_GL(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
outputTexture.textureId = _outputTexture;
if (rs.len > 0) {
ImageQueue::getInstance()->releaseNode(rs);
}
#endif
return outputTexture;
}
void OLARenderIMP::setCanvasPixels(int width, int height, const void *pixels, int64_t frameTime,
Vec4 roi) {
if (_blendTexture != -1) {
if (_lastTransformSize != Vec2(width, height)) {
glDeleteTextures(1, &_transformTexture);
_transformTexture = -1;
}
if (_transformTexture == -1) {
glGenTextures(1, &_transformTexture);
glBindTexture(GL_TEXTURE_2D, _transformTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
CHECK_GL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels));
glBindTexture(GL_TEXTURE_2D, 0);
}
if (_transformTexture != -1 && _blendFbo != -1) {
// test
_setROI(roi);
glUseProgram(_transformProgram);
glBindFramebuffer(GL_FRAMEBUFFER, _blendFbo);
glViewport(0, 0, _renderWidth, _renderHeight);
glClearColor(0, 0, 0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, _transformTexture);
Log("OLARender", "transformTexture :%d", _transformTexture);
glUniform1i(_transformTextureSlot, 0);
glUniformMatrix4fv(_transform_mvp, 1, GL_FALSE, (GLfloat * ) & _mvp_matrix);
glVertexAttribPointer(_transformTexCoordSlot, 2, GL_FLOAT, 0, 0, textureCoords);
glEnableVertexAttribArray(_transformTexCoordSlot);
glVertexAttribPointer(_transformPositionSlot, 3, GL_FLOAT, 0, 0, positionCoords);
glEnableVertexAttribArray(_transformPositionSlot);
CHECK_GL(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
}
}
}
#if USE_OLARENDER
#if PLATFORM == PLATFORM_IOS
void OLARenderIMP::setDisplayView(OLARenderView *target) {
#else
void OLARenderIMP::setDisplayView(TargetView *target) {
#endif
_targetView = target;
if (_terminalFilter) {
_terminalFilter->addTarget(target);
}
}
void OLARenderIMP::removeRenderTarget() {
_terminalFilter->removeAllTargets();
}
Source* OLARenderIMP::getTerminalSource() {
return _terminalFilter;
}
#else
void OLARenderIMP::_loadProgram() {
if (_blendProgram == -1) {
GLuint vertexShader = _loadShader(GL_VERTEX_SHADER, VertexShaderString);
GLuint fragmentShader = _loadShader(GL_FRAGMENT_SHADER, FragmentShaderString);
_blendProgram = glCreateProgram();
if (!_blendProgram) {
assert(0);
return;
}
glAttachShader(_blendProgram, vertexShader);
glAttachShader(_blendProgram, fragmentShader);
glLinkProgram(_blendProgram);
// 检查错误
GLint linked;
glGetProgramiv(_blendProgram, GL_LINK_STATUS, &linked);
if (!linked) {
glDeleteProgram(_blendProgram);
_blendProgram = 0;
return;
}
glUseProgram(_blendProgram);
_positionSlot = glGetAttribLocation(_blendProgram, "position");
_texCoordSlot = glGetAttribLocation(_blendProgram, "texCoord");
_texCoordSlot1 = glGetAttribLocation(_blendProgram, "texCoord1");
_inputTextureSlot = glGetUniformLocation(_blendProgram, "colorMap");
_inputTextureSlot1 = glGetUniformLocation(_blendProgram, "colorMap1");
}
if (_transformProgram == -1) {
GLuint vertexShader = _loadShader(GL_VERTEX_SHADER, TransformVertexShaderString);
GLuint fragmentShader = _loadShader(GL_FRAGMENT_SHADER, TransformFragmentShaderString);
_transformProgram = glCreateProgram();
if (!_transformProgram) {
assert(0);
return;
}
glAttachShader(_transformProgram, vertexShader);
glAttachShader(_transformProgram, fragmentShader);
glLinkProgram(_transformProgram);
// 检查错误
GLint linked;
glGetProgramiv(_transformProgram, GL_LINK_STATUS, &linked);
if (!linked) {
glDeleteProgram(_transformProgram);
_transformProgram = 0;
return;
}
glUseProgram(_transformProgram);
_transformPositionSlot = glGetAttribLocation(_transformProgram, "position");
_transformTexCoordSlot = glGetAttribLocation(_transformProgram, "texCoord");
_transformTextureSlot = glGetUniformLocation(_transformProgram, "colorMap");
_transform_mvp = glGetUniformLocation(_transformProgram, "mvp");
}
}
void OLARenderIMP::_loadOutputTexture(int width, int height) {
if (_outputTexture == -1 || _outputFramebuffer == -1) {
glGenFramebuffers(1, &_outputFramebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, _outputFramebuffer);
glGenTextures(1, &_outputTexture);
glBindTexture(GL_TEXTURE_2D, _outputTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _outputTexture, 0);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
assert(status == GL_FRAMEBUFFER_COMPLETE);
glBindTexture(GL_TEXTURE_2D, 0);
glGenFramebuffers(1, &_blendFbo);
glBindFramebuffer(GL_FRAMEBUFFER, _blendFbo);
glGenTextures(1, &_blendTexture);
glBindTexture(GL_TEXTURE_2D, _blendTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _blendTexture, 0);
status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
assert(status == GL_FRAMEBUFFER_COMPLETE);
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
glBindTexture(GL_TEXTURE_2D, 0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
}
void OLARenderIMP::_setROI(Vec4 roi) {
_mvp_matrix.set_identity();
_roi.x = roi.x;
_roi.y = roi.y;
_roi.z = roi.z;
_roi.w = roi.w;
//transform OK
float realXOffset = 1.0 / _roi.z * (1.0 - _roi.z);
float realYOffset = 1.0 / _roi.w * (1.0 - _roi.w);
auto roiAdjusted = Vec4(1.0 / _roi.z * _roi.x * 2.0,
1.0 / _roi.w * _roi.y * 2.0, 1.0, 1.0);
_mvp_matrix.scale(_roi.z, _roi.w, 1.0);
// #if defined(__ANDROID__) || defined(ANDROID)
_mvp_matrix.translate(-realXOffset, realYOffset, 0.0);
_mvp_matrix.translate(roiAdjusted.x, -roiAdjusted.y, 0.0);
// #else
// _mvp_matrix.translate(-realXOffset, -realYOffset, 0.0);
// _mvp_matrix.translate(roiAdjusted.x, roiAdjusted.y, 0.0);
// #endif
}
GLuint OLARenderIMP::_loadShader(GLenum shaderType, const std::string &shaderString) {
GLuint shader = glCreateShader(shaderType);
if (shader == 0) {
return 0;
}
// Load the shader source
const char *shaderStringUTF8 = shaderString.c_str();
glShaderSource(shader, 1, &shaderStringUTF8, NULL);
// Compile the shader
glCompileShader(shader);
// Check the compile status
GLint compiled = 0;
glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
if (!compiled) {
assert(0);
glDeleteShader(shader);
return 0;
}
return shader;
}
#endif
NS_OLA_END

View File

@ -0,0 +1,122 @@
//
// OlaRenderIMP.hpp
// OlaRender
//
// Created by 王韧竹 on 2022/6/20.
//
#ifndef OlaRenderIMP_hpp
#define OlaRenderIMP_hpp
#include <stdio.h>
#include "macros.h"
#include "OlaRender.h"
#include <math/math_utils.hpp>
#if USE_OLARENDER
#include <Source.hpp>
#include <BrightnessFilter.hpp>
#include <SobelEdgeDetectionFilter.hpp>
#include <SourceImage.h>
#include <OlaBridgeTextureFilter.hpp>
#if PLATFORM == PLATFORM_IOS
#include <OLARenderView+private.h>
#endif
#else
#if PLATFORM == PLATFORM_IOS
#import <UIKit/UIKit.h>
#endif
#endif
NS_OLA_BEGIN
class OLARenderIMP : public OlaRender {
public:
OLARenderIMP();
~OLARenderIMP();
/// 加载测试图 初次使用或者release后需要重新Load
virtual int loadGraph() override;
virtual int release() override;
virtual TextureInfo render(TextureInfo inputTexture, bool exportFlag) override;
virtual void setCanvasPixels(int width, int height, const void *pixels,
int64_t frameTime, Vec4 roi);
#if USE_OLARENDER
#if PLATFORM == PLATFORM_IOS
virtual void setDisplayView(OLARenderView *target) override;
#else
virtual void setDisplayView(TargetView *target) override;
#endif
virtual void removeRenderTarget() override;
virtual Source* getTerminalSource() override;
#endif
private:
#if USE_OLARENDER
Framebuffer *_inputFramebuffer = nullptr;
Filter *_terminalFilter = nullptr;
BrightnessFilter *_brightFilter = nullptr;
SobelEdgeDetectionFilter *_sobelFilter = nullptr;
OlaBridgeTextureFilter *_bridgeFilter = nullptr;
#if PLATFORM == PLATFORM_IOS
OLARenderView *_targetView = nullptr;
#else
TargetView *_targetView = nullptr;
#endif
#else
GLuint _outputFramebuffer = -1;
GLuint _blendProgram = -1;
GLuint _positionSlot;
GLuint _positionSlot1;
GLuint _texCoordSlot;
GLuint _texCoordSlot1;
GLuint _inputTextureSlot;
GLuint _inputTextureSlot1;
GLuint _outputTexture = -1;
GLuint _blendTexture = -1;
GLuint _blendFbo = -1;
GLuint _blend_mvp = -1;
GLuint _transformProgram = -1;
GLuint _transformPositionSlot = -1;
GLuint _transformTexCoordSlot = -1;
GLuint _transformTextureSlot = -1;
GLuint _transform_mvp = -1;
GLuint _transformTexture = -1;
Vec2 _lastTransformSize = Vec2(0.0, 0.0);
Mat4 _mvp_matrix;
Vec4 _roi;
void _loadProgram();
GLuint _loadShader(GLenum shaderType, const std::string &shaderString);
void _setROI(Vec4 roi);
void _loadOutputTexture(int width, int height);
#if PLATFORM == PLATFORM_IOS
#endif
#endif
bool _isInit = false;
float _tempFactor = 0.0;
int _renderWidth = 0, _renderHeight = 0;
};
NS_OLA_END
#endif /* OlaRenderIMP_hpp */

View File

@ -0,0 +1,31 @@
//
// OlaRenderManager.h
// OlaRender
//
// Created by 王韧竹 on 2022/6/17.
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface OlaRenderManager : NSObject
+ (OlaRenderManager *)sharedInstance;
- (void)resume;
- (void)dispose;
- (int)render:(int64_t)frameTime textureId:(NSUInteger)inputTexture renderSize:(CGSize)size;
- (void)setRenderView:(UIView *)renderView;
+ (void) addImg;
+(void) disposeImg;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,97 @@
//
// OlaRenderManager.m
// OlaRender
//
// Created by 王韧竹 on 2022/6/17.
//
#import "OlaRenderManager.h"
#include "mediapipe/modules/render_queue/OlaRender.hpp"
#include "mediapipe/modules/render_queue/image_queue.h"
#include "mediapipe/modules/render_queue/image.h"
USING_NS_OLA
@interface OlaRenderManager() {
OlaRender *olaRender;
#if USE_OLARENDER
OLARenderView *targetView;
#endif
EAGLContext *currentContext;
}
@end
@implementation OlaRenderManager
+ (OlaRenderManager *)sharedInstance {
static dispatch_once_t onceToken;
static OlaRenderManager *instance = nil;
dispatch_once(&onceToken, ^{
instance = [OlaRenderManager new];
});
return instance;
}
- (instancetype)init
{
self = [super init];
if (self) {
}
return self;
}
- (void)dispose
{
if (olaRender) {
olaRender->release();
olaRender = nullptr;
}
}
// void addImageCache(const uint8_t *img, int len, double startX, double startY, double normalWidth, double normalHeight,
// int width, int height, uint64_t javaTime, uint64_t startT, uint64_t beforeFFi, bool exportFlag);
+(void)addImg
{
addImageCache(nullptr, 0, 0.0, 0.0, 0.0, 0.0, 0,0,0,0,0, false);
}
+(void)disposeImg
{
disposeImage();
}
- (int)render:(int64_t)frameTime textureId:(NSUInteger)inputTexture renderSize:(CGSize)size
{
[self resume];
TextureInfo info;
info.width = size.width;
info.height = size.height;
info.frameTime = frameTime;
info.textureId = (int)inputTexture;
TextureInfo rs = olaRender->render(info, false);
return rs.textureId;
}
- (void)resume
{
if (olaRender == nullptr) {
olaRender = OlaRender::create();
}
}
- (void)setRenderView:(UIView *)renderView
{
#if USE_OLARENDER
targetView = (OLARenderView *)renderView;
olaRender->setDisplayView(targetView);
#endif
}
@end

View File

@ -0,0 +1,45 @@
//
// Created by Felix Wang on 2022/6/29.
//
#include <jni.h>
#include <malloc.h>
#include "OlaRender.hpp"
#include "image_queue.h"
#include <android/log.h>
#include <jni.h>
#define TAG "ImageQueue-jni" // 这个是自定义的LOG的标识
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,TAG,__VA_ARGS__) // 定义LOGI类型
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,TAG,__VA_ARGS__) // 定义LOGE类型
extern "C"
JNIEXPORT jlong JNICALL
Java_com_weatherfish_render_RenderJni_create(JNIEnv *env, jobject thiz) {
auto *render = OLARender::OlaRender::create();
return reinterpret_cast<int64_t>(render);
}
extern "C"
JNIEXPORT jint JNICALL
Java_com_weatherfish_render_RenderJni_render(JNIEnv *env, jobject thiz, jlong render_context, jint texture_id,
jint width, jint height, jlong timestamp, jboolean exportFlag) {
auto *render = reinterpret_cast<OLARender::OlaRender *>(render_context);
OLARender::TextureInfo info;
info.textureId = texture_id;
info.width = width;
info.height = height;
info.frameTime = timestamp;
auto res = render->render(info, exportFlag);
return res.textureId;
}
extern "C"
JNIEXPORT void JNICALL
Java_com_weatherfish_render_RenderJni_release(JNIEnv *env, jobject thiz, jlong renderId) {
auto *render = reinterpret_cast<OLARender::OlaRender *>(renderId);
render->release();
}

View File

@ -0,0 +1,47 @@
#include "image.h"
#include "image_queue.h"
#include <cstdlib>
#include <cstdio>
#ifdef ANDROID
#include <jni.h>
//extern "C" JNIEXPORT void JNICALL
//Java_com_felix_text_1plugin_ImageCache_addImageCache(JNIEnv *env, jclass clazz, jbyteArray img, jint len) {
//
// auto *arr = (unsigned char *) malloc(len);
// (*env).GetByteArrayRegion(img, 0, len, (jbyte *) arr);
// ImageInfo info;
// ImageQueue.
//}
//extern "C"
//JNIEXPORT void JNICALL
//Java_com_felix_text_1plugin_ImageCache_addImageCache(JNIEnv *env, jclass clazz, jbyteArray img, jint len, jint width,
// jint height,
// jlong timestamp) {
// auto *arr = (unsigned char *) malloc(len);
// (*env).GetByteArrayRegion(img, 0, len, (jbyte *) arr);
// ImageQueue::getInstance()->push(arr, len, width, height, (uint32_t) timestamp);
//}
#else
#endif
extern "C" __attribute__((visibility("default"))) __attribute__((used))
void addImageCache(const uint8_t *img, int len, double startX, double startY, double normalWidth, double normalHeight,
int width, int height, uint64_t javaTime, uint64_t startT, uint64_t beforeFFi, bool exportFlag) {
ImageQueue::getInstance()->push(img, len, startX, startY, normalWidth, normalHeight, width, height, javaTime,
startT, beforeFFi, exportFlag);
}
extern "C" __attribute__((visibility("default"))) __attribute__((used))
void disposeImage() {
ImageQueue::getInstance()->dispose();
}
extern "C" __attribute__((visibility("default"))) __attribute__((used))
void test() {
}

View File

@ -0,0 +1,28 @@
#ifndef IMAGE_H
#define IMAGE_H
#include "image_queue.h"
#include "image_queue.h"
#include <stdint.h>
// #ifdef __cplusplus
extern "C"
{
// #endif
__attribute__((visibility("default"))) __attribute__((used))
void addImageCache(const uint8_t *img, int len, double startX, double startY, double normalWidth, double normalHeight,
int width, int height, uint64_t javaTime, uint64_t startT, uint64_t beforeFFi, bool exportFlag);
__attribute__((visibility("default"))) __attribute__((used))
void disposeImage();
__attribute__((visibility("default"))) __attribute__((used))
void test();
// #ifdef __cplusplus
}
// #endif
#endif

View File

@ -0,0 +1,96 @@
//
// Created by Felix Wang on 2022/6/24.
//
#include "image_queue.h"
#include <chrono>
#include <unistd.h>
ImageQueue *ImageQueue::instance = ImageQueue::getInstance();
void
ImageQueue::push(const uint8_t *img, int len, double startX, double startY, double normalWidth, double normalHeight,
int width, int height, uint64_t javaTime,
uint64_t startT,
uint64_t beforeFFi, bool exportFlag) {
LOGE("~~~~~~~~~~~~~~~~~~~~push ImageQueue push len: %d", len);
auto *arr = (uint8_t *) malloc(len);
memcpy(arr, img, len);
LOGE("~~~~~~~~~~~~~~~~~~~~push arr: %ld", reinterpret_cast<int64_t>(arr));
uint64_t afterFFi = getTimeStamp();
ImageInfo info = {arr, len, startX, startY, normalWidth, normalHeight, width, height, javaTime, startT, beforeFFi,
afterFFi, false};
rawPush(info);
if (exportFlag) {
#if defined(__APPLE__)
dispatch_semaphore_signal(sem);
#else
LOGE("~~~~~~~~~~~~~~~~~~~~push exportFlag111 true %d", sem.count);
int rs = sem_post(&sem);
LOGE("~~~~~~~~~~~~~~~~~~~~push exportFlag222 true %d ,rs = %d", sem.count, rs);
#endif
}
LOGE("############ push end %lu size:%zu startX:%f startY:%f, normalWidth:%f normalHeight:%f,width:%d,height:%d\n",
getTimeStamp(), instance->rawSize(), startX, startY, normalWidth, normalHeight, width, height);
}
void ImageQueue::pop(ImageInfo &info, bool exportFlag) {
int g_running_count = 0;
if (exportFlag) {
// LOGE("~~~~~~~~~~~~~~~~~~~~~push sem_wait33 %d", sem.count);
#if defined(__APPLE__)
dispatch_time_t dispatchtime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5* NSEC_PER_SEC));
int rs = (int)dispatch_semaphore_wait(sem, dispatchtime);
#else
int rs = sem_trywait(&sem);
while (rs == -1 && g_running_count < 3) {
usleep(9000);
rs = sem_trywait(&sem);
g_running_count++; // Break here to show we can handle breakpoints
}
#endif
// LOGE("~~~~~~~~~~~~~~~~~~~~~push sem_wait44 %d, rs=%d", sem.count, rs);
if (instance->rawSize() > 0) {
instance->rawPop(info, exportFlag);
// LOGE("########## pop end 1 %ld\n", getTimeStamp());
} else {
// LOGE("~~~~~~~~~~~~~~33 pop empty %ld\n", getTimeStamp());
info = instance->emptyInfo;
}
} else {
if (instance->rawSize() > 0) {
instance->rawPop(info, exportFlag);
// LOGE("########## pop end 1 %ld\n", getTimeStamp());
} else {
// LOGE("~~~~~~~~~~~~~~33 pop empty %ld\n", getTimeStamp());
info = instance->emptyInfo;
}
}
}
void ImageQueue::dispose() {
#if defined(__APPLE__)
dispatch_semaphore_signal(sem);
#else
sem_post(&sem);
#endif
rawRelease();
}
ImageQueue *ImageQueue::getInstance() {
if (!instance) {
instance = new ImageQueue(2);
} else {
return instance;
}
return instance;
}

View File

@ -0,0 +1,94 @@
//
// Created by Felix Wang on 2022/6/24.
//
#ifndef IMAGE_QUEUE_H
#define IMAGE_QUEUE_H
#include <queue>
#if defined(__ANDROID__) || defined(ANDROID)
#include <semaphore.h>
#else
#import <Foundation/Foundation.h>
#endif
#include <mutex>
#include <atomic>
#include "LockFreeQueue.h"
struct ImageInfo {
uint8_t *data;
int len;
double startX;
double startY;
double normalWidth;
double normalHeight;
int width;
int height;
uint64_t javaTime;
uint64_t startT;
uint64_t beforeFFi;
uint64_t afterFFi;
int flag;
};
class ImageQueue : public LockFreeQueue<ImageInfo> {
private:
static ImageQueue *instance;
// sem_t sem;
#if defined(__APPLE__)
dispatch_semaphore_t sem = 0;
#else
sem_t sem;
#endif
ImageInfo emptyInfo;
ImageQueue(size_t capacity) : LockFreeQueue(capacity) {
emptyInfo.data = nullptr;
emptyInfo.len = 0;
#if defined(__APPLE__)
sem = dispatch_semaphore_create(1);
#else
sem_init(&sem, 0, 1);
sem_wait(&sem);
#endif
};
~ImageQueue() {
#if defined(__APPLE__)
dispatch_semaphore_signal(sem);
// dispatch_release(sem);
sem = 0;
#else
sem_destroy(&sem);
#endif
};
ImageQueue(const ImageQueue &);
ImageQueue &operator=(const ImageQueue &);
public:
static long getTimeStamp() {
std::chrono::time_point<std::chrono::system_clock, std::chrono::microseconds> tp =
std::chrono::time_point_cast<std::chrono::microseconds>(std::chrono::system_clock::now());
auto tmp = std::chrono::duration_cast<std::chrono::microseconds>(tp.time_since_epoch());
long timestamp = tmp.count();
return timestamp;
}
static ImageQueue *getInstance();
// void push(ImageInfo &imageInfo);
void
push(const uint8_t *img, int len, double startX, double startY, double normalWidth, double normalHeight, int width,
int height, uint64_t javaTime, uint64_t startT, uint64_t beforeFFi, bool exportFlag);
void pop(ImageInfo &info, bool exportFlag = false);
void dispose();
};
#endif //IMAGE_QUEUE_H

View File

@ -0,0 +1,63 @@
#ifndef macros_h
#define macros_h
#define PLATFORM_UNKNOW 0
#define PLATFORM_ANDROID 1
#define PLATFORM_IOS 2
#define PLATFORM PLATFORM_UNKNOW
#if defined(__ANDROID__) || defined(ANDROID)
#undef PLATFORM
#define PLATFORM PLATFORM_ANDROID
#include <assert.h>
#elif defined(__APPLE__)
#undef PLATFORM
#define PLATFORM PLATFORM_IOS
#endif
#define NS_OLA_BEGIN namespace OLARender {
#define NS_OLA_END }
#define USING_NS_OLA using namespace OLARender;
#define STRINGIZE(x) #x
#define SHADER_STRING(text) STRINGIZE(text)
#define PI 3.14159265358979323846264338327950288
#define ENABLE_GL_CHECK false
#ifndef PLATFORM_WINDOWS
#if ENABLE_GL_CHECK
#define CHECK_GL(glFunc) \
glFunc; \
{ \
int e = glGetError(); \
if (e != 0) \
{ \
std::string errorString = ""; \
switch (e) \
{ \
case GL_INVALID_ENUM: errorString = "GL_INVALID_ENUM"; break; \
case GL_INVALID_VALUE: errorString = "GL_INVALID_VALUE"; break; \
case GL_INVALID_OPERATION: errorString = "GL_INVALID_OPERATION"; break; \
case GL_OUT_OF_MEMORY: errorString = "GL_OUT_OF_MEMORY"; break; \
default: break; \
} \
OLARender::Log("ERROR", "GL ERROR 0x%04X %s in %s at line %i\n", e, \
errorString.c_str(), __PRETTY_FUNCTION__, __LINE__); \
assert(0);\
} \
}
#else
#define CHECK_GL(glFunc) glFunc;
#endif
#endif
#include "util.h"
#endif /* macros_h */

View File

@ -0,0 +1,8 @@
cc_library(
name = "math",
srcs = glob(["*.cpp","*.inl"]),
hdrs = glob(["*.hpp"]),
# Use -Dverbose=-1 to turn off zlib's trace logging. (#3280)
includes = ["."],
visibility = ["//visibility:public"],
)

View File

@ -0,0 +1,684 @@
//
// Mat4.cpp
// OLARender
//
// Created by Wang,Renzhu on 2018/11/20.
// Copyright © 2018年 Wang,Renzhu. All rights reserved.
//
#if defined(__APPLE__)
#include "mat4.hpp"
#include "math_utils.hpp"
#else
#include "mat4.hpp"
#include "math_utils.hpp"
#endif
#include <cstring>
namespace OLARender {
static const int MATRIX_SIZE = (sizeof(float) * 16);
Mat4::Mat4()
{
*this = IDENTITY;
}
Mat4::Mat4(float m11, float m12, float m13, float m14, float m21, float m22, float m23, float m24,
float m31, float m32, float m33, float m34, float m41, float m42, float m43, float m44)
{
set(m11, m12, m13, m14, m21, m22, m23, m24, m31, m32, m33, m34, m41, m42, m43, m44);
}
Mat4::Mat4(const float* mat)
{
set(mat);
}
Mat4::Mat4(const Mat4& copy)
{
memcpy(m, copy.m, MATRIX_SIZE);
}
void Mat4::create_look_at(const Vec3& eyePosition, const Vec3& targetPosition, const Vec3& up, Mat4* dst)
{
create_look_at(eyePosition.x, eyePosition.y, eyePosition.z,
targetPosition.x, targetPosition.y, targetPosition.z,
up.x, up.y, up.z, dst);
}
void Mat4::create_look_at(float eyePositionX, float eyePositionY, float eyePositionZ,
float targetPositionX, float targetPositionY, float targetPositionZ,
float upX, float upY, float upZ, Mat4* dst)
{
Vec3 eye(eyePositionX, eyePositionY, eyePositionZ);
Vec3 target(targetPositionX, targetPositionY, targetPositionZ);
Vec3 up(upX, upY, upZ);
up.normalize();
Vec3 zaxis;
Vec3::subtract(eye, target, &zaxis);
zaxis.normalize();
Vec3 xaxis;
Vec3::cross(up, zaxis, &xaxis);
xaxis.normalize();
Vec3 yaxis;
Vec3::cross(zaxis, xaxis, &yaxis);
yaxis.normalize();
dst->m[0] = xaxis.x;
dst->m[1] = yaxis.x;
dst->m[2] = zaxis.x;
dst->m[3] = 0.0f;
dst->m[4] = xaxis.y;
dst->m[5] = yaxis.y;
dst->m[6] = zaxis.y;
dst->m[7] = 0.0f;
dst->m[8] = xaxis.z;
dst->m[9] = yaxis.z;
dst->m[10] = zaxis.z;
dst->m[11] = 0.0f;
dst->m[12] = -Vec3::dot(xaxis, eye);
dst->m[13] = -Vec3::dot(yaxis, eye);
dst->m[14] = -Vec3::dot(zaxis, eye);
dst->m[15] = 1.0f;
}
void Mat4::create_perspective(float fieldOfView, float aspectRatio,
float zNearPlane, float zFarPlane, Mat4* dst)
{
float f_n = 1.0f / (zFarPlane - zNearPlane);
float theta = MATH_DEG_TO_RAD(fieldOfView) * 0.5f;
if (std::abs(std::fmod(theta, MATH_PIOVER2)) < MATH_EPSILON)
{
return;
}
float divisor = std::tan(theta);
float factor = 1.0f / divisor;
memset(dst, 0, MATRIX_SIZE);
dst->m[0] = (1.0f / aspectRatio) * factor;
dst->m[5] = factor;
dst->m[10] = (-(zFarPlane + zNearPlane)) * f_n;
dst->m[11] = -1.0f;
dst->m[14] = -2.0f * zFarPlane * zNearPlane * f_n;
}
void Mat4::create_orthographic(float width, float height, float zNearPlane, float zFarPlane, Mat4* dst)
{
float halfWidth = width / 2.0f;
float halfHeight = height / 2.0f;
create_orthographic_off_center(-halfWidth, halfWidth, -halfHeight, halfHeight, zNearPlane, zFarPlane, dst);
}
void Mat4::create_orthographic_off_center(float left, float right, float bottom, float top,
float zNearPlane, float zFarPlane, Mat4* dst)
{
memset(dst, 0, MATRIX_SIZE);
dst->m[0] = 2 / (right - left);
dst->m[5] = 2 / (top - bottom);
dst->m[10] = 2 / (zNearPlane - zFarPlane);
dst->m[12] = (left + right) / (left - right);
dst->m[13] = (top + bottom) / (bottom - top);
dst->m[14] = (zNearPlane + zFarPlane) / (zNearPlane - zFarPlane);
dst->m[15] = 1;
}
void Mat4::create_scale(const Vec3& scale, Mat4* dst)
{
memcpy(dst, &IDENTITY, MATRIX_SIZE);
dst->m[0] = scale.x;
dst->m[5] = scale.y;
dst->m[10] = scale.z;
}
void Mat4::create_scale(float xScale, float yScale, float zScale, Mat4* dst)
{
memcpy(dst, &IDENTITY, MATRIX_SIZE);
dst->m[0] = xScale;
dst->m[5] = yScale;
dst->m[10] = zScale;
}
void Mat4::create_rotation(const Vec3& axis, float angle, Mat4* dst)
{
float x = axis.x;
float y = axis.y;
float z = axis.z;
// Make sure the input axis is normalized.
float n = x*x + y*y + z*z;
if (n != 1.0f)
{
// Not normalized.
n = std::sqrt(n);
// Prevent divide too close to zero.
if (n > 0.000001f)
{
n = 1.0f / n;
x *= n;
y *= n;
z *= n;
}
}
float c = std::cos(angle);
float s = std::sin(angle);
float t = 1.0f - c;
float tx = t * x;
float ty = t * y;
float tz = t * z;
float txy = tx * y;
float txz = tx * z;
float tyz = ty * z;
float sx = s * x;
float sy = s * y;
float sz = s * z;
dst->m[0] = c + tx*x;
dst->m[1] = txy + sz;
dst->m[2] = txz - sy;
dst->m[3] = 0.0f;
dst->m[4] = txy - sz;
dst->m[5] = c + ty*y;
dst->m[6] = tyz + sx;
dst->m[7] = 0.0f;
dst->m[8] = txz + sy;
dst->m[9] = tyz - sx;
dst->m[10] = c + tz*z;
dst->m[11] = 0.0f;
dst->m[12] = 0.0f;
dst->m[13] = 0.0f;
dst->m[14] = 0.0f;
dst->m[15] = 1.0f;
}
void Mat4::create_rotation_x(float angle, Mat4* dst)
{
memcpy(dst, &IDENTITY, MATRIX_SIZE);
float c = std::cos(angle);
float s = std::sin(angle);
dst->m[5] = c;
dst->m[6] = s;
dst->m[9] = -s;
dst->m[10] = c;
}
void Mat4::create_rotation_y(float angle, Mat4* dst)
{
memcpy(dst, &IDENTITY, MATRIX_SIZE);
float c = std::cos(angle);
float s = std::sin(angle);
dst->m[0] = c;
dst->m[2] = -s;
dst->m[8] = s;
dst->m[10] = c;
}
void Mat4::create_rotation_z(float angle, Mat4* dst)
{
memcpy(dst, &IDENTITY, MATRIX_SIZE);
float c = std::cos(angle);
float s = std::sin(angle);
dst->m[0] = c;
dst->m[1] = s;
dst->m[4] = -s;
dst->m[5] = c;
}
void Mat4::create_translation(const Vec3& translation, Mat4* dst)
{
memcpy(dst, &IDENTITY, MATRIX_SIZE);
dst->m[12] = translation.x;
dst->m[13] = translation.y;
dst->m[14] = translation.z;
}
void Mat4::create_translation(float xTranslation, float yTranslation, float zTranslation, Mat4* dst)
{
memcpy(dst, &IDENTITY, MATRIX_SIZE);
dst->m[12] = xTranslation;
dst->m[13] = yTranslation;
dst->m[14] = zTranslation;
}
void Mat4::add(float scalar)
{
add(scalar, this);
}
void Mat4::add(float scalar, Mat4* dst)
{
MathUtils::add_matrix(m, scalar, dst->m);
}
void Mat4::add(const Mat4& mat)
{
add(*this, mat, this);
}
void Mat4::add(const Mat4& m1, const Mat4& m2, Mat4* dst)
{
MathUtils::add_matrix(m1.m, m2.m, dst->m);
}
float Mat4::determinant() const
{
float a0 = m[0] * m[5] - m[1] * m[4];
float a1 = m[0] * m[6] - m[2] * m[4];
float a2 = m[0] * m[7] - m[3] * m[4];
float a3 = m[1] * m[6] - m[2] * m[5];
float a4 = m[1] * m[7] - m[3] * m[5];
float a5 = m[2] * m[7] - m[3] * m[6];
float b0 = m[8] * m[13] - m[9] * m[12];
float b1 = m[8] * m[14] - m[10] * m[12];
float b2 = m[8] * m[15] - m[11] * m[12];
float b3 = m[9] * m[14] - m[10] * m[13];
float b4 = m[9] * m[15] - m[11] * m[13];
float b5 = m[10] * m[15] - m[11] * m[14];
// Calculate the determinant.
return (a0 * b5 - a1 * b4 + a2 * b3 + a3 * b2 - a4 * b1 + a5 * b0);
}
void Mat4::get_up_vector(Vec3* dst) const
{
dst->x = m[4];
dst->y = m[5];
dst->z = m[6];
}
void Mat4::get_down_vector(Vec3* dst) const
{
dst->x = -m[4];
dst->y = -m[5];
dst->z = -m[6];
}
void Mat4::get_left_vector(Vec3* dst) const
{
dst->x = -m[0];
dst->y = -m[1];
dst->z = -m[2];
}
void Mat4::get_right_vector(Vec3* dst) const
{
dst->x = m[0];
dst->y = m[1];
dst->z = m[2];
}
void Mat4::get_forward_vector(Vec3* dst) const
{
dst->x = -m[8];
dst->y = -m[9];
dst->z = -m[10];
}
void Mat4::get_back_vector(Vec3* dst) const
{
dst->x = m[8];
dst->y = m[9];
dst->z = m[10];
}
Mat4 Mat4::get_inversed() const
{
Mat4 mat(*this);
mat.inverse();
return mat;
}
bool Mat4::inverse()
{
float a0 = m[0] * m[5] - m[1] * m[4];
float a1 = m[0] * m[6] - m[2] * m[4];
float a2 = m[0] * m[7] - m[3] * m[4];
float a3 = m[1] * m[6] - m[2] * m[5];
float a4 = m[1] * m[7] - m[3] * m[5];
float a5 = m[2] * m[7] - m[3] * m[6];
float b0 = m[8] * m[13] - m[9] * m[12];
float b1 = m[8] * m[14] - m[10] * m[12];
float b2 = m[8] * m[15] - m[11] * m[12];
float b3 = m[9] * m[14] - m[10] * m[13];
float b4 = m[9] * m[15] - m[11] * m[13];
float b5 = m[10] * m[15] - m[11] * m[14];
// Calculate the determinant.
float det = a0 * b5 - a1 * b4 + a2 * b3 + a3 * b2 - a4 * b1 + a5 * b0;
// Close to zero, can't invert.
if (std::abs(det) <= MATH_TOLERANCE)
return false;
// Support the case where m == dst.
Mat4 inverse;
inverse.m[0] = m[5] * b5 - m[6] * b4 + m[7] * b3;
inverse.m[1] = -m[1] * b5 + m[2] * b4 - m[3] * b3;
inverse.m[2] = m[13] * a5 - m[14] * a4 + m[15] * a3;
inverse.m[3] = -m[9] * a5 + m[10] * a4 - m[11] * a3;
inverse.m[4] = -m[4] * b5 + m[6] * b2 - m[7] * b1;
inverse.m[5] = m[0] * b5 - m[2] * b2 + m[3] * b1;
inverse.m[6] = -m[12] * a5 + m[14] * a2 - m[15] * a1;
inverse.m[7] = m[8] * a5 - m[10] * a2 + m[11] * a1;
inverse.m[8] = m[4] * b4 - m[5] * b2 + m[7] * b0;
inverse.m[9] = -m[0] * b4 + m[1] * b2 - m[3] * b0;
inverse.m[10] = m[12] * a4 - m[13] * a2 + m[15] * a0;
inverse.m[11] = -m[8] * a4 + m[9] * a2 - m[11] * a0;
inverse.m[12] = -m[4] * b3 + m[5] * b1 - m[6] * b0;
inverse.m[13] = m[0] * b3 - m[1] * b1 + m[2] * b0;
inverse.m[14] = -m[12] * a3 + m[13] * a1 - m[14] * a0;
inverse.m[15] = m[8] * a3 - m[9] * a1 + m[10] * a0;
multiply(inverse, 1.0f / det, this);
return true;
}
bool Mat4::is_identity() const
{
return (memcmp(m, &IDENTITY, MATRIX_SIZE) == 0);
}
void Mat4::multiply(float scalar)
{
multiply(scalar, this);
}
void Mat4::multiply(float scalar, Mat4* dst) const
{
multiply(*this, scalar, dst);
}
void Mat4::multiply(const Mat4& m, float scalar, Mat4* dst)
{
MathUtils::multiply_matrix(m.m, scalar, dst->m);
}
void Mat4::multiply(const Mat4& mat)
{
multiply(*this, mat, this);
}
void Mat4::multiply(const Mat4& m1, const Mat4& m2, Mat4* dst)
{
MathUtils::multiply_matrix(m1.m, m2.m, dst->m);
}
void Mat4::negate()
{
MathUtils::negate_matrix(m, m);
}
Mat4 Mat4::get_negated() const
{
Mat4 mat(*this);
mat.negate();
return mat;
}
void Mat4::rotate(const Vec3& axis, float angle)
{
rotate(axis, angle, this);
}
void Mat4::rotate(const Vec3& axis, float angle, Mat4* dst) const
{
Mat4 r;
create_rotation(axis, angle, &r);
multiply(*this, r, dst);
}
void Mat4::rotate_x(float angle)
{
rotate_x(angle, this);
}
void Mat4::rotate_x(float angle, Mat4* dst) const
{
Mat4 r;
create_rotation_x(angle, &r);
multiply(*this, r, dst);
}
void Mat4::rotate_y(float angle)
{
rotate_y(angle, this);
}
void Mat4::rotate_y(float angle, Mat4* dst) const
{
Mat4 r;
create_rotation_y(angle, &r);
multiply(*this, r, dst);
}
void Mat4::rotate_z(float angle)
{
rotate_z(angle, this);
}
void Mat4::rotate_z(float angle, Mat4* dst) const
{
Mat4 r;
create_rotation_z(angle, &r);
multiply(*this, r, dst);
}
void Mat4::scale(float value)
{
scale(value, this);
}
void Mat4::scale(float value, Mat4* dst) const
{
scale(value, value, value, dst);
}
void Mat4::scale(float xScale, float yScale, float zScale)
{
scale(xScale, yScale, zScale, this);
}
void Mat4::scale(float xScale, float yScale, float zScale, Mat4* dst) const
{
Mat4 s;
create_scale(xScale, yScale, zScale, &s);
multiply(*this, s, dst);
}
void Mat4::scale(const Vec3& s)
{
scale(s.x, s.y, s.z, this);
}
void Mat4::scale(const Vec3& s, Mat4* dst) const
{
scale(s.x, s.y, s.z, dst);
}
void Mat4::set(float m11, float m12, float m13, float m14, float m21, float m22, float m23, float m24,
float m31, float m32, float m33, float m34, float m41, float m42, float m43, float m44)
{
m[0] = m11;
m[1] = m21;
m[2] = m31;
m[3] = m41;
m[4] = m12;
m[5] = m22;
m[6] = m32;
m[7] = m42;
m[8] = m13;
m[9] = m23;
m[10] = m33;
m[11] = m43;
m[12] = m14;
m[13] = m24;
m[14] = m34;
m[15] = m44;
}
void Mat4::set(const float* mat)
{
memcpy(this->m, mat, MATRIX_SIZE);
}
void Mat4::set(const Mat4& mat)
{
memcpy(this->m, mat.m, MATRIX_SIZE);
}
void Mat4::set_identity()
{
memcpy(m, &IDENTITY, MATRIX_SIZE);
}
void Mat4::set_zero()
{
memset(m, 0, MATRIX_SIZE);
}
void Mat4::subtract(const Mat4& mat)
{
subtract(*this, mat, this);
}
void Mat4::subtract(const Mat4& m1, const Mat4& m2, Mat4* dst)
{
MathUtils::subtract_matrix(m1.m, m2.m, dst->m);
}
void Mat4::transform_vector(Vec3* vector) const
{
transform_vector(vector->x, vector->y, vector->z, 0.0f, vector);
}
void Mat4::transform_vector(const Vec3& vector, Vec3* dst) const
{
transform_vector(vector.x, vector.y, vector.z, 0.0f, dst);
}
void Mat4::transform_vector(float x, float y, float z, float w, Vec3* dst) const
{
MathUtils::transform_vec4(m, x, y, z, w, (float*)dst);
}
void Mat4::transform_vector(Vec4* vector) const
{
transform_vector(*vector, vector);
}
void Mat4::transform_vector(const Vec4& vector, Vec4* dst) const
{
MathUtils::transform_vec4(m, (const float*) &vector, (float*)dst);
}
void Mat4::translate(float x, float y, float z)
{
translate(x, y, z, this);
}
void Mat4::translate(float x, float y, float z, Mat4* dst) const
{
Mat4 t;
create_translation(x, y, z, &t);
multiply(*this, t, dst);
}
void Mat4::translate(const Vec3& t)
{
translate(t.x, t.y, t.z, this);
}
void Mat4::translate(const Vec3& t, Mat4* dst) const
{
translate(t.x, t.y, t.z, dst);
}
void Mat4::transpose()
{
MathUtils::transpose_matrix(m, m);
}
Mat4 Mat4::get_transposed() const
{
Mat4 mat(*this);
mat.transpose();
return mat;
}
const Mat4 Mat4::operator+(float scalar) const
{
Mat4 result(*this);
result.add(scalar);
return result;
}
Mat4& Mat4::operator+=(float scalar)
{
add(scalar);
return *this;
}
const Mat4 Mat4::operator-(float scalar) const
{
Mat4 result(*this);
result.add(-scalar);
return result;
}
Mat4& Mat4::operator-=(float scalar)
{
add(-scalar);
return *this;
}
const Mat4 Mat4::operator*(float scalar) const
{
Mat4 result(*this);
result.multiply(scalar);
return result;
}
Mat4& Mat4::operator*=(float scalar)
{
multiply(scalar);
return *this;
}
const Mat4 Mat4::IDENTITY = Mat4(1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f);
const Mat4 Mat4::ZERO = Mat4(0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0 );
}

View File

@ -0,0 +1,816 @@
//
// mat4.h
// OLARender
//
// Created by Wang,Renzhu on 2018/11/20.
// Copyright © 2018年 Wang,Renzhu. All rights reserved.
//
#ifndef MAT4_H
#define MAT4_H
#include "vec3.hpp"
#include "vec4.hpp"
namespace OLARender {
class Mat4
{
public:
float m[16];
/**
* Default constructor.
* Constructs a matrix initialized to the identity matrix:
*
* 1 0 0 0
* 0 1 0 0
* 0 0 1 0
* 0 0 0 1
*/
Mat4();
/**
* Constructs a matrix initialized to the specified value.
*
* @param m11 The first element of the first row.
* @param m12 The second element of the first row.
* @param m13 The third element of the first row.
* @param m14 The fourth element of the first row.
* @param m21 The first element of the second row.
* @param m22 The second element of the second row.
* @param m23 The third element of the second row.
* @param m24 The fourth element of the second row.
* @param m31 The first element of the third row.
* @param m32 The second element of the third row.
* @param m33 The third element of the third row.
* @param m34 The fourth element of the third row.
* @param m41 The first element of the fourth row.
* @param m42 The second element of the fourth row.
* @param m43 The third element of the fourth row.
* @param m44 The fourth element of the fourth row.
*/
Mat4(float m11, float m12, float m13, float m14, float m21, float m22, float m23, float m24,
float m31, float m32, float m33, float m34, float m41, float m42, float m43, float m44);
/**
* Creates a matrix initialized to the specified column-major array.
*
* The passed-in array is in column-major order, so the memory layout of the array is as follows:
*
* 0 4 8 12
* 1 5 9 13
* 2 6 10 14
* 3 7 11 15
*
* @param mat An array containing 16 elements in column-major order.
*/
Mat4(const float* mat);
/**
* Constructs a new matrix by copying the values from the specified matrix.
*
* @param copy The matrix to copy.
*/
Mat4(const Mat4& copy);
/**
* Creates a view matrix based on the specified input parameters.
*
* @param eyePosition The eye position.
* @param targetPosition The target's center position.
* @param up The up vector.
* @param dst A matrix to store the result in.
*/
static void create_look_at(const Vec3& eyePosition, const Vec3& targetPosition, const Vec3& up, Mat4* dst);
/**
* Creates a view matrix based on the specified input parameters.
*
* @param eyePositionX The eye x-coordinate position.
* @param eyePositionY The eye y-coordinate position.
* @param eyePositionZ The eye z-coordinate position.
* @param targetCenterX The target's center x-coordinate position.
* @param targetCenterY The target's center y-coordinate position.
* @param targetCenterZ The target's center z-coordinate position.
* @param upX The up vector x-coordinate value.
* @param upY The up vector y-coordinate value.
* @param upZ The up vector z-coordinate value.
* @param dst A matrix to store the result in.
*/
static void create_look_at(float eyePositionX, float eyePositionY, float eyePositionZ,
float targetCenterX, float targetCenterY, float targetCenterZ,
float upX, float upY, float upZ, Mat4* dst);
/**
* Builds a perspective projection matrix based on a field of view and returns by value.
*
* Projection space refers to the space after applying projection transformation from view space.
* After the projection transformation, visible content has x- and y-coordinates ranging from -1 to 1,
* and a z-coordinate ranging from 0 to 1. To obtain the viewable area (in world space) of a scene,
* create a BoundingFrustum and pass the combined view and projection matrix to the constructor.
*
* @param fieldOfView The field of view in the y direction (in degrees).
* @param aspectRatio The aspect ratio, defined as view space width divided by height.
* @param zNearPlane The distance to the near view plane.
* @param zFarPlane The distance to the far view plane.
* @param dst A matrix to store the result in.
*/
static void create_perspective(float fieldOfView, float aspectRatio, float zNearPlane, float zFarPlane, Mat4* dst);
/**
* Creates an orthographic projection matrix.
*
* @param width The width of the view.
* @param height The height of the view.
* @param zNearPlane The minimum z-value of the view volume.
* @param zFarPlane The maximum z-value of the view volume.
* @param dst A matrix to store the result in.
*/
static void create_orthographic(float width, float height, float zNearPlane, float zFarPlane, Mat4* dst);
/**
* Creates an orthographic projection matrix.
*
* Projection space refers to the space after applying
* projection transformation from view space. After the
* projection transformation, visible content has
* x and y coordinates ranging from -1 to 1, and z coordinates
* ranging from 0 to 1.
*
* Unlike perspective projection, in orthographic projection
* there is no perspective foreshortening.
*
* The viewable area of this orthographic projection extends
* from left to right on the x-axis, bottom to top on the y-axis,
* and zNearPlane to zFarPlane on the z-axis. These values are
* relative to the position and x, y, and z-axes of the view.
* To obtain the viewable area (in world space) of a scene,
* create a BoundingFrustum and pass the combined view and
* projection matrix to the constructor.
*
* @param left The minimum x-value of the view volume.
* @param right The maximum x-value of the view volume.
* @param bottom The minimum y-value of the view volume.
* @param top The maximum y-value of the view volume.
* @param zNearPlane The minimum z-value of the view volume.
* @param zFarPlane The maximum z-value of the view volume.
* @param dst A matrix to store the result in.
*/
static void create_orthographic_off_center(float left, float right, float bottom, float top,
float zNearPlane, float zFarPlane, Mat4* dst);
//Fills in an existing Mat4 so that it reflects the coordinate system about a specified Plane.
//plane The Plane about which to create a reflection.
//dst A matrix to store the result in.
//static void createReflection(const Plane& plane, Mat4* dst);
/**
* Creates a scale matrix.
*
* @param scale The amount to scale.
* @param dst A matrix to store the result in.
*/
static void create_scale(const Vec3& scale, Mat4* dst);
/**
* Creates a scale matrix.
*
* @param xScale The amount to scale along the x-axis.
* @param yScale The amount to scale along the y-axis.
* @param zScale The amount to scale along the z-axis.
* @param dst A matrix to store the result in.
*/
static void create_scale(float xScale, float yScale, float zScale, Mat4* dst);
/**
* Creates a rotation matrix from the specified axis and angle.
*
* @param axis A vector describing the axis to rotate about.
* @param angle The angle (in radians).
* @param dst A matrix to store the result in.
*/
static void create_rotation(const Vec3& axis, float angle, Mat4* dst);
/**
* Creates a matrix describing a rotation around the x-axis.
*
* @param angle The angle of rotation (in radians).
* @param dst A matrix to store the result in.
*/
static void create_rotation_x(float angle, Mat4* dst);
/**
* Creates a matrix describing a rotation around the y-axis.
*
* @param angle The angle of rotation (in radians).
* @param dst A matrix to store the result in.
*/
static void create_rotation_y(float angle, Mat4* dst);
/**
* Creates a matrix describing a rotation around the z-axis.
*
* @param angle The angle of rotation (in radians).
* @param dst A matrix to store the result in.
*/
static void create_rotation_z(float angle, Mat4* dst);
/**
* Creates a translation matrix.
*
* @param translation The translation.
* @param dst A matrix to store the result in.
*/
static void create_translation(const Vec3& translation, Mat4* dst);
/**
* Creates a translation matrix.
*
* @param xTranslation The translation on the x-axis.
* @param yTranslation The translation on the y-axis.
* @param zTranslation The translation on the z-axis.
* @param dst A matrix to store the result in.
*/
static void create_translation(float xTranslation, float yTranslation, float zTranslation, Mat4* dst);
/**
* Adds a scalar value to each component of this matrix.
*
* @param scalar The scalar to add.
*/
void add(float scalar);
/**
* Adds a scalar value to each component of this matrix and stores the result in dst.
*
* @param scalar The scalar value to add.
* @param dst A matrix to store the result in.
*/
void add(float scalar, Mat4* dst);
/**
* Adds the specified matrix to this matrix.
*
* @param mat The matrix to add.
*/
void add(const Mat4& mat);
/**
* Adds the specified matrices and stores the result in dst.
*
* @param m1 The first matrix.
* @param m2 The second matrix.
* @param dst The destination matrix to add to.
*/
static void add(const Mat4& m1, const Mat4& m2, Mat4* dst);
/**
* Computes the determinant of this matrix.
*
* @return The determinant.
*/
float determinant() const;
/**
* Gets the up vector of this matrix.
*
* @param dst The destination vector.
*/
void get_up_vector(Vec3* dst) const;
/**
* Gets the down vector of this matrix.
*
* @param dst The destination vector.
*/
void get_down_vector(Vec3* dst) const;
/**
* Gets the left vector of this matrix.
*
* @param dst The destination vector.
*/
void get_left_vector(Vec3* dst) const;
/**
* Gets the right vector of this matrix.
*
* @param dst The destination vector.
*/
void get_right_vector(Vec3* dst) const;
/**
* Gets the forward vector of this matrix.
*
* @param dst The destination vector.
*/
void get_forward_vector(Vec3* dst) const;
/**
* Gets the backward vector of this matrix.
*
* @param dst The destination vector.
*/
void get_back_vector(Vec3* dst) const;
/**
* Inverts this matrix.
*
* @return true if the matrix can be inverted, false otherwise.
*/
bool inverse();
/**
* Get the inversed matrix.
*/
Mat4 get_inversed() const;
/**
* Determines if this matrix is equal to the identity matrix.
*
* @return true if the matrix is an identity matrix, false otherwise.
*/
bool is_identity() const;
/**
* Multiplies the components of this matrix by the specified scalar.
*
* @param scalar The scalar value.
*/
void multiply(float scalar);
/**
* Multiplies the components of this matrix by a scalar and stores the result in dst.
*
* @param scalar The scalar value.
* @param dst A matrix to store the result in.
*/
void multiply(float scalar, Mat4* dst) const;
/**
* Multiplies the components of the specified matrix by a scalar and stores the result in dst.
*
* @param mat The matrix.
* @param scalar The scalar value.
* @param dst A matrix to store the result in.
*/
static void multiply(const Mat4& mat, float scalar, Mat4* dst);
/**
* Multiplies this matrix by the specified one.
*
* @param mat The matrix to multiply.
*/
void multiply(const Mat4& mat);
/**
* Multiplies m1 by m2 and stores the result in dst.
*
* @param m1 The first matrix to multiply.
* @param m2 The second matrix to multiply.
* @param dst A matrix to store the result in.
*/
static void multiply(const Mat4& m1, const Mat4& m2, Mat4* dst);
/**
* Negates this matrix.
*/
void negate();
/**
Get the Negated matrix.
*/
Mat4 get_negated() const;
/**
* Post-multiplies this matrix by the matrix corresponding to the
* specified rotation about the specified axis.
*
* @param axis The axis to rotate about.
* @param angle The angle (in radians).
*/
void rotate(const Vec3& axis, float angle);
/**
* Post-multiplies this matrix by the matrix corresponding to the specified
* rotation about the specified axis and stores the result in dst.
*
* @param axis The axis to rotate about.
* @param angle The angle (in radians).
* @param dst A matrix to store the result in.
*/
void rotate(const Vec3& axis, float angle, Mat4* dst) const;
/**
* Post-multiplies this matrix by the matrix corresponding to the
* specified rotation around the x-axis.
*
* @param angle The angle (in radians).
*/
void rotate_x(float angle);
/**
* Post-multiplies this matrix by the matrix corresponding to the
* specified rotation around the x-axis and stores the result in dst.
*
* @param angle The angle (in radians).
* @param dst A matrix to store the result in.
*/
void rotate_x(float angle, Mat4* dst) const;
/**
* Post-multiplies this matrix by the matrix corresponding to the
* specified rotation around the y-axis.
*
* @param angle The angle (in radians).
*/
void rotate_y(float angle);
/**
* Post-multiplies this matrix by the matrix corresponding to the
* specified rotation around the y-axis and stores the result in dst.
*
* @param angle The angle (in radians).
* @param dst A matrix to store the result in.
*/
void rotate_y(float angle, Mat4* dst) const;
/**
* Post-multiplies this matrix by the matrix corresponding to the
* specified rotation around the z-axis.
*
* @param angle The angle (in radians).
*/
void rotate_z(float angle);
/**
* Post-multiplies this matrix by the matrix corresponding to the
* specified rotation around the z-axis and stores the result in dst.
*
* @param angle The angle (in radians).
* @param dst A matrix to store the result in.
*/
void rotate_z(float angle, Mat4* dst) const;
/**
* Post-multiplies this matrix by the matrix corresponding to the
* specified scale transformation.
*
* @param value The amount to scale along all axes.
*/
void scale(float value);
/**
* Post-multiplies this matrix by the matrix corresponding to the
* specified scale transformation and stores the result in dst.
*
* @param value The amount to scale along all axes.
* @param dst A matrix to store the result in.
*/
void scale(float value, Mat4* dst) const;
/**
* Post-multiplies this matrix by the matrix corresponding to the
* specified scale transformation.
*
* @param xScale The amount to scale along the x-axis.
* @param yScale The amount to scale along the y-axis.
* @param zScale The amount to scale along the z-axis.
*/
void scale(float xScale, float yScale, float zScale);
/**
* Post-multiplies this matrix by the matrix corresponding to the
* specified scale transformation and stores the result in dst.
*
* @param xScale The amount to scale along the x-axis.
* @param yScale The amount to scale along the y-axis.
* @param zScale The amount to scale along the z-axis.
* @param dst A matrix to store the result in.
*/
void scale(float xScale, float yScale, float zScale, Mat4* dst) const;
/**
* Post-multiplies this matrix by the matrix corresponding to the
* specified scale transformation.
*
* @param s The scale values along the x, y and z axes.
*/
void scale(const Vec3& s);
/**
* Post-multiplies this matrix by the matrix corresponding to the
* specified scale transformation and stores the result in dst.
*
* @param s The scale values along the x, y and z axes.
* @param dst A matrix to store the result in.
*/
void scale(const Vec3& s, Mat4* dst) const;
/**
* Sets the values of this matrix.
*
* @param m11 The first element of the first row.
* @param m12 The second element of the first row.
* @param m13 The third element of the first row.
* @param m14 The fourth element of the first row.
* @param m21 The first element of the second row.
* @param m22 The second element of the second row.
* @param m23 The third element of the second row.
* @param m24 The fourth element of the second row.
* @param m31 The first element of the third row.
* @param m32 The second element of the third row.
* @param m33 The third element of the third row.
* @param m34 The fourth element of the third row.
* @param m41 The first element of the fourth row.
* @param m42 The second element of the fourth row.
* @param m43 The third element of the fourth row.
* @param m44 The fourth element of the fourth row.
*/
void set(float m11, float m12, float m13, float m14, float m21, float m22, float m23, float m24,
float m31, float m32, float m33, float m34, float m41, float m42, float m43, float m44);
/**
* Sets the values of this matrix to those in the specified column-major array.
*
* @param mat An array containing 16 elements in column-major format.
*/
void set(const float* mat);
/**
* Sets the values of this matrix to those of the specified matrix.
*
* @param mat The source matrix.
*/
void set(const Mat4& mat);
/**
* Sets this matrix to the identity matrix.
*/
void set_identity();
/**
* Sets all elements of the current matrix to zero.
*/
void set_zero();
/**
* Subtracts the specified matrix from the current matrix.
*
* @param mat The matrix to subtract.
*/
void subtract(const Mat4& mat);
/**
* Subtracts the specified matrix from the current matrix.
*
* @param m1 The first matrix.
* @param m2 The second matrix.
* @param dst A matrix to store the result in.
*/
static void subtract(const Mat4& m1, const Mat4& m2, Mat4* dst);
/**
* Transforms the specified point by this matrix.
*
* The result of the transformation is stored directly into point.
*
* @param point The point to transform and also a vector to hold the result in.
*/
inline void transform_point(Vec3* point) const {
transform_vector(point->x, point->y, point->z, 1.0f, point);
}
/**
* Transforms the specified point by this matrix, and stores
* the result in dst.
*
* @param point The point to transform.
* @param dst A vector to store the transformed point in.
*/
inline void transform_point(const Vec3& point, Vec3* dst) const {
transform_vector(point.x, point.y, point.z, 1.0f, dst);
}
/**
* Transforms the specified vector by this matrix by
* treating the fourth (w) coordinate as zero.
*
* The result of the transformation is stored directly into vector.
*
* @param vector The vector to transform and also a vector to hold the result in.
*/
void transform_vector(Vec3* vector) const;
/**
* Transforms the specified vector by this matrix by
* treating the fourth (w) coordinate as zero, and stores the
* result in dst.
*
* @param vector The vector to transform.
* @param dst A vector to store the transformed vector in.
*/
void transform_vector(const Vec3& vector, Vec3* dst) const;
/**
* Transforms the specified vector by this matrix.
*
* @param x The vector x-coordinate to transform by.
* @param y The vector y-coordinate to transform by.
* @param z The vector z-coordinate to transform by.
* @param w The vector w-coordinate to transform by.
* @param dst A vector to store the transformed point in.
*/
void transform_vector(float x, float y, float z, float w, Vec3* dst) const;
/**
* Transforms the specified vector by this matrix.
*
* The result of the transformation is stored directly into vector.
*
* @param vector The vector to transform.
*/
void transform_vector(Vec4* vector) const;
/**
* Transforms the specified vector by this matrix.
*
* @param vector The vector to transform.
* @param dst A vector to store the transformed point in.
*/
void transform_vector(const Vec4& vector, Vec4* dst) const;
/**
* Post-multiplies this matrix by the matrix corresponding to the
* specified translation.
*
* @param x The amount to translate along the x-axis.
* @param y The amount to translate along the y-axis.
* @param z The amount to translate along the z-axis.
*/
void translate(float x, float y, float z);
/**
* Post-multiplies this matrix by the matrix corresponding to the
* specified translation and stores the result in dst.
*
* @param x The amount to translate along the x-axis.
* @param y The amount to translate along the y-axis.
* @param z The amount to translate along the z-axis.
* @param dst A matrix to store the result in.
*/
void translate(float x, float y, float z, Mat4* dst) const;
/**
* Post-multiplies this matrix by the matrix corresponding to the
* specified translation.
*
* @param t The translation values along the x, y and z axes.
*/
void translate(const Vec3& t);
/**
* Post-multiplies this matrix by the matrix corresponding to the
* specified translation and stores the result in dst.
*
* @param t The translation values along the x, y and z axes.
* @param dst A matrix to store the result in.
*/
void translate(const Vec3& t, Mat4* dst) const;
/**
* Transposes this matrix.
*/
void transpose();
/**
* Get the Transposed matrix.
*/
Mat4 get_transposed() const;
/**
* Calculates the sum of this matrix with the given matrix.
*
* Note: this does not modify this matrix.
*
* @param mat The matrix to add.
* @return The matrix sum.
*/
inline Mat4 operator+(const Mat4& mat) const;
/**
* Adds the given matrix to this matrix.
*
* @param mat The matrix to add.
* @return This matrix, after the addition occurs.
*/
inline Mat4& operator+=(const Mat4& mat);
/**
* Calculates the difference of this matrix with the given matrix.
*
* Note: this does not modify this matrix.
*
* @param mat The matrix to subtract.
* @return The matrix difference.
*/
inline Mat4 operator-(const Mat4& mat) const;
/**
* Subtracts the given matrix from this matrix.
*
* @param mat The matrix to subtract.
* @return This matrix, after the subtraction occurs.
*/
inline Mat4& operator-=(const Mat4& mat);
/**
* Calculates the negation of this matrix.
*
* Note: this does not modify this matrix.
*
* @return The negation of this matrix.
*/
inline Mat4 operator-() const;
/**
* Calculates the matrix product of this matrix with the given matrix.
*
* Note: this does not modify this matrix.
*
* @param mat The matrix to multiply by.
* @return The matrix product.
*/
inline Mat4 operator*(const Mat4& mat) const;
/**
* Right-multiplies this matrix by the given matrix.
*
* @param mat The matrix to multiply by.
* @return This matrix, after the multiplication occurs.
*/
inline Mat4& operator*=(const Mat4& mat);
const Mat4 operator+(float scalar) const;
Mat4& operator+=(float scalar);
const Mat4 operator-(float scalar) const;
Mat4& operator-=(float scalar);
const Mat4 operator*(float scalar) const;
Mat4& operator*=(float scalar);
/** equals to a matrix full of zeros */
static const Mat4 ZERO;
/** equals to the identity matrix */
static const Mat4 IDENTITY;
};
/**
* Transforms the given vector by the given matrix.
*
* Note: this treats the given vector as a vector and not as a point.
*
* @param v The vector to transform.
* @param m The matrix to transform by.
* @return This vector, after the transformation occurs.
*/
inline Vec3& operator*=(Vec3& v, const Mat4& m);
/**
* Transforms the given vector by the given matrix.
*
* Note: this treats the given vector as a vector and not as a point.
*
* @param m The matrix to transform by.
* @param v The vector to transform.
* @return The resulting transformed vector.
*/
inline Vec3 operator*(const Mat4& m, const Vec3& v);
/**
* Transforms the given vector by the given matrix.
*
* Note: this treats the given vector as a vector and not as a point.
*
* @param v The vector to transform.
* @param m The matrix to transform by.
* @return This vector, after the transformation occurs.
*/
inline Vec4& operator*=(Vec4& v, const Mat4& m);
/**
* Transforms the given vector by the given matrix.
*
* Note: this treats the given vector as a vector and not as a point.
*
* @param m The matrix to transform by.
* @param v The vector to transform.
* @return The resulting transformed vector.
*/
inline Vec4 operator*(const Mat4& m, const Vec4& v);
}
#include "mat4.inl"
#endif /* MAT4_H */

View File

@ -0,0 +1,85 @@
//
// mat4.inl
// BdiEngine
//
// Created by Wang,Renzhu on 2018/11/20.
// Copyright © 2018年 Wang,Renzhu. All rights reserved.
//
#include "mat4.hpp"
namespace OLARender {
inline Mat4 Mat4::operator+(const Mat4& mat) const
{
Mat4 result(*this);
result.add(mat);
return result;
}
inline Mat4& Mat4::operator+=(const Mat4& mat)
{
add(mat);
return *this;
}
inline Mat4 Mat4::operator-(const Mat4& mat) const
{
Mat4 result(*this);
result.subtract(mat);
return result;
}
inline Mat4& Mat4::operator-=(const Mat4& mat)
{
subtract(mat);
return *this;
}
inline Mat4 Mat4::operator-() const
{
Mat4 mat(*this);
mat.negate();
return mat;
}
inline Mat4 Mat4::operator*(const Mat4& mat) const
{
Mat4 result(*this);
result.multiply(mat);
return result;
}
inline Mat4& Mat4::operator*=(const Mat4& mat)
{
multiply(mat);
return *this;
}
inline Vec3& operator*=(Vec3& v, const Mat4& m)
{
m.transform_vector(&v);
return v;
}
inline Vec3 operator*(const Mat4& m, const Vec3& v)
{
Vec3 x;
m.transform_vector(v, &x);
return x;
}
inline Vec4& operator*=(Vec4& v, const Mat4& m)
{
m.transform_vector(&v);
return v;
}
inline Vec4 operator*(const Mat4& m, const Vec4& v)
{
Vec4 x;
m.transform_vector(v, &x);
return x;
}
}

View File

@ -0,0 +1,136 @@
//
// math_utils.cpp
// OLARender
//
// Created by Wang,Renzhu on 2018/11/20.
// Copyright © 2018年 Wang,Renzhu. All rights reserved.
//
#if defined(__APPLE__)
#include "math_utils.hpp"
#else
#include "math_utils.hpp"
#endif
#include <cstring>
namespace OLARender {
static const int MATRIX_SIZE = (sizeof(float) * 16);
void MathUtils::add_matrix(const float* m, float scalar, float* dst) {
for (int i = 0; i < 16; ++i) {
dst[i] = m[i] + scalar;
}
}
void MathUtils::add_matrix(const float* m1, const float* m2, float* dst) {
for (int i = 0; i < 16; ++i) {
dst[i] = m1[i] + m2[i];
}
}
void MathUtils::subtract_matrix(const float* m1, const float* m2, float* dst) {
for (int i = 0; i < 16; ++i) {
dst[i] = m1[i] - m2[i];
}
}
void MathUtils::multiply_matrix(const float* m, float scalar, float* dst) {
for (int i = 0; i < 16; ++i) {
dst[i] = m[i] * scalar;
}
}
void MathUtils::multiply_matrix(const float* m1, const float* m2, float* dst) {
// Support the case where m1 or m2 is the same array as dst.
float product[16];
product[0] = m1[0] * m2[0] + m1[4] * m2[1] + m1[8] * m2[2] + m1[12] * m2[3];
product[1] = m1[1] * m2[0] + m1[5] * m2[1] + m1[9] * m2[2] + m1[13] * m2[3];
product[2] = m1[2] * m2[0] + m1[6] * m2[1] + m1[10] * m2[2] + m1[14] * m2[3];
product[3] = m1[3] * m2[0] + m1[7] * m2[1] + m1[11] * m2[2] + m1[15] * m2[3];
product[4] = m1[0] * m2[4] + m1[4] * m2[5] + m1[8] * m2[6] + m1[12] * m2[7];
product[5] = m1[1] * m2[4] + m1[5] * m2[5] + m1[9] * m2[6] + m1[13] * m2[7];
product[6] = m1[2] * m2[4] + m1[6] * m2[5] + m1[10] * m2[6] + m1[14] * m2[7];
product[7] = m1[3] * m2[4] + m1[7] * m2[5] + m1[11] * m2[6] + m1[15] * m2[7];
product[8] = m1[0] * m2[8] + m1[4] * m2[9] + m1[8] * m2[10] + m1[12] * m2[11];
product[9] = m1[1] * m2[8] + m1[5] * m2[9] + m1[9] * m2[10] + m1[13] * m2[11];
product[10] = m1[2] * m2[8] + m1[6] * m2[9] + m1[10] * m2[10] + m1[14] * m2[11];
product[11] = m1[3] * m2[8] + m1[7] * m2[9] + m1[11] * m2[10] + m1[15] * m2[11];
product[12] = m1[0] * m2[12] + m1[4] * m2[13] + m1[8] * m2[14] + m1[12] * m2[15];
product[13] = m1[1] * m2[12] + m1[5] * m2[13] + m1[9] * m2[14] + m1[13] * m2[15];
product[14] = m1[2] * m2[12] + m1[6] * m2[13] + m1[10] * m2[14] + m1[14] * m2[15];
product[15] = m1[3] * m2[12] + m1[7] * m2[13] + m1[11] * m2[14] + m1[15] * m2[15];
memcpy(dst, product, MATRIX_SIZE);
}
void MathUtils::negate_matrix(const float* m, float* dst) {
for (int i = 0; i < 16; ++i) {
dst[i] = -m[i];
}
}
void MathUtils::transpose_matrix(const float* m, float* dst) {
float t[16] = {
m[0], m[4], m[8], m[12],
m[1], m[5], m[9], m[13],
m[2], m[6], m[10], m[14],
m[3], m[7], m[11], m[15]
};
memcpy(dst, t, MATRIX_SIZE);
}
void MathUtils::transform_vec4(const float* m, float x, float y, float z, float w, float* dst) {
dst[0] = x * m[0] + y * m[4] + z * m[8] + w * m[12];
dst[1] = x * m[1] + y * m[5] + z * m[9] + w * m[13];
dst[2] = x * m[2] + y * m[6] + z * m[10] + w * m[14];
}
void MathUtils::transform_vec4(const float* m, const float* v, float* dst) {
// Handle case where v == dst.
float x = v[0] * m[0] + v[1] * m[4] + v[2] * m[8] + v[3] * m[12];
float y = v[0] * m[1] + v[1] * m[5] + v[2] * m[9] + v[3] * m[13];
float z = v[0] * m[2] + v[1] * m[6] + v[2] * m[10] + v[3] * m[14];
float w = v[0] * m[3] + v[1] * m[7] + v[2] * m[11] + v[3] * m[15];
dst[0] = x;
dst[1] = y;
dst[2] = z;
dst[3] = w;
}
void MathUtils::cross_vec3(const float* v1, const float* v2, float* dst) {
float x = (v1[1] * v2[2]) - (v1[2] * v2[1]);
float y = (v1[2] * v2[0]) - (v1[0] * v2[2]);
float z = (v1[0] * v2[1]) - (v1[1] * v2[0]);
dst[0] = x;
dst[1] = y;
dst[2] = z;
}
void MathUtils::smooth(float* x, float target, float elapsedTime, float responseTime)
{
if (elapsedTime > 0) {
*x += (target - *x) * elapsedTime / (elapsedTime + responseTime);
}
}
void MathUtils::smooth(float* x, float target, float elapsedTime, float riseTime, float fallTime)
{
if (elapsedTime > 0) {
float delta = target - *x;
*x += delta * elapsedTime / (elapsedTime + (delta > 0 ? riseTime : fallTime));
}
}
float MathUtils::lerp(float from, float to, float alpha)
{
return from * (1.0f - alpha) + to * alpha;
}
}

View File

@ -0,0 +1,99 @@
//
// math_utils.h
// OLARender
//
// Created by Wang,Renzhu on 2018/11/20.
// Copyright © 2018年 Wang,Renzhu. All rights reserved.
//
#ifndef DI_ENGINE_MATH_UTILS_H
#define DI_ENGINE_MATH_UTILS_H
#include "mat4.hpp"
#include "vec2.hpp"
#include "vec3.hpp"
#include "vec4.hpp"
#include <cstring>
#define MATH_DEG_TO_RAD(x) ((x) * 0.0174532925f)
#define MATH_RAD_TO_DEG(x) ((x)* 57.29577951f)
#define MATH_FLOAT_SMALL 1.0e-37f
#define MATH_TOLERANCE 2e-37f
#define MATH_PIOVER2 1.57079632679489661923f
#define MATH_EPSILON 0.000001f
#define MATH_FLOAT_EQUAL(src, dst) (((src) >= (dst) - MATH_EPSILON) && ((src) <= (dst) + MATH_EPSILON))
namespace OLARender {
class MathUtils
{
public:
static void add_matrix(const float* m, float scalar, float* dst);
static void add_matrix(const float* m1, const float* m2, float* dst);
static void subtract_matrix(const float* m1, const float* m2, float* dst);
static void multiply_matrix(const float* m, float scalar, float* dst);
static void multiply_matrix(const float* m1, const float* m2, float* dst);
static void negate_matrix(const float* m, float* dst);
static void transpose_matrix(const float* m, float* dst);
static void transform_vec4(const float* m, float x, float y, float z, float w, float* dst);
static void transform_vec4(const float* m, const float* v, float* dst);
static void cross_vec3(const float* v1, const float* v2, float* dst);
public:
/**
* Updates the given scalar towards the given target using a smoothing function.
* The given response time determines the amount of smoothing (lag). A longer
* response time yields a smoother result and more lag. To force the scalar to
* follow the target closely, provide a response time that is very small relative
* to the given elapsed time.
*
* @param x the scalar to update.
* @param target target value.
* @param elapsedTime elapsed time between calls.
* @param responseTime response time (in the same units as elapsedTime).
*/
static void smooth(float* x, float target, float elapsedTime, float responseTime);
/**
* Updates the given scalar towards the given target using a smoothing function.
* The given rise and fall times determine the amount of smoothing (lag). Longer
* rise and fall times yield a smoother result and more lag. To force the scalar to
* follow the target closely, provide rise and fall times that are very small relative
* to the given elapsed time.
*
* @param x the scalar to update.
* @param target target value.
* @param elapsedTime elapsed time between calls.
* @param riseTime response time for rising slope (in the same units as elapsedTime).
* @param fallTime response time for falling slope (in the same units as elapsedTime).
*/
static void smooth(float* x, float target, float elapsedTime, float riseTime, float fallTime);
/**
* Linearly interpolates between from value to to value by alpha which is in
* the range [0,1]
*
* @param from the from value.
* @param to the to value.
* @param alpha the alpha value between [0,1]
*
* @return interpolated float value
*/
static float lerp(float from, float to, float alpha);
};
}
#endif /* DI_ENGINE_MATH_UTILS_H */

View File

@ -0,0 +1,179 @@
//
// vec2.cpp
// OLARender
//
// Created by Wang,Renzhu on 2018/11/20.
// Copyright © 2018年 Wang,Renzhu. All rights reserved.
//
#if defined(__APPLE__)
#include "vec2.hpp"
#include "math_utils.hpp"
#else
#include "vec2.hpp"
#include "math_utils.hpp"
#endif
namespace OLARender {
float Vec2::angle(const Vec2& v1, const Vec2& v2)
{
float dz = v1.x * v2.y - v1.y * v2.x;
return atan2f(fabsf(dz) + MATH_FLOAT_SMALL, dot(v1, v2));
}
void Vec2::add(const Vec2& v1, const Vec2& v2, Vec2* dst)
{
if (dst) {
dst->x = v1.x + v2.x;
dst->y = v1.y + v2.y;
}
}
void Vec2::clamp(const Vec2& min, const Vec2& max)
{
// Clamp the x value.
if (x < min.x)
x = min.x;
if (x > max.x)
x = max.x;
// Clamp the y value.
if (y < min.y)
y = min.y;
if (y > max.y)
y = max.y;
}
void Vec2::clamp(const Vec2& v, const Vec2& min, const Vec2& max, Vec2* dst)
{
if (dst) {
// Clamp the x value.
dst->x = v.x;
if (dst->x < min.x)
dst->x = min.x;
if (dst->x > max.x)
dst->x = max.x;
// Clamp the y value.
dst->y = v.y;
if (dst->y < min.y)
dst->y = min.y;
if (dst->y > max.y)
dst->y = max.y;
}
}
float Vec2::distance(const Vec2& v) const
{
float dx = v.x - x;
float dy = v.y - y;
return std::sqrt(dx * dx + dy * dy);
}
float Vec2::dot(const Vec2& v1, const Vec2& v2)
{
return (v1.x * v2.x + v1.y * v2.y);
}
float Vec2::length() const
{
return std::sqrt(x * x + y * y);
}
void Vec2::normalize()
{
float n = x * x + y * y;
// Already normalized.
if (n == 1.0f)
return;
n = std::sqrt(n);
// Too close to zero.
if (n < MATH_TOLERANCE)
return;
n = 1.0f / n;
x *= n;
y *= n;
}
Vec2 Vec2::get_normalized() const
{
Vec2 v(*this);
v.normalize();
return v;
}
void Vec2::rotate(const Vec2& point, float angle)
{
float sinAngle = std::sin(angle);
float cosAngle = std::cos(angle);
if (point.is_zero())
{
float tempX = x * cosAngle - y * sinAngle;
y = y * cosAngle + x * sinAngle;
x = tempX;
}
else
{
float tempX = x - point.x;
float tempY = y - point.y;
x = tempX * cosAngle - tempY * sinAngle + point.x;
y = tempY * cosAngle + tempX * sinAngle + point.y;
}
}
void Vec2::set(const float* array)
{
if (array) {
x = array[0];
y = array[1];
}
}
void Vec2::subtract(const Vec2& v1, const Vec2& v2, Vec2* dst)
{
if (dst) {
dst->x = v1.x - v2.x;
dst->y = v1.y - v2.y;
}
}
bool Vec2::equals(const Vec2& target) const
{
return (std::abs(this->x - target.x) < MATH_EPSILON)
&& (std::abs(this->y - target.y) < MATH_EPSILON);
}
float Vec2::get_angle(const Vec2& other) const
{
Vec2 a2 = get_normalized();
Vec2 b2 = other.get_normalized();
float angle = atan2f(a2.cross(b2), a2.dot(b2));
if (std::abs(angle) < MATH_EPSILON) return 0.f;
return angle;
}
Vec2 Vec2::rotate_by_angle(const Vec2& pivot, float angle) const
{
return pivot + (*this - pivot).rotate(Vec2::for_angle(angle));
}
const Vec2 Vec2::ZERO(0.0f, 0.0f);
const Vec2 Vec2::ONE(1.0f, 1.0f);
const Vec2 Vec2::UNIT_X(1.0f, 0.0f);
const Vec2 Vec2::UNIT_Y(0.0f, 1.0f);
const Vec2 Vec2::ANCHOR_MIDDLE(0.5f, 0.5f);
const Vec2 Vec2::ANCHOR_BOTTOM_LEFT(0.0f, 0.0f);
const Vec2 Vec2::ANCHOR_TOP_LEFT(0.0f, 1.0f);
const Vec2 Vec2::ANCHOR_BOTTOM_RIGHT(1.0f, 0.0f);
const Vec2 Vec2::ANCHOR_TOP_RIGHT(1.0f, 1.0f);
const Vec2 Vec2::ANCHOR_MIDDLE_RIGHT(1.0f, 0.5f);
const Vec2 Vec2::ANCHOR_MIDDLE_LEFT(0.0f, 0.5f);
const Vec2 Vec2::ANCHOR_MIDDLE_TOP(0.5f, 1.0f);
const Vec2 Vec2::ANCHOR_MIDDLE_BOTTOM(0.5f, 0.0f);
}

View File

@ -0,0 +1,615 @@
//
// vec2.h
// OLARender
//
// Created by Wang,Renzhu on 2018/11/20.
// Copyright © 2018年 Wang,Renzhu. All rights reserved.
//
#ifndef VEC2_H
#define VEC2_H
#include <algorithm>
#include <cmath>
namespace OLARender {
inline float clampf(float value, float min_inclusive, float max_inclusive) {
if (min_inclusive > max_inclusive) {
std::swap(min_inclusive, max_inclusive);
}
return value < min_inclusive ? min_inclusive : value < max_inclusive ? value : max_inclusive;
}
/**
* Defines a 2-element floating point vector.
*/
class Vec2
{
public:
float x;
float y;
/**
* Constructs a new vector initialized to all zeros.
*/
Vec2();
/**
* Constructs a new vector initialized to the specified values.
*
* @param xx The x coordinate.
* @param yy The y coordinate.
*/
Vec2(float xx, float yy);
/**
* Constructs a new vector from the values in the specified array.
*
* @param array An array containing the elements of the vector in the order x, y.
*/
Vec2(const float* array);
/**
* Constructs a vector that describes the direction between the specified points.
*
* @param p1 The first point.
* @param p2 The second point.
*/
Vec2(const Vec2& p1, const Vec2& p2);
/**
* Constructs a new vector that is a copy of the specified vector.
*
* @param copy The vector to copy.
*/
Vec2(const Vec2& copy);
/**
* Indicates whether this vector contains all zeros.
*
* @return true if this vector contains all zeros, false otherwise.
*/
inline bool is_zero() const;
/**
* Indicates whether this vector contains all ones.
*
* @return true if this vector contains all ones, false otherwise.
*/
inline bool is_one() const;
/**
* Returns the angle (in radians) between the specified vectors.
*
* @param v1 The first vector.
* @param v2 The second vector.
*
* @return The angle between the two vectors (in radians).
*/
static float angle(const Vec2& v1, const Vec2& v2);
/**
* Adds the elements of the specified vector to this one.
*
* @param v The vector to add.
*/
inline void add(const Vec2& v);
/**
* Adds the specified vectors and stores the result in dst.
*
* @param v1 The first vector.
* @param v2 The second vector.
* @param dst A vector to store the result in.
*/
static void add(const Vec2& v1, const Vec2& v2, Vec2* dst);
/**
* Clamps this vector within the specified range.
*
* @param min The minimum value.
* @param max The maximum value.
*/
void clamp(const Vec2& min, const Vec2& max);
/**
* Clamps the specified vector within the specified range and returns it in dst.
*
* @param v The vector to clamp.
* @param min The minimum value.
* @param max The maximum value.
* @param dst A vector to store the result in.
*/
static void clamp(const Vec2& v, const Vec2& min, const Vec2& max, Vec2* dst);
/**
* Returns the distance between this vector and v.
*
* @param v The other vector.
*
* @return The distance between this vector and v.
*
* @see distanceSquared
*/
float distance(const Vec2& v) const;
/**
* Returns the squared distance between this vector and v.
*
* When it is not necessary to get the exact distance between
* two vectors (for example, when simply comparing the
* distance between different vectors), it is advised to use
* this method instead of distance.
*
* @param v The other vector.
*
* @return The squared distance between this vector and v.
*
* @see distance
*/
inline float distance_squared(const Vec2& v) const;
/**
* Returns the dot product of this vector and the specified vector.
*
* @param v The vector to compute the dot product with.
*
* @return The dot product.
*/
inline float dot(const Vec2& v) const;
/**
* Returns the dot product between the specified vectors.
*
* @param v1 The first vector.
* @param v2 The second vector.
*
* @return The dot product between the vectors.
*/
static float dot(const Vec2& v1, const Vec2& v2);
/**
* Computes the length of this vector.
*
* @return The length of the vector.
*
* @see lengthSquared
*/
float length() const;
/**
* Returns the squared length of this vector.
*
* When it is not necessary to get the exact length of a
* vector (for example, when simply comparing the lengths of
* different vectors), it is advised to use this method
* instead of length.
*
* @return The squared length of the vector.
*
* @see length
*/
inline float length_squared() const;
/**
* Negates this vector.
*/
inline void negate();
/**
* Normalizes this vector.
*
* This method normalizes this Vec2 so that it is of
* unit length (in other words, the length of the vector
* after calling this method will be 1.0f). If the vector
* already has unit length or if the length of the vector
* is zero, this method does nothing.
*/
void normalize();
/**
Get the normalized vector.
*/
Vec2 get_normalized() const;
/**
* Scales all elements of this vector by the specified value.
*
* @param scalar The scalar value.
*/
inline void scale(float scalar);
/**
* Scales each element of this vector by the matching component of scale.
*
* @param scale The vector to scale by.
*/
inline void scale(const Vec2& scale);
/**
* Rotates this vector by angle (specified in radians) around the given point.
*
* @param point The point to rotate around.
* @param angle The angle to rotate by (in radians).
*/
void rotate(const Vec2& point, float angle);
/**
* Sets the elements of this vector to the specified values.
*
* @param xx The new x coordinate.
* @param yy The new y coordinate.
*/
inline void set(float xx, float yy);
/**
* Sets the elements of this vector from the values in the specified array.
*
* @param array An array containing the elements of the vector in the order x, y.
*/
void set(const float* array);
/**
* Sets the elements of this vector to those in the specified vector.
*
* @param v The vector to copy.
*/
inline void set(const Vec2& v);
/**
* Sets this vector to the directional vector between the specified points.
*
* @param p1 The first point.
* @param p2 The second point.
*/
inline void set(const Vec2& p1, const Vec2& p2);
/**
* Sets the elements of this vector to zero.
*/
inline void set_zero();
/**
* Subtracts this vector and the specified vector as (this - v)
* and stores the result in this vector.
*
* @param v The vector to subtract.
*/
inline void subtract(const Vec2& v);
/**
* Subtracts the specified vectors and stores the result in dst.
* The resulting vector is computed as (v1 - v2).
*
* @param v1 The first vector.
* @param v2 The second vector.
* @param dst The destination vector.
*/
static void subtract(const Vec2& v1, const Vec2& v2, Vec2* dst);
/**
* Updates this vector towards the given target using a smoothing function.
* The given response time determines the amount of smoothing (lag). A longer
* response time yields a smoother result and more lag. To force this vector to
* follow the target closely, provide a response time that is very small relative
* to the given elapsed time.
*
* @param target target value.
* @param elapsedTime elapsed time between calls.
* @param responseTime response time (in the same units as elapsedTime).
*/
inline void smooth(const Vec2& target, float elapsedTime, float responseTime);
/**
* Calculates the sum of this vector with the given vector.
*
* Note: this does not modify this vector.
*
* @param v The vector to add.
* @return The vector sum.
*/
inline Vec2 operator+(const Vec2& v) const;
/**
* Adds the given vector to this vector.
*
* @param v The vector to add.
* @return This vector, after the addition occurs.
*/
inline Vec2& operator+=(const Vec2& v);
/**
* Calculates the sum of this vector with the given vector.
*
* Note: this does not modify this vector.
*
* @param v The vector to add.
* @return The vector sum.
*/
inline Vec2 operator-(const Vec2& v) const;
/**
* Subtracts the given vector from this vector.
*
* @param v The vector to subtract.
* @return This vector, after the subtraction occurs.
*/
inline Vec2& operator-=(const Vec2& v);
/**
* Calculates the negation of this vector.
*
* Note: this does not modify this vector.
*
* @return The negation of this vector.
*/
inline Vec2 operator-() const;
/**
* Calculates the scalar product of this vector with the given value.
*
* Note: this does not modify this vector.
*
* @param s The value to scale by.
* @return The scaled vector.
*/
inline Vec2 operator*(float s) const;
/**
* Scales this vector by the given value.
*
* @param s The value to scale by.
* @return This vector, after the scale occurs.
*/
inline Vec2& operator*=(float s);
/**
* Returns the components of this vector divided by the given constant
*
* Note: this does not modify this vector.
*
* @param s the constant to divide this vector with
* @return a smaller vector
*/
inline Vec2 operator/(float s) const;
/**
* Determines if this vector is less than the given vector.
*
* @param v The vector to compare against.
*
* @return True if this vector is less than the given vector, false otherwise.
*/
inline bool operator<(const Vec2& v) const;
/**
* Determines if this vector is greater than the given vector.
*
* @param v The vector to compare against.
*
* @return True if this vector is greater than the given vector, false otherwise.
*/
inline bool operator>(const Vec2& v) const;
/**
* Determines if this vector is equal to the given vector.
*
* @param v The vector to compare against.
*
* @return True if this vector is equal to the given vector, false otherwise.
*/
inline bool operator==(const Vec2& v) const;
/**
* Determines if this vector is not equal to the given vector.
*
* @param v The vector to compare against.
*
* @return True if this vector is not equal to the given vector, false otherwise.
*/
inline bool operator!=(const Vec2& v) const;
//code added compatible for Point
public:
/**
* @js NA
* @lua NA
*/
inline void set_point(float xx, float yy);
/**
* @js NA
*/
bool equals(const Vec2& target) const;
/** Calculates distance between point an origin
@return float
@since v2.1.4
* @js NA
* @lua NA
*/
inline float get_length() const {
return sqrtf(x*x + y*y);
}
/** Calculates the square length of a Vec2 (not calling sqrt() )
@return float
@since v2.1.4
* @js NA
* @lua NA
*/
inline float get_length_sq() const {
return dot(*this); //x*x + y*y;
}
/** Calculates the square distance between two points (not calling sqrt() )
@return float
@since v2.1.4
* @js NA
* @lua NA
*/
inline float get_distance_sq(const Vec2& other) const {
return (*this - other).get_length_sq();
}
/** Calculates the distance between two points
@return float
@since v2.1.4
* @js NA
* @lua NA
*/
inline float get_distance(const Vec2& other) const {
return (*this - other).get_length();
}
/** @returns the angle in radians between this vector and the x axis
@since v2.1.4
* @js NA
* @lua NA
*/
inline float get_angle() const {
return atan2f(y, x);
}
/** @returns the angle in radians between two vector directions
@since v2.1.4
* @js NA
* @lua NA
*/
float get_angle(const Vec2& other) const;
/** Calculates cross product of two points.
@return float
@since v2.1.4
* @js NA
* @lua NA
*/
inline float cross(const Vec2& other) const {
return x*other.y - y*other.x;
}
/** Calculates midpoint between two points.
@return Vec2
@since v3.0
* @js NA
* @lua NA
*/
inline Vec2 get_mid_point(const Vec2& other) const {
return Vec2((x + other.x) / 2.0f, (y + other.y) / 2.0f);
}
/** Clamp a point between from and to.
@since v3.0
* @js NA
* @lua NA
*/
inline Vec2 get_clamp_point(const Vec2& min_inclusive, const Vec2& max_inclusive) const {
return Vec2(clampf(x, min_inclusive.x, max_inclusive.x), clampf(y, min_inclusive.y, max_inclusive.y));
}
/** Calculates the projection of this over other.
@return Vec2
@since v2.1.4
* @js NA
* @lua NA
*/
inline Vec2 project(const Vec2& other) const {
return other * (dot(other)/other.dot(other));
}
/** Complex multiplication of two points ("rotates" two points).
@return Vec2 vector with an angle of this.getAngle() + other.getAngle(),
and a length of this.getLength() * other.getLength().
@since v2.1.4
* @js NA
* @lua NA
*/
inline Vec2 rotate(const Vec2& other) const {
return Vec2(x*other.x - y*other.y, x*other.y + y*other.x);
}
/** Unrotates two points.
@return Vec2 vector with an angle of this.getAngle() - other.getAngle(),
and a length of this.getLength() * other.getLength().
@since v2.1.4
* @js NA
* @lua NA
*/
inline Vec2 unrotate(const Vec2& other) const {
return Vec2(x*other.x + y*other.y, y*other.x - x*other.y);
}
/** Linear Interpolation between two points a and b
@returns
alpha == 0 ? a
alpha == 1 ? b
otherwise a value between a..b
@since v2.1.4
* @js NA
* @lua NA
*/
inline Vec2 lerp(const Vec2& other, float alpha) const {
return *this * (1.f - alpha) + other * alpha;
}
/** Rotates a point counter clockwise by the angle around a pivot
@param pivot is the pivot, naturally
@param angle is the angle of rotation ccw in radians
@returns the rotated point
@since v2.1.4
* @js NA
* @lua NA
*/
Vec2 rotate_by_angle(const Vec2& pivot, float angle) const;
/**
* @js NA
* @lua NA
*/
static inline Vec2 for_angle(const float a) {
return Vec2(cosf(a), sinf(a));
}
/** equals to Vec2(0,0) */
static const Vec2 ZERO;
/** equals to Vec2(1,1) */
static const Vec2 ONE;
/** equals to Vec2(1,0) */
static const Vec2 UNIT_X;
/** equals to Vec2(0,1) */
static const Vec2 UNIT_Y;
/** equals to Vec2(0.5, 0.5) */
static const Vec2 ANCHOR_MIDDLE;
/** equals to Vec2(0, 0) */
static const Vec2 ANCHOR_BOTTOM_LEFT;
/** equals to Vec2(0, 1) */
static const Vec2 ANCHOR_TOP_LEFT;
/** equals to Vec2(1, 0) */
static const Vec2 ANCHOR_BOTTOM_RIGHT;
/** equals to Vec2(1, 1) */
static const Vec2 ANCHOR_TOP_RIGHT;
/** equals to Vec2(1, 0.5) */
static const Vec2 ANCHOR_MIDDLE_RIGHT;
/** equals to Vec2(0, 0.5) */
static const Vec2 ANCHOR_MIDDLE_LEFT;
/** equals to Vec2(0.5, 1) */
static const Vec2 ANCHOR_MIDDLE_TOP;
/** equals to Vec2(0.5, 0) */
static const Vec2 ANCHOR_MIDDLE_BOTTOM;
};
/**
* Calculates the scalar product of the given vector with the given value.
*
* @param x The value to scale by.
* @param v The vector to scale.
* @return The scaled vector.
*/
inline Vec2 operator*(float x, const Vec2& v);
typedef Vec2 Point;
}
#include "vec2.inl"
#endif /* VEC2_H */

View File

@ -0,0 +1,216 @@
//
// vec2.inl
// BdiEngine
//
// Created by Wang,Renzhu on 2018/11/20.
// Copyright © 2018年 Wang,Renzhu. All rights reserved.
//
#include "vec2.hpp"
namespace OLARender {
inline Vec2::Vec2() : x(0.0f), y(0.0f)
{
}
inline Vec2::Vec2(float xx, float yy) : x(xx), y(yy)
{
}
inline Vec2::Vec2(const float* array)
{
set(array);
}
inline Vec2::Vec2(const Vec2& p1, const Vec2& p2)
{
set(p1, p2);
}
inline Vec2::Vec2(const Vec2& copy)
{
set(copy);
}
inline bool Vec2::is_zero() const
{
return x == 0.0f && y == 0.0f;
}
bool Vec2::is_one() const
{
return x == 1.0f && y == 1.0f;
}
inline void Vec2::add(const Vec2& v)
{
x += v.x;
y += v.y;
}
inline float Vec2::distance_squared(const Vec2& v) const
{
float dx = v.x - x;
float dy = v.y - y;
return (dx * dx + dy * dy);
}
inline float Vec2::dot(const Vec2& v) const
{
return (x * v.x + y * v.y);
}
inline float Vec2::length_squared() const
{
return (x * x + y * y);
}
inline void Vec2::negate()
{
x = -x;
y = -y;
}
inline void Vec2::scale(float scalar)
{
x *= scalar;
y *= scalar;
}
inline void Vec2::scale(const Vec2& scale)
{
x *= scale.x;
y *= scale.y;
}
inline void Vec2::set(float xx, float yy)
{
this->x = xx;
this->y = yy;
}
inline void Vec2::set(const Vec2& v)
{
this->x = v.x;
this->y = v.y;
}
inline void Vec2::set(const Vec2& p1, const Vec2& p2)
{
x = p2.x - p1.x;
y = p2.y - p1.y;
}
void Vec2::set_zero()
{
x = y = 0.0f;
}
inline void Vec2::subtract(const Vec2& v)
{
x -= v.x;
y -= v.y;
}
inline void Vec2::smooth(const Vec2& target, float elapsedTime, float responseTime)
{
if (elapsedTime > 0)
{
*this += (target - *this) * (elapsedTime / (elapsedTime + responseTime));
}
}
inline Vec2 Vec2::operator+(const Vec2& v) const
{
Vec2 result(*this);
result.add(v);
return result;
}
inline Vec2& Vec2::operator+=(const Vec2& v)
{
add(v);
return *this;
}
inline Vec2 Vec2::operator-(const Vec2& v) const
{
Vec2 result(*this);
result.subtract(v);
return result;
}
inline Vec2& Vec2::operator-=(const Vec2& v)
{
subtract(v);
return *this;
}
inline Vec2 Vec2::operator-() const
{
Vec2 result(*this);
result.negate();
return result;
}
inline Vec2 Vec2::operator*(float s) const
{
Vec2 result(*this);
result.scale(s);
return result;
}
inline Vec2& Vec2::operator*=(float s)
{
scale(s);
return *this;
}
inline Vec2 Vec2::operator/(const float s) const
{
return Vec2(this->x / s, this->y / s);
}
inline bool Vec2::operator<(const Vec2& v) const
{
if (x == v.x)
{
return y < v.y;
}
return x < v.x;
}
inline bool Vec2::operator>(const Vec2& v) const
{
if (x == v.x)
{
return y > v.y;
}
return x > v.x;
}
inline bool Vec2::operator==(const Vec2& v) const
{
return x==v.x && y==v.y;
}
inline bool Vec2::operator!=(const Vec2& v) const
{
return x!=v.x || y!=v.y;
}
inline Vec2 operator*(float x, const Vec2& v)
{
Vec2 result(v);
result.scale(x);
return result;
}
void Vec2::set_point(float xx, float yy)
{
this->x = xx;
this->y = yy;
}
}

View File

@ -0,0 +1,193 @@
//
// vec3.cpp
// OLARender
//
// Created by Wang,Renzhu on 2018/11/20.
// Copyright © 2018年 Wang,Renzhu. All rights reserved.
//
#if defined(__APPLE__)
#include "vec3.hpp"
#include "math_utils.hpp"
#else
#include "vec3.hpp"
#include "math_utils.hpp"
#endif
namespace OLARender {
Vec3::Vec3() : x(0.0f), y(0.0f), z(0.0f) {
}
Vec3::Vec3(float xx, float yy, float zz) : x(xx), y(yy), z(zz) {
}
Vec3::Vec3(const float* array) {
set(array);
}
Vec3::Vec3(const Vec3& p1, const Vec3& p2) {
set(p1, p2);
}
Vec3::Vec3(const Vec3& copy) {
set(copy);
}
Vec3 Vec3::from_color(unsigned int color) {
float components[3];
int componentIndex = 0;
for (int i = 2; i >= 0; --i)
{
int component = (color >> i*8) & 0x0000ff;
components[componentIndex++] = static_cast<float>(component) / 255.0f;
}
Vec3 value(components);
return value;
}
float Vec3::angle(const Vec3& v1, const Vec3& v2) {
float dx = v1.y * v2.z - v1.z * v2.y;
float dy = v1.z * v2.x - v1.x * v2.z;
float dz = v1.x * v2.y - v1.y * v2.x;
return std::atan2(std::sqrt(dx * dx + dy * dy + dz * dz) + MATH_FLOAT_SMALL, dot(v1, v2));
}
void Vec3::add(const Vec3& v1, const Vec3& v2, Vec3* dst) {
if (dst) {
dst->x = v1.x + v2.x;
dst->y = v1.y + v2.y;
dst->z = v1.z + v2.z;
}
}
void Vec3::clamp(const Vec3& min, const Vec3& max) {
// Clamp the x value.
if (x < min.x)
x = min.x;
if (x > max.x)
x = max.x;
// Clamp the y value.
if (y < min.y)
y = min.y;
if (y > max.y)
y = max.y;
// Clamp the z value.
if (z < min.z)
z = min.z;
if (z > max.z)
z = max.z;
}
void Vec3::clamp(const Vec3& v, const Vec3& min, const Vec3& max, Vec3* dst) {
if (dst) {
// Clamp the x value.
dst->x = v.x;
if (dst->x < min.x)
dst->x = min.x;
if (dst->x > max.x)
dst->x = max.x;
// Clamp the y value.
dst->y = v.y;
if (dst->y < min.y)
dst->y = min.y;
if (dst->y > max.y)
dst->y = max.y;
// Clamp the z value.
dst->z = v.z;
if (dst->z < min.z)
dst->z = min.z;
if (dst->z > max.z)
dst->z = max.z;
}
}
void Vec3::cross(const Vec3& v) {
cross(*this, v, this);
}
void Vec3::cross(const Vec3& v1, const Vec3& v2, Vec3* dst) {
if (dst) {
// NOTE: This code assumes Vec3 struct members are contiguous floats in memory.
// We might want to revisit this (and other areas of code that make this assumption)
// later to guarantee 100% safety/compatibility.
MathUtils::cross_vec3(&v1.x, &v2.x, &dst->x);
}
}
float Vec3::distance(const Vec3& v) const {
float dx = v.x - x;
float dy = v.y - y;
float dz = v.z - z;
return std::sqrt(dx * dx + dy * dy + dz * dz);
}
float Vec3::distance_squared(const Vec3& v) const {
float dx = v.x - x;
float dy = v.y - y;
float dz = v.z - z;
return (dx * dx + dy * dy + dz * dz);
}
float Vec3::dot(const Vec3& v) const {
return (x * v.x + y * v.y + z * v.z);
}
float Vec3::dot(const Vec3& v1, const Vec3& v2) {
return (v1.x * v2.x + v1.y * v2.y + v1.z * v2.z);
}
void Vec3::normalize() {
float n = x * x + y * y + z * z;
// Already normalized.
if (n == 1.0f)
return;
n = std::sqrt(n);
// Too close to zero.
if (n < MATH_TOLERANCE)
return;
n = 1.0f / n;
x *= n;
y *= n;
z *= n;
}
Vec3 Vec3::get_normalized() const {
Vec3 v(*this);
v.normalize();
return v;
}
void Vec3::subtract(const Vec3& v1, const Vec3& v2, Vec3* dst) {
if (dst) {
dst->x = v1.x - v2.x;
dst->y = v1.y - v2.y;
dst->z = v1.z - v2.z;
}
}
void Vec3::smooth(const Vec3& target, float elapsedTime, float responseTime) {
if (elapsedTime > 0)
{
*this += (target - *this) * (elapsedTime / (elapsedTime + responseTime));
}
}
const Vec3 Vec3::ZERO(0.0f, 0.0f, 0.0f);
const Vec3 Vec3::ONE(1.0f, 1.0f, 1.0f);
const Vec3 Vec3::UNIT_X(1.0f, 0.0f, 0.0f);
const Vec3 Vec3::UNIT_Y(0.0f, 1.0f, 0.0f);
const Vec3 Vec3::UNIT_Z(0.0f, 0.0f, 1.0f);
}

View File

@ -0,0 +1,454 @@
//
// vec3.h
// OLARender
//
// Created by Wang,Renzhu on 2018/11/20.
// Copyright © 2018年 Wang,Renzhu. All rights reserved.
//
#ifndef VEC3_H
#define VEC3_H
namespace OLARender {
class Vec3
{
public:
float x;
float y;
float z;
/**
* Constructs a new vector initialized to all zeros.
*/
Vec3();
/**
* Constructs a new vector initialized to the specified values.
*
* @param xx The x coordinate.
* @param yy The y coordinate.
* @param zz The z coordinate.
*/
Vec3(float xx, float yy, float zz);
/**
* Constructs a new vector from the values in the specified array.
*
* @param array An array containing the elements of the vector in the order x, y, z.
*/
Vec3(const float* array);
/**
* Constructs a vector that describes the direction between the specified points.
*
* @param p1 The first point.
* @param p2 The second point.
*/
Vec3(const Vec3& p1, const Vec3& p2);
/**
* Constructs a new vector that is a copy of the specified vector.
*
* @param copy The vector to copy.
*/
Vec3(const Vec3& copy);
/**
* Creates a new vector from an integer interpreted as an RGB value.
* E.g. 0xff0000 represents red or the vector (1, 0, 0).
*
* @param color The integer to interpret as an RGB value.
*
* @return A vector corresponding to the interpreted RGB color.
*/
static Vec3 from_color(unsigned int color);
/**
* Indicates whether this vector contains all zeros.
*
* @return true if this vector contains all zeros, false otherwise.
*/
inline bool is_zero() const;
/**
* Indicates whether this vector contains all ones.
*
* @return true if this vector contains all ones, false otherwise.
*/
inline bool is_one() const;
/**
* Returns the angle (in radians) between the specified vectors.
*
* @param v1 The first vector.
* @param v2 The second vector.
*
* @return The angle between the two vectors (in radians).
*/
static float angle(const Vec3& v1, const Vec3& v2);
/**
* Adds the elements of the specified vector to this one.
*
* @param v The vector to add.
*/
inline void add(const Vec3& v);
/**
* Adds the elements of this vector to the specified values.
*
* @param xx The add x coordinate.
* @param yy The add y coordinate.
* @param zz The add z coordinate.
*/
inline void add(float xx, float yy, float zz);
/**
* Adds the specified vectors and stores the result in dst.
*
* @param v1 The first vector.
* @param v2 The second vector.
* @param dst A vector to store the result in.
*/
static void add(const Vec3& v1, const Vec3& v2, Vec3* dst);
/**
* Clamps this vector within the specified range.
*
* @param min The minimum value.
* @param max The maximum value.
*/
void clamp(const Vec3& min, const Vec3& max);
/**
* Clamps the specified vector within the specified range and returns it in dst.
*
* @param v The vector to clamp.
* @param min The minimum value.
* @param max The maximum value.
* @param dst A vector to store the result in.
*/
static void clamp(const Vec3& v, const Vec3& min, const Vec3& max, Vec3* dst);
/**
* Sets this vector to the cross product between itself and the specified vector.
*
* @param v The vector to compute the cross product with.
*/
void cross(const Vec3& v);
/**
* Computes the cross product of the specified vectors and stores the result in dst.
*
* @param v1 The first vector.
* @param v2 The second vector.
* @param dst A vector to store the result in.
*/
static void cross(const Vec3& v1, const Vec3& v2, Vec3* dst);
/**
* Returns the distance between this vector and v.
*
* @param v The other vector.
*
* @return The distance between this vector and v.
*
* @see distanceSquared
*/
float distance(const Vec3& v) const;
/**
* Returns the squared distance between this vector and v.
*
* When it is not necessary to get the exact distance between
* two vectors (for example, when simply comparing the
* distance between different vectors), it is advised to use
* this method instead of distance.
*
* @param v The other vector.
*
* @return The squared distance between this vector and v.
*
* @see distance
*/
float distance_squared(const Vec3& v) const;
/**
* Returns the dot product of this vector and the specified vector.
*
* @param v The vector to compute the dot product with.
*
* @return The dot product.
*/
float dot(const Vec3& v) const;
/**
* Returns the dot product between the specified vectors.
*
* @param v1 The first vector.
* @param v2 The second vector.
*
* @return The dot product between the vectors.
*/
static float dot(const Vec3& v1, const Vec3& v2);
/**
* Computes the length of this vector.
*
* @return The length of the vector.
*
* @see lengthSquared
*/
inline float length() const;
/**
* Returns the squared length of this vector.
*
* When it is not necessary to get the exact length of a
* vector (for example, when simply comparing the lengths of
* different vectors), it is advised to use this method
* instead of length.
*
* @return The squared length of the vector.
*
* @see length
*/
inline float length_squared() const;
/**
* Negates this vector.
*/
inline void negate();
/**
* Normalizes this vector.
*
* This method normalizes this Vec3 so that it is of
* unit length (in other words, the length of the vector
* after calling this method will be 1.0f). If the vector
* already has unit length or if the length of the vector
* is zero, this method does nothing.
*/
void normalize();
/**
* Get the normalized vector.
*/
Vec3 get_normalized() const;
/**
* Scales all elements of this vector by the specified value.
*
* @param scalar The scalar value.
*/
inline void scale(float scalar);
/**
* Sets the elements of this vector to the specified values.
*
* @param xx The new x coordinate.
* @param yy The new y coordinate.
* @param zz The new z coordinate.
*/
inline void set(float xx, float yy, float zz);
/**
* Sets the elements of this vector from the values in the specified array.
*
* @param array An array containing the elements of the vector in the order x, y, z.
*/
inline void set(const float* array);
/**
* Sets the elements of this vector to those in the specified vector.
*
* @param v The vector to copy.
*/
inline void set(const Vec3& v);
/**
* Sets this vector to the directional vector between the specified points.
*/
inline void set(const Vec3& p1, const Vec3& p2);
/**
* Sets the elements of this vector to zero.
*/
inline void set_zero();
/**
* Subtracts this vector and the specified vector as (this - v)
* and stores the result in this vector.
*
* @param v The vector to subtract.
*/
inline void subtract(const Vec3& v);
/**
* Subtracts the specified vectors and stores the result in dst.
* The resulting vector is computed as (v1 - v2).
*
* @param v1 The first vector.
* @param v2 The second vector.
* @param dst The destination vector.
*/
static void subtract(const Vec3& v1, const Vec3& v2, Vec3* dst);
/**
* Updates this vector towards the given target using a smoothing function.
* The given response time determines the amount of smoothing (lag). A longer
* response time yields a smoother result and more lag. To force this vector to
* follow the target closely, provide a response time that is very small relative
* to the given elapsed time.
*
* @param target target value.
* @param elapsedTime elapsed time between calls.
* @param responseTime response time (in the same units as elapsedTime).
*/
void smooth(const Vec3& target, float elapsedTime, float responseTime);
/**
* Linear interpolation between two vectors A and B by alpha which
* is in the range [0,1]
*/
inline Vec3 lerp(const Vec3& target, float alpha) const;
/**
* Calculates the sum of this vector with the given vector.
*
* Note: this does not modify this vector.
*
* @param v The vector to add.
* @return The vector sum.
*/
inline Vec3 operator+(const Vec3& v) const;
/**
* Adds the given vector to this vector.
*
* @param v The vector to add.
* @return This vector, after the addition occurs.
*/
inline Vec3& operator+=(const Vec3& v);
/**
* Calculates the difference of this vector with the given vector.
*
* Note: this does not modify this vector.
*
* @param v The vector to subtract.
* @return The vector difference.
*/
inline Vec3 operator-(const Vec3& v) const;
/**
* Subtracts the given vector from this vector.
*
* @param v The vector to subtract.
* @return This vector, after the subtraction occurs.
*/
inline Vec3& operator-=(const Vec3& v);
/**
* Calculates the negation of this vector.
*
* Note: this does not modify this vector.
*
* @return The negation of this vector.
*/
inline Vec3 operator-() const;
/**
* Calculates the scalar product of this vector with the given value.
*
* Note: this does not modify this vector.
*
* @param s The value to scale by.
* @return The scaled vector.
*/
inline Vec3 operator*(float s) const;
/**
* Scales this vector by the given value.
*
* @param s The value to scale by.
* @return This vector, after the scale occurs.
*/
inline Vec3& operator*=(float s);
/**
* Returns the components of this vector divided by the given constant
*
* Note: this does not modify this vector.
*
* @param s the constant to divide this vector with
* @return a smaller vector
*/
inline Vec3 operator/(float s) const;
/** Returns true if the vector's scalar components are all greater
that the ones of the vector it is compared against.
*/
inline bool operator < (const Vec3& rhs) const
{
if (x < rhs.x && y < rhs.y && z < rhs.z)
return true;
return false;
}
/** Returns true if the vector's scalar components are all smaller
that the ones of the vector it is compared against.
*/
inline bool operator >(const Vec3& rhs) const
{
if (x > rhs.x && y > rhs.y && z > rhs.z)
return true;
return false;
}
/**
* Determines if this vector is equal to the given vector.
*
* @param v The vector to compare against.
*
* @return True if this vector is equal to the given vector, false otherwise.
*/
inline bool operator==(const Vec3& v) const;
/**
* Determines if this vector is not equal to the given vector.
*
* @param v The vector to compare against.
*
* @return True if this vector is not equal to the given vector, false otherwise.
*/
inline bool operator!=(const Vec3& v) const;
/** equals to Vec3(0,0,0) */
static const Vec3 ZERO;
/** equals to Vec3(1,1,1) */
static const Vec3 ONE;
/** equals to Vec3(1,0,0) */
static const Vec3 UNIT_X;
/** equals to Vec3(0,1,0) */
static const Vec3 UNIT_Y;
/** equals to Vec3(0,0,1) */
static const Vec3 UNIT_Z;
};
/**
* Calculates the scalar product of the given vector with the given value.
*
* @param x The value to scale by.
* @param v The vector to scale.
* @return The scaled vector.
*/
inline Vec3 operator*(float x, const Vec3& v);
}
#include "vec3.inl"
#endif /* VEC3_H */

View File

@ -0,0 +1,177 @@
//
// vec3.inl
// BdiEngine
//
// Created by Wang,Renzhu on 2018/11/20.
// Copyright © 2018年 Wang,Renzhu. All rights reserved.
//
#include "vec3.hpp"
#include <cmath>
namespace OLARender {
inline bool Vec3::is_zero() const
{
return x == 0.0f && y == 0.0f && z == 0.0f;
}
inline bool Vec3::is_one() const
{
return x == 1.0f && y == 1.0f && z == 1.0f;
}
inline void Vec3::add(const Vec3& v)
{
x += v.x;
y += v.y;
z += v.z;
}
inline void Vec3::add(float xx, float yy, float zz)
{
x += xx;
y += yy;
z += zz;
}
inline float Vec3::length() const
{
return std::sqrt(x * x + y * y + z * z);
}
inline float Vec3::length_squared() const
{
return (x * x + y * y + z * z);
}
inline void Vec3::negate()
{
x = -x;
y = -y;
z = -z;
}
inline void Vec3::scale(float scalar)
{
x *= scalar;
y *= scalar;
z *= scalar;
}
inline Vec3 Vec3::lerp(const Vec3 &target, float alpha) const
{
return *this * (1.f - alpha) + target * alpha;
}
inline void Vec3::set(float xx, float yy, float zz)
{
this->x = xx;
this->y = yy;
this->z = zz;
}
inline void Vec3::set(const float* array)
{
if (array) {
x = array[0];
y = array[1];
z = array[2];
}
}
inline void Vec3::set(const Vec3& v)
{
this->x = v.x;
this->y = v.y;
this->z = v.z;
}
inline void Vec3::set(const Vec3& p1, const Vec3& p2)
{
x = p2.x - p1.x;
y = p2.y - p1.y;
z = p2.z - p1.z;
}
inline void Vec3::set_zero()
{
x = y = z = 0.0f;
}
inline void Vec3::subtract(const Vec3& v)
{
x -= v.x;
y -= v.y;
z -= v.z;
}
inline Vec3 Vec3::operator+(const Vec3& v) const
{
Vec3 result(*this);
result.add(v);
return result;
}
inline Vec3& Vec3::operator+=(const Vec3& v)
{
add(v);
return *this;
}
inline Vec3 Vec3::operator-(const Vec3& v) const
{
Vec3 result(*this);
result.subtract(v);
return result;
}
inline Vec3& Vec3::operator-=(const Vec3& v)
{
subtract(v);
return *this;
}
inline Vec3 Vec3::operator-() const
{
Vec3 result(*this);
result.negate();
return result;
}
inline Vec3 Vec3::operator*(float s) const
{
Vec3 result(*this);
result.scale(s);
return result;
}
inline Vec3& Vec3::operator*=(float s)
{
scale(s);
return *this;
}
inline Vec3 Vec3::operator/(const float s) const
{
return Vec3(this->x / s, this->y / s, this->z / s);
}
inline bool Vec3::operator==(const Vec3& v) const
{
return x==v.x && y==v.y && z==v.z;
}
inline bool Vec3::operator!=(const Vec3& v) const
{
return x!=v.x || y!=v.y || z!=v.z;
}
inline Vec3 operator*(float x, const Vec3& v)
{
Vec3 result(v);
result.scale(x);
return result;
}
}

View File

@ -0,0 +1,299 @@
//
// vec4.cpp
// OLARender
//
// Created by Wang,Renzhu on 2018/11/20.
// Copyright © 2018年 Wang,Renzhu. All rights reserved.
//
#if defined(__APPLE__)
#include "vec4.hpp"
#include "math_utils.hpp"
#else
#include "vec4.hpp"
#include "math_utils.hpp"
#endif
#include <cmath>
namespace OLARender {
Vec4::Vec4() : x(0.0f), y(0.0f), z(0.0f), w(0.0f)
{
}
Vec4::Vec4(float xx, float yy, float zz, float ww) : x(xx), y(yy), z(zz), w(ww)
{
}
Vec4::Vec4(const float* src)
{
set(src);
}
Vec4::Vec4(const Vec4& p1, const Vec4& p2)
{
set(p1, p2);
}
Vec4::Vec4(const Vec4& copy)
{
set(copy);
}
Vec4 Vec4::from_color(unsigned int color)
{
float components[4];
int componentIndex = 0;
for (int i = 3; i >= 0; --i)
{
int component = (color >> i*8) & 0x000000ff;
components[componentIndex++] = static_cast<float>(component) / 255.0f;
}
Vec4 value(components);
return value;
}
bool Vec4::is_zero() const
{
return x == 0.0f && y == 0.0f && z == 0.0f && w == 0.0f;
}
bool Vec4::is_one() const
{
return x == 1.0f && y == 1.0f && z == 1.0f && w == 1.0f;
}
float Vec4::angle(const Vec4& v1, const Vec4& v2)
{
float dx = v1.w * v2.x - v1.x * v2.w - v1.y * v2.z + v1.z * v2.y;
float dy = v1.w * v2.y - v1.y * v2.w - v1.z * v2.x + v1.x * v2.z;
float dz = v1.w * v2.z - v1.z * v2.w - v1.x * v2.y + v1.y * v2.x;
return std::atan2(std::sqrt(dx * dx + dy * dy + dz * dz) + MATH_FLOAT_SMALL, dot(v1, v2));
}
void Vec4::add(const Vec4& v)
{
x += v.x;
y += v.y;
z += v.z;
w += v.w;
}
void Vec4::add(const Vec4& v1, const Vec4& v2, Vec4* dst)
{
if (dst) {
dst->x = v1.x + v2.x;
dst->y = v1.y + v2.y;
dst->z = v1.z + v2.z;
dst->w = v1.w + v2.w;
}
}
void Vec4::clamp(const Vec4& min, const Vec4& max)
{
// Clamp the x value.
if (x < min.x)
x = min.x;
if (x > max.x)
x = max.x;
// Clamp the y value.
if (y < min.y)
y = min.y;
if (y > max.y)
y = max.y;
// Clamp the z value.
if (z < min.z)
z = min.z;
if (z > max.z)
z = max.z;
// Clamp the z value.
if (w < min.w)
w = min.w;
if (w > max.w)
w = max.w;
}
void Vec4::clamp(const Vec4& v, const Vec4& min, const Vec4& max, Vec4* dst)
{
if (dst) {
// Clamp the x value.
dst->x = v.x;
if (dst->x < min.x)
dst->x = min.x;
if (dst->x > max.x)
dst->x = max.x;
// Clamp the y value.
dst->y = v.y;
if (dst->y < min.y)
dst->y = min.y;
if (dst->y > max.y)
dst->y = max.y;
// Clamp the z value.
dst->z = v.z;
if (dst->z < min.z)
dst->z = min.z;
if (dst->z > max.z)
dst->z = max.z;
// Clamp the w value.
dst->w = v.w;
if (dst->w < min.w)
dst->w = min.w;
if (dst->w > max.w)
dst->w = max.w;
}
}
float Vec4::distance(const Vec4& v) const
{
float dx = v.x - x;
float dy = v.y - y;
float dz = v.z - z;
float dw = v.w - w;
return std::sqrt(dx * dx + dy * dy + dz * dz + dw * dw);
}
float Vec4::distance_squared(const Vec4& v) const
{
float dx = v.x - x;
float dy = v.y - y;
float dz = v.z - z;
float dw = v.w - w;
return (dx * dx + dy * dy + dz * dz + dw * dw);
}
float Vec4::dot(const Vec4& v) const
{
return (x * v.x + y * v.y + z * v.z + w * v.w);
}
float Vec4::dot(const Vec4& v1, const Vec4& v2)
{
return (v1.x * v2.x + v1.y * v2.y + v1.z * v2.z + v1.w * v2.w);
}
float Vec4::length() const
{
return std::sqrt(x * x + y * y + z * z + w * w);
}
float Vec4::length_squared() const
{
return (x * x + y * y + z * z + w * w);
}
void Vec4::negate()
{
x = -x;
y = -y;
z = -z;
w = -w;
}
void Vec4::normalize()
{
float n = x * x + y * y + z * z + w * w;
// Already normalized.
if (n == 1.0f)
return;
n = std::sqrt(n);
// Too close to zero.
if (n < MATH_TOLERANCE)
return;
n = 1.0f / n;
x *= n;
y *= n;
z *= n;
w *= n;
}
Vec4 Vec4::get_normalized() const
{
Vec4 v(*this);
v.normalize();
return v;
}
void Vec4::scale(float scalar)
{
x *= scalar;
y *= scalar;
z *= scalar;
w *= scalar;
}
void Vec4::set(float xx, float yy, float zz, float ww)
{
this->x = xx;
this->y = yy;
this->z = zz;
this->w = ww;
}
void Vec4::set(const float* array)
{
if (array) {
x = array[0];
y = array[1];
z = array[2];
w = array[3];
}
}
void Vec4::set(const Vec4& v)
{
this->x = v.x;
this->y = v.y;
this->z = v.z;
this->w = v.w;
}
void Vec4::set(const Vec4& p1, const Vec4& p2)
{
x = p2.x - p1.x;
y = p2.y - p1.y;
z = p2.z - p1.z;
w = p2.w - p1.w;
}
void Vec4::subtract(const Vec4& v)
{
x -= v.x;
y -= v.y;
z -= v.z;
w -= v.w;
}
void Vec4::subtract(const Vec4& v1, const Vec4& v2, Vec4* dst)
{
if (dst) {
dst->x = v1.x - v2.x;
dst->y = v1.y - v2.y;
dst->z = v1.z - v2.z;
dst->w = v1.w - v2.w;
}
}
const Vec4 Vec4::ZERO = Vec4(0.0f, 0.0f, 0.0f, 0.0f);
const Vec4 Vec4::ONE = Vec4(1.0f, 1.0f, 1.0f, 1.0f);
const Vec4 Vec4::UNIT_X = Vec4(1.0f, 0.0f, 0.0f, 0.0f);
const Vec4 Vec4::UNIT_Y = Vec4(0.0f, 1.0f, 0.0f, 0.0f);
const Vec4 Vec4::UNIT_Z = Vec4(0.0f, 0.0f, 1.0f, 0.0f);
const Vec4 Vec4::UNIT_W = Vec4(0.0f, 0.0f, 0.0f, 1.0f);
}

View File

@ -0,0 +1,402 @@
//
// vec4.h
// OLARender
//
// Created by Wang,Renzhu on 2018/11/20.
// Copyright © 2018年 Wang,Renzhu. All rights reserved.
//
#ifndef VEC4_H
#define VEC4_H
namespace OLARender {
class Vec4
{
public:
float x;
float y;
float z;
float w;
/**
* Constructs a new vector initialized to all zeros.
*/
Vec4();
/**
* Constructs a new vector initialized to the specified values.
*
* @param xx The x coordinate.
* @param yy The y coordinate.
* @param zz The z coordinate.
* @param ww The w coordinate.
*/
Vec4(float xx, float yy, float zz, float ww);
/**
* Constructs a new vector from the values in the specified array.
*
* @param array An array containing the elements of the vector in the order x, y, z, w.
*/
Vec4(const float* array);
/**
* Constructs a vector that describes the direction between the specified points.
*
* @param p1 The first point.
* @param p2 The second point.
*/
Vec4(const Vec4& p1, const Vec4& p2);
/**
* Constructor.
*
* Creates a new vector that is a copy of the specified vector.
*
* @param copy The vector to copy.
*/
Vec4(const Vec4& copy);
/**
* Creates a new vector from an integer interpreted as an RGBA value.
* E.g. 0xff0000ff represents opaque red or the vector (1, 0, 0, 1).
*
* @param color The integer to interpret as an RGBA value.
*
* @return A vector corresponding to the interpreted RGBA color.
*/
static Vec4 from_color(unsigned int color);
/**
* Indicates whether this vector contains all zeros.
*
* @return true if this vector contains all zeros, false otherwise.
*/
bool is_zero() const;
/**
* Indicates whether this vector contains all ones.
*
* @return true if this vector contains all ones, false otherwise.
*/
bool is_one() const;
/**
* Returns the angle (in radians) between the specified vectors.
*
* @param v1 The first vector.
* @param v2 The second vector.
*
* @return The angle between the two vectors (in radians).
*/
static float angle(const Vec4& v1, const Vec4& v2);
/**
* Adds the elements of the specified vector to this one.
*
* @param v The vector to add.
*/
void add(const Vec4& v);
/**
* Adds the specified vectors and stores the result in dst.
*
* @param v1 The first vector.
* @param v2 The second vector.
* @param dst A vector to store the result in.
*/
static void add(const Vec4& v1, const Vec4& v2, Vec4* dst);
/**
* Clamps this vector within the specified range.
*
* @param min The minimum value.
* @param max The maximum value.
*/
void clamp(const Vec4& min, const Vec4& max);
/**
* Clamps the specified vector within the specified range and returns it in dst.
*
* @param v The vector to clamp.
* @param min The minimum value.
* @param max The maximum value.
* @param dst A vector to store the result in.
*/
static void clamp(const Vec4& v, const Vec4& min, const Vec4& max, Vec4* dst);
/**
* Returns the distance between this vector and v.
*
* @param v The other vector.
*
* @return The distance between this vector and v.
*
* @see distanceSquared
*/
float distance(const Vec4& v) const;
/**
* Returns the squared distance between this vector and v.
*
* When it is not necessary to get the exact distance between
* two vectors (for example, when simply comparing the
* distance between different vectors), it is advised to use
* this method instead of distance.
*
* @param v The other vector.
*
* @return The squared distance between this vector and v.
*
* @see distance
*/
float distance_squared(const Vec4& v) const;
/**
* Returns the dot product of this vector and the specified vector.
*
* @param v The vector to compute the dot product with.
*
* @return The dot product.
*/
float dot(const Vec4& v) const;
/**
* Returns the dot product between the specified vectors.
*
* @param v1 The first vector.
* @param v2 The second vector.
*
* @return The dot product between the vectors.
*/
static float dot(const Vec4& v1, const Vec4& v2);
/**
* Computes the length of this vector.
*
* @return The length of the vector.
*
* @see lengthSquared
*/
float length() const;
/**
* Returns the squared length of this vector.
*
* When it is not necessary to get the exact length of a
* vector (for example, when simply comparing the lengths of
* different vectors), it is advised to use this method
* instead of length.
*
* @return The squared length of the vector.
*
* @see length
*/
float length_squared() const;
/**
* Negates this vector.
*/
void negate();
/**
* Normalizes this vector.
*
* This method normalizes this Vec4 so that it is of
* unit length (in other words, the length of the vector
* after calling this method will be 1.0f). If the vector
* already has unit length or if the length of the vector
* is zero, this method does nothing.
*/
void normalize();
/**
* Get the normalized vector.
*/
Vec4 get_normalized() const;
/**
* Scales all elements of this vector by the specified value.
*
* @param scalar The scalar value.
*/
void scale(float scalar);
/**
* Sets the elements of this vector to the specified values.
*
* @param xx The new x coordinate.
* @param yy The new y coordinate.
* @param zz The new z coordinate.
* @param ww The new w coordinate.
*/
void set(float xx, float yy, float zz, float ww);
/**
* Sets the elements of this vector from the values in the specified array.
*
* @param array An array containing the elements of the vector in the order x, y, z, w.
*/
void set(const float* array);
/**
* Sets the elements of this vector to those in the specified vector.
*
* @param v The vector to copy.
*/
void set(const Vec4& v);
/**
* Sets this vector to the directional vector between the specified points.
*
* @param p1 The first point.
* @param p2 The second point.
*/
void set(const Vec4& p1, const Vec4& p2);
/**
* Subtracts this vector and the specified vector as (this - v)
* and stores the result in this vector.
*
* @param v The vector to subtract.
*/
void subtract(const Vec4& v);
/**
* Subtracts the specified vectors and stores the result in dst.
* The resulting vector is computed as (v1 - v2).
*
* @param v1 The first vector.
* @param v2 The second vector.
* @param dst The destination vector.
*/
static void subtract(const Vec4& v1, const Vec4& v2, Vec4* dst);
/**
* Calculates the sum of this vector with the given vector.
*
* Note: this does not modify this vector.
*
* @param v The vector to add.
* @return The vector sum.
*/
inline Vec4 operator+(const Vec4& v) const;
/**
* Adds the given vector to this vector.
*
* @param v The vector to add.
* @return This vector, after the addition occurs.
*/
inline Vec4& operator+=(const Vec4& v);
/**
* Calculates the sum of this vector with the given vector.
*
* Note: this does not modify this vector.
*
* @param v The vector to add.
* @return The vector sum.
*/
inline Vec4 operator-(const Vec4& v) const;
/**
* Subtracts the given vector from this vector.
*
* @param v The vector to subtract.
* @return This vector, after the subtraction occurs.
*/
inline Vec4& operator-=(const Vec4& v);
/**
* Calculates the negation of this vector.
*
* Note: this does not modify this vector.
*
* @return The negation of this vector.
*/
inline Vec4 operator-() const;
/**
* Calculates the scalar product of this vector with the given value.
*
* Note: this does not modify this vector.
*
* @param s The value to scale by.
* @return The scaled vector.
*/
inline Vec4 operator*(float s) const;
/**
* Scales this vector by the given value.
*
* @param s The value to scale by.
* @return This vector, after the scale occurs.
*/
inline Vec4& operator*=(float s);
/**
* Returns the components of this vector divided by the given constant
*
* Note: this does not modify this vector.
*
* @param s the constant to divide this vector with
* @return a smaller vector
*/
inline Vec4 operator/(float s) const;
/**
* Determines if this vector is less than the given vector.
*
* @param v The vector to compare against.
*
* @return True if this vector is less than the given vector, false otherwise.
*/
inline bool operator<(const Vec4& v) const;
/**
* Determines if this vector is equal to the given vector.
*
* @param v The vector to compare against.
*
* @return True if this vector is equal to the given vector, false otherwise.
*/
inline bool operator==(const Vec4& v) const;
/**
* Determines if this vector is not equal to the given vector.
*
* @param v The vector to compare against.
*
* @return True if this vector is not equal to the given vector, false otherwise.
*/
inline bool operator!=(const Vec4& v) const;
/** equals to Vec4(0,0,0,0) */
static const Vec4 ZERO;
/** equals to Vec4(1,1,1,1) */
static const Vec4 ONE;
/** equals to Vec4(1,0,0,0) */
static const Vec4 UNIT_X;
/** equals to Vec4(0,1,0,0) */
static const Vec4 UNIT_Y;
/** equals to Vec4(0,0,1,0) */
static const Vec4 UNIT_Z;
/** equals to Vec4(0,0,0,1) */
static const Vec4 UNIT_W;
};
/**
* Calculates the scalar product of the given vector with the given value.
*
* @param x The value to scale by.
* @param v The vector to scale.
* @return The scaled vector.
*/
inline Vec4 operator*(float x, const Vec4& v);
}
#include "vec4.inl"
#endif /* VEC4_H */

View File

@ -0,0 +1,97 @@
//
// vec4.inl
// BdiEngine
//
// Created by Wang,Renzhu on 2018/11/20.
// Copyright © 2018年 Wang,Renzhu. All rights reserved.
//
#include "vec4.hpp"
namespace OLARender {
inline Vec4 Vec4::operator+(const Vec4& v) const
{
Vec4 result(*this);
result.add(v);
return result;
}
inline Vec4& Vec4::operator+=(const Vec4& v)
{
add(v);
return *this;
}
inline Vec4 Vec4::operator-(const Vec4& v) const
{
Vec4 result(*this);
result.subtract(v);
return result;
}
inline Vec4& Vec4::operator-=(const Vec4& v)
{
subtract(v);
return *this;
}
inline Vec4 Vec4::operator-() const
{
Vec4 result(*this);
result.negate();
return result;
}
inline Vec4 Vec4::operator*(float s) const
{
Vec4 result(*this);
result.scale(s);
return result;
}
inline Vec4& Vec4::operator*=(float s)
{
scale(s);
return *this;
}
inline Vec4 Vec4::operator/(const float s) const
{
return Vec4(this->x / s, this->y / s, this->z / s, this->w / s);
}
inline bool Vec4::operator<(const Vec4& v) const
{
if (x == v.x) {
if (y == v.y) {
if (z == v.z) {
if (w < v.w) {
return w < v.w;
}
}
return z < v.z;
}
return y < v.y;
}
return x < v.x;
}
inline bool Vec4::operator==(const Vec4& v) const
{
return x == v.x && y == v.y && z == v.z && w == v.w;
}
inline bool Vec4::operator!=(const Vec4& v) const
{
return x != v.x || y != v.y || z != v.z || w != v.w;
}
inline Vec4 operator*(float x, const Vec4& v)
{
Vec4 result(v);
result.scale(x);
return result;
}
}

View File

@ -0,0 +1,38 @@
//
// Created by Felix Wang on 2022/7/12.
//
#ifndef ANDROID_SPIN_LOCK_H
#define ANDROID_SPIN_LOCK_H
class spin_lock {
private:
std::atomic_flag _atomic;
public:
spin_lock();
void lock();
void unlock();
bool try_lock();
};
spin_lock::spin_lock() : _atomic(ATOMIC_FLAG_INIT) {}
void spin_lock::lock() {
while (_atomic.test_and_set(std::memory_order_acquire));
}
void spin_lock::unlock() {
_atomic.clear(std::memory_order_release);
}
bool spin_lock::try_lock() {
return _atomic.test() ? false : (_atomic.test_and_set(std::memory_order_acquire));
}
#endif //ANDROID_SPIN_LOCK_H

View File

@ -0,0 +1,58 @@
//
// OlaRender.h
// OlaRender
//
// Created by 王韧竹 on 2022/6/17.
//
#include "util.h"
#if PLATFORM == PLATFORM_ANDROID
#include <android/log.h>
#endif
NS_OLA_BEGIN
std::string str_format(const char *fmt,...) {
std::string strResult="";
if (NULL != fmt)
{
va_list marker;
va_start(marker, fmt);
char *buf = 0;
int result = vasprintf (&buf, fmt, marker);
if (!buf)
{
va_end(marker);
return strResult;
}
if (result < 0)
{
free (buf);
va_end(marker);
return strResult;
}
result = (int)strlen (buf);
strResult.append(buf,result);
free(buf);
va_end(marker);
}
return strResult;
}
void Log(const std::string& tag, const std::string& format, ...)
{
char buffer[10240];
va_list args;
va_start(args, format);
vsprintf(buffer, format.c_str(), args);
va_end(args);
#if PLATFORM == PLATFORM_ANDROID
__android_log_print(ANDROID_LOG_INFO, tag.c_str(), "%s", buffer);
#endif
}
NS_OLA_END

View File

@ -0,0 +1,19 @@
#ifndef util_h
#define util_h
#include <stdlib.h>
#include <string>
#include "macros.h"
NS_OLA_BEGIN
std::string str_format(const char *fmt,...);
void Log(const std::string& tag, const std::string& format, ...);
#define rotationSwapsSize(rotation) ((rotation) == OLARender::RotateLeft || (rotation) == OLARender::RotateRight || (rotation) == OLARender::RotateRightFlipVertical || (rotation) == OLARender::RotateRightFlipHorizontal)
NS_OLA_END
#endif /* util_h */