threejs官方demo学习(1):animation

news2024/12/23 10:41:37

前言

之前的threejs入门视频教学已经学习完了,下面会陆续学习官方demo。官方网址太卡了建议在本地进行搭建,具体见:threejs视频教程学习(1):本地搭建threeJS官网、渲染第一个场景

官方的例子都是html格式,后续以vue3的格式进行学习。

webgl_animation_keyframes

代码

<template>
    <div id="keyframes"> </div>
</template>

<script setup lang="ts">
import { onMounted, ref } from 'vue';
import * as THREE from 'three';
// 引入轨道控制器
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
// 引入模型加载器
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
// 引入模型解压器
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader';
// 引入房间环境,之前没有用过,应该是创建一个室内环境
import { RoomEnvironment } from 'three/examples/jsm/environments/RoomEnvironment';
// 引入性能监视器,之前也没用过
import Stats from 'three/examples/jsm/libs/stats.module';

const mixer = ref();

onMounted(() => {
    // 创建一个clock对象,用于跟踪时间
    const clock = new THREE.Clock();
    // 获取dom容器
    const container = document.getElementById('keyframes');
    // 创建一个性能监听器
    const stats = new Stats();
    // 修改一下位置
    stats.dom.style.position = 'relative';
    // 将性能监听器添加到容器中
    container?.appendChild(stats.dom);
    // 创建一个渲染器
    const renderer = new THREE.WebGLRenderer({
        antialias: true // 设置防锯齿
    });
    // 设置渲染器的像素比例
    renderer.setPixelRatio(window.devicePixelRatio);
    // 设置渲染的尺寸
    renderer.setSize(1000, 800);
    // 设置渲染的输出格式
    renderer.outputEncoding = THREE.sRGBEncoding;
    // 将渲染的内容添加到容器中
    container?.appendChild(renderer.domElement);

    // 创建一个PMREMGenerator,从立方体映射环境纹理生成预过滤的 Mipmap 辐射环境贴图
    const pmremGenerator = new THREE.PMREMGenerator(renderer);
    // 创建一个场景
    const scene = new THREE.Scene();
    // 设置背景色
    scene.background = new THREE.Color(0xbfe3dd);
    // 设置场景的纹理,从提供的场景中生成纹理
    scene.environment = pmremGenerator.fromScene(new RoomEnvironment(), 0.04).texture;

    // 创建相机并设置位置
    const camera = new THREE.PerspectiveCamera(40, 1.25, 1, 100);
    camera.position.set(5, 2, 8);

    // 设置轨道控制器
    const controls = new OrbitControls(camera, renderer.domElement);
    controls.target.set(0, 0.5, 0);
    controls.update();
    controls.enablePan = false; // 当设置为false时,控制器将不会响应用户的操作。默认值为true。
    controls.enableDamping = true; // 开启阻尼

    // 创建解压器并设置路径,官方文档中有draco文件夹,直接复制到自己项目里就好,另外gltf后面一定要加斜杠
    const dracoLoader = new DRACOLoader();
    dracoLoader.setDecoderPath('../../../../public/draco/gltf/');

    // 创建模型加载器并加载模型
    const loader = new GLTFLoader();
    loader.setDRACOLoader(dracoLoader);
    loader.load('../../../../public/LittlestTokyo.glb', gltf => {
        const model = gltf.scene;
        // 设置模型的位置
        model.position.set(1, 1, 0);
        // 设置视角
        model.scale.set(0.01, 0.01, 0.01);
        // 将模型添加到场景中
        scene.add(model);

        // 创建一个动画混合器,动画混合器是用于场景中特定对象的动画的播放器。当场景中的多个对象独立动画时,每个对象都可以使用同一个动画混合器。
        mixer.value = new THREE.AnimationMixer(model);
        // 设置剪辑动画
        mixer.value.clipAction(gltf.animations[0]).play();
        // 执行动画
        animate();
    });

    // 动画执行函数
    const animate = () => {
        // 调用动画帧执行动画
        requestAnimationFrame(animate);
        // 获取当前秒数
        const delta = clock.getDelta();
        // 更新动画混合器、轨道控制器、性能监听器
        mixer.value.update(delta);
        controls.update();
        stats.update();
        // 重新渲染
        renderer.render(scene, camera);
    };
});
</script>

