Skip to content

Commit

Permalink
C99 shared library build and API example. #80
Browse files Browse the repository at this point in the history
  • Loading branch information
jpcy committed Sep 30, 2020
1 parent e73b7c9 commit fbb9b4a
Show file tree
Hide file tree
Showing 4 changed files with 218 additions and 22 deletions.
156 changes: 156 additions & 0 deletions extra/example_c99.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
/*
MIT License
Copyright (c) 2018-2020 Jonathan Young
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
/*
example
This example shows how to use the xatlas API to generate a unique set of texture coordinates.
Input: an .obj model file.
Output:
* an .obj model file (example_output.obj). This is simplistic for example purposes, it doesn't copy materials from the input .obj file.
* texture coordinates rasterized to images, colored by chart (example_charts*.tga) and by triangle (example_tris*.tga).
*/
#include <assert.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "../xatlas_c.h"
#include "objzero/objzero.h"

#ifdef _MSC_VER
#define STRICMP _stricmp
#include <windows.h>
static CRITICAL_SECTION s_progressMutex;
#else
#include <strings.h>
#define STRICMP strcasecmp
#endif

static bool s_verbose = false;

static int Print(const char *format, ...)
{
va_list arg;
va_start(arg, format);
printf("\r"); // Clear progress text.
const int result = vprintf(format, arg);
va_end(arg);
return result;
}

// May be called from any thread.
static bool ProgressCallback(xatlasProgressCategory category, int progress, void *userData)
{
(void)userData;
// Don't interupt verbose printing.
if (s_verbose)
return true;
#ifdef _MSC_VER
EnterCriticalSection(&s_progressMutex);
#endif
printf("\r %s [", xatlasProgressCategoryString(category));
for (int i = 0; i < 10; i++)
printf(progress / ((i + 1) * 10) ? "*" : " ");
printf("] %d%%", progress);
fflush(stdout);
if (progress == 100)
printf("\n");
#ifdef _MSC_VER
LeaveCriticalSection(&s_progressMutex);
#endif
return true;
}

int main(int argc, char *argv[])
{
#ifdef _MSC_VER
InitializeCriticalSection(&s_progressMutex);
#endif
if (argc < 2) {
printf("Usage: %s input_file.obj [options]\n", argv[0]);
printf(" Options:\n");
printf(" -verbose\n");
return 1;
}
s_verbose = (argc >= 3 && STRICMP(argv[2], "-verbose") == 0);
// Load object file.
printf("Loading '%s'...\n", argv[1]);
objz_setIndexFormat(OBJZ_INDEX_FORMAT_U32);
objzModel *model = objz_load(argv[1]);
if (!model) {
printf("%s\n", objz_getError());
return EXIT_FAILURE;
}
if (objz_getError()) // Print warnings.
printf("%s\n", objz_getError());
// Create empty atlas.
xatlasSetPrint(Print, s_verbose);
xatlasAtlas *atlas = xatlasCreate();
// Set progress callback.
xatlasSetProgressCallback(atlas, ProgressCallback, NULL);
// Add mesh to atlas.
const uint32_t vertexStride = (uint32_t)(sizeof(float) * 8);
xatlasMeshDecl meshDecl;
xatlasMeshDeclInit(&meshDecl);
meshDecl.vertexCount = model->numVertices;
meshDecl.vertexPositionData = model->vertices;
meshDecl.vertexPositionStride = vertexStride;
if (model->flags & OBJZ_FLAG_NORMALS) {
meshDecl.vertexNormalData = (float *)model->vertices + 5;
meshDecl.vertexNormalStride = vertexStride;
}
if (model->flags & OBJZ_FLAG_TEXCOORDS) {
meshDecl.vertexUvData = (float *)model->vertices + 3;
meshDecl.vertexUvStride = vertexStride;
}
meshDecl.indexCount = model->numIndices;
meshDecl.indexData = model->indices;
meshDecl.indexFormat = XATLAS_INDEX_FORMAT_UINT32;
xatlasAddMeshError error = xatlasAddMesh(atlas, &meshDecl, 1);
if (error != XATLAS_ADD_MESH_ERROR_SUCCESS) {
xatlasDestroy(atlas);
printf("\rError adding mesh: %s\n", xatlasAddMeshErrorString(error));
return EXIT_FAILURE;
}
xatlasAddMeshJoin(atlas); // Not necessary. Only called here so geometry totals are printed after the AddMesh progress indicator.
printf(" %u total vertices\n", meshDecl.vertexCount);
printf(" %u total faces\n", meshDecl.indexCount / 3);
// Generate atlas.
printf("Generating atlas\n");
xatlasGenerate(atlas, NULL, NULL);
printf(" %d charts\n", atlas->chartCount);
printf(" %d atlases\n", atlas->atlasCount);
for (uint32_t i = 0; i < atlas->atlasCount; i++)
printf(" %d: %0.2f%% utilization\n", i, atlas->utilization[i] * 100.0f);
printf(" %ux%u resolution\n", atlas->width, atlas->height);
printf(" %u total vertices\n", atlas->meshes[0].vertexCount);
// Cleanup.
xatlasDestroy(atlas);
objz_destroy(model);
printf("Done\n");
return EXIT_SUCCESS;
}
22 changes: 18 additions & 4 deletions extra/projects.lua
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,21 @@ project "example"
sanitizer()
files "example.cpp"
includedirs(THIRDPARTY_DIR)
links { "stb_image_write", "tiny_obj_loader", "xatlas" }
links { "stb_image_write", "tiny_obj_loader", "xatlas_static" }
filter "action:vs*"
files "xatlas.natvis"
filter "system:linux"
links { "pthread" }

