Skip to content

Commit

Permalink
Update 3D Renderer
Browse files Browse the repository at this point in the history
3Dレンダリングエンジンのz=ZNEAR平面でクリップを実装。自動で複数ポリゴンに分割することもある。
この追加により近くの物体、床や壁なども描画できるようになった。

パフォーマンスの向上
 - 同時描画ライン数を60に増加
 - SPIクロックを40MHzにした。(不安定であれば修正すること)
24fpsくらい出てるところ
  • Loading branch information
elect-gombe committed Sep 20, 2018
1 parent 9682081 commit ce6b36b
Show file tree
Hide file tree
Showing 6 changed files with 144 additions and 27 deletions.
10 changes: 6 additions & 4 deletions main/3dconfig.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,15 @@ This software is released under the MIT License.
const static int window_width = 320;
const static int window_height = 240;

//#define ENDIAN_LITTLE
#define ENDIAN_LITTLE

//#define DISABLE_ANIMATION

//#define ESP32
#define DRAW_NLINES (20)

#define DRAW_NLINES (60)
#define MAXPROC_POLYNUM (300)
#ifdef ESP32

#ifndef PC
#define OMIT_ZBUFFER_CONFLICT
//comment out if U use M5Stack.
#define ILI9341
Expand Down
138 changes: 119 additions & 19 deletions main/3dmain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ uint16_t *g_zbuff;
fvector4 poly_transed[POINTNUM];
Matrix4 m;

#define ZNEAR 0.1f

