Java3D使用QuadArray创建立方体时底部与背面缺失无报错如何解决
Java3D QuadArray创建立方体部分面缺失解决方案
问题说明
使用Java3D的QuadArray接口编写立方体生成代码后,运行时底部、背面部分面无报错缺失,传入Size参数为1,顶点坐标与立方体顶点完全匹配,调整顶点顺序后问题仍存在,渲染效果如下:
问题原代码
package Main.Shapes; import javax.media.j3d.QuadArray; import javax.media.j3d.Shape3D; import javax.vecmath.Point3f; import com.sun.j3d.utils.geometry.GeometryInfo; import com.sun.j3d.utils.geometry.NormalGenerator; public class Square { Shape3D shape; public Square() { } public Shape3D Make(float Size) { QuadArray polygon1 = new QuadArray (24, QuadArray.COORDINATES); //Bottom polygon1.setCoordinate(0, new Point3f (-Size/2, -Size/2, Size/2)); polygon1.setCoordinate(1, new Point3f (Size/2, -Size/2, Size/2)); polygon1.setCoordinate(2, new Point3f(Size/2, -Size/2, -Size/2)); polygon1.setCoordinate(3, new Point3f(-Size/2, -Size/2, -Size/2)); //Front polygon1.setCoordinate(4, new Point3f (-Size/2, -Size/2, Size/2)); polygon1.setCoordinate(5, new Point3f (Size/2, -Size/2, Size/2)); polygon1.setCoordinate(6, new Point3f (Size/2, Size/2, Size/2)); polygon1.setCoordinate(7, new Point3f (-Size/2, Size/2, Size/2)); //Right polygon1.setCoordinate(8, new Point3f (Size/2, -Size/2, Size/2)); polygon1.setCoordinate(9, new Point3f (Size/2, Size/2, Size/2)); polygon1.setCoordinate(10, new Point3f(Size/2, Size/2, -Size/2)); polygon1.setCoordinate(11, new Point3f(Size/2, -Size/2, -Size/2)); //Back polygon1.setCoordinate(12, new Point3f (-Size/2, -Size/2, -Size/2)); polygon1.setCoordinate(13, new Point3f (Size/2, -Size/2, -Size/2)); polygon1.setCoordinate(14, new Point3f (Size/2, Size/2, -Size/2)); polygon1.setCoordinate(15, new Point3f (-Size/2, Size/2, -Size/2)); //Left polygon1.setCoordinate(16, new Point3f (-Size/2, -Size/2, Size/2)); polygon1.setCoordinate(17, new Point3f (-Size/2, Size/2, Size/2)); polygon1.setCoordinate(18, new Point3f(-Size/2, Size/2, -Size/2)); polygon1.setCoordinate(19, new Point3f(-Size/2, -Size/2, -Size/2)); //Top polygon1.setCoordinate(20, new Point3f (-Size/2, Size/2, Size/2)); polygon1.setCoordinate(21, new Point3f (Size/2, Size/2, Size/2)); polygon1.setCoordinate(22, new Point3f(Size/2, Size/2, -Size/2)); polygon1.setCoordinate(23, new Point3f(-Size/2, Size/2, -Size/2)); GeometryInfo GI = new GeometryInfo(polygon1); NormalGenerator normalGenerator = new NormalGenerator(); normalGenerator.generateNormals(GI); shape = new Shape3D(GI.getIndexedGeometryArray()); return shape; } }
问题根源
Java3D默认开启背面剔除功能,渲染时会自动剔除顶点顺序为顺时针的面(从面的外侧视角判断顶点顺序,逆时针为正面)。你代码中底部、背面的顶点顺序从外侧看为顺时针,所以被判定为背面直接跳过渲染,不会产生任何报错。
解决方案
方案1:调整异常面的顶点顺序
将底部、背面的顶点顺序调整为外侧视角下的逆时针即可:
- 底部面顶点顺序修改为
0→3→2→1 - 背面面顶点顺序修改为
12→15→14→13
修改后的对应代码如下:
// 修改后的Bottom部分 polygon1.setCoordinate(0, new Point3f (-Size/2, -Size/2, Size/2)); polygon1.setCoordinate(1, new Point3f(-Size/2, -Size/2, -Size/2)); polygon1.setCoordinate(2, new Point3f(Size/2, -Size/2, -Size/2)); polygon1.setCoordinate(3, new Point3f (Size/2, -Size/2, Size/2)); // 修改后的Back部分 polygon1.setCoordinate(12, new Point3f (-Size/2, -Size/2, -Size/2)); polygon1.setCoordinate(13, new Point3f (-Size/2, Size/2, -Size/2)); polygon1.setCoordinate(14, new Point3f (Size/2, Size/2, -Size/2)); polygon1.setCoordinate(15, new Point3f (Size/2, -Size/2, -Size/2));
方案2:关闭背面剔除功能
如果不想调整顶点顺序,直接为Shape3D添加关闭背面剔除的外观属性即可,操作如下:
- 导入相关依赖包:
import javax.media.j3d.Appearance; import javax.media.j3d.PolygonAttributes;
- 在Make方法中创建Appearance对象并配置背面剔除规则:
// 生成法线代码后添加以下内容 Appearance app = new Appearance(); PolygonAttributes pa = new PolygonAttributes(); pa.setCullFace(PolygonAttributes.CULL_NONE); // 关闭所有面的剔除 app.setPolygonAttributes(pa); // 创建Shape3D时传入外观对象 shape = new Shape3D(GI.getIndexedGeometryArray(), app);
两种方案任选其一即可解决面缺失问题。
内容的提问来源于stack exchange,提问作者Hoax
相关产品推荐
相关产品推荐

