西昌.何雨锋 粒子系统
ravity(重力) bounce反弹 generator(创始人) blend(混合)
[setSetEmittorMoveMode(常量); CONST_TV_EMITTORMOVEMODE 常量为: TV_EMITTOR_LERP = 0 TV_EMITTOR_NOLERP = 1
设置辐射移动模式:有/无]
[SetNewParticleData(发散x,发散y,发散z,颜色R,颜色B,颜色C,生命周期,纹理图)
用于实时改变粒子系统的参数],这里的函数VScale,VNormalize都是global的函数
V = gloabal1->VScale(global1->VNormalize(&Vector(Rnd * 2 - 1, Rnd * 4 + 2, Rnd * 2 - 1)), CurrentPower)
[
par1->UpdateParticles(常量CONST_TV_PARTICLEUPDATE)
常量CONST_TV_PARTICLEUPDATE:
TV_UPDATE_ACTIVE = 0 Update only active particles
TV_UPDATE_NON_ACTIVE = 1 Update only non-active particles
TV_UPDATE_BOTH = 2 Updates non-active and active particle.
TV_UPDATE_GENERATOR = 4 Generates new particle when needed.
TV_UPDATE_RANDOM_GENERATOR = 8 随机起点.
TV_UPDATE_FOLLOW_LANDSCAPE = 16 Particles must follow the terrain (altitude)
TV_UPDATE_BOUNCE_ON_LANDSCAPE = 32 在陆地高度将反弹
TV_UPDATE_BOUNCE_ON_Y0_PLANE = 64 在Y=0的零高度将反弹
TV_UPDATE_BOUNCE_ON_CUSTOM_PLANE = 128 particles Must bounce on a custom defined plane
]
ITVParticleSystem par1;
par1=CreateTVParticleSystem();
par1->CreateBillboardSystem(1000,0,5,&pos1,3000,global1->GetTex("water1"));
//pos1是D3DVECTOR,在读取粒子图的时候,记得用参数TV_COLORKEY_BLACK,这样读出的粒子图才不是方的。
par1->SetGravity(3,0.5); //设置重力和反弹强度
par1->SetGeneratorSpeed(10); //设置初始速度
par1->ParticleSize=3; //设置粒子大小
//以上三项是可以直接调整的。
//记得渲染
par1->UpdateParticles(TV_UPDATE_BOUNCE_ON_LANDSCAPE);
par1->RenderParticles();
//end
以下问题是没搞懂的:1、在很多par1的set函数中有long particle的参数,不知道从哪个类里能得到这个,所以很多set函数根本用不起。
2、如何让par1分开和有方向。
以下问题基本清楚:
1、par1->UpdateParticles(TV_UPDATE_BOUNCE_ON_LANDSCAPE);
是用来说明当粒子碰到land时会反弹,如果改成FLOOR参数则碰到地板会反弹。
2、par1->CreateBillboardSystem(粒子数量,起数,结束数,&Vector,范围?,long型的图片)
3、可以用puase与stop函数控制其是否暂停。
4、可以用moveEmittor(&pos)将其移动到另一个地方。
5、可以用SetParticleTexture(纹理)来改变纹理。
6、GetActiveParticlesNumber()好象是返回粒子的总浈数,然后可以用循环得到 某一贞,然后就可以用那些set来设置每一贞所体现不同的效果了?
创建粒子有很多种方法:
一、最简单的方法:只定义粒子本身,然后用自动生成功能产生简单的粒子。
par1->CreateBillboardSystem(153,0,3,&par_pos,0,global1->GetTex("par1"));
par1->SetAlphaBlendingMode(TV_CHANGE_ALPHA,(TrueVision3D::CONST_D3DBLEND) D3DBLEND_SRCALPHA,(TrueVision3D::CONST_D3DBLEND) D3DBLEND_ONE);
par1->SetParticleAutoGenerateMode(tvtrue,0.4,0.4,0.4,0.4,0.8,0,0.1,0,0.01,0.01,0.01);
par1->ParticleSize=28; //大小
par1->SetGeneratorSpeed(21); //粒子产生速度
par1->SetParticleSpeed(0.2); //粒子运动速度*/
这样产生的粒子可以控制简单的分岔功能,但是无法控制粒子飞出的方向和飞行轨迹。
二、使用轨迹系统来编辑粒子的轨迹:
D3DVECTOR tmpVel;
tmpVel.x = rand()* 2 - 1;
tmpVel.y = rand()* 4 + 2;
tmpVel.z = rand()* 2 - 1;
tmpVel =global1->VScale(global1->VNormalize(&tmpVel),1.4);
par1->MoveEmittor(&Pos1); //这个是控制整个粒子产生器的位置的,一般随着物体运动
par1->SetParticleAutoGenerateMode(tvtrue,0.4,0.4,0.4,0.4,0.8,tmpVel.x,tmpVel.y,tmpVel.z,0.01,0.01,0.01); //这里是控制粒子产生器产生出粒子的形状的
这样编辑出的粒子不但可以控制轨迹(由pos1控制),而且可以控制粒子群的变化和形状(由tempvel控制)。
par1->SetParticleAutoGenerateMode(enable,红,绿,蓝,A,粒子生命周期,粒子微器的x,粒子微器的y,粒子微器的z,随机因子x,随机因子y,随机因子z);
注意,这部分将被加到循环中,这样才能产生出烟花般的粒子系统,其中粒子微器坐标可以自己用公式计算,也可以使用TV自带的
粒子编辑器中的运算代码,然后通过此代码算出粒子微器坐标,这样就产生了同粒子编辑器相同的粒子群了。
三、使用两个点:位置点与方向点,可以控制出有方向的粒子系统。
myPos = new DxVBLibA::D3DVECTOR;
myPos->x = 1;
myPos->z = 1;
myPos->y = 1;
myDir = new DxVBLibA::D3DVECTOR;
myDir->x = 1;
myDir->z = 1;
myDir->y = 1;
myParticleSystem->CreateBillboardSystem(1000, 1, 3.0, myPos, 3.0, pGlobals->GetTex("ParticleTexture"));
myParticleSystem->CreateSystemFromPreset(TV_PARTICLE_EXPLOSIONUP, 1000, myPos, myDir, pGlobals->GetTex("ParticleTexture"), -1);
render中://这里忽略了编辑粒子轨迹的过程
myParticleSystem->UpdateParticles(TV_UPDATE_BOTH);
myParticleSystem->RenderPreset();
----------------------------------------我
用0键来实现了一键让粒子到或出现在某个方向
if(input1->IsKeyPressed(TV_KEY_0))
{
int kk;
int i,j;
kk=par1->GetActiveParticlesNumber();
for(i=1;i<=kk-1;i++)
{
j=par1->GetParticleKey(i);
par1->SetParticlePosition(&posb,i);
par1->SetParticleDirection(&posb,i);
}
--------------------------------------------------------------------------------
粒子的代码:外
With My_Particle1
.CreateBillboardSystem 543, 0, 3, Vector3(0,0,0), 0, GetTex("My_Texture1")
.ParticleSize = 14
.SetAlphaBlendingMode TV_CHANGE_ALPHA, D3DBLEND_SRCALPHA, D3DBLEND_ONE
.SetGravity 2, .4
.SetGeneratorSpeed 7
.SetParticleSpeed .01
End With
'Event Code for My_Particle1 :
LifeTime = 3.1
Dim tmpVel as D3DVECTOR
tmpVel.x = Rnd * 2 - 1
tmpVel.y = Rnd * 4 + 2
tmpVel.z = Rnd * 2 - 1
tmpVel = VScale(VNormalize(tmpVel), 1.4)
VelocX = tmpVel.x
VelocY = tmpVel.y
VelocZ = tmpVel.z
Dim tmpPos As Integer
Dim vNewPosition As D3DVECTOR
tmpPos = (TV.TickCount * .52) Mod 360
vNewPosition.x = Sin(Deg2Rad(tmpPos)) * 0 + 0
vNewPosition.y = Sin(Deg2Rad(tmpPos)) * 1 + 0
vNewPosition.z = Cos(Deg2Rad(tmpPos)) * 0 + 0
My_Particle1.MoveEmittor vNewPosition
ColorR = 1.568628E-02
ColorG = .2509804
ColorB = .7176471
ColorA = 1
My_Particle1.UpdateParticles TV_UPDATE_BOUNCE_ON_Y0_PLANE Or TV_UPDATE_GENERATOR
My_Particle1.RenderParticles
--------------------------
外
/********************************************************
* Copyright (C) Truevision3D LLC. *
* File: Tutorial 1.cpp *
* Description: TrueVision3D Tutorial 1 *
* Written By: MadProgrammer *
********************************************************/
#include "stdafx.h"
#include "../tv3dcpp.h"
//Setup TrueVision3D
ITVEngine pEngine;
ITVInputEngine pInput;
ITVScene pScene;
ITVMesh myMesh;
ITVGlobals pGlobals;
ITVParticleSystem myParticleSystem;
void render();
void input();
void unload();
DxVBLibA::D3DVECTOR* myPos;
DxVBLibA::D3DVECTOR* myDir;
LRESULT CALLBACK WndProc(HWND wpHWnd, UINT msg, WPARAM wParam, LPARAM lParam);
float fAngle = 0;
float fTimeElapsed = 0;
//WinMain: The entry point to everything Windows
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
HWND WindowHandle;
// HINSTANCE hInst;
WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, WndProc, 0L, 0L,
GetModuleHandle(NULL), NULL, NULL, NULL, NULL,
"MyParticles", NULL };
RegisterClassEx(&wc);
WindowHandle = CreateWindow( "MyParticles", "Small System",
WS_OVERLAPPEDWINDOW, 100, 100, 640, 480,
GetDesktopWindow(), NULL, wc.hInstance, NULL );
// there is a problem creating the window
if (WindowHandle == NULL)
{
MessageBox(NULL, "Unable to Create a Window", "Error", MB_OK);
return false;
}
ShowWindow (WindowHandle, 1);
UpdateWindow (WindowHandle);
SetFocus (WindowHandle);
ShowCursor (TRUE);
//Initialze COM
CoInitialize(NULL);
pEngine = CreateTVEngine();
//Engine Running boolean
double Gamma = 0.0;
MSG msg;
msg.message = WM_NULL;
//Set the debug file before doing anything else
pEngine->SetDebugFile ("c://debug.txt");
//Initialize Windowed
pEngine->Init3DWindowedMode ((long)WindowHandle, true);
//Tell it to display the FPS
pEngine->put_DisplayFPS(tvtrue);
//Init input after main init
pInput = CreateTVInputEngine();
//AppPath is a small Macro function in tv3dcpp lib to return the path
//of a file you pass to it, in this case we get the application path
char path[256];
char srchpath[256];
HMODULE Module = (HMODULE)hInstance;
GetModuleFileName(Module,path,255);
AppPath(path,srchpath);
//Set the search directory of the objects, textures, ...
pEngine->SetSearchDirectory(srchpath);
//We set the AngleSystem to Degrees
pEngine->SetAngleSystem (TV_ANGLE_DEGREE);
//Init input after main init, and check if it errors anywhere.
pInput = CreateTVInputEngine();
pScene = CreateTVScene();
pGlobals = CreateTVGlobals();
long LoadTexRet;
LoadTexRet=pScene->LoadTexture ("..//..//..//Media//texture.bmp", -1, -1, "ParticleTexture");
if(LoadTexRet==0)
MessageBox(NULL, "The Texture did not load properly", "Error", MB_OK);
// Create System
myPos = new DxVBLibA::D3DVECTOR;
myPos->x = 1;
myPos->z = 1;
myPos->y = 1;
myDir = new DxVBLibA::D3DVECTOR;
myDir->x = 1;
myDir->z = 1;
myDir->y = 1;
myParticleSystem->CreateBillboardSystem(1000, 1, 3.0, myPos, 3.0, pGlobals->GetTex("ParticleTexture"));
myParticleSystem->CreateSystemFromPreset(TV_PARTICLE_EXPLOSIONUP, 1000, myPos, myDir, pGlobals->GetTex("ParticleTexture"), -1);
/* CreateSystemFromPreset( Preset As CONST_TV_PARTICLE_PRESET, NumParticles As Integer,
Position As D3DVECTOR, Direction As D3DVECTOR, Texture As Long, Color As Long)
*/
/* TVParticleSystem.CreateBillboardSystem( ParticleCount As Integer, ParticleStart As Integer,
SquareSize As Single, Position As D3DVECTOR, Radius As Single, Texture As Long)
*/
//Main loop
while( msg.message!=WM_QUIT)
{
if(PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
else
{
render();
input();
}
}
//Uninitialize the variables
pInput->Release ();
pInput = NULL;
pEngine->Release ();
pEngine = NULL;
//Uninitialize COM
CoUninitialize();
//Exit sucessfully
return 0;
}
//Render sub
void render()
{
pEngine->Clear(false); //Clear the screen
//myParticleSystem->UpdateParticles(TV_UPDATE_BOTH);
//myParticleSystem->RenderParticles();
myParticleSystem->UpdateParticles(TV_UPDATE_BOTH);
myParticleSystem->RenderPreset();
pEngine->RenderToScreen (); //Render the screen
}
//Input sub
void input()
{
if(pInput->IsKeyPressed(TV_KEY_ESCAPE)) //Check if ESCAPE has been pressed.
{
PostQuitMessage(0);
}
}
LRESULT CALLBACK WndProc(HWND wpHWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
} break;
default:break;
}
return DefWindowProc(wpHWnd, msg, wParam, lParam);
}
-------------------------------------外
下面的是使用long的粒子来更改每一贞。
Private Sub Particle_Do()
facex = Math.Sin(Facing)
facez = Math.Cos(Facing)
particlenumber = particle.GetActiveParticlesNumber()
Dim i As Integer
For i = 0 To particlenumber-1
key = particle.GetParticleKey(i)
vector.x = ship.GetPosition.x - (180 * facex * (key + 0.1))
vector.z = ship.GetPosition.z - (180 * facez * (key + 0.1))
vector.y = -3
particle.SetParticlePosition(vector, i)
Next i
particle.UpdateParticles()
particle.RenderParticles()
End Sub
---------------------------------------外
下面是C#的让粒子随路径行动的例子
Particle follow Path
First we need a Path:
PPath := TTVPath.Create(nil);
PPath.SetPathType(TV_PATH_LINEAR);
We add some Nodes:
PPath.AddNode(100,1000,100);
PPath.AddNode(2500,500,2500);
PPath.AddNode(0,100,2500);
PPath.AddNode(500,1000,3000);
PPath.AddNode(2500,100,3500);
PPath.AddNode(3500,2000,4000);
PPath.AddNode(3500,100,900);
PPath.AddNode(5000,1500,0);
Then we need a Particle System:
FParti := TTVParticleSystem.Create(NIL);
FParti.OnNewParticle := NewParticle; // OnNewParticle Event … see SDK
And :
type
TRelPos = Record
RelX : Single;
RelY : Single;
RelZ : Single;
Posi : Single;
end;
RelPos : Array of TRelPos; //Dynamic Array
The Event :
FParti .NewParticle(ASender : TObject; Var VelocX, VelocY, VelocZ, ColorR, ColorG,
ColorB, ColorA, LifeTime: Single; Var TextureIndex : Integer);
Begin
TextureIndex := Global. GetTex(‘particletexture’)
ColorR := 1;
ColorG := 1;
ColorB := 1;
ColorA := 1;
LifeTime := 30;
// VelocX .. Z is not needed because we move our Particles ‘manually’
End ;
Now we need a Startup Procedure for the Random Positions of the Particles.
Procedure StartUp;
Var I : Integer;
Begin
Randomize;
SetLength(RelPos, ParticleCount); //wahtever your count is ..
for i := 0 to length(RelPos)-1 do
begin
RelPos[i].RelX := RandomRange(100, -100); // so you have a cube where the Particles be ‘borne’
RelPos[i].RelY := RandomRange(100, -100);
RelPos[i].RelZ := RandomRange(100, -100);
RelPos[i].Posi := 1; // its the first Node … if you set 0 the Particle Starts at the last Node .. test it
end;
End;
The Follow Path Procedure called in the render Loop:
procedure TParticles.follow;
var i : Integer; RandPos : _D3DVECTOR;
begin
for i := 0 to ParticleCount do
begin
RandPos.x := PPath.GetSplinePoint(RelPos[i].Posi).x + RelPos[i].RelX; // now we get the Position of a SplinePoint on the Path
RandPos.y := PPath.GetSplinePoint(RelPos[i].Posi).y + RelPos[i].RelY; // and add the relative Positions
RandPos.z := PPath.GetSplinePoint(RelPos[i].Posi).z + RelPos[i].RelZ;
FParti.SetParticlePosition(RandPos, i+1); // Set The Position of each Particle.
RelPos[i].Posi := RelPos[i].Posi + 0.01; // 0.01 means the Speed if you set to 1 .. it’s the next Node
if RelPos[i].Posi >= PPath.GetNodeCount then RelPos[i].Posi := 1; // if the last Node reached .. we start at 1
end;
end;
You should set the LifeTime > 0, the EmmetorSpeed := 50 (play wit it ) )
---------------------------------------------------外
看来那个long particle只是一个粒子了
for ParticleIndex= 1 to 32000
ParticleEngine.SetParticlePosition (vector3(Xpos, Ypos, Zpos), ParticleIndex)
ParticleEngine.SetParticleLifeTime(lifetime, ParticleIndex)
ParticleEngine.SetParticleDirection(Vector3(Xdir, Ydir, Zdir), ParticleIndex)
ParticleEngine.SetParticleColor(red, geewn, blue, alpha, ParticleIndex)
next ParticleIndex