📄 texture.c
字号:
/* texture.c, HAWK game engine
*
* Copyright 1997-1998 by Phil Frisbie, Jr.
* for Hawk Software
*
*/
#include "hawk.h"
#include "internal.h"
#include "graphics.h"
#define CEILING( A, B ) ( (A) % (B) == 0 ? (A)/(B) : (A)/(B)+1 )
#ifdef EPSILON
#undef EPSILON
#endif
#define EPSILON 0.001
void texScaleImage(int widthin, int heightin, unsigned char *datain,
int widthout, int heightout, unsigned char *dataout )
{
int components, i, j, k;
float *tempin, *tempout;
float sx, sy;
int rowstride, rowlen;
components = 4;
tempin = (float *)TempMalloc(widthin * heightin * components * sizeof(float));
tempout = (float *)TempMalloc(widthout * heightout * components * sizeof(float));
/* Unpack the pixel data and convert to floating point */
rowlen = widthin;
rowstride = components * rowlen;
k = 0;
for (i=0;i<heightin;i++)
{
unsigned char *ubptr = (unsigned char *) datain + i * rowstride;
for (j=0;j<widthin*components;j++)
tempin[k++] = (float) *ubptr++;
}
/* Scale the image! */
sx = (float)widthin / (float)widthout;
sy = (float)heightin / (float)heightout;
if (sx<1.0 && sy<1.0)
{
for(i=0;i<heightout;i++)
{
int ii = i * sy;
for(j=0;j<widthout;j++)
{
int jj = j * sx;
float *src = tempin + (ii * widthin + jj) * components;
float *dst = tempout + (i * widthout + j) * components;
for (k=0;k<components;k++)
{
*dst++ = *src++;
}
}
}
}
else
{
/* shrink width and/or height: use an unweighted box filter */
int i0, i1;
int j0, j1;
int ii, jj;
float sum, *dst;
for(i=0;i<heightout;i++)
{
i0 = i * sy;
i1 = (i+1) * sy - EPSILON;
for(j=0;j<widthout;j++)
{
j0 = j * sx;
j1 = (j+1) * sx - EPSILON;
dst = tempout + (i * widthout + j) * components;
/* compute average of pixels in the rectangle (i0,j0)-(i1,j1) */
for(k=0;k<components;k++)
{
sum = 0.0;
for(ii=i0;ii<=i1;ii++)
{
for(jj=j0;jj<=j1;jj++)
sum += *(tempin + (ii * widthin + jj) * components + k);
}
sum /= (j1-j0+1) * (i1-i0+1);
*dst++ = sum;
}
}
}
}
/* Return output image */
rowlen = widthout;
rowstride = components * rowlen;
k = 0;
for(i=0;i<heightout;i++)
{
unsigned char *ubptr = (unsigned char *)dataout + i * rowstride;
for (j=0;j<widthout*components;j++)
*ubptr++ = (unsigned char) F_TO_I(tempout[k++]);
}
/* free temporary image storage */
TempFree(tempin);
TempFree(tempout);
}
void texFastScaleImage(int in_w, int in_h, unsigned char *datain,
int out_w, int out_h, unsigned char *dataout )
{
int *in = (int *)datain;
int *out = (int *)dataout;
float sx = (float)in_w / (float)out_w;
float sy = (float)in_h / (float)out_h;
float i, j;
for(i=0;i<out_h;i+=1.0f)
{
int ii = F_TO_I(i * sy) * in_w;
for (j=0;j<out_w;j+=1.0f)
{
int jj = F_TO_I(j * sx);
*out++ = in[ii + jj];
}
}
}
/* Find the value nearest to n which is also a power of two */
static int round2(int n)
{
int m;
for(m=1; m<n; m*=2);
if(m-n <= n-m/2)
return m;
else
return m/2;
}
int texBuildMipmaps(int components, int width, int height, unsigned char *data)
{
int w, h, maxsize, tex;
unsigned char *image, *newimage;
int neww, newh, level, bpp;
maxsize = graphGetMaxTexSize();
if(!maxsize)
maxsize = 256;
if((width==0) || (height==0))
return (0);
w = round2(width)/Engine.texturescale;
if(w>maxsize)
w = maxsize;
h = round2(height)/Engine.texturescale;
if(h>maxsize)
h = maxsize;
/* correct aspect ratio for 3Dfx */
if(w>h)
{
if((w / h) > 8)
h = w / 8;
}
else
{
if((h / w) > 8)
w = h / 8;
}
bpp = 4;
if(w!=width || h!=height)
{
/* must rescale image to get "top" mipmap texture image */
image = TempMalloc((w+4) * h * bpp);
texScaleImage(width, height, data, w, h, image );
}
else
image = (void *)data;
level = 0;
tex = graphNextTex();
graphUseTexture(tex);
graphSetTexWrap(TRUE);
graphSetTexFilter(TRUE);
while(1)
{
graphCreateTex(level, components, w, h, image);
if(w==1 && h==1)
break;
neww = (w<2) ? 1 : w/2;
newh = (h<2) ? 1 : h/2;
newimage = TempMalloc((neww+4) * newh * bpp);
texScaleImage(w, h, image, neww, newh, newimage );
if(image!=data)
{
TempFree(image);
}
image = newimage;
w = neww;
h = newh;
level++;
}
if(image!=data)
{
TempFree(image);
}
return tex;
}
int texBuildTex(int components, int width, int height, unsigned char *data)
{
int tex;
tex = graphNextTex();
graphUseTexture(tex);
graphSetTexWrap(TRUE);
graphSetTexFilter(FALSE);
graphCreateTex(0, components, width, height, data);
return tex;
}
int texBuildLightmap(int components, int width, int height, unsigned char *data)
{
int w, h, maxsize, tex;
unsigned char *image;
int bpp;
maxsize = graphGetMaxTexSize();
if(!maxsize)
maxsize = 256;
if((width==0) || (height==0))
return (0);
w = round2(width)/Engine.texturescale;
if(w>maxsize)
w = maxsize;
h = round2(height)/Engine.texturescale;
if(h>maxsize)
h = maxsize;
/* correct aspect ratio for 3Dfx */
if(w>h)
{
if((w / h) > 8)
h = w / 8;
}
else
{
if((h / w) > 8)
w = h / 8;
}
bpp = 4;
if(w!=width || h!=height)
{
/* must rescale image to get "top" mipmap texture image */
image = TempMalloc((w+4) * h * bpp);
texFastScaleImage(width, height, data, w, h, image );
}
else
image = (void *)data;
tex = graphNextTex();
graphUseTexture(tex);
graphSetTexWrap(FALSE);
graphSetTexFilter(FALSE);
graphCreateTex(0, components, w, h, image);
if(image!=data)
{
TempFree(image);
}
return tex;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -