当前位置:  编程技术>移动开发
本页文章导读:
    ▪Unity3D研究院之与依据动态的两个轨迹点绘制面详解(二十)        Unity3D研究院之与根据动态的两个轨迹点绘制面详解(二十)        暂时我们先忽略Z轴(这样在平面中看得更清楚),假设Z轴坐标都为0。假设游戏中有两个轨迹点在动态的增加与改变,最.........
    ▪ CCLayer 在 init 中调用 schedual 方法后引用计数混乱的有关问题        CCLayer 在 init 中调用 schedual 方法后引用计数混乱的问题参考相关问题链接: http://www.cocos2d-iphone.org/forum/topic/314 先上代码再解释: RefferenceCountLayer.h // // RefferenceCountLayer.h // HungryBear // // Cre.........
    ▪ objective-c 交叉引用有关问题的解决方案       objective-c 交叉引用问题的objective-c 不允许交叉引用,上代码: A.h #import <Foundation/Foundation.h> #import "B.h" @interface A : NSObject { B* _b; // 报错点 1~ } -(void) test:(B*)b; // 报错点 2~ @end A.mm #im.........

[1]Unity3D研究院之与依据动态的两个轨迹点绘制面详解(二十)
    来源: 互联网  发布时间: 2014-02-18
Unity3D研究院之与根据动态的两个轨迹点绘制面详解(二十)
原创文章如需转载请注明:转载自雨松MOMO程序研究院本文链接地址:Unity3D研究院之与根据动态的两个轨迹点绘制面详解(二十)

        大家应该知道3D世界中任何的面都是由三角形绘制完成的,因为任何无规则的集合图形都可以由三角形来组成。比如四边形,无论是正四边形还是无规则四边形都可以由两个三角形拼接而成。结合本文的标题大家仔细想想,如果需要绘制一个动态无规则面其实只需要得到动态的两个轨迹点即可,那么结合下面的图片大家仔细在想想。



(点击图片,查看大图)

        暂时我们先忽略Z轴(这样在平面中看得更清楚),假设Z轴坐标都为0。假设游戏中有两个轨迹点在动态的增加与改变,最后将这两个点改变的轨迹拼接起来就是它们生成的面。如上图所示,第一个点的轨迹是“ 3,4,5,6,7” 第二个点的轨迹是“2,1,10,9,8” 。这两个点的长度是可变的,前提是他们两个的数量必需完全一样。接着,如下图所示,我们将这些点两两相连起来,目前一共形成了8个三角形面(可根据两个动态点的数量而确定整个网格面三角形面的数量)。最后我们将这8个三角形填充上同样的颜色,就可以实现一个完整的立体网格面。

 


(点击图片,查看大图)

         原理很简单,就是这样的我相信大家看到这里大家都能明白,接着我们就学习如何使用代码来实现它。首先创建Unity工程,接着创建一个空的游戏对象,然后给该游戏对象绑定Mesh Filter组件 与 Mesh Renderer组件。

Mesh Filter组件:表示网格面,这个网格面是由我们使用代码将所有三角形拼接起来生成的面。

Mesh Renderer组件:表示表示网格的渲染,可设置一个渲染的材质,它包括贴图与颜色。

       如下图所示,我说说里面比较重要的属性。Mesh Renderer中,Materials下拉列表中可设置网格模型的材质,此时我们设置了一个红色的材质。 Mesh Filter:目前为None,也不用再编辑器中为它赋值,因为这个网格模型我们会在代码中生成并且赋值。在下面就是方刚我们设置红色的材质资源,Shader中设置了贴图的属性,目前是GUI/ TextShader。它表示这个材质的渲染级别在GUI上,就是优先级是最一层的。举个例子无论在这个网格模型的前面绘制多少模型,它永远都会在最前面显示。就这个例子而言它的存在并不是必需的,其实Shader的选项还有很多,可透明、不可透明、镜面、反射等等,后期我会向大家详细道来。


 

OK,现在资源文件都已经准备完毕,下面我们学习如何来绘制一个三角形,从简单的开始。。把下面的代码绑定在摄像机对象当中。

using UnityEngine;
using System.Collections.Generic;
using System;

public class Test : MonoBehaviour {

