Hold Your Hats, Some Cool Lightning Need Container Help.?

Started by
0 comments, last by ankhd 9 years, 8 months ago

Hi all.

I found a cool site that has Lightning here.

Now I'm stuck on what storage type to use, list or vector or other.????

What I have done is create a queue but it does not rap back to the start gets to the last element and I call it full.
//this is working but it fills off.

What would you all do.?????

How should I structure this code or what way would any of the Dev Team go about it.?????

All that being said I'm doinging it on the GPU Shader 4 with streamout this buffer holds all the points. and I have a c++ one I made
the same way I'll post the data type so you can see what I'm going on about.

Here Is what It looks like CPU Generated ones on the left side, GPU to the Right Notice the short one. I changed the splitend rule and it blows short still ok.

CoolLightning.jpg?psid=1

//this is the shader version(Don't laugh too hard when you see my code)



#define SEGMENT_TYPE_BRANCH	0
#define SEGMENT_TYPE_SPLITEND	1

#define MAXARRAY  200
//to build our lightning we need to have a list for start points and end points
static float3 StartPoints[MAXARRAY];
static float3 EndPoints[MAXARRAY];
static float2 GenerationSize[MAXARRAY];//we now make the splits smaller
static uint	SegmentType[MAXARRAY];
static float Incert = 0.0;//start empty
static float Pop = 0.0;//allows us to remove the head element



//---------------------------------------------------------
//this function allows usto add to the above lists
//---------------------------------------------------------
void AddSegment(float3 start, float3 end, float2 size, uint type)
{
	float temp = Incert + 1.0;
	if(temp >= MAXARRAY)
		return;//full

	

	//add our points
	StartPoints[Incert]		= start;
	EndPoints[Incert]		= end;
	GenerationSize[Incert]	= size;
	SegmentType[Incert]		= type;

	Incert = temp;
}//end AddSegment
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////




//---------------------------------------------------------
//this function allows usto pop the head off
//---------------------------------------------------------
void PopSegment(void)
{

	if(Pop == Incert)
		return;//empty

	

	Pop++;//move through the list
	if(Pop >= MAXARRAY)
	{
		Pop = 0.0;//go back to the start
	}

	
}//end PopSegment
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////






//---------------------------------------------------------
//this function allows us to get the segmenttype
//---------------------------------------------------------
uint GetType(void)
{
	return SegmentType[Pop];

}//end GetType
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////









//---------------------------------------------------------
//this function allows usto get the menber call it before
//you pop the list
//returns the element
//---------------------------------------------------------
float3 GetStart(void)
{
	return StartPoints[Pop];

}//end GetStart
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////






//---------------------------------------------------------
//this function allows usto get the menber call it before
//you pop the list
//returns the element
//---------------------------------------------------------
float3 GetEnd(void)
{
	
	return EndPoints[Pop];

}//end  GetEnd
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////







//--------------------------------------------------------------
//gets the size
//--------------------------------------------------------------
float2 GetSize(void)
{
	return GenerationSize[Pop];
}//end GetSize
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////



//---------------------------------------------------------------
//returns the mid point between 2 points
//---------------------------------------------------------------
float3 Perpendicular(float3 direction)
{
	//float3 a = float3(0.0, 1.0, 0.0);
	
	//float3 rt = cross(a, v1);
	//return rt;

 // to be filled in
    float3 quasiPerp;// a direction which is "almost perpendicular"
    float3 result;// the computed perpendicular to be returned

    // three mutually perpendicular basis vectors
    float3 i = float3(1, 0, 0);
    float3 j = float3(0, 1, 0);
    float3 k = float3(0, 0, 1);

    // measure the projection of "direction" onto each of the axes
    float id = dot(i, direction);//i.dot (direction);
    float jd = dot(j, direction);//j.dot (direction);
    float kd = dot(k, direction);//k.dot (direction);

    // set quasiPerp to the basis which is least parallel to "direction"
    if ((id <= jd) && (id <= kd))
    {
        quasiPerp = i;               // projection onto i was the smallest
    }
    else
    {
        if ((jd <= id) && (jd <= kd))
            quasiPerp = j;           // projection onto j was the smallest
        else
            quasiPerp = k;           // projection onto k was the smallest
    }

    // return the cross product (direction x quasiPerp)
    // which is guaranteed to be perpendicular to both of them
   // result.cross (direction, quasiPerp);
	result = cross(direction, quasiPerp);
	return result;

}//end Perpendicular
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////







