diff --git a/mediapipe/modules/render_queue/BUILD b/mediapipe/modules/render_queue/BUILD new file mode 100644 index 000000000..4a4d09fe8 --- /dev/null +++ b/mediapipe/modules/render_queue/BUILD @@ -0,0 +1,33 @@ +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.hpp", + "OlaRenderIMP.hpp", + ], + # Use -Dverbose=-1 to turn off zlib's trace logging. (#3280) + 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": [], + }), +) + diff --git a/mediapipe/modules/render_queue/LockFreeQueue.h b/mediapipe/modules/render_queue/LockFreeQueue.h new file mode 100644 index 000000000..ef30eeba8 --- /dev/null +++ b/mediapipe/modules/render_queue/LockFreeQueue.h @@ -0,0 +1,122 @@ +// +// Created by Felix Wang on 2022/7/7. +// + + +#pragma once + +#include + +#ifdef ANDROID + +#include + +#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 +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(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(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 tail; + std::atomic head; + }; + +private: + size_t _capacityMask; + Node *_queue; + size_t _capacity; + std::atomic _tail; + std::atomic _head; +}; diff --git a/mediapipe/modules/render_queue/OlaRender.cpp b/mediapipe/modules/render_queue/OlaRender.cpp new file mode 100644 index 000000000..28fe0a254 --- /dev/null +++ b/mediapipe/modules/render_queue/OlaRender.cpp @@ -0,0 +1,39 @@ +// +// OlaRender.cpp +// OlaRender +// +// Created by 王韧竹 on 2022/6/17. +// + +#include "OlaRender.hpp" +#if USE_OLARENDER +#include +#include +#endif +#include "OlaRenderIMP.hpp" + + + +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 diff --git a/mediapipe/modules/render_queue/OlaRender.hpp b/mediapipe/modules/render_queue/OlaRender.hpp new file mode 100644 index 000000000..f3adb8fe9 --- /dev/null +++ b/mediapipe/modules/render_queue/OlaRender.hpp @@ -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 +#include "macros.h" + +#if USE_OLARENDER +#include +#if PLATFORM == PLATFORM_IOS +#include "OLARenderView.h" +#endif +#endif + +#if PLATFORM == PLATFORM_IOS + +#import +#import +#elif PLATFORM == PLATFORM_ANDROID + +#include +#include + +#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 */ diff --git a/mediapipe/modules/render_queue/OlaRenderIMP.cpp b/mediapipe/modules/render_queue/OlaRenderIMP.cpp new file mode 100644 index 000000000..e2a4d08d9 --- /dev/null +++ b/mediapipe/modules/render_queue/OlaRenderIMP.cpp @@ -0,0 +1,603 @@ +// +// OlaRenderIMP.cpp +// OlaRender +// +// Created by 王韧竹 on 2022/6/20. +// + + +#include "OlaRenderIMP.hpp" +#include "image_queue.h" + +#if USE_OLARENDER +#include +#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 diff --git a/mediapipe/modules/render_queue/OlaRenderIMP.hpp b/mediapipe/modules/render_queue/OlaRenderIMP.hpp new file mode 100644 index 000000000..56baedd24 --- /dev/null +++ b/mediapipe/modules/render_queue/OlaRenderIMP.hpp @@ -0,0 +1,122 @@ +// +// OlaRenderIMP.hpp +// OlaRender +// +// Created by 王韧竹 on 2022/6/20. +// + +#ifndef OlaRenderIMP_hpp +#define OlaRenderIMP_hpp + +#include +#include "macros.h" +#include "OlaRender.hpp" +#include + +#if USE_OLARENDER +#include +#include +#include +#include +#include + +#if PLATFORM == PLATFORM_IOS +#include + +#endif +#else +#if PLATFORM == PLATFORM_IOS +#import +#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 */ diff --git a/mediapipe/modules/render_queue/image.cpp b/mediapipe/modules/render_queue/image.cpp new file mode 100644 index 000000000..7515d5a53 --- /dev/null +++ b/mediapipe/modules/render_queue/image.cpp @@ -0,0 +1,41 @@ +#include "image.h" +#include "image_queue.h" +#include +#include + +#ifdef ANDROID + +#include + +//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 dispose() { + ImageQueue::getInstance()->dispose(); +} \ No newline at end of file diff --git a/mediapipe/modules/render_queue/image.h b/mediapipe/modules/render_queue/image.h new file mode 100644 index 000000000..1e373d751 --- /dev/null +++ b/mediapipe/modules/render_queue/image.h @@ -0,0 +1,22 @@ + +#ifndef IMAGE_H +#define IMAGE_H + +#include "image_queue.h" +#include "image_queue.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 dispose(); +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/mediapipe/modules/render_queue/image_queue.cpp b/mediapipe/modules/render_queue/image_queue.cpp new file mode 100644 index 000000000..2e9047a8b --- /dev/null +++ b/mediapipe/modules/render_queue/image_queue.cpp @@ -0,0 +1,96 @@ +// +// Created by Felix Wang on 2022/6/24. +// + +#include "image_queue.h" +#include +#include + +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(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; +} + diff --git a/mediapipe/modules/render_queue/image_queue.h b/mediapipe/modules/render_queue/image_queue.h new file mode 100644 index 000000000..45a32f612 --- /dev/null +++ b/mediapipe/modules/render_queue/image_queue.h @@ -0,0 +1,94 @@ +// +// Created by Felix Wang on 2022/6/24. +// + +#ifndef IMAGE_QUEUE_H +#define IMAGE_QUEUE_H + +#include +#if defined(__ANDROID__) || defined(ANDROID) +#include +#else +#import +#endif +#include +#include +#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 { +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 tp = + std::chrono::time_point_cast(std::chrono::system_clock::now()); + auto tmp = std::chrono::duration_cast(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 diff --git a/mediapipe/modules/render_queue/ios/BUILD b/mediapipe/modules/render_queue/ios/BUILD new file mode 100644 index 000000000..5c379b9bf --- /dev/null +++ b/mediapipe/modules/render_queue/ios/BUILD @@ -0,0 +1,41 @@ +load("@build_bazel_rules_apple//apple:ios.bzl", "ios_framework") + +objc_library( + name = "OlaRenderLibrary", + srcs = ["OlaRenderManager.mm"], + hdrs = ["OlaRenderManager.h"], + 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", + ], +) + + +ios_framework( + name = "OlaRenderFramework", + hdrs = ["OlaRenderManager.h"], + infoplists = ["Info.plist"], + bundle_id = "com.ola.dartrenderplugin", + families = ["iphone", "ipad"], + minimum_os_version = "11.0", + deps = [ + "//mediapipe/modules/render_queue/ios:OlaRenderLibrary", + ], +) diff --git a/mediapipe/modules/render_queue/ios/Info.plist b/mediapipe/modules/render_queue/ios/Info.plist new file mode 100644 index 000000000..8208eaf0f --- /dev/null +++ b/mediapipe/modules/render_queue/ios/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1.0 + + diff --git a/mediapipe/modules/render_queue/ios/OlaRenderManager.h b/mediapipe/modules/render_queue/ios/OlaRenderManager.h new file mode 100644 index 000000000..d81635349 --- /dev/null +++ b/mediapipe/modules/render_queue/ios/OlaRenderManager.h @@ -0,0 +1,27 @@ +// +// OlaRenderManager.h +// OlaRender +// +// Created by 王韧竹 on 2022/6/17. +// + +#import +#import + +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; + +@end + +NS_ASSUME_NONNULL_END diff --git a/mediapipe/modules/render_queue/ios/OlaRenderManager.mm b/mediapipe/modules/render_queue/ios/OlaRenderManager.mm new file mode 100644 index 000000000..b4d80234c --- /dev/null +++ b/mediapipe/modules/render_queue/ios/OlaRenderManager.mm @@ -0,0 +1,83 @@ +// +// 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" + +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; + } + +} + +- (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 diff --git a/mediapipe/modules/render_queue/macros.h b/mediapipe/modules/render_queue/macros.h new file mode 100755 index 000000000..102cdb1e9 --- /dev/null +++ b/mediapipe/modules/render_queue/macros.h @@ -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 +#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 */ diff --git a/mediapipe/modules/render_queue/math/BUILD b/mediapipe/modules/render_queue/math/BUILD new file mode 100644 index 000000000..c4e6125e9 --- /dev/null +++ b/mediapipe/modules/render_queue/math/BUILD @@ -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"], +) \ No newline at end of file diff --git a/mediapipe/modules/render_queue/math/mat4.cpp b/mediapipe/modules/render_queue/math/mat4.cpp new file mode 100644 index 000000000..d2d320559 --- /dev/null +++ b/mediapipe/modules/render_queue/math/mat4.cpp @@ -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 + +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 ); + +} diff --git a/mediapipe/modules/render_queue/math/mat4.hpp b/mediapipe/modules/render_queue/math/mat4.hpp new file mode 100644 index 000000000..c45fad219 --- /dev/null +++ b/mediapipe/modules/render_queue/math/mat4.hpp @@ -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 */ diff --git a/mediapipe/modules/render_queue/math/mat4.inl b/mediapipe/modules/render_queue/math/mat4.inl new file mode 100644 index 000000000..ea8fa5cbb --- /dev/null +++ b/mediapipe/modules/render_queue/math/mat4.inl @@ -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; + } + +} diff --git a/mediapipe/modules/render_queue/math/math_utils.cpp b/mediapipe/modules/render_queue/math/math_utils.cpp new file mode 100644 index 000000000..14b984354 --- /dev/null +++ b/mediapipe/modules/render_queue/math/math_utils.cpp @@ -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 + +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; + } + +} diff --git a/mediapipe/modules/render_queue/math/math_utils.hpp b/mediapipe/modules/render_queue/math/math_utils.hpp new file mode 100644 index 000000000..3d8c08098 --- /dev/null +++ b/mediapipe/modules/render_queue/math/math_utils.hpp @@ -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 + +#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 */ diff --git a/mediapipe/modules/render_queue/math/vec2.cpp b/mediapipe/modules/render_queue/math/vec2.cpp new file mode 100644 index 000000000..81c666aa6 --- /dev/null +++ b/mediapipe/modules/render_queue/math/vec2.cpp @@ -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); + +} diff --git a/mediapipe/modules/render_queue/math/vec2.hpp b/mediapipe/modules/render_queue/math/vec2.hpp new file mode 100644 index 000000000..79c6b795c --- /dev/null +++ b/mediapipe/modules/render_queue/math/vec2.hpp @@ -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 +#include + +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 */ diff --git a/mediapipe/modules/render_queue/math/vec2.inl b/mediapipe/modules/render_queue/math/vec2.inl new file mode 100644 index 000000000..e101a3c6c --- /dev/null +++ b/mediapipe/modules/render_queue/math/vec2.inl @@ -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; + } + +} diff --git a/mediapipe/modules/render_queue/math/vec3.cpp b/mediapipe/modules/render_queue/math/vec3.cpp new file mode 100644 index 000000000..1f905d784 --- /dev/null +++ b/mediapipe/modules/render_queue/math/vec3.cpp @@ -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(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); + +} diff --git a/mediapipe/modules/render_queue/math/vec3.hpp b/mediapipe/modules/render_queue/math/vec3.hpp new file mode 100644 index 000000000..4b659c954 --- /dev/null +++ b/mediapipe/modules/render_queue/math/vec3.hpp @@ -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 */ diff --git a/mediapipe/modules/render_queue/math/vec3.inl b/mediapipe/modules/render_queue/math/vec3.inl new file mode 100644 index 000000000..c00decc89 --- /dev/null +++ b/mediapipe/modules/render_queue/math/vec3.inl @@ -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 + +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; + } + +} diff --git a/mediapipe/modules/render_queue/math/vec4.cpp b/mediapipe/modules/render_queue/math/vec4.cpp new file mode 100644 index 000000000..330df4dff --- /dev/null +++ b/mediapipe/modules/render_queue/math/vec4.cpp @@ -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 + +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(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); + +} diff --git a/mediapipe/modules/render_queue/math/vec4.hpp b/mediapipe/modules/render_queue/math/vec4.hpp new file mode 100644 index 000000000..7c7723821 --- /dev/null +++ b/mediapipe/modules/render_queue/math/vec4.hpp @@ -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 */ diff --git a/mediapipe/modules/render_queue/math/vec4.inl b/mediapipe/modules/render_queue/math/vec4.inl new file mode 100644 index 000000000..7af8f3da1 --- /dev/null +++ b/mediapipe/modules/render_queue/math/vec4.inl @@ -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; + } + +} diff --git a/mediapipe/modules/render_queue/spin_lock.h b/mediapipe/modules/render_queue/spin_lock.h new file mode 100644 index 000000000..4617313b6 --- /dev/null +++ b/mediapipe/modules/render_queue/spin_lock.h @@ -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 diff --git a/mediapipe/modules/render_queue/util.cpp b/mediapipe/modules/render_queue/util.cpp new file mode 100755 index 000000000..6d8b9d9dc --- /dev/null +++ b/mediapipe/modules/render_queue/util.cpp @@ -0,0 +1,58 @@ +// +// OlaRender.h +// OlaRender +// +// Created by 王韧竹 on 2022/6/17. +// +#include "util.h" + +#if PLATFORM == PLATFORM_ANDROID +#include +#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 diff --git a/mediapipe/modules/render_queue/util.h b/mediapipe/modules/render_queue/util.h new file mode 100755 index 000000000..638401305 --- /dev/null +++ b/mediapipe/modules/render_queue/util.h @@ -0,0 +1,19 @@ + + +#ifndef util_h +#define util_h + +#include +#include +#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 */