	void Start ()
	{
		//得到MeshFilter对象,目前是空的。
		MeshFilter meshFilter = (MeshFilter)GameObject.Find("face").GetComponent(typeof(MeshFilter));
		//得到对应的网格对象
		Mesh mesh = meshFilter.mesh;

		//三角形顶点的坐标数组
		Vector3[] vertices = new Vector3[3];
		//三角形顶点ID数组
		int[] triangles   = new int[3];

		//三角形三个定点坐标,为了显示清楚忽略Z轴
		vertices[0] = new Vector3(0,0,0);
		vertices[1] = new Vector3(0,1,0);
		vertices[2] = new Vector3(1,0,0);

		//三角形绘制顶点的数组
		triangles[0] =0;
		triangles[1] =1;
		triangles[2] =2;

		//注释1
		mesh.vertices = vertices;

		mesh.triangles = triangles;

	}

}



注解1:这里是将模型的顶点数组与坐标数组赋值给网格模型,还记得刚刚在创建Mesh Filter时,当时没有在编辑器中给网格模型赋值,实际上代码走到这里就会重新为网格模型MeshFilter赋值,接着我们在代码中绘制的三角形就会显示在屏幕当中。          代码中有两个非常重要的概念,就是三角形顶点数组与坐标数组。先说说坐标数组,假设需要绘制一个四边形,此时三角形坐标数组的长度应当是4,它保存着四边形四个顶点的坐标。然后是顶点数组,四边形是由两个三角形组成,然而一个三角形是由3个顶点组成,两个三角形就应当是6个顶点组成,无论多少个三角形它们的结构都应当是以此类推。

如图所示,三角形已经绘制在屏幕当中。 图中数组 0 1 2 表示该三角形的三个顶点的ID。这个ID对应代码中对应vertices数组索引顶点的坐标。

 


 

下面我们修改一下代码,让屏幕中一共绘制4个三角形。

using UnityEngine;
using System.Collections.Generic;
using System;

public class Test : MonoBehaviour {

    //网格模型顶点数量
	private int VERTICES_COUNT = 6;

	void Start ()
	{
		//得到MeshFilter对象,目前是空的。
		MeshFilter meshFilter = (MeshFilter)GameObject.Find("face").GetComponent(typeof(MeshFilter));
		//得到对应的网格对象
		Mesh mesh = meshFilter.mesh;

		//三角形顶点的坐标数组
		Vector3[] vertices = new Vector3[VERTICES_COUNT];

		//得到三角形的数量
		int triangles_count = VERTICES_COUNT - 2;

		//三角形顶点ID数组
		int[] triangles   = new int[triangles_count *3];

		//三角形三个定点坐标,为了显示清楚忽略Z轴
		vertices[0] = new Vector3(0,0,0);
		vertices[1] = new Vector3(0,1,0);
		vertices[2] = new Vector3(1,0,0);
		vertices[3] = new Vector3(1,1,0);
		vertices[4] = new Vector3(2,0,0);
		vertices[5] = new Vector3(2,1,0);

		//三角形绘制顶点的数组
		triangles[0] =0;
		triangles[1] =1;
		triangles[2] =2;
		triangles[3] =3;
		triangles[4] =2;
		triangles[5] =1;

		triangles[6] =2;
		triangles[7] =3;
		triangles[8] =4;

		triangles[9] =5;
		triangles[10] =4;
		triangles[11] =3;

     	//绘制三角形
		mesh.vertices = vertices;

		mesh.triangles = triangles;

	}

}

 

         已知模型的顶点数量,顶点数量减去2就是三角形的数量,三角形的数量在乘以3就是三角形顶点的数量。根据这个公式计算得知,上述代码中共绘制4个三角形,顶点坐标数组应当是6,顶点ID数组应当是12。多个三角形在顶点ID数组中排列方式比较特殊,大家需要仔细记录一下不然无法绘制出正确的三角形。如下图所示,由于我这边没有合适的3D坐标点,就用正三角形拼接出一个正四边形,这个四边形是由6个顶点4个小三角形组成 ,看到这里思路清晰的朋友应当明了无规则四边形的绘制原理和它完全一样。只需要传入适当的3D坐标点即可。

 


 

          根据上面的逻辑,我们修改一下算法。假设三角形的顶点坐标为任意数量,我们需要更根据顶点坐标数量来计算对应顶点ID的数组内容。在for循环中start =0 与end =3的含义是绘制从顶点坐标数组中索引为0的顶点开始绘制到数组索引为3的顶点,也就说是这里从0到3绘制了3个三角形。


using UnityEngine;
using System.Collections.Generic;
using System;

public class Test : MonoBehaviour {