//---------------------------------------------------------------
//returns the mid point between 2 points
//---------------------------------------------------------------
float3 Average(float3 v1, float3 v2)
{//float3((v1.x + v2.x) /2, (v1.y + v2.y) /2, (v1.z + v2.z) /2);
	float3 a = (v1 + v2) * 0.5;
	return a;
}//end average
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////

Streamout GeometryShader.



struct Particle
{
	float3 initialPosW	: POSITION;
	float3 initialVelW	: VELOCITY;
	float3 pDirW		: PDIR;//partile direction
	float2 sizeW		: SIZE;
	float age			: AGE;
	uint type			: TYPE;
	uint arrayid		: ARRAYID;
};
  
Particle StreamOutVS(Particle vIn)
{
	return vIn;
}

//Im abusing my particle shader to make it lightning it does this once or when ever the particle system gets reset.
//GeometryShader does all the grunt work here.
//we can only return 72 particle structure it at max for the size of the particle Im not using all the values here but to keep it the same
//as the other particle shaders it is
// different.
//it says the shader model 4 can only have 64 but I think its the size of the data that cant go over 1024 mb
[maxvertexcount(72)]
void StreamOutGS(point Particle gIn[1], 
                 inout PointStream<Particle> ptStream)
{	
	gIn[0].age += gTimeStep;
	
	
			
	if( gIn[0].type == PT_EMITTER )
	{	
	
//reset the list 
Incert	= 0.0;
Pop		= 0.0;


	//we spawn once only we run the L-system to build our points
	float offsetamount = gSpawnNewParticalTime;//3900.0;//when the points are At great distance apart we need a larger value here
	float3 midpoint = 0;
	float generation = 5.0;
	float3 start = gEmitPosW.xyz;//start location
	float3 end = gEmitDirW.xyz;//end location
	float po;
	float inc;
	float lengthScale = gParticleSpreadAmount;//1500.7;//we reduce this each time we make a split
	float subsequentgeneration = 0.0;//when this gets to 2 we create a split end then we reset it
	
	float2 Fatness = float2(gParticleWidth, gParticleHeight);
	
	uint Type = SEGMENT_TYPE_BRANCH;

	//add our start locations to the list to start it off
	AddSegment(start,
				end,
				Fatness,//the size
				SEGMENT_TYPE_BRANCH);//

	[loop]
	for(float gen = 0.0; gen < generation; gen++)
	{
		inc = Incert;
		po = Pop;

		[loop]
		for(float segments = po; segments < inc; segments++)
		{
			//get the start and end
			start	= GetStart();
			end		= GetEnd();
			Fatness = GetSize();

subsequentgeneration++;
float3 direction = (start - end);
				//only if we are not to close
				if(length(direction) >= gGravity.x)//30)
				{
					//we can pop this node
					PopSegment();
			
					//ok we can get the midpoint
					midpoint = Average(start, end);

					// Offset the midpoint by a random amount along the normal.
					float3 vRandom = RandUnitVec3(gGameTime * gTimeStep);

					midpoint +=  Perpendicular(normalize(end-start)) * (vRandom *offsetamount);
		
					//add 2 segments that we just split
					AddSegment(start,
							midpoint,
							Fatness,
							SEGMENT_TYPE_BRANCH);
			
					AddSegment(midpoint,
								end,
								Fatness,
								SEGMENT_TYPE_BRANCH);


					
					//see if we want to add a split end this here will limmit the length if we run out of points
					float choice[4] = {3.0, 2.0,3.0, 1.0};
					uint index = gGameTime%4;
					if(subsequentgeneration >= choice[index])//2.0)
					{
						vRandom = RandUnitVec3(gGameTime * gTimeStep);//4.5);
						//add split end we create a rendom end point at some angle and length
						
				     
						//if(Type == SEGMENT_TYPE_BRANCH)//reset to the max lenght
						//	lengthScale = gParticleSpreadAmount;

						float3 direction = (midpoint - start);
						//only if we are not to close
						float sl = length(direction);
						if(sl >= gGravity.y)//6.0)
						{
							
						
							float3 newendpoint = midpoint;
				
							newendpoint += normalize(direction *clamp(length(vRandom), -20.0, 20.0))* sl;// lengthScale;


							//each split can offset at max half as much as the generation before
							lengthScale /= 2.0;
				
							//float l = length(Fatness * 0.5);
							//if(l <= 4.0)
							Fatness *= 0.5;
								
							float3 splitEnd = newendpoint; 
							AddSegment(midpoint, 
									splitEnd,
									Fatness,
									SEGMENT_TYPE_SPLITEND);
				
							
						}//end length
						
						subsequentgeneration = 0.0;//reset
					}//end subsequentgeneration

			}//end past the length of split

		}//end for segments
		
		offsetamount /= 2.0; //Each subsequent generation offsets at max half as much as the generation before


	}//end generation
	
	float numadded = 0.0;

	//ok from Pop to Incert should have our particle points
	for(float segments = Pop; segments < Incert; segments++)
	{
		//get the start and end
		start	= StartPoints[segments];
		end		= EndPoints[segments];

		Particle p;
		p.initialPosW   = start;
		p.initialVelW	= end;

		p.pDirW		  =	0;
		p.sizeW       = GenerationSize[segments];//float2(gParticleWidth, gParticleHeight);
		p.age         = 0.0f;//vRandom.x;
		p.type        = PT_FLARE;
		p.arrayid     = 0;
		
		//add new particle
		ptStream.Append(p);


		
				
	}//end all list points

	
		
	}
	else
	{
		
		// Specify conditions to keep particle; this may vary from system to system.
		if( gIn[0].age <=  gFlashspeed)//1000.0)
			ptStream.Append(gIn[0]);
		
			
	
	}		
}//end
///////////////////////////////////////////////////////////////////////////////////////////////////

