惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

MongoDB | Blog
MongoDB | Blog
博客园 - 聂微东
Attack and Defense Labs
Attack and Defense Labs
WordPress大学
WordPress大学
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Spread Privacy
Spread Privacy
AI
AI
宝玉的分享
宝玉的分享
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
C
Cyber Attacks, Cyber Crime and Cyber Security
爱范儿
爱范儿
Help Net Security
Help Net Security
V
Visual Studio Blog
大猫的无限游戏
大猫的无限游戏
Forbes - Security
Forbes - Security
P
Privacy & Cybersecurity Law Blog
Project Zero
Project Zero
IT之家
IT之家
Hugging Face - Blog
Hugging Face - Blog
博客园 - 三生石上(FineUI控件)
S
SegmentFault 最新的问题
有赞技术团队
有赞技术团队
T
Troy Hunt's Blog
美团技术团队
T
Threatpost
K
Kaspersky official blog
V
V2EX
Scott Helme
Scott Helme
Vercel News
Vercel News
T
The Blog of Author Tim Ferriss
T
Tailwind CSS Blog
V
Vulnerabilities – Threatpost
Last Week in AI
Last Week in AI
PCI Perspectives
PCI Perspectives
Google Online Security Blog
Google Online Security Blog
Apple Machine Learning Research
Apple Machine Learning Research
Engineering at Meta
Engineering at Meta
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
I
InfoQ
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
酷 壳 – CoolShell
酷 壳 – CoolShell
GbyAI
GbyAI
L
LINUX DO - 最新话题
T
The Exploit Database - CXSecurity.com
L
LangChain Blog
S
Security @ Cisco Blogs
The Last Watchdog
The Last Watchdog
H
Hacker News: Front Page
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
TaoSecurity Blog
TaoSecurity Blog

StudyingLover's Blog

Diffusion Policy笔记 rwkv笔记 act笔记 nanovllm-block_manager opencode多智能体 nanobot-pre-train nanobot-rl nanobot-sft nanobot-checkpoint_manager nanobot-gpt nanobot-mid-train Vision Mamba (Vim)笔记 BPE演示 最后一遍学习Transformer YOLOv5 目标检测笔记 下载根服务器解析记录 Dynaseal A Backend-Controlled LLM API Key Distribution Scheme with Constrained Invocation Parameters 判断链表有环 王道25数据结构勘误 关于perplexity的open-sourcing-r1-1776 AI为什么不像人类一样进行多轮对话 新博客改造日记和功能测试 linuxqq只显示登陆背景图 数字设计和计算机体系结构(机械工业出版社)勘误(自制) Dynaseal:面向未来端侧llm agent的llm api key分发机制 A Definitive Guide to Markdown Style This post is using MDX, Where you can embed JSX and Astro components RT-Patch学习 pydantic实现的LLM ReAct fastapi 和 uvicorn 设置监听 ipv6 pydantic+openai+json 控制大模型输出的最佳范式 解决 Matplotlib Scatter 不支持 Marker 列表的问题:mscatter 实现 roofline model zhipuAI接口兼容openai 在docker部署fastapi宝塔里使用nginx反代套上cloudflare获取请求的真实ip clion搭建libbpf-bootstrap开发环境 coze+coze-discord-proxy+ChatNextWebUI实现AI自由 安卓内核时间使用的是UTC时间 colab运行google最新开源模型Gemma Sora技术报告 视频生成模型作为世界模拟器 笔记 archlinux flutter开发踩坑 fastapi集成google auth登录 linux下NTFS磁盘报错输入输出错误 Venn-Abers 预测器 基于Venn-Abers预测器的系统日志异常检测方法_顾兆军 手机平板远程访问kvm虚拟机的windows phi-2弱智吧测评 poe的gemini pro或是百度开发 google gemini api使用 google gemini api申请 构建用于复杂数据处理的高效UDP服务器和客户端 matplotlib中文字体渲染 TruFor笔记和代码复现 深入分析:GitHub Trending 项目 "multipleWindow3dScene" pua大模型 ggml教程|mnist手写体识别量化推理 xgboost2.0最佳实践 xgboost使用GPU最佳实践 马踏棋盘 cloudlflare推理llama2 docker搭建elasticsearch并使用python连接 FreeU-文字生成图片的免费午餐笔记 使用xgboost的c接口推理模型 Archlinux使用CMake调用xgboost的c接口 m2cgen生成机器学习c语言推理代码 xgboost模型序列化存储并推理 speculative-sampling笔记 prompt2model笔记 RoboTAP笔记 自建obsidian同步服务 MediaPipe即将推出图像生成服务 Dual-Stream Diffusion Net for Text-to-Video Generation笔记 ViT在DDPM取代UNet(DiT) arch4edu搞崩了我的flutter LISA(推理分割)笔记 在终端绘制GPU显存使用曲线 GPTBot介绍 arch蓝牙无法连接 GPU部署llama-cpp-python(llama.cpp通用) 花式求GCD 使用llama构建一个蜜罐(前端) 使用llama构建一个蜜罐(后端) llama-cpp-python快速上手 快速上手llama2.c(更新版) Paper Gestalt笔记 DINO-v2笔记 快速上手llama2.c AnyDoor笔记 Archlinux安装scrcpy加载共享库出错 error while loading shared libraries:libusb-1.0.so.0:wrong ELF class:ELFCLASS32 npc_gzip笔记 python调用c++函数 Filesystem type ntfs3,ntfs not configured in kernel open_clip编码图像和文本 PicGo配置CloudflareR2图片储存 ArchlinuxGnome快捷键打开终端 clip-interrogator代码解析 GroundingDINO安装报错解决 2023华为鲲鹏畅想日暨西安高新国际会议中心零食午饭测评 RoboMaster开源仓库汇总(长期更新) 没有手都可以在腾讯云创建镜像
ThreeJS实现屏幕坐标转3d坐标
About the Author StudyingLover · 2023-02-05 · via StudyingLover's Blog

