mirror of
https://git.coom.tech/drummyfish/small3dlib.git
synced 2024-11-23 20:59:58 +01:00
Add computeNormals
This commit is contained in:
parent
289487ceea
commit
16f548f963
2 changed files with 148 additions and 79 deletions
|
@ -31,6 +31,8 @@ const S3L_Unit ver[] = { S3L_CUBE_VERTICES(S3L_FRACTIONS_PER_UNIT) };
|
|||
const S3L_Index tri[] = { S3L_CUBE_TRIANGLES };
|
||||
const S3L_Unit tex_coords[] = { S3L_CUBE_TEXCOORDS(16) };
|
||||
|
||||
S3L_Unit houseNormals[HOUSE_VERTEX_COUNT * 3];
|
||||
|
||||
S3L_Model3D models[2];
|
||||
S3L_Scene scene;
|
||||
|
||||
|
@ -129,75 +131,8 @@ void houseTex(int32_t u, int32_t v, uint8_t *r, uint8_t *g, uint8_t *b)
|
|||
*b = houseTexture[index + 2];
|
||||
}
|
||||
|
||||
int l0, l1, l2;
|
||||
int previousTriangle = 255;
|
||||
|
||||
void drawPixel(S3L_PixelInfo *p)
|
||||
{
|
||||
|
||||
S3L_Vec4 a,b,c,n,V;
|
||||
|
||||
int tmpI = scene.models[p->modelIndex].triangles[p->triangleIndex * 3] * 3;
|
||||
|
||||
a.x = scene.models[p->modelIndex].vertices[tmpI];
|
||||
tmpI++;
|
||||
a.y = scene.models[p->modelIndex].vertices[tmpI];
|
||||
tmpI++;
|
||||
a.z = scene.models[p->modelIndex].vertices[tmpI];
|
||||
|
||||
tmpI = scene.models[p->modelIndex].triangles[p->triangleIndex * 3 + 1] * 3;
|
||||
|
||||
b.x = scene.models[p->modelIndex].vertices[tmpI];
|
||||
tmpI++;
|
||||
b.y = scene.models[p->modelIndex].vertices[tmpI];
|
||||
tmpI++;
|
||||
b.z = scene.models[p->modelIndex].vertices[tmpI];
|
||||
|
||||
tmpI = scene.models[p->modelIndex].triangles[p->triangleIndex * 3 + 2] * 3;
|
||||
|
||||
c.x = scene.models[p->modelIndex].vertices[tmpI];
|
||||
tmpI++;
|
||||
c.y = scene.models[p->modelIndex].vertices[tmpI];
|
||||
tmpI++;
|
||||
c.z = scene.models[p->modelIndex].vertices[tmpI];
|
||||
|
||||
S3L_triangleNormal(a,b,c,&n);
|
||||
/*
|
||||
printf("--------\n");
|
||||
S3L_logVec4(a);
|
||||
S3L_logVec4(b);
|
||||
S3L_logVec4(c);
|
||||
S3L_logVec4(n);
|
||||
*/
|
||||
V.x = 10;
|
||||
V.y = 10;
|
||||
V.z = 10;
|
||||
|
||||
S3L_normalizeVec3(&V);
|
||||
|
||||
int16_t l = S3L_clamp(S3L_dotProductVec3(V,n) / 2,0,255);
|
||||
|
||||
l &= 192;
|
||||
|
||||
/*
|
||||
setPixel(p->x,p->y,
|
||||
S3L_clamp(128 + n.x / 4,0,255),
|
||||
S3L_clamp(128 + n.y / 4,0,255),
|
||||
S3L_clamp(128 + n.z / 4,0,255));
|
||||
*/
|
||||
|
||||
setPixel(p->x,p->y,l,l,l);
|
||||
|
||||
return;
|
||||
|
||||
if (p->triangleIndex != previousTriangle)
|
||||
{
|
||||
l0 = houseVertexLighting[houseTriangleIndices[p->triangleIndex * 3]];
|
||||
l1 = houseVertexLighting[houseTriangleIndices[p->triangleIndex * 3 + 1]];
|
||||
l2 = houseVertexLighting[houseTriangleIndices[p->triangleIndex * 3 + 2]];
|
||||
previousTriangle = p->triangleIndex;
|
||||
}
|
||||
|
||||
if (p->x < 0 || p ->x >= S3L_RESOLUTION_X || p->y < 0 || p->y >= S3L_RESOLUTION_Y)
|
||||
{
|
||||
offScreenPixels++;
|
||||
|
@ -256,23 +191,39 @@ if (p->modelIndex != 0)
|
|||
(v / ((float) S3L_FRACTIONS_PER_UNIT)) * HOUSE_TEXTURE_HEIGHT,
|
||||
&r,&g,&b);
|
||||
|
||||
uint8_t l = S3L_interpolateBarycentric(l0,l1,l2,
|
||||
p->barycentric[0],
|
||||
p->barycentric[1],
|
||||
p->barycentric[2]);
|
||||
S3L_Vec4 n0, n1, n2, n;
|
||||
|
||||
l = 255 - l;
|
||||
n0.x = houseNormals[scene.models[p->modelIndex].triangles[p->triangleIndex * 3] * 3];
|
||||
n0.y = houseNormals[scene.models[p->modelIndex].triangles[p->triangleIndex * 3] * 3 + 1];
|
||||
n0.z = houseNormals[scene.models[p->modelIndex].triangles[p->triangleIndex * 3] * 3 + 2];
|
||||
|
||||
l /= 2;
|
||||
n1.x = houseNormals[scene.models[p->modelIndex].triangles[p->triangleIndex * 3 + 1] * 3];
|
||||
n1.y = houseNormals[scene.models[p->modelIndex].triangles[p->triangleIndex * 3 + 1] * 3 + 1];
|
||||
n1.z = houseNormals[scene.models[p->modelIndex].triangles[p->triangleIndex * 3 + 1] * 3 + 2];
|
||||
|
||||
int16_t clampTmp = r - l;
|
||||
r = clampTmp >= 0 ? clampTmp : 0;
|
||||
n2.x = houseNormals[scene.models[p->modelIndex].triangles[p->triangleIndex * 3 + 2] * 3];
|
||||
n2.y = houseNormals[scene.models[p->modelIndex].triangles[p->triangleIndex * 3 + 2] * 3 + 1];
|
||||
n2.z = houseNormals[scene.models[p->modelIndex].triangles[p->triangleIndex * 3 + 2] * 3 + 2];
|
||||
|
||||
clampTmp = g - l;
|
||||
g = clampTmp >= 0 ? clampTmp : 0;
|
||||
n.x = S3L_interpolateBarycentric(n0.x,n1.x,n2.x,p->barycentric[0],p->barycentric[1],p->barycentric[2]);
|
||||
n.y = S3L_interpolateBarycentric(n0.y,n1.y,n2.y,p->barycentric[0],p->barycentric[1],p->barycentric[2]);
|
||||
n.z = S3L_interpolateBarycentric(n0.z,n1.z,n2.z,p->barycentric[0],p->barycentric[1],p->barycentric[2]);
|
||||
|
||||
clampTmp = b - l;
|
||||
b = clampTmp >= 0 ? clampTmp : 0;
|
||||
S3L_Vec4 V;
|
||||
|
||||
V.x = 10;
|
||||
V.y = 10;
|
||||
V.z = 10;
|
||||
|
||||
S3L_normalizeVec3(&V);
|
||||
|
||||
int16_t l = 64 + S3L_clamp(S3L_dotProductVec3(n,V),-511,511) / 8;
|
||||
|
||||
//setPixel(p->x,p->y,l,l,l);
|
||||
|
||||
r = S3L_clamp(((int16_t) r) - l,0,255);
|
||||
g = S3L_clamp(((int16_t) g) - l,0,255);
|
||||
b = S3L_clamp(((int16_t) b) - l,0,255);
|
||||
|
||||
setPixel(p->x,p->y,r,g,b);
|
||||
}
|
||||
|
@ -360,6 +311,8 @@ void draw()
|
|||
printf("camera: ");
|
||||
S3L_logTransform3D(scene.camera.transform);
|
||||
fps = 0;
|
||||
|
||||
S3L_computeModelNormals(scene.models[1],houseNormals,1);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
116
small3dlib.h
116
small3dlib.h
|
@ -460,6 +460,16 @@ S3L_Unit S3L_sqrt(S3L_Unit value);
|
|||
void S3L_triangleNormal(S3L_Vec4 t0, S3L_Vec4 t1, S3L_Vec4 t2,
|
||||
S3L_Vec4 *n);
|
||||
|
||||
/** Computes a normalized normal for every vertex of given model (this is
|
||||
relatively slow and SHOUDN'T be done each frame). The dst array must have a
|
||||
sufficient size preallocated! The size is: number of model vertices * 3 *
|
||||
sizeof(S3L_Unit). Note that for advanced allowing sharp edges it is not
|
||||
sufficient to have per-vertex normals, but must be per-triangle. This
|
||||
function doesn't support this. */
|
||||
|
||||
void S3L_computeModelNormals(S3L_Model3D model, S3L_Unit *dst,
|
||||
int8_t transformNormals);
|
||||
|
||||
/** Interpolated between two values, v1 and v2, in the same ratio as t is to
|
||||
tMax. Does NOT prevent zero division. */
|
||||
static inline S3L_Unit S3L_interpolate(
|
||||
|
@ -790,6 +800,112 @@ void S3L_triangleNormal(S3L_Vec4 t0, S3L_Vec4 t1, S3L_Vec4 t2,
|
|||
S3L_normalizeVec3(n);
|
||||
}
|
||||
|
||||
void S3L_computeModelNormals(S3L_Model3D model, S3L_Unit *dst,
|
||||
int8_t transformNormals)
|
||||
{
|
||||
S3L_Index vPos = 0;
|
||||
|
||||
S3L_Vec4 n;
|
||||
|
||||
n.w = 0;
|
||||
|
||||
#define MAX_NORMALS 6
|
||||
|
||||
S3L_Vec4 ns[MAX_NORMALS];
|
||||
S3L_Index normalCount;
|
||||
|
||||
for (S3L_Index i = 0; i < model.vertexCount; ++i)
|
||||
{
|
||||
normalCount = 0;
|
||||
|
||||
for (S3L_Index j = 0; j < model.triangleCount * 3; j += 3)
|
||||
{
|
||||
if (
|
||||
(model.triangles[j] == i) ||
|
||||
(model.triangles[j + 1] == i) ||
|
||||
(model.triangles[j + 2] == i))
|
||||
{
|
||||
S3L_Vec4 t0, t1, t2;
|
||||
S3L_Index vIndex;
|
||||
|
||||
#define getVertex(n)\
|
||||
vIndex = model.triangles[j + n] * 3;\
|
||||
t##n.x = model.vertices[vIndex];\
|
||||
vIndex++;\
|
||||
t##n.y = model.vertices[vIndex];\
|
||||
vIndex++;\
|
||||
t##n.z = model.vertices[vIndex];
|
||||
|
||||
getVertex(0)
|
||||
getVertex(1)
|
||||
getVertex(2)
|
||||
|
||||
#undef getVertex
|
||||
|
||||
S3L_triangleNormal(t0,t1,t2,&(ns[normalCount]));
|
||||
|
||||
normalCount++;
|
||||
|
||||
if (normalCount >= MAX_NORMALS)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
n.x = S3L_FRACTIONS_PER_UNIT;
|
||||
n.y = 0;
|
||||
n.z = 0;
|
||||
|
||||
if (normalCount != 0)
|
||||
{
|
||||
// compute average
|
||||
|
||||
n.x = 0;
|
||||
|
||||
for (uint8_t i = 0; i < MAX_NORMALS; ++i)
|
||||
{
|
||||
n.x += ns[i].x;
|
||||
n.y += ns[i].y;
|
||||
n.z += ns[i].z;
|
||||
}
|
||||
|
||||
n.x /= normalCount;
|
||||
n.y /= normalCount;
|
||||
n.z /= normalCount;
|
||||
|
||||
S3L_normalizeVec3(&n);
|
||||
}
|
||||
|
||||
dst[vPos] = n.x;
|
||||
vPos++;
|
||||
|
||||
dst[vPos] = n.y;
|
||||
vPos++;
|
||||
|
||||
dst[vPos] = n.z;
|
||||
vPos++;
|
||||
}
|
||||
|
||||
#undef MAX_NORMALS
|
||||
|
||||
S3L_Mat4 m;
|
||||
|
||||
S3L_makeWorldMatrix(model.transform,&m);
|
||||
|
||||
if (transformNormals)
|
||||
for (S3L_Index i = 0; i < model.vertexCount * 3; i += 3)
|
||||
{
|
||||
n.x = dst[i];
|
||||
n.y = dst[i + 1];
|
||||
n.z = dst[i + 2];
|
||||
|
||||
S3L_vec4Xmat4(&n,&m);
|
||||
|
||||
dst[i] = n.x;
|
||||
dst[i + 1] = n.y;
|
||||
dst[i + 2] = n.z;
|
||||
}
|
||||
}
|
||||
|
||||
void S3L_vec4Xmat4(S3L_Vec4 *v, S3L_Mat4 *m)
|
||||
{
|
||||
S3L_Vec4 vBackup;
|
||||
|
|
Loading…
Reference in a new issue