no message

This commit is contained in:
gem
2025-02-18 15:21:31 +08:00
commit 2d133e56d7
1980 changed files with 465595 additions and 0 deletions

147
cocos/primitive/Box.cpp Normal file
View File

@@ -0,0 +1,147 @@
/****************************************************************************
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "primitive/Box.h"
#include "base/std/optional.h"
namespace cc {
namespace {
const ccstd::vector<ccstd::vector<uint32_t>> FACE_AXES{
{2, 3, 1}, // FRONT
{4, 5, 7}, // BACK
{7, 6, 2}, // TOP
{1, 0, 4}, // BOTTOM
{1, 4, 2}, // RIGHT
{5, 0, 6} // LEFT
};
const ccstd::vector<ccstd::vector<float>> FACE_NORMALS{
{0, 0, 1}, // FRONT
{0, 0, -1}, // BACK
{0, 1, 0}, // TOP
{0, -1, 0}, // BOTTOM
{1, 0, 0}, // RIGHT
{-1, 0, 0} // LEFT
};
const ccstd::vector<ccstd::vector<float>> FACE_TANGENTS{
{-1, 0, 0, 1}, // FRONT
{-1, 0, 0, 1}, // BACK
{-1, 0, 0, 1}, // TOP
{-1, 0, 0, 1}, // BOTTOM
{0, 0, -1, 1}, // RIGHT
{0, 0, 1, 1} // LEFT
};
} // namespace
IGeometry box(const ccstd::optional<IBoxOptions> &options) {
const uint32_t ws = options->widthSegments.has_value() ? options->widthSegments.value() : 1;
const uint32_t hs = options->heightSegments.has_value() ? options->heightSegments.value() : 1;
const uint32_t ls = options->lengthSegments.has_value() ? options->lengthSegments.value() : 1;
const float hw = options->width.has_value() ? options->width.value() / 2 : 1.0F / 2;
const float hh = options->height.has_value() ? options->height.value() / 2 : 1.0F / 2;
const float hl = options->length.has_value() ? options->length.value() / 2 : 1.0F / 2;
ccstd::vector<Vec3> corners{Vec3{-hw, -hh, hl}, Vec3{hw, -hh, hl}, Vec3{hw, hh, hl}, Vec3{-hw, hh, hl}, Vec3{hw, -hh, -hl}, Vec3{-hw, -hh, -hl}, Vec3{-hw, hh, -hl}, Vec3{hw, hh, -hl}};
ccstd::vector<float> positions;
ccstd::vector<float> normals;
ccstd::vector<float> uvs;
ccstd::vector<float> tangents;
ccstd::vector<uint32_t> indices;
const Vec3 minPos(-hw, -hh, -hl);
const Vec3 maxPos(hw, hh, hl);
float boundingRadius{static_cast<float>(sqrt(hw * hw + hh * hh + hl * hl))};
auto buildPlane = [&](uint32_t side, uint32_t uSegments, uint32_t vSegments) {
float u = 0;
float v = 0;
const auto offset = static_cast<uint32_t>(positions.size() / 3);
const ccstd::vector<uint32_t> faceAxe = FACE_AXES[side];
const ccstd::vector<float> faceNormal = FACE_NORMALS[side];
const ccstd::vector<float> faceTangent = FACE_TANGENTS[side];
for (index_t iy = 0; iy <= vSegments; ++iy) {
for (index_t ix = 0; ix <= uSegments; ++ix) {
u = static_cast<float>(ix) / static_cast<float>(uSegments);
v = static_cast<float>(iy) / static_cast<float>(vSegments);
Vec3 temp1 = corners[faceAxe[0]].lerp(corners[faceAxe[1]], u);
Vec3 temp2 = corners[faceAxe[0]].lerp(corners[faceAxe[2]], v);
temp2.subtract(corners[faceAxe[0]]);
temp1.add(temp2);
positions.emplace_back(temp1.x);
positions.emplace_back(temp1.y);
positions.emplace_back(temp1.z);
normals.emplace_back(faceNormal[0]);
normals.emplace_back(faceNormal[1]);
normals.emplace_back(faceNormal[2]);
uvs.emplace_back(u);
uvs.emplace_back(v);
tangents.emplace_back(faceTangent[0]);
tangents.emplace_back(faceTangent[1]);
tangents.emplace_back(faceTangent[2]);
tangents.emplace_back(faceTangent[3]);
if ((ix < uSegments) && (iy < vSegments)) {
auto uSeg1 = uSegments + 1;
const auto a = ix + iy * uSeg1;
const auto b = ix + (iy + 1) * uSeg1;
const auto c = (ix + 1) + (iy + 1) * uSeg1;
const auto d = (ix + 1) + iy * uSeg1;
indices.emplace_back(offset + a);
indices.emplace_back(offset + d);
indices.emplace_back(offset + b);
indices.emplace_back(offset + b);
indices.emplace_back(offset + d);
indices.emplace_back(offset + c);
}
}
}
};
buildPlane(0, ws, hs); // FRONT
buildPlane(4, ls, hs); // RIGHT
buildPlane(1, ws, hs); // BACK
buildPlane(5, ls, hs); // LEFT
buildPlane(3, ws, ls); // BOTTOM
buildPlane(2, ws, ls); // TOP
IGeometry info;
info.positions = positions;
info.normals = normals;
info.uvs = uvs;
info.tangents = tangents;
info.boundingRadius = boundingRadius;
info.minPos = minPos;
info.maxPos = maxPos;
info.indices = indices;
return info;
}
} // namespace cc

95
cocos/primitive/Box.h Normal file
View File

@@ -0,0 +1,95 @@
/****************************************************************************
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include "primitive/PrimitiveDefine.h"
namespace cc {
/**
* @en
* The definition of the parameter for building a box.
* @zh
* 立方体参数选项。
*/
struct IBoxOptions : public IGeometryOptions {
/**
* @en
* Box extent on X-axis.
* @zh
* 立方体宽度。
*/
ccstd::optional<float> width;
/**
* @en
* Box extent on Y-axis.
* @zh
* 立方体高度。
*/
ccstd::optional<float> height;
/**
* @en
* Box extent on Z-axis.
* @zh
* 立方体长度。
*/
ccstd::optional<float> length;
/**
* @en
* Segment count on X-axis.
* @zh
* 宽度线段数。
*/
ccstd::optional<uint32_t> widthSegments;
/**
* @en
* Segment count on Y-axis.
* @zh
* 高度线段数。
*/
ccstd::optional<uint32_t> heightSegments;
/**
* @en
* Segment count on Z-axis.
* @zh
* 长度线段数。
*/
ccstd::optional<uint32_t> lengthSegments;
};
/**
* @en
* This function generates a box with specified extents and centered at origin,
* but may be repositioned through the `center` option.
* @zh
* 生成一个立方体,其大小是定义的范围且中心在原点。
* @param options 参数选项。
*/
IGeometry box(const ccstd::optional<IBoxOptions> &options = ccstd::nullopt);
} // namespace cc

