📄 spharm.c
字号:
////////////////////////////////////////////////////////////////////////////////////////
// Spherical Harmonic Surface
// Copyright (c) 2004,5 adresd <adresd_ps2dev@yahoo.com>
//
// calculated with each point, as done.
// as drawn re-uses previous strip for making the tri strips, so
// first strip may not be correct first run.
//
// Note that this code is highly unoptimized, but might be useful to learn from or so.
//
#include <pspkernel.h>
#include <pspdisplay.h>
#include <pspdebug.h>
#include <pspge.h>
#include <stdlib.h>
#include <stdio.h>
#include <pspgu.h>
#include <pspgum.h>
#include "mt19937.h"
/*
*/
#define PSP_GEVERT_SET(TEX,COL,NORM,VERT,INDEX,TRAN) ((TEX)|(COL<<2)|(NORM<<5)|(VERT<<7)|(INDEX<<11)|(TRAN<<23))
#define PI (3.14159265358979323846f)
#define TWOPI (PI+PI)
float shift23=(float)(1<<23);
float OOshift23=1.0f/(float)(1<<23);
static inline float floorf(float i)
{ // return largest integer that is less than or equal to i
float k = (float)((int) i);
if (k <= i)
return k;
else // if k greater than i
return k-1.0f;
}
static inline float myLog2(float i)
{
float LogBodge=0.346607f;
float x;
float y;
x=*(int *)&i;
x*= OOshift23; //1/pow(2,23);
x=x-127;
y=x-floorf(x);
y=(y-y*y)*LogBodge;
return x+y;
}
static inline float myPow2(float i)
{
float PowBodge=0.33971f;
float x;
float y=i-floorf(i);
y=(y-y*y)*PowBodge;
x=i+127-y;
x*= shift23; //pow(2,23);
*(int*)&x=(int)x;
return x;
}
static inline float mypowf(float a, float b)
{
return myPow2(b*myLog2(a));
}
static inline float invsqrtf (float x)
{
float xhalf = 0.5f*x;
int i = *(int*)&x;
i = 0x5f3759df - (i >> 1);
x = *(float*)&i;
x = x*(1.5f - xhalf*x*x);
return x;
}
static inline float mysqrtf(float val)
{
float val2 = invsqrtf(val);
if (val2 == 0.0f) return 0.0f; // check for div by 0
return (1.0f / val2);
}
static int mi[8];
static float mf[8];
static float mft[8];
// Float Vector
typedef struct
{
float x, y, z;
} FVec;
// Short Vector
typedef struct
{
short x, y, z;
} SVec;
// Integer Vector
typedef struct
{
int x, y, z;
} IVec;
static inline void FVecMult(FVec *v0, const FVec *v1, const FVec *v2)
{
v0->x = v1->x * v2->x;
v0->y = v1->y * v2->y;
v0->z = v1->z * v2->z;
}
static inline void FVecSub(FVec *v0, const FVec *v1, const FVec *v2)
{
v0->x = v1->x - v2->x;
v0->y = v1->y - v2->y;
v0->z = v1->z - v2->z;
}
static inline void FVecAdd(FVec *v0, const FVec *v1, const FVec *v2)
{
v0->x = v1->x + v2->x;
v0->y = v1->y + v2->y;
v0->z = v1->z + v2->z;
}
static inline void FVecCrossProduct(FVec *v0, const FVec *v1, const FVec *v2)
{
v0->x = (v1->y * v2->z) - (v2->y * v1->z);
v0->y = (v1->z * v2->x) - (v2->z * v1->x);
v0->z = (v1->x * v2->y) - (v2->x * v1->y);
}
static inline void FVecNormalize(FVec *v0, const FVec *v1)
{
float dist;
dist = (v1->x * v1->x) + (v1->y * v1->y) + (v1->z * v1->z);
dist = mysqrtf(dist);
v0->x = v1->x / dist;
v0->y = v1->y / dist;
v0->z = v1->z / dist;
}
static inline void objgen_spharm_calcnormal(FVec *point1,FVec *point2,FVec *point3,FVec *output)
{
FVec temp1,temp2,temp3;
FVecSub(&temp1,point1,point2);
FVecSub(&temp2,point1,point3);
FVecCrossProduct(&temp3,&temp1,&temp2);
FVecNormalize(output,&temp3);
}
static inline void objgen_spharm_Evaln(float theta, float phi, FVec *output,float dx,float dy, FVec *normal)
{
float r,rp,rt,rtemp;
float sinphi,cosphi,sintheta,costheta;
float phix, thex;
FVec t1,t2;
phix = phi + dx;
thex = theta + dy;
sinphi = sinf(phi);
cosphi = cosf(phi);
sintheta = sinf(theta);
costheta = cosf(theta);
// eval posy,posx
rt = mypowf(sinf(mf[4]*theta),mf[5]);
rt += mypowf(cosf(mf[6]*theta),mf[7]);
rp = mypowf(sinf(mf[0]*phi),mf[1]);
rp += mypowf(cosf(mf[2]*phi),mf[3]);
r = rt + rp;
output->x = r * sinphi * costheta;
output->y = r * cosphi;
output->z = r * sinphi * sintheta;
// eval posy+dy,posx
rtemp = mypowf(sinf(mf[4]*thex),mf[5]);
rtemp += mypowf(cosf(mf[6]*thex),mf[7]);
r = rtemp + rp;
t1.x = r * sinphi * cosf(thex);
t1.y = r * cosphi;
t1.z = r * sinphi * sinf(thex);
// eval posy,posx+dx
rtemp = mypowf(sinf(mf[0]*phix),mf[1]);
rtemp += mypowf(cosf(mf[2]*phix),mf[3]);
r = rt + rtemp;
sinphi = sinf(phix);
t2.x = r * sinphi * costheta;
t2.y = r * cosf(phix);
t2.z = r * sinphi * sintheta;
// Calculate normal
objgen_spharm_calcnormal(output,&t1,&t2,normal);
}
void objgen_spharm_setparam(float v1,float v2,float v3, float v4, float v5, float v6, float v7, float v8)
{
mf[0] = v1;
mf[1] = v2;
mf[2] = v3;
mf[3] = v4;
mf[4] = v5;
mf[5] = v6;
mf[6] = v7;
mf[7] = v8;
}
void objgen_spharm_setparamg(float v1,float v2,float v3, float v4, float v5, float v6, float v7, float v8)
{
mft[0] = v1;
mft[1] = v2;
mft[2] = v3;
mft[3] = v4;
mft[4] = v5;
mft[5] = v6;
mft[6] = v7;
mft[7] = v8;
}
void objgen_spharm_setparamt(int time,float v1,float v2,float v3, float v4, float v5, float v6, float v7, float v8)
{
float ftime = (float)time;
mft[0] = (v1 - mf[0]) / ftime;
mft[1] = (v2 - mf[1]) / ftime;
mft[2] = (v3 - mf[2]) / ftime;
mft[3] = (v4 - mf[3]) / ftime;
mft[4] = (v5 - mf[4]) / ftime;
mft[5] = (v6 - mf[5]) / ftime;
mft[6] = (v7 - mf[6]) / ftime;
mft[7] = (v8 - mf[7]) / ftime;
}
void objgen_spharm_tick()
{
mf[0] += mft[0];
mf[1] += mft[1];
mf[2] += mft[2];
mf[3] += mft[3];
mf[4] += mft[4];
mf[5] += mft[5];
mf[6] += mft[6];
mf[7] += mft[7];
}
void objgen_spharm_setparamc(char *ptr)
{
int count;
for (count=0;count<8;count++)
{
mi[count] = (int)*(ptr+count);
mf[count] = (float)mi[count];
}
}
// This is for the GU display list
static unsigned int __attribute__((aligned(16))) spharmlist[20*1024];
struct Vertex
{
float u, v;
unsigned int color;
float nx,ny,nz;
float x,y,z;
};
// current and previous list
static struct Vertex __attribute__((aligned(16))) vertices[20*1024];
static struct Vertex __attribute__((aligned(16))) vertices2[20*1024];
static struct Vertex __attribute__((aligned(16))) preverts[1024];
#define ENABLE_GU
static FVec q;
static FVec n;
void SparmGenList(struct Vertex *vertptr,int xpoints,int ypoints,int color)
{
int x,y;
float dx,dy;
float dx10,dy10;
float dtx,dty;
float texx,texy;
float posx,posy;
float dcolx,dcoly;
float colx,coly;
struct Vertex *verts;
struct Vertex *prevptr;
float ypoints2 = ypoints-2;
dx = PI / (float)(xpoints - 1);
dy = TWOPI / (float)ypoints2;
dx10 = dx / 50.0f;
dy10 = dy / 50.0f;
dtx = 1.0f / (float)xpoints;
dty = 1.0f / (float)ypoints2;
dcolx = 96.0f/(float)xpoints;
dcoly = 96.0f/(float)ypoints2;
coly = 0.0f;
verts = vertptr;
for (y=0;y<ypoints;y++) {
// Setup memory for verts, and previous pointer
posy = (float)y * dy;
texy = (float)y * dty;
prevptr = (struct Vertex *)preverts;
colx = 0.0f;
for (x=0;x<xpoints;x++) {
posx = (float)x * dx;
texx = (float)x * dtx;
// Evaluate the point
objgen_spharm_Evaln(posy,posx,&q,dy10,dx10,&n);
q.x *= 40.0f;
q.y *= 40.0f;
q.z *= 40.0f;
// Add point to our list
verts->u = texy;
verts->v = texx;
if (color)
verts->color = 0xff000020 | (((int)coly)<< 16) | (((int)colx)<<8);
else
verts->color = 0xff555555;
verts->x = q.x;
verts->y = q.y;
verts->z = q.z;
verts->nx = n.x;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -