Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/html/75.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 使用xdim和ydim进行等轴测简单排序_Javascript_Html_Canvas_Isometric - Fatal编程技术网

Javascript 使用xdim和ydim进行等轴测简单排序

Javascript 使用xdim和ydim进行等轴测简单排序,javascript,html,canvas,isometric,Javascript,Html,Canvas,Isometric,我有一个带有此功能的简单等距排序系统(代码位于Typescript/Javascript): 现在我想支持对象x和y维度,那么如何在这个表达式中实现类似的东西呢? 例如,对于立方体,x和y标注值为(2,2),对于长方体,x和y标注值为(2,4) this.Position[0] + this.Position[1] + 1000 // + x dimension + y dimension ??? 等轴测视觉遮挡排序(深度排序) 定义深度: 深度值越高,越接近屏幕。与3D透视投影不同,3D透视

我有一个带有此功能的简单等距排序系统(代码位于
Typescript
/
Javascript
):

现在我想支持对象x和y维度,那么如何在这个表达式中实现类似的东西呢?

例如,对于立方体,x和y标注值为(2,2),对于长方体,x和y标注值为(2,4)

this.Position[0] + this.Position[1] + 1000 // + x dimension + y dimension ???
等轴测视觉遮挡排序(深度排序) 定义深度: 深度值越高,越接近屏幕。与3D透视投影不同,3D透视投影的深度是与前平面的距离,此答案使用深度作为与屏幕的距离

等投影 如果你有一个iso投影

const P2 = (x = 0,y = 0) => ({x, y});
const isoProjMat = {
    xAxis : P2(1   , 0.5),
    yAxis : P2(-0.5, 1  ),
    zAxis : P2(0   , -1 ),
}
这需要一个3d点并投影到屏幕空间

const P3 = (x = 0, y = 0, z = 0) => ({x, y, z});
isoProjMat.project = function (p, retP = P2()) { // p is 3D point
    retP.x = p.x * this.xAxis.x + p.y * this.yAxis.x + p.z * this.zAxis.x;
    retP.y = p.x * this.xAxis.y + p.y * this.yAxis.y + p.z * this.zAxis.y;
    return retP;
}
可以将点的深度添加为二维投影点的z值。需要为深度添加变换轴

isoProjMat.depth = P3(0.5,1, 1 );
对于x,将其尺寸y*1和z*1移近一半

修改后的
项目现在将z添加到返回点

isoProjMat.project = function (p, retP = P3()) { 
    retP.x = p.x * this.xAxis.x + p.y * this.yAxis.x + p.z * this.zAxis.x;
    retP.y = p.x * this.xAxis.y + p.y * this.yAxis.y + p.z * this.zAxis.y;
    retP.z = p.x * this.depth.x + p.y * this.depth.y + p.z * this.depth.z; 
    return retP;
}
因此,对于投影到2D iso屏幕空间的3D空间中的一组点,可以在z轴上排序

const points = mySetOfPoints(); // what ever your points come from
const projected = points.map(p => isoProjMat.project(p));
projected.sort((a,b) => a.z - b.z);
所有这些都适用于点,但对于占据3D体积的精灵,这不起作用

您需要做的是添加一个边界体积(即正方形)。如果投影是静态的,那么我们可以将边界体积简化为最近的点。对于作为右上下角顶点的长方体,例如位于(0,0,0)的精灵具有大小(10,10,20),3d中最近的点位于(10,10,20)

我无法完成您的排序,因为问题中没有足够的信息,但我猜是sprite。Iso是sprite和sprite的基本原点。平铺和平铺2表示边界框

从而得到最近的点

const depthProj = P3(0.5,1, 1 ); // depth projection matrix
// get the depth of each sprite adding the property depth
sprites.forEach(spr => {
    const p = {
        x : spr.IsoX + Math.max(spr.TileX,spr.Tile2X),
        y : spr.IsoY + Math.max(spr.TileY,spr.Tile2Y),
        z : spr.IsoZ + Math.max(spr.TileZ,spr.Tile2Z)
    };
    spr.depth = p.x * depthProj.x + p.y * depthProj.y + p.z * depthProj.z; 
})
sprites.sort((a,b) => a.depth - b.depth);
然后从索引0向上渲染

