p5.js下4D线条透视投影与z/w平面裁剪渲染问题排查
4D线条投影裁剪渲染问题
问题描述
- 尝试实现4D线条经3D到2D的投影流程,在z=p、w=p平面执行裁剪,无法确认渲染结果是否正确。
- 编写的可渲染4D线条程序中,负责渲染的函数接收已完成旋转的线条数据,按需在z=p、w=p平面对线条执行裁剪后绘制到屏幕。由于缺乏四维可视化相关经验,无法区分显示效果是视觉bug还是4D渲染的正常表现,无法确认当前第一人称相机4D透视投影的实现是否正确。
现有实现逻辑
- 渲染函数执行逻辑:首先将线条的两个端点分别存入对应变量,若两个端点的z、w坐标均大于裁剪平面变量
clippl(即位于裁剪平面外侧),则对端点执行透视变换后在屏幕绘制对应线条;若端点满足跨裁剪平面的判定条件,则先执行裁剪流程,再按相同逻辑完成渲染。程序初始通过Ox、Oy、Oz、Ow变量存储相机位置。 - 测试结果:在渲染列表中添加所渲染超立方体的角点后,确认点渲染逻辑正常,但点之间的线条无法稳定显示,判断线条裁剪逻辑存在问题,怀疑问题与w=p平面的裁剪实现有关。
- 程序基于p5.js开发,核心
drawPLines函数代码如下:
function drawPLines(P){ var lA,lB; for(var i=0;i<P.length;i++){ lA = [P[i][0],P[i][1],P[i][2],P[i][3]]; lB = [P[i][4],P[i][5],P[i][6],P[i][7]]; //X: ( x*VS+(width*0.5)+(ox*VS) ) //Y: ( y*VS+(height*0.5)+(oy*VS) ) //x: (XV[0]*P[i][0])+(YV[0]*P[i][1])+(ZV[0]*P[i][2])+(WV[0]*P[i][3]) //y: (XV[1]*P[i][0])+(YV[1]*P[i][1])+(ZV[1]*P[i][2])+(WV[1]*P[i][3]) var x0,y0,x1,y1; //x0 = (XV[0]*lA[0])+(YV[0]*lA[1])+(ZV[0]*lA[2])+(WV[0]*lA[3]); //y0 = (XV[1]*lA[0])+(YV[1]*lA[1])+(ZV[1]*lA[2])+(WV[1]*lA[3]); //new rendering pipeline //old rendering pipeline if(lA[2]>clippl&&lB[2]>clippl&&lA[3]>clippl&&lB[3]>clippl){ x0 = XV[0]*lA[0]; y0 = YV[1]*lA[1]; x0 = (x0/lA[3])/(lA[2]/lA[3]); y0 = (y0/lA[3])/(lA[2]/lA[3]); x0 = ( x0*VS+(width*0.5)+(ox*VS) ); y0 = ( y0*VS+(height*0.5)+(oy*VS) ); x1 = XV[0]*lB[0]; y1 = YV[1]*lB[1]; x1 = (x1/lB[3])/(lB[2]/lB[3]); y1 = (y1/lB[3])/(lB[2]/lB[3]); x1 = ( x1*VS+(width*0.5)+(ox*VS) ); y1 = ( y1*VS+(height*0.5)+(oy*VS) ); stroke([P[i][8],P[i][9],P[i][10],P[i][11]]); line(x0,y0,x1,y1); }else if((lA[2]>clippl||lA[3]>clippl||lB[2]>clippl||lB[3]>clippl)){ var V = 0; var zV = 0; var wV = 0; if(lA[2]>clippl&&lA[3]>clippl){ V++; }else if(lA[2]>clippl&&lA[3]<=clippl){ zV++; }else if(lA[2]<=clippl&&lA[3]>clippl){ wV++; } if(lB[2]>clippl&&lB[3]>clippl){ V++; }else if(lB[2]>clippl&&lB[3]<=clippl){ zV++; }else if(lB[2]<=clippl&&lB[3]>clippl){ wV++; } if((V==1)||(wV==1&&(V==1||zV==1))||(zV==1&&(V==1||wV==1))){ var lin = lB; var out = lA; if(lA[2]<=clippl){ out = lB; lin = lA; } if(lin[2]<=clippl){ lin = [((((lA[0]-lB[0])*clippl)-((lA[0]-lB[0])*lB[2]))/(lA[2]-lB[2]))+lB[0],((((lA[1]-lB[1])*clippl)-((lA[1]-lB[1])*lB[2]))/(lA[2]-lB[2]))+lB[1],clippl,((((lA[3]-lB[3])*clippl)-((lA[3]-lB[3])*lB[2]))/(lA[2]-lB[2]))+lB[3]]; } if((lA[2]-lB[2])!==0){ lA = lin; lB = out; } lin = lA; out = lB; if(lB[3]<=clippl){ out = lA; lin = lB; } if(lin[3]<=clippl){ lin = [((((lA[0]-lB[0])*clippl)-((lA[0]-lB[0])*lB[3]))/(lA[3]-lB[3]))+lB[0],((((lA[1]-lB[1])*clippl)-((lA[1]-lB[1])*lB[3]))/(lA[3]-lB[3]))+lB[1],((((lA[2]-lB[2])*clippl)-((lA[2]-lB[2])*lB[3]))/(lA[3]-lB[3]))+lB[2],clippl]; } if((lA[3]-lB[3])!==0){ lA = lin; lB = out; } if(lA[2]>clippl||lB[2]>clippl||lA[3]>clippl||lB[3]>clippl){ x0 = XV[0]*lA[0]; y0 = YV[1]*lA[1]; x0 = (x0/lA[3])/(lA[2]/lA[3]); y0 = (y0/lA[3])/(lA[2]/lA[3]); x0 = ( x0*VS+(width*0.5)+(ox*VS) ); y0 = ( y0*VS+(height*0.5)+(oy*VS) ); x1 = XV[0]*lB[0]; y1 = YV[1]*lB[1]; x1 = (x1/lB[3])/(lB[2]/lB[3]); y1 = (y1/lB[3])/(lB[2]/lB[3]); x1 = ( x1*VS+(width*0.5)+(ox*VS) ); y1 = ( y1*VS+(height*0.5)+(oy*VS) ); stroke([P[i][8],P[i][9],P[i][10],P[i][11]]); line(x0,y0,x1,y1); } } } } }
内容的提问来源于stack exchange,提问作者Joe Dimagio
相关产品推荐
相关产品推荐

