You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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添加关闭背面剔除的外观属性即可,操作如下:

  1. 导入相关依赖包:
import javax.media.j3d.Appearance;
import javax.media.j3d.PolygonAttributes;
  1. 在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.11 21:57:02