238
cocos/primitive/Capsule.cpp Normal file
View File

@@ -0,0 +1,238 @@
/****************************************************************************
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "primitive/Capsule.h"
namespace cc {
IGeometry capsule(float radiusTop, float radiusBottom, float height, const ccstd::optional<ICapsuleOptions> &opts) {
const float torsoHeight = height - radiusTop - radiusBottom;
const uint32_t sides = opts.has_value() ? opts->sides : 32;
const uint32_t heightSegments = opts.has_value() ? opts->heightSegments : 32;
const float bottomProp = radiusBottom / height;
const float torProp = torsoHeight / height;
const float topProp = radiusTop / height;
const uint32_t bottomSegments = floor(static_cast<float>(heightSegments) * bottomProp);
const uint32_t topSegments = floor(static_cast<float>(heightSegments) * topProp);
const uint32_t torSegments = floor(static_cast<float>(heightSegments) * torProp);
const float topOffset = torsoHeight + radiusBottom - height / 2;
const float torOffset = radiusBottom - height / 2;
const float bottomOffset = radiusBottom - height / 2;
const float arc = opts.has_value() ? opts->arc : math::PI_2;
// calculate vertex count
ccstd::vector<float> positions;
ccstd::vector<float> normals;
ccstd::vector<float> uvs;
ccstd::vector<uint32_t> indices;
const float maxRadius = std::max(radiusTop, radiusBottom);
const Vec3 minPos(-maxRadius, -height / 2, -maxRadius);
const Vec3 maxPos(maxRadius, height / 2, maxRadius);
const float boundingRadius = height / 2;
uint32_t index = 0;
ccstd::vector<ccstd::vector<uint32_t>> indexArray;
// =======================
// internal functions
// =======================
auto generateTorso = [&]() {
// this will be used to calculate the normal
float slope = (radiusTop - radiusBottom) / torsoHeight;
// generate positions, normals and uvs
for (uint32_t y = 0; y <= torSegments; y++) {
ccstd::vector<uint32_t> indexRow;
const float lat = static_cast<float>(y) / static_cast<float>(torSegments);
const float radius = lat * (radiusTop - radiusBottom) + radiusBottom;
for (uint32_t x = 0; x <= sides; ++x) {
const float u = static_cast<float>(x) / static_cast<float>(sides);
const float v = lat * torProp + bottomProp;
const float theta = u * arc - (arc / 4);
const float sinTheta = sin(theta);
const float cosTheta = cos(theta);
// vertex
positions.emplace_back(radius * sinTheta);
positions.emplace_back(lat * torsoHeight + torOffset);
positions.emplace_back(radius * cosTheta);
// normal
Vec3 temp1(sinTheta, -slope, cosTheta);
temp1.normalize();
normals.emplace_back(temp1.x);
normals.emplace_back(temp1.y);
normals.emplace_back(temp1.z);
// uv
uvs.emplace_back(u);
uvs.emplace_back(v);
// save index of vertex in respective row
indexRow.emplace_back(index);
// increase index
++index;
}
// now save positions of the row in our index array
indexArray.emplace_back(indexRow);
}
// generate indices
for (uint32_t y = 0; y < torSegments; ++y) {
for (uint32_t x = 0; x < sides; ++x) {
// we use the index array to access the correct indices
const uint32_t i1 = indexArray[y][x];
const uint32_t i2 = indexArray[y + 1][x];
const uint32_t i3 = indexArray[y + 1][x + 1];
const uint32_t i4 = indexArray[y][x + 1];
// face one
indices.emplace_back(i1);
indices.emplace_back(i4);
indices.emplace_back(i2);
// face two
indices.emplace_back(i4);
indices.emplace_back(i3);
indices.emplace_back(i2);
}
}
};
auto generateBottom = [&]() {
for (uint32_t lat = 0; lat <= bottomSegments; ++lat) {
float theta = static_cast<float>(lat) * math::PI / static_cast<float>(bottomSegments) / 2;
float sinTheta = sin(theta);
float cosTheta = -cos(theta);
for (uint32_t lon = 0; lon <= sides; ++lon) {
const float phi = static_cast<float>(lon) * math::PI_2 / static_cast<float>(sides) - math::PI / 2;
const float sinPhi = sin(phi);
const float cosPhi = cos(phi);
const float x = sinPhi * sinTheta;
const float y = cosTheta;
const float z = cosPhi * sinTheta;
const float u = static_cast<float>(lon) / static_cast<float>(sides);
const float v = static_cast<float>(lat) / static_cast<float>(heightSegments);
positions.emplace_back(x * radiusBottom);
positions.emplace_back(y * radiusBottom + bottomOffset);
positions.emplace_back(z * radiusBottom);
normals.emplace_back(x);
normals.emplace_back(y);
normals.emplace_back(z);
uvs.emplace_back(u);
uvs.emplace_back(v);
if ((lat < bottomSegments) && (lon < sides)) {
const uint32_t seg1 = sides + 1;
const uint32_t a = seg1 * lat + lon;
const uint32_t b = seg1 * (lat + 1) + lon;
const uint32_t c = seg1 * (lat + 1) + lon + 1;
const uint32_t d = seg1 * lat + lon + 1;
indices.emplace_back(a);
indices.emplace_back(d);
indices.emplace_back(b);
indices.emplace_back(d);
indices.emplace_back(c);
indices.emplace_back(b);
}
++index;
}
}
};
auto generateTop = [&]() {
for (uint32_t lat = 0; lat <= topSegments; ++lat) {
const float theta = static_cast<float>(lat) * math::PI / static_cast<float>(topSegments) / 2 + math::PI / 2;
const float sinTheta = sin(theta);
const float cosTheta = -cos(theta);
for (uint32_t lon = 0; lon <= sides; ++lon) {
const float phi = static_cast<float>(lon) * 2 * math::PI / static_cast<float>(sides) - math::PI / 2;
const float sinPhi = sin(phi);
const float cosPhi = cos(phi);
const float x = sinPhi * sinTheta;
const float y = cosTheta;
const float z = cosPhi * sinTheta;
const float u = static_cast<float>(lon) / static_cast<float>(sides);
const float v = static_cast<float>(lat) / static_cast<float>(heightSegments) + (1 - topProp);
positions.emplace_back(x * radiusTop);
positions.emplace_back(y * radiusTop + topOffset);
positions.emplace_back(z * radiusTop);
normals.emplace_back(x);
normals.emplace_back(y);
normals.emplace_back(z);
uvs.emplace_back(u);
uvs.emplace_back(v);
if ((lat < topSegments) && (lon < sides)) {
const uint32_t seg1 = sides + 1;
const uint32_t a = seg1 * lat + lon + indexArray[torSegments][sides] + 1;
const uint32_t b = seg1 * (lat + 1) + lon + indexArray[torSegments][sides] + 1;
const uint32_t c = seg1 * (lat + 1) + lon + 1 + indexArray[torSegments][sides] + 1;
const uint32_t d = seg1 * lat + lon + 1 + indexArray[torSegments][sides] + 1;
indices.emplace_back(a);
indices.emplace_back(d);
indices.emplace_back(b);
indices.emplace_back(d);
indices.emplace_back(c);
indices.emplace_back(b);
}
}
}
};
generateBottom();
generateTorso();
generateTop();
IGeometry info;
info.positions = positions;
info.normals = normals;
info.uvs = uvs;
info.boundingRadius = boundingRadius;
info.minPos = minPos;
info.maxPos = maxPos;
info.indices = indices;
return info;
}
} // namespace cc

53
cocos/primitive/Capsule.h Normal file
View File

@@ -0,0 +1,53 @@
/****************************************************************************
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include "primitive/PrimitiveDefine.h"
namespace cc {
/**
* @en
* The definition of the parameter for building a capsule.
* @zh
* 胶囊体参数选项。
*/
struct ICapsuleOptions {
uint32_t sides{32};
uint32_t heightSegments{32};
bool capped{true};
float arc{math::PI_2};
};
/**
* Generate a capsule with radiusTop radiusBottom 0.5, height 2, centered at origin,
* but may be repositioned through the `center` option.
* @zh
* 生成一个胶囊体。
* @param radiusTop 顶部半径。
* @param radiusBottom 底部半径。
* @param opts 胶囊体参数选项。
*/
IGeometry capsule(float radiusTop = 0.5, float radiusBottom = 0.5, float height = 2, const ccstd::optional<ICapsuleOptions> &opts = ccstd::nullopt);
} // namespace cc