project "example_c99"
kind "ConsoleApp"
language "C"
cdialect "C99"
warnings "Extra"
sanitizer()
files "example_c99.c"
includedirs(THIRDPARTY_DIR)
links { "objzero", "xatlas" }
filter "action:vs*"
files "xatlas.natvis"
filter "system:linux"
Expand All @@ -38,7 +52,7 @@ project "example_uvmesh"
sanitizer()
files "example_uvmesh.cpp"
includedirs(THIRDPARTY_DIR)
links { "stb_image_write", "tiny_obj_loader", "xatlas" }
links { "stb_image_write", "tiny_obj_loader", "xatlas_static" }
filter "action:vs*"
files "xatlas.natvis"
filter "system:linux"
Expand All @@ -54,7 +68,7 @@ project "test"
sanitizer()
includedirs(THIRDPARTY_DIR)
files "test.cpp"
links { "tiny_obj_loader", "xatlas" }
links { "tiny_obj_loader", "xatlas_static" }
filter "action:vs*"
files "xatlas.natvis"
filter "system:linux"
Expand Down Expand Up @@ -84,7 +98,7 @@ project "viewer"
path.join(OIDN_DIR, "include"),
OPENFBX_DIR
}
links { "bgfx", "bimg", "bx", "cgltf", "enkiTS", "glfw", "imgui", "mimalloc", "nativefiledialog", "objzero", "OpenFBX", "stb_image", "stb_image_resize", "xatlas" }
links { "bgfx", "bimg", "bx", "cgltf", "enkiTS", "glfw", "imgui", "mimalloc", "nativefiledialog", "objzero", "OpenFBX", "stb_image", "stb_image_resize", "xatlas_static" }
filter "system:windows"
links { "bcrypt", "gdi32", "ole32", "psapi", "uuid"}
filter "system:linux"
Expand Down
14 changes: 13 additions & 1 deletion premake5.lua
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ solution "xatlas"
end
sanitizer()

project "xatlas"
project "xatlas_static"
kind "StaticLib"
language "C++"
cppdialect "C++11"
Expand All @@ -97,4 +97,16 @@ project "xatlas"
files { "xatlas.cpp", "xatlas.h", "xatlas_c.h" }
sanitizer()

project "xatlas"
kind "SharedLib"
language "C++"
cppdialect "C++11"
exceptionhandling "Off"
rtti "Off"
warnings "Extra"
enablewarnings { "shadow" }
defines { "XATLAS_EXPORT_API=1" }
files { "xatlas.cpp", "xatlas.h", "xatlas_c.h" }
sanitizer()

dofile("extra/projects.lua")
48 changes: 31 additions & 17 deletions xatlas_c.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,26 @@ Copyright NVIDIA Corporation 2006 -- Ignacio Castano <icastano@nvidia.com>
#pragma once
#ifndef XATLAS_C_H
#define XATLAS_C_H
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>

