loader_aw

Load OBJ/MTL file formats
git clone git://git.meso-star.fr/loader_aw.git
Log | Files | Refs | README | LICENSE

commit 4cb8077cfd37657217d60412a68681edbf0a0eea
parent 4a522ac3e4a2ac5ab339b9c9ede62c44d1ca97c8
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Wed, 18 Oct 2023 11:51:29 +0200

Merge remote-tracking branch 'origin/feature_posix_make' into develop

Diffstat:
M.gitignore | 15+++++++++------
AMakefile | 151++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
MREADME.md | 50+++++++++++++++++++++++++++-----------------------
Aaw.pc.in | 10++++++++++
Dcmake/CMakeLists.txt | 93-------------------------------------------------------------------------------
Aconfig.mk | 75+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amake.sh | 70++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/aw.c | 2+-
Msrc/aw.h | 20+++++++++++++++++++-
Msrc/aw_c.h | 2+-
Msrc/aw_mtl.c | 2+-
Msrc/aw_obj.c | 29++++++++++++++++++++++++++++-
Msrc/test_aw.c | 2+-
Msrc/test_aw_mtl.c | 8++++----
Msrc/test_aw_obj.c | 94++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
15 files changed, 486 insertions(+), 137 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -1,11 +1,14 @@ .gitignore -CMakeCache.txt -CMakeFiles -Makefile -tmp [Bb]uild* *.sw[po] -*.[ao] +*.[aod] +*.so *~ +test* +!test*.[ch] +.test +.config tags - +aw.pc +aw-local.pc +*.mtl diff --git a/Makefile b/Makefile @@ -0,0 +1,151 @@ +# Copyright (C) 2014-2017, 2020-2023 Vincent Forest (vaplv@free.fr) +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +.POSIX: +.SUFFIXES: # Clean up default inference rules + +include config.mk + +LIBNAME_STATIC = libaw.a +LIBNAME_SHARED = libaw.so +LIBNAME = $(LIBNAME_$(LIB_TYPE)) + +################################################################################ +# Library building +################################################################################ +SRC = src/aw.c src/aw_obj.c src/aw_mtl.c +OBJ = $(SRC:.c=.o) +DEP = $(SRC:.c=.d) + +build_library: .config $(DEP) + @$(MAKE) -fMakefile $$(for i in $(DEP); do echo -f $${i}; done) \ + $$(if [ -n "$(LIBNAME)" ]; then\ + echo "$(LIBNAME)";\ + else\ + echo "$(LIBNAME_SHARED)";\ + fi) + +$(DEP) $(OBJ): config.mk + +$(LIBNAME_SHARED): $(OBJ) + $(CC) $(CFLAGS_SO) $(RSYS_CFLAGS) -o $@ $(OBJ) $(LDFLAGS_SO) $(RSYS_LIBS) + +$(LIBNAME_STATIC): libaw.o + $(AR) -rc $@ $? + $(RANLIB) $@ + +libaw.o: $(OBJ) + $(LD) -r $(OBJ) -o $@ + $(OBJCOPY) $(OCPFLAGS) $@ + +.config: Makefile config.mk + @if ! $(PKG_CONFIG) --atleast-version $(RSYS_VERSION) rsys; then \ + echo "rsys $(RSYS_VERSION) not found"; exit 1; fi + @echo "config done" > .config + +.SUFFIXES: .c .d .o +.c.d: + @$(CC) $(CFLAGS_SO) $(RSYS_CFLAGS) -MM -MT "$(@:.d=.o) $@" $< -MF $@ + +.c.o: + $(CC) $(CFLAGS_SO) $(RSYS_CFLAGS) -DAW_SHARED_BUILD -c $< -o $@ + +################################################################################ +# Installation +################################################################################ +pkg: + sed -e 's#@PREFIX@#$(PREFIX)#g' \ + -e 's#@VERSION@#$(VERSION)#g' \ + -e 's#@RSYS_VERSION@#$(RSYS_VERSION)#g' \ + aw.pc.in > aw.pc + +aw-local.pc: aw.pc.in + sed -e '1d'\ + -e 's#^includedir=.*#includedir=./src/#'\ + -e 's#^libdir=.*#libdir=./#'\ + -e 's#@VERSION@#$(VERSION)#g'\ + -e 's#@RSYS_VERSION@#$(RSYS_VERSION)#g' \ + aw.pc.in > $@ + +install: build_library pkg + @$(SHELL) make.sh install "$(DESTDIR)$(PREFIX)/lib" $(LIBNAME) + @$(SHELL) make.sh install "$(DESTDIR)$(PREFIX)/lib/pkgconfig" aw.pc + @$(SHELL) make.sh install "$(DESTDIR)$(PREFIX)/include" src/aw.h + @$(SHELL) make.sh install "$(DESTDIR)$(PREFIX)/share/doc/aw"\ + COPYING README.md + +uninstall: + rm -f "$(DESTDIR)$(PREFIX)/lib/$(LIBNAME)" + rm -f "$(DESTDIR)$(PREFIX)/lib/pkgconfig/aw.pc" + rm -f "$(DESTDIR)$(PREFIX)/include/aw.h" + rm -f "$(DESTDIR)$(PREFIX)/share/doc/aw/COPYING" + rm -f "$(DESTDIR)$(PREFIX)/share/doc/aw/README.md" + +################################################################################ +# Miscellaneous targets +################################################################################ +all: build_library build_tests + +clean: clean_test + rm -f $(OBJ) $(TEST_OBJ) $(LIBNAME) + rm -f .config .test aw.pc aw-local.pc libaw.o + +distclean: clean + rm -f $(DEP) $(TEST_DEP) + +lint: + shellcheck -o all make.sh + +################################################################################ +# Tests +################################################################################ +TEST_SRC =\ + src/test_aw.c\ + src/test_aw_mtl.c\ + src/test_aw_obj.c +TEST_OBJ = $(TEST_SRC:.c=.o) +TEST_DEP = $(TEST_SRC:.c=.d) + +PKG_CONFIG_LOCAL = PKG_CONFIG_PATH="./:$${PKG_CONFIG_PATH}" $(PKG_CONFIG) +AW_CFLAGS = $$($(PKG_CONFIG_LOCAL) $(PCFLAGS) --cflags aw-local.pc) +AW_LIBS = $$($(PKG_CONFIG_LOCAL) $(PCFLAGS) --libs aw-local.pc) + +build_tests: build_library $(TEST_DEP) .test + @$(MAKE) -fMakefile -f.test $$(for i in $(TEST_DEP); do echo -f"$${i}"; done) test_bin + +test: build_tests + @$(SHELL) make.sh run_test src/test_aw_mtl.c src/test_aw_obj.c + +.test: Makefile make.sh + @$(SHELL) make.sh config_test $(TEST_SRC) > $@ + +clean_test: + rm -f test_cbox.obj test_obj_cube.obj test_obj_plane.obj test_obj_squares.obj + rm -f mtl0.mtl test_mtl_common.mtl test_mtl_multi.mtl + $(SHELL) make.sh clean_test $(TEST_SRC) + +$(TEST_DEP) $(TEST_OBJ): config.mk aw-local.pc + +$(TEST_DEP): + @$(CC) $(CFLAGS_EXE) $(AW_CFLAGS) $(RSYS_CFLAGS) -MM -MT "$(@:.d=.o) $@" $(@:.d=.c) -MF $@ + +$(TEST_OBJ): + $(CC) $(CFLAGS_EXE) $(AW_CFLAGS) $(RSYS_CFLAGS) -c $(@:.o=.c) -o $@ + +test_aw \ +test_aw_mtl \ +test_aw_obj \ +: config.mk aw-local.pc $(LIBNAME) + $(CC) $(CFLAGS_EXE) -o $@ src/$@.o $(LDFLAGS_EXE) $(AW_LIBS) $(RSYS_LIBS) diff --git a/README.md b/README.md @@ -1,30 +1,33 @@ # Loader of the Alias Wafefront obj and mtl file formats -This C89 code base loads the Alias Wavefront +AW is a C library whose purpose is to load the Alias Wavefront [`obj`](http://www.martinreddy.net/gfx/3d/OBJ.spec) and -[`mtl`](http://www.fileformat.info/format/material/) file formats. Note that -only a subset of these formats are currently supported. +[`mtl`](http://www.fileformat.info/format/material/) file formats. Only a +subset of these formats are currently supported. -For `obj` files, polygonal primitives with their per vertex position, normal +For `obj` files, polygonal primitives with their per vertex-position, normal and texture coordinates are loaded. Smooth, common and material groupings are -also correctly handled. +also handled correctly. -For `mtl` files, the ambient, diffuse, specular, glossiness and transmissive RGB -or XYZ colors are supported. In addition, it loads the refraction index and the -illumination model. It also handles the ambient, diffuse, specular, glossiness and -bump textures as well as their attributes (blend< u|v \>, color correction, -channel mapping, texcoord < offset|scale|turbulence \>, image resolution and bump -multiplier). +For `mtl` files, ambient, diffuse, specular, glossiness and transmissive RGB or +XYZ colors are supported. Additionally, it loads the refraction index and the +illumination model. The library also loads the filename of ambient, diffuse, +specular, glossiness and bump textures and their attributes (blend< u|v \>, +color correction, channel mapping, texcoord < offset|scale|turbulence \>, image +resolution and bump multiplier). -## How to build +## Requirements -The library uses [CMake](http://www.cmake.org) and the -[RCMake](https://gitlab.com/vaplv/rcmake/#tab-readme) package to build. It also -depends on the [RSys](https://gitlab.com/vaplv/rsys/#tab-readme) library. First, -install the RCMake package and the RSys library. Then, generate the project -from the cmake/CMakeLists.txt file by appending the RCMake and RSys -install directories to the `CMAKE_PREFIX_PATH` variable. The resulting project -can be edited, built, tested and installed as any CMake project. +- C compiler +- POSIX make +- pkg-config +- [RSys](https://gitlab.com/vaplv/rsys/) + +## Installation + +Edit config.mk as needed, then run: + + make clean install ## Release notes @@ -67,7 +70,8 @@ Full review and refactoring of the code. ## License -Copyright (C) 2014-2017, 2020, 2021 Vincent Forest (vaplv@free.fr). AW is free -software released under GPL v3+ license: GNU GPL version 3 or later. You are -welcome to redistribute it under certain conditions; refer to the COPYING file -for details. +Copyright (C) 2014-2017, 2020-2023 Vincent Forest (vaplv@free.fr) + +AW is free software released under GPL v3+ license: GNU GPL version 3 or later. +You are welcome to redistribute it under certain conditions; refer to the +COPYING file for details. diff --git a/aw.pc.in b/aw.pc.in @@ -0,0 +1,10 @@ +prefix=@PREFIX@ +includedir=${prefix}/include +libdir=${prefix}/lib + +Requires: rsys >= @RSYS_VERSION@ +Name: AW +Description: AW library +Version: @VERSION@ +Libs: -L${libdir} -law +CFlags: -I${includedir} diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -1,93 +0,0 @@ -# Copyright (C) 2014-2017, 2020, 2021 Vincent Forest (vaplv@free.fr) -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. - -cmake_minimum_required(VERSION 3.1) -project(aw C) -cmake_policy(SET CMP0011 NEW) -enable_testing() - -option(NO_TEST "Do not compile the test pograms" OFF) - -set(AW_SOURCE_DIR ${PROJECT_SOURCE_DIR}/../src) - -################################################################################ -# Dependencies -################################################################################ -find_package(RCMake 0.4 REQUIRED) -find_package(RSys 0.9 REQUIRED) - -set(CMAKE_MODULE_PATH ${RCMAKE_SOURCE_DIR}) -include(rcmake) -include(rcmake_runtime) -rcmake_append_runtime_dirs(_runtime_dirs RSys) - -################################################################################ -# Define targets -################################################################################ -set(VERSION_MAJOR 2) -set(VERSION_MINOR 0) -set(VERSION_PATCH 1) -set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}) - -set(AW_FILES_SRC aw_c.h aw.c aw_obj.c aw_mtl.c) -set(AW_FILES_INC aw.h) -set(AW_FILES_DOC COPYING README.md) -rcmake_prepend_path(AW_FILES_SRC ${AW_SOURCE_DIR}) -rcmake_prepend_path(AW_FILES_INC ${AW_SOURCE_DIR}) -rcmake_prepend_path(AW_FILES_DOC ${PROJECT_SOURCE_DIR}/../) - -add_library(aw SHARED ${AW_FILES_SRC} ${AW_FILES_INC}) -set_target_properties(aw PROPERTIES - DEFINE_SYMBOL AW_SHARED_BUILD - VERSION ${VERSION} - SOVERSION ${VERSION_MAJOR}) -target_link_libraries(aw RSys) - -if(MSVC) - # The CL compiler does not support the strtok_r POSIX function but proposes - # the strtok_s function that have the same profile and does the same thing. - set_target_properties(aw PROPERTIES COMPILE_FLAGS "/Dstrtok_r=strtok_s") -endif(MSVC) - -rcmake_setup_devel(aw AW ${VERSION} aw_version.h) - -################################################################################ -# Define tests -################################################################################ -if(NOT NO_TEST) - add_executable(test_aw_obj ${AW_SOURCE_DIR}/test_aw_obj.c) - target_link_libraries(test_aw_obj aw) - add_test(test_aw_obj test_aw_obj) - rcmake_set_test_runtime_dirs(test_aw_obj _runtime_dirs) - - add_executable(test_aw_mtl ${AW_SOURCE_DIR}/test_aw_mtl.c) - target_link_libraries(test_aw_mtl aw) - add_test(test_aw_mtl test_aw_mtl) - rcmake_set_test_runtime_dirs(test_aw_mtl _runtime_dirs) - - add_executable(test_aw ${AW_SOURCE_DIR}/test_aw.c) - target_link_libraries(test_aw aw) -endif(NOT NO_TEST) - -################################################################################ -# Install directories -################################################################################ -install(TARGETS aw - ARCHIVE DESTINATION bin - LIBRARY DESTINATION lib - RUNTIME DESTINATION bin) -install(FILES ${AW_FILES_INC} DESTINATION include) -install(FILES ${AW_FILES_DOC} DESTINATION share/doc/aw) - diff --git a/config.mk b/config.mk @@ -0,0 +1,75 @@ +VERSION = 2.1.0 +PREFIX = /usr/local + +LIB_TYPE = SHARED +#LIB_TYPE = STATIC + +BUILD_TYPE = RELEASE +#BUILD_TYPE = DEBUG + +################################################################################ +# Tools +################################################################################ +AR = ar +CC = cc +LD = ld +PKG_CONFIG = pkg-config +OBJCOPY = objcopy +RANLIB = ranlib + +################################################################################ +# Dependencies +################################################################################ +PCFLAGS_STATIC = --static +PCFLAGS = $(PCFLAGS_$(LIB_TYPE)) + +RSYS_VERSION = 0.14 +RSYS_CFLAGS = $$($(PKG_CONFIG) $(PCFLAGS) --cflags rsys) +RSYS_LIBS = $$($(PKG_CONFIG) $(PCFLAGS) --libs rsys) + +################################################################################ +# Compilation options +################################################################################ +WFLAGS =\ + -Wall\ + -Wcast-align\ + -Wconversion\ + -Wextra\ + -Wmissing-declarations\ + -Wmissing-prototypes\ + -Wshadow + +CFLAGS_HARDENED =\ + -D_FORTIFY_SOURCES=2\ + -fcf-protection=full\ + -fstack-clash-protection\ + -fstack-protector-strong + +CFLAGS_COMMON=\ + -std=c89\ + -pedantic\ + -fvisibility=hidden\ + -fstrict-aliasing\ + $(CFLAGS_HARDENED)\ + $(WFLAGS) + +CFLAGS_RELEASE = -O2 -DNDEBUG $(CFLAGS_COMMON) +CFLAGS_DEBUG = -g $(CFLAGS_COMMON) +CFLAGS = $(CFLAGS_$(BUILD_TYPE)) +CFLAGS_SO = $(CFLAGS) -fPIC +CFLAGS_EXE = $(CFLAGS) -fPIE + +################################################################################ +# Linker options +################################################################################ +LDFLAGS_HARDENED = -Wl,-z,relro,-z,now +LDFLAGS_DEBUG = $(LDFLAGS_HARDENED) +LDFLAGS_RELEASE = -s $(LDFLAGS_HARDENED) +LDFLAGS = $(LDFLAGS_$(BUILD_TYPE)) + +LDFLAGS_SO = $(LDFLAGS) -shared -Wl,--no-undefined +LDFLAGS_EXE = $(LDFLAGS) -pie + +OCPFLAGS_DEBUG = --localize-hidden +OCPFLAGS_RELEASE = --localize-hidden --strip-unneeded +OCPFLAGS = $(OCPFLAGS_$(BUILD_TYPE)) diff --git a/make.sh b/make.sh @@ -0,0 +1,70 @@ +#!/bin/sh + +# Copyright (C) 2014-2017, 2020-2023 Vincent Forest (vaplv@free.fr) +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +set -e + +config_test() +{ + for i in "$@"; do + test=$(basename "${i}" ".c") + test_list="${test_list} ${test}" + printf "%s: src/%s.o\n" "${test}" "${test}" + done + printf "test_bin: %s\n" "${test_list}" +} + +run_test() +{ + for i in "$@"; do + test=$(basename "${i}" ".c") + + printf "%s " "${test}" + if ./"${test}" > /dev/null 2>&1; then + printf "\033[1;32mOK\033[m\n" + else + printf "\033[1;31mError\033[m\n" + fi + done 2> /dev/null +} + +clean_test() +{ + for i in "$@"; do + rm -f "$(basename "${i}" ".c")" + done +} + +install() +{ + prefix=$1 + shift 1 + + mkdir -p "${prefix}" + + for i in "$@"; do + dst="${prefix}/${i##*/}" + + if cmp -s "${i}" "${dst}"; then + printf "Up to date %s\n" "${dst}" + else + printf "Installing %s\n" "${dst}" + cp "${i}" "${prefix}" + fi + done +} + +"$@" diff --git a/src/aw.c b/src/aw.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2014-2017, 2020, 2021 Vincent Forest (vaplv@free.fr) +/* Copyright (C) 2014-2017, 2020-2023 Vincent Forest (vaplv@free.fr) * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/aw.h b/src/aw.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2014-2017, 2020, 2021 Vincent Forest (vaplv@free.fr) +/* Copyright (C) 2014-2017, 2020-2023 Vincent Forest (vaplv@free.fr) * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -58,6 +58,9 @@ enum aw_map_channel { struct aw_obj_desc { size_t faces_count; + size_t positions_count; + size_t normals_count; + size_t texcoords_count; size_t groups_count; size_t smooth_groups_count; size_t usemtls_count; @@ -222,6 +225,21 @@ aw_obj_get_vertex_data const struct aw_obj_vertex* vertex, struct aw_obj_vertex_data* vertex_data); +AW_API res_T +aw_obj_get_positions + (const struct aw_obj* obj, + const double** positions); /* List of double 4 */ + +AW_API res_T +aw_obj_get_texcoords + (const struct aw_obj* obj, + const double** texcoords); /* List of double 3 */ + +AW_API res_T +aw_obj_get_normals + (const struct aw_obj* obj, + const double** normals); /* List of double 3 */ + /******************************************************************************* * Mtl functions ******************************************************************************/ diff --git a/src/aw_c.h b/src/aw_c.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2014-2017, 2020, 2021 Vincent Forest (vaplv@free.fr) +/* Copyright (C) 2014-2017, 2020-2023 Vincent Forest (vaplv@free.fr) * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/aw_mtl.c b/src/aw_mtl.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2014-2017, 2020, 2021 Vincent Forest (vaplv@free.fr) +/* Copyright (C) 2014-2017, 2020-2023 Vincent Forest (vaplv@free.fr) * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/aw_obj.c b/src/aw_obj.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2014-2017, 2020, 2021 Vincent Forest (vaplv@free.fr) +/* Copyright (C) 2014-2017, 2020-2023 Vincent Forest (vaplv@free.fr) * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -816,6 +816,9 @@ aw_obj_get_desc(const struct aw_obj* obj, struct aw_obj_desc* desc) if(!obj || !desc) return RES_BAD_ARG; desc->faces_count = darray_face_size_get(&obj->faces); + desc->positions_count = darray_double_size_get(&obj->positions) / 4; + desc->normals_count = darray_double_size_get(&obj->normals) / 3; + desc->texcoords_count = darray_double_size_get(&obj->texcoords) / 3; desc->groups_count = darray_named_group_size_get(&obj->groups); desc->smooth_groups_count = darray_smooth_group_size_get(&obj->smooth_groups); desc->usemtls_count = darray_named_group_size_get(&obj->usemtls); @@ -970,6 +973,30 @@ error: goto exit; } +res_T +aw_obj_get_positions(const struct aw_obj* obj, const double** positions) +{ + if(!obj || !positions) return RES_BAD_ARG; + *positions = darray_double_cdata_get(&obj->positions); + return RES_OK; +} + +res_T +aw_obj_get_texcoords(const struct aw_obj* obj, const double** texcoords) +{ + if(!obj || !texcoords) return RES_BAD_ARG; + *texcoords = darray_double_cdata_get(&obj->texcoords); + return RES_OK; +} + +res_T +aw_obj_get_normals(const struct aw_obj* obj, const double** normals) +{ + if(!obj || !normals) return RES_BAD_ARG; + *normals = darray_double_cdata_get(&obj->normals); + return RES_OK; +} + #ifdef COMPILER_CL #pragma warning(pop) #endif diff --git a/src/test_aw.c b/src/test_aw.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2014-2017, 2020, 2021 Vincent Forest (vaplv@free.fr) +/* Copyright (C) 2014-2017, 2020-2023 Vincent Forest (vaplv@free.fr) * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/test_aw_mtl.c b/src/test_aw_mtl.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2014-2017, 2020, 2021 Vincent Forest (vaplv@free.fr) +/* Copyright (C) 2014-2017, 2020-2023 Vincent Forest (vaplv@free.fr) * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -58,7 +58,7 @@ test_common(struct aw_mtl* mtl) file = fopen("test_mtl_common.mtl", "w"); CHK(file != NULL); fwrite(mtl_common, sizeof(char), strlen(mtl_common), file); - fclose(file); + CHK(fclose(file) == 0); CHK(aw_mtl_load(NULL, NULL) == RES_BAD_ARG); CHK(aw_mtl_load(mtl, NULL) == RES_BAD_ARG); @@ -278,7 +278,7 @@ test_multiple_materials(struct aw_mtl* mtl) CHK(!mat.bump_map.filename); CHK(!mat.specular_exponent_map.filename); - fclose(file); + CHK(fclose(file) == 0); } static void @@ -303,7 +303,7 @@ test_unloadable(struct aw_mtl* mtl) file = fopen("mtl0.mtl", "w"); CHK(file != NULL); fwrite(mtl0, sizeof(char), strlen(mtl0), file); - fclose(file); + CHK(fclose(file) == 0); CHK(aw_mtl_load(mtl, "mtl0.mtl") == RES_BAD_ARG); CHK(aw_mtl_get_materials_count(mtl, &nmtls) == RES_OK); diff --git a/src/test_aw_obj.c b/src/test_aw_obj.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2014-2017, 2020, 2021 Vincent Forest (vaplv@free.fr) +/* Copyright (C) 2014-2017, 2020-2023 Vincent Forest (vaplv@free.fr) * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -50,6 +50,7 @@ test_plane(struct aw_obj* obj) struct aw_obj_named_group mtl; struct aw_obj_vertex vertex; struct aw_obj_vertex_data vdata; + const double* data = NULL; FILE* file; const char* mtllib; @@ -58,7 +59,7 @@ test_plane(struct aw_obj* obj) file = fopen("test_obj_plane.obj", "w"); CHK(file != NULL); fwrite(plane_obj, sizeof(char), strlen(plane_obj), file); - fclose(file); + CHK(fclose(file) == 0); CHK(aw_obj_load(obj, NULL) == RES_BAD_ARG); CHK(aw_obj_load(NULL, "test_obj_plane.obj") == RES_BAD_ARG); @@ -70,6 +71,9 @@ test_plane(struct aw_obj* obj) CHK(aw_obj_get_desc(NULL, &desc) == RES_BAD_ARG); CHK(aw_obj_get_desc(obj, &desc) == RES_OK); CHK(desc.faces_count == 1); + CHK(desc.positions_count == 4); + CHK(desc.texcoords_count == 4); + CHK(desc.normals_count == 0); CHK(desc.groups_count == 1); CHK(desc.smooth_groups_count == 0); CHK(desc.usemtls_count == 1); @@ -143,6 +147,22 @@ test_plane(struct aw_obj* obj) CHK(!strcmp(group.name, "default")); CHK(group.face_id == 0); CHK(group.faces_count == 1); + + CHK(aw_obj_get_positions(NULL, &data) == RES_BAD_ARG); + CHK(aw_obj_get_positions(obj, NULL) == RES_BAD_ARG); + CHK(aw_obj_get_positions(obj, &data) == RES_OK); + CHK(d4_eq(data+0, d4(v4,0,2,0,1))); + CHK(d4_eq(data+4, d4(v4,0,0,0,1))); + CHK(d4_eq(data+8, d4(v4,2,0,0,1))); + CHK(d4_eq(data+12, d4(v4,2,2,0,1))); + + CHK(aw_obj_get_texcoords(NULL, &data) == RES_BAD_ARG); + CHK(aw_obj_get_texcoords(obj, NULL) == RES_BAD_ARG); + CHK(aw_obj_get_texcoords(obj, &data) == RES_OK); + CHK(d3_eq(data+0, d3(v4,0,1,0))); + CHK(d3_eq(data+3, d3(v4,0,0,0))); + CHK(d3_eq(data+6, d3(v4,1,0,0))); + CHK(d3_eq(data+9, d3(v4,1,1,0))); } static void @@ -178,6 +198,7 @@ test_squares(struct aw_obj* obj) struct aw_obj_smooth_group sgroup; struct aw_obj_vertex vertex; struct aw_obj_vertex_data vdata; + const double* data = NULL; FILE* file; CHK(obj != NULL); @@ -185,11 +206,14 @@ test_squares(struct aw_obj* obj) file = fopen("test_obj_squares.obj", "w"); CHK(file != NULL); fwrite(squares_obj, sizeof(char), strlen(squares_obj), file); - fclose(file); + CHK(fclose(file) == 0); CHK(aw_obj_load(obj, "test_obj_squares.obj") == RES_OK); CHK(aw_obj_get_desc(obj, &desc) == RES_OK); CHK(desc.faces_count == 2); + CHK(desc.positions_count == 6); + CHK(desc.texcoords_count == 0); + CHK(desc.normals_count == 6); CHK(desc.groups_count == 1); CHK(desc.smooth_groups_count == 1); CHK(desc.usemtls_count == 0); @@ -260,6 +284,24 @@ test_squares(struct aw_obj* obj) CHK(sgroup.faces_count == 2); CHK(aw_obj_get_mtl(obj, 0, &mtl) == RES_BAD_ARG); + + CHK(aw_obj_get_positions(obj, &data) == RES_OK); + CHK(d4_eq(data+0, d4(v4,0,2,0,1))); + CHK(d4_eq(data+4, d4(v4,0,0,0,1))); + CHK(d4_eq(data+8, d4(v4,2,0,0,1))); + CHK(d4_eq(data+12, d4(v4,2,2,0,1))); + CHK(d4_eq(data+16, d4(v4,4,0,-1.255298,1))); + CHK(d4_eq(data+20, d4(v4,4,2,-1.255298,1))); + + CHK(aw_obj_get_normals(NULL, &data) == RES_BAD_ARG); + CHK(aw_obj_get_normals(obj, NULL) == RES_BAD_ARG); + CHK(aw_obj_get_normals(obj, &data) == RES_OK); + CHK(d3_eq(data+0, d3(v4,0,0,1))); + CHK(d3_eq(data+3, d3(v4,0,0,1))); + CHK(d3_eq(data+6, d3(v4,0.276597,0,0.960986))); + CHK(d3_eq(data+9, d3(v4,0.276597,0,0.960986))); + CHK(d3_eq(data+12, d3(v4,0.531611,0,0.846988))); + CHK(d3_eq(data+15, d3(v4,0.531611,0,0.846988))); } static void @@ -297,6 +339,7 @@ test_cube(struct aw_obj* obj) "usemtl purple\n" "f 2 6 7 3\n" "# 6 elements\n"; + double v4[4]; const char* group_names[6] = { "front", "back", "right", "top", "left", "bottom" }; const char* mtl_names[6] = @@ -304,6 +347,7 @@ test_cube(struct aw_obj* obj) struct aw_obj_desc desc; FILE* file; const char* mtllib; + const double* data; size_t i; CHK(obj != NULL); @@ -319,6 +363,9 @@ test_cube(struct aw_obj* obj) CHK(aw_obj_get_desc(obj, &desc) == RES_OK); CHK(desc.faces_count == 6); + CHK(desc.positions_count == 8); + CHK(desc.texcoords_count == 0); + CHK(desc.normals_count == 0); CHK(desc.groups_count == 6); CHK(desc.smooth_groups_count == 0); CHK(desc.usemtls_count == 6); @@ -371,6 +418,16 @@ test_cube(struct aw_obj* obj) CHK(!strcmp(mtllib, "my.mtl")); CHK(aw_obj_get_mtllib(obj, 3, &mtllib) == RES_BAD_ARG); + CHK(aw_obj_get_positions(obj, &data) == RES_OK); + CHK(d4_eq(data+0, d4(v4,0,2,2,1))); + CHK(d4_eq(data+4, d4(v4,0,0,2,1))); + CHK(d4_eq(data+8, d4(v4,2,0,2,1))); + CHK(d4_eq(data+12, d4(v4,2,2,2,1))); + CHK(d4_eq(data+16, d4(v4,0,2,0,1))); + CHK(d4_eq(data+20, d4(v4,0,0,0,1))); + CHK(d4_eq(data+24, d4(v4,2,0,0,1))); + CHK(d4_eq(data+28, d4(v4,2,2,0,1))); + CHK(aw_obj_purge(NULL) == RES_BAD_ARG); CHK(aw_obj_purge(obj) == RES_OK); CHK(aw_obj_get_desc(obj, &desc) == RES_OK); @@ -380,7 +437,7 @@ test_cube(struct aw_obj* obj) CHK(desc.usemtls_count == 0); CHK(desc.mtllibs_count == 0); - fclose(file); + CHK(fclose(file) == 0); } static void @@ -433,7 +490,9 @@ test_cbox(struct aw_obj* obj) struct aw_obj_vertex_data vdata; struct aw_obj_named_group group; struct aw_obj_named_group mtl; + double v4[4]; double tmp[3]; + const double* data; FILE* file; CHK(obj != NULL); @@ -443,10 +502,13 @@ test_cbox(struct aw_obj* obj) fwrite(cbox_obj, sizeof(char), strlen(cbox_obj), file); CHK(fseek(file, 0, SEEK_SET) == 0); CHK(aw_obj_load_stream(obj, file, "cbox") == RES_OK); - fclose(file); + CHK(fclose(file) == 0); CHK(aw_obj_get_desc(obj, &desc) == RES_OK); CHK(desc.faces_count == 5); + CHK(desc.positions_count == 20); + CHK(desc.texcoords_count == 0); + CHK(desc.normals_count == 0); CHK(desc.groups_count == 5); CHK(desc.smooth_groups_count == 0); CHK(desc.usemtls_count == 5); @@ -538,6 +600,28 @@ test_cbox(struct aw_obj* obj) CHK(aw_obj_get_vertex(obj, 19, &vertex) == RES_OK); CHK(aw_obj_get_vertex_data(obj, &vertex, &vdata) == RES_OK); CHK(d3_eq_eps(vdata.position, d3(tmp, -1.02, 1.99, 0.99), 1.e-6)); + + CHK(aw_obj_get_positions(obj, &data) == RES_OK); + CHK(d4_eq(data+0, d4(v4,-1.01,0,0.99,1))); + CHK(d4_eq(data+4, d4(v4,1,0,0.99,1))); + CHK(d4_eq(data+8, d4(v4,1,0,-1.04,1))); + CHK(d4_eq(data+12, d4(v4,-0.99,0,-1.04,1))); + CHK(d4_eq(data+16, d4(v4,-1.02,1.99,0.99,1))); + CHK(d4_eq(data+20, d4(v4,-1.02,1.99,-1.04,1))); + CHK(d4_eq(data+24, d4(v4,1,1.99,-1.04,1))); + CHK(d4_eq(data+28, d4(v4,1,1.99,0.99,1))); + CHK(d4_eq(data+32, d4(v4,-0.99,0,-1.04,1))); + CHK(d4_eq(data+36, d4(v4,1,0,-1.04,1))); + CHK(d4_eq(data+40, d4(v4,1,1.99,-1.04,1))); + CHK(d4_eq(data+44, d4(v4,-1.02,1.99,-1.04,1))); + CHK(d4_eq(data+48, d4(v4,1,0,-1.04,1))); + CHK(d4_eq(data+52, d4(v4,1,0,0.99,1))); + CHK(d4_eq(data+56, d4(v4,1,1.99,0.99,1))); + CHK(d4_eq(data+60, d4(v4,1,1.99,-1.04,1))); + CHK(d4_eq(data+64, d4(v4,-1.01,0,0.99,1))); + CHK(d4_eq(data+68, d4(v4,-0.99,0,-1.04,1))); + CHK(d4_eq(data+72, d4(v4,-1.02,1.99,-1.04,1))); + CHK(d4_eq(data+76, d4(v4,-1.02,1.99,0.99,1))); } int