1
0
Fork 0
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:
Miloslav Číž 2019-06-06 20:22:20 +02:00
parent 289487ceea
commit 16f548f963
2 changed files with 148 additions and 79 deletions

View file

@ -31,6 +31,8 @@ const S3L_Unit ver[] = { S3L_CUBE_VERTICES(S3L_FRACTIONS_PER_UNIT) };
const S3L_Index tri[] = { S3L_CUBE_TRIANGLES }; const S3L_Index tri[] = { S3L_CUBE_TRIANGLES };
const S3L_Unit tex_coords[] = { S3L_CUBE_TEXCOORDS(16) }; const S3L_Unit tex_coords[] = { S3L_CUBE_TEXCOORDS(16) };
S3L_Unit houseNormals[HOUSE_VERTEX_COUNT * 3];
S3L_Model3D models[2]; S3L_Model3D models[2];
S3L_Scene scene; 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]; *b = houseTexture[index + 2];
} }
int l0, l1, l2;
int previousTriangle = 255;
void drawPixel(S3L_PixelInfo *p) 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) if (p->x < 0 || p ->x >= S3L_RESOLUTION_X || p->y < 0 || p->y >= S3L_RESOLUTION_Y)
{ {
offScreenPixels++; offScreenPixels++;
@ -256,23 +191,39 @@ if (p->modelIndex != 0)
(v / ((float) S3L_FRACTIONS_PER_UNIT)) * HOUSE_TEXTURE_HEIGHT, (v / ((float) S3L_FRACTIONS_PER_UNIT)) * HOUSE_TEXTURE_HEIGHT,
&r,&g,&b); &r,&g,&b);
uint8_t l = S3L_interpolateBarycentric(l0,l1,l2, S3L_Vec4 n0, n1, n2, n;
p->barycentric[0],
p->barycentric[1],
p->barycentric[2]);
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; n2.x = houseNormals[scene.models[p->modelIndex].triangles[p->triangleIndex * 3 + 2] * 3];
r = clampTmp >= 0 ? clampTmp : 0; 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; n.x = S3L_interpolateBarycentric(n0.x,n1.x,n2.x,p->barycentric[0],p->barycentric[1],p->barycentric[2]);
g = clampTmp >= 0 ? clampTmp : 0; 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; S3L_Vec4 V;
b = clampTmp >= 0 ? clampTmp : 0;
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); setPixel(p->x,p->y,r,g,b);
} }
@ -360,6 +311,8 @@ void draw()
printf("camera: "); printf("camera: ");
S3L_logTransform3D(scene.camera.transform); S3L_logTransform3D(scene.camera.transform);
fps = 0; fps = 0;
S3L_computeModelNormals(scene.models[1],houseNormals,1);
} }
} }

View file

@ -460,6 +460,16 @@ S3L_Unit S3L_sqrt(S3L_Unit value);
void S3L_triangleNormal(S3L_Vec4 t0, S3L_Vec4 t1, S3L_Vec4 t2, void S3L_triangleNormal(S3L_Vec4 t0, S3L_Vec4 t1, S3L_Vec4 t2,
S3L_Vec4 *n); 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 /** Interpolated between two values, v1 and v2, in the same ratio as t is to
tMax. Does NOT prevent zero division. */ tMax. Does NOT prevent zero division. */
static inline S3L_Unit S3L_interpolate( 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); 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) void S3L_vec4Xmat4(S3L_Vec4 *v, S3L_Mat4 *m)
{ {
S3L_Vec4 vBackup; S3L_Vec4 vBackup;