java 数据转换引擎_使用Java实现3d引擎--渲染系统

目前代码已经在Github:https://github.com/Qinxianshen/GameEngine-Java-3D

GameEngine-Java-3D

使用Java实现一个游戏引擎

编写一个Vector2f - 2维向量

添加运算 求模 点积 单位化 旋转 向量加减乘除

编写一个Vector3f - 3维向量

添加运算 求模 点积 外积(叉积) 单位化 旋转 向量加减乘除

在添加Camera前,要在Vector3f内添加 旋转公式

728f6c1808781e986cb3924624cdebb1.png

e31aab0e75abc8a4336175a376596157.png

三维旋转:欧拉角、四元数、旋转矩阵、轴角之间的转换

编写一个Quaternion - 四元数 简化旋转计算

添加运算 求模 单位化 四元数乘法

编写一个Matrix4f - 四维矩阵

添加运算 单位化 四元数乘法

添加Transorm前要添加好矩阵平移与旋转运算的初始化

平移

旋转

缩放

ff49b71c47371f2f8294b959ffa095c3.png

透视投影

3ee86d3ee15d00f8d34cb7b148e8e502.png

透视投影公式证明过程

世界坐标系向摄像机坐标系转化 --->摄像机矩阵

编写Vertex 类

3维点结构

编写Mesh

添加顶点 并 绘制

8db20136fde68bd1d6bcfc8e1d4bea85.png

添加mesh face 使用基于面渲染 而不是点渲染 减少冗余数据

mesh的资源文件有 以vs后缀结尾 与 以 fs结尾 两类 在model的obj文件里记录了 v(顶点) 与 f(点的连接顺序)的信息

下面以box.obj为例:

任意的模型的面都能由 三角形碎片拼接而成(因为三角形不可再分) c5e0e0109c21c804b7fac0e12ed4bd75.png

创建资源文件夹res

models

shaders --着色器

textures

shaders --着色器

fs后缀名的文件类型,通常是指矢量文件格式

textures 纹理

为平面加入纹理:

创建资源加载器

资源文件类型

shaders 着色器文件 vs fs GLSL编写文件

model 文件 blender 导出的obj文件 加载到mesh中

其中obj文件里记录了两类信息 v-->顶点坐标信息 f-->mesh face的信息 下图为通过 obj加载器 加载blender导出的方块

根据文件路径加载文件资源

编写 shaders 着色器

为资源着色

其中使用了GLSL着色语言写的资源

GLSL - OpenGL Shading Language 也称作 GLslang,是一个以C语言为基础的高阶着色语言。它是由 OpenGL ARB 所建立,提供开发者对绘图管线更多的直接控制,而无需使用汇编语言或硬件规格语言。 已在渲染管线中的顶点(vertex)和片断(fragment)层次中,加入更具弹性的新功能。 达到在这个层次中,使用片断和顶点着色器的可编程性

为shaders 添加Uniform方法

动态调整颜色

编写Transorm

平移 Translation

旋转 Rotation

缩放 Scale

透视投影 perspective projection

转化到摄像机坐标系 cameraRotation + cameraTranslation

透视投影

在添加透视投影前,要在矩阵类(Matrix4f)添加投影的计算方法

透视投影是为了获得接近真实三维物体的视觉效果而在二维的纸或者画布平面上绘图或者渲染的一种方法,它也称为透视图。透视投影的绘制必须根据已有的几何规则进行。

编写Camera

在添加Camera前,要在矩阵类(Matrix4f)添加转化到摄像机坐标系的的计算方法

编写Texture 与 Material

用来给模型上材质

b952432c98f0c790cc92ded3b9194660.png

abe99e1aeaabe8a5ffb7b2bb7ee0d4b1.png

添加光源

环境光 ambient light

直线光(平行光) Directional Light 会产生漫反射

点光源 point light

聚光灯 spot light

环境光 ambient light

下图为将环境光亮值设置为0.1 Vector3f(0.1f,0.1f,0.1f)); 让周围环境变暗

下图为将环境光亮值设置为10 Vector3f(10f,10f,10f)); 让周围环境变亮

直线光(平行光) Directional Light

颜色 光强 方向

考虑环境漫反射 diffuse Color

