Intelligent Assistant
Chat with our virtual assistant to get answers promptly.
This plugin can quickly calculate occlusions for 3D models. Based on the result, you can set not to draw the occluded models, improving the rendering performance. Good Culling is applicable to scenarios with complex occlusions, for example, scenarios with large amounts of vegetation and particle animations.
To calculate occlusion for 3D models, you only need to mark the models as occluders and occludees and then enter the vertex data and bounding box data of them.
- cmake_minimum_required(VERSION 3.4.1)
-
- set(CMAKE_CXX_STANDARD 17)
- set(CMAKE_CXX_STANDARD_REQUIRED ON)
-
- include_directories(src/main/cpp/include)
- link_directories(src/main/jniLibs/arm64-v8a)
-
- add_library(native-lib # Sets the name of the library.
- SHARED # Set the library as a shared library.
- src/main/cpp/goodculling-demo.cpp
- )
-
- find_library( # Sets the name of the path variable.
- log-lib
- log
- )
-
- # Specify the libraries CMake should link to your target library. You
- # can link multiple libraries, such as the libraries you have defined in the
- # build script, pre-built third-party libraries, or system libraries.
- target_link_libraries( # Specify the target library.
- native-lib
- android
- ${log-lib}
- # Link the target library to the log library.
- libc++_shared.so
- libCoreCulling.so
- )
Create the jniLibs directory in the project's root directory, place the libCoreCulling.so file in the jniLibs directory, and compile the goodculling-demo file.
- #include <stdlib.h>
- #include <iostream>
- #include <vector>
- #include <android/log.h>
- #include "include/goodculling.h"
-
- #define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "GoodCulling", __VA_ARGS__))
- #define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, "GoodCulling", __VA_ARGS__))
- #define LOGD(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, "GoodCulling", __VA_ARGS__))
- #define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, "GoodCulling", __VA_ARGS__))
-
- using MeshData = OccluderData;
-
- struct Vec3 {
- Vec3() {}
- Vec3(float x1, float y1, float z1) : x(x1), y(y1), z(z1) {}
- ~Vec3() {}
-
- float x = 0.0f;
- float y = 0.0f;
- float z = 0.0f;
- };
-
- struct Object {
- int id = 0;
- int meshId = 0;
- MeshData meshData;
- Vec3 minBox;
- Vec3 maxBox;
- bool updateTranFlag = true;
- std::vector<float> transformMatrix;
- Vec3 position;
- Vec3 rotation;
- Vec3 scale;
- };
-
- int goodcullingId = 0;
- // Prepare view matrix.
- std::vector<float> viewMatrix = { 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, -1.0f, -10.0f, 1.0f };
- // Prepare projection matrix.
- std::vector<float> projMatrix = { 0.3226795f, 0.0f, 0.0f, 0.0f,
- 0.0f, 1.732051f, 0.0f, 0.0f,
- 0.0f, 0.0f, -1.0006f, -1.0f,
- 0.0f, 0.0f, -0.60018f, 0.0f };
- const unsigned int VERTEX_DIMENSION_CNT = 3; // Each vertex contains three coordinates, for the X, Y, and Z axes respectively.
- std::vector<Object> senceObjArray;
-
- float* GetBoundingBox(Vec3 box)
- {
- std::vector<float> result = {box.x, box.y, box.z};
- return &result[0];
- }
-
- void CreateSence()
- {
- Object object_0;
- Object object_1;
- Object object_2;
- Object object_3;
-
- // Prepare mesh data.
- MeshData meshData;
- // Prepare vertex data.
- std::vector<float> vtxData = { 0.5f, -0.5f, 0.5f, -0.5f, -0.5f, 0.5f, 0.5f, 0.5f, 0.5f, -0.5f, 0.5f, 0.5f, 0.5f,
- 0.5f, -0.5f, -0.5f, 0.5f, -0.5f, 0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, 0.5f,
- 0.5f, 0.5f, -0.5f, 0.5f, 0.5f, 0.5f, 0.5f, -0.5f, -0.5f, 0.5f, -0.5f, 0.5f, -0.5f,
- -0.5f, 0.5f, -0.5f, 0.5f, -0.5f, -0.5f, 0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f,
- 0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f, -0.5f, -0.5f, -0.5f, -0.5f, 0.5f, -0.5f,
- -0.5f, 0.5f, 0.5f, -0.5f, 0.5f, 0.5f, 0.5f, 0.5f, -0.5f, 0.5f };
- meshData.vtxData = static_cast<void*>(vtxData.data());
- meshData.vtxStride = sizeof(float) * VERTEX_DIMENSION_CNT;
- meshData.vtxOffset = 0;
- meshData.vtxCount = static_cast<unsigned int>(vtxData.size()) / VERTEX_DIMENSION_CNT;
- // Prepare index data.
- std::vector<unsigned int> idxData = { 0, 2, 3, 0, 3, 1, 8, 4, 5, 8, 5, 9, 10, 6, 7, 10, 7, 11, 12, 13,
- 14, 12, 14, 15, 16, 17, 18, 16, 18, 19, 20, 21, 22, 20, 22, 23 };
- meshData.idxData = static_cast<void*>(idxData.data());
- meshData.type = UINT_TYPE;
- meshData.indCount = static_cast<unsigned int>(idxData.size());
- // Prepare bounding box data in the format of {minX, minY, minZ, maxX, maxY, maxZ}.
- std::vector<float> boundBox = { -0.5f, -0.5f, -0.5f, 0.5f, 0.5f, 0.5f };
- meshData.boundBox = static_cast<void*>(boundBox.data());
-
- // Create object_0.
- bool occluderUpdateTranFlag = true;
-
- std::vector<float> occluderTransformMatrix = { 2.5f, 0.0f, 0.0f, 0.0f,
- 0.0f, 2.5f, 0.0f, 0.0f,
- 0.0f, 0.0f, 2.5f, 0.0f,
- -4.0f, 0.0f, 7.0f, 1.0f };
- object_0.id = 0;
- object_0.meshId = 0;
- object_0.meshData = meshData;
-
- object_0.updateTranFlag = occluderUpdateTranFlag;
- object_0.transformMatrix = occluderTransformMatrix;
- object_0.position = Vec3( -4.0f, 0.0f, 7.0f );
- object_0.rotation = Vec3( 0.0f, 0.0f, 0.0f );
- object_0.scale = Vec3( 2.5f, 2.5f, 2.5f );
- senceObjArray.push_back(object_0);
-
- // Create object_1.
- Vec3 minBox_oc0(-0.5f, -0.5f, -0.5f);
- Vec3 maxBox_oc0(0.5f, 0.5f, 0.5f);
- bool TranFlag_oc0 = true;
- std::vector<float> TransformMatrix_oc0 = { 0.72589f, 0.0f, 0.0f, 0.0f,
- 0.0f, 10.2f, 0.0f, 0.0f,
- 0.0f, 0.0f, 0.46233f, 0.0f,
- -4.5f, 0.76f, 12.0f, 1.0f };
- object_1.id = 1;
- object_1.meshId = 1;
- object_1.meshData = meshData;
- object_1.minBox = minBox_oc0;
- object_1.maxBox = maxBox_oc0;
- object_1.updateTranFlag = TranFlag_oc0;
- object_1.transformMatrix = TransformMatrix_oc0;
- object_1.position = Vec3( -4.5f, 0.76f, 12.0f );
- object_1.rotation = Vec3( 0.0f, 0.0f, 0.0f );
- object_1.scale = Vec3( 0.72589f, 10.2f, 0.46233f );
- senceObjArray.push_back(object_1);
-
- // Create object_2.
- Vec3 minBox_oc1(-0.5f, -0.5f, -0.5f);
- Vec3 maxBox_oc1(0.5f, 0.5f, 0.5f);
- bool TranFlag_oc1 = true;
- std::vector<float> TransformMatrix_oc1 = { 0.7257298f, 0.0f, -0.01520186f, 0.0f,
- 0.0003874408f, 3.53327f, 0.01849625f, 0.0f,
- 0.009682182f, -0.002420745f, 0.4622231f, 0.0f,
- -0.5299997f, 0.0f, 4.079999f, 1.0f };
- object_2.id = 2;
- object_2.meshId = 2;
- object_2.meshData = meshData;
- object_2.minBox = minBox_oc1;
- object_2.maxBox = maxBox_oc1;
- object_2.updateTranFlag = TranFlag_oc1;
- object_2.transformMatrix = TransformMatrix_oc1;
- object_2.position = Vec3( -0.5299997f, 0.0f, 4.079999f );
- object_2.rotation = Vec3( 0.2999997f, 1.199999f, 0.0f );
- object_2.scale = Vec3( 0.725889f, 3.533318f, 0.4623308f );
- senceObjArray.push_back(object_2);
-
- // Create object_3.
- Vec3 minBox_oc2(-0.5f, -0.5f, -0.5f);
- Vec3 maxBox_oc2(0.5f, 0.5f, 0.5f);
- bool TranFlag_oc2 = true;
- std::vector<float> TransformMatrix_oc2 = { 0.5122236f, 0.0f, 0.0f, 0.0f,
- 0.0f, 1.428458f, 0.0f, 0.0f,
- 0.0f, 0.0f, 0.3524071f, 0.0f,
- -5.32f, -0.84f, 9.0f, 1.0f };
- object_3.id = 3;
- object_3.meshId = 3;
- object_3.meshData = meshData;
- object_3.minBox = minBox_oc2;
- object_3.maxBox = maxBox_oc2;
- object_3.updateTranFlag = TranFlag_oc2;
- object_3.transformMatrix = TransformMatrix_oc2;
- object_3.position = Vec3( -5.32f, -0.84f, 9.0f );
- object_3.rotation = Vec3( 0.0f, 0.0f, 0.0f );
- object_3.scale = Vec3( 0.5122236f, 1.428458f, 0.3524071f );
- senceObjArray.push_back(object_3);
- }
-
- int Init()
- {
- CreateSence();
- goodcullingId = CreateGoodCulling();
-
- AddOccluder(senceObjArray[0].meshId, senceObjArray[0].meshData);
- AddOccludee(senceObjArray[1].meshId, GetBoundingBox(senceObjArray[1].minBox),
- GetBoundingBox(senceObjArray[1].maxBox));
- AddOccludee(senceObjArray[2].meshId, GetBoundingBox(senceObjArray[2].minBox),
- GetBoundingBox(senceObjArray[2].maxBox));
- AddOccludee(senceObjArray[3].meshId, GetBoundingBox(senceObjArray[3].minBox),
- GetBoundingBox(senceObjArray[3].maxBox));
- }
- void Render()
- {
-
- CleanUp(goodcullingId);
-
- UpdateViewMatrix(goodcullingId, &viewMatrix[0]);
- UpdateProjectionMatrix(goodcullingId, &projMatrix[0]);
-
- UpdateOccluderInfo(goodcullingId, senceObjArray[0].id, senceObjArray[0].meshId, senceObjArray[0].updateTranFlag,
- &senceObjArray[0].transformMatrix[0]);
- UpdateOccludeeInfo(goodcullingId, senceObjArray[1].id, senceObjArray[1].meshId, senceObjArray[1].updateTranFlag,
- &senceObjArray[1].transformMatrix[0]);
- UpdateOccludeeInfo(goodcullingId, senceObjArray[2].id, senceObjArray[2].meshId, senceObjArray[2].updateTranFlag,
- &senceObjArray[2].transformMatrix[0]);
- UpdateOccludeeInfo(goodcullingId, senceObjArray[3].id, senceObjArray[3].meshId, senceObjArray[3].updateTranFlag,
- &senceObjArray[3].transformMatrix[0]);
-
- // Rasterization and culling.
- RasterizationAndCulling(goodcullingId);
- bool result = GetCullingResult(goodcullingId, senceObjArray[1].id);
- 1 LOGI("occludee object_1 is visible: %d \n", result); // 1: visible.
- result = GetCullingResult(goodcullingId, senceObjArray[2].id);
- LOGI("occludee object_2 is visible: %d \n", result); // 1: visible.
- result = GetCullingResult(goodcullingId, senceObjArray[3].id);
- LOGI("occludee object_3 is visible: %d \n", result); // 0: invisible.
- }
- void DeInit()
- {
- Disable(goodcullingId);
- RemoveAllOccluders();
- RemoveAllOccludees();
- DestroyGoodCulling(goodcullingId);
- }