Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >带角度的LibGDX Cut纹理

带角度的LibGDX Cut纹理
EN

Stack Overflow用户
提问于 2021-01-07 00:28:50
回答 1查看 59关注 0票数 2

假设我有一个Texture,我想把它分成两半,放在一条以给定角度旋转的直线上。

在结果中,我希望得到两个Texture对象与相应的原始纹理的一半。如果它可以通过某种转换/屏蔽来完成,那将是非常好的,这样我就不必在运行时存储两个新纹理的副本。

这有可能吗?

我试图绕过Gdx.gl.glSsisors(),但无法让它工作,因为它需要将屏幕坐标作为参数传递。此外,我还尝试使用Pixmap,但找不到任何可以证明这一点的东西。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-01-10 18:06:40

这可以通过手动计算两个倾斜的四边形并使用SpriteBatch渲染它们来实现。

沿着角度angle切割一个精灵,我们得到一个表示切割的方向矢量

代码语言:javascript
运行
AI代码解释
复制
public void cut(float angle) {
    Vector2 d = (new Vector2(1.0f, 0.0f)).rotate(angle);

如果我们还为TextureUV Mapping定义了四个角,以及中心和一个向量la d远离中心和lb going -d

代码语言:javascript
运行
AI代码解释
复制
Vector2 c = new Vector2(0.5f, 0.5f);
Vector2 la = (new Vector2(d)).scl( 1.0f).add(c);
Vector2 lb = (new Vector2(d)).scl(-1.0f).add(c);

Vector2 tl = new Vector2(0, 1);
Vector2 tr = new Vector2(1, 1);
Vector2 bl = new Vector2(0, 0);
Vector2 br = new Vector2(1, 0);

然后我们可以计算切割的交点。

代码语言:javascript
运行
AI代码解释
复制
Vector2 i1 = new Vector2();
Vector2 i2 = new Vector2();

if (Intersector.intersectSegments(c, la, tl, tr, i1) || Intersector.intersectSegments(c, lb, tl, tr, i1))
    i2.set(1.0f - i1.x, 1.0f - i1.y);
else {
    if (Intersector.intersectSegments(c, la, tl, bl, i1) || Intersector.intersectSegments(c, lb, tl, bl, i1))
        i2.set(1.0f - i1.x, 1.0f - i1.y);
}

在这一点上,我们知道切割的一半将由顶点i1i2tltrblbr中的两个组成,所以如果我们按远离切割的角度对它们进行排序,然后从i1中取出前4个,我们就得到了构建倾斜四边形所需的顶点:

代码语言:javascript
运行
AI代码解释
复制
Vector2[] vertexList = new Vector2[] {
        tl, tr, bl, br, i1, i2
};

Array<VertexAngle> vas = new Array<>();
for (Vector2 v : vertexList) {
    Vector2 vd = (new Vector2(v)).sub(c);
    float a = d.angle(vd);
    VertexAngle va = new VertexAngle();
    va.v = v;
    va.a = a;
    vas.add(va);
}

vas.sort(new Comparator<VertexAngle>() {
    @Override
    public int compare(VertexAngle a, VertexAngle b) {
        return Float.compare(a.a, b.a);
    }
});

Array<Vector2> nv = new Array<>();
for (VertexAngle va : vas)
    nv.add(va.v);

int index = nv.indexOf(i1, true);

可以通过调用SpriteBatch上的draw来构造和呈现包含绘制调用的顶点数据的浮点数组。

例如:

以上示例的完整源代码如下:

代码语言:javascript
运行
AI代码解释
复制
package com.bornander.sandbox;

import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.math.Intersector;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.utils.Array;

import java.util.Comparator;

public class SandboxGame extends ApplicationAdapter {
    OrthographicCamera camera;
    SpriteBatch batch;
    Texture texture;
    CutTexture cutTexture;

    public static class CutTexture
    {
        public static class VertexAngle {
            public Vector2 v;
            public float a;
        }

        public static class CutHalf {
            public float[] vertices = new float[4 * 5];

            public void translate(float x, float y) {
                for(int i = 0; i < vertices.length; i += 5) {
                    vertices[i + 0] += x;
                    vertices[i + 1] += y;
                }
            }
        }

        public Vector2 position = new Vector2();
        public Vector2 driftDirection = new Vector2();
        public float drift = 0.0f;
        public Texture source;
        public CutHalf halfA = new CutHalf();
        public CutHalf halfB = new CutHalf();

        public void cut(float angle) {
            Vector2 d = (new Vector2(1.0f, 0.0f)).rotate(angle);
            Vector2 c = new Vector2(0.5f, 0.5f);
            driftDirection.set(d).rotate(90.0f);
            Vector2 la = (new Vector2(d)).scl( 1.0f).add(c);
            Vector2 lb = (new Vector2(d)).scl(-1.0f).add(c);

            Vector2 tl = new Vector2(0, 1);
            Vector2 tr = new Vector2(1, 1);
            Vector2 bl = new Vector2(0, 0);
            Vector2 br = new Vector2(1, 0);

            Vector2 i1 = new Vector2();
            Vector2 i2 = new Vector2();

            if (Intersector.intersectSegments(c, la, tl, tr, i1) || Intersector.intersectSegments(c, lb, tl, tr, i1))
                i2.set(1.0f - i1.x, 1.0f - i1.y);
            else {
                if (Intersector.intersectSegments(c, la, tl, bl, i1) || Intersector.intersectSegments(c, lb, tl, bl, i1))
                    i2.set(1.0f - i1.x, 1.0f - i1.y);
            }

            Vector2[] vertexList = new Vector2[] {
                    tl, tr, bl, br, i1, i2
            };

            Array<VertexAngle> vas = new Array<>();
            for (Vector2 v : vertexList) {
                Vector2 vd = (new Vector2(v)).sub(c);
                float a = d.angle(vd);
                VertexAngle va = new VertexAngle();
                va.v = v;
                va.a = a;
                vas.add(va);
            }

            vas.sort(new Comparator<VertexAngle>() {
                @Override
                public int compare(VertexAngle a, VertexAngle b) {
                    return Float.compare(a.a, b.a);
                }
            });

            Array<Vector2> nv = new Array<>();
            for (VertexAngle va : vas)
                nv.add(va.v);

            int index = nv.indexOf(i1, true);
            int idx = 0;
            int lastIndex = 0;
            for(int j = 0; j < 4; ++j) {
                lastIndex = (index + j) % nv.size;
                Vector2 vertex = nv.get(lastIndex);
                float width = source.getWidth();
                float height = source.getWidth();
                float fx2 = position.x + width * vertex.x - width / 2.0f;
                float fy2 = position.y + height * vertex.y - height / 2.0f;

                halfA.vertices[idx++] = fx2;
                halfA.vertices[idx++] = fy2;
                halfA.vertices[idx++] = Color.WHITE_FLOAT_BITS;
                halfA.vertices[idx++] = vertex.x;
                halfA.vertices[idx++] = 1.0f - vertex.y;
            }

            idx = 0;
            for(int j = 0; j < 4; ++j) {
                Vector2 vertex = nv.get((lastIndex + j) % nv.size);
                float width = source.getWidth();
                float height = source.getWidth();
                float fx2 = position.x + width * vertex.x - width / 2.0f;
                float fy2 = position.y + height * vertex.y - height / 2.0f;

                halfB.vertices[idx++] = fx2;
                halfB.vertices[idx++] = fy2;
                halfB.vertices[idx++] = Color.WHITE_FLOAT_BITS;
                halfB.vertices[idx++] = vertex.x;
                halfB.vertices[idx++] = 1.0f - vertex.y;
            }
        }

        public void render(SpriteBatch batch) {

            float dx = driftDirection.x * drift;
            float dy = driftDirection.y * drift;

            halfA.translate(dx, dy);
            halfB.translate(-dx, -dy);

            batch.draw(source, halfA.vertices, 0, 20);
            batch.draw(source, halfB.vertices, 0, 20);

            halfA.translate(-dx, -dy);
            halfB.translate(dx, dy);
        }
    }

    @Override
    public void create () {
        float aspectRatio = (float)Gdx.graphics.getHeight()/(float)Gdx.graphics.getWidth();
        camera = new OrthographicCamera(800, 800 * aspectRatio);
        camera.position.set(camera.viewportWidth / 2.0f, camera.viewportHeight / 2.0f, 0.0f);
        batch = new SpriteBatch();
        texture = new Texture(Gdx.files.internal("badlogic.jpg"));

        Gdx.gl.glCullFace(0);
        cutTexture = new CutTexture();
        cutTexture.position.set(camera.viewportWidth / 2.0f, camera.viewportHeight / 2.0f);
        cutTexture.source = texture;
        cutTexture.cut(0);
    }

    float[] cutAngles = new float[] { 0.0f, -22.5f, -45.0f, -12.0f, -75.0f, -90.0f};
    int ai = 0;

    @Override
    public void render () {
        if (Gdx.input.isKeyJustPressed(Input.Keys.SPACE))
        {
            cutTexture.drift = 0.0f;
            cutTexture.cut(cutAngles[(ai++) % cutAngles.length]);
        }
        cutTexture.drift -= 64.0f * Gdx.graphics.getDeltaTime();
        Gdx.gl.glClearColor(0.6f, 0.6f, 1.0f, 1);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
        Gdx.gl.glCullFace(GL20.GL_NONE);
        camera.update();
        batch.setProjectionMatrix(camera.combined);
        batch.begin();
        cutTexture.render(batch);
        batch.end();
    }
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65605106

复制
相关文章
libgdx 概述
libgdx 是一个跨平台的2D/3D的游戏开发框架,由Java/C/C++语言编写而成,基于 Apache License 2.0 协议,对商业使用和非商业使用均免费,代码托管于github
阳光岛主
2019/02/19
2.4K0
libgdx 概述
libgdx 环境搭建
1) libgdx 开发包下载: google code(最新 libgdx-0.9.7.zip    2012.11.12)
阳光岛主
2019/02/19
1.2K0
libgdx 环境搭建
第二章:图形绘制TextureSpriteBatch 类(相当于画笔)为什么要2的N次方?TextureRegion 可用于图片截取。Sprite类清屏
1.纹理(Texture):图片从原始格式,解码并上传到GPU的过程,被称之为纹理。 2.用途:其实就是承装获取到目的图片的容器 3.使用:Gdx.files.* 文件模块
Xiaolei123
2018/08/10
1K0
第二章:图形绘制TextureSpriteBatch 类(相当于画笔)为什么要2的N次方?TextureRegion 可用于图片截取。Sprite类清屏
libgdx 图形绘制
一个图片从原始格式解码并上传到GPU就被称为纹理。OpenGL要求纹理的高度和宽度都必须是2的n次方大小,只有满足这个条件纹理图片才是有效的。 一旦获取了像素值,我们就可以将这些数据传给OpenGL,让OpenGL生成一个纹理贴图
阳光岛主
2019/02/19
1.7K0
libgdx 图形绘制
使用 Win2D 绘制带图片纹理的圆(或椭圆)
发布于 2018-11-11 21:50 更新于 2018-11-28 08:25
walterlv
2020/02/10
7490
Grab Cut与Graph Cut
关注深度学习、神经网络最近几年发展的朋友一定知道,现在图像的语义分割等技术最近几年发展非常迅猛,最典型的就是像Mask R-CNN这样的神作,可以非常精准的从图像中分割出不同的物体。
bye
2020/10/30
1.8K0
Grab Cut与Graph Cut
第六章:常用控件日常科普标签(Lable)图片(Image)按钮(Button)
1.控件是用于开发构建用户界面(UI)控件,帮助完成开发中视窗,文本框,按钮,下拉菜单,等界面元素 2.在LibGdx中,提供的控件有 按钮,勾选框,下拉框,图片,输入框,列表,滑动面板,滑条,分割面板 3.LibGdx中,控件需要样式(Style)才能完成控件的初始化,比如:(LabelStyle,ButtonStyle)等
Xiaolei123
2018/08/10
8780
第六章:常用控件日常科普标签(Lable)图片(Image)按钮(Button)
Unity3D学习笔记2——绘制一个带纹理的面
上一篇文章《Unity3D学习笔记1——绘制一个三角形》中介绍了Unity3D的HelloWorld——绘制一个简单的三角形。不过这个三角形太简单了,连材质都没有。那么这里就将三角形扩展为一个矩形的面,并且为这个面贴上纹理。
charlee44
2021/07/13
1.1K0
cut命令
cut命令用来显示行中的指定部分,其从文件的每一行剪切字节、字符和字段并将这些字节、字符和字段写至标准输出,如果不指定File参数,cut命令将读取标准输入,该命令常用的两项功能,一是用来显示文件的内容,它依次读取由参数file所指明的文件,将它们的内容输出到标准输出上,其二是连接两个或多个文件,如cut f1 f2 > f3将把文件f1和几的内容合并起来,然后通过输出重定向符>的作用,将它们放入文件f3中,当文件较大时,文本在屏幕上迅速闪过,也就是滚屏现象,为了控制滚屏,可以执行Ctrl+S按键停止滚屏,按Ctrl+Q键可以恢复滚屏,按Ctrl+C键终止该命令的执行等操作。
WindRunnerMax
2020/08/27
1.3K0
Shader-基础纹理-遮罩纹理
遮罩纹理(mask texture)控制光照的强度,获得更加细腻的效果,通过遮罩纹理控制光照。在制作地形材质的时候混合多张图片,遮罩纹理控制如何混合这些纹理。 通过采样得到的纹素值与某种表面属性相乘,来更加精准的控制模型表面的各种属性。 在代码中添加了BumpMap来进行凹凸纹理效果,通过SpecularMask实现控制高光的光照
祝你万事顺利
2019/05/28
1.2K0
Shader-基础纹理-渐变纹理
一种基于冷暖色调的着色技术,通过渐变纹理控制漫反射光照。核心部分来说用过使用halfLambert构建一个纹理坐标,用这个纹理坐标来对渐变纹理进行采样。
祝你万事顺利
2019/05/28
1.2K0
Linux 命令 | cut
cut 命令可用于删除一个文本文件中每行的字符,留下需要的列,是一个很方便的文本处理命令。
小林C语言
2023/09/14
3050
Linux 命令 | cut
纹理压缩
本文介绍了纹理压缩的基本概念、原理、常用压缩方式、压缩工具及相关技术标准,旨在帮助读者了解纹理压缩的基本知识,从而更好地进行纹理压缩相关的实践。
MelonTeam
2018/01/04
1.6K0
纹理压缩
Shell之cut
cut的工作就是“剪”,具体的说就是在文件中负责剪切数据用的。 cut 命令从文件的每一行剪切字节、字符和字段并将这些字节、字符和字段输出。
编程那点事
2023/02/25
6320
Shader-高级纹理-立方体纹理
是环境映射(EnvironmentMapping)一种实现方式。 纹理采样:对立方体采样需要提供一个三维的纹理坐标,这个三维纹理坐标表示了我们在世界空间下的一个3D、方向。
祝你万事顺利
2019/05/29
9090
cuda纹理内存的使用
CUDA纹理内存的访问速度比全局内存要快,因此处理图像数据时,使用纹理内存是一个提升性能的好方法。 贴一段自己写的简单的实现两幅图像加权和的代码,使用纹理内存实现。 输入:两幅图 lena, moon
一棹烟波
2018/01/12
2.2K0
cuda纹理内存的使用
第一章:Hello Libgdx
https://gitee.com/xcode_xiao/LibGdxDemos2/tree/master/HelloGDX
Xiaolei123
2018/08/10
8190
第一章:Hello Libgdx
OpenGL(八)--纹理相关APIOpenGL(八)--纹理相关API
OpenGL(八)--纹理相关API 1. 原始图像数据 //存储图像数据所占内存大小 size = 图像的高度 * 图像的宽度 * 每个像素所占字节数 像素所占字节数:一般为4Byte,包含RGBA四个通道,每个通道为1Byte(8Bit) 2. 认识函数 像素存储方式 //改变像素存储方式 void glPixelStorei(GLenum pname,GLint param); //恢复像素存储方式 void glPixelStoref(GLenum pname,GLint param); /
用户8893176
2021/08/09
1.3K0
OpenGL(八)--纹理相关APIOpenGL(八)--纹理相关API
带有实际示例的Linux Cut命令
cut命令用于Linux和Unix系统中,从文件的每一行剪切字节、字符和字段并将这些字节、字符和字段写至标准输出。
用户6543014
2020/04/15
3.7K0
带有实际示例的Linux Cut命令
点击加载更多

相似问题

Tkinter中的Entry Widget导致的空白

114

Tkinter文件路径中的文件读取

11

Tkinter类中entry.get()的问题

12

Python Tkinter中的Entry.get()错误

11

限制Tkinter Entry小部件中的值

82
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档