    //网格模型顶点数量
	private int VERTICES_COUNT = 6;

	void Start ()
	{
		//得到MeshFilter对象,目前是空的。
		MeshFilter meshFilter = (MeshFilter)GameObject.Find("face").GetComponent(typeof(MeshFilter));
		//得到对应的网格对象
		Mesh mesh = meshFilter.mesh;

		//三角形顶点的坐标数组
		Vector3[] vertices = new Vector3[VERTICES_COUNT];

		//得到三角形的数量
		int triangles_count = VERTICES_COUNT - 2;

		//三角形顶点ID数组
		int[] triangles   = new int[triangles_count *3];

		//三角形三个定点坐标,为了显示清楚忽略Z轴
		vertices[0] = new Vector3(0,0,0);
		vertices[1] = new Vector3(0,1,0);
		vertices[2] = new Vector3(1,0,0);
		vertices[3] = new Vector3(1,1,0);
		vertices[4] = new Vector3(2,0,0);
		vertices[5] = new Vector3(2,1,0);

     	//绘制三角形
		mesh.vertices = vertices;

		//起始三角形顶点
		int start = 0;

		//结束三角形的顶点
		int end = 3;

		for(int i = start; i <end; i++)
		{
			for(int j = 0; j < 3; j++)
			{
				if( i%2 ==0)
				{
					triangles[3*i + j] = i +j;
				}else
				{
					triangles[3*i + j] = i + 2-j;
				}

			}
		}

		mesh.triangles = triangles;
	}
}


      如下图所示,根据上面的逻辑算法,共绘制了3个三角形,并且顶点坐标ID是由 0 到3 。 说到这里请大家仔细想想本文的标题内容,其实两个动态轨迹的点就是在维护triangles顶点坐标数组。triangles[0]、triangles[2]、triangles[4]……表示一个轨迹点的值,triangles[1]、triangles[3]、triangles[5]……就表示另一个轨迹点的值,最终将它们通过上面的算法将三角形面连接起来那么就是动态的两个点轨迹绘制面了。


 

         Unity3D其实非常好玩,上手虽然很简单,但是想深入其实并没有那么容易,今天这篇文章的思路已经写完,如果还是没能明白的朋友请仔细揣摩三角形与四边形之间的却别,哇咔咔,已经不早了我也得睡觉了,明天还得上班 GOGOGOGOGO加油~希望我们大家可以共同学习,共同进步。


1楼szjhqt0512昨天 15:32路过

    
[2] CCLayer 在 init 中调用 schedual 方法后引用计数混乱的有关问题
    来源: 互联网  发布时间: 2014-02-18
CCLayer 在 init 中调用 schedual 方法后引用计数混乱的问题

参考相关问题链接:

http://www.cocos2d-iphone.org/forum/topic/314

先上代码再解释:

RefferenceCountLayer.h

//
//  RefferenceCountLayer.h
//  HungryBear
//
//  Created by Bruce Yang on 12-8-9.
//  Copyright (c) 2012年 EricGameStudio. All rights reserved.
//

#import "cocos2d.h"

@interface RefferenceCountLayer : CCLayer

@end


RefferenceCountLayer.mm
//
//  RefferenceCountLayer.mm
//  HungryBear
//
//  Created by Bruce Yang on 12-8-9.
//  Copyright (c) 2012年 EricGameStudio. All rights reserved.
//

#import "RefferenceCountLayer.h"

@implementation RefferenceCountLayer

-(ccColor4B) randomBrightColor {
    while(true) {
        float requiredBrightness = 192;
        ccColor4B randomColor = ccc4(arc4random() % 255, 
                                     arc4random() % 255, 
                                     arc4random() % 255, 
                                     255);
        if (randomColor.r > requiredBrightness || 
            randomColor.g > requiredBrightness ||
            randomColor.b > requiredBrightness) {
            return randomColor;
        }        
    }
}

-(id) init {
    if((self = [super init])) {
        self.isTouchEnabled = YES;
        
        ccColor4B color4B = [self randomBrightColor];
        CCLayerColor* lyrColor = [CCLayerColor layerWithColor:color4B];
        [self addChild:lyrColor];
        
        NSLog(@"init() -> 1.RefferenceCount = %d", [self retainCount]);
        
        [self schedule:@selector(tick:)];
        
        NSLog(@"init() -> 2.RefferenceCount = %d", [self retainCount]);
    }
    return self;
}