View File

@@ -0,0 +1,64 @@
/****************************************************************************
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "primitive/Circle.h"
#include "gfx-base/GFXDef-common.h"
namespace cc {
IGeometry circle(ccstd::optional<ICircleOptions> &options) {
if (!options.has_value()) options = ICircleOptions();
const uint32_t segments = options->segments;
ccstd::vector<float> positions(3 * (segments + 1));
positions[0] = 0;
positions[1] = 0;
positions[2] = 0;
ccstd::vector<uint32_t> indices(1 + segments * 2);
indices[0] = 0;
const float step = math::PI * 2 / static_cast<float>(segments);
for (uint32_t iSegment = 0; iSegment < segments; ++iSegment) {
const float angle = step * static_cast<float>(iSegment);
const float x = cos(angle);
const float y = sin(angle);
const uint32_t p = (iSegment + 1) * 3;
positions[p + 0] = x;
positions[p + 1] = y;
positions[p + 2] = 0;
const uint32_t i = iSegment * 2;
indices[1 + (i)] = iSegment + 1;
indices[1 + (i + 1)] = iSegment + 2;
}
if (segments > 0) {
indices[indices.size() - 1] = 1;
}
IGeometry info;
info.positions = positions;
info.boundingRadius = 1;
info.minPos = Vec3(1, 1, 0);
info.maxPos = Vec3(-1, -1, 0);
info.indices = indices;
info.primitiveMode = gfx::PrimitiveMode::TRIANGLE_FAN;
return info;
}
} // namespace cc

51
cocos/primitive/Circle.h Normal file
View File

@@ -0,0 +1,51 @@
/****************************************************************************
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include "primitive/PrimitiveDefine.h"
namespace cc {
/**
* @en
* The definition of the parameter for building a circle.
* @zh
* 圆形参数选项。
*/
struct ICircleOptions : public IGeometryOptions {
// The segments. Default to 64.
uint32_t segments{64};
};
/**
* @en
* Generate a circle with radius 1, centered at origin,
* but may be repositioned through the `center` option.
* @zh
* 生成一个圆其半径是单位1中心点在原点。
* @param options 参数选项。
*/
IGeometry circle(ccstd::optional<ICircleOptions> &options);
} // namespace cc

33
cocos/primitive/Cone.cpp Normal file
View File

@@ -0,0 +1,33 @@
/****************************************************************************
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "primitive/Cone.h"
namespace cc {
IGeometry cone(float radius, float height, const ccstd::optional<IConeOptions> &opts) {
return cylinder(0, radius, height, opts);
}
} // namespace cc

41
cocos/primitive/Cone.h Normal file
View File

@@ -0,0 +1,41 @@
/****************************************************************************
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include "primitive/Cylinder.h"
#include "primitive/PrimitiveDefine.h"
namespace cc {
/**
* @en
* The definition of the parameter for building a cylinder.
* @zh
* 圆锥参数选项。
*/
using IConeOptions = ICylinderOptions;
IGeometry cone(float radius = 0.5F, float height = 1.0F, const ccstd::optional<IConeOptions> &opts = ccstd::nullopt);
} // namespace cc

View File

