Skip to content

Commit

Permalink
introduce suite of offline conformance tests using doctest
Browse files Browse the repository at this point in the history
  • Loading branch information
ddiakopoulos committed Jan 25, 2020
1 parent 7503f89 commit 0cf271a
Show file tree
Hide file tree
Showing 5 changed files with 6,514 additions and 112 deletions.
9 changes: 7 additions & 2 deletions CMakeLists.txt
Expand Up @@ -6,9 +6,10 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

project(tinyply LANGUAGES CXX)
set(PROJECT_VERSION 2.2)
set(PROJECT_VERSION 2.3)

include_directories("${CMAKE_SOURCE_DIR}/source")
include_directories("${CMAKE_SOURCE_DIR}/third-party")

set(CMAKE_DEBUG_POSTFIX "d")

Expand All @@ -21,10 +22,14 @@ else()
add_library(tinyply STATIC source/tinyply.cpp source/tinyply.h)
endif()

# Example
# Example Application
add_executable(example source/example.cpp)
target_link_libraries(example PRIVATE tinyply)

# Test Application
add_executable(tests source/tests.cpp)
target_link_libraries(tests PRIVATE tinyply)

# pkg-config support
set(generated_dir "${CMAKE_CURRENT_BINARY_DIR}/generated")
if(UNIX)
Expand Down
124 changes: 124 additions & 0 deletions source/example-utils.hpp
@@ -0,0 +1,124 @@
// This software is in the public domain. Where that dedication is not
// recognized, you are granted a perpetual, irrevocable license to copy,
// distribute, and modify this file as you see fit.
// https://github.com/ddiakopoulos/tinyply

// This file is only required for the example and test programs.

#pragma once

#ifndef tinyply_example_utils_hpp
#define tinyply_example_utils_hpp

#include <thread>
#include <chrono>
#include <vector>
#include <sstream>
#include <fstream>
#include <iostream>
#include <cstring>
#include <iterator>

inline std::vector<uint8_t> read_file_binary(const std::string & pathToFile)
{
std::ifstream file(pathToFile, std::ios::binary);
std::vector<uint8_t> fileBufferBytes;

if (file.is_open())
{
file.seekg(0, std::ios::end);
size_t sizeBytes = file.tellg();
file.seekg(0, std::ios::beg);
fileBufferBytes.resize(sizeBytes);
if (file.read((char*)fileBufferBytes.data(), sizeBytes)) return fileBufferBytes;
}
else throw std::runtime_error("could not open binary ifstream to path " + pathToFile);
return fileBufferBytes;
}

struct memory_buffer : public std::streambuf
{
char * p_start {nullptr};
char * p_end {nullptr};
size_t size;

memory_buffer(char const * first_elem, size_t size)
: p_start(const_cast<char*>(first_elem)), p_end(p_start + size), size(size)
{
setg(p_start, p_start, p_end);
}

pos_type seekoff(off_type off, std::ios_base::seekdir dir, std::ios_base::openmode which) override
{
if (dir == std::ios_base::cur) gbump(static_cast<int>(off));
else setg(p_start, (dir == std::ios_base::beg ? p_start : p_end) + off, p_end);
return gptr() - p_start;
}

pos_type seekpos(pos_type pos, std::ios_base::openmode which) override
{
return seekoff(pos, std::ios_base::beg, which);
}
};

struct memory_stream : virtual memory_buffer, public std::istream
{
memory_stream(char const * first_elem, size_t size)
: memory_buffer(first_elem, size), std::istream(static_cast<std::streambuf*>(this)) {}
};

class manual_timer
{
std::chrono::high_resolution_clock::time_point t0;
double timestamp{ 0.f };
public:
void start() { t0 = std::chrono::high_resolution_clock::now(); }
void stop() { timestamp = std::chrono::duration<float>(std::chrono::high_resolution_clock::now() - t0).count() * 1000; }
const double & get() { return timestamp; }
};

struct float2 { float x, y; };
struct float3 { float x, y, z; };
struct double3 { double x, y, z; };
struct uint3 { uint32_t x, y, z; };
struct uint4 { uint32_t x, y, z, w; };

struct geometry
{
std::vector<float3> vertices;
std::vector<float3> normals;
std::vector<float2> texcoords;
std::vector<uint3> triangles;
};