<style lang="scss" scoped>
#keyframes {
    background-color: #bfe3dd;
    width: 1000px;
    height: 800px;
}
</style>

效果图
左上角的是性能监听器,点击启动,再次点击关闭
在这里插入图片描述

知识点

最复杂的是模型,不过模型是做好的。主要是如何加载模型,设置动画。

RoomEnvironment

import { RoomEnvironment } from 'three/examples/jsm/environments/RoomEnvironment';

应该是室内环境,但是在官方文档里没有找到。

PMREMGenerator

// 创建一个PMREMGenerator,从立方体映射环境纹理生成预过滤的 Mipmap 辐射环境贴图
 const pmremGenerator = new THREE.PMREMGenerator(renderer);
 // 创建一个场景
 const scene = new THREE.Scene();
 // 设置背景色
 scene.background = new THREE.Color(0xbfe3dd);
 // 设置场景的纹理,从提供的场景中生成纹理
 scene.environment = pmremGenerator.fromScene(new RoomEnvironment(), 0.04).texture;

看官方的demo应该是用来提取场景中的纹理的。

AnimationMixer

官方文档的解释是:动画混合器是用于场景中特定对象的动画的播放器。
当我将相关代码注释后,模型里的动画停止了执行,结合文档的解释,应该就是用于播放模型自身的动画。

Clock
该对象用于跟踪时间,结合上面动画混合器的update 方法,这里单纯用于给动画混合器提供参数。
在这里插入图片描述

webgl_animation_skinning_blending

官方的例子有点复杂,看了好几遍才明白,实际上也是基于上面的动画加载,只是将各个动作给拆解开来了。在官方例子的基础上进行了简化,把一些代码进行了删除,这样更适合我这样的初学者。

代码
这里是有点问题的,没太搞明白,new THREE.AnimationMixer(model)单独定为一个变量使用时会提示某些方法找不到,因此就没有单独定义

<template>
    <div id="keyframes"> </div>
</template>

<script setup lang="ts">
import { onMounted } from 'vue';
import * as THREE from 'three';
// 引入gui
import * as dat from 'dat.gui';
// 模型加载器
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
// 引入轨道控制器
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';

onMounted(() => {
    // 获取dom容器
    const container = document.getElementById('keyframes');
    // 创建一个场景
    const scene = new THREE.Scene();
    // 设置场景的背景色
    scene.background = new THREE.Color(0xa0a0a0);
    // 给场景中添加雾、雾的颜色、最小距离、最大距离。最小距离和最大距离之间是雾的范围
    scene.fog = new THREE.Fog(0xa0a0a0, 10, 50);

    // 创建相机
    const camera = new THREE.PerspectiveCamera(75, 1.25, 1, 1000);
    // 设置相机的位置
    camera.position.set(2, 2, -10);
    // 将相机添加到场景里
    scene.add(camera);

    // 创建渲染器
    const renderer = new THREE.WebGLRenderer({
        antialias: true // 设置防锯齿
    });
    // 设置渲染器的像素比例
    renderer.setPixelRatio(window.devicePixelRatio);
    // 设置渲染尺寸
    renderer.setSize(1000, 800);
    // 设置渲染输出的编码
    renderer.outputEncoding = THREE.sRGBEncoding;
    // 开启场景阴影渲染
    renderer.shadowMap.enabled = true;
    // 将渲染对象添加到容器
    container?.appendChild(renderer.domElement);

    // 添加平行光,平行光可以产生投影
    const dirLight = new THREE.DirectionalLight(0xffffff);
    // 设置平行光的位置
    dirLight.position.set(-3, 10, -10);
    // 设置光照产生阴影
    dirLight.castShadow = true;

    // 向场景中添加灯光
    scene.add(dirLight);
    // 添加坐标辅助器
    const axesHelper = new THREE.AxesHelper(10);
    scene.add(axesHelper);
    // 创建轨道控制器
    const controls = new OrbitControls(camera, renderer.domElement);
    // 设置控制器阻尼
    controls.enableDamping = true;

    // 渲染函数
    const render = () => {
        controls.update();
        renderer.render(scene, camera);
        requestAnimationFrame(render);
    };
    render();
    // 创建一个具有镜面高光的平面
    const mesh = new THREE.Mesh(new THREE.PlaneGeometry(100, 100), new THREE.MeshPhongMaterial({ color: 0x999999 }));
    // 把平面变成水平的
    mesh.rotation.x = -Math.PI / 2;
    // 设置接收物体投影
    mesh.receiveShadow = true;
    scene.add(mesh);

    // 模型
    let model = null;
    // clock对象
    const clock = new THREE.Clock();
    // 用来模拟骨骼 Skeleton 的辅助对象
    let skeleton = null;
    // 放松动作
    let idleAction = null;
    // 步行
    let walkAction = null;
    // 跑
    let runAction = null;
    // 所有的设置
    let settings = {};
    // 所有动作
    let actions = [];
    // 当前激活动作
    let active = 2;
    // 所有的动画
    let animations = [];

    // 创建模型加载器,加载模型
    const loader = new GLTFLoader();
    // 应该是模型比较小,这里没有引入模型解压器
    loader.load('../../../../public/Soldier.glb', gltf => {
        model = gltf.scene;
        scene.add(model);
        // 进行深度遍历
        model.traverse(function(object) {
            // 如果是物体的话开启投影
            if (object.isMesh) {
                object.castShadow = true;
            }
        });
        // 获取模型的骨骼对象
        skeleton = new THREE.SkeletonHelper(model);
        // 将骨骼设置为可见
        skeleton.visible = true;
        // 向场景中添加骨骼辅助对象
        scene.add(skeleton);

        // 创建控制面板
        createPanel();
        // 获取模型的动画
        animations = gltf.animations;
        // 这里new THREE.AnimationMixer(model);不统一使用一个变量代替是因为,使用一个变量代替后报错了,不知道因为什么
        // 跑
        runAction = new THREE.AnimationMixer(model);
        runAction.clipAction(animations[1]);
        // 放松动作
        idleAction = new THREE.AnimationMixer(model);
        idleAction.clipAction(animations[2]);
        // 步行
        walkAction = new THREE.AnimationMixer(model);
        walkAction.clipAction(animations[3]).play();

        actions = [runAction, idleAction, walkAction];
        animate();
    });

    /** **************上面的是模型的加载和渲染,下面这些都与动画有关***************** */

    // 执行动画
    const animate = () => {
        // 调用动画帧执行动画
        requestAnimationFrame(animate);
        // 获取当前秒数
        const delta = clock.getDelta();
        // 更新动画混合器、轨道控制器、性能监听器
        actions[active].update(delta);
        controls.update();
        // 重新渲染
        renderer.render(scene, camera);
    };

    // 创建GUI面板
    const createPanel = () => {
        const panel = new dat.GUI({ width: 310 });
        settings = {
            visible: true, // 显示模型
            idle: false // 放松
        };
        panel.add(settings, 'visible').name('是否显示').onChange(showModel);
        panel.add(settings, 'idle').name('放松').onChange(runIdleAction);
    };

    // 显示模型
    const showModel = (visibility: boolean) => {
        // 隐藏模型
        model.visible = visibility;
        // 隐藏骨骼
        skeleton.visible = visibility;
    };

    // 放松
    const runIdleAction = (value:boolean) => {
        if (value) {
            // 将跑、走动画停止,开启放松动画
            actions[0].clipAction(animations[1]).stop();
            actions[2].clipAction(animations[3]).stop();
            actions[1].clipAction(animations[2]).play();
            // 更新激活的动作
            active = 1;
        } else {
        // 变为走
            actions[0].clipAction(animations[1]).stop();
            actions[2].clipAction(animations[3]).play();
            actions[1].clipAction(animations[2]).stop();
            // 更新激活的动作
            active = 2;
        }
    };
});
</script>

<style lang="scss" scoped>
#keyframes {
    width: 1000px;
    height: 800px;
    background-color: #bfe3dd;
}
</style>

效果图
在这里插入图片描述

知识点

Fog
在常见中添加雾,具体内容可以看官方文档

 scene.fog = new THREE.Fog(0xa0a0a0, 10, 50);

如何产生投影
这个之前梳理过,具体见:threejs视频教程学习(4):贴图、材质、光线

SkeletonHelper
SkeletonHelper,用来模拟骨骼 Skeleton 的辅助对象.。该辅助对象使用 LineBasicMaterial 材质。
模型里面必须有骨骼辅助对象,才能够获取到

// 获取模型的骨骼对象
skeleton = new THREE.SkeletonHelper(model);
// 将骨骼设置为可见
skeleton.visible = true;
// 向场景中添加骨骼辅助对象
scene.add(skeleton);

gui
gui的基本使用见:threejs视频教程学习(3):应用图形用户界面更改变量 (dat.gui的简单使用)

webgl_animation_skinning_additive_blending

做的比较简陋,好多细节都没有实现。
代码

<template>
    <div id="keyframes"> </div>
</template>

<script setup lang="ts">
import { onMounted } from 'vue';
import * as THREE from 'three';
// 引入gui
import * as dat from 'dat.gui';
// 模型加载器
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
// 引入轨道控制器
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';

onMounted(() => {
    // 获取dom
    const container = document.getElementById('keyframes');
    // 走
    let walkAction = null;
    let walk = null;
    // 跑
    let runAction = null;
    let run = null;
    const clock = new THREE.Clock();

    // 创建场景
    const scene = new THREE.Scene();
    // 设置背景色
    scene.background = new THREE.Color(0xa0a0a0);
    // 设置雾气
    scene.fog = new THREE.Fog(0xa0a0a0, 10, 50);
    // 设置半球光
    const hemiLight = new THREE.HemisphereLight(0xffffff, 0x444444);
    hemiLight.position.set(0, 20, 0);
    scene.add(hemiLight);
    // 设置平行光
    const dirLight = new THREE.DirectionalLight(0xffffff);
    dirLight.position.set(3, 10, 10);
    dirLight.castShadow = true; // 开启阴影
    scene.add(dirLight);

    // 创建透视相机
    const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 100);
    camera.position.set(-1, 2, 3);
    scene.add(camera);

    // 创建渲染器
    const renderer = new THREE.WebGLRenderer({
        antialias: true // 抗锯齿
    });
    renderer.setPixelRatio(window.devicePixelRatio); // 像素比
    renderer.setSize(window.innerWidth, window.innerHeight); // 渲染尺寸
    renderer.outputEncoding = THREE.sRGBEncoding;
    renderer.shadowMap.enabled = true; // 开启场景阴影渲染
    container?.appendChild(renderer.domElement);

    // 创建轨道控制器
    const control = new OrbitControls(camera, renderer.domElement);
    control.enableZoom = false; // 关闭缩放
    control.target.set(0, 1, 0);
    control.update(); // 更新控制器

    // 创建一个平面
    const mesh = new THREE.Mesh(new THREE.PlaneGeometry(100, 100), new THREE.MeshPhongMaterial({ color: 0x999999, depthWrite: false }));
    mesh.rotation.x = -Math.PI / 2;
    mesh.receiveShadow = true; // 设置平面接收阴影
    scene.add(mesh);

    // 加载模型
    const loader = new GLTFLoader();
    loader.load('../../../../public/Xbot.glb', gltf => {
        // 模型
        const model = gltf.scene;
        scene.add(model);
        // 递归找到物体开启阴影
        model.traverse(object => {
            if (object.isMesh) object.castShadow = true;
        });
        // 获取模型的动作
        const animations = gltf.animations;
        console.log('动画', animations);

        // 跑
        runAction = new THREE.AnimationMixer(model);
        run = runAction.clipAction(animations[3]);

        // 走
        walkAction = new THREE.AnimationMixer(model);
        walk = walkAction.clipAction(animations[6]);

        animate();
    });

    // 执行动画
    const animate = () => {
        // 调用动画帧执行动画
        requestAnimationFrame(animate);
        // 获取当前时间,这个不能直接new ,不然动画不会生效
        const delta = clock.getDelta();
        if (settings.run) {
            run.play();
            runAction.update(delta);
        } else {
            walk.play();
            walkAction.update(delta);
        }
        control.update();
        // 重新渲染
        renderer.render(scene, camera);
    };

    // 添加GUI
    let settings = {};
    const panel = new dat.GUI({ width: 310 });
    settings = {
        run: true,
        speed: 1
    };
    panel.add(settings, 'run').name('跑');
    panel.add(settings, 'speed').min(0).max(5)
        .onChange((value) => {
            // 通过修改AnimationAction对象的timeScale(时间比例因子)来调节动画的速度
            if (settings.run) {
                runAction.timeScale = value;
            } else {
                walkAction.timeScale = value;
            }
        });
});
</script>