@@ -0,0 +1,265 @@
/****************************************************************************
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "primitive/Cylinder.h"
namespace cc {
float sign(float v) {
return (v < 0 ? -1.0F : (v > 0 ? 1.0F : 0.0F));
}
IGeometry cylinder(float radiusTop, float radiusBottom, float height, const ccstd::optional<ICylinderOptions> &opts) {
const float halfHeight = height * 0.5F;
const uint32_t radialSegments = opts.has_value() ? opts->radialSegments : 32;
const uint32_t heightSegments = opts.has_value() ? opts->heightSegments : 1;
const bool capped = opts.has_value() ? opts->capped : true;
const float arc = opts.has_value() ? opts->arc : math::PI_2;
uint32_t cntCap = 0;
if (capped) {
if (radiusTop > 0) {
++cntCap;
}
if (radiusBottom > 0) {
++cntCap;
}
}
// calculate vertex count
uint32_t vertCount = (radialSegments + 1) * (heightSegments + 1);
if (capped) {
vertCount += ((radialSegments + 1) * cntCap) + (radialSegments * cntCap);
}
// calculate index count
uint32_t indexCount = radialSegments * heightSegments * 2 * 3;
if (capped) {
indexCount += radialSegments * cntCap * 3;
}
ccstd::vector<uint32_t> indices(indexCount);
ccstd::vector<float> positions(vertCount * 3);
ccstd::vector<float> normals(vertCount * 3);
ccstd::vector<float> uvs(vertCount * 2);
const float maxRadius = std::max(radiusTop, radiusBottom);
const Vec3 minPos(-maxRadius, -halfHeight, -maxRadius);
const Vec3 maxPos(maxRadius, halfHeight, maxRadius);
const float boundingRadius = sqrt(maxRadius * maxRadius + halfHeight * halfHeight);
uint32_t index = 0;
uint32_t indexOffset = 0;
// =======================
// internal functions
// =======================
auto generateTorso = [&]() {
ccstd::vector<ccstd::vector<uint32_t>> indexArray;
// this will be used to calculate the normal
const float r = radiusTop - radiusBottom;
const float slope = r * r / height * sign(r);
// generate positions, normals and uvs
for (uint32_t y = 0; y <= heightSegments; y++) {
ccstd::vector<uint32_t> indexRow;
const float v = static_cast<float>(y) / static_cast<float>(heightSegments);
// calculate the radius of the current row
const float radius = v * r + radiusBottom;
for (uint32_t x = 0; x <= radialSegments; ++x) {
const float u = static_cast<float>(x) / static_cast<float>(radialSegments);
const float theta = u * arc;
const float sinTheta = sin(theta);
const float cosTheta = cos(theta);
// vertex
positions[3 * index] = radius * sinTheta;
positions[3 * index + 1] = v * height - halfHeight;
positions[3 * index + 2] = radius * cosTheta;
// normal
Vec3 temp1(sinTheta, -slope, cosTheta);
temp1.normalize();
normals[3 * index] = temp1.x;
normals[3 * index + 1] = temp1.y;
normals[3 * index + 2] = temp1.z;
// uv
uvs[2 * index] = fmod((1 - u) * 2.0F, 1.0F);
uvs[2 * index + 1] = v;
// save index of vertex in respective row
indexRow.emplace_back(index);
// increase index
++index;
}
// now save positions of the row in our index array
indexArray.emplace_back(indexRow);
}
// generate indices
for (uint32_t y = 0; y < heightSegments; ++y) {
for (uint32_t x = 0; x < radialSegments; ++x) {
// we use the index array to access the correct indices
const uint32_t i1 = indexArray[y][x];
const uint32_t i2 = indexArray[y + 1][x];
const uint32_t i3 = indexArray[y + 1][x + 1];
const uint32_t i4 = indexArray[y][x + 1];
// face one
indices[indexOffset] = i1;
++indexOffset;
indices[indexOffset] = i4;
++indexOffset;
indices[indexOffset] = i2;
++indexOffset;
// face two
indices[indexOffset] = i4;
++indexOffset;
indices[indexOffset] = i3;
++indexOffset;
indices[indexOffset] = i2;
++indexOffset;
}
}
};
auto generateCap = [&](bool top) {
const float radius = top ? radiusTop : radiusBottom;
const float sign = top ? 1 : -1;
// save the index of the first center vertex
const uint32_t centerIndexStart = index;
// first we generate the center vertex data of the cap.
// because the geometry needs one set of uvs per face,
// we must generate a center vertex per face/segment
for (uint32_t x = 1; x <= radialSegments; ++x) {
// vertex
positions[3 * index] = 0;
positions[3 * index + 1] = halfHeight * sign;
positions[3 * index + 2] = 0;
// // normal
normals[3 * index] = 0;
normals[3 * index + 1] = sign;
normals[3 * index + 2] = 0;
// uv
uvs[2 * index] = 0.5;
uvs[2 * index + 1] = 0.5;
// increase index
++index;
}
// save the index of the last center vertex
const uint32_t centerIndexEnd = index;
// now we generate the surrounding positions, normals and uvs
for (uint32_t x = 0; x <= radialSegments; ++x) {
const float u = static_cast<float>(x) / static_cast<float>(radialSegments);
const float theta = u * arc;
const float cosTheta = cos(theta);
const float sinTheta = sin(theta);
// vertex
positions[3 * index] = radius * sinTheta;
positions[3 * index + 1] = halfHeight * sign;
positions[3 * index + 2] = radius * cosTheta;
// normal
normals[3 * index] = 0;
normals[3 * index + 1] = sign;
normals[3 * index + 2] = 0;
// uv
uvs[2 * index] = 0.5F - (sinTheta * 0.5F * sign);
uvs[2 * index + 1] = 0.5F + (cosTheta * 0.5F);
// increase index
++index;
}
// generate indices
for (uint32_t x = 0; x < radialSegments; ++x) {
const uint32_t c = centerIndexStart + x;
const uint32_t i = centerIndexEnd + x;
if (top) {
// face top
indices[indexOffset] = i + 1;
++indexOffset;
indices[indexOffset] = c;
++indexOffset;
indices[indexOffset] = i;
++indexOffset;
} else {
// face bottom
indices[indexOffset] = c;
++indexOffset;
indices[indexOffset] = i + 1;
++indexOffset;
indices[indexOffset] = i;
++indexOffset;
}
}
};
generateTorso();
if (capped) {
if (radiusBottom > 0) {
generateCap(false);
}
if (radiusTop > 0) {
generateCap(true);
}
}
IGeometry info;
info.positions = positions;
info.normals = normals;
info.uvs = uvs;
info.boundingRadius = boundingRadius;
info.minPos = minPos;
info.maxPos = maxPos;
info.indices = indices;
return info;
}
} // namespace cc

View File

@@ -0,0 +1,55 @@
/****************************************************************************
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include <cmath>
#include "3d/assets/Mesh.h"
#include "primitive/PrimitiveDefine.h"
namespace cc {
/**
* @zh
* 球参数选项。
*/
struct ICylinderOptions : public IGeometryOptions {
uint32_t radialSegments{32};
uint32_t heightSegments{1};
bool capped{true};
float arc{math::PI_2};
};
/**
* @en
* Generate a sphere with radius 0.5.
* @zh
* 生成一个球。
* @param radius 球半径。
* @param options 参数选项。
*/
IGeometry cylinder(float radiusTop = 0.5, float radiusBottom = 0.5, float height = 2, const ccstd::optional<ICylinderOptions> &opts = ccstd::nullopt);
} // namespace cc

110
cocos/primitive/Plane.cpp Normal file
View File

