不用浮点运算的3D图形算法~
神之觉醒2015/05/04软件综合 IP:广西
用浮点运算很浪费时间, 于是就想了一个办法...
屏幕坐标都是整数, 我们不需要尾数, 把一个0.0000000 ~ 1.0000000 的数表示成0x00~0x80,最高位和低7位的中间是小数点, 由于二进制小数表示十进制小数会有误差,只能取近似值, 比如0.7880108,取0.7890625也就是0x65, 要把一个二进制整数调整成0.7890625倍, 只需要用0x65乘上那个整数再右移7位, OK , 按这个思路弄进程序里面运行...

运行效果:
XXXXXXXXXXXXXXXXXXXX/programs/view/TNCI_Cbmb-E/
点击此处查看视频


测试.png

测试1.png

KC-LS1u机原理图 : https://www.kechuang.org/t/71330
KC-LS1u的C程序代码(乱七八糟的写来测试一下,暂时没进行特别优化, 即兴编写):
#include<io.h>

int sin[91] =  //格式 : 低8位的最高位为整数,尾数为小数
{
0x00, //sin(0) = 0 无误差
0x02, //sin(1) = 0.0174524,这里取值0.015625
0x04, //sin(2) = 0.0348995,这里取值0.03125
0x07, //sin(3) = 0.052336,这里取值0.0546875
0x09, //sin(4) = 0.0697565,这里取值0.0703125
0x0b, //sin(5) = 0.0871557,这里取值0.0859375
0x0d, //sin(6) = 0.1045285,这里取值0.1015625
0x10, //sin(7) = 0.1218693,这里取值0.125
0x12, //sin(8) = 0.1391731,这里取值0.140625
0x14, //sin(9) = 0.1564344,这里取值0.15625
0x16, //sin(10) = 0.1736482,这里取值0.171875
0x18, //sin(11) = 0.190809,这里取值0.1875
0x1b, //sin(12) = 0.2079117,这里取值0.2109375
0x1d, //sin(13) = 0.2249511,这里取值0.2265625
0x1f, //sin(14) = 0.2419219,这里取值0.2421875
0x21, //sin(15) = 0.258819,这里取值0.2578125
0x23, //sin(16) = 0.2756374,这里取值0.2734375
0x25, //sin(17) = 0.2923717,这里取值0.2890625
0x28, //sin(18) = 0.309017,这里取值0.3125
0x2a, //sin(19) = 0.3255682,这里取值0.328125
0x2c, //sin(20) = 0.3420201,这里取值0.34375
0x2e, //sin(21) = 0.3583679,这里取值0.359375
0x30, //sin(22) = 0.3746066,这里取值0.375
0x32, //sin(23) = 0.3907311,这里取值0.390625
0x34, //sin(24) = 0.4067366,这里取值0.40625
0x36, //sin(25) = 0.4226183,这里取值0.421875
0x38, //sin(26) = 0.4383711,这里取值0.4375
0x3a, //sin(27) = 0.4539905,这里取值0.453125
0x3c, //sin(28) = 0.4694716,这里取值0.46875
0x3e, //sin(29) = 0.4848096,这里取值0.484375
0x40, //sin(30) = 0.5, 无误差
0x42, //sin(31) = 0.5150381,这里取值0.515625
0x44, //sin(32) = 0.5299193,这里取值0.53125
0x46, //sin(33) = 0.544639,这里取值0.546875
0x48, //sin(34) = 0.5591929,这里取值0.5625
0x49, //sin(35) = 0.5735764,这里取值0.5703125
0x4b, //sin(36) = 0.5877852,这里取值0.5859375
0x4d, //sin(37) = 0.601815,这里取值0.6015625
0x4f, //sin(38) = 0.6156615,这里取值0.6171875
0x51, //sin(39) = 0.6293204,这里取值0.6328125
0x52, //sin(40) = 0.6427876,这里取值0.640625
0x54, //sin(41) = 0.656059,这里取值0.65625
0x56, //sin(42) = 0.6691306,这里取值0.671875
0x57, //sin(43) = 0.6819984,这里取值0.6796875
0x59, //sin(44) = 0.6946584,这里取值0.6953125
0x5a, //sin(45) = 0.7071068,这里取值0.7109375
0x5c, //sin(46) = 0.7193398,这里取值0.71875
0x5e, //sin(47) = 0.7313537,这里取值0.734375
0x5f, //sin(48) = 0.7431448,这里取值0.7421875
0x61, //sin(49) = 0.7547096,这里取值0.7578125
0x62, //sin(50) = 0.7660444,这里取值0.765625
0x63, //sin(51) = 0.777146,这里取值0.7734375
0x65, //sin(52) = 0.7880108,这里取值0.7890625
0x66, //sin(53) = 0.7986355,这里取值0.796875
0x68, //sin(54) = 0.809017,这里取值0.8125
0x69, //sin(55) = 0.819152,这里取值0.8203125
0x6a, //sin(56) = 0.8290376,这里取值0.828125
0x6b, //sin(57) = 0.838671,这里取值0.8359375
0x6d, //sin(58) = 0.8480481,这里取值0.8515625
0x6e, //sin(59) = 0.8571673,这里取值0.859375
0x6f, //sin(60) = 0.8660254,这里取值0.8671875
0x70, //sin(61) = 0.8746197,这里取值0.875
0x71, //sin(62) = 0.8829476,这里取值0.8828125
0x72, //sin(63) = 0.8910065,这里取值0.890625
0x73, //sin(64) = 0.8987941,这里取值0.8984375
0x74, //sin(65) = 0.9063078,这里取值0.90625
0x75, //sin(66) = 0.9135455,这里取值0.9140625
0x76, //sin(67) = 0.9205049,这里取值0.921875
0x77, //sin(68) = 0.9271839,这里取值0.9296875
0x78, //sin(69) = 0.9335804,这里取值0.9375
0x78, //sin(70) = 0.9396926,这里取值0.9375
0x79, //sin(71) = 0.9455186,这里取值0.9453125
0x7a, //sin(72) = 0.9510565,这里取值0.953125
0x7a, //sin(73) = 0.9563048,这里取值0.953125
0x7b, //sin(74) = 0.9612617,这里取值0.9609375
0x7c, //sin(75) = 0.9659258,这里取值0.96875
0x7c, //sin(76) = 0.9702957,这里取值0.96875
0x7d, //sin(77) = 0.9743701,这里取值0.9765625
0x7d, //sin(78) = 0.9781476,这里取值0.9765625
0x7e, //sin(79) = 0.9816272,这里取值0.984375
0x7e, //sin(80) = 0.9848078,这里取值0.984375
0x7e, //sin(81) = 0.9876883,这里取值0.984375
0x7f, //sin(82) = 0.9902681,这里取值0.9921875
0x7f, //sin(83) = 0.9925462,这里取值0.9921875
0x7f, //sin(84) = 0.9945219,这里取值0.9921875
0x7f, //sin(85) = 0.9961947,这里取值0.9921875
0x80, //sin(86) = 0.9975641,这里取值1
0x80, //sin(87) = 0.9984295,这里取值1
0x80, //sin(88) = 0.9993908,这里取值1
0x80, //sin(89) = 0.9998477,这里取值1
0x80  //sin(90) = 1,这里取值1
};


