geometryOverrideHighPerformance/geometryOverrideHighPerformanceHelper.cpp

geometryOverrideHighPerformance/geometryOverrideHighPerformanceHelper.cpp
//-
// ==========================================================================
// Copyright 2018 Autodesk, Inc. All rights reserved.
//
// Use of this software is subject to the terms of the Autodesk
// license agreement provided at the time of installation or download,
// or which otherwise accompanies this software in either electronic
// or hard copy form.
// ==========================================================================
//+
#include "geometryOverrideHighPerformanceHelper.h"
#include <maya/MFloatVector.h>
constexpr float PI = 3.14159265358979323846f;
void createSphere(float radius,
unsigned int sliceCount,
unsigned int stackCount,
Float3Array& positions,
Float3Array& normals,
Float3Array& tangents,
Float3Array& biTangents,
Float2Array& texCoords,
IndexList& indices,
MBoundingBox& boundingBox
)
{
positions.clear();
normals.clear();
tangents.clear();
texCoords.clear();
indices.clear();
const std::size_t vertexCount = stackCount * sliceCount + 1;
const std::size_t indexCount = sliceCount * 3 * 2 + (sliceCount - 2) * sliceCount * 6;
positions.reserve(vertexCount);
normals.reserve(vertexCount);
tangents.reserve(vertexCount);
texCoords.reserve(vertexCount);
indices.reserve(indexCount);
// vertex on the top of the sphere
positions.emplace_back( 0.0f, radius, 0.0f );
normals.emplace_back( 0.0f, 1.0f, 0.0f );
tangents.emplace_back( 1.0f, 0.0f, 0.0f );
biTangents.emplace_back(0.0f, 0.0f, -1.0f);
texCoords.emplace_back( 0.0f, 0.0f );
const float phiStep = PI / stackCount;
const float thetaStep = 2.0f * PI / sliceCount;
// Compute vertices for each stack ring
for (unsigned int i = 1; i <= stackCount - 1; ++i)
{
float phi = i * phiStep;
// Vertices of ring.
for (unsigned int j = 0; j <= sliceCount; ++j)
{
float theta = j * thetaStep;
// spherical to cartesian
Float3 position;
position.x = radius * sinf(phi) * cosf(theta);
position.y = radius * cosf(phi);
position.z = radius * sinf(phi) * sinf(theta);
positions.emplace_back( position.x, position.y, position.z );
MFloatVector normal(position.x, position.y, position.z);
normal.normalize();
normals.emplace_back( normal.x, normal.y, normal.z );
// Partial derivative of P with respect to theta
MFloatVector tangent(
-radius * sinf(phi) * sinf(theta),
0.0f,
radius * sinf(phi) * cosf(theta)
);
tangent.normalize();
tangents.emplace_back( tangent.x, tangent.y, tangent.z );
MFloatVector biTangent = normal ^ tangent;
biTangents.emplace_back(biTangent.x, biTangent.y, biTangent.z);
texCoords.emplace_back( theta / PI, phi / PI);
}
}
// vertex at the buttom of the sphere
positions.emplace_back( 0.0f, -radius, 0.0f );
normals.emplace_back( 0.0f, -1.0f, 0.0f );
tangents.emplace_back( 1.0f, 0.0f, 0.0f );
biTangents.emplace_back(0.0f, 0.0f, -1.0f);
texCoords.emplace_back( 0.0f, 1.0f );
//
// Compute indices for top stack. The top stack was written first to the vertex buffer
// and connects the top pole to the first ring.
//
for (unsigned int i = 1; i <= sliceCount; ++i)
{
indices.push_back(0);
indices.push_back(i + 1);
indices.push_back(i);
}
// Offset the indices to the index of the first vertex in the first ring.
// This is just skipping the top pole vertex.
unsigned int baseIndex = 1;
unsigned int ringVertexCount = sliceCount + 1;
for (unsigned int i = 0; i < sliceCount - 2; ++i)
{
for (unsigned int j = 0; j < sliceCount; ++j)
{
indices.push_back(baseIndex + i * ringVertexCount + j);
indices.push_back(baseIndex + i * ringVertexCount + j + 1);
indices.push_back(baseIndex + (i + 1) * ringVertexCount + j);
indices.push_back(baseIndex + (i + 1) * ringVertexCount + j);
indices.push_back(baseIndex + i * ringVertexCount + j + 1);
indices.push_back(baseIndex + (i + 1) * ringVertexCount + j + 1);
}
}
// South pole vertex was added last.
unsigned int southPoleIndex = (unsigned int)positions.size() - 1;
// Offset the indices to the index of the first vertex in the last ring.
baseIndex = southPoleIndex - ringVertexCount;
for (unsigned int i = 0; i < sliceCount; ++i)
{
indices.push_back(southPoleIndex);
indices.push_back(baseIndex + i);
indices.push_back(baseIndex + i + 1);
}
//
// Compute the bounding box
//
boundingBox = MBoundingBox(MPoint( -radius , -radius , -radius ), MPoint( radius, radius ,radius ));
}