@@ -0,0 +1,110 @@
/****************************************************************************
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "primitive/Plane.h"
namespace cc {
IGeometry plane(ccstd::optional<IPlaneOptions> options) {
if (!options.has_value()) {
options = IPlaneOptions();
}
const float width = options->width;
const float length = options->length;
const uint32_t uSegments = options->widthSegments;
const uint32_t vSegments = options->lengthSegments;
const float hw = width * 0.5F;
const float hl = length * 0.5F;
ccstd::vector<float> positions;
ccstd::vector<float> uvs;
ccstd::vector<uint32_t> indices;
const Vec3 minPos(-hw, 0, -hl);
const Vec3 maxPos(hw, 0, hl);
const float boundingRadius = sqrt(width * width + length * length);
Vec3 c00(-hw, 0, hl);
Vec3 c10(hw, 0, hl);
Vec3 c01(-hw, 0, -hl);
for (uint32_t y = 0; y <= vSegments; ++y) {
for (uint32_t x = 0; x <= uSegments; ++x) {
const float u = static_cast<float>(x) / static_cast<float>(uSegments);
const float v = static_cast<float>(y) / static_cast<float>(vSegments);
Vec3 temp1 = c00.lerp(c10, u);
Vec3 temp2 = c00.lerp(c01, v);
temp2.subtract(c00);
temp1.add(temp2);
positions.emplace_back(temp1.x);
positions.emplace_back(temp1.y);
positions.emplace_back(temp1.z);
if (options->includeUV) {
uvs.emplace_back(u);
uvs.emplace_back(v);
}
if ((x < uSegments) && (y < vSegments)) {
const uint32_t uSeg1 = uSegments + 1;
const uint32_t a = x + y * uSeg1;
const uint32_t b = x + (y + 1) * uSeg1;
const uint32_t c = (x + 1) + (y + 1) * uSeg1;
const uint32_t d = (x + 1) + y * uSeg1;
indices.emplace_back(a);
indices.emplace_back(d);
indices.emplace_back(b);
indices.emplace_back(d);
indices.emplace_back(c);
indices.emplace_back(b);
}
}
}
IGeometry result;
result.positions = positions;
result.boundingRadius = boundingRadius;
result.minPos = minPos;
result.maxPos = maxPos;
result.indices = indices;
if (options->includeNormal) {
const uint32_t nVertex = (vSegments + 1) * (uSegments + 1);
ccstd::vector<float> normals(3 * nVertex);
for (uint32_t i = 0; i < nVertex; ++i) {
normals[i * 3 + 0] = 0;
normals[i * 3 + 1] = 1;
normals[i * 3 + 2] = 0;
}
result.normals = normals;
}
if (options->includeUV) {
result.uvs = uvs;
}
return result;
}
} // namespace cc

68
cocos/primitive/Plane.h Normal file
View File

@@ -0,0 +1,68 @@
/****************************************************************************
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include "primitive/PrimitiveDefine.h"
namespace cc {
/**
* @en
* The definition of the parameter for building a plane.
* @zh
* 平面参数选项。
*/
struct IPlaneOptions : public IGeometryOptions {
/**
* Plane extent on X-axis. Default to 10.
*/
float width{10};
/**
* Plane extent on Z-axis. Default to 10.
*/
float length{10};
/**
* Segment count on X-axis. Default to 10.
*/
uint32_t widthSegments{10};
/**
* Segment count on Z-axis. Default to 10.
*/
uint32_t lengthSegments{10};
};
/**
* @en
* This function generates a plane on XOZ plane with positive Y direction.
* @zh
* 生成一个平面其位于XOZ平面方向为Y轴正方向。
* @param options 平面参数选项。
*/
IGeometry plane(ccstd::optional<IPlaneOptions> options = ccstd::nullopt);
} // namespace cc

View File

@@ -0,0 +1,79 @@
/****************************************************************************
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "primitive/Primitive.h"
#include "3d/misc/CreateMesh.h"
#include "core/assets/RenderingSubMesh.h"
namespace cc {
Primitive::Primitive(PrimitiveType type) : type(type) {
}
Primitive::~Primitive() = default;
void Primitive::onLoaded() {
reset(MeshUtils::createMeshInfo(createGeometry(type)));
}
IGeometry createGeometry(PrimitiveType type, const ccstd::optional<PrimitiveOptions> &options) {
switch (type) {
case PrimitiveType::BOX: {
return options.has_value() ? box(ccstd::get<IBoxOptions>(options.value())) : box();
break;
}
case PrimitiveType::SPHERE: {
return options.has_value() ? sphere(0.5F, ccstd::get<ISphereOptions>(options.value())) : sphere();
break;
}
case PrimitiveType::CYLINDER: {
return options.has_value() ? cylinder(0.5F, 0.5F, 2, ccstd::get<4>(options.value())) : cylinder();
break;
}
case PrimitiveType::CONE: {
return options.has_value() ? cone(0.5F, 1.0F, ccstd::get<5>(options.value())) : cone();
break;
}
case PrimitiveType::CAPSULE: {
return options.has_value() ? capsule(0.5F, 0.5F, 2, ccstd::get<ICapsuleOptions>(options.value())) : capsule();
break;
}
case PrimitiveType::TORUS: {
return options.has_value() ? torus(0.4F, 0.1F, ccstd::get<ITorusOptions>(options.value())) : torus();
break;
}
case PrimitiveType::PLANE: {
return options.has_value() ? quad(ccstd::get<IGeometryOptions>(options.value())) : plane();
break;
}
case PrimitiveType::QUAD: {
return options.has_value() ? quad(ccstd::get<IGeometryOptions>(options.value())) : quad();
break;
}
default:
break;
}
return box();
}
} // namespace cc

View File

@@ -0,0 +1,98 @@
/****************************************************************************
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include "base/std/optional.h"
#include "3d/assets/Mesh.h"
#include "base/std/variant.h"
#include "primitive/Box.h"
#include "primitive/Capsule.h"
#include "primitive/Circle.h"
#include "primitive/Cone.h"
#include "primitive/Cylinder.h"
#include "primitive/Plane.h"
#include "primitive/Quad.h"
#include "primitive/Sphere.h"
#include "primitive/Torus.h"
#include "primitive/PrimitiveDefine.h"
namespace cc {
using PrimitiveOptions = ccstd::variant<IGeometryOptions, IBoxOptions, ICapsuleOptions, ICircleOptions, ICylinderOptions, IConeOptions, IPlaneOptions, ISphereOptions, ITorusOptions>;
enum class PrimitiveType {
BOX = 0,
SPHERE = 1,
CYLINDER = 2,
CONE = 3,
CAPSULE = 4,
TORUS = 5,
PLANE = 6,
QUAD = 7,
};
/**
* @en
* Basic primitive mesh, this can be generate some primitive mesh at runtime.
* @zh
* 基础图形网格,可以在运行时构建一些基础的网格。
*/
class Primitive : public Mesh {
public:
/**
* @en
* The type of the primitive mesh, set it before you call onLoaded.
* @zh
* 此基础图形网格的类型,请在 onLoaded 调用之前设置。
*/
// @type(PrimitiveType)
PrimitiveType type{PrimitiveType::BOX};
/**
* @en
* The option for build the primitive mesh, set it before you call onLoaded.
* @zh
* 创建此基础图形网格的可选参数,请在 onLoaded 调用之前设置。
*/
// @serializable
// @editable
ccstd::unordered_map<ccstd::string, float> info; // cjh float?
explicit Primitive(PrimitiveType type = PrimitiveType::BOX);
~Primitive() override;
/**
* @en
* Construct the primitive mesh with `type` and `info`.
* @zh
* 根据`type`和`info`构建相应的网格。
*/
void onLoaded() override;
private:
CC_DISALLOW_COPY_MOVE_ASSIGN(Primitive);
};
IGeometry createGeometry(PrimitiveType type, const ccstd::optional<PrimitiveOptions> &options = ccstd::nullopt);
} // namespace cc