ThreeJS实现屏幕坐标转3d坐标

本文使用chatGPT辅助完成

在虚拟世界中,3D坐标与屏幕坐标之间的转换是一个重要的问题。使用ThreeJS开发3D场景时,经常需要将屏幕坐标转换为3D坐标。在本文中,我们将介绍如何使用ThreeJS实现屏幕坐标转3D坐标的两种方法

根据相机的投影矩阵和射线拾取

在我的笔记摄像机模型中详细推导了相机的投影矩阵。

在ThreeJS中,相机的投影矩阵是一个4x4的矩阵,它将3D坐标转换为屏幕坐标。我们可以使用这个矩阵将屏幕坐标转换为3D坐标。 官方为我们提供了一个接口vector.unproject(camera),它可以将屏幕坐标转换为3D坐标。但是这个接口只能将屏幕坐标转换为相机坐标系下的3D坐标,如果我们需要将屏幕坐标转换为世界坐标系下的3D坐标,我们需要使用vector.applyMatrix4(camera.matrixWorldInverse)将相机坐标系下的3D坐标转换为世界坐标系下的3D坐标。(这里代码本来不是这么写的,但是copilot给了我好多提示,我就照着他的提示改了改,如果你发现代码有问题,问问chatGPT吧)

function screenToWorld(screenX, screenY, camerahyper_z) {
    const vector = new THREE.Vector3();
    vector.set(
        (screenX / window.innerWidth) * 2 - 1,
        -(screenY / window.innerHeight) * 2 + 1,
        hyper_z
    );
    vector.unproject(camera);
    vector.applyMatrix4(camera.matrixWorldInverse);
    return vector;
}

这里的hyper_z网上很多教程认为是写0.5,但是我实际试了一下,发现效果很差,就把他改成了一个超参数。后来在一位不能透露姓名的大佬的帮助下,得知这个参数的值应该写成1。我试了下,勉强可以得到预期的效果

通过深度图采样,shader改深度缓冲

这种方法是通过深度图采样,shader改深度缓冲,然后再通过深度缓冲得到3D坐标。这种方法的优点是可以得到更精确的3D坐标,但是缺点是需要使用shader,而且需要修改深度缓冲,可能会影响性能。

感谢chatGPT,我只需要把我需要的内容告诉他,他就会给我写一个完整的代码。

function convert2Dto3D(mouseX, mouseY, camera, width, height, scene) {
        // 构建纹理
        var depthTarget = new THREE.WebGLRenderTarget(width, height);
        depthTarget.texture.minFilter = THREE.LinearFilter;

        // 渲染深度图
        renderer.render(scene, camera, depthTarget);

        // 创建着色器
        var material = new THREE.ShaderMaterial({
            uniforms: {
                mouse: { value: new THREE.Vector2(mouseX, mouseY) },
                depthMap: { value: depthTarget.texture },
                projectionMatrix: { value: camera.projectionMatrix },
                viewMatrix: { value: camera.matrixWorldInverse }
            },
            vertexShader: `
                uniform vec2 mouse;
                uniform mat4 projectionMatrix;
                uniform mat4 viewMatrix;
                uniform sampler2D depthMap;
                varying vec4 pos;
                void main() {
                    pos = vec4(position, 1.0);
                    gl_Position = projectionMatrix * viewMatrix * pos;
                }
            `,
            fragmentShader: `
                uniform vec2 mouse;
                uniform sampler2D depthMap;
                varying vec4 pos;
                void main() {
                    float depth = texture2D(depthMap, mouse).r;
                    vec4 viewPos = vec4(mouse * 2.0 - 1.0, depth * 2.0 - 1.0, 1.0);
                    vec4 worldPos = viewMatrix * viewPos;
                    worldPos /= worldPos.w;
                    gl_FragColor = vec4(worldPos.xyz, 1.0);
                }
            `
        });

        // 创建一个平面作为渲染目标
        var plane = new THREE.PlaneBufferGeometry(width, height);
        var mesh = new THREE.Mesh(plane, material);
        scene.add(mesh);

        // 渲染一次着色器并获取结果
        renderer.render(scene, camera);
        var pixelBuffer = new Uint8Array(4);
        renderer.readRenderTargetPixels(depthTarget, mouseX, height - mouseY, 1, 1, pixelBuffer);
        var worldPos = new THREE.Vector3(
            (pixelBuffer[0] / 255) * 2 - 1,
            (pixelBuffer[1] / 255) * 2 - 1,
            (pixelBuffer[2] / 255) * 2 - 1
        );
        worldPos.applyMatrix4(camera.matrixWorldInverse);
        scene.remove(mesh);
        return worldPos;
    },

    //获取触摸点的坐标并转换为ThreeJS中的坐标
    touch_crash_detect: function touch_crash_detect() {
        window.addEventListener('touchmove', (event) => {
            // screen3D_to_3DCoord(event.touches[0].clientX, event.touches[0].clientY,camera, window.innerWidth, window.innerHeight);
            let pos = space_pos_convert.get3DPosition(event.touches[0].clientX, event.touches[0].clientY, camera, scene, 1);
            if (pos.y != 0) {
                pos.y = 0;
            }
            return pos;
            // playerMesh.position.set(pos.x, pos.y, pos.z);
        });
    }