int sin_360[361];
int cos_360[361];


void sin_cos_csh()
{
unsigned int D = 0;
while(D != 361)
{
   if(D < 91) //角度为0到90度 取出sin值和cos值
   {
      sin_360[D] = sin[D];
      cos_360[D] = sin[90 - D];
   }
   else if(D > 90 && D < 181) //角度为91到180度 取出sin值和cos值
   {
      sin_360[D] = sin[180 - D];
      cos_360[D] = -sin[D - 90];
   }
   else if(D > 180 && D < 271) //角度为181到270度 取出sin值和cos值
   {
      sin_360[D] = -sin[D - 180];
      cos_360[D] = -sin[270 - D];
   }
   else //角度为271到360度 取出sin值和cos值
   {
      sin_360[D] = -sin[360 - D];
      cos_360[D] = sin[D - 270];
   }
   ++D;
}
}

void yuan(VRAMY,VRAMX,XD,YD,ZD,r,VRAM_DATA)
{
   int dd = 0,Y,X,Z,y,x,_sin,_cos;
   int _Y,_X,_Z;
   do
   {
      _sin = sin_360[dd];
      _cos = cos_360[dd];
      X = _cos*r >> 7;
      _Y = _sin*r >> 7;
      _sin = sin_360[XD];
      _cos = cos_360[XD];
      Y = _cos*_Y >> 7;
      _Z = _sin*_Y >> 7;
      _sin = sin_360[YD];
      _cos = cos_360[YD];
//     Z = _cos*_Z - _sin*X >> 7;
      _X = _sin*_Z + _cos*X >> 7;
      _sin = sin_360[ZD];
      _cos = cos_360[ZD];
      X = _cos*_X - _sin*Y >> 7;
      Y = _sin*_X + _cos*Y >> 7;

      y = VRAMY - Y; //转换为实际坐标
      x = VRAMX + X;
      VRAM[(y << 8) | (x & 0x00ff)] = VRAM_DATA; //写入显存
      dd += 10;
   }while(dd < 360);
}