View File

@@ -0,0 +1,284 @@
/****************************************************************************
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include "base/std/optional.h"
#include "core/TypedArray.h"
#include "math/Vec3.h"
#include "math/Vec4.h"
#include "renderer/gfx-base/GFXDef.h"
namespace cc {
/**
* @en
* The definition of the parameter for building a primitive geometry.
* @zh
* 几何体参数选项。
*/
struct IGeometryOptions {
/**
* @en
* Whether to include normal. Default to true.
* @zh
* 是否包含法线。默认为true。
*/
bool includeNormal{true};
/**
* @en
* Whether to include uv. Default to true.
* @zh
* 是否包含UV。默认为true。
*/
bool includeUV{true};
};
struct CustomAttribute {
gfx::Attribute attr;
ccstd::vector<float> values;
};
/**
* @en
* The definition of the geometry, this struct can build a mesh.
* @zh
* 几何体信息。
*/
struct IGeometry {
/**
* @en
* Vertex positions.
* @zh
* 顶点位置。
*/
ccstd::vector<float> positions;
/**
* @en
* Vertex normals.
* @zh
* 顶点法线。
*/
ccstd::optional<ccstd::vector<float>> normals;
/**
* @en
* Texture coordinates.
* @zh
* 纹理坐标。
*/
ccstd::optional<ccstd::vector<float>> uvs;
/**
* @en
* Vertex Tangents.
* @zh
* 顶点切线。
*/
ccstd::optional<ccstd::vector<float>> tangents;
/**
* @en
* Vertex colors.
* @zh
* 顶点颜色。
*/
ccstd::optional<ccstd::vector<float>> colors;
/**
* @en
* specify vertex attributes, use (positions|normals|uvs|colors) as keys
* @zh
* 顶点属性。
*/
ccstd::optional<gfx::AttributeList> attributes;
/**
* @en
* Custom attributes
* @zh
* 定制属性列表。
*/
ccstd::optional<ccstd::vector<CustomAttribute>> customAttributes;
/**
* @en
* Bounding sphere radius.
* @zh
* 包围球半径。
*/
ccstd::optional<float> boundingRadius;
/**
* @en
* Min position.
* @zh
* 最小位置。
*/
ccstd::optional<Vec3> minPos;
/**
* @en
* Max position.
* @zh
* 最大位置。
*/
ccstd::optional<Vec3> maxPos;
/**
* @en
* Geometry indices, if one needs indexed-draw.
* @zh
* 几何索引,当使用索引绘制时。
*/
ccstd::optional<ccstd::vector<uint32_t>> indices; //cjh uint16_t ?
/**
* @en
* Topology of the geometry vertices. Default is TRIANGLE_LIST.
* @zh
* 几何顶点的拓扑图元。默认值是TRIANGLE_LIST。
*/
ccstd::optional<gfx::PrimitiveMode> primitiveMode;
/**
* @en
* whether rays casting from the back face of this geometry could collide with it
* @zh
* 是否是双面,用于判断来自于几何体背面的射线检测。
*/
ccstd::optional<bool> doubleSided;
};
struct DynamicCustomAttribute {
gfx::Attribute attr;
Float32Array values;
};
/**
* @en
* The definition of the dynamic geometry, this struct can build a dynamic mesh.
* @zh
* 几何体信息。
*/
struct IDynamicGeometry {
/**
* @en
* Vertex positions: 3 float components.
* @zh
* 顶点位置3个float分量。
*/
Float32Array positions;
/**
* @en
* Vertex normals: 3 float components.
* @zh
* 顶点法线3个float分量。
*/
ccstd::optional<Float32Array> normals;
/**
* @en
* Texture coordinates: 2 float components.
* @zh
* 纹理坐标2个float分量。
*/
ccstd::optional<Float32Array> uvs;
/**
* @en
* Vertex Tangents: 4 float components.
* @zh
* 顶点切线4个float分量。
*/
ccstd::optional<Float32Array> tangents;
/**
* @en
* Vertex colors: 4 float components.
* @zh
* 顶点颜色4个float分量。
*/
ccstd::optional<Float32Array> colors;
/**
* @en
* Custom attributes
* @zh
* 定制属性列表。
*/
ccstd::optional<ccstd::vector<DynamicCustomAttribute>> customAttributes;
/**
* @en
* Min position, it is more efficient to calculate bounding box by user.
* @zh
* 最小位置。包围盒大小由用户提供,更高效。
*/
ccstd::optional<Vec3> minPos;
/**
* @en
* Max position, it is more efficient to calculate bounding box by user.
* @zh
* 最大位置。包围盒大小由用户提供,更高效。
*/
ccstd::optional<Vec3> maxPos;
/**
* @en
* 16 bits Geometry indices, if one needs indexed-draw.
* @zh
* 16位几何索引当使用索引绘制时。
*/
ccstd::optional<Uint16Array> indices16;
/**
* @en
* 32 bits Geometry indices, if one needs indexed-draw.
* @zh
* 32位几何索引当使用索引绘制时。
*/
ccstd::optional<Uint32Array> indices32;
/**
* @en
* Topology of the geometry vertices. Default is TRIANGLE_LIST.
* @zh
* 几何顶点的拓扑图元。默认值是TRIANGLE_LIST。
*/
ccstd::optional<gfx::PrimitiveMode> primitiveMode;
/**
* @en
* whether rays casting from the back face of this geometry could collide with it
* @zh
* 是否是双面,用于判断来自于几何体背面的射线检测。
*/
ccstd::optional<bool> doubleSided;
};
} // namespace cc