and here is the c++ version



//defines for a branck and a splitends
#define SEGMENT_TYPE_BRANCH		0
#define SEGMENT_TYPE_SPLITEND	1
//#define SEGMENT_TYPE_







//----------------------------------------------------
//this holds data we need for the processing of the 
//lightning
//----------------------------------------------------
class cLightningSegment
{
public:

	//lightning we need to have a list for start points and end points
	D3DXVECTOR3 StartPoints;
	D3DXVECTOR3 EndPoints;
	D3DXVECTOR2 GenerationSize;//we now make the splits smaller
	UINT SegmentType;
	bool Valid;//if true we can use the locations

	cLightningSegment(void)
	{
		StartPoints		= D3DXVECTOR3(0.0, 0.0, 0.0);
		EndPoints		= D3DXVECTOR3(0.0, 0.0, 0.0);
		GenerationSize	= D3DXVECTOR2(10.0, 10.0);//we now make the splits smaller
		SegmentType		= SEGMENT_TYPE_BRANCH;
		Valid			= false;

	}//end
	/////////////////////////////////////////////////////////

	~cLightningSegment(void)
	{
	}//end
	///////////////////////////////////////////////////////////




	//------------------------------------------------------
	//sets all the elements
	//-------------------------------------------------------
	void AddLightningSegment(D3DXVECTOR3 &start, D3DXVECTOR3 &end, D3DXVECTOR2 &size, UINT type)
	{
		StartPoints		= start;
		EndPoints		= end;
		GenerationSize	= size;//we now make the splits smaller
		SegmentType		= type;
		Valid			= true;
	}



};//end class cLightningSegment
////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////











//-----------------------------------------------------------------------------
// File: LightningGenerator.cpp
//generates a list of lightning 3dpoints when ran depending on the generations
//it could get slow its the same as the lightning shader but we have more points we can use
//this works with my particle system to inject these points into its streamed out vertex buffer
//using some sort of L-System
//we now need to create a buffer for stagging so we can copy this to the particles systems gpu buffer
//-----------------------------------------------------------------------------
class cLightningGenerator
{
private:
	std::vector<cLightningSegment>::iterator segments;
	std::vector<cLightningSegment>::iterator Pop;
	std::vector<cLightningSegment>::iterator Incert;

	ID3D10Buffer *mInitVB;	
	DWORD AmountCopyedToBuffer;//we need to pass this info back with the buffer to who uses it
public:
	
	int NumberToCreate;//how many we create we dont go over this value

	//holds the points we add when done this will have all the locations to create good lightning
	//we will allocate for 400 and it can expand after that sould not need that many the shader gets by with 72
	//doing it the same way as the shader we move the to interators to suit
	std::vector<cLightningSegment> LightningSegments;


	

