Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
build/

# CLion
cmake-build-*/
.idea/
19 changes: 19 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
cmake_minimum_required(VERSION 3.4 FATAL_ERROR)
project(tgen)

set(CMAKE_CXX_STANDARD_REQUIRED 11)
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)

if(EMSCRIPTEN)
option(TGEN_WEBASSEMBLY "Generate WebAssembly instead of asm.js" OFF)
if(TGEN_WEBASSEMBLY)
set(CMAKE_CXX_FLAGS "-s WASM=1 ${CMAKE_CXX_FLAGS}")
endif()

# For some reason CMAKE_CXX_STANDARD_REQUIRED does not work for emscripten
set(CMAKE_CXX_FLAGS "--bind -std=c++11 ${CMAKE_CXX_FLAGS}")
else()
option(TGEN_SHARED_LIBRARY "Build tgen as a shared library" OFF)
endif()

add_subdirectory(src bin)
22 changes: 20 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,35 @@ Current Features:
* Generation of per-corner tangents for triangle data with UVs
* Computation of per-wedge / per-UV-vertex tangent spaces
* Tangent frame orthogonalization
* Encoding of 4-component tangents (with "flip factor") for avoiding explicit binormals
* Encoding of 4-component tangents (with "flip factor") for avoiding explicit bitangents
* Simple C++ implementation, no dependencies
* Compilable to asm.js and WebAssembly (right now, only the functions are exported, there is no web demo yet)

The code consists basically of one header + .cpp file.
For debugging and visualization, there is also a simple X3D exporter in a separate file, which was used to generate the 3D visualizations shown below.
The baked tangent-space normal maps are just provided for demonstration purposes, the actual baking code is not part of this repository.

So far, the C++ code from this project has just been compiled and tested with VS 2015.
So far, the C++ code from this project has been compiled and tested with VS 2015, gcc 6.3 / 7.0 trunk, clang 5.0 trunk and emscripten 1.37 (clang 3.9).

Feedback and contributions are always welcome.

## Building and installing

TGen has no external dependencies and can be built using CMake 3.4 or newer:
```
cd <this-repo>
mkdir build
cd build

# Native targets
cmake .. [-DCMAKE_BUILD_TYPE=Release] [-DTGEN_STATIC_LIBRARY=0] # Default is building as a shared library
cmake --build . [--target install]

# Emscripten
emconfigure cmake .. [-DCMAKE_BUILD_TYPE=Release] [-DTGEN_WEBASSEMBLY=1] # Default is asm.js instead of WebAssembly
cmake --build .
emrun --port 8080 bin
```

## Results

Expand Down
37 changes: 37 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
set(SOURCE_FILES
tgen.h tgen.cpp
tgen_debug.h tgen_debug.cpp
)

if(TGEN_SHARED_LIBRARY)
add_library(tgen SHARED ${SOURCE_FILES})
else()
add_library(tgen STATIC ${SOURCE_FILES})
endif()

if(EMSCRIPTEN)
add_executable(tgen_driver EmscriptenMain.cpp)
else()
add_executable(tgen_driver main.cpp)
endif()

target_link_libraries(tgen_driver PRIVATE tgen)
set_target_properties(tgen_driver PROPERTIES OUTPUT_NAME tgen)

install(TARGETS tgen_driver
RUNTIME DESTINATION bin
)

install(TARGETS tgen
RUNTIME DESTINATION bin
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib
)

install(DIRECTORY . DESTINATION include
FILES_MATCHING PATTERN "*.h"
)

if(EMSCRIPTEN)
configure_file(webdemo.html index.html COPYONLY)
endif()
27 changes: 27 additions & 0 deletions src/EmscriptenMain.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/**
* TGen - Simple Tangent Generator
*
* 2016 by Max Limper, Fraunhofer IGD
*
* This code is public domain.
*
*/

#include <emscripten/bind.h>
#include "tgen.h"

using namespace emscripten;

int add(int a, int b)
{
return a + b;
}

EMSCRIPTEN_BINDINGS(tgen)
{
function("computeCornerTSpace", &tgen::computeCornerTSpace);
function("computeVertexTSpace", &tgen::computeVertexTSpace);
function("orthogonalizeTSpace", &tgen::orthogonalizeTSpace);
function("computeTangent4D", &tgen::computeTangent4D);
function("add", &add);
}
12 changes: 12 additions & 0 deletions src/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#include "tgen.h"
#include "tgen_debug.h"
#include <iostream>

int main(int argc, char ** argv)
{
if(argc != 3)
{
std::cout << "Usage: " << argv[0] << " input.gltf output.gltf\n";
std::exit(EXIT_FAILURE);
}
}
62 changes: 31 additions & 31 deletions src/tgen_debug.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,20 +103,20 @@ namespace
double vScale,
std::stringstream & ss )
{
ss << " <Shape>" << std::endl;
ss << " <Appearance>" << std::endl;
ss << " <Shape>" << '\n';
ss << " <Appearance>" << '\n';
ss << " <Material emissiveColor=\"" << colorStr << "\"/>"
<< std::endl;
ss << " </Appearance>" << std::endl;
<< '\n';
ss << " </Appearance>" << '\n';
ss << " <LineSet vertexCount=\"";
writeX3DLinesVCount(pos3D.size() / 3, ss);
ss << "\" >"
<< std::endl;
<< '\n';
ss << " <Coordinate point=\"";
writeX3DVecFieldLineData(pos3D, dir3D, vScale, ss);
ss << "\"/>" << std::endl;
ss << " </LineSet>" << std::endl;
ss << " </Shape>" << std::endl;
ss << "\"/>" << '\n';
ss << " </LineSet>" << '\n';
ss << " </Shape>" << '\n';
}