View File

@@ -0,0 +1,23 @@
/****************************************************************************
Copyright (c) 2022-2023 Xiamen Yaji Software Co., Ltd.
https://www.cocos.com/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/

View File

@@ -0,0 +1,29 @@
/****************************************************************************
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
namespace cc {
}

54
cocos/primitive/Quad.cpp Normal file
View File

@@ -0,0 +1,54 @@
/****************************************************************************
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "primitive/Quad.h"
namespace cc {
IGeometry quad(ccstd::optional<IGeometryOptions> options) {
if (!options.has_value()) {
options = IGeometryOptions();
}
IGeometry result;
result.positions = ccstd::vector<float>{-0.5, -0.5, 0, -0.5, 0.5, 0, 0.5, 0.5, 0, 0.5, -0.5, 0};
result.boundingRadius = sqrt(0.5 * 0.5 + 0.5 * 0.5);
result.minPos = Vec3(-0.5, -0.5, 0);
result.maxPos = Vec3(0.5, 0.5, 0);
result.indices = ccstd::vector<uint32_t>{0, 3, 1, 3, 2, 1};
if (options->includeNormal) {
result.normals = ccstd::vector<float>{
0, 0, 1,
0, 0, 1,
0, 0, 1,
0, 0, 1};
}
if (options->includeUV) {
result.uvs = ccstd::vector<float>{
0, 0,
0, 1,
1, 1,
1, 0};
}
return result;
}
} // namespace cc

38
cocos/primitive/Quad.h Normal file
View File

@@ -0,0 +1,38 @@
/****************************************************************************
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include "primitive/PrimitiveDefine.h"
namespace cc {
/**
* @en
* Generate a quad with width and height both to 1, centered at origin.
* @zh
* 生成一个四边形宽高都为1中心在原点。
* @param options 参数选项。
*/
IGeometry quad(ccstd::optional<IGeometryOptions> options = ccstd::nullopt);
} // namespace cc

View File

@@ -0,0 +1,98 @@
/****************************************************************************
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "primitive/Sphere.h"
namespace cc {
IGeometry sphere(float radius, const ccstd::optional<ISphereOptions> &opts) {
const uint32_t segments = opts.has_value() ? opts->segments : 32;
// lat === latitude
// lon === longitude
ccstd::vector<float> positions;
ccstd::vector<float> normals;
ccstd::vector<float> uvs;
ccstd::vector<uint32_t> indices;
const Vec3 minPos(-radius, -radius, -radius);
const Vec3 maxPos(radius, radius, radius);
const float boundingRadius = radius;
for (uint32_t lat = 0; lat <= segments; lat++) {
const float theta = static_cast<float>(lat) * math::PI / static_cast<float>(segments);
const float sinTheta = sin(theta);
const float cosTheta = -cos(theta);
for (uint32_t lon = 0; lon <= segments; ++lon) {
const float phi = static_cast<float>(lon) * 2.F * math::PI / static_cast<float>(segments) - math::PI / 2.F;
const float sinPhi = sin(phi);
const float cosPhi = cos(phi);
const float x = sinPhi * sinTheta;
const float y = cosTheta;
const float z = cosPhi * sinTheta;
const float u = static_cast<float>(lon) / static_cast<float>(segments);
const float v = static_cast<float>(lat) / static_cast<float>(segments);
positions.emplace_back(x * radius);
positions.emplace_back(y * radius);
positions.emplace_back(z * radius);
normals.emplace_back(x);
normals.emplace_back(y);
normals.emplace_back(z);
uvs.emplace_back(u);
uvs.emplace_back(v);
if ((lat < segments) && (lon < segments)) {
const uint32_t seg1 = segments + 1;
const uint32_t a = seg1 * lat + lon;
const uint32_t b = seg1 * (lat + 1) + lon;
const uint32_t c = seg1 * (lat + 1) + lon + 1;
const uint32_t d = seg1 * lat + lon + 1;
indices.emplace_back(a);
indices.emplace_back(d);
indices.emplace_back(b);
indices.emplace_back(d);
indices.emplace_back(c);
indices.emplace_back(b);
}
}
}
IGeometry info;
info.positions = positions;
info.normals = normals;
info.uvs = uvs;
info.boundingRadius = boundingRadius;
info.minPos = minPos;
info.maxPos = maxPos;
info.indices = indices;
return info;
}
} // namespace cc

52
cocos/primitive/Sphere.h Normal file
View File

@@ -0,0 +1,52 @@
/****************************************************************************
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include <cmath>
#include "3d/assets/Mesh.h"
#include "primitive/PrimitiveDefine.h"
namespace cc {
/**
* @zh
* 球参数选项。
*/
struct ISphereOptions : public IGeometryOptions {
uint32_t segments{0};
};
/**
* @en
* Generate a shpere with radius 0.5.
* @zh
* 生成一个球。
* @param radius 球半径。
* @param options 参数选项。
*/
IGeometry sphere(float radius = 0.5, const ccstd::optional<ISphereOptions> &opts = ccstd::nullopt);
} // namespace cc

98
cocos/primitive/Torus.cpp Normal file
View File