	cLightningGenerator(void);

	~cLightningGenerator(void);




	//----------------------------------------------------------------
	//we now have a int function
	//----------------------------------------------------------------
	bool LightningInitialize(ID3D10Device* md3dDevice, int amount);


	//-----------------------------------------------------------------------------------------
	//get the heads data before we pop this data
	//returns NULL if empty
	//------------------------------------------------------------------------------------------
	cLightningSegment *GetSegment(void)
	{
		if(LightningSegments.empty())
			return NULL;//error

		//we have members get the head data
		return &*Pop;
	}//end GetSegment
	////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	////////////////////////////////////////////////////////////////////////////////////////////////////////////////




	//-------------------------------------------------------------------------------------------------
	//this here will generate the points for the lightning each frame it will create a new build
	//-------------------------------------------------------------------------------------------------
	void CalculateLightning(D3DXVECTOR3 &EmitPosW, D3DXVECTOR3 &EmitDirW,
											 float width, float height,//size of the lightning
											 float deltatime,//the time delta
														float gametime);//the timer class





	//----------------------------------------------------------------------------------------------
	//this will return out buffer so we can copy this to the particle systems buffer
	//also has the number of vertex in this buffer
	//----------------------------------------------------------------------------------------------
	ID3D10Buffer *GetBuffer(DWORD *holdsthismany)
	{
		*holdsthismany = AmountCopyedToBuffer;
		return mInitVB;

	}//end GetBuffer
	//////////////////////////////////////////////////////////////////////////////////////////////////



private:

	//------------------------------------------------------
	//sets all the elements
	//-------------------------------------------------------
	void AddLightningSegment(D3DXVECTOR3 &start, D3DXVECTOR3 &end, D3DXVECTOR2 &size, UINT type);

 	//---------------------------------------------------------------
	//returns the mid point between 2 points
	//---------------------------------------------------------------
	D3DXVECTOR3 Average(D3DXVECTOR3 &v1, D3DXVECTOR3 &v2)
	{
		D3DXVECTOR3 a = (v1 + v2) * 0.5;
		return a;
	}//end average
	/////////////////////////////////////////////////////////////////////
	/////////////////////////////////////////////////////////////////////




	//---------------------------------------------------------
	//this function allows usto pop the head off
	//---------------------------------------------------------
	void PopSegment(void)
	{

		if(Pop == Incert)
			return;//empty

		

		Pop++;//move through the list
		if(Pop == LightningSegments.end())
		{
			Pop = LightningSegments.begin();//go back to the start
		}

		
	}//end PopSegment
	/////////////////////////////////////////////////////////////////////
	/////////////////////////////////////////////////////////////////////


};///end class cLightningGenerator
////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////

Cpp


cLightningGenerator::cLightningGenerator(void)
{
	mInitVB = NULL;

	AmountCopyedToBuffer = 0;
	
}//end
///////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////

cLightningGenerator::~cLightningGenerator(void)
{
	SAFE_RELEASE(mInitVB);


}//end
///////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////







//----------------------------------------------------------------
//we now have a int function
//----------------------------------------------------------------
bool cLightningGenerator::LightningInitialize(ID3D10Device* md3dDevice, int amount)
{
	//how many this can hold you will need to matck the particles
	NumberToCreate = amount;


	//we need a staging buffer so we can copy our data to thye particle systems gpu buffer
	D3D10_BUFFER_DESC vbd;
    vbd.Usage = D3D10_USAGE_STAGING;
    vbd.ByteWidth = sizeof(ParticleVertex);// * 1;
    vbd.BindFlags = 0;//D3D10_BIND_VERTEX_BUFFER;
    vbd.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
    vbd.MiscFlags = 0;

	
	//
	// Create the ping-pong buffers for stream-out and drawing.
	//
	vbd.ByteWidth = sizeof(ParticleVertex) * NumberToCreate;
   

	HRESULT hr = md3dDevice->CreateBuffer(&vbd, 0, &mInitVB);
	if(hr != S_OK)
	{
		OutPutDebugText("Failed LOAD buffer",//the message to display
			"cLightningGenerator::LightningInitialize()",//TCHAR *locmsg,//the location the message was called Eg. what function
					 true);

		return false;//error

	}



	return true;
}//end LightningInitialize
///////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////












