如何在javascript中实现3D可视化的DDA算法?
How to implement DDA algorythm for 3D visualisation in javascript?
我正在研究体素引擎,我的 DDA 算法有问题,该引擎是用 javascript 编写的。数据是基本的 3D 网格。现在,算法看起来像这样:
function RayDDA(Xs,Zs,d,xB,yB) {
var directionVector = [Math.round(Xs*100000000)/100000000,Math.round(d*100000000)/100000000,Math.round(Zs*100000000)/100000000]
var step = [0,0,0]
var invDir = [0,0,0]
var T = [0,0,0]
var DeltaT = [0,0,0]
var VoxelIncr = [0,0,0]
var CurrentV = [camera[0],camera[1],camera[2]]
for (var i = 0;i<3;i++) {
if (directionVector[i] != 0) {
if (directionVector[i]<0) {
step[i] = -1
}
else {
step[i] = 1
}
invDir[i] = 1/directionVector[i]
T[i] = CurrentV[i]-directionVector[i]
//T[i] = Math.sqrt((CurrentV[0]-directionVector[0])**2+(CurrentV[1]-directionVector[1])**2+(CurrentV[2]-directionVector[2])**2)
}
else {
invDir[i] = 100000000000000011111
T[i] = 111111111111111102221
}
}
for (var i =0;i<3;i++) {
DeltaT[i]=invDir[i]
}
while (true) {
VoxelIncr[0] = (T[0]<=T[1] && T[0]<=T[2])
VoxelIncr[1] = (T[1]<=T[0] && T[1]<=T[2])
VoxelIncr[2] = (T[2]<=T[0] && T[2]<=T[1])
T[0]+=DeltaT[0]
T[1]+=DeltaT[1]
T[2]+=DeltaT[2]
CurrentV[0]+=VoxelIncr[0]*step[0]
CurrentV[1]+=VoxelIncr[1]*step[1]
CurrentV[2]+=VoxelIncr[2]*step[2]
var rotateDir = [CurrentV[0],CurrentV[1],CurrentV[2]]
if (Math.sqrt(CurrentV[0]**2+CurrentV[1]**2+CurrentV[2]**2)>ray_length) {
break
}
if (parseInt(rotateDir[2]) < map.length && parseInt(rotateDir[1]) < map[0].length && parseInt(rotateDir[0]) < map[0][0].length && parseInt(rotateDir[2]) >= 0 && parseInt(rotateDir[1]) >= 0 && parseInt(rotateDir[0]) >= 0 && map[parseInt(rotateDir[2])][parseInt(rotateDir[1])][parseInt(rotateDir[0])][0] == 1) {
//drawn the pixel
break
}
}
}
算法来自这篇论文:The pdf
我做错了什么?
编辑:最后我发现了问题。事实上,我忘了放一些值。但对于对光线投射引擎感兴趣的人:这里是 javascript.
中的 DDA 算法
所以都是我的错,我忘了正确复制算法,所以这是正确的代码:
function RayDDA(Xs,Zs,d,xB,yB) {
var directionVector = rotateZ(Math.round(Xs*100000000)/100000000,Math.round(d*100000000)/100000000,Math.round(Zs*100000000)/100000000,direction[0])
var step = [0,0,0]
var invDir = [0,0,0]
var T = [0,0,0]
var DeltaT = [0,0,0]
var VoxelIncr = [0,0,0]
var CurrentV = [camera[0],camera[1],camera[2]]
for (var i = 0;i<3;i++) {
if (directionVector[i] != 0) {
if (directionVector[i]<0) {
step[i] = -1
}
else {
step[i] = 1
}
invDir[i] = Math.abs(1/directionVector[i])
T[i] = CurrentV[i]-directionVector[i]
}
else {
invDir[i] = 100000000000000011111
T[i] = 111111111111111102221
}
}
for (var i =0;i<3;i++) {
DeltaT[i]=invDir[i]
}
while (true) {
if (T[0]<=T[1] && T[0]<=T[2]) {
VoxelIncr[0] = 1
}
else {
VoxelIncr[0] = 0
}
if (T[1]<=T[0] && T[1]<=T[2]) {
VoxelIncr[1] = 1
}
else {
VoxelIncr[1] = 0
}
if (T[2]<=T[1] && T[2]<=T[0]) {
VoxelIncr[2] = 1
}
else {
VoxelIncr[2] = 0
}
T[0]+=DeltaT[0]*VoxelIncr[0]
T[1]+=DeltaT[1]*VoxelIncr[1]
T[2]+=DeltaT[2]*VoxelIncr[2]
CurrentV[0]+=VoxelIncr[0]*step[0]
CurrentV[1]+=VoxelIncr[1]*step[1]
CurrentV[2]+=VoxelIncr[2]*step[2]
var rotateDir = [CurrentV[0],CurrentV[1],CurrentV[2]]
if (Math.sqrt(CurrentV[0]**2+CurrentV[1]**2+CurrentV[2]**2)>ray_length) {
break
}
if (parseInt(rotateDir[2]) < map.length && parseInt(rotateDir[1]) < map[0].length && parseInt(rotateDir[0]) < map[0][0].length && parseInt(rotateDir[2]) >= 0 && parseInt(rotateDir[1]) >= 0 && parseInt(rotateDir[0]) >= 0 && map[parseInt(rotateDir[2])][parseInt(rotateDir[1])][parseInt(rotateDir[0])][0] == 1) {
var color = map[parseInt(rotateDir[2])][parseInt(rotateDir[1])][parseInt(rotateDir[0])][1]
ctx.fillStyle = 'rgb('+color[0]+","+color[1]+","+color[2]+")"
ctx.fillRect(xB*canvas.width/resolution[0],yB*canvas.height/resolution[1],canvas.width/resolution[0],canvas.height/resolution[1]);
break
}
}
}
我正在研究体素引擎,我的 DDA 算法有问题,该引擎是用 javascript 编写的。数据是基本的 3D 网格。现在,算法看起来像这样:
function RayDDA(Xs,Zs,d,xB,yB) {
var directionVector = [Math.round(Xs*100000000)/100000000,Math.round(d*100000000)/100000000,Math.round(Zs*100000000)/100000000]
var step = [0,0,0]
var invDir = [0,0,0]
var T = [0,0,0]
var DeltaT = [0,0,0]
var VoxelIncr = [0,0,0]
var CurrentV = [camera[0],camera[1],camera[2]]
for (var i = 0;i<3;i++) {
if (directionVector[i] != 0) {
if (directionVector[i]<0) {
step[i] = -1
}
else {
step[i] = 1
}
invDir[i] = 1/directionVector[i]
T[i] = CurrentV[i]-directionVector[i]
//T[i] = Math.sqrt((CurrentV[0]-directionVector[0])**2+(CurrentV[1]-directionVector[1])**2+(CurrentV[2]-directionVector[2])**2)
}
else {
invDir[i] = 100000000000000011111
T[i] = 111111111111111102221
}
}
for (var i =0;i<3;i++) {
DeltaT[i]=invDir[i]
}
while (true) {
VoxelIncr[0] = (T[0]<=T[1] && T[0]<=T[2])
VoxelIncr[1] = (T[1]<=T[0] && T[1]<=T[2])
VoxelIncr[2] = (T[2]<=T[0] && T[2]<=T[1])
T[0]+=DeltaT[0]
T[1]+=DeltaT[1]
T[2]+=DeltaT[2]
CurrentV[0]+=VoxelIncr[0]*step[0]
CurrentV[1]+=VoxelIncr[1]*step[1]
CurrentV[2]+=VoxelIncr[2]*step[2]
var rotateDir = [CurrentV[0],CurrentV[1],CurrentV[2]]
if (Math.sqrt(CurrentV[0]**2+CurrentV[1]**2+CurrentV[2]**2)>ray_length) {
break
}
if (parseInt(rotateDir[2]) < map.length && parseInt(rotateDir[1]) < map[0].length && parseInt(rotateDir[0]) < map[0][0].length && parseInt(rotateDir[2]) >= 0 && parseInt(rotateDir[1]) >= 0 && parseInt(rotateDir[0]) >= 0 && map[parseInt(rotateDir[2])][parseInt(rotateDir[1])][parseInt(rotateDir[0])][0] == 1) {
//drawn the pixel
break
}
}
}
算法来自这篇论文:The pdf
我做错了什么?
编辑:最后我发现了问题。事实上,我忘了放一些值。但对于对光线投射引擎感兴趣的人:这里是 javascript.
中的 DDA 算法所以都是我的错,我忘了正确复制算法,所以这是正确的代码:
function RayDDA(Xs,Zs,d,xB,yB) {
var directionVector = rotateZ(Math.round(Xs*100000000)/100000000,Math.round(d*100000000)/100000000,Math.round(Zs*100000000)/100000000,direction[0])
var step = [0,0,0]
var invDir = [0,0,0]
var T = [0,0,0]
var DeltaT = [0,0,0]
var VoxelIncr = [0,0,0]
var CurrentV = [camera[0],camera[1],camera[2]]
for (var i = 0;i<3;i++) {
if (directionVector[i] != 0) {
if (directionVector[i]<0) {
step[i] = -1
}
else {
step[i] = 1
}
invDir[i] = Math.abs(1/directionVector[i])
T[i] = CurrentV[i]-directionVector[i]
}
else {
invDir[i] = 100000000000000011111
T[i] = 111111111111111102221
}
}
for (var i =0;i<3;i++) {
DeltaT[i]=invDir[i]
}
while (true) {
if (T[0]<=T[1] && T[0]<=T[2]) {
VoxelIncr[0] = 1
}
else {
VoxelIncr[0] = 0
}
if (T[1]<=T[0] && T[1]<=T[2]) {
VoxelIncr[1] = 1
}
else {
VoxelIncr[1] = 0
}
if (T[2]<=T[1] && T[2]<=T[0]) {
VoxelIncr[2] = 1
}
else {
VoxelIncr[2] = 0
}
T[0]+=DeltaT[0]*VoxelIncr[0]
T[1]+=DeltaT[1]*VoxelIncr[1]
T[2]+=DeltaT[2]*VoxelIncr[2]
CurrentV[0]+=VoxelIncr[0]*step[0]
CurrentV[1]+=VoxelIncr[1]*step[1]
CurrentV[2]+=VoxelIncr[2]*step[2]
var rotateDir = [CurrentV[0],CurrentV[1],CurrentV[2]]
if (Math.sqrt(CurrentV[0]**2+CurrentV[1]**2+CurrentV[2]**2)>ray_length) {
break
}
if (parseInt(rotateDir[2]) < map.length && parseInt(rotateDir[1]) < map[0].length && parseInt(rotateDir[0]) < map[0][0].length && parseInt(rotateDir[2]) >= 0 && parseInt(rotateDir[1]) >= 0 && parseInt(rotateDir[0]) >= 0 && map[parseInt(rotateDir[2])][parseInt(rotateDir[1])][parseInt(rotateDir[0])][0] == 1) {
var color = map[parseInt(rotateDir[2])][parseInt(rotateDir[1])][parseInt(rotateDir[0])][1]
ctx.fillStyle = 'rgb('+color[0]+","+color[1]+","+color[2]+")"
ctx.fillRect(xB*canvas.width/resolution[0],yB*canvas.height/resolution[1],canvas.width/resolution[0],canvas.height/resolution[1]);
break
}
}
}