-(void) draw {
    NSLog(@"draw() -> RefferenceCount = %d", [self retainCount]);
}

-(void) tick:(ccTime)dt {
    NSLog(@"tick() -> RefferenceCount = %d", [self retainCount]);
}

-(void) ccTouchesBegan:(NSSet*)touches withEvent:(UIEvent*)event {
    NSLog(@"ccTouchesBegan()");
    [[CCDirector sharedDirector] replaceScene:[RefferenceCountLayer node]];
}

-(void) dealloc {
    NSLog(@"ReffenceCountLayer.dealloc!");
    [super dealloc];
}

@end


控制台输出如下:

2012-08-09 00:41:55.733 WonderPipeEffects1[18926:707] init() -> 1.RefferenceCount = 1
2012-08-09 00:41:55.737 WonderPipeEffects1[18926:707] init() -> 2.RefferenceCount = 2
2012-08-09 00:41:55.741 WonderPipeEffects1[18926:707] tick() -> RefferenceCount = 4
2012-08-09 00:41:55.748 WonderPipeEffects1[18926:707] draw() -> RefferenceCount = 4
2012-08-09 00:41:55.753 WonderPipeEffects1[18926:707] tick() -> RefferenceCount = 4
2012-08-09 00:41:55.758 WonderPipeEffects1[18926:707] draw() -> RefferenceCount = 4
2012-08-09 00:41:55.769 WonderPipeEffects1[18926:707] tick() -> RefferenceCount = 4
2012-08-09 00:41:55.775 WonderPipeEffects1[18926:707] draw() -> RefferenceCount = 4
2012-08-09 00:41:55.785 WonderPipeEffects1[18926:707] tick() -> RefferenceCount = 4
2012-08-09 00:41:55.788 WonderPipeEffects1[18926:707] draw() -> RefferenceCount = 4
2012-08-09 00:41:55.803 WonderPipeEffects1[18926:707] tick() -> RefferenceCount = 4
2012-08-09 00:41:55.807 WonderPipeEffects1[18926:707] draw() -> RefferenceCount = 4
2012-08-09 00:41:55.818 WonderPipeEffects1[18926:707] tick() -> RefferenceCount = 4
2012-08-09 00:41:55.820 WonderPipeEffects1[18926:707] draw() -> RefferenceCount = 4
2012-08-09 00:41:55.836 WonderPipeEffects1[18926:707] tick() -> RefferenceCount = 4
2012-08-09 00:41:55.839 WonderPipeEffects1[18926:707] draw() -> RefferenceCount = 4
2012-08-09 00:41:55.852 WonderPipeEffects1[18926:707] tick() -> RefferenceCount = 4
2012-08-09 00:41:55.856 WonderPipeEffects1[18926:707] draw() -> RefferenceCount = 4
2012-08-09 00:41:55.869 WonderPipeEffects1[18926:707] tick() -> RefferenceCount = 4
2012-08-09 00:41:55.872 WonderPipeEffects1[18926:707] draw() -> RefferenceCount = 4
2012-08-09 00:41:55.886 WonderPipeEffects1[18926:707] tick() -> RefferenceCount = 4
2012-08-09 00:41:55.889 WonderPipeEffects1[18926:707] draw() -> RefferenceCount = 4
2012-08-09 00:41:55.907 WonderPipeEffects1[18926:707] tick() -> RefferenceCount = 4
2012-08-09 00:41:55.911 WonderPipeEffects1[18926:707] draw() -> RefferenceCount = 4
2012-08-09 00:41:55.917 WonderPipeEffects1[18926:707] ccTouchesBegan()
2012-08-09 00:41:55.921 WonderPipeEffects1[18926:707] init() -> 1.RefferenceCount = 1
2012-08-09 00:41:55.925 WonderPipeEffects1[18926:707] init() -> 2.RefferenceCount = 2
2012-08-09 00:41:55.928 WonderPipeEffects1[18926:707] tick() -> RefferenceCount = 3
2012-08-09 00:41:55.932 WonderPipeEffects1[18926:707] ReffenceCountLayer.dealloc!
2012-08-09 00:41:55.936 WonderPipeEffects1[18926:707] draw() -> RefferenceCount = 4
2012-08-09 00:41:55.940 WonderPipeEffects1[18926:707] tick() -> RefferenceCount = 4
2012-08-09 00:41:55.944 WonderPipeEffects1[18926:707] draw() -> RefferenceCount = 4
2012-08-09 00:41:55.952 WonderPipeEffects1[18926:707] tick() -> RefferenceCount = 4
2012-08-09 00:41:55.954 WonderPipeEffects1[18926:707] draw() -> RefferenceCount = 4
2012-08-09 00:41:55.970 WonderPipeEffects1[18926:707] tick() -> RefferenceCount = 4
2012-08-09 00:41:55.980 WonderPipeEffects1[18926:707] draw() -> RefferenceCount = 4