举个例子。 以下内容不完全适用,因为它按多边形排序,并使用多边形的平均深度,而不是其最大深度(确实应该使用最大深度,但不麻烦ATM)

我添加它只是为了说明如何使用
jmat
的上述代码。它从画布上渲染的像素alpha和颜色绘制堆叠框

单击“渲染结果”(rendered result)以将投影从双态切换到三态(因为您没有指定所使用的投影类型)。这显示了深度变换在两种平行投影类型之间的变化

const ctx=canvas.getContext(“2d”);
var计数=0;
var firstRun=0;
函数doIt(){
//三维二维点
常数P3=(x=0,y=0,z=0)=>({x,y,z});
常数P2=(x=0,y=0)=>({x,y});
//同构投影矩阵
常数jmat={
xAxis:计数?P2(1,0.5):P2(1,0.5),
yAxis:count?P2(-0.5,1):P2(-1,0.5),
zAxis:计数?P2(0,-1):P2(0,-1),
深度:计数?P3(0.5,1,1):P3(0.5,0.5,1),//投影以z作为深度
原点:P2(),/(0,0)默认二维点
项目(p,retP=P3()){
retP.x=p.x*this.xAxis.x+p.y*this.yAxis.x+p.z*this.zAxis.x+this.origin.x;
retP.y=p.x*this.xAxis.y+p.y*this.yAxis.y+p.z*this.zAxis.y+this.origin.y;
retP.z=p.x*this.depth.x+p.y*this.depth.y+p.z*this.depth.z;
返回retP;
}
}
//作为顶点和多边形的同构网格形状
常量isoMesh=(()=>{
常数多边形={
inds:null,
深度:0,
填充样式:“888”,
线宽:0.5,
strokeStyle:#000“,
设置样式(ctx){
ctx.fillStyle=this.fillStyle;
ctx.lineWidth=此.lineWidth;
ctx.strokeStyle=this.strokeStyle;
},
}
常数等形={
verts:null,
pVerts:null,//投影顶点
polys:null,
addVert(p3=p3(){this.verts.push(p3);返回p3},
addPoly(poly=isoShape.createPoly()){this.polys.push(poly);返回poly},
createPoly(options={}){return Object.assign({},polygon,{inds:[]},options)},
渲染(ctx,mat=jmat){
变量i,j,d;
const pv=this.pVerts==null?this.pVerts=[]:this.pVerts;
const v=this.verts;
const ps=this.polys;
对于(i=0;ia.depth-b.depth);
对于(i=0;iObject.assign({},isoShape,{verts:[],polys:[]});
})();
//惰性编码我使用点3(P3)来保存RGB值
函数createBoxMesh(box=isoMesh(),pos=P3(),size=P3(10,10,10),rgb=P3(128128)){//x,y,z是这些方向上的大小
常数PA3=(x,y,z)=>P3(x+pos.x,y+pos.y,z+pos.z);
常量RGB=(s)=>`RGB(${(RGB.x*s)|0},${(RGB.y*s)|0},${(RGB.z*s)|0});
常量indA=(inds)=>inds.map(ind=>ind+i);
const i=box.verts.length;//获取顶部垂直索引
if(typeof size==“number”){size=P3(size,size,size)}
常数x=大小x/2;
常数y=尺寸y/2;
常数z=大小z;
box.addVert(PA3(-x,-y,0));//ind 0
盒.addVert(PA3(x,-y,0));
盒.addVert(PA3(x,y,0));
盒子.地址(PA3(-x,y,0));
box.addVert(PA3(-x,-y,z));//ind 4
盒体addVert(PA3(x,-y,z));
const points = mySetOfPoints(); // what ever your points come from
const projected = points.map(p => isoProjMat.project(p));
projected.sort((a,b) => a.z - b.z);
const depthProj = P3(0.5,1, 1 ); // depth projection matrix
// get the depth of each sprite adding the property depth
sprites.forEach(spr => {
    const p = {
        x : spr.IsoX + Math.max(spr.TileX,spr.Tile2X),
        y : spr.IsoY + Math.max(spr.TileY,spr.Tile2Y),
        z : spr.IsoZ + Math.max(spr.TileZ,spr.Tile2Z)
    };
    spr.depth = p.x * depthProj.x + p.y * depthProj.y + p.z * depthProj.z; 
})
sprites.sort((a,b) => a.depth - b.depth);