<style lang="scss" scoped>
#keyframes {
    width: 1000px;
    height: 800px;
    background-color: #bfe3dd;
}
</style>

效果图
在这里插入图片描述

知识点

主要是AnimationAction 动画对象的应用。动画的速度是通过修改timeScale 来实现的,动作之间的过渡是通过修改weight来实现的,动作过渡没太弄清楚。

详情内容可以看官方文档。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/66327.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Qt源码编译aarch等架构可参考

前言&#xff1a; 我的建议是&#xff1a; 编译环境一定要有网络&#xff0c;依赖的包才可以方便安装&#xff01;&#xff01;&#xff01; 一、准备工作 有网但ping不通、或者没有源的 可能需要先配置: 源路径&#xff1a; /etc/apt/source.list 系统默认DNS配置: /etc/r…

iTOP3588开发板编译Android内核方法一

iTOP3588开发板编译Android内核方法一&#xff1a; 在 Android 源码目录下执行如下命令编译 Android 内核&#xff1a; ./build.sh -CKA 编译完成后如下图所示&#xff1a; 编译后会在 rockdev/Image-rk3588_s 目录下生成 boot.img&#xff0c;boot.img 为内核镜像。boot.i…

《操作系统实战 45 讲》系统环境搭建 (Ubuntu + Vmware)

系统环境搭建 1. Ubuntu下载2. Vmware安装 Ubuntu系统2.1 配置电脑2.2 安装系统&#xff08;Ubuntu16.04&#xff09;3、配置网络和修改yum源3.1. 编辑 VMware 的网络配置3.2 windows 的网络配置3 .3 虚拟机网络 IP 修改地址配置3.4 修改yum源3.5 安装vm-tools1. Ubuntu下载 清…

【泊车】基于强化学习实现智能泊车附matlab代码

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;修心和技术同步精进&#xff0c;matlab项目合作可私信。 &#x1f34e;个人主页&#xff1a;Matlab科研工作室 &#x1f34a;个人信条&#xff1a;格物致知。 更多Matlab仿真内容点击&#x1f447; 智能优化算法 …

仿照string类,实现自定义My_strng类,以及相关操作

代码 #include <iostream> #include <cstring>using namespace std;class My_string { private:char* cstr;int len; public:My_string():cstr(NULL),len(0) //无参构造{}My_string(const char* str) //有参构造{this->len strlen(s…

【C++笔试强训】第二天

选择题 1.使用printf函数打印一个double类型的数据&#xff0c;要求&#xff1a;输出为10进制&#xff0c;输出左对齐30个字符&#xff0c;4位精度。以下哪个选项是正确的&#xff1f; A %-30.4e B %4.30e C %-30.4f D %-4.30f 对于 %m.nf &#xff0c;double对应%f.要求打印…

爬虫之Scrapy架构

目录 Scrapy架构介绍 Scrapy下载 Scrapy基本使用 Scrapy目录结构 Scrapy解析数据 settings相关配置 基础配置 增加爬虫的爬取效率 去重规则&#xff08;布隆过滤器&#xff09; 持久化方案(数据保存) request和response传递参数 网页解析下一页继续爬取 爬虫和下载…

Java安全之深入了解SQL注入

深入了解Java中的SQL注入 本文以代码实例复现了Java中JDBC及Mybatis框架采用预编译和非预编译时可能存在SQL注入的几种情况&#xff0c;并给予修复建议。 JDBC 首先看第一段代码&#xff0c;使用了远古时期的JDBC并且并没有使用预编译。这种简单的字符串拼接就存在SQL注入 …

信息化带来的制造业生产管理系统究竟有哪些作用呢?

制造业是一个现代国家的经济基础&#xff0c;决定着着国家的兴衰存亡。长期以来人们和国家都对制造业给予高度重视&#xff0c;无论是资金投入还是管理的手段和方法的提高&#xff0c;制造业在生产行业中的优势越来越明显。尤其是随着科学技术的快速发展&#xff0c;制造业的现…

uniapp easycom

