开启辅助访问
 找回密码
 注册帐号

扫一扫,访问微社区

开发者专栏

关注:1972

当前位置:游戏蛮牛 技术专区 开发者专栏

__________________________________________________________________________________
开发者干货区版块规则:

  1、文章必须是图文形式。(至少2幅图)
      2、文章字数必须保持在1500字节以上。(编辑器右下角有字数检查)
      3、本版块只支持在游戏蛮牛原创首发,不支持转载。
      4、本版块回复不得无意义,如:顶、呵呵、不错......【真的会扣分的哦】
      5、......
__________________________________________________________________________________
查看: 4222|回复: 46

[Moscibroda] 空间增强现实——使用Unity3D实现基于贝塞尔曲面的投影变形

[复制链接]  [移动端链接]
排名
3711
昨日变化
1

11

主题

42

帖子

732

积分

Rank: 9Rank: 9Rank: 9

UID
139121
好友
7
蛮牛币
1442
威望
0
注册时间
2016-3-11
在线时间
237 小时
最后登录
2017-11-23

专栏作家

发表于 2016-12-16 20:55:31 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?注册帐号

x
本帖最后由 仅为年时 于 2016-12-29 17:05 编辑

车体投影

车体投影

异形表面投影如何实现?
——答曰:空间增强现实中的投影变形技术

前言
      一般的投影是在平面、柱面或者球面屏幕上进行的。但是由于某游戏蛮牛2017些特殊的需求,需要在一些特殊的外形表面上进行投影,例如汽车表面、机器人表面或者其他一些工艺品等。这时仅仅从一个方向进行投影往往会有很多投影死角是不能被照亮的。所以需要从多个角度使用多个投影机进行工作。对于这种特殊的投影需求,投影的图像需要进行一些手动的变形以适应那些特殊的投影表面,以及不同投影图像之间的拼接。本文对最主要的贝塞尔变形过程进行介绍,并且附上主要源代码。

1 原理介绍
     在Unity 3D中,可以生成一个网格,网格线的每一个交叉点都是三角面片的顶点,如图1所示。
                           
                                  图1  网格控制示意图
      然后将要投影的图像以纹理贴图的方式贴在网格上。此时,网格对应点已经和图像的像素点产生了映射关系。用户只需要控制网格顶点变动,其动作趋势就会被捕捉到,然后图像相应的映射点产生一致的位移。图中的每一个三角形面片都是一个图像单元。在图像区域人为生成一个控制点阵列(例如3*4),当某一个控制点移动时,其周围的三角面片顶点会依据距离远近进行不同程度的移动,这些三角面片也会随之发生形变。从全局角度看,所有的面片都发生着变化,进而使得贴附在网格面上的图像也发生着相应的变化。这一过程如图2所示。
               
                                   图2  图像随顶点变化示意图
      这样一来,将控制点进行拖动,同时对照投影屏幕上的图像,就可以使图像的特定点达到指定的位置上。图1中网格记录的是图像的对应点的位置,一旦网格控制点的位置变化,对应的图像位置也会发生相应的变化,被拉伸的地方要进行插值,被压缩的地方进行抽样,为了使这种变换更加平滑,有必要采用一种适当的变形算法。

2 贝塞尔曲面变形的实现
      上面介绍的变形我们采用贝塞尔变形来完成。这种变形的特点在于,图像的每一个位置都是与所有的控制点的位置相关的,对于某一个选定的图像位置,离它越近的控制点被赋予越高的权重。因此,我们只需要调整控制点的位置,就可以控制图像进行变形了。并且这种变形是比较平滑的。(参考书:计算机图形学(第三版),Donald Hearn et al.)
         
                                    图3  贝塞尔曲面

      主要公式如下:
      其中:
  