//-------------------------------------------------------------------------
Expand Down Expand Up @@ -178,52 +178,52 @@ namespace tgen
std::stringstream sstr;

// prologue
sstr << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl;
sstr << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << '\n';
sstr << "<!DOCTYPE X3D PUBLIC \"ISO//Web3D//DTD X3D 3.0//EN\" "
<< "\"http://www.web3d.org/specifications/x3d-3.0.dtd\">"
<< std::endl;
sstr << "<X3D>" << std::endl;
sstr << " <Scene>" << std::endl;
<< '\n';
sstr << "<X3D>" << '\n';
sstr << " <Scene>" << '\n';

// textured object
sstr << " <Shape>" << std::endl;
sstr << " <Appearance>" << std::endl;
sstr << " <Material/>" << std::endl;
sstr << " <ImageTexture url=\"checker.png\">" << std::endl;
sstr << " <TextureProperties magnificationFilter=\"NEAREST_PIXEL\"/>" << std::endl;
sstr << " </ImageTexture>" << std::endl;
sstr << " </Appearance>" << std::endl;
sstr << " <IndexedFaceSet solid=\"false\"" << std::endl;
sstr << " <Shape>" << '\n';
sstr << " <Appearance>" << '\n';
sstr << " <Material/>" << '\n';
sstr << " <ImageTexture url=\"checker.png\">" << '\n';
sstr << " <TextureProperties magnificationFilter=\"NEAREST_PIXEL\"/>" << '\n';
sstr << " </ImageTexture>" << '\n';
sstr << " </Appearance>" << '\n';
sstr << " <IndexedFaceSet solid=\"false\"" << '\n';
sstr << " coordIndex =\"";
writeX3DTriIndexArray(triIndicesPos, sstr);
sstr << "\"" << std::endl;
sstr << "\"" << '\n';
sstr << " texCoordIndex=\"";
writeX3DTriIndexArray(triIndicesUV, sstr);
sstr << "\">" << std::endl;
sstr << "\">" << '\n';
sstr << " <Coordinate point=\"";
writeX3DArray(positions3D, sstr);
sstr << "\"/>" << std::endl;
sstr << "\"/>" << '\n';
sstr << " <Normal vector=\"";
writeX3DArray(normals3D, sstr);
sstr << "\"/>" << std::endl;
sstr << "\"/>" << '\n';
sstr << " <TextureCoordinate point=\"";
writeX3DArray(uvs2D, sstr);
sstr << "\"/>" << std::endl;
sstr << " </IndexedFaceSet>" << std::endl;
sstr << " </Shape>" << std::endl;
sstr << "\"/>" << '\n';
sstr << " </IndexedFaceSet>" << '\n';
sstr << " </Shape>" << '\n';

// vector field visualizations
writeX3DVecFieldVis(positions3D, normals3D, "0 0 1", vScale, sstr);
writeX3DVecFieldVis(positions3D, tangents3D, "1 0 0", vScale, sstr);
writeX3DVecFieldVis(positions3D, bitangents3D, "0 1 0", vScale, sstr);

// epilogue
sstr << " </Scene>" << std::endl;
sstr << "</X3D>" << std::endl;
sstr << " </Scene>" << '\n';
sstr << "</X3D>" << '\n';


std::ofstream fstr("tangents.x3d");
fstr << sstr.str() << std::endl;
std::ofstream fstr(filename);
fstr << sstr.str() << '\n';
}

//-------------------------------------------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion src/tgen_debug.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ namespace tgen
const std::vector<tgen::RealT> & uvs2D,
const std::vector<tgen::RealT> & tangents3D,
const std::vector<tgen::RealT> & bitangents3D,
const char * filename );
const char * filename = "tangents.x3d");

//-------------------------------------------------------------------------

Expand Down
31 changes: 31 additions & 0 deletions src/webdemo.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<!doctype html>
<html>
<body>
<script>
var run = function() {
let res = Module.add(42, 23)
console.log(res)
}

var Module = {}
let xhr = new XMLHttpRequest()
xhr.open('GET', 'tgen.wasm')
xhr.responseType = 'arraybuffer'
xhr.onload = function() {
if(xhr.status == 404) {
console.log("wasm module not found - continuing with assumption that tgen has been compiled to asm.js")
}
else {
Module.wasmBinary = xhr.response
}

let script = document.createElement('script')
script.src = "tgen.js"
document.body.appendChild(script)

script.onload = run
}
xhr.send(null)
</script>
</body>
</html>