测试结论如下:

init 方法里面调用 schedual 方法以后,RefferenceCountLayer 的引用计数会加1,这里没有问题~

但是到了 draw()、tick() 方法里面,引用计数竟然由 2 直接跳到 4!

我是百思不得其解,不过经过我的测试,发现引用计数虽然直接跳到 4 了,

但是在 replaceScene 的时候,依然能够看到 RefferenceCountLayer 的 dealloc 方法被调用了,

也就是说,该对象并不会因此而出现什么内存泄露的问题~

后面我思考了一下,引用计数由 2 跳到 4 肯定是在 cocos2d 框架内部安全的增长到 4 的,

这个不用我们去操心,没有内存泄露,我们知道这样一件事情就行了~

前面附的链接里面 cocos2d 作者之一 Riq 没有就此问题做较为仔细的回复,这是问题的来源,

不过也不能去责怪他什么,人的精力毕竟是有限的,他不可能就每个问题都做详细的回复,

凡事都往好的方面想,Riq 作为 cocos2d 的主要负责人之一,为我们提供了这么 nice 的东西,这样便行了~



    
[3] objective-c 交叉引用有关问题的解决方案
    来源: 互联网  发布时间: 2014-02-18
objective-c 交叉引用问题的

objective-c 不允许交叉引用,上代码:

A.h

#import <Foundation/Foundation.h>
#import "B.h"

@interface A : NSObject {
    B* _b; // 报错点 1~
}

-(void) test:(B*)b; // 报错点 2~

@end

A.mm

#import "A.h"

@implementation A

-(void) test:(B*)b {
    NSLog(@"test");
}

@end

B.h

#import <Foundation/Foundation.h>
#import "A.h"

@interface B : NSObject {
    A* _a; // 报错点 3~
}

@end

B.mm

#import "B.h"

@implementation B

@end


头文件中不要包含彼此的头文件,将成员变量类型、方法参数类型改为由具体的类名 (A*,B*)  改为 id

.mm 实现文件中包含彼此的头文件不会出错,that's all!

1楼gaoyp昨天 09:05可以在.h文件中用@class啊。用id代替类名是误导人啊。Re: yang3wei昨天 10:17回复gaoyp额,还可以那样么,呵呵,我也是摸索阶段啊,多谢指点!

    
最新技术文章:
▪Android开发之注册登录方法示例 iis7站长之家
▪Android开发之注册登录方法示例
▪Android获取手机SIM卡运营商信息的方法
▪Android实现将已发送的短信写入短信数据库的...
▪Android发送短信功能代码
▪Android根据电话号码获得联系人头像实例代码
▪Android中GPS定位的用法实例
▪Android实现退出时关闭所有Activity的方法
▪Android实现文件的分割和组装
▪Android录音应用实例教程
▪Android双击返回键退出程序的实现方法
▪Android实现侦听电池状态显示、电量及充电动...
▪Android获取当前已连接的wifi信号强度的方法
▪Android实现动态显示或隐藏密码输入框的内容
▪根据USER-AGENT判断手机类型并跳转到相应的app...
▪Android Touch事件分发过程详解
▪Android中实现为TextView添加多个可点击的文本
▪Android程序设计之AIDL实例详解
▪Android显式启动与隐式启动Activity的区别介绍
▪Android按钮单击事件的四种常用写法总结
▪Android消息处理机制Looper和Handler详解
▪Android实现Back功能代码片段总结
▪Android实用的代码片段 常用代码总结
▪Android实现弹出键盘的方法
▪Android中通过view方式获取当前Activity的屏幕截...
▪Android提高之自定义Menu(TabMenu)实现方法
▪Android提高之多方向抽屉实现方法
▪Android提高之MediaPlayer播放网络音频的实现方法...
▪Android提高之MediaPlayer播放网络视频的实现方法...
▪Android提高之手游转电视游戏的模拟操控
 


站内导航:


特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

©2012-2021,,E-mail:www_#163.com(请将#改为@)

浙ICP备11055608号-3