I'm trying to make an "Explosion effect on a grid", and I need an algorithm that will allow me to do the following:
Note: The grid represents a List<List>, and I'm trying to filter out the red dots
So we start off with a given grid with black dots (in our case, black dots represent solid points on our grid, and red dots represent the points we remove from the list)
Eventually, our ractangle transformed into this random shape with holes on the edges (blue area)
My Attempt:
The Problem:
Sometimes the radius of my star/circle shape is pretty big and the output doesn't give me that "explosion" effect I'm looking for (basically, an unpredictable output), plus it really limits the shape.
Do you have any ideas or know of some mathematical algorithms that can help? Thanks for reading! :)
Sorry if I wasn't clear enough, but this is basically what I'm looking for:
This is straightforward approach to get template:
using System;
namespace ConsoleApp2
{
class Program
{
static void Main(string[] args)
{
int size = 10;
var grid = GetExplosionTemplate(size, new Random(),1);
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
{
Console.Write(grid[i + j * size] ? "X" : "O");
}
Console.WriteLine();
}
}
private static bool[] GetExplosionTemplate(int size, Random rnd = null, float explosionRoughness = 0)
{
var grid = new bool[size * size];
var rr = (size + 1) / 2f;
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
{
var cellId = i + j * size;
var r = Math.Sqrt(Math.Pow(i - size / 2, 2) + Math.Pow(j - size / 2, 2)) + rnd?.NextDouble()*explosionRoughness ?? 0;
grid[cellId] = r > rr;
}
}
return grid;
}
}
}
Roughness above 1 will give scattered inside explosion, below will give more round explosion. Value around 0.5 to 1.5 is great looking for both even/non-even values. You can play around to make it better looking, honestly for explosion physics I rather choose this roughness based on material in cell (sand penetration is better than stone, for example), cause you don't want fully fledged physics where you calculate explosion power traveling across weighted by resistance cells (for example, explosion in cave will travel along empty paths and slightly destruct environment, rather than create vacuum in radius)
Another simple approach to actually simulate explosion physics is to use recursion. You start at center with explosion power equal to some value, than as you travel wide, each cell will consume some part of that power (and may be destroyed in process), than equaly emits left part of its power to adjacent cells (even visited, so you simulate explosion wave). This way it will be more realistic in terms of materials. You can even simulate partially empty cell from resistance materials (like, iron fence, it is resistant but emits better and destroy everything around)
Related
This is not a duplicate of the Reingold-tolford, since that's just for drawing normal tree like structures. specifically I am looking for an algorithm where a node can link to a node thats not only on the level below it.
I'm building a tree like structure within a canvas control in WPF.
Currently I have a structure built like this(ignore the collisions of boxes I have that fixed) that generates automatically from my data.
While this structure isn't to bad, it'd be nice to work towards something with less collisions.
Therefore are there any algorithms I can follow and work with to draw a graph like this with less collisions.
I'm calculating all positions of the boxes like this currently,
flattenedList is a List < List< Object>> hence the i, j itteration. and that object has a treePosition Property with an X and Y double.
var canvasWidthFinder = new List<int>();
//Loop through all componentversions, use indexes to calc their positions.
for (int i = 0; i < flattenedList.Count; i++)
{
canvasWidthFinder.Add(flattenedList[i].Count);
for (int j = 0; j < flattenedList[i].Count; j++)
{
flattenedList[i][j].TreePosition.YPosition = (i * 150) + 25;
flattenedList[i][j].TreePosition.XPosition = ((Canvas.ActualWidth / (flattenedList[i].Count + 1)) * (j + 1)) - (125 / 2);
}
}
Canvas.Width = (canvasWidthFinder.Max() * 160);
These values are then used to draw borders with text inside and lines drawn between the connecting ones.
You could represent links that skip layers by creating dummy items in the intermediate layers. Then when you display the tree you could replace each dummy item with a vertical line instead of a block.
I am drawing on canvas based on device movement, I want to draw different characters in canvas based on mobile movement.
Currently its working, but I want to find time difference and i want to detect pause, pause means when user is not trying to draw and user is not moving mobile phone, so that Application ca assume that now user want to draw next character.
How to find pause in accelerometer values. Any logic? Also tell me how i can smooth accelerometer values, so that user can draw lines without noise.
I cannot help with the accelerator part, but for the noise in the data, here is one approach using Weighted Moving Average.
The basics are simple:
Find out how many points before current you want to use for smoothing
Calculate a weight based on length, f.ex. if length is 5 then the weight = 1+2+3+4+5 = 15
Iterate each data point starting from length of weight (you can start at 1 and cut the weighting short - below I'll demo the latter approach)
For point current - 5 multiply with 1/15, for current - 4 multiply with 2/15 and so forth. The sum is stored as value for this point, repeat for the next value points
Live demo
Below is a demo (enter full page to see all graphics). I wrote it in JavaScript so it could be shown live here in the answer. I think you should have little problem converting it into the language you're using (which is not stated).
Move the slider to increase number of points to weight. You can run the data through several passes to smooth even more. The original data is a sinus curve with noise jitter. With many points you can see the curve smooths to replicate this. Just using 9-10 points length over 2 passes will give a good result with very little time delay:
var ctx = document.querySelector("canvas").getContext("2d"),
rng = document.querySelector("input"),
val = document.querySelector("span"),
data = [], scale = 30;
// generate sinus wave with noise jitters
for(var i = 0; i < ctx.canvas.width; i += 2)
data.push(Math.sin(i*0.1) * Math.random() + Math.random())
// draw initial smoothed curve (length=1, no smoothing)
drawWMA();
// calculate moving average
function drawWMA() {
var len = +rng.value, // get smoothing length (number of previous points)
dataa = [], datab = [], // pass A and B arrays
weight = 0; // calc weight based on length
val.innerHTML = len;
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
ctx.beginPath();
// calc weight
for(var i = 1; i <= len; i++) weight += i; // add range together [1, length]
// plot original data at top of canvas
plot(data, 30);
// PASS 1: Calc new smoothed array
dataa = calcWMA(data, len, weight);
// plot smoothed curve
ctx.fillText("FIRST PASS:", 0, 100);
plot(dataa, 120);
// PASS 2 (optional)
datab = calcWMA(dataa, len, weight);
ctx.fillText("SECOND PASS:", 0, 190);
plot(datab, 210);
ctx.stroke(); // render plots
}
function calcWMA(data, len, weight) {
var i, t, datao = [];
// calc new smoothed array
for(i = 0; i < data.length; i++) { // iterate from length to end of data
var v = 0; // calc average value for this position
for(t = 0; t < len; t++) { // [1, len]
if (i-t >= 0)
v += data[i-t] * ((t+1) / weight); // weight previous values based on -delta
}
datao.push(v); // store new value
}
return datao
}
function plot(data, y) {
ctx.moveTo(0, y + data[0]*scale);
for(i = 1; i < data.length; i++) ctx.lineTo(i * 2, y + data[i]*scale);
}
rng.onchange = rng.oninput = drawWMA;
<label>Points to consider: <input type="range" min=1 max=50 value=1></label><span>1</span><br>
<canvas width=600 height=300></canvas>
A different approach would be to use a Savitzky–Golay filter which gives a similar result, but not "sacrifice" any points at the end (moving average will push forward or crop at the end).
I've been having trouble implementing an algorithm to shift my textures given their positions and the cameras position. The first two pictures in the image explain what I'm trying to accomplish, but I can't figure out how to move them accordingly. I had created a program once upon a time that did this, but I've gone and lost it. Any ideas?
If it helps any, the Cameras/Viewports width and height are the same as the textures' width and height. The goal is the get them to shift positions, giving the illusion of an infinite plane. (With out having to draw an infinite plane, lol.)
You do not really need to move your regions, enough to decide where to draw them. Lets assume you have a terrain containing N*M blocks (in this case N=M=2), each of them are size of A*A (in this case the screen hase the same size, but this doesn't matter), and the Tiles are continously following each other.
int LeftColumn = Camera.X / A; // let it round to nearest lower int
int TopRow = Camera.Y / A;
LeftColumn = LeftColumn % N; // Calculate the first tile
TopRow = TopRow % M;
for (int i = LeftColumn+N; i < LeftColumn+2*N; i++)
for (int l = TopRow+M; l < TopRow+2*M; l++)
// you may check here if the tile is visible or not based on the screen size
{
Tile[i % N, l % M].Draw(i*A, l*A); // Or do whatever you like
}
Is this clear?
After a couple hours of trial and error, I finally figured out how to get the regions/textures/rectangles to move accordingly. For those who want the solution,
if ((int)Math.Abs(region.X - camPos.X) > region.Width * 2)
{
region.X += region.Width * 2;
}
if (camPos.X < region.X - region.Width)
{
region.X -= region.Width * 2;
}
if ((int)Math.Abs(region.Y - camPos.Y) > region.Height * 2)
{
region.Y += region.Height * 2;
}
if (camPos.Y < region.Y - region.Height)
{
region.Y -= region.Height * 2;
}
Where camPos is the camera position, and region is the region/texture/rectangle/whatever.
This code works for a 4 square region (2 regions by 2 regions). To change for more regions, simply change all the *2s to *3s or *4s for a 9 square region and 16 square region, respectively.
I am currently trying to write some fourier transform algorithm. I started with a simple DFT algorithm as described in the mathematical definition:
public class DFT {
public static Complex[] Transform(Complex[] input) {
int N = input.Length;
Complex[] output = new Complex[N];
double arg = -2.0 * Math.PI / (double)N;
for (int n = 0; n < N; n++) {
output[n] = new Complex();
for (int k = 0; k < N; k++)
output[n] += input[k] * Complex.Polar(1, arg * (double)n * (double)k);
}
return output;
}
}
So I tested this algorithm with the following code:
private int samplingFrequency = 120;
private int numberValues = 240;
private void doCalc(object sender, EventArgs e) {
Complex[] input = new Complex[numberValues];
Complex[] output = new Complex[numberValues];
double t = 0;
double y = 0;
for (int i = 0; i < numberValues; i++) {
t = (double)i / (double)samplingFrequency;
y = Math.Sin(2 * Math.PI * t);
input[i] = new Complex(y, 0);
}
output = DFT.Transform(input);
printFunc(input);
printAbs(output);
}
The transformation works fine, but only if numberValues is a multiple number of the samplingFrequency (in this case: 120, 240, 360,...). Thats my result for 240 values:
The transformation just worked fine.
If i am trying to calculate 280 values I get this result:
Why I am getting a incorrect result if I change the number of my calculated values?
I am not sure if my problem here is a problem with my code or a misunderstanding of the mathematical definition of the DFT. In either way, can anybody help me with my problem? Thanks.
What you are experiencing is called Spectral Leakage.
This is caused because the underlying mathematics of the Fourier transform assumes a continuous function from -infinity to + infinity. So the range of samples you provide is effectively repeated an infinite number of times. If you don't have a complete number of cycles of the waveform in the window the ends won't line up and you will get a discontinuity which manifests its self as the frequency smearing out to either side.
The normal way to handle this is called Windowing. However, this does come with a downside as it causes the amplitudes to be slightly off. This is the process of multiply the whole window of samples you are going to process by some function which tends towards 0 at both ends of the window causing the ends to line up but with some amplitude distortion because this process lowers the total signal power.
So to summarise there is no error in your code, and the result is as expected. The artefacts can be reduced using a window function, however this will effect the accuracy of the amplitudes. You will need to investigate and determine what solution best fits the requirements of your project.
You are NOT getting the incorrect result for a non-periodic sinusoid. And they are not just "artifacts". Your result is actually the more complete DFT result which you don't see with a periodic sinusoid. Those other non-zero values contain useful information which can be used to, for example, interpolate the frequency of a single non-periodic-in-aperture sinusoid.
A DFT can be thought of as convolving a rectangular window with your sine wave. This produces (something very close to) a Sinc function, which has infinite extent, BUT just happens to be zero at every DFT bin frequency other than its central DFT bin for any sinusoid centered exactly on a DFT bin. This happens only when the frequency is exactly periodic in the FFT aperture, not for any other. The Sinc function has lots of "humps" which are all hidden in your first plot.
I'm trying to write a simple raytracer as a hobby project and it's all working fine now, except I can't get soft-shadows to work at all. My idea of soft-shadows is that the lightsource is considered to have a location and a radius. To do a shadow test on this light I take the point where the primary ray hit an object in the scene and cast an n-amount of rays towards the lightsource where each new ray has a random component to every axis, where the random component varies between -radius and radius.
If such a ray hits an object in the scene, I increment a hitcounter (if a ray hits multiple objects, it still only increments with one). If it makes it to the lightsource without collisions, I add the distance of the primary ray's intersect point to the lightsource's center to a variable.
When n samples have been taken, I calculate the ratio of rays that have collided and multiply the color of the light by this ratio (so a light with color 1000,1000,1000 will become 500,500,500 with a ratio of 0.5, where half the rays have collided). Then I calculate the average distance to the lightsource by dividing the distance variable of earlier by the amount of non-colliding rays. I return that variable and the function exits.
The problem is: it doesn't work. Not quite at least. What it looks like can be seen here. You can see it sort of resembles soft-shadows, if you squint real hard.
I don't get it, am I making some sort of fundamental flaw here, or is it something tiny? I'm fairly sure the problem is in this method, because when I count the number of partially lit pixels produced directly by this method, there are only about 250, when there should be a lot more. And when you look closely at the picture, you can see there's some partially lit pixels, suggesting the rest of the code processes the partially lit pixels just fine.
Here's the actual light for soft-shadows class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MyFirstRayTracer
{
public class AreaLight : ILight
{
private const int _radius = 5;
private const int _samples = 16;
public Color Color { get; set; }
public Vector Location { get; set; }
#region ILight Members
public float GetLightingInformation(Vector point, ISceneObject[] scene, out Color color)
{
int intersectCount = 0;
float distance = -1;
for(int i = 0; i < _samples; i++)
{
bool intersects = false;
float rand = 0;
rand = _radius - (float)(new Random().NextDouble()*(2*_radius));
foreach (ISceneObject obj in scene)
{
Vector iPoint;
Vector loc = new Vector(Location.X + rand, Location.Y + rand, Location.Z + rand);
if (!obj.Intersect(new Ray(point, loc), out iPoint))
{
distance += (Location - point).SqLength;
}
else
{
intersects = true;
distance -= (Location - point).SqLength;
}
}
if (intersects)
intersectCount++;
}
float factor = 1-((float)intersectCount/_samples);
color = new Color(factor*Color.R, factor*Color.G, factor*Color.B);
return (float)Math.Sqrt(distance / (_samples - intersectCount));
}
#endregion
}
}
minor point but is this the best use of the random class..
for(int i = 0; i < _samples; i++)
{
bool intersects = false;
float rand = 0;
rand = _radius - (float)(new Random().NextDouble()*(2*_radius));
should this not be..
var rnd = new Random()
for(int i = 0; i < _samples; i++)
{
bool intersects = false;
float rand = 0;
rand = _radius - (float)(rnd.NextDouble()*(2*_radius));
Try generating a different "rand" for each component of "loc". As is, your jittered points all lie on a line.
You actually generate the point on the line on a line with direction (1, 1, 1). Is the lightsource really linear?
Also, I can barely see anything in your example. Could you make your camera nearer the to-be shadow and not pointing from the direction of the light?
See, this is why I come to this site :)
Every axis has its own random now, and it looks a lot better. It's still a little weird looking, increasing the number of samples helps though. It now looks like this.
Do you know a more efficient way to reduce the pattern-forming?
The biggest help though: not instantiating Random for every sample. It seriously tripled my rendering speed with soft shadows! I never knew that Random was so costly to instantiate. Wow.
Thanks a lot.
In your response you asked for an improved way to make soft shadows. An improvement could be, instead of randomizing all the rays from the same point, to give each ray a different offset on all axes to effectively give them a seperate little window to randomize in. This should result in a more even distribution. I don't know if that was clear but another way to describe it is as a grid which is perpendicular to the shadow ray. Each tile in the grid contains one of the n shadow rays but the location in the grid is random. Here you can find a part of a tutorial which describes how this can be used for soft shadows.