void VRAM_qingping(unsigned char Y,unsigned char _Y,unsigned char DATA)
{
while(Y != _Y)
{
   _B = DATA;
   _A = 0;
   do
   {
     _A1 = Y;
     _A2 = 0x80;
     _A0 = _A;
     _NOP;
     _RAM = _B;
     _A = _A + 1;
     _A0 = _A;
     _NOP;
     _RAM = _B;
     _A = _A + 1;
     _A0 = _A;
     _NOP;
     _RAM = _B;
     _A = _A + 1;
     _A0 = _A;
     _NOP;
     _RAM = _B;
     _A = _A + 1;
     _A0 = _A;
     _NOP;
     _RAM = _B;
     _A = _A + 1;
     _A0 = _A;
     _NOP;
     _RAM = _B;
     _A = _A + 1;
     _A0 = _A;
     _NOP;
     _RAM = _B;
     _A = _A + 1;
     _A0 = _A;
     _NOP;
     _RAM = _B;
     _A = _A + 1;
   }while(_SUB_A_1 != -1);
   ++Y;
}

}

void zhongxinzhou(VRAMY,VRAMX,XD,YD,ZD,VRAM_DATA)
{

   int zz = -32,Y,X,Z,y,x,_sin,_cos;
   int _Y,_X,_Z;
   do
   {
      _sin = sin_360[XD];
      _cos = cos_360[XD];
      Y = - _sin*zz >> 7;
      _Z =  _cos*zz >> 7;
      _sin = sin_360[YD];
      _cos = cos_360[YD];
//     Z = _cos*_Z >> 7;
      _X = _sin*_Z >> 7;
      _sin = sin_360[ZD];
      _cos = cos_360[ZD];
      X = _cos*_X - _sin*Y >> 7;
      Y = _sin*_X + _cos*Y >> 7;

      y = VRAMY - Y; //转换为实际坐标
      x = VRAMX + X;
      VRAM[(y << 8) | (x & 0x00ff)] = VRAM_DATA; //写入显存
      zz += 4;
   }while(zz < 32);


}