easycom 是 uniapp 的一种组件自动引入的规则&#xff0c;使用这种规则可以使满足规则的组件无需注册直接使用。 接下来我们来看一眼效果 这里可以看到我并没有进行组件注册而是直接使用了组件&#xff0c;这样的效果就是通过 easycom 的自定义规则来实现的。 来看一眼我的自…

庐山真面目之——LWIP初探

目录 LWIP简介 网络层协议分层模型介绍 LWIP源代码结构 lwip源码文件说明 lwip的contrib包文件说明 以太网接入MCU方案 LWIP结构框图 LWIP简介 lwIP 是 Light Weight&#xff08;轻型&#xff09;IP 协议&#xff0c;有无操作系统的支持都可以运行。lwIP 实现的重点 是在保…

Android Studio compose的简单使用与案例实现

Compose是Android团队与JetBrain大力推动的新一代UI框架&#xff0c;它能够简化安卓界面的开发&#xff0c;让本来繁琐的xml文件写法变为简便的kt文件写法。 其声明式 UI、更简单的自定义、实时且带交互的预览功能更是让安卓开发锦上添花 android compose框架的使用一.前置知识…

vue+elementUI 使用腾讯地图

效果如下 引入地图qqmap 刚开始我是直接用 npm install qqmap&#xff0c;但是好像只有v1版本的&#xff0c;我需要用v2版本的&#xff0c;所以直接使用script标签加载API服务。 文件&#xff1a;/public/index.html <script charset"utf-8" src"https:…

2023最新SSM计算机毕业设计选题大全(附源码+LW)之java双笙映画ou5oj

毕业设计也不需要做多高端的程序&#xff0c;毕业设计对于大多数同学来说&#xff0c;为什么感觉到难&#xff0c;最重要的一个原因&#xff0c;那就是理论课到实践课的转变&#xff0c;很多人一下不适应&#xff0c;本能开始拒绝&#xff0c;如果是一个考试&#xff0c;大家都…

spring boot基于Java的电影院售票与管理系统毕业设计源码011449

电影院售票与管理系统的设计与实现 摘 要 信息化社会内需要与之针对性的信息获取途径&#xff0c;但是途径的扩展基本上为人们所努力的方向&#xff0c;由于站在的角度存在偏差&#xff0c;人们经常能够获得不同类型信息&#xff0c;这也是技术最为难以攻克的课题。针对电影院售…

SpringBoot —— 整合RabbitMQ常见问题及解决方案

前言 企业中最常用的消息中间件既不是RocketMQ&#xff0c;也不是Kafka&#xff0c;而是RabbitMQ。 RocketMQ很强大&#xff0c;但主要是阿里推广自己的云产品而开源出来的一款消息队列&#xff0c;其实中小企业用RocketMQ的没有想象中那么多。 至于Kafka&#xff0c;主要还是…

常见的推荐算法原理介绍

常见的推荐算法原理介绍&#xff0c;随着互联网的发展短视频运营越来越精准化&#xff0c;我们身边常见的抖音、火山小视频等软件让你刷的停不下来&#xff0c;这些软件会根据你的浏览行为推荐你感兴趣的相关内容&#xff0c;这就用到了很多推荐算法在里面。 在淘宝购物&#…

Linux 负载均衡介绍之LVS工作模式-DR直接路由模式

Linux 负载均衡介绍之LVS工作模式-DR直接路由模式 图示&#xff1a; 工作原理&#xff1a; ①.客户端将请求发往前端的负载均衡器&#xff0c;请求报文源地址是CIP&#xff0c;目标地址为VIP。 ②.负载均衡器收到报文后&#xff0c;发现请求的是在规则里面存在的地址&#x…

[Java反序列化]—Shiro反序列化(二)

0x01 这篇利用CC链来进行RCE 利用分析 在shiro-web 中加上CC依赖 <dependency><groupId>commons-collections</groupId><artifactId>commons-collections</artifactId><version>3.2.1</version><scope>compile</scope>…

ZKP方案衍变及对比

1. 引言 2019年是ZKP方案创新井喷的一年。 2019年10月&#xff0c;Chiesa在#zk0x04上的分享 State of the SNARG-scape - Alessandro Chiesa (UC Berkeley, StarkWare, Zcash)&#xff0c;有&#xff1a; 根据reference string的类型&#xff0c;可将zk-SNARKs分类为&#…