在OPENGL中顶点-三角形模型对光照的反射取决于顶点法向量的设置,如果法向量计算正确,显示出来的模型表面很光滑,有光泽,否则不是棱角分明就是模糊、看不清

漫反射计算公式:

08a6db29a1ee2b3e376cf6da6a0cb850.png

漫反射的计算

因此在计算之前要考虑计算法线方向

3eb8aa6513f406b71d9f43caf33c6c4d.png

顶点法向量的计算

可以明显发现,加入漫反射后,明显材质变光滑和自然许多

考虑镜面反射 (specular reflection)

66794b7f019c70ea92c087510b13a3c1.png

可以明显发现,加入镜面反射后,明显材质变更加光滑和自然许多 还可以看到反光

点光源 point light Attenuation

点光源衰减公式 因此在计算前要设计好 衰减类

点光源在下图中

聚光灯 spot light

9e3f241b1452794ca39c0b5abad70fc6.png

聚光公式:

c319b8e66e860a894d0578180032526a.png

聚光公式推导说明

cutoff是一个0-1的数

加入聚光灯:

bc2bf53539cfb1168aca568cd5bc23a3.png

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
商品三级分类可以使用树形结构来实现,每个节点代表一个分类,其中根节点代表一级分类,根节点的子节点代表二级分类,以此类推。实现步骤如下: 后端实现: 1. 定义分类实体类,包含分类ID、分类名称、父分类ID等属性; 2. 使用递归算法构建分类树,根据父分类ID在数据库中查询子分类,将子分类添加到父分类的子节点中,直到查询不到子分类为止; 3. 将分类树转换为JSON格式返回给前端。 前端实现: 1. 使用Ajax技术向后端请求分类树数据; 2. 使用递归算法遍历分类树,生成HTML代码,展示分类列表; 3. 为列表项添加点击事件,点击后展开或收起子分类列表。 示例代码: 后端Java代码: ``` // 分类实体类 public class Category { private int id; // 分类ID private String name; // 分类名称 private int parentId; // 父分类ID private List<Category> children; // 子分类列表 // 构造函数、Getter和Setter方法省略 } // 分类服务类 @Service public class CategoryService { @Autowired private CategoryMapper categoryMapper; // 获取所有分类列表 public List<Category> getCategoryList() { return categoryMapper.getCategoryList(); } // 获取指定分类ID的子分类列表 public List<Category> getChildrenCategories(int parentId) { return categoryMapper.getChildrenCategories(parentId); } // 递归构建分类树 private void buildCategoryTree(Category category) { List<Category> children = getChildrenCategories(category.getId()); if (children != null && children.size() > 0) { category.setChildren(children); for (Category child : children) { buildCategoryTree(child); } } } // 获取分类树 public List<Category> getCategoryTree() { List<Category> categories = getCategoryList(); List<Category> roots = new ArrayList<>(); for (Category category : categories) { if (category.getParentId() == 0) { roots.add(category); } } for (Category root : roots) { buildCategoryTree(root); } return roots; } } // 分类控制器类 @RestController @RequestMapping("/category") public class CategoryController { @Autowired private CategoryService categoryService; // 获取分类树数据 @GetMapping("/tree") public List<Category> getCategoryTree() { return categoryService.getCategoryTree(); } } ``` 前端HTML代码: ``` <div id="category-list"></div> <!-- 分类列表模板 --> <template id="category-template"> <ul> {{#each categories}} <li> <span>{{name}}</span> {{#if children}} <button class="toggle-btn">+</button> {{/if}} {{#if children}} <ul class="children"> {{> category-template categories=children}} </ul> {{/if}} </li> {{/each}} </ul> </template> ``` 前端JavaScript代码: ``` $(function() { // 加载分类树数据 $.ajax({ url: '/category/tree', type: 'get', dataType: 'json', success: function(categories) { // 渲染分类列表 var template = Handlebars.compile($('#category-template').html()); $('#category-list').html(template({categories: categories})); } }); // 点击展开或收起子分类列表 $('#category-list').on('click', '.toggle-btn', function() { $(this).toggleClass('opened'); $(this).siblings('.children').toggle(); }); }); ``` 以上代码仅供参考,具体实现还需要根据业务逻辑进行调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值