#ifdef __cplusplus
extern "C" {
#endif

#ifndef XATLAS_EXPORT_API
#define XATLAS_EXPORT_API 0
#endif

#ifndef XATLAS_API
#if XATLAS_EXPORT_API
#define XATLAS_API __declspec(dllexport)
#else
#define XATLAS_API
#endif
#endif

typedef enum
{
XATLAS_CHART_TYPE_PLANAR,
Expand Down Expand Up @@ -195,23 +209,23 @@ typedef void *(*xatlasReallocFunc)(void *, size_t);
typedef void (*xatlasFreeFunc)(void *);
typedef int (*xatlasPrintFunc)(const char *, ...);

xatlasAtlas *xatlasCreate();
void xatlasDestroy(xatlasAtlas *atlas);
xatlasAddMeshError xatlasAddMesh(xatlasAtlas *atlas, const xatlasMeshDecl *meshDecl, uint32_t meshCountHint);
void xatlasAddMeshJoin(xatlasAtlas *atlas);
xatlasAddMeshError xatlasAddUvMesh(xatlasAtlas *atlas, const xatlasUvMeshDecl *decl);
void xatlasComputeCharts(xatlasAtlas *atlas, const xatlasChartOptions *chartOptions);
void xatlasPackCharts(xatlasAtlas *atlas, const xatlasPackOptions *packOptions);
void xatlasGenerate(xatlasAtlas *atlas, const xatlasChartOptions *chartOptions, const xatlasPackOptions *packOptions);
void xatlasSetProgressCallback(xatlasAtlas *atlas, xatlasProgressFunc progressFunc, void *progressUserData);
void xatlasSetAlloc(xatlasReallocFunc reallocFunc, xatlasFreeFunc freeFunc);
void xatlasSetPrint(xatlasPrintFunc print, bool verbose);
const char *xatlasAddMeshErrorString(xatlasAddMeshError error);
const char *xatlasProgressCategoryString(xatlasProgressCategory category);
void xatlasMeshDeclInit(xatlasMeshDecl *meshDecl);
void xatlasUvMeshDeclInit(xatlasUvMeshDecl *uvMeshDecl);
void xatlasChartOptionsInit(xatlasChartOptions *chartOptions);
void xatlasPackOptionsInit(xatlasPackOptions *packOptions);
XATLAS_API xatlasAtlas *xatlasCreate();
XATLAS_API void xatlasDestroy(xatlasAtlas *atlas);
XATLAS_API xatlasAddMeshError xatlasAddMesh(xatlasAtlas *atlas, const xatlasMeshDecl *meshDecl, uint32_t meshCountHint);
XATLAS_API void xatlasAddMeshJoin(xatlasAtlas *atlas);
XATLAS_API xatlasAddMeshError xatlasAddUvMesh(xatlasAtlas *atlas, const xatlasUvMeshDecl *decl);
XATLAS_API void xatlasComputeCharts(xatlasAtlas *atlas, const xatlasChartOptions *chartOptions);
XATLAS_API void xatlasPackCharts(xatlasAtlas *atlas, const xatlasPackOptions *packOptions);
XATLAS_API void xatlasGenerate(xatlasAtlas *atlas, const xatlasChartOptions *chartOptions, const xatlasPackOptions *packOptions);
XATLAS_API void xatlasSetProgressCallback(xatlasAtlas *atlas, xatlasProgressFunc progressFunc, void *progressUserData);
XATLAS_API void xatlasSetAlloc(xatlasReallocFunc reallocFunc, xatlasFreeFunc freeFunc);
XATLAS_API void xatlasSetPrint(xatlasPrintFunc print, bool verbose);
XATLAS_API const char *xatlasAddMeshErrorString(xatlasAddMeshError error);
XATLAS_API const char *xatlasProgressCategoryString(xatlasProgressCategory category);
XATLAS_API void xatlasMeshDeclInit(xatlasMeshDecl *meshDecl);
XATLAS_API void xatlasUvMeshDeclInit(xatlasUvMeshDecl *uvMeshDecl);
XATLAS_API void xatlasChartOptionsInit(xatlasChartOptions *chartOptions);
XATLAS_API void xatlasPackOptionsInit(xatlasPackOptions *packOptions);

#ifdef __cplusplus
} // extern "C"
Expand Down

0 comments on commit fbb9b4a

Please sign in to comment.