main()
{
   int i,YD = 0,XD = 0,ZD = 0;
   VRAM_qingping(0,240,0x00);
   sin_cos_csh();
   while(1)
   {
      CTVGA_C &= ~0x01; //请求访问VRAM
      while((CTVGA_C & 0x80) == 0x80); //可以访问的时候跳出
      VRAM_qingping(120 - 100,120 + 100,0x00);

    //  ++YD;
   //   ++YD;
   //   if(YD == 360) YD = 0;
      ++XD;
      ++XD;
      ++XD;
      if(XD == 360) XD = 0;
      ++ZD;
      if(ZD == 360) ZD = 0;

      zhongxinzhou(120,128,XD,YD,ZD,0x1f);
      yuan(120,128,XD,YD,ZD,32,0x03);
      yuan(120,128,XD,YD,ZD,64,0xe0);
      yuan(120,128,XD,YD,ZD,80,0x13);
      yuan(120,128,XD,YD,ZD,96,0xe5);

      CTVGA_C |= 0x01; //请求VRAM显示
      for(i = 0;i != 7000;++i);
   }

}
来自:计算机科学 / 软件综合
23
 
已屏蔽 原因:{{ notice.reason }}已屏蔽
{{notice.noticeContent}}
~~空空如也
神之觉醒 作者
9年0个月前 IP:广西
766861
只需要大量整数乘法运算和移位运算.. 很容易构建一个简单的硬件运算器, 加速运算~~~~
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
gkcn
9年0个月前 IP:江苏
766875
你这是TI使用的Q格式。。你可以看看他们的库。。写的很全。。算法很多
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
smith
9年0个月前 IP:广东
766876
编译器用的是什么
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
.........
9年0个月前 IP:江西
766900
现在FPU那么普及了,定点数优势不大啊。
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
既不回头
9年0个月前 IP:广东
766901
不懂c,菜鸟一枚得去把c弄懂先[s::lol]
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
cccyl
9年0个月前 IP:广东
766905
不错,感觉略屌,可是帧率好像有点低,一卡一卡的
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
acmilan
9年0个月前 IP:四川
766927
不错,查表法[s::lol]
不过目测有误差抖动,帧率也有点小。。。有FPU的话还是用浮点数好了
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
fshwen
9年0个月前 IP:广东
766962
楼主应该赶快开发第二代CPU
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
神之觉醒作者
9年0个月前 IP:广西
766964
引用 smith:
编译器用的是什么
独家搭配KC-LS1uC编译器, 每行代码都亲自动手..
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
神之觉醒作者
9年0个月前 IP:广西
766965
引用 .........:
现在FPU那么普及了,定点数优势不大啊。
看场合
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
神之觉醒作者
9年0个月前 IP:广西
766966
引用 cccyl:
不错,感觉略屌,可是帧率好像有点低,一卡一卡的
暂时只能做到这样了... https://www.kechuang.org/t/71398
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
神之觉醒作者
9年0个月前 IP:广西
766967
引用 acmilan:
不错,查表法
不过目测有误差抖动,帧率也有点小。。。有FPU的话还是用浮点数好了
嗯~ 查表法很常见的   这里核心是一个整数和一个小数相乘
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
神之觉醒作者
9年0个月前 IP:广西
766968
引用 fshwen:
楼主应该赶快开发第二代CPU
第二代玩具CPU, 可能会N个CPU并行处理~
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
傅rank
9年0个月前 IP:北京
767101
想法不错
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
神之觉醒作者
9年0个月前 IP:广西
767319
这个经典的坐标变换挺好玩的, 通过组合变换可以让空间坐标绕Z轴X轴Y轴旋转~~~  转转转转转转转转转转转转转转转转转转转转转转转转转转转转转转转转

绕Z轴旋转:
X = cos(角度)*X - sin(角度)*Y;
Y =  sin(角度)*X + cos(角度)*Y;

绕X轴旋转:
Y = cos(角度)*Y - sin(角度)*Z;
Z =  sin(角度)*Y + cos(角度)*Z;

绕Y轴旋转:
Z = cos(角度)*Z - sin(角度)*X;
X =  sin(角度)*Z + cos(角度)*X;


