130 lines
5.9 KiB
Rust
130 lines
5.9 KiB
Rust
|
|
#![allow(bad_style)]
|
|
#![allow(dead_code)]
|
|
|
|
use std::os::raw::*;
|
|
|
|
pub type tbool = c_int;
|
|
pub const TFALSE: tbool = 0;
|
|
pub const TTRUE: tbool = 1;
|
|
|
|
#[repr(C)]
|
|
pub struct SMikkTSpaceInterface {
|
|
/// Returns the number of faces (triangles/quads) on the mesh to be processed.
|
|
pub m_getNumFaces: extern "C" fn(pContext: *const SMikkTSpaceContext) -> c_int,
|
|
|
|
/// Returns the number of vertices on face number iFace
|
|
/// iFace is a number in the range {0, 1, ..., getNumFaces()-1}
|
|
pub m_getNumVerticesOfFace: extern "C" fn(
|
|
pContext: *const SMikkTSpaceContext,
|
|
iFace: c_int,
|
|
) -> c_int,
|
|
|
|
/// Returns the position of the referenced face of vertex number
|
|
/// iVert, in the range {0,1,2} for triangles, and {0,1,2,3} for quads.
|
|
pub m_getPosition: extern "C" fn(
|
|
pContext: *const SMikkTSpaceContext,
|
|
fvPosOut: *mut c_float,
|
|
iFace: c_int,
|
|
iVert: c_int,
|
|
),
|
|
|
|
/// Returns the normal of the referenced face of vertex number
|
|
/// iVert, in the range {0,1,2} for triangles, and {0,1,2,3} for quads.
|
|
pub m_getNormal: extern "C" fn(
|
|
pContext: *const SMikkTSpaceContext,
|
|
fvNormOut: *mut c_float,
|
|
iFace: c_int,
|
|
iVert: c_int,
|
|
),
|
|
|
|
/// Returns the texcoord of the referenced face of vertex number
|
|
/// iVert, in the range {0,1,2} for triangles, and {0,1,2,3} for quads.
|
|
pub m_getTexCoord: extern "C" fn(
|
|
pContext: *const SMikkTSpaceContext,
|
|
fvTexcOut: *mut c_float,
|
|
iFace: c_int,
|
|
iVert: c_int,
|
|
),
|
|
|
|
/// either (or both) of the two setTSpace callbacks can be set.
|
|
/// The call-back m_setTSpaceBasic() is sufficient for basic normal mapping.
|
|
|
|
/// This function is used to return the tangent and fSign to the application.
|
|
/// fvTangent is a unit length vector.
|
|
/// For normal maps it is sufficient to use the following simplified version of the bitangent which is generated at pixel/vertex level.
|
|
/// bitangent = fSign * cross(vN, tangent);
|
|
/// Note that the results are returned unindexed. It is possible to generate a new index list
|
|
/// But averaging/overwriting tangent spaces by using an already existing index list WILL produce INCRORRECT results.
|
|
/// DO NOT! use an already existing index list.
|
|
pub m_setTSpaceBasic: extern "C" fn(
|
|
pContext: *mut SMikkTSpaceContext,
|
|
fvTangent: *const c_float,
|
|
fSign: *const c_float,
|
|
iFace: c_int,
|
|
iVert: c_int,
|
|
),
|
|
|
|
/// This function is used to return tangent space results to the application.
|
|
/// fvTangent and fvBiTangent are unit length vectors and fMagS and fMagT are their
|
|
/// true magnitudes which can be used for relief mapping effects.
|
|
/// fvBiTangent is the "real" bitangent and thus may not be perpendicular to fvTangent.
|
|
/// However, both are perpendicular to the vertex normal.
|
|
/// For normal maps it is sufficient to use the following simplified version of the bitangent which is generated at pixel/vertex level.
|
|
/// fSign = bIsOrientationPreserving ? 1.0f : (-1.0f);
|
|
/// bitangent = fSign * cross(vN, tangent);
|
|
/// Note that the results are returned unindexed. It is possible to generate a new index list
|
|
/// But averaging/overwriting tangent spaces by using an already existing index list WILL produce INCRORRECT results.
|
|
/// DO NOT! use an already existing index list.
|
|
pub m_setTSpace: extern "C" fn(
|
|
pContext: *mut SMikkTSpaceContext,
|
|
fvTangent: *const c_float,
|
|
fvBiTangent: *const c_float,
|
|
fMagS: *const c_float,
|
|
fMagT: *const c_float,
|
|
bIsOrientationPreserving: tbool,
|
|
iFace: c_int,
|
|
iVert: c_int,
|
|
),
|
|
}
|
|
|
|
/// these are both thread safe!
|
|
/// Default (recommended) fAngularThreshold is 180 degrees (which means threshold disabled)
|
|
extern "system" {
|
|
pub fn genTangSpaceDefault(pContext: *const SMikkTSpaceContext) -> tbool;
|
|
#[allow(dead_code)]
|
|
pub fn genTangSpace(pContext: *const SMikkTSpaceContext, fAngularThreshold: c_float) -> tbool;
|
|
}
|
|
|
|
/// To avoid visual errors (distortions/unwanted hard edges in lighting), when using sampled normal maps, the
|
|
/// normal map sampler must use the exact inverse of the pixel shader transformation.
|
|
/// The most efficient transformation we can possibly do in the pixel shader is
|
|
/// achieved by using, directly, the "unnormalized" interpolated tangent, bitangent and vertex normal: vT, vB and vN.
|
|
/// pixel shader (fast transform out)
|
|
/// vNout = normalize( vNt.x * vT + vNt.y * vB + vNt.z * vN );
|
|
/// where vNt is the tangent space normal. The normal map sampler must likewise use the
|
|
/// interpolated and "unnormalized" tangent, bitangent and vertex normal to be compliant with the pixel shader.
|
|
/// sampler does (exact inverse of pixel shader):
|
|
/// float3 row0 = cross(vB, vN);
|
|
/// float3 row1 = cross(vN, vT);
|
|
/// float3 row2 = cross(vT, vB);
|
|
/// float fSign = dot(vT, row0)<0 ? -1 : 1;
|
|
/// vNt = normalize( fSign * float3(dot(vNout,row0), dot(vNout,row1), dot(vNout,row2)) );
|
|
/// where vNout is the sampled normal in some chosen 3D space.
|
|
///
|
|
/// Should you choose to reconstruct the bitangent in the pixel shader instead
|
|
/// of the vertex shader, as explained earlier, then be sure to do this in the normal map sampler also.
|
|
/// Finally, beware of quad triangulations. If the normal map sampler doesn't use the same triangulation of
|
|
/// quads as your renderer then problems will occur since the interpolated tangent spaces will differ
|
|
/// eventhough the vertex level tangent spaces match. This can be solved either by triangulating before
|
|
/// sampling/exporting or by using the order-independent choice of diagonal for splitting quads suggested earlier.
|
|
/// However, this must be used both by the sampler and your tools/rendering pipeline.
|
|
|
|
#[repr(C)]
|
|
pub struct SMikkTSpaceContext {
|
|
/// initialized with callback functions
|
|
pub m_pInterface: *const SMikkTSpaceInterface,
|
|
/// pointer to client side mesh data etc. (passed as the first parameter with every interface call)
|
|
pub m_pUserData: *mut c_void,
|
|
}
|