float loadPower(// const fvector3 &light_pos,
const fvector3 &light_n,const fvector4 obj[3]){
fvector3 light_obj;
Expand All @@ -61,7 +63,7 @@ float loadPower(// const fvector3 &light_pos,
obj_pos.x = obj_pos.x / 3;
obj_pos.y = obj_pos.y / 3;
obj_pos.z = obj_pos.z / 3;

n = calc_nv(obj);
cos_cross = light_n * n;

Expand All @@ -86,19 +88,19 @@ bonelist bl;
static inline
bool unvisible(fvector4 *v){
if((0 > v[0].x&&0>v[1].x&&0 > v[2].x)||(window_width <= v[0].x&&window_width<=v[1].x&&window_width <= v[2].x))return 1;
//簡易1次クリッピング
if(v[0].w < 0)return 1;
if(v[2].w < 0)return 1;
if(v[1].w < 0)return 1;


return culling(v);
}

void calc_vertices(unsigned int begin,unsigned int end){
for(unsigned int j=begin;j<end;j++){
// obj_transed[j] = fvector4(pointvec[j].x,pointvec[j].y,pointvec[j].z);
#ifdef DISABLE_ANIMATION
poly_transed[j] = m.mul_fv4(fvector3(pointvec[j]));
#else
poly_transed[j] = bl.boneworld[bone_index[j]].mul_fv4(fvector3(pointvec[j]));
poly_transed[j].x=poly_transed[j].x*window_width+window_width/2;poly_transed[j].y=poly_transed[j].y*window_height+window_height/2;
#endif
poly_transed[j].x=poly_transed[j].x*window_width+window_width/2;poly_transed[j].y=poly_transed[j].y*window_height+window_height/2;
}
}

Expand All @@ -118,16 +120,19 @@ void initialize_draw_buffer(int ps){
#endif
}



void generate_polygons_and_draw(unsigned int split,unsigned int num,uint16_t *zbuff,uint16_t *drawbuff){
int searchidx = MAXPROC_POLYNUM*num/split;
unsigned mati=0;
int nextmati=0;
fvector4 v[3];
int zovercount = 0;

if(num)
initialize_draw_buffer(num-1);
nextmati = materiallist[mati].num;
nextmati = materiallist[mati].num;

for(int i=num;i<POLYNUM;i+=split){
while(i >= nextmati){
mati ++;
Expand All @@ -139,7 +144,13 @@ void generate_polygons_and_draw(unsigned int split,unsigned int num,uint16_t *zb
}
if((draw_y*DRAW_NLINES+DRAW_NLINES < v[0].y&&draw_y*DRAW_NLINES+DRAW_NLINES < v[1].y&&draw_y*DRAW_NLINES+DRAW_NLINES < v[2].y))continue;
drawidx[i] = 1;
if(unvisible(v))continue;
zovercount = 0;
for(int j=0;j<3;j++){
if(v[j].w < ZNEAR){
zovercount++;
}
}
if(zovercount==0&&unvisible(v))continue;

//光量の計算
float light = 1.0f;
Expand All @@ -148,10 +159,95 @@ void generate_polygons_and_draw(unsigned int split,unsigned int num,uint16_t *zb
texturelist[materiallist[mati].texture],//vector2(4,4)
};
fvector2 puv[3];

for(int j=0;j<3;j++){
puv[j].x = (1.f-point_uv[polyvec[i][j]].x)*SIZE_TEX;
puv[j].y = (point_uv[polyvec[i][j]].y)*SIZE_TEX;
}
if(zovercount == 1){
fvector2 uv_near;
fvector4 v_near;
printf("sprit:1");
// 1 vertex is too near the camera.
// split 2 triangles from 1 triangle.

// triangle1
float t1,t2;
int i1,i2,i3;
if(v[0].w < ZNEAR){
i1 = 0;
i2 = 1;
i3 = 2;
}else if(v[1].w < ZNEAR){
i1 = 1;
i2 = 0;
i3 = 2;
}else{
i1 = 2;
i2 = 0;
i3 = 1;
}
uv_near = puv[i1];
v_near = v[i1];
v_near.resetperspective();
t1 = 1.f-(v[i1].w-ZNEAR)/(v[i1].w-v[i2].w);
t2 = 1.f-(v[i1].w-ZNEAR)/(v[i1].w-v[i3].w);
printf(",%f,%f\n",t1,t2);
v[i2].resetperspective();
v[i1] = v_near*t1+v[i2]*(1.f-t1);
v[i2].setperspective();
v[i1].setperspective();
puv[i1] = uv_near*t1+puv[i2]*(1.f-t1);

while(searchidx < MAXPROC_POLYNUM&&tri[searchidx/TRI_MULTI][searchidx%TRI_MULTI].isexisting)searchidx++;
if(searchidx == MAXPROC_POLYNUM){
printf("TOO MUCH FACES IN THIS LINE\n");
break;
}
if(tri[searchidx/TRI_MULTI][searchidx%TRI_MULTI].triangle_set(v,light,&tex,puv)==-1||
tri[searchidx/TRI_MULTI][searchidx%TRI_MULTI].draw(zbuff,drawbuff,draw_y*DRAW_NLINES))
tri[searchidx/TRI_MULTI][searchidx%TRI_MULTI].isexisting = 0;

//triangle2
v[i3].resetperspective();
v[i2] = v_near*t2+v[i3]*(1.f-t2);
v[i2].setperspective();
v[i3].setperspective();
puv[i2] = uv_near*t2+puv[i3]*(1.f-t2);
}else if(zovercount == 2){
printf("sprit:2\n");
float t1,t2;
int i1,i2,i3;
if(v[0].w > ZNEAR){
i1 = 0;
i2 = 1;
i3 = 2;
}else if(v[1].w > ZNEAR){
i1 = 1;
i2 = 0;
i3 = 2;
}else{
i1 = 2;
i2 = 0;
i3 = 1;
}
printf("sprit:2\n");
t1 = 1.f-(v[i1].w-ZNEAR)/(v[i1].w-v[i2].w);
t2 = 1.f-(v[i1].w-ZNEAR)/(v[i1].w-v[i3].w);
v[i1].resetperspective();
v[i2].resetperspective();
v[i3].resetperspective();
v[i2] = v[i1]*t1+ v[i2]*(1.f-t1);
puv[i2] = puv[i1]*t1+ puv[i2]*(1.f-t1);
v[i3] = v[i1]*t2 + v[i3]*(1.f-t2);
puv[i3] = puv[i1]*t2+ puv[i3]*(1.f-t2);
v[i1].setperspective();
v[i2].setperspective();
v[i3].setperspective();
// printf("%f,%f",v[i2].w);
// continue
}else if(zovercount == 3)continue;//unvisible(behind the camera.)

while(searchidx < MAXPROC_POLYNUM&&tri[searchidx/TRI_MULTI][searchidx%TRI_MULTI].isexisting)searchidx++;
if(searchidx == MAXPROC_POLYNUM){
printf("TOO MUCH FACES IN THIS LINE\n");
Expand Down Expand Up @@ -238,17 +334,18 @@ int main3d(void){
Matrix4 obj;
#ifdef USE_SDL
SDL_Init(SDL_INIT_VIDEO);

SDL_Window* sdlWindow;
SDL_Event ev;
SDL_Texture *sdlTexture;
SDL_Renderer *sdlRenderer;

SDL_CreateWindowAndRenderer(window_width, window_height, SDL_WINDOW_OPENGL, &sdlWindow, &sdlRenderer);
sdlTexture = SDL_CreateTexture(sdlRenderer, SDL_PIXELFORMAT_RGB565, SDL_TEXTUREACCESS_TARGET, window_width, DRAW_NLINES);
#endif
#ifndef DISABLE_ANIMATION
bl.init(bones,sizeof(bones)/sizeof(bones[0]),sizeof(mixedbone)/sizeof(mixedbone[0]));

#endif
g_drawbuff[0] = new uint16_t[window_width*DRAW_NLINES];
g_drawbuff[1] = new uint16_t[window_width*DRAW_NLINES];
g_zbuff = new uint16_t[window_width*DRAW_NLINES];
Expand All @@ -262,13 +359,13 @@ int main3d(void){
}

//透視投影行列
projection=loadPerspective(0.25f,float(window_height)/window_width,0.0001f,30.f,0,0)*projection;
projection=loadPerspective(0.25f,float(window_height)/window_width,ZNEAR,30.f,0,0)*projection;

fvector3 viewdir;
float dist = 3.f, dd=1.0f;
float dist = 3.f;
fvector2 np = fvector2(150.f,0);
// float fps = 0.f;

fvector3 n;

float disttarget = 30.f;
Expand All @@ -283,13 +380,14 @@ int main3d(void){
#endif

#ifdef USE_SDL
// usleep(20000);
/* usleep(20000); */
if(SDL_PollEvent(&ev)){
if(ev.type == SDL_QUIT) {
break;
}
}
#endif
// disttarget -= 0.05f;
if(0){
getchar();
if(disttarget == 30.f){
Expand All @@ -307,8 +405,10 @@ int main3d(void){

veye = -fvector3(cosf(np.x/300.f*3.14159265f)*cosf(np.y/300.f*3.14159265f),sinf(np.y/300.f*3.14159265f),sinf(np.x/300.f*3.14159265f)*cosf(np.y/300.f*3.14159265f));
//透視投影行列とカメラ行列の合成
m=projection*lookat(fvector3(0,0,0),veye*dist*dd)*obj*translation(trans);
m=projection*lookat(fvector3(0,0,100),veye*dist)*obj*translation(trans);
#ifndef DISABLE_ANIMATION
bl.calcall(m);
#endif

//頂点データを変換
for(int s=0;s<PROCESSNUM-1;s++)clientps[s].vtaskstate = VTASK_VERTEX_CALCULATION;
Expand All @@ -334,7 +434,7 @@ int main3d(void){
for(int s=0;s<PROCESSNUM-1;s++)clientps[s].vtaskstate = VTASK_POLY_GENERATE;
generate_polygons_and_draw(PROCESSNUM,0,g_zbuff,g_drawbuff[lastbuff]);
barrier_sync();

merge_screen();
#ifdef USE_SDL
SDL_UpdateTexture(sdlTexture, NULL, (uint8_t*)g_drawbuff[lastbuff], window_width*2);
Expand Down
6 changes: 3 additions & 3 deletions main/esp32.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#include "3dconfig.hpp"
//disabled by default.
//uncomment if you want to execute by esp32
#ifdef ESP32
#ifndef PC
/* SPI Master example
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
Expand Down Expand Up @@ -1071,9 +1071,9 @@ void app_main()
};
spi_device_interface_config_t devcfg={
#ifdef CONFIG_LCD_OVERCLOCK
.clock_speed_hz=26*1000*1000, //Clock out at 40 MHz
.clock_speed_hz=40*1000*1000, //Clock out at 40 MHz
#else
.clock_speed_hz=26*1000*1000, //Clock out at 26 MHz
.clock_speed_hz=40*1000*1000, //Clock out at 26 MHz
#endif
.mode=0, //SPI mode 0
.spics_io_num=PIN_NUM_CS, //CS pin
Expand Down
11 changes: 11 additions & 0 deletions main/fvector4.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,17 @@ class fvector4{
v.w = -this->w;
return v;
}
void resetperspective(){
this->x *= this->w;
this->y *= this->w;
this->z *= this->w;
}
void setperspective(){
float rw = 1.f/this->w;
this->x *= rw;
this->y *= rw;
this->z *= rw;
}
};

static inline
Expand Down
2 changes: 1 addition & 1 deletion main/kbhit.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#include "3dconfig.hpp"
#ifndef ESP32
#ifdef PC
#include <stdio.h>
#include <termios.h>
#include <unistd.h>
Expand Down
4 changes: 4 additions & 0 deletions main/texturepoly.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,10 @@ int texturetriangle::draw(uint16_t *zlinebuf,uint16_t *buff,int dry){
//テクスチャの取得
dtx = tx[65535-
(((int)(cuv.x)&mask)+(((int)(cuv.y)&mask)<<shift))];

// Checkered pattern
// dtx = (((int)(cuv.x/16.f)+(int)(cuv.y/16.f))&1)*65535;

// cr = (dtx) >> 11;
// cg = ((dtx) >> 5)&0x3F;
// cb = (dtx) &0x1F;
Expand Down

0 comments on commit ce6b36b

Please sign in to comment.