inline geometry make_cube_geometry()
{
geometry cube;

const struct CubeVertex { float3 position, normal; float2 texCoord; } verts[] = {
{ { -1, -1, -1 },{ -1, 0, 0 },{ 0, 0 } },{ { -1, -1, +1 },{ -1, 0, 0 },{ 1, 0 } },{ { -1, +1, +1 },{ -1, 0, 0 },{ 1, 1 } },{ { -1, +1, -1 },{ -1, 0, 0 },{ 0, 1 } },
{ { +1, -1, +1 },{ +1, 0, 0 },{ 0, 0 } },{ { +1, -1, -1 },{ +1, 0, 0 },{ 1, 0 } },{ { +1, +1, -1 },{ +1, 0, 0 },{ 1, 1 } },{ { +1, +1, +1 },{ +1, 0, 0 },{ 0, 1 } },
{ { -1, -1, -1 },{ 0, -1, 0 },{ 0, 0 } },{ { +1, -1, -1 },{ 0, -1, 0 },{ 1, 0 } },{ { +1, -1, +1 },{ 0, -1, 0 },{ 1, 1 } },{ { -1, -1, +1 },{ 0, -1, 0 },{ 0, 1 } },
{ { +1, +1, -1 },{ 0, +1, 0 },{ 0, 0 } },{ { -1, +1, -1 },{ 0, +1, 0 },{ 1, 0 } },{ { -1, +1, +1 },{ 0, +1, 0 },{ 1, 1 } },{ { +1, +1, +1 },{ 0, +1, 0 },{ 0, 1 } },
{ { -1, -1, -1 },{ 0, 0, -1 },{ 0, 0 } },{ { -1, +1, -1 },{ 0, 0, -1 },{ 1, 0 } },{ { +1, +1, -1 },{ 0, 0, -1 },{ 1, 1 } },{ { +1, -1, -1 },{ 0, 0, -1 },{ 0, 1 } },
{ { -1, +1, +1 },{ 0, 0, +1 },{ 0, 0 } },{ { -1, -1, +1 },{ 0, 0, +1 },{ 1, 0 } },{ { +1, -1, +1 },{ 0, 0, +1 },{ 1, 1 } },{ { +1, +1, +1 },{ 0, 0, +1 },{ 0, 1 } }};

std::vector<uint4> quads = { { 0, 1, 2, 3 },{ 4, 5, 6, 7 },{ 8, 9, 10, 11 },{ 12, 13, 14, 15 },{ 16, 17, 18, 19 },{ 20, 21, 22, 23 } };

for (auto & q : quads)
{
cube.triangles.push_back({ q.x,q.y,q.z });
cube.triangles.push_back({ q.x,q.z,q.w });
}

for (int i = 0; i < 24; ++i)
{
cube.vertices.push_back(verts[i].position);
cube.normals.push_back(verts[i].normal);
cube.texcoords.push_back(verts[i].texCoord);
}

return cube;
}

#endif
111 changes: 1 addition & 110 deletions source/example.cpp
Expand Up @@ -9,119 +9,10 @@
// treats the file format as structured data, it's up to you to copy or move the parsed data
// into your application-specific data structures (e.g. float3, vec3, etc).

#include <thread>
#include <chrono>
#include <vector>
#include <sstream>
#include <fstream>
#include <iostream>
#include <cstring>
#include <iterator>

#include "tinyply.h"
using namespace tinyply;

inline std::vector<uint8_t> read_file_binary(const std::string & pathToFile)
{
std::ifstream file(pathToFile, std::ios::binary);
std::vector<uint8_t> fileBufferBytes;

if (file.is_open())
{
file.seekg(0, std::ios::end);
size_t sizeBytes = file.tellg();
file.seekg(0, std::ios::beg);
fileBufferBytes.resize(sizeBytes);
if (file.read((char*)fileBufferBytes.data(), sizeBytes)) return fileBufferBytes;
}
else throw std::runtime_error("could not open binary ifstream to path " + pathToFile);
return fileBufferBytes;
}

struct memory_buffer : public std::streambuf
{
char * p_start {nullptr};
char * p_end {nullptr};
size_t size;

memory_buffer(char const * first_elem, size_t size)
: p_start(const_cast<char*>(first_elem)), p_end(p_start + size), size(size)
{
setg(p_start, p_start, p_end);
}

pos_type seekoff(off_type off, std::ios_base::seekdir dir, std::ios_base::openmode which) override
{
if (dir == std::ios_base::cur) gbump(static_cast<int>(off));
else setg(p_start, (dir == std::ios_base::beg ? p_start : p_end) + off, p_end);
return gptr() - p_start;
}

pos_type seekpos(pos_type pos, std::ios_base::openmode which) override
{
return seekoff(pos, std::ios_base::beg, which);
}
};

