Skip to content

Commit

Permalink
Improve resize UI quality (#968)
Browse files Browse the repository at this point in the history
  • Loading branch information
MortimerGoro authored and bluemarvin committed Feb 26, 2019
1 parent a7df7c3 commit 1466339
Show file tree
Hide file tree
Showing 4 changed files with 213 additions and 35 deletions.
50 changes: 45 additions & 5 deletions app/src/main/cpp/Cylinder.cpp
Expand Up @@ -37,6 +37,9 @@ struct Cylinder::State {
float theta;
float textureScaleX;
float textureScaleY;
float border;
vrb::Color borderColor;
vrb::Color solidColor;

State()
: textureWidth(0)
Expand All @@ -46,6 +49,7 @@ struct Cylinder::State {
, theta((float)M_PI)
, textureScaleX(1.0f)
, textureScaleY(1.0f)
, border(0.0f)
{}

void Initialize() {
Expand Down Expand Up @@ -77,8 +81,28 @@ struct Cylinder::State {
vrb::GeometryPtr geometry = vrb::Geometry::Create(create);
vrb::VertexArrayPtr array = vrb::VertexArray::Create(create);

for (int y = 0; y <= kHeightSegments; ++y) {
const float v = (float) y / (float) kHeightSegments;
const int ySegments = kHeightSegments + (border > 0.0f ? 2 : 0);

for (int y = 0; y <= ySegments; ++y) {
float offset = 0.0f;
float v = (float) y / (float) kHeightSegments;
vrb::Color vertexColor = solidColor;

if (border > 0) {
if (y == 0) {
v = 0.0f;
offset = border;
vertexColor = borderColor;
} else if (y == ySegments) {
v = 1.0f;
offset = -border;
vertexColor = borderColor;
} else {
v = (float) (y - 1) / (float) kHeightSegments;
}
}


for (int x = 0; x <= kRadialSegments; ++x) {
const float u = (float) x / (float) kRadialSegments;

Expand All @@ -91,7 +115,7 @@ struct Cylinder::State {
vrb::Vector normal;

vertex.x() = aRadius * cosTheta;
vertex.y() = -v * aHeight + aHeight * 0.5f;
vertex.y() = -v * aHeight + aHeight * 0.5f + offset;
vertex.z() = -aRadius * sinTheta;

uv.x() = u;
Expand All @@ -105,14 +129,17 @@ struct Cylinder::State {
array->AppendVertex(vertex);
array->AppendUV(uv);
array->AppendNormal(vertex.Normalize());
if (border > 0.0f) {
array->AppendColor(vertexColor);
}
}
}
geometry->SetVertexArray(array);

std::vector<int> indices;

for (int x = 0; x < kRadialSegments; ++x) {
for (int y = 0; y < kHeightSegments; ++y) {
for (int y = 0; y < ySegments; ++y) {
const int a = 1 + y * (kRadialSegments + 1) + x;
const int b = 1 + (y + 1) * (kRadialSegments + 1) + x;
const int c = 1 + (y + 1) * (kRadialSegments + 1) + x + 1;
Expand All @@ -131,6 +158,7 @@ struct Cylinder::State {

vrb::RenderStatePtr state = vrb::RenderState::Create(create);
state->SetLightsEnabled(false);
state->SetVertexColorEnabled(border > 0.0f);
state->SetFragmentPrecision(GL_HIGH_FLOAT);
state->SetUVTransformEnabled(true);
geometry->SetRenderState(state);
Expand All @@ -155,7 +183,7 @@ struct Cylinder::State {
if (segments % 2 != 0) {
segments++;
}
const int32_t indicesPerSegment = 6;
const int32_t indicesPerSegment = border > 0.0f ? 18 : 6;
const int32_t start = (kRadialSegments - segments) / 2;
geometry->SetRenderRange(start * indicesPerSegment, segments * indicesPerSegment);
}
Expand All @@ -172,6 +200,18 @@ Cylinder::Create(vrb::CreationContextPtr aContext, const float aRadius, const fl
return result;
}

CylinderPtr
Cylinder::Create(vrb::CreationContextPtr aContext, const float aRadius, const float aHeight, const vrb::Color& aSolidColor, const float aBorder, const vrb::Color& aBorderColor) {
CylinderPtr result = std::make_shared<vrb::ConcreteClass<Cylinder, Cylinder::State> >(aContext);
result->m.radius = aRadius;
result->m.height = aHeight;
result->m.solidColor = aSolidColor;
result->m.border = aBorder;
result->m.borderColor = aBorderColor;
result->m.Initialize();
return result;
}

CylinderPtr
Cylinder::Create(vrb::CreationContextPtr aContext, const VRLayerCylinderPtr& aLayer) {
CylinderPtr result = std::make_shared<vrb::ConcreteClass<Cylinder, Cylinder::State> >(aContext);
Expand Down
1 change: 1 addition & 0 deletions app/src/main/cpp/Cylinder.h
Expand Up @@ -27,6 +27,7 @@ typedef std::shared_ptr<Cylinder> CylinderPtr;
class Cylinder {
public:
static CylinderPtr Create(vrb::CreationContextPtr aContext, const float aRadius, const float aHeight, const VRLayerCylinderPtr& aLayer = nullptr);
static CylinderPtr Create(vrb::CreationContextPtr aContext, const float aRadius, const float aHeight, const vrb::Color& aSolidColor, const float kBorder, const vrb::Color& aBorderColor);
static CylinderPtr Create(vrb::CreationContextPtr aContext, const VRLayerCylinderPtr& aLayer = nullptr);
void GetTextureSize(int32_t& aWidth, int32_t& aHeight) const;
void SetTextureSize(int32_t aWidth, int32_t aHeight);
Expand Down
195 changes: 166 additions & 29 deletions app/src/main/cpp/WidgetResizer.cpp
Expand Up @@ -28,6 +28,11 @@ struct ResizeBar;
typedef std::shared_ptr<ResizeBar> ResizeBarPtr;

static const float kBarSize = 0.04f;
#if defined(OCULUSVR)
static const float kBorder = 0.0f;
#else
static const float kBorder = kBarSize * 0.15f;
#endif
static const float kHandleRadius = 0.08f;
static const vrb::Vector kMinResize(1.5f, 1.5f, 0.0f);
static const vrb::Vector kMaxResize(8.0f, 4.5f, 0.0f);
Expand Down Expand Up @@ -60,18 +65,18 @@ struct ResizeBar {
Quad,
Cylinder
};
static ResizeBarPtr Create(vrb::CreationContextPtr& aContext, const vrb::Vector& aCenter, const vrb::Vector& aScale, const ResizeBar::Mode aMode) {
static ResizeBarPtr Create(vrb::CreationContextPtr& aContext, const vrb::Vector& aCenter, const vrb::Vector& aScale, const device::EyeRect& aBorder, const ResizeBar::Mode aMode) {
auto result = std::make_shared<ResizeBar>();
result->center = aCenter;
result->scale = aScale;
vrb::Vector max(kBarSize * 0.5f, kBarSize * 0.5f, 0.0f);
result->transform = vrb::Transform::Create(aContext);
if (aMode == ResizeBar::Mode::Cylinder) {
result->cylinder = Cylinder::Create(aContext, 1.0f, kBarSize);
result->cylinder = Cylinder::Create(aContext, 1.0f, kBarSize, vrb::Color(1.0f, 1.0f, 1.0f, 1.0f), kBorder, vrb::Color(1.0f, 1.0f, 1.0f, 0.0f));
result->cylinder->SetLightsEnabled(false);
result->transform->AddNode(result->cylinder->GetRoot());
} else {
result->geometry = Quad::CreateGeometry(aContext, -max, max);
result->geometry = CreateGeometry(aContext, -max, max, aBorder);
result->geometry->GetRenderState()->SetLightsEnabled(false);
result->transform->AddNode(result->geometry);
}
Expand All @@ -81,6 +86,90 @@ struct ResizeBar {
return result;
}

static void AppendBorder(const vrb::GeometryPtr& geometry, GLint index1, GLint index2, const vrb::Vector& offset, const vrb::Color& aColor, GLint& currentIndex) {
vrb::VertexArrayPtr array = geometry->GetVertexArray();
vrb::Vector offset1 = array->GetVertex(index1 - 1) + offset;
vrb::Vector offset2 = array->GetVertex(index2 - 1) + offset;
array->AppendVertex(offset1);
array->AppendVertex(offset2);
array->AppendColor(aColor);
array->AppendColor(aColor);

GLint index3 = currentIndex++;
GLint index4 = currentIndex++;
std::vector<int> index;
if (offset.y() > 0.0f) {
index = { index1, index2, index4, index3};
} else if (offset.y() < 0.0f) {
index = { index3, index4, index2, index1};
} else if (offset.x() > 0.0f) {
index = { index1, index3, index4, index2};
} else {
index = { index3, index1, index2, index4};
}

std::vector<int> normalIndex;
normalIndex.push_back(1);
normalIndex.push_back(1);
normalIndex.push_back(1);
normalIndex.push_back(1);
geometry->AddFace(index, index, normalIndex);
}

static vrb::GeometryPtr CreateGeometry(vrb::CreationContextPtr aContext, const vrb::Vector &aMin, const vrb::Vector &aMax, const device::EyeRect& aBorder) {
vrb::VertexArrayPtr array = vrb::VertexArray::Create(aContext);
vrb::Color solid(1.0f, 1.0f, 1.0f, 1.0f);
vrb::Color border(1.0f, 1.0f, 1.0f, 0.0f);

const vrb::Vector bottomRight(aMax.x(), aMin.y(), aMin.z());
array->AppendVertex(aMin); // Bottom left
array->AppendVertex(bottomRight); // Bottom right
array->AppendVertex(aMax); // Top right
array->AppendVertex(vrb::Vector(aMin.x(), aMax.y(), aMax.z())); // Top left
for (int i = 0; i < 4; ++i) {
array->AppendColor(solid);
}

vrb::Vector normal = (bottomRight - aMin).Cross(aMax - aMin).Normalize();
array->AppendNormal(normal);

vrb::RenderStatePtr state = vrb::RenderState::Create(aContext);
state->SetVertexColorEnabled(true);
vrb::GeometryPtr geometry = vrb::Geometry::Create(aContext);
geometry->SetVertexArray(array);
geometry->SetRenderState(state);

std::vector<int> index;
index.push_back(1);
index.push_back(2);
index.push_back(3);
index.push_back(4);
std::vector<int> normalIndex;
normalIndex.push_back(1);
normalIndex.push_back(1);
normalIndex.push_back(1);
normalIndex.push_back(1);

geometry->AddFace(index, index, normalIndex);

GLint currentIndex = 5;

if (aBorder.mX > 0.0f) {
AppendBorder(geometry, 1, 4, vrb::Vector(-aBorder.mX, 0.0f, 0.0f), border, currentIndex);
}
if (aBorder.mWidth > 0.0f) {
AppendBorder(geometry, 2, 3, vrb::Vector(aBorder.mWidth, 0.0f, 0.0f), border, currentIndex);
}
if (aBorder.mY > 0.0f) {
AppendBorder(geometry, 1, 2, vrb::Vector(0.0f, -aBorder.mY, 0.0f), border, currentIndex);
}
if (aBorder.mHeight > 0.0f) {
AppendBorder(geometry, 4, 3, vrb::Vector(0.0f, aBorder.mHeight, 0.0f), border, currentIndex);
}

return geometry;
}

void SetResizeState(ResizeState aState) {
if (resizeState != aState) {
resizeState = aState;
Expand Down Expand Up @@ -145,37 +234,80 @@ struct ResizeHandle {
array->AppendVertex(vrb::Vector(0.0f, 0.0f, 0.0f));
array->AppendNormal(vrb::Vector(0.0f, 0.0f, 1.0f));

std::vector<int> index;
std::vector<int> normalIndex;
vrb::Color solid(1.0f, 1.0f, 1.0f, 1.0f);
vrb::Color border(1.0f, 1.0f, 1.0f, 0.0f);
array->AppendColor(solid);

std::vector<int> indices;
std::vector<int> normalIndices;

const int kSides = 30;
double delta = 2.0 * M_PI / kSides;
for (int i = 0; i < kSides; ++i) {
const double angle = delta * i;
array->AppendVertex(vrb::Vector(kHandleRadius * (float)cos(angle), kHandleRadius * (float)sin(angle), 0.0f));
array->AppendColor(solid);
if (i > 0) {
index.push_back(1);
index.push_back(i + 1);
index.push_back(i + 2);
normalIndex.push_back(1);
normalIndex.push_back(1);
normalIndex.push_back(1);
indices.push_back(1);
indices.push_back(i + 1);
indices.push_back(i + 2);
normalIndices.push_back(1);
normalIndices.push_back(1);
normalIndices.push_back(1);
}
}

index.push_back(1);
index.push_back(array->GetVertexCount());
index.push_back(2);
normalIndex.push_back(1);
normalIndex.push_back(1);
normalIndex.push_back(1);
indices.push_back(1);
indices.push_back(array->GetVertexCount());
indices.push_back(2);
normalIndices.push_back(1);
normalIndices.push_back(1);
normalIndices.push_back(1);

vrb::GeometryPtr geometry = vrb::Geometry::Create(aContext);
vrb::RenderStatePtr state = vrb::RenderState::Create(aContext);
state->SetLightsEnabled(false);
state->SetVertexColorEnabled(true);
geometry->SetVertexArray(array);
geometry->SetRenderState(state);
geometry->AddFace(index, index, normalIndex);
geometry->AddFace(indices, indices, normalIndices);


if (kBorder > 0.0f) {
int lastCircleIndex = array->GetVertexCount();
int borderIndex = array->GetVertexCount() + 1;
for (int i = 0; i < kSides; ++i) {
const double angle = delta * i;
const float r = kHandleRadius + kBorder;
array->AppendVertex(vrb::Vector(r * (float)cos(angle), r * (float)sin(angle), 0.0f));
array->AppendColor(border);
if (i > 0) {
indices.clear();
normalIndices.clear();
indices.push_back(i + 2);
indices.push_back(i + 1);
indices.push_back(borderIndex);
indices.push_back(++borderIndex);
normalIndices.push_back(1);
normalIndices.push_back(1);
normalIndices.push_back(1);
normalIndices.push_back(1);
geometry->AddFace(indices, indices, normalIndices);
}
}
indices.clear();
normalIndices.clear();
indices.push_back(2);
indices.push_back(lastCircleIndex);
indices.push_back(borderIndex);
indices.push_back(lastCircleIndex + 1);
normalIndices.push_back(1);
normalIndices.push_back(1);
normalIndices.push_back(1);
normalIndices.push_back(1);
geometry->AddFace(indices, indices, normalIndices);
}


return geometry;
}
Expand Down Expand Up @@ -223,15 +355,20 @@ struct WidgetResizer::State {

vrb::Vector horizontalSize(0.0f, 0.5f, 0.0f);
vrb::Vector verticalSize(0.5f, 0.0f, 0.0f);
device::EyeRect horizontalBorder(0.0f, kBorder, 0.0f, kBorder);
device::EyeRect verticalBorder(kBorder, 0.0f, kBorder, 0.0f);
ResizeBar::Mode mode = widget->GetCylinder() ? ResizeBar::Mode::Cylinder : ResizeBar::Mode::Quad;
ResizeBarPtr leftTop = CreateResizeBar(vrb::Vector(0.0f, 0.75f, 0.0f), horizontalSize, ResizeBar::Mode::Quad);
ResizeBarPtr leftBottom = CreateResizeBar(vrb::Vector(0.0f, 0.25f, 0.0f), horizontalSize, ResizeBar::Mode::Quad);
ResizeBarPtr rightTop = CreateResizeBar(vrb::Vector(1.0f, 0.75f, 0.0f), horizontalSize, ResizeBar::Mode::Quad);
ResizeBarPtr rightBottom = CreateResizeBar(vrb::Vector(1.0f, 0.25f, 0.0f), horizontalSize, ResizeBar::Mode::Quad);
ResizeBarPtr topLeft = CreateResizeBar(vrb::Vector(0.25f, 1.0f, 0.0f), verticalSize, mode);
ResizeBarPtr topRight = CreateResizeBar(vrb::Vector(0.75f, 1.0f, 0.0f), verticalSize, mode);
ResizeBarPtr bottomLeft = CreateResizeBar(vrb::Vector(0.25f, 0.0f, 0.0f), verticalSize, mode);
ResizeBarPtr bottomRight = CreateResizeBar(vrb::Vector(0.75f, 0.0f, 0.0f), verticalSize, mode);
ResizeBarPtr leftTop = CreateResizeBar(vrb::Vector(0.0f, 0.75f, 0.0f), horizontalSize, verticalBorder, ResizeBar::Mode::Quad);
ResizeBarPtr leftBottom = CreateResizeBar(vrb::Vector(0.0f, 0.25f, 0.0f), horizontalSize, verticalBorder, ResizeBar::Mode::Quad);
ResizeBarPtr rightTop = CreateResizeBar(vrb::Vector(1.0f, 0.75f, 0.0f), horizontalSize, verticalBorder, ResizeBar::Mode::Quad);
ResizeBarPtr rightBottom = CreateResizeBar(vrb::Vector(1.0f, 0.25f, 0.0f), horizontalSize, verticalBorder, ResizeBar::Mode::Quad);
ResizeBarPtr topLeft = CreateResizeBar(vrb::Vector(0.25f, 1.0f, 0.0f), verticalSize, horizontalBorder, mode);
ResizeBarPtr topRight = CreateResizeBar(vrb::Vector(0.75f, 1.0f, 0.0f), verticalSize, horizontalBorder, mode);
//ResizeBarPtr bottomLeft = CreateResizeBar(vrb::Vector(0.25f, 0.0f, 0.0f), verticalSize, mode);
//ResizeBarPtr bottomRight = CreateResizeBar(vrb::Vector(0.75f, 0.0f, 0.0f), verticalSize, mode);
ResizeBarPtr bottom = CreateResizeBar(vrb::Vector(0.5f, 0.0f, 0.0f), vrb::Vector(1.0f, 0.0f, 0.0f), horizontalBorder, mode);
//ResizeBarPtr bottomLeftCorner = CreateResizeBar(vrb::Vector(0.0f, 0.0f, 0.0f), vrb::Vector(0.0f, 0.0f, 0.0f), device::EyeRect(kBorder, kBorder, 0.0f, 0.0f), ResizeBar::Mode::Quad);
//ResizeBarPtr bottomRightCorner = CreateResizeBar(vrb::Vector(1.0f, 0.0f, 0.0f), vrb::Vector(0.0f, 0.0f, 0.0f), device::EyeRect(.0f, 0.0f, kBorder, kBorder), ResizeBar::Mode::Quad);

CreateResizeHandle(vrb::Vector(0.0f, 1.0f, 0.0f), ResizeHandle::ResizeMode::Both, {leftTop, topLeft});
CreateResizeHandle(vrb::Vector(1.0f, 1.0f, 0.0f), ResizeHandle::ResizeMode::Both, {rightTop, topRight});
Expand All @@ -245,12 +382,12 @@ struct WidgetResizer::State {
Layout();
}

ResizeBarPtr CreateResizeBar(const vrb::Vector& aCenter, vrb::Vector aScale, const ResizeBar::Mode aMode) {
ResizeBarPtr CreateResizeBar(const vrb::Vector& aCenter, vrb::Vector aScale, const device::EyeRect& aBorder, const ResizeBar::Mode aMode) {
vrb::CreationContextPtr create = context.lock();
if (!create) {
return nullptr;
}
ResizeBarPtr result = ResizeBar::Create(create, aCenter, aScale, aMode);
ResizeBarPtr result = ResizeBar::Create(create, aCenter, aScale, aBorder, aMode);
resizeBars.push_back(result);
root->AddNode(result->transform);
return result;
Expand Down Expand Up @@ -329,7 +466,7 @@ struct WidgetResizer::State {
const float pointerAngle = (float)M_PI * 0.5f + theta * 0.5f - theta * bar->center.x();
vrb::Matrix rotation = vrb::Matrix::Rotation(vrb::Vector(-cosf(pointerAngle), 0.0f, sinf(pointerAngle)));
if (bar->cylinder) {
bar->cylinder->SetCylinderTheta(theta * 0.5f);
bar->cylinder->SetCylinderTheta(theta * bar->scale.x());
vrb::Matrix translation = vrb::Matrix::Position(vrb::Vector(0.0f, min.y() + height * bar->center.y(), radius));
vrb::Matrix scale = vrb::Matrix::Identity();
scale.ScaleInPlace(vrb::Vector(radius, 1.0f, radius));
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/cpp/vrb

0 comments on commit 1466339

Please sign in to comment.