lava flow along texture

Hi everyone

I hope someone can help me work out this issue for an educational project.
I have a model of a volcano, which has been textured. I can add a particle system to represent the smoke coming from the top. What I would like to do is to add lava to the slopes, according to the texture map. So, I create a new map and make it black and white. Lava = black. I would like for my lava particles appear only where there are black areas on the texture. I have found some code on the forum that can convert texture to particles, but from what I can tell it only does it as a flat image. I need it to follow the texture map on the model, in 3d. How could I adapt this code? I also don’t need it to animate, but would like for the particles to glow, so they only appear to be moving.

using UnityEngine;
using System.Collections;

public class ParticleShape : MonoBehaviour
{
	public Texture2D shapeTexture;
	public Vector3 scale = new Vector3(10, 10, 10);

	private Vector3[] posEnd;

	// initialize
	void Start()
	{
		// store the end positions (one position for each particle we'll be spawning)
		posEnd = new Vector3[CountOpaquePixels(shapeTexture)];
		
		// keep track of which particle we're on
		int i = 0;
		
		// texture aspect ratio
		float aspect = shapeTexture.width / shapeTexture.height;

		// loop through each pixel in our texture
		for (int x = 0; x < shapeTexture.width; x++)
		{
			for (int y = 0; y < shapeTexture.height; y++)
			{
				Color testColor = shapeTexture.GetPixel(x, y);
			
				// only emit if we're opaque
				if (testColor.a > 0)
				{
					// emit a particle (random initial position and velocity, use our pixel color, the two f numbers are particle size and how long they live)
					particleEmitter.Emit(Random.insideUnitSphere * 1, Random.insideUnitSphere * 1, 0.5f, 100f, testColor);

					// record the end position (standardized to 0-1 position)
posEnd[i] = new Vector3(0, (float)y / shapeTexture.height - 0.5f, ((float)x / shapeTexture.width - 0.5f) * aspect);

					// scale according to user setting
					posEnd[i].Scale(scale);

					// increment our particle counter
					i++;
					
				}
			}
		}

		// start our actual loop
		StartCoroutine("SnapToPosition");
	}

	// in this example it just loops--but it demonstrates the idea!
	IEnumerator SnapToPosition()
	{
		while (true)
		{
			// wait a bit
			yield return new WaitForSeconds(0.0f);

			// keep track of time and position (in a real script should make public variables) first number is how long we wait to show particles (if this number is larger than the seccond, then particles just appear), second number is how long it takes for the particles to get to their end state.
			float timeElapsed = 1;
			float timeLength = 0.5f;
			float pos;

			// hold the start/end position in these arrays
			int length = particleEmitter.particles.Length;
			Vector3[] posStart = new Vector3[length];

			// set up the start of our cycle (start position)
			Particle[] particles = particleEmitter.particles;
			for (int i = 0; i < particles.Length; i++)
			{
				// start position
				posStart[i] = particles[i].position;
				
				// stop our particles from moving
				particles[i].velocity = Vector3.zero;
			}

			// loop for our collapse animation
			bool go = true;
			while (go)
			{
				// how far into our cycle
				pos = timeElapsed / timeLength;

				// we're using a boolean to do one last iteration with pos=1
				if (pos >= 1.0f)
				{
					go = false;
					pos = 1;
				}

				// loop all of our particles and update positions
				particles = particleEmitter.particles;
				for (int i = 0; i < particles.Length; i++)
				{
					particles[i].position = Vector3.Lerp(posStart[i], posEnd[i], pos);
					particles[i].velocity = Vector3.zero;
				}
				particleEmitter.particles = particles;

				// wait a frame
				yield return 0;

			}
			particleEmitter.particles = particles;
		}
	}

	// count the number of non-transparent pixels in a texture
	int CountOpaquePixels(Texture2D texture)
	{
		int count = 0;
		for (int x = 0; x < texture.width; x++)
			for (int y = 0; y < texture.height; y++)
				if (texture.GetPixel(x, y).a > 0)
					count++;

		return count;
		
	}
}

i’m sorry, this is a classical case of “i found something, make it work for me please”. If you’re lucky somebody will help you, however, chances are that people are gonna be too lazy to read through all that code to help you out. Generally speaking, I think that people are willing to help you LEARN how to code, not code for them. In short, unless somebody generous comes by, you’re more likely better off reading the code yourself :slight_smile:

Zigs

I have read the code myself and have tinkered with it so it doesn’t animate. However it’s not quite doing what I want. I am very willing to learn and don’t want anyone to code the whole thing for me, just to point me in the right direction.

You’ve already been generous enough to take time to respond to my post… I only wish you took the time out to be a little more positive and helpful too. If you don’t want to be either helpful or positive then don’t respond.

I’m not trying to negative, sorry if it sounds that way. I just figured that I’d rather respond than moving on, leaving your post to die… I had a look at the code before, and it’s pretty huge + I’m not exactly very experinced with emitters and particles. My only guess is that you have to either rotate the particles towards the camara or check some boolean variable that says something about always facing the cam. Other than that I’m clueless.

Thanks Zigs

Sorry, I didn’t mean to be abrasive. Just would like some help, thats all. Seems like this should be doable, but I really don’t know where to start.

Cheers

Would it be possible to have a second (invisible?) mesh to mark the lava areas and use that for the mesh particle emitter?

Hi Andeee

Thanks for the suggestion, but although that is a good workaround I would like to position the particles via texture coordinates, because the texture may change. Also would be a lot simpler to change a texture rather than an object + the code above takes the color of the texture and applies it to particles which is something that I need.

It seems to me that the code above sets particles x and y position according to the pixel position (if it is opaque). I would like to also give the particles a z position according to the height where they appear on the model.

I had a look at terrain.SampleHeight(transform.position); but as my volcano is not a terrain but an object, I don’t know how to implement that.

Thanks