22 #include "base/integral_types.h"
36 #include "third_party/openctm/files/tools/3ds.h"
37 #include "third_party/openctm/files/tools/dae.h"
38 #include "third_party/openctm/files/tools/lwo.h"
39 #include "third_party/openctm/files/tools/mesh.h"
40 #include "third_party/openctm/files/tools/obj.h"
41 #include "third_party/openctm/files/tools/off.h"
66 VertexP() :
position(Point3f::Zero()) {}
79 VertexPN() :
position(Point3f::Zero()),
normal(Vector3f::Zero()) {}
89 normal(Vector3f::Zero()) {}
105 template <
typename VertexType>
106 static void CompactVertices(
size_t count,
const VertexPTN vertices_in[],
107 VertexType vertices_out[]) {
108 #if !defined(ION_COVERAGE) // COV_NF_START
109 DCHECK(
false) <<
"Unspecialized CompactVertices called";
115 void CompactVertices<VertexP>(
size_t count,
const VertexPTN vertices_in[],
116 VertexP vertices_out[]) {
117 for (
size_t i = 0; i < count; ++i)
123 void CompactVertices<VertexPT>(
size_t count,
const VertexPTN vertices_in[],
124 VertexPT vertices_out[]) {
125 for (
size_t i = 0; i < count; ++i) {
126 vertices_out[i].position = vertices_in[i].position;
127 vertices_out[i].texture_coords = vertices_in[i].texture_coords;
133 void CompactVertices<VertexPN>(
size_t count,
const VertexPTN vertices_in[],
134 VertexPN vertices_out[]) {
135 for (
size_t i = 0; i < count; ++i) {
136 vertices_out[i].position = vertices_in[i].position;
137 vertices_out[i].normal = vertices_in[i].normal;
150 template <
typename VertexType>
153 #if !defined(ION_COVERAGE) // COV_NF_START
154 DCHECK(
false) <<
"Unspecialized BindVertices called";
163 BufferToAttributeBinder<VertexP>(v)
164 .Bind(v.position,
"aVertex")
166 attribute_array, buffer_object);
174 BufferToAttributeBinder<VertexPT>(v)
175 .Bind(v.position,
"aVertex")
176 .Bind(v.texture_coords,
"aTexCoords")
178 attribute_array, buffer_object);
186 BufferToAttributeBinder<VertexPN>(v)
187 .Bind(v.position,
"aVertex")
188 .Bind(v.normal,
"aNormal")
190 attribute_array, buffer_object);
198 BufferToAttributeBinder<VertexPTN>(v)
199 .Bind(v.position,
"aVertex")
200 .Bind(v.texture_coords,
"aTexCoords")
201 .Bind(v.normal,
"aNormal")
203 attribute_array, buffer_object);
218 return allocator.
Get() ?
224 static const Vector3f SwizzleVector3f(
const Vector3f& v,
225 const char swizzle[3]) {
234 template <
typename VertexType>
237 const VertexPTN vertices[]) {
239 base::ScopedAllocation<VertexType> sa(allocator, count);
242 CompactVertices<VertexType>(count, vertices, sa.Get());
246 return sa.TransferToDataContainer(is_wipeable);
251 static bool IsWipeable(
const ShapeSpec& spec) {
257 static bool HasTextureCoordinates(
const ShapeSpec& spec) {
263 static bool HasNormals(
const ShapeSpec& spec) {
274 new(spec.allocator) gfx::AttributeArray);
275 switch (spec.vertex_type) {
277 BindVertices<VertexP>(attribute_array, buffer_object);
280 BindVertices<VertexPT>(attribute_array, buffer_object);
283 BindVertices<VertexPN>(attribute_array, buffer_object);
287 BindVertices<VertexPTN>(attribute_array, buffer_object);
290 return attribute_array;
298 const ShapeSpec& spec,
size_t vertex_count,
const VertexPTN vertices[]) {
300 const bool is_wipeable = IsWipeable(spec);
304 switch (spec.vertex_type) {
306 container = CompactVerticesIntoDataContainer<VertexP>(
308 vertex_size =
sizeof(VertexP);
311 container = CompactVerticesIntoDataContainer<VertexPT>(
313 vertex_size =
sizeof(VertexPT);
316 container = CompactVerticesIntoDataContainer<VertexPN>(
318 vertex_size =
sizeof(VertexPN);
323 container = base::DataContainer::CreateAndCopy<VertexPTN>(
325 vertex_size =
sizeof(vertices[0]);
328 buffer_object->SetData(container, vertex_size, vertex_count, spec.usage_mode);
329 return buffer_object;
335 const ShapeSpec& spec,
size_t num_indices,
const uint16 indices[]) {
338 base::DataContainer::CreateAndCopy<uint16>(
339 indices, num_indices, IsWipeable(spec), spec.allocator);
342 index_buffer->SetData(container,
sizeof(indices[0]), num_indices,
351 template <
typename T>
355 const T* tri_indices = tri_data->GetData<
T>();
358 base::AllocVector<T> line_indices(GetShortTermAllocator(allocator),
359 line_index_count, static_cast<T>(0));
362 const size_t num_tris = tri_index_count / 3;
363 size_t tri_index = 0;
364 size_t line_index = 0;
365 for (
size_t i = 0; i < num_tris; ++i) {
366 line_indices[line_index + 0] = tri_indices[tri_index + 0];
367 line_indices[line_index + 1] = tri_indices[tri_index + 1];
368 line_indices[line_index + 2] = tri_indices[tri_index + 1];
369 line_indices[line_index + 3] = tri_indices[tri_index + 2];
370 line_indices[line_index + 4] = tri_indices[tri_index + 2];
371 line_indices[line_index + 5] = tri_indices[tri_index + 0];
379 &line_indices[0], line_index_count, tri_data->IsWipeable(),
396 static const char* GetPlanarShapeSwizzle(
398 switch (plane_normal) {
416 static const Vector3f GetPlanarShapeSigns(
418 switch (plane_normal) {
420 return Vector3f(-1.f, 1.f, 1.f);
422 return Vector3f(1.f, 1.f, -1.f);
424 return Vector3f(1.f, -1.f, 1.f);
426 return Vector3f(1.f, 1.f, -1.f);
428 return Vector3f(1.f, 1.f, 1.f);
431 return Vector3f(-1.f, 1.f, -1.f);
441 static void GetRectangleVertices(
442 const ShapeSpec& spec,
float width,
float height,
443 const char* swizzle,
const Vector3f& signs, VertexPTN vertices[]) {
445 const float half_w = signs[0] * 0.5f *
width;
446 const float half_h = signs[1] * 0.5f * height;
453 const Vector3f
translation = spec.translation - Point3f::Zero();
454 for (
int i = 0; i < 4; ++i)
456 spec.rotation * (vertices[i].position * spec.scale) +
translation;
459 if (HasTextureCoordinates(spec)) {
460 vertices[0].texture_coords.Set(0.f, 0.f);
461 vertices[1].texture_coords.Set(1.f, 0.f);
462 vertices[2].texture_coords.Set(1.f, 1.f);
463 vertices[3].texture_coords.Set(0.f, 1.f);
467 if (HasNormals(spec)) {
469 math::Swizzle(Vector3f(0.f, 0.f, signs[2]), swizzle, &normal);
470 for (
int i = 0; i < 4; ++i)
471 vertices[i].normal = spec.rotation * normal;
477 static void GetRegularPolygonVertices(
478 const ShapeSpec& spec,
const base::AllocVector<Point2f>& points,
479 const char* swizzle,
const Vector3f& signs, VertexPTN vertices[]) {
480 const Vector3f translation = spec.translation - Point3f::Zero();
481 const bool has_textures = HasTextureCoordinates(spec);
482 const bool has_normals = HasNormals(spec);
485 math::Swizzle(Vector3f(0.f, 0.f, signs[2]), swizzle, &normal);
488 const size_t num_vertices = points.size();
489 for (
size_t i = 0; i < num_vertices; i++) {
490 math::Swizzle(Point3f(points[i][0], points[i][1], 0.0f), swizzle,
492 vertices[i].position =
493 spec.rotation * (vertices[i].position * spec.scale) + translation;
497 vertices[i].texture_coords.Set((points[i][0] + 1.0f) * 0.5f,
498 (points[i][1] + 1.0f) * 0.5f);
501 vertices[i].normal = spec.rotation *
normal;
513 const Anglef sector_angle =
514 (angle_end - angle_start) / static_cast<float>(sector_count);
515 for (
size_t i = 0; i < sector_count + 1; ++i) {
516 const Anglef angle = angle_start + sector_angle *
static_cast<float>(i);
517 const float radians = angle.Radians();
518 points[i].Set(cosf(radians), sinf(radians));
525 static void GetCirclePoints(
size_t sector_count, Point2f points[]) {
526 GetPartialCirclePoints(sector_count,
528 math::Anglef::FromDegrees(360.f),
546 Import_3DS(in, mesh);
549 Import_DAE(in, mesh);
552 Import_LWO(in, mesh);
555 Import_OBJ(in, mesh);
558 Import_OFF(in, mesh);
568 const ExternalShapeSpec& spec,
const Mesh& mesh) {
570 const size_t vertex_count = mesh.mVertices.size();
571 base::AllocVector<VertexPTN> vertices(GetShortTermAllocator(spec.allocator),
572 vertex_count, VertexPTN());
574 Vector3f center = Vector3f::Zero();
575 if (spec.center_at_origin) {
577 mesh.BoundingBox(bmin, bmax);
578 const Point3f mesh_min = Point3f(bmin.x, bmin.y, bmin.z);
579 const Point3f mesh_max = Point3f(bmax.x, bmax.y, bmax.z);
580 center =
Range3f(mesh_min, mesh_max).GetCenter() - Point3f::Zero();
583 const Point3f point(mesh.mVertices[i].x, mesh.mVertices[i].y,
584 mesh.mVertices[i].z);
585 vertices[i].position = spec.rotation * ((point - center) * spec.scale) +
587 if (mesh.HasNormals())
590 Vector3f(mesh.mNormals[i].x, mesh.mNormals[i].y, mesh.mNormals[i].z);
591 if (mesh.HasTexCoords())
596 return BuildBufferObject(spec, vertex_count, vertices.data());
601 const ExternalShapeSpec& spec,
const Mesh& mesh) {
602 switch (spec.index_size) {
603 case ExternalShapeSpec::IndexSize::k16Bit: {
604 const size_t index_count = mesh.mIndices.size();
605 base::AllocVector<uint16> indices(GetShortTermAllocator(spec.allocator),
606 index_count, static_cast<uint16>(0));
607 for (
size_t i = 0; i < index_count; ++i) {
608 if (mesh.mIndices[i] >= (1 << 16)) {
609 LOG(
ERROR) <<
"Vertex index " << mesh.mIndices[i]
610 <<
" is too large to store as uint16.";
613 indices[i] =
static_cast<uint16
>(mesh.mIndices[i]);
615 return BuildIndexBuffer(spec, index_count, indices.data());
617 case ExternalShapeSpec::IndexSize::k32Bit: {
620 mesh.mIndices.data(), mesh.mIndices.size(), IsWipeable(spec),
623 index_buffer->SetData(container,
sizeof(mesh.mIndices[0]),
624 mesh.mIndices.size(), spec.usage_mode);
628 DCHECK(
false) <<
"Unknown vertex size.";
643 const RectangleSpec& spec) {
644 VertexPTN vertices[4];
645 GetRectangleVertices(spec, spec.size[0], spec.size[1],
646 GetPlanarShapeSwizzle(spec.plane_normal),
647 GetPlanarShapeSigns(spec.plane_normal),
649 return BuildBufferObject(spec, 4U, vertices);
654 const RectangleSpec& spec) {
655 static const int kNumIndices = 6;
656 static const uint16 kIndices[kNumIndices] = { 0, 1, 2, 0, 2, 3 };
657 return BuildIndexBuffer(spec, kNumIndices, kIndices);
671 const RegularPolygonSpec& spec) {
674 const int kNumVertices = spec.sides + 2;
679 base::AllocVector<Point2f> points(allocator, kNumVertices, Point2f::Zero());
680 GetCirclePoints(static_cast<size_t>(spec.sides), &points[1]);
682 base::AllocVector<VertexPTN> vertices(allocator, kNumVertices, VertexPTN());
683 GetRegularPolygonVertices(
684 spec, points, GetPlanarShapeSwizzle(spec.plane_normal),
685 GetPlanarShapeSigns(spec.plane_normal), vertices.data());
686 return BuildBufferObject(spec, kNumVertices, vertices.data());
698 static void GetBoxFaceVertices(
const BoxSpec& spec,
700 VertexPTN vertices[]) {
703 const char* swizzle = GetPlanarShapeSwizzle(plane_normal);
704 const Vector3f signs = GetPlanarShapeSigns(plane_normal);
705 const Vector3f swizzled_size = SwizzleVector3f(spec.size, swizzle);
708 GetRectangleVertices(spec, swizzled_size[0], swizzled_size[1],
709 swizzle, signs, vertices);
712 const Vector3f translation = spec.rotation * SwizzleVector3f(
713 Vector3f(0.f, 0.f, 0.5f * signs[2] * swizzled_size[2] * spec.scale),
717 for (
int i = 0; i < 4; ++i)
723 static const size_t kNumVertices = 6 * 4;
724 VertexPTN verts[kNumVertices];
731 return BuildBufferObject(spec, kNumVertices, verts);
737 static const size_t kNumFaces = 6;
738 static const size_t kNumIndices = kNumFaces * 6;
739 uint16 indices[kNumIndices];
740 for (uint16 i = 0; i < kNumFaces; ++i) {
741 indices[6 * i + 0] =
static_cast<uint16
>(4 * i + 0);
742 indices[6 * i + 1] =
static_cast<uint16
>(4 * i + 1);
743 indices[6 * i + 2] =
static_cast<uint16
>(4 * i + 2);
744 indices[6 * i + 3] =
static_cast<uint16
>(4 * i + 0);
745 indices[6 * i + 4] =
static_cast<uint16
>(4 * i + 2);
746 indices[6 * i + 5] =
static_cast<uint16
>(4 * i + 3);
748 return BuildIndexBuffer(spec, kNumIndices, indices);
760 struct EllipsoidData {
767 static const EllipsoidData GetEllipsoidData(
const EllipsoidSpec& spec) {
771 data.band_count = std::max(static_cast<size_t>(2), spec.band_count);
772 data.sector_count = std::max(static_cast<size_t>(3), spec.sector_count);
775 data.vertices_per_ring = data.sector_count + 1;
779 data.vertex_count = (data.band_count + 1U) * data.vertices_per_ring;
786 const EllipsoidSpec& spec) {
790 const EllipsoidData data = GetEllipsoidData(spec);
791 const bool has_tex_coords = HasTextureCoordinates(spec);
792 const bool has_normals = HasNormals(spec);
793 base::AllocVector<VertexPTN> vertices(allocator, data.vertex_count,
797 base::AllocVector<Point2f> ring_points(allocator, data.vertices_per_ring,
799 GetPartialCirclePoints(data.sector_count,
800 spec.longitude_start,
807 const Vector3f
scale = 0.5f * spec.size;
808 const Vector3f inv_scale = 1.0f /
scale;
817 const Anglef delta_angle = (spec.latitude_end - spec.latitude_start)
818 / static_cast<float>(data.band_count);
819 size_t cur_vertex = 0;
820 for (
size_t ring = 0; ring <= data.band_count; ++ring) {
821 const Anglef latitude_angle = spec.latitude_end -
822 delta_angle *
static_cast<float>(ring);
823 const float ring_radius = cosf(latitude_angle.Radians());
824 const float sphere_y = sinf(latitude_angle.Radians());
826 for (
size_t s = 0; s <= data.sector_count; ++s) {
827 VertexPTN& v = vertices[cur_vertex];
831 const Point2f& ring_pt = ring_points[s];
832 const Vector3f sphere_pt_vec(ring_radius * -ring_pt[1],
834 ring_radius * -ring_pt[0]);
835 v.position = spec.rotation * ((scale * sphere_pt_vec) * spec.scale) +
839 if (has_tex_coords) {
840 const float ts =
static_cast<float>(s) /
841 static_cast<float>(data.sector_count);
842 const float tt =
static_cast<float>(data.band_count - ring) /
843 static_cast<float>(data.band_count);
844 v.texture_coords.Set(ts, tt);
856 DCHECK_EQ(cur_vertex, data.vertex_count);
858 return BuildBufferObject(spec, vertices.size(), &vertices[0]);
863 const EllipsoidSpec& spec) {
864 const EllipsoidData data = GetEllipsoidData(spec);
868 const size_t index_count = 6U * data.band_count * data.sector_count;
869 base::AllocVector<uint16> indices(GetShortTermAllocator(spec.allocator),
870 index_count, static_cast<uint16>(0));
872 size_t cur_index = 0;
873 const uint16 ring_offset =
static_cast<uint16
>(data.vertices_per_ring);
874 for (uint16 band = 0; band < data.band_count; ++band) {
875 const uint16 first_band_vertex =
static_cast<uint16
>(band * ring_offset);
876 for (uint16 s = 0; s < data.sector_count; ++s) {
877 const uint16 v =
static_cast<uint16
>(first_band_vertex + s);
878 indices[cur_index + 0] = v;
879 indices[cur_index + 1] =
static_cast<uint16
>(v + ring_offset);
880 indices[cur_index + 2] =
static_cast<uint16
>(v + 1U);
881 indices[cur_index + 3] =
static_cast<uint16
>(v + 1U);
882 indices[cur_index + 4] =
static_cast<uint16
>(v + ring_offset);
883 indices[cur_index + 5] =
static_cast<uint16
>(v + ring_offset + 1U);
884 DCHECK_LE(indices[cur_index + 5U], data.vertex_count);
890 return BuildIndexBuffer(spec, index_count, &indices[0]);
902 struct CylinderData {
915 static const CylinderData GetCylinderData(
const CylinderSpec& spec) {
918 data.add_top_cap = spec.has_top_cap && spec.top_radius != 0.f;
919 data.add_bottom_cap = spec.has_bottom_cap && spec.bottom_radius != 0.f;
921 data.num_caps = (data.add_top_cap ? 1 : 0) + (data.add_bottom_cap ? 1 : 0);
924 data.shaft_band_count = std::max(static_cast<size_t>(1),
925 spec.shaft_band_count);
926 data.cap_band_count = std::max(static_cast<size_t>(1), spec.cap_band_count);
927 data.sector_count = std::max(static_cast<size_t>(3), spec.sector_count);
930 data.vertices_per_ring = data.sector_count + 1;
932 data.shaft_vertex_count =
933 (data.shaft_band_count + 1) * data.vertices_per_ring;
936 data.cap_vertex_count = 1U + data.cap_band_count * data.vertices_per_ring;
940 data.shaft_vertex_count + data.num_caps * data.cap_vertex_count;
948 static void GetCylinderShaftNormals(
949 size_t count,
const Point2f ring_points[],
float top_radius,
950 float bottom_radius,
float height, Vector3f shaft_normals[]) {
951 if (top_radius == bottom_radius) {
953 for (
size_t i = 0; i < count; ++i) {
954 const Point2f& ring_pt = ring_points[i];
965 if (top_radius < bottom_radius) {
966 base_radius = bottom_radius;
967 apex_y = height + (top_radius * height) / (bottom_radius - top_radius);
969 base_radius = top_radius;
970 apex_y = -(height + (bottom_radius * height) /
971 (top_radius - bottom_radius));
981 const float base_radius_squared =
math::Square(base_radius);
982 const float ny = base_radius_squared / apex_y;
986 const float inv_length = 1.f /
math::Sqrt(base_radius_squared + ny * ny);
988 for (
size_t i = 0; i < count; ++i) {
989 const Point2f& ring_pt = ring_points[i];
990 shaft_normals[i] = inv_length * Vector3f(base_radius * -ring_pt[1], ny,
991 base_radius * -ring_pt[0]);
997 static size_t AddCylinderCapVertices(
const CylinderSpec& spec,
998 const Point2f ring_points[],
bool is_top,
999 VertexPTN* vertices) {
1000 const Vector3f normal =
1001 spec.rotation * (is_top ? Vector3f::AxisY() : -Vector3f::AxisY());
1002 const Vector3f scale =
1003 is_top ? Vector3f(spec.top_radius, spec.height, spec.top_radius)
1004 : Vector3f(spec.bottom_radius, spec.height, spec.bottom_radius);
1005 const bool has_tex_coords = HasTextureCoordinates(spec);
1006 const bool has_normals = HasNormals(spec);
1007 const CylinderData data = GetCylinderData(spec);
1008 const float y = is_top ? .5f : -.5f;
1010 size_t cur_vertex = 0;
1013 VertexPTN& center_v = vertices[0];
1015 spec.rotation * ((scale * Vector3f(0.f, y, 0.f)) * spec.scale) +
1018 center_v.texture_coords.Set(.5f, .5f);
1023 const float delta_radius = 1.f /
static_cast<float>(data.cap_band_count);
1024 const float s_scale = .5f;
1025 const float t_scale = is_top ? -.5f : .5f;
1026 for (
size_t ring = 0; ring < data.cap_band_count; ++ring) {
1027 radius += delta_radius;
1028 for (
size_t s = 0; s <= data.sector_count; ++s) {
1029 VertexPTN& v = vertices[cur_vertex];
1030 const Point2f& ring_pt = ring_points[s];
1034 const Vector3f pt_vec(radius * -ring_pt[1], y, -radius * ring_pt[0]);
1036 spec.rotation * ((scale * pt_vec) * spec.scale) + spec.translation;
1041 v.texture_coords.Set(.5f + s_scale * pt_vec[0],
1042 .5f + t_scale * pt_vec[2]);
1050 for (
size_t i = 0; i < cur_vertex; ++i)
1051 vertices[i].normal = normal;
1059 static size_t AddCylinderCapIndices(
1060 const CylinderData& data,
size_t start_index,
bool invert_orientation,
1063 const uint16 center_index =
static_cast<uint16
>(start_index);
1064 size_t cur_index = 0;
1067 const int i0 = invert_orientation ? 1 : 0;
1068 const int i1 = 1 - i0;
1071 for (uint16 s = 0; s < data.sector_count; ++s) {
1072 const uint16 v =
static_cast<uint16
>(center_index + 1U + s);
1073 indices[cur_index + 0] = center_index;
1074 indices[cur_index + 1 + i0] = v;
1075 indices[cur_index + 1 + i1] =
static_cast<uint16
>(v + 1U);
1080 const uint16 ring_offset =
static_cast<uint16
>(data.vertices_per_ring);
1081 uint16 first_band_vertex =
static_cast<uint16
>(center_index + 1U);
1082 for (uint16 band = 1; band < data.cap_band_count; ++band) {
1083 for (uint16 s = 0; s < data.sector_count; ++s) {
1084 const uint16 v =
static_cast<uint16
>(first_band_vertex + s);
1085 indices[cur_index + 0] = v;
1086 indices[cur_index + 1 + i0] =
static_cast<uint16
>(v + ring_offset);
1087 indices[cur_index + 1 + i1] =
static_cast<uint16
>(v + 1U);
1088 indices[cur_index + 3] =
static_cast<uint16
>(v + 1U);
1089 indices[cur_index + 4 + i0] =
static_cast<uint16
>(v + ring_offset);
1090 indices[cur_index + 4 + i1] =
static_cast<uint16
>(v + ring_offset + 1U);
1091 DCHECK_LE(indices[cur_index + 4], data.vertex_count);
1092 DCHECK_LE(indices[cur_index + 5], data.vertex_count);
1095 first_band_vertex =
static_cast<uint16
>(first_band_vertex + ring_offset);
1102 const CylinderSpec& spec) {
1106 const CylinderData data = GetCylinderData(spec);
1107 const bool has_tex_coords = HasTextureCoordinates(spec);
1108 const bool has_normals = HasNormals(spec);
1109 base::AllocVector<VertexPTN> vertices(allocator, data.vertex_count,
1113 base::AllocVector<Point2f> ring_points(allocator, data.vertices_per_ring,
1115 GetCirclePoints(data.sector_count, &ring_points[0]);
1118 base::AllocVector<Vector3f> shaft_normals(allocator, data.vertices_per_ring,
1120 GetCylinderShaftNormals(data.vertices_per_ring, &ring_points[0],
1121 spec.top_radius, spec.bottom_radius, spec.height,
1125 const float delta_y = 1.f /
static_cast<float>(data.shaft_band_count);
1126 const float delta_radius = (spec.top_radius - spec.bottom_radius) /
1127 static_cast<float>(data.shaft_band_count);
1129 float ring_radius = spec.top_radius;
1130 size_t cur_vertex = 0;
1131 for (
size_t ring = 0; ring <= data.shaft_band_count; ++ring) {
1132 const float ring_t = ring_y + .5f;
1134 const Vector3f
scale(ring_radius, spec.height, ring_radius);
1135 for (
size_t s = 0; s <= data.sector_count; ++s) {
1136 VertexPTN& v = vertices[cur_vertex];
1137 const Point2f& ring_pt = ring_points[s];
1140 const Vector3f shaft_pt_vec(-ring_pt[1], ring_y, -ring_pt[0]);
1141 v.position = spec.rotation * ((scale * shaft_pt_vec) * spec.scale) +
1145 v.texture_coords.Set(static_cast<float>(s) /
1146 static_cast<float>(data.sector_count), ring_t);
1149 v.normal = spec.rotation * shaft_normals[s];
1154 ring_radius -= delta_radius;
1158 if (data.add_top_cap)
1159 cur_vertex += AddCylinderCapVertices(spec, &ring_points[0],
true,
1160 &vertices[cur_vertex]);
1161 if (data.add_bottom_cap)
1162 cur_vertex += AddCylinderCapVertices(spec, &ring_points[0],
false,
1163 &vertices[cur_vertex]);
1165 DCHECK_EQ(cur_vertex, data.vertex_count);
1167 return BuildBufferObject(spec, vertices.size(), &vertices[0]);
1172 const CylinderSpec& spec) {
1173 const CylinderData data = GetCylinderData(spec);
1177 const size_t shaft_index_count =
1178 6U * data.shaft_band_count * data.sector_count;
1181 const size_t cap_index_count =
1182 3U * data.sector_count +
1183 6U * data.sector_count * (data.cap_band_count - 1U);
1184 const size_t index_count =
1185 shaft_index_count + data.num_caps * cap_index_count;
1186 base::AllocVector<uint16> indices(GetShortTermAllocator(spec.allocator),
1187 index_count, static_cast<uint16>(0));
1189 size_t cur_index = 0;
1192 const uint16 ring_offset =
static_cast<uint16
>(data.vertices_per_ring);
1193 for (uint16 band = 0; band < data.shaft_band_count; ++band) {
1194 const uint16 first_band_vertex =
static_cast<uint16
>(band * ring_offset);
1195 for (uint16 s = 0; s < data.sector_count; ++s) {
1196 const uint16 v =
static_cast<uint16
>(first_band_vertex + s);
1197 indices[cur_index + 0] = v;
1198 indices[cur_index + 1] =
static_cast<uint16
>(v + ring_offset);
1199 indices[cur_index + 2] =
static_cast<uint16
>(v + 1U);
1200 indices[cur_index + 3] =
static_cast<uint16
>(v + 1U);
1201 indices[cur_index + 4] =
static_cast<uint16
>(v + ring_offset);
1202 indices[cur_index + 5] =
static_cast<uint16
>(v + ring_offset + 1U);
1203 DCHECK_LE(indices[cur_index + 5U], data.vertex_count);
1209 size_t first_cap_vertex = data.shaft_vertex_count;
1210 if (data.add_top_cap) {
1211 cur_index += AddCylinderCapIndices(data, first_cap_vertex,
false,
1212 &indices[cur_index]);
1213 first_cap_vertex += data.cap_vertex_count;
1216 if (data.add_bottom_cap) {
1217 cur_index += AddCylinderCapIndices(data, first_cap_vertex,
true,
1218 &indices[cur_index]);
1219 first_cap_vertex += data.cap_vertex_count;
1223 return BuildIndexBuffer(spec, index_count, &indices[0]);
1240 if (tri_index_buffer.
Get()) {
1242 const size_t tri_index_count = tri_index_buffer->GetCount();
1244 if (tri_index_count % 3U == 0U && tri_data.
Get() && tri_data->GetData()) {
1246 const size_t line_index_count = 2U * tri_index_count;
1254 line_data = TriIndicesToLineIndices<uint8>(
1255 tri_data, tri_index_count, line_index_count, al);
1257 line_data = TriIndicesToLineIndices<uint16>(
1258 tri_data, tri_index_count, line_index_count, al);
1260 if (line_data.
Get()) {
1262 line_index_buffer->AddSpec(spec.
type, 1, 0);
1263 line_index_buffer->SetData(line_data, tri_index_buffer->GetStructSize(),
1265 tri_index_buffer->GetUsageMode());
1269 return line_index_buffer;
1275 LoadExternalShapeData(spec.
format, in, &mesh);
1278 if (mesh.mIndices.empty() || mesh.mVertices.empty())
1283 shape->SetLabel(
"External geometry");
1285 shape->SetAttributeArray(BuildAttributeArray(spec, buffer_object));
1286 shape->SetIndexBuffer(BuildExternalIndexBuffer(spec, mesh));
1292 shape->SetLabel(
"Rectangle");
1294 shape->SetAttributeArray(
1295 BuildAttributeArray(spec, BuildRectangleBufferObject(spec)));
1296 shape->SetIndexBuffer(BuildRectangleIndexBuffer(spec));
1301 DCHECK_LE(3, spec.
sides) <<
"Polygons must have at least 3 sides";
1303 shape->SetLabel(
"Polygon");
1305 shape->SetAttributeArray(
1306 BuildAttributeArray(spec, BuildRegularPolygonBufferObject(spec)));
1312 shape->SetLabel(
"Box");
1314 shape->SetAttributeArray(
1315 BuildAttributeArray(spec, BuildBoxBufferObject(spec)));
1316 shape->SetIndexBuffer(BuildBoxIndexBuffer(spec));
1322 shape->SetLabel(
"Ellipsoid");
1324 shape->SetAttributeArray(
1325 BuildAttributeArray(spec, BuildEllipsoidBufferObject(spec)));
1326 shape->SetIndexBuffer(BuildEllipsoidIndexBuffer(spec));
1332 shape->SetLabel(
"Cylinder");
1334 shape->SetAttributeArray(
1335 BuildAttributeArray(spec, BuildCylinderBufferObject(spec)));
1336 shape->SetIndexBuffer(BuildCylinderIndexBuffer(spec));
bool IsInvalidReference(const T &value)
IsInvalidReference() returns true if a passed const reference of type T has an address of InvalidRefe...
kShortTerm is used for objects that are very transient in nature, such as scratch memory used to comp...
ComponentType type
The type of each component.
bool Swizzle(const VectorBase< InDimension, T > &input, const char *swizzle_string, VectorBase< OutDimension, T > *output)
Computes the result of swizzling a Vector or Point (or anything else derived from VectorBase)...
Angle< float > Anglef
Type-specific typedefs.
An IndexBuffer is a type of BufferObject that contains the element indices of an array, e.g., a vertex index array.
#define LOG(severity)
Logs the streamed message unconditionally with a severity of severity.
size_t byte_offset
The offset of the element defined by this Spec in the data type.
Matrix< 3, float > Matrix3f
virtual const AllocatorPtr & GetAllocatorForLifetime(AllocationLifetime lifetime) const
Returns the correct Allocator to use to allocate memory with a specific lifetime. ...
External geometry formats.
const gfx::ShapePtr BuildEllipsoidShape(const EllipsoidSpec &spec)
Builds and returns a Shape representing an axis-aligned ellipsoid.
T Sqrt(const T &val)
Returns the square root of a value.
SharedPtr< Allocator > AllocatorPtr
size_t shaft_vertex_count
base::ReferentPtr< IndexBuffer >::Type IndexBufferPtr
T * Get() const
Returns a raw pointer to the instance, which may be NULL.
const gfx::ShapePtr BuildCylinderShape(const CylinderSpec &spec)
Builds and returns a Shape representing an axis-aligned cylinder.
const gfx::IndexBufferPtr BuildWireframeIndexBuffer(const gfx::IndexBufferPtr &tri_index_buffer)
Public functions.
Range< 3, float > Range3f
const gfx::ShapePtr LoadExternalShape(const ExternalShapeSpec &spec, std::istream &in)
Loads a Shape with the specified format from the passed stream.
A Shape object represents a shape (vertices + indices) to draw.
const gfx::ShapePtr BuildRegularPolygonShape(const RegularPolygonSpec &spec)
Builds and returns a Shape representing a flat regular polygon.
Format
The set of external geometry file formats that can be read with LoadExternalShape().
const Vector< Dimension, T > Normalized(const Vector< Dimension, T > &v)
Returns a unit-length version of a Vector.
const gfx::ShapePtr BuildBoxShape(const BoxSpec &spec)
Builds and returns a Shape representing an axis-aligned box.
Copyright 2016 Google Inc.
#define DCHECK_EQ(val1, val2)
base::ReferentPtr< AttributeArray >::Type AttributeArrayPtr
Convenience typedef for shared pointer to a AttributeArray.
PlaneNormal
This enum specifies the principal Cartesian plane containing the rectangle by its directed normal...
#define DCHECK_LE(val1, val2)
const T Square(const T &val)
Squares a value.
static DataContainerPtr CreateAndCopy(const T *data, size_t count, bool is_wipeable, const AllocatorPtr &container_and_data_allocator)
See class comment for documentation.
base::ReferentPtr< DataContainer >::Type DataContainerPtr
base::ReferentPtr< BufferObject >::Type BufferObjectPtr
Convenience typedef for shared pointer to a BufferObject.
base::AllocatorPtr allocator
A SharedPtr is a smart shared pointer to an instance of some class that implements reference counting...
const gfx::ShapePtr BuildRectangleShape(const RectangleSpec &spec)
Builds and returns a Shape representing a rectangle in one of the principal Cartesian planes...
static const AllocatorPtr & GetDefaultAllocatorForLifetime(AllocationLifetime lifetime)