//------------------------------------------------------
//sets all the elements
//-------------------------------------------------------
void cLightningGenerator::AddLightningSegment(D3DXVECTOR3 &start, D3DXVECTOR3 &end, D3DXVECTOR2 &size, UINT type)
{
	
	
	if(Incert == LightningSegments.end())
	{	
		Incert = LightningSegments.end();
		return;//full
	}
	
	cLightningSegment LightningSegment;

	LightningSegment.AddLightningSegment(start, end, size, type);


	*Incert = LightningSegment;

	Incert++;
	if(Incert == LightningSegments.end())
	{	
		Incert = LightningSegments.end();
		return;//full
	}

}//end AddLightningSegment
///////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////



















//-------------------------------------------------------------------------------------------------
//this here will generate the points for the lightning each frame it will create a new build
//-------------------------------------------------------------------------------------------------
void cLightningGenerator::CalculateLightning(D3DXVECTOR3 &EmitPosW, D3DXVECTOR3 &EmitDirW,
											 float width, float height,//size of the lightning
											 float deltatime,//the time delta
														float gametime)//the timer class
{
	if(mInitVB == NULL)
		return;//error failed

//	static bool once = false;
//	if(once)
//		return;//test only once

//	once = true;

	//clear it
	LightningSegments.resize(NumberToCreate,	cLightningSegment());
	

	//set the interrators
	Pop		= LightningSegments.begin();
	Incert	= LightningSegments.begin();

	float gGameTime = gametime;
	float gTimeStep = deltatime;
	//this code is the same as in the shader but we can hold more locations
	//we spawn once only we run the L-system to build our points
	float offsetamount = 3000.0;//3900.0;//gSpawnNewParticalTime;//when the points are At great distance apart we need a larger value here
	D3DXVECTOR3 midpoint;
	float generation = 5.0;
	D3DXVECTOR3 start	= EmitPosW;//start location
	D3DXVECTOR3 end		= EmitDirW;//end location
	std::vector<cLightningSegment>::iterator po;
	std::vector<cLightningSegment>::iterator inc;
	float lengthScale = 1000.0;//1500.7;//gParticleSpreadAmount;//we reduce this each time we make a split
	float subsequentgeneration = 0.0;//when this gets to 2 we create a split end then we reset it
	
	D3DXVECTOR2 Fatness = D3DXVECTOR2(width, height);
	
	UINT Type = SEGMENT_TYPE_BRANCH;

	//add our start locations to the list to start it off
	AddLightningSegment(start,
						end,
						Fatness,//the size
						SEGMENT_TYPE_BRANCH);//

	

	for(int gen = 0.0; gen < generation; gen++)
	{
		po = Pop;
		inc = Incert;
	
		for(segments = po; segments != inc; segments++)
		{
			//get the start and end
			cLightningSegment *seg = GetSegment();
			start	= seg->StartPoints;//GetStart();
			end		= seg->EndPoints;//GetEnd();
			Fatness = seg->GenerationSize;//GetSize();
			Type	= seg->SegmentType;

			subsequentgeneration++;
			D3DXVECTOR3 direction = (start - end);
			float l = D3DXVec3Length(&direction);
				//only if we are not to closelength(direction)
				//if(l >= 30)//gGravity.x)//30)
				{
					//we can pop this node
					PopSegment();
			
					//ok we can get the midpoint
					midpoint = Average(start, end);

					// Offset the midpoint by a random amount along the normal.
					//D3DXVECTOR3 vRandom;//RandUnitVec3();//(gGameTime * gTimeStep);
					
					D3DXVECTOR3 n = end-start;
					D3DXVec3Normalize(&n, &n);				//need a clamp here on the cpu version
					midpoint +=  findPerpendicularIn3d(n) * RandInRange(-offsetamount, offsetamount);//* ( Clamp<float>(gGameTime * gTimeStep, -30.0, 30.0) *offsetamount);
		
					

					//add 2 segments that we just split
					AddLightningSegment(start,
							midpoint,
							Fatness,
							SEGMENT_TYPE_BRANCH);
			
					AddLightningSegment(midpoint,
								end,
								Fatness,
								SEGMENT_TYPE_BRANCH);


					
					//see if we want to add a split end this here will limmit the length if we run out of points
					float choice[4] = {3.0, 2.0,3.0, 1.0};
					UINT index = rand()%4;
					if(subsequentgeneration >= choice[index])//2.0)
					{
						//vRandom = RandUnitVec3();//gGameTime * gTimeStep);//4.5);
						//add split end we create a rendom end point at some angle and length
						
				     
						//if(Type == SEGMENT_TYPE_BRANCH)//reset to the max lenght
						//	lengthScale = gParticleSpreadAmount;

						D3DXVECTOR3 direction = (midpoint - start);
						//only if we are not to close
						//float sl = length(direction);
						l = D3DXVec3Length(&direction);
						//if(l >= 10)//gGravity.y)//6.0)
						{
							
						
							D3DXVECTOR3 newendpoint = midpoint;
				
							float r = Clamp<float>(rand(), -lengthScale, lengthScale);//RandF(-lengthScale, lengthScale);//
							D3DXVECTOR3 n1 = (direction * r);//);
							D3DXVec3Normalize(&n1, &n1);

							newendpoint += n1* l;// lengthScale;


							//each split can offset at max half as much as the generation before
							lengthScale /= 2.0;
				
							
							//Fatness *= 0.5;
								
							D3DXVECTOR3 splitEnd = newendpoint; 
							AddLightningSegment(midpoint, 
									splitEnd,
									Fatness,
									SEGMENT_TYPE_SPLITEND);
				
							
						}//end length
						
						subsequentgeneration = 0.0;//reset
					}//end subsequentgeneration

			}//end past the length of split

		}//end for segments
		
		offsetamount /= 2.0; //Each subsequent generation offsets at max half as much as the generation before


	}//end generation
	

	

	//ok we want to lock our buffer
	ParticleVertex *particl = NULL;//our data type

	HRESULT hr = mInitVB->Map(D3D10_MAP_WRITE,//[in]   D3D10_MAP MapType,
					 D3D10_MAP_FLAG_DO_NOT_WAIT,//[in]   UINT MapFlags,
					(void**)&particl);//[out]  void **ppData

	if(hr != S_OK)
		return;//could be bizzy


	//ok we can copy our data here but we can only copy mMaxParticles but
	int numbertocopy = NumberToCreate;

	if(LightningSegments.size() < numbertocopy)
		numbertocopy = LightningSegments.size();


	//reset so we can draw the correct amount later
	AmountCopyedToBuffer = 0;
	
	for(inc = Pop; inc != Incert; inc++)
	{
		if(inc->Valid)
		{
			//fill in the buffers data
			particl[AmountCopyedToBuffer].Pos		= inc->StartPoints;//in the shader is initialPosW
			particl[AmountCopyedToBuffer].Velocity	= inc->EndPoints;//in the shader is initialVelW
			particl[AmountCopyedToBuffer].Size		= inc->GenerationSize;
			particl[AmountCopyedToBuffer].Type		= inc->SegmentType;
			
			AmountCopyedToBuffer++;//increase our count of data added

			if(AmountCopyedToBuffer >= NumberToCreate)
			{
				//we are at max vertex buffer stop set flag and quit
				AmountCopyedToBuffer = NumberToCreate -1;

				//unmap the buffer
				mInitVB->Unmap();

				return;//done
			}
		}

		//particl[ctr].Velocity;not used for lightning
		//particl[ctr].Age;
		//particl[ctr].ArrayID;
	}//end all data

	//unmap the buffer
	mInitVB->Unmap();



}//end CalculateLightning
///////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////
Advertisement

Hi again.

I've updated some code, I've added a rotate function and the draw gs to out put real cubes based on a direction and size of the lightning segment.

the rotate function in hlsl


//------------------------------------------------------------------
//this will rotate the point passed in and return the rotated point
//pass in x y and z rotaion angles in  radians
//---------------------------------------------------------------------
float3 Rotate(float3 v1, float rotx, float roty, float rotz)
{
	float4x4 rotateX = { 1.0, 0.0, 0.0, 0.0,                
						0.0, cos(rotx), -sin(rotx), 0.0,                
						0.0, sin(rotx), cos(rotx), 0.0,                
						0.0, 0.0, 0.0, 1.0 };

	float4x4 rotateY = { cos(roty), 0.0, sin(roty), 0.0,               
					0.0, 1.0, 0.0, 0.0,                
					-sin(roty), 0.0, cos(roty), 0.0,               
					 0.0, 0.0, 0.0, 1.0   };

	float4x4 rotateZ = { cos(rotz), -sin(rotz), 0.0, 0.0,                
					sin(rotz), cos(rotz), 0.0, 0.0,                
					0.0, 0.0, 1.0, 0.0,                
					0.0, 0.0, 0.0, 1.0   };

	float4x4 TransformationMatrix =    
	{   
		{1,0,0,0},   
		{0,1,0,0},   
		{0,0,1,0},   
		{v1.x,v1.y,v1.z,1}   
	};   



float4x4 final = mul(rotateX , rotateY);// * rotateZ * TransformationMatrix;

final = mul(final, rotateZ);

final = mul(final, TransformationMatrix);


float3 rt = float3(final[3].x, final[3].y, final[3].z);
return rt;


}//end Rotate
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////

and the new geometry shader that extrudes the shape based on the direction the lightning segment is.

I'm using the 4 points to create a quad, the code also has triangles. but im using the quads it out put is 24 compared to 36.

there is no change between the frame time doing it iether way.


//-----------------------------------------------------------------------------
//going to greate a face that faces the direction and then extrude it by its length
//------------------------------------------------------------------------------
// The draw GS just expandsa quad facing the direction post and target form
[maxvertexcount(24)]
void Draw2GS(point VS_OUT gIn[1], 
            inout TriangleStream<GS_OUT> triStream)
{	
	// do not draw emitter particles.
	//if( gIn[0].type != PT_EMITTER )
	{
float4x4 WVP = gViewProj;//mul(W, gViewProj);
		
		//
		// Compute 4 triangle strip vertices (quad) in local space.
		// The quad faces down the direction start and end form.
		//
	
//holds triangles for the 6 faces
		//float4 v[36];
	
		//we make this shape here sortof
		//      ____________
		//  4  /\  1 faces  \
		//    /  \___________\
		//    \  /   2       /
		//   3 \/___________/
	
		//we only can have 1 size ore we will ned to keep switch whats size is where
		//we have a start and a target position
		//gEmitDirW is a vector3 in 3d world coords and now a direction in this shader its a target
		//if its a SEGMENT_TYPE_SPLITEND the growamount is not added
		float addsize = ggrowamount;
		if(gIn[0].type == SEGMENT_TYPE_SPLITEND)
			addsize = ggrowamount * 0.5;//we don't want to add extra glow
		float wdthp		= gIn[0].sizeW.x + addsize;//gParticleWidth ;//starting points width 
		
		float3 target	= gIn[0].posT;//gEmitDirW;
		float3 pos		= gIn[0].posW;//gEmitPosW;
		
		
		
//the face vertex points defines our cube
//float3 p1, p2, p3, p4, p5, p6, p7, p8;
float3 vetexdata[8];


//we need to get the direction we are heading
float3 dir = normalize(target - pos);

//create a up vector
float3 up = Perpendicular(dir);//float3(0.0, 1.0, 0.0);//

float halfsize = wdthp * 0.5;

//add a bit to the length to reduce the join not being linked to the next segment
float extrudelength = length(target - pos) + halfsize;

// todo: handle case when (dir == up) done with the perpendicular
float3 o1 = normalize(cross(dir, up)) * halfsize;
float3 o2 = normalize(cross(o1, dir)) * halfsize;

//this is the first face of the cube starting at our position facing the direction we want to extrude in
vetexdata[0] = pos + o1 + o2;
vetexdata[1] = pos + o1 - o2;
vetexdata[2] = pos - o1 - o2;
vetexdata[3] = pos - o1 + o2;

//the second face at the target location
vetexdata[4] = vetexdata[0] + dir* extrudelength;
vetexdata[5] = vetexdata[1] + dir* extrudelength;
vetexdata[6] = vetexdata[2] + dir* extrudelength;
vetexdata[7] = vetexdata[3] + dir* extrudelength;


//the above defines our cubes face vertices now we need to lay them out
//to form eighter the 4 faces with no end caps or the whole cube with end caps

//the easyest way I think is to make a index list with 3 index for a triangle
/*
static int indices[36]={
        // Front face
        0,1,2,
        0,2,3,
        // Back face
        4,6,5,
        4,7,6,
        // Left face
        4,5,1,
        4,1,0,
        // Right face
        3,2,6,
        3,6,7,
        // Top face
        1,5,6,
        1,6,2,
        // Bottom face
        4,0,3,
        4,3,7,
};
*/

/*
static float4 c[6] =
{
float4(1,0,0,1),
float4(0,1,0,1),
float4(0,0,1,1),
float4(0.5,0.5,0,1),
float4(0,0.5,0.5,1),
float4(1,1,1,1),
};

*/

//cheaper not that its a frame hit any way they run the same
static int faces[24] = {

// Front edges
    3,//0,
	2,//1,
	0,//3,
	1,//2,
	

// Back edges
    4,//4,
	5,//5,
	7,//6,
	6,//7,

// Left edges
    0,//4,
	1,//5,
	4,//1,
	5,//0,

// Right edges
    7,//3,
	6,//2,
	3,//6,
	2,//7,

// Top edges
    6,//1,
	5,//5,
	2,//6,
	1,//2,

// Bottom edges
    4,//4,
	7,//0,
	0,//3,
	3,//7,
};
 /*
// Front face		
		//make a quad from pos to face target
		v[0] = float4(vetexdata[0], 1.0f);
		v[1] = float4(vetexdata[1], 1.0f);
		v[2] = float4(vetexdata[2], 1.0f);

		v[3] = float4(vetexdata[0], 1.0f);
		v[4] = float4(vetexdata[2], 1.0f);
		v[5] = float4(vetexdata[3], 1.0f);

//bottom
		v[6] = float4(vetexdata[4], 1.0f);
		v[7] = float4(vetexdata[0], 1.0f);
		v[8] = float4(vetexdata[3], 1.0f);

		v[9] = float4(vetexdata[4], 1.0f);
		v[10] = float4(vetexdata[3], 1.0f);
		v[11] = float4(vetexdata[7], 1.0f);


//left face 
		v[12] = float4(vetexdata[4], 1.0f);
		v[13] = float4(vetexdata[5], 1.0f);
		v[14] = float4(vetexdata[1], 1.0f);

		v[15] = float4(vetexdata[4], 1.0f);
		v[16] = float4(vetexdata[1], 1.0f);
		v[17] = float4(vetexdata[0], 1.0f);


 // Back face
      
		v[18] = float4(vetexdata[4], 1.0f);
		v[19] = float4(vetexdata[6], 1.0f);
		v[20] = float4(vetexdata[5], 1.0f);

		v[21] = float4(vetexdata[4], 1.0f);
		v[22] = float4(vetexdata[7], 1.0f);
		v[23] = float4(vetexdata[6], 1.0f);

 // Right face
       
		v[24] = float4(vetexdata[3], 1.0f);
		v[25] = float4(vetexdata[2], 1.0f);
		v[26] = float4(vetexdata[6], 1.0f);

		v[27] = float4(vetexdata[3], 1.0f);
		v[28] = float4(vetexdata[6], 1.0f);
		v[29] = float4(vetexdata[7], 1.0f);
		
 // Top face
      
		v[30] = float4(vetexdata[1], 1.0f);
		v[31] = float4(vetexdata[5], 1.0f);
		v[32] = float4(vetexdata[6], 1.0f);

		v[33] = float4(vetexdata[1], 1.0f);
		v[34] = float4(vetexdata[6], 1.0f);
		v[35] = float4(vetexdata[2], 1.0f);

*/
		//
		// Transform quad vertices to world space and output 
		// them as a triangle strip.
		//
		GS_OUT gOut;
//int colourele = 0;//1 colour each face
		int facecount = 0;//we resetstrip at 4 1 face
		[unroll]
		for(int i = 0; i < 24; i++)
		{
			gOut.posH  = mul(float4(vetexdata[faces[i]], 1.0f), WVP);//v[i], WVP);
			//gOut.texC  = float2(0.0, 0.0);//gQuadTexC[i];
			//gOut.color = c[colourele];//gIn[0].color;
			//gOut.arrayid = 0;//gIn[0].arrayid;

	triStream.Append(gOut);

		
		facecount++;
		if(facecount >=4)
		{
			//colourele++;
			//if(colourele >=6)
			//	colourele = 5;
			//1 face 
			facecount = 0;
			triStream.RestartStrip();
		}//end 1 quad
			
	

	
		}//end all

	}//en not emmitor
}//////////////////////////////////////////////////////////////////////////////////////////////////

This topic is closed to new replies.

Advertisement