@@ -0,0 +1,98 @@
/****************************************************************************
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "primitive/Torus.h"
namespace cc {
IGeometry torus(float radius, float tube, const ccstd::optional<ITorusOptions> &opts) {
const uint32_t radialSegments = opts.has_value() ? opts->radialSegments : 32;
const uint32_t tubularSegments = opts.has_value() ? opts->tubularSegments : 32;
const float arc = opts.has_value() ? opts->arc : math::PI_2;
ccstd::vector<float> positions;
ccstd::vector<float> normals;
ccstd::vector<float> uvs;
ccstd::vector<uint32_t> indices;
const Vec3 minPos(-radius - tube, -tube, -radius - tube);
const Vec3 maxPos(radius + tube, tube, radius + tube);
const float boundingRadius = radius + tube;
for (uint32_t j = 0; j <= radialSegments; j++) {
for (uint32_t i = 0; i <= tubularSegments; i++) {
const float u = static_cast<float>(i) / static_cast<float>(tubularSegments);
const float v = static_cast<float>(j) / static_cast<float>(radialSegments);
const float u1 = u * arc;
const float v1 = v * math::PI_2;
// vertex
const float x = (radius + tube * cos(v1)) * sin(u1);
const float y = tube * sin(v1);
const float z = (radius + tube * cos(v1)) * cos(u1);
// this vector is used to calculate the normal
const float nx = sin(u1) * cos(v1);
const float ny = sin(v1);
const float nz = cos(u1) * cos(v1);
positions.emplace_back(x);
positions.emplace_back(y);
positions.emplace_back(z);
normals.emplace_back(nx);
normals.emplace_back(ny);
normals.emplace_back(nz);
uvs.emplace_back(u);
uvs.emplace_back(v);
if ((i < tubularSegments) && (j < radialSegments)) {
const uint32_t seg1 = tubularSegments + 1;
const uint32_t a = seg1 * j + i;
const uint32_t b = seg1 * (j + 1) + i;
const uint32_t c = seg1 * (j + 1) + i + 1;
const uint32_t d = seg1 * j + i + 1;
indices.emplace_back(a);
indices.emplace_back(d);
indices.emplace_back(b);
indices.emplace_back(d);
indices.emplace_back(c);
indices.emplace_back(b);
}
}
}
IGeometry info;
info.positions = positions;
info.normals = normals;
info.uvs = uvs;
info.boundingRadius = boundingRadius;
info.minPos = minPos;
info.maxPos = maxPos;
info.indices = indices;
return info;
}
} // namespace cc

50
cocos/primitive/Torus.h Normal file
View File

@@ -0,0 +1,50 @@
/****************************************************************************
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include "primitive/PrimitiveDefine.h"
namespace cc {
/**
* @zh
* 环面参数选项。
*/
struct ITorusOptions {
uint32_t radialSegments{32};
uint32_t tubularSegments{32};
float arc{math::PI_2};
};
/**
* @en
* Generate a torus with raidus 0.4, tube 0.1 and centered at origin.
* @zh
* 生成一个环面。
* @param radius 环面半径。
* @param tube 管形大小。
* @param opts 参数选项。
*/
IGeometry torus(float radius = 0.4, float tube = 0.1, const ccstd::optional<ITorusOptions> &opts = ccstd::nullopt);
} // namespace cc

View File

@@ -0,0 +1,127 @@
/****************************************************************************
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "primitive/Transform.h"
namespace cc {
IGeometry translate(IGeometry &geometry, const ccstd::optional<Vec3> &offset) {
const float x = offset.has_value() ? offset->x : 0;
const float y = offset.has_value() ? offset->y : 0;
const float z = offset.has_value() ? offset->z : 0;
const uint32_t nVertex = floor(geometry.positions.size() / 3);
for (uint32_t iVertex = 0; iVertex < nVertex; ++iVertex) {
const uint32_t iX = iVertex * 3;
const uint32_t iY = iVertex * 3 + 1;
const uint32_t iZ = iVertex * 3 + 2;
geometry.positions[iX] += x;
geometry.positions[iY] += y;
geometry.positions[iZ] += z;
}
if (geometry.minPos.has_value()) {
geometry.minPos->x += x;
geometry.minPos->y += y;
geometry.minPos->z += z;
}
if (geometry.maxPos.has_value()) {
geometry.maxPos->x += x;
geometry.maxPos->y += y;
geometry.maxPos->z += z;
}
return geometry;
}
IGeometry scale(IGeometry &geometry, const ccstd::optional<Vec3> &value) {
const float x = value.has_value() ? value->x : 0;
const float y = value.has_value() ? value->y : 0;
const float z = value.has_value() ? value->z : 0;
const uint32_t nVertex = floor(geometry.positions.size() / 3);
for (uint32_t iVertex = 0; iVertex < nVertex; ++iVertex) {
const uint32_t iX = iVertex * 3;
const uint32_t iY = iVertex * 3 + 1;
const uint32_t iZ = iVertex * 3 + 2;
geometry.positions[iX] += x;
geometry.positions[iY] += y;
geometry.positions[iZ] += z;
}
if (geometry.minPos.has_value()) {
geometry.minPos->x += x;
geometry.minPos->y += y;
geometry.minPos->z += z;
}
if (geometry.maxPos.has_value()) {
geometry.maxPos->x += x;
geometry.maxPos->y += y;
geometry.maxPos->z += z;
}
geometry.boundingRadius = std::max(std::max(x, y), z);
return geometry;
}
IGeometry wireframed(IGeometry &geometry) {
const auto indices = geometry.indices;
if (!indices.has_value()) {
return geometry;
}
// We only support triangles' wireframe.
if (geometry.primitiveMode.has_value() && geometry.primitiveMode.value() != gfx::PrimitiveMode::TRIANGLE_LIST) {
return geometry;
}
// const offsets = [ [ 0, 1 ], [ 1, 2 ], [ 2, 0 ] ];
ccstd::vector<ccstd::vector<uint32_t>> offsets{{0, 1}, {1, 2}, {2, 0}};
ccstd::vector<uint32_t> lines;
ccstd::unordered_map<uint32_t, uint32_t> lineIDs;
for (uint32_t i = 0; i < indices->size(); i += 3) {
for (uint32_t k = 0; k < 3; ++k) {
const uint32_t i1 = (*indices)[i + offsets[k][0]];
const uint32_t i2 = (*indices)[i + offsets[k][1]];
// check if we already have the line in our lines
const uint32_t id = (i1 > i2) ? ((i2 << 16) | i1) : ((i1 << 16) | i2);
if (lineIDs.find(id) == lineIDs.end()) {
lineIDs[id] = 0;
lines.emplace_back(i1);
lines.emplace_back(i2);
}
}
}
geometry.indices = lines;
geometry.primitiveMode = gfx::PrimitiveMode::LINE_LIST;
return geometry;
}
} // namespace cc

View File

@@ -0,0 +1,60 @@
/****************************************************************************
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include "primitive/PrimitiveDefine.h"
namespace cc {
/**
* @en
* Translate the geometry.
* @zh
* 平移几何体。
* @param geometry 几何体信息。
* @param offset 偏移量。
*/
IGeometry translate(IGeometry &geometry, const ccstd::optional<Vec3> &offset);
/**
* @en
* Scale the geometry.
* @zh
* 缩放几何体。
* @param geometry 几何体信息。
* @param value 缩放量。
*/
IGeometry scale(IGeometry &geometry, const ccstd::optional<Vec3> &value);
/**
* @en
* Converts geometry to wireframe mode. Only geometry with triangle topology is supported.
* @zh
* 将几何体转换为线框模式,仅支持三角形拓扑的几何体。
* @param geometry 几何体信息。
*/
IGeometry wireframed(IGeometry &geometry);
} // namespace cc