Bezier.cs 的主要代码如下:
[C#] 纯文本查看 复制代码
using UnityEngine;
using System.Collections;

public class Bezier : MonoBehaviour {

    Vector2[,] UV;
    void Start () {
        UV = new Vector2[GenerateController.sphere_m, GenerateController.sphere_n];
        for (int i = 0; i < GenerateController.sphere_m; i++)
        { 
            for(int j = 0; j < GenerateController.sphere_n; j++)
            {
                float _u = (float)j /( GenerateController.sphere_n -1);
                float _v = (float)i /( GenerateController.sphere_m -1);
                UV[i, j] = new Vector2(_u, _v);
               // Debug.Log("uv: "+_u+"  "+_v);
            }
        }     

    }
    
    // Update is called once per frame
    void Update () {

        //to texture vertices
        int total =  GenerateController.sphere_m* GenerateController.sphere_n;
        int index=0;
        
        for (int i = 0; i < GenerateController.sphere_m; i++)
        {
            for (int j = 0; j < GenerateController.sphere_n; j++)
            {
                Vector3 _p = P(UV[i, j].x, UV[i, j].y);                    
                GenerateController.Spheres[i, j].transform.position = _p;             

            }
        }

        for (int i = 0; i < GenerateController.sphere_m; i++)
        {
            for (int j = 0; j < GenerateController.sphere_n; j++)
            {
                MeshGeneration.vertices[index++] = GenerateController.Spheres[i, j].transform.position;

            }
        }              
    }

    float Factorial(int n)
    { 
        float product=1;
        while(n!= 0)
        {
            product *= n;
            n--;
        }
        return product;
    }
    float Combin(int n,int k)
    {
        if(n>=k)
        {
            float result = Factorial(n) / (Factorial(k) * Factorial(n - k));
            return result;
        }
        else
        {
            return 0;
           
        }       
    }

    float BEZ(int k, int n, float u)
    {
        float result = Combin(n, k) * Mathf.Pow(u, k) * Mathf.Pow(1-u,n-k);
        return result;
    }

    //compute the position of the point with (u,v) image coordinate 
    Vector3 P(float u,float v)
    {
        int m = GenerateController.m;
        int n = GenerateController.n;
        float tempX = 0;
        float tempY = 0;
        float tempZ = 0;
        for (int j = 0; j < m; j++)
        {
            for (int k = 0; k < n; k++)
            {
                tempX += GenerateController.controlPoints[j, k].x * BEZ(j, m-1, v) * BEZ(k, n-1, u);
                tempY += GenerateController.controlPoints[j, k].y * BEZ(j, m-1, v) * BEZ(k, n-1, u);
                tempZ += GenerateController.controlPoints[j, k].z * BEZ(j, m-1, v) * BEZ(k, n-1, u);
            }
        }
        return new Vector3(tempX,tempY,tempZ+5f);
    }

}


3 运行结果
       实验结果如下所示。黄色的方块表示控制点的位置,可以使用鼠标拖动来改变位置。青色的小球显示了生成的网格的顶点位置,实际使用时候没有必要绘制出来。
                                           图4 实验结果图
小结
        通过上面的简单介绍,相信你已经对于贝塞尔曲面有了初步的认识。可以利用给出的代码扩展自己的工程,将变形功能加入到现有的程序中了。

评分

参与人数 3蛮牛币 +6 鲜花 +17 收起 理由
开拓ay + 1 不完整。。。少个类
z7232124 + 6 + 8 很给力!
winning11jc + 8 赞一个!

查看全部评分


回复

使用道具 举报

排名
6128
昨日变化
6

61

主题

273

帖子

1190

积分

Rank: 9Rank: 9Rank: 9

UID
32616
好友
11
蛮牛币
1316
威望
0
注册时间
2014-7-5
在线时间
184 小时
最后登录
2017-9-22

专栏作家

发表于 2016-12-19 08:33:25 | 显示全部楼层
帮你顶一下,好东西。
不去哦缺少代码,MeshGeneration  ,GenerateController 能共享一下吗

回复 支持 反对

使用道具 举报

4四处流浪
429/500
排名
6859
昨日变化
4

6

主题

176

帖子

429

积分

Rank: 4

UID
104368
好友
0
蛮牛币
300
威望
0
注册时间
2015-5-30
在线时间
101 小时
最后登录
2017-7-7
发表于 2016-12-19 09:49:53 | 显示全部楼层
还有数学公式 醉了

回复 支持 反对

使用道具 举报

排名
3711
昨日变化
1

11

主题

42

帖子

732

积分

Rank: 9Rank: 9Rank: 9

UID
139121
好友
7
蛮牛币
1442
威望
0
注册时间
2016-3-11
在线时间
237 小时
最后登录
2017-11-23

专栏作家

 楼主| 发表于 2016-12-19 10:50:59 | 显示全部楼层
gmq517 发表于 2016-12-19 08:33
帮你顶一下,好东西。
不去哦缺少代码,MeshGeneration  ,GenerateController 能共享一下吗 ...

后面会写一个稍微详细的版本,并且把完整的工程发布出来。。。感谢支持~

回复 支持 反对

使用道具 举报

4四处流浪
452/500
排名
4658
昨日变化
3

1

主题

43

帖子

452

积分

Rank: 4

UID
153222
好友
0
蛮牛币
840
威望
0
注册时间
2016-6-30
在线时间
166 小时
最后登录
2017-11-18
发表于 2016-12-19 11:29:01 | 显示全部楼层
虽然不懂,但是我要顶你。

回复 支持 反对

使用道具 举报

5熟悉之中
656/1000
排名
6025
昨日变化
5

11

主题

135

帖子

656

积分

Rank: 5Rank: 5

UID
152229
好友
0
蛮牛币
2532
威望
0
注册时间
2016-6-16
在线时间
296 小时
最后登录
2017-11-22
发表于 2016-12-19 12:10:27 | 显示全部楼层
楼主的这篇让我非常受益,谢谢分享,期待完整工程!!!

回复 支持 反对

使用道具 举报

5熟悉之中
661/1000
排名
3324
昨日变化
1

0

主题

142

帖子

661

积分

Rank: 5Rank: 5

UID
147717
好友
0
蛮牛币
695
威望
0
注册时间
2016-5-5
在线时间
170 小时
最后登录
2017-11-23
发表于 2016-12-19 12:31:12 | 显示全部楼层

楼主的这篇让我非常受益,谢谢分享,期待完整工程!!!

回复 支持 反对

使用道具 举报

7日久生情
1532/5000
排名
874
昨日变化
1

2

主题

87

帖子

1532

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
66098
好友
2
蛮牛币
5082
威望
0
注册时间
2015-1-5
在线时间
487 小时
最后登录
2017-11-24
发表于 2016-12-19 14:00:07 | 显示全部楼层
就是羡慕你们这些个数学大神!~~

回复 支持 反对

使用道具 举报

7日久生情
2035/5000
排名
977
昨日变化
4

3

主题

414

帖子

2035

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
46577
好友
1
蛮牛币
2450
威望
0
注册时间
2014-9-24
在线时间
716 小时
最后登录
2017-11-22
发表于 2016-12-19 14:31:04 | 显示全部楼层
很厉害啊,PS里的变形功能啊

回复 支持 反对

使用道具 举报

排名
6128
昨日变化
6

61

主题

273

帖子

1190

积分

Rank: 9Rank: 9Rank: 9

UID
32616
好友
11
蛮牛币
1316
威望
0
注册时间
2014-7-5
在线时间
184 小时
最后登录
2017-9-22

专栏作家

发表于 2016-12-19 14:44:27 | 显示全部楼层
Moscibroda 发表于 2016-12-19 10:50
后面会写一个稍微详细的版本,并且把完整的工程发布出来。。。感谢支持~ ...

关注你啊,加油

回复 支持 反对

使用道具 举报

7日久生情
3165/5000
排名
92
昨日变化

0

主题

392

帖子

3165

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
239
好友
4
蛮牛币
5703
威望
0
注册时间
2013-6-6
在线时间
661 小时
最后登录
2017-11-24
发表于 2016-12-19 15:21:17 | 显示全部楼层
不错,感谢分享!
[发帖际遇]: ylaier 在论坛发帖时没有注意,被小偷偷去了 1 蛮牛币. 幸运榜 / 衰神榜

回复

使用道具 举报

6蛮牛粉丝
1105/1500
排名
1221
昨日变化
1

3

主题

97

帖子

1105

积分

Rank: 6Rank: 6Rank: 6

UID
3872
好友
1
蛮牛币
2429
威望
0
注册时间
2013-9-14
在线时间
221 小时
最后登录
2017-11-19
发表于 2016-12-19 21:41:37 | 显示全部楼层
太高大上了

回复

使用道具 举报

6蛮牛粉丝
1046/1500
排名
1484
昨日变化
1

0

主题

97

帖子

1046

积分

Rank: 6Rank: 6Rank: 6

UID
1627
好友
0
蛮牛币
1620
威望
0
注册时间
2013-8-6
在线时间
263 小时
最后登录
2017-6-6
发表于 2016-12-20 09:10:58 | 显示全部楼层
就是羡慕你们这些个数学大神!~~

回复 支持 反对

使用道具 举报

2初来乍到
138/150
排名
12493
昨日变化
7

0

主题

17

帖子

138

积分

Rank: 2Rank: 2

UID
116040
好友
0
蛮牛币
135
威望
0
注册时间
2015-7-31
在线时间
69 小时
最后登录
2017-11-7
QQ
发表于 2016-12-20 16:52:23 | 显示全部楼层

虽然不懂,但是我要顶你

回复 支持 反对

使用道具 举报

5熟悉之中
568/1000
排名
3607
昨日变化
4

2

主题

34

帖子

568

积分

Rank: 5Rank: 5

UID
123713
好友
0
蛮牛币
727
威望
0
注册时间
2015-9-23
在线时间
210 小时
最后登录
2017-11-24
发表于 2016-12-21 09:24:56 | 显示全部楼层
不错,谢谢分享!
[发帖际遇]: 一个袋子砸在了 not 头上,not 赚了 1 蛮牛币. 幸运榜 / 衰神榜

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册帐号

本版积分规则

快速回复 返回顶部 返回列表