然后再加上缩放平移神魔的......  就可以用代码构建一个属于你的3D世界....  高级点的话再弄填充、纹理、光照上去~~
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
rpg-7
9年0个月前 IP:江苏
767764
浮点模块貌似就是前x位做数字位,后y位做小数点,大约相当于X*10^y的样子吧。。。然后算起来前面的归前面的,后面的归后面的。。。。事实上就是搞得复杂点的整数ALU。。。。记得不太清楚了。。。
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
acmilan
8年11个月前 IP:四川
770180
楼主的8位计算机?搞3D运算的话还是要有强大的FPU,不然很吃力。
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
strange
8年9个月前 IP:广东
780536
void yuan(VRAMY,VRAMX,XD,YD,ZD,r,VRAM_DATA)
求头文件<io.h>...[s::)]
我也想写一个编译器
最近看了Linux0.11把内核写进你的机
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
神之觉醒作者
8年9个月前 IP:广西
780583
引用 strange:
void yuan(VRAMY,VRAMX,XD,YD,ZD,r,VRAM_DATA)
求头文件<io.h>...
我也想写一个编译器
最近看了Linux0.11把内核写进你的机
要是在其他机上跑, 直接操作显存 "VRAM" , "VRAM" 这里是一个数组, 偏移低8位是X坐标, 高8位是Y坐标, 写入数组的数据是8位像素数据,  其他机上跑有 "CTVGA_C" 的语句可以不用, 还有main函数下面那个for 7000延时也不用,

VRAM_qingping() 是擦除屏幕, 里面有机器码.. 要是想跑的话, 改下这个函数OK, <io.h> 暂时没什么东西..

Linux  没详细研究= = 不知道能不能跑,
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
那抹余辉
8年7个月前 IP:北京
791017
引用 神之觉醒:
要是在其他机上跑, 直接操作显存 "VRAM" , "VRAM" 这里是一个数组, 偏移低8位是X坐标, 高8位是Y坐标, 写入数组的数据是8位像素数据,  其他机上跑有 "CTVGA_C" 的语句可以不用, 还有main函数下面那个for...
我还没搞懂怎么让屏幕显示图案,跟别说3D变化了
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
广东穷佬仔
8年7个月前 IP:广东
791085
有想法应该支持,先顶一个
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
季节逝去
8年7个月前 IP:福建
791284
其实我看不懂你写的。你这是用C语言的吗?
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
acmilan
7年6个月前 修改于 7年6个月前 IP:四川
827081
感觉挺不错的,如果用透视投影就好了→_→
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论

想参与大家的讨论?现在就 登录 或者 注册

所属专业
所属分类
上级专业
同级专业
神之觉醒
学者 机友 笔友
文章
71
回复
1163
学术分
4
2011/08/12注册,1年3个月前活动
暂无简介
主体类型:个人
所属领域:无
认证方式:手机号
IP归属地:未同步
文件下载
加载中...
{{errorInfo}}
{{downloadWarning}}
你在 {{downloadTime}} 下载过当前文件。
文件名称:{{resource.defaultFile.name}}
下载次数:{{resource.hits}}
上传用户:{{uploader.username}}
所需积分:{{costScores}},{{holdScores}}下载当前附件免费{{description}}
积分不足,去充值
文件已丢失

当前账号的附件下载数量限制如下:
时段 个数
{{f.startingTime}}点 - {{f.endTime}}点 {{f.fileCount}}
视频暂不能访问,请登录试试
仅供内部学术交流或培训使用,请先保存到本地。本内容不代表科创观点,未经原作者同意,请勿转载。
音频暂不能访问,请登录试试
支持的图片格式:jpg, jpeg, png
插入公式
评论控制
加载中...
文号:{{pid}}
投诉或举报
加载中...
{{tip}}
请选择违规类型:
{{reason.type}}

空空如也

加载中...
详情
详情
推送到专栏从专栏移除
设为匿名取消匿名
查看作者
回复
只看作者
加入收藏取消收藏
收藏
取消收藏
折叠回复
置顶取消置顶
评学术分
鼓励
设为精选取消精选
管理提醒
编辑
通过审核
评论控制
退修或删除
历史版本
违规记录
投诉或举报
加入黑名单移除黑名单
查看IP
{{format('YYYY/MM/DD HH:mm:ss', toc)}}