struct memory_stream : virtual memory_buffer, public std::istream
{
memory_stream(char const * first_elem, size_t size)
: memory_buffer(first_elem, size), std::istream(static_cast<std::streambuf*>(this)) {}
};

class manual_timer
{
std::chrono::high_resolution_clock::time_point t0;
double timestamp{ 0.f };
public:
void start() { t0 = std::chrono::high_resolution_clock::now(); }
void stop() { timestamp = std::chrono::duration<float>(std::chrono::high_resolution_clock::now() - t0).count() * 1000; }
const double & get() { return timestamp; }
};

struct float2 { float x, y; };
struct float3 { float x, y, z; };
struct double3 { double x, y, z; };
struct uint3 { uint32_t x, y, z; };
struct uint4 { uint32_t x, y, z, w; };

struct geometry
{
std::vector<float3> vertices;
std::vector<float3> normals;
std::vector<float2> texcoords;
std::vector<uint3> triangles;
};

inline geometry make_cube_geometry()
{
geometry cube;

const struct CubeVertex { float3 position, normal; float2 texCoord; } verts[] = {
{ { -1, -1, -1 },{ -1, 0, 0 },{ 0, 0 } },{ { -1, -1, +1 },{ -1, 0, 0 },{ 1, 0 } },{ { -1, +1, +1 },{ -1, 0, 0 },{ 1, 1 } },{ { -1, +1, -1 },{ -1, 0, 0 },{ 0, 1 } },
{ { +1, -1, +1 },{ +1, 0, 0 },{ 0, 0 } },{ { +1, -1, -1 },{ +1, 0, 0 },{ 1, 0 } },{ { +1, +1, -1 },{ +1, 0, 0 },{ 1, 1 } },{ { +1, +1, +1 },{ +1, 0, 0 },{ 0, 1 } },
{ { -1, -1, -1 },{ 0, -1, 0 },{ 0, 0 } },{ { +1, -1, -1 },{ 0, -1, 0 },{ 1, 0 } },{ { +1, -1, +1 },{ 0, -1, 0 },{ 1, 1 } },{ { -1, -1, +1 },{ 0, -1, 0 },{ 0, 1 } },
{ { +1, +1, -1 },{ 0, +1, 0 },{ 0, 0 } },{ { -1, +1, -1 },{ 0, +1, 0 },{ 1, 0 } },{ { -1, +1, +1 },{ 0, +1, 0 },{ 1, 1 } },{ { +1, +1, +1 },{ 0, +1, 0 },{ 0, 1 } },
{ { -1, -1, -1 },{ 0, 0, -1 },{ 0, 0 } },{ { -1, +1, -1 },{ 0, 0, -1 },{ 1, 0 } },{ { +1, +1, -1 },{ 0, 0, -1 },{ 1, 1 } },{ { +1, -1, -1 },{ 0, 0, -1 },{ 0, 1 } },
{ { -1, +1, +1 },{ 0, 0, +1 },{ 0, 0 } },{ { -1, -1, +1 },{ 0, 0, +1 },{ 1, 0 } },{ { +1, -1, +1 },{ 0, 0, +1 },{ 1, 1 } },{ { +1, +1, +1 },{ 0, 0, +1 },{ 0, 1 } }};

std::vector<uint4> quads = { { 0, 1, 2, 3 },{ 4, 5, 6, 7 },{ 8, 9, 10, 11 },{ 12, 13, 14, 15 },{ 16, 17, 18, 19 },{ 20, 21, 22, 23 } };

for (auto & q : quads)
{
cube.triangles.push_back({ q.x,q.y,q.z });
cube.triangles.push_back({ q.x,q.z,q.w });
}

for (int i = 0; i < 24; ++i)
{
cube.vertices.push_back(verts[i].position);
cube.normals.push_back(verts[i].normal);
cube.texcoords.push_back(verts[i].texCoord);
}

return cube;
}
#include "example-utils.hpp"

void write_ply_example(const std::string & filename)
{
Expand Down

0 comments on commit 0cf271a

Please sign in to comment.