blob: bfedf1d17f15fa3fb4ee039b7b67ba9658f223fd [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <array>
#include <memory>
#include "lib/ui/scenic/cpp/commands.h"
#include "lib/ui/scenic/cpp/resources.h"
using scenic::Buffer;
using scenic::Memory;
using scenic::Mesh;
using scenic::Session;
namespace scenic_util {
std::unique_ptr<Mesh> NewMeshWithVertices(Session* session, const std::vector<float>& vertices,
const std::vector<uint32_t>& indices) {
auto mesh = std::make_unique<Mesh>(session);
ZX_DEBUG_ASSERT(vertices.size() % 3 == 0);
const uint64_t num_vertices = vertices.size() / 3;
ZX_DEBUG_ASSERT(*std::max_element(indices.begin(), indices.end()) < num_vertices);
// TODO(SCN-558) vertex_elements should be 3.
uint64_t vertex_elements = 5;
uint64_t vertex_size = vertex_elements * sizeof(float);
uint64_t vertex_buffer_size = num_vertices * vertex_size;
uint64_t index_buffer_size = indices.size() * sizeof(uint32_t);
// TODO(SCN-558) This whole block is a workaround and should be removed.
std::vector<float> vertices_scn_558;
vertices_scn_558.reserve(vertex_buffer_size / sizeof(float));
for (uint64_t i = 0; i < num_vertices; i++) {
const float* vertex_in = vertices.data() + i * 3;
float* vertex_out = vertices_scn_558.data() + i * vertex_elements;
vertex_out[0] = vertex_in[0];
vertex_out[1] = vertex_in[1];
vertex_out[2] = vertex_in[2];
vertex_out[3] = 0;
vertex_out[4] = 0;
}
// END TODO(SCN-558)
// Copy data to VMO and create buffers
uint64_t vmo_size = vertex_buffer_size + index_buffer_size;
zx::vmo vmo;
zx_status_t status;
status = zx::vmo::create(vmo_size, 0u, &vmo);
// TODO(SCN-558) uses vertices.data()
status = vmo.write(vertices_scn_558.data(), 0, vertex_buffer_size);
ZX_DEBUG_ASSERT(status == ZX_OK);
status = vmo.write(indices.data(), vertex_buffer_size, index_buffer_size);
ZX_DEBUG_ASSERT(status == ZX_OK);
Memory mem(session, std::move(vmo), vmo_size, fuchsia::images::MemoryType::VK_DEVICE_MEMORY);
Buffer vertex_buffer(mem, 0, vertex_buffer_size);
Buffer index_buffer(mem, vertex_buffer_size, index_buffer_size);
auto vertex_format = scenic::NewMeshVertexFormat(fuchsia::ui::gfx::ValueType::kVector3,
fuchsia::ui::gfx::ValueType::kNone,
fuchsia::ui::gfx::ValueType::kVector2);
// Compute bounding box.
std::array<float, 3> bounding_box_min;
std::array<float, 3> bounding_box_max;
for (int i = 0; i < 3; i++) {
bounding_box_min[i] = std::numeric_limits<float>::max();
bounding_box_max[i] = std::numeric_limits<float>::min();
}
for (uint64_t i = 0; i < num_vertices; i++) {
const float* vertex = vertices.data() + i * 3;
bounding_box_min[0] = std::min(bounding_box_min[0], vertex[0]);
bounding_box_min[1] = std::min(bounding_box_min[1], vertex[1]);
bounding_box_min[2] = std::min(bounding_box_min[2], vertex[2]);
bounding_box_max[0] = std::max(bounding_box_max[0], vertex[0]);
bounding_box_max[1] = std::max(bounding_box_max[1], vertex[1]);
bounding_box_max[2] = std::max(bounding_box_max[2], vertex[2]);
}
// Bind buffers.
mesh->BindBuffers(index_buffer, fuchsia::ui::gfx::MeshIndexFormat::kUint32, 0, indices.size(),
vertex_buffer, std::move(vertex_format), 0, num_vertices,
std::move(bounding_box_min), std::move(bounding_box_max));
return mesh;
}
} // namespace scenic_util