I'm new to DirectX, graphics, and HLSL and I have seen some weird code in the example below :
Texture2D g_BaseTexture : register(t0); // It may be used in the second argument in GaussianSample function
static float Gaussian5x5[25] =
{
0.003765f, 0.015019f, 0.023792f, 0.015019f, 0.003765f,
0.015019f, 0.059912f, 0.094907f, 0.059912f, 0.015019f,
0.023792f, 0.094907f, 0.150342f, 0.094907f, 0.023792f,
0.015019f, 0.059912f, 0.094907f, 0.059912f, 0.015019f,
0.003765f, 0.015019f, 0.023792f, 0.015019f, 0.003765f
};
float GaussianSample(int2 UV, Texture2D Tex)
{
float4 Output = (float4)0.f;
for (int i = 0; i < 5; ++i)
{
for (int j = 0; j < 5; ++j)
{
int2 ConvertUV = UV + int2(i - 2, j - 2); // Convert UV can be (x,y) = (-2, -2)
Output += Tex[ConvertUV] * Gaussian5x5[i * 5 + j];
}
}
return Output.x;
}
In this nested loop, ConvertUV can be (x,y) = (-2, -2). If then, It access to the "Tex" which is the Texture2D type resource using negative Index. I think negative indexing is invalid but If I test like this, there is no error or crash at all :
int2 Temp = int2(-2, -2);
float4 TempOutput = Tex[Temp];
What am I missing here?
Accessing resource out of bounds is guaranteed to return zero. See here:
Accessing Resources.
Related
I'm able to execute a hello world example, but beyond that I'm new to nan and node add-ons.
I'm concerned about memory leaks so if I'm causing any please let me
know.
And how do I push an array onto that out array similar to
[].push([0, 1]). I'm not sure how to do it in the cleanest way possible without creating a new variable to store it - if possible.
Also if there's anything else I'm doing that's not best practice please let me know! I've been researching this for a while now.
Here's the code I have so far
#include <nan.h>
void Method(const Nan::FunctionCallbackInfo <v8::Value> &info) {
v8::Local <v8::Context> context = info.GetIsolate()->GetCurrentContext();
v8::Local <v8::Array> coordinate = v8::Local<v8::Array>::Cast(info[0]);
unsigned int radius = info[2]->Uint32Value(context).FromJust();
// Also if creating the array is wasteful this way by giving it the max possible size
v8::Local <v8::Array> out = Nan::New<v8::Array>(x * y);
for (int x = -radius; x <= radius; ++x) {
for (int y = -radius; y <= radius; ++y) {
if (x * x + y * y <= radius * radius) {
// I need to push something like [x + coordinate->Get(context, 0), y + coordinate->Get(context, 0)];
out->push_back();
}
}
}
}
I was later able to write this.. If anyone can point out if I approached it correctly and/or if there are any memory issues I need to watch out for.
#include <nan.h>
void Method(const Nan::FunctionCallbackInfo <v8::Value> &info) {
v8::Local <v8::Context> context = info.GetIsolate()->GetCurrentContext();
v8::Local <v8::Array> coordinates v8::Local<v8::Array>::Cast(info[0]);
int radius = info[1]->Int32Value(context).FromJust();
v8::Local <v8::Array> out = Nan::New<v8::Array>();
int index = 0;
for (unsigned int i = 0; i < coordinates->Length(); i++) {
v8::Local <v8::Array> coordinate = v8::Local<v8::Array>::Cast(coordinates->Get(context, i).ToLocalChecked());
int xArg = coordinate->Get(context, 0).ToLocalChecked()->Int32Value(context).FromJust();
int yArg = coordinate->Get(context, 1).ToLocalChecked()->Int32Value(context).FromJust();
for (int xPos = -radius; xPos <= radius; ++xPos) {
for (int yPos = -radius; yPos <= radius; ++yPos) {
if (xPos * xPos + yPos * yPos <= radius * radius) {
v8::Local <v8::Array> xy = Nan::New<v8::Array>();
(void) xy->Set(context, 0, Nan::New(xPos + xArg));
(void) xy->Set(context, 1, Nan::New(yPos + yArg));
(void) out->Set(context, index++, xy);
}
}
}
}
info.GetReturnValue().Set(out);
}
I don't think you have any leaks - in fact there is no implicit memory allocation at all in your code - but in case you need it, I suggest you check the gyp files of my addons for more information on how to build them with asan with g++ or clang. As far as I am concerned, it is a mandatory step when creating Node addons.
https://github.com/mmomtchev/node-gdal-async/blob/master/binding.gyp
https://github.com/mmomtchev/exprtk.js/blob/main/binding.gyp
The option is called --enable_asan
I have made an implementation of the Reaction-Diffusion algorithm on Processing 3.1.1, following a video tutorial. I have made some adaptations on my code, like implementing it on a torus space, instead of a bounded box, like the video.
However, I ran into this annoying issue, that the code runs really slow, proportional to the canvas size (larger, slower). With that, I tried optmizing the code, according to my (limited) knowledge. The main thing I did was to reduce the number of loops running.
Even then, my code still ran quite slow.
Since I have noticed that with a canvas of 50 x 50 in size, the algorithm ran at a good speed, I tried making it multithreaded, in such a way that the canvas would be divided between the threads, and each thread would run the algorithm for a small region of the canvas.
All threads read from the current state of the canvas, and all write to the future state of the canvas. The canvas is then updated using Processing's pixel array.
However, even with multithreading, I didn't see any performance improvement. By the contrary, I saw it getting worse. Now sometimes the canvas flicker between a rendered state and completely white, and in some cases, it doesn't even render.
I'm quite sure that I'm doing something wrong, or I may be taking the wrong approach to optimizing this algorithm. And now, I'm asking for help to understand what I'm doing wrong, and how I could fix or improve my code.
Edit: Implementing ahead of time calculation and rendering using a buffer of PImage objects has removed flickering, but the calculation step on the background doesn't run fast enough to fill the buffer.
My Processing Sketch is below, and thanks in advance.
ArrayList<PImage> buffer = new ArrayList<PImage>();
Thread t;
Buffer b;
PImage currentImage;
Point[][] grid; //current state
Point[][] next; //future state
//Reaction-Diffusion algorithm parameters
final float dA = 1.0;
final float dB = 0.5;
//default: f = 0.055; k = 0.062
//mitosis: f = 0.0367; k = 0.0649
float feed = 0.055;
float kill = 0.062;
float dt = 1.0;
//multi-threading parameters to divide canvas
int threadSizeX = 50;
int threadSizeY = 50;
//red shading colors
color red = color(255, 0, 0);
color white = color(255, 255, 255);
color black = color(0, 0, 0);
//if redShader is false, rendering will use a simple grayscale mode
boolean redShader = true;
//simple class to hold chemicals A and B amounts
class Point
{
float a;
float b;
Point(float a, float b)
{
this.a = a;
this.b = b;
}
}
void setup()
{
size(300, 300);
//initialize matrices with A = 1 and B = 0
grid = new Point[width][];
next = new Point[width][];
for (int x = 0; x < width; x++)
{
grid[x] = new Point[height];
next[x] = new Point[height];
for (int y = 0; y < height; y++)
{
grid[x][y] = new Point(1.0, 0.0);
next[x][y] = new Point(1.0, 0.0);
}
}
int a = (int) random(1, 20); //seed some areas with B = 1.0
for (int amount = 0; amount < a; amount++)
{
int siz = 2;
int x = (int)random(width);
int y = (int)random(height);
for (int i = x - siz/2; i < x + siz/2; i++)
{
for (int j = y - siz/2; j < y + siz/2; j++)
{
int i2 = i;
int j2 = j;
if (i < 0)
{
i2 = width + i;
} else if (i >= width)
{
i2 = i - width;
}
if (j < 0)
{
j2 = height + j;
} else if (j >= height)
{
j2 = j - height;
}
grid[i2][j2].b = 1.0;
}
}
}
initializeThreads();
}
/**
* Divide canvas between threads
*/
void initializeThreads()
{
ArrayList<Reaction> reactions = new ArrayList<Reaction>();
for (int x1 = 0; x1 < width; x1 += threadSizeX)
{
for (int y1 = 0; y1 < height; y1 += threadSizeY)
{
int x2 = x1 + threadSizeX;
int y2 = y1 + threadSizeY;
if (x2 > width - 1)
{
x2 = width - 1;
}
if (y2 > height - 1)
{
y2 = height - 1;
}
Reaction r = new Reaction(x1, y1, x2, y2);
reactions.add(r);
}
}
b = new Buffer(reactions);
t = new Thread(b);
t.start();
}
void draw()
{
if (buffer.size() == 0)
{
return;
}
PImage i = buffer.get(0);
image(i, 0, 0);
buffer.remove(i);
//println(frameRate);
println(buffer.size());
//saveFrame("output/######.png");
}
/**
* Faster than calling built in pow() function
*/
float pow5(float x)
{
return x * x * x * x * x;
}
class Buffer implements Runnable
{
ArrayList<Reaction> reactions;
boolean calculating = false;
public Buffer(ArrayList<Reaction> reactions)
{
this.reactions = reactions;
}
public void run()
{
while (true)
{
if (buffer.size() < 1000)
{
calculate();
if (isDone())
{
buffer.add(currentImage);
Point[][] temp;
temp = grid;
grid = next;
next = temp;
calculating = false;
}
}
}
}
boolean isDone()
{
for (Reaction r : reactions)
{
if (!r.isDone())
{
return false;
}
}
return true;
}
void calculate()
{
if (calculating)
{
return;
}
currentImage = new PImage(width, height);
for (Reaction r : reactions)
{
r.calculate();
}
calculating = true;
}
}
class Reaction
{
int x1;
int x2;
int y1;
int y2;
Thread t;
public Reaction(int x1, int y1, int x2, int y2)
{
this.x1 = x1;
this.x2 = x2;
this.y1 = y1;
this.y2 = y2;
}
public void calculate()
{
Calculator c = new Calculator(x1, y1, x2, y2);
t = new Thread(c);
t.start();
}
public boolean isDone()
{
if (t.getState() == Thread.State.TERMINATED)
{
return true;
} else
{
return false;
}
}
}
class Calculator implements Runnable
{
int x1;
int x2;
int y1;
int y2;
//weights for calculating the Laplacian for A and B
final float[][] laplacianWeights = {{0.05, 0.2, 0.05},
{0.2, -1, 0.2},
{0.05, 0.2, 0.05}};
/**
* x1, x2, y1, y2 delimit a rectangle. The object will only work within it
*/
public Calculator(int x1, int y1, int x2, int y2)
{
this.x1 = x1;
this.x2 = x2;
this.y1 = y1;
this.y2 = y2;
//println("x1: " + x1 + ", y1: " + y1 + ", x2: " + x2 + ", y2: " + y2);
}
#Override
public void run()
{
reaction();
show();
}
public void reaction()
{
for (int x = x1; x <= x2; x++)
{
for (int y = y1; y <= y2; y++)
{
float a = grid[x][y].a;
float b = grid[x][y].b;
float[] l = laplaceAB(x, y);
float a2 = reactionDiffusionA(a, b, l[0]);
float b2 = reactionDiffusionB(a, b, l[1]);
next[x][y].a = a2;
next[x][y].b = b2;
}
}
}
float reactionDiffusionA(float a, float b, float lA)
{
return a + ((dA * lA) - (a * b * b) + (feed * (1 - a))) * dt;
}
float reactionDiffusionB(float a, float b, float lB)
{
return b + ((dB * lB) + (a * b * b) - ((kill + feed) * b)) * dt;
}
/**
* Calculates Laplacian for both A and B at same time, to reduce amount of loops executed
*/
float[] laplaceAB(int x, int y)
{
float[] l = {0.0, 0.0};
for (int i = x - 1; i < x + 2; i++)
{
for (int j = y - 1; j < y + 2; j++)
{
int i2 = i;
int j2 = j;
if (i < 0)
{
i2 = width + i;
} else if (i >= width)
{
i2 = i - width;
}
if (j < 0)
{
j2 = height + j;
} else if (j >= height)
{
j2 = j - height;
}
int weightX = (i - x) + 1;
int weightY = (j - y) + 1;
l[0] += laplacianWeights[weightX][weightY] * grid[i2][j2].a;
l[1] += laplacianWeights[weightX][weightY] * grid[i2][j2].b;
}
}
return l;
}
public void show()
{
currentImage.loadPixels();
//renders the canvas using the pixel array
for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
{
float a = next[x][y].a;
float b = next[x][y].b;
int pix = x + y * width;
float diff = (a - b);
color c;
if (redShader) //aply red shading
{
float thresh = 0.5;
if (diff < thresh)
{
float diff2 = map(pow5(diff), 0, pow5(thresh), 0, 1);
c = lerpColor(black, red, diff2);
} else
{
float diff2 = map(1 - pow5(-diff + 1), 1 - pow5(-thresh + 1), 1, 0, 1);
c = lerpColor(red, white, diff2);
}
} else //apply gray scale shading
{
c = color(diff * 255, diff * 255, diff * 255);
}
currentImage.pixels[pix] = c;
}
}
currentImage.updatePixels();
}
}
A programmer had a problem. He thought “I know, I’ll solve it with threads!”. has Now problems. two he
Processing uses a single rendering thread.
It does this for good reason, and most other renderers do the same thing. In fact, I don't know of any multi-threaded renderers.
You should only change what's on the screen from Processing's main rendering thread. In other words, you should only change stuff from Processing's functions, not your own thread. This is what's causing the flickering you're seeing. You're changing stuff as it's being drawn to the screen, which is a horrible idea. (And it's why Processing uses a single rendering thread in the first place.)
You could try to use your multiple threads to do the processing, not the rendering. But I highly doubt that's going to be worth it, and like you saw, it might even make things worse.
If you want to speed up your sketch, you might also consider doing the processing ahead of time instead of in real time. Do all your calculations at the beginning of the sketch, and then just reference the results of the calculations when it's time to draw the frame. Or you could draw to a PImage ahead of time, and then just draw those.
Followed this guide here
I am tasked with "using map and unmap methods to draw a line across the screen by setting pixel byte data to rgb red values".
I have the sprite and background displaying but have no idea how to get the data.
I also tried doing this:
//Create device
D3D11_TEXTURE2D_DESC desc;
ZeroMemory(&desc, sizeof(D3D11_TEXTURE2D_DESC));
desc.Width = 500;
desc.Height = 300;
desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
desc.Usage = D3D11_USAGE_DYNAMIC;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
desc.MiscFlags = 0;
desc.MipLevels = 1;
desc.ArraySize = 1;
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
m_d3dDevice->CreateTexture2D(&desc, nullptr, &texture);
m_d3dDevice->CreateShaderResourceView(texture, 0, &textureView);
// Render
D3D11_MAPPED_SUBRESOURCE mapped;
m_d3dContext->Map(texture, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped);
data = (BYTE*)mapped.pData;
rows = (BYTE)sizeof(data);
std::cout << "hi" << std::endl;
m_d3dContext->Unmap(texture, 0);
Problem is that in that case data array is size 0 but has a pointer. This means that I am pointing to a texture that doesn't have any data or am I not getting this?
Edit:
currently I found
D3D11_SHADER_RESOURCE_VIEW_DESC desc;
m_background->GetDesc(&desc);
desc.Buffer; // buffer
I felt the need to create an Answer for this as when I searched for how do this. This question pops up first and the supplied answer didn't really solve the problem for me and wasn't quite the way I wanted to do it anyways...
In my program I have a method as below.
void ContentLoader::WritePixelsToShaderIndex(uint32_t *data, int width, int height, int index)
{
D3D11_TEXTURE2D_DESC desc = {};
desc.Width = width;
desc.Height = height;
desc.MipLevels = 1;
desc.ArraySize = 1;
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
desc.Usage = D3D11_USAGE_DEFAULT;
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
desc.CPUAccessFlags = 0;
desc.MiscFlags = 0;
D3D11_SUBRESOURCE_DATA initData;
initData.pSysMem = data;
initData.SysMemPitch = width * 4;
initData.SysMemSlicePitch = width * height * 4;
Microsoft::WRL::ComPtr<ID3D11Texture2D> tex;
Engine::device->CreateTexture2D(&desc, &initData, tex.GetAddressOf());
Engine::device->CreateShaderResourceView(tex.Get(), NULL, ContentLoader::GetTextureAddress(index));
}
Then using the below code I tested drawing a Blue Square with a White Line. And it works perfectly fine. The issue I was getting was setting the System Mem Slice and Mem Pitch after looking in the WICTextureLoader class I was able to figure out how the data is stored. So it appears the
MemPitch = The Row's Size in Bytes.
MemSlice = The Total Image Pixels Size In Bytes.
const int WIDTH = 200;
const int HEIGHT = 200;
const uint32_t RED = 255 | (0 << 8) | (0 << 16) | (255 << 24);
const uint32_t WHITE = 255 | (255 << 8) | (255 << 16) | (255 << 24);
const uint32_t BLUE = 0 | (0 << 8) | (255 << 16) | (255 << 24);
uint32_t *buffer = new uint32_t[WIDTH * HEIGHT];
bool flip = false;
for (int X = 0; X < WIDTH; ++X)
{
for (int Y = 0; Y < HEIGHT; ++Y)
{
int pixel = X + Y * WIDTH;
buffer[pixel] = flip ? BLUE : WHITE;
}
flip = true;
}
WritePixelsToShaderIndex(buffer, WIDTH, HEIGHT, 3);
delete [] buffer;
First of all, most of those functions return HRESULT values that you are ignoring. That's not safe as you will miss important errors that invalidate the remaining code. You can use if(FAILED(...)) if you want, or you can use ThrowIfFailed, but you can't just ignore the return value in a functioning app.
HRESULT hr = m_d3dDevice->CreateTexture2D(&desc, nullptr, &texture);
if (FAILED(hr))
// error!
hr = m_d3dDevice->CreateShaderResourceView(texture, 0, &textureView);
if (FAILED(hr))
// error!
// Render
D3D11_MAPPED_SUBRESOURCE mapped;
hr = m_d3dContext->Map(texture, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped);
if (FAILED(hr))
// error!
Second, you should enable the Debug Device and look for diagnostic output which will likely point you to the reason for the failure.
sizeof(data) is always going to be 4 or 8 since data is a BYTE* i.e. the size of a pointer. It has nothing to do with the size of your data array. The locked buffer pointed to by mapped.pData is going to be mapped.RowPitch * desc.Height bytes in size.
You have to copy your pixel data into it row-by-row. Depending on the format and other factors, mapped.RowPitch is not necessarily going to be 4 * desc.Width--4 bytes per pixel is because you are using a format of DXGI_FORMAT_B8G8R8A8_UNORM. It should be at least that big, but it could be bigger to align the overall size.
This is pseudo-code and not necessarily an efficient way to do it, but:
for(UINT y = 0; y < desc.Height; ++y )
{
for(UINT x = 0; x < desc.Width; ++x )
{
// Find the memory location of the pixel at (x,y)
int pixel = y * mapped.RowPitch + (x*4)
BYTE* blue = data[pixel];
BYTE* green = data[pixel] + 1;
BYTE* red = data[pixel] + 2;
BYTE* alpha = data[pixel] + 3;
*blue = /* value between 0 and 255 */;
*green = /* value between 0 and 255 */;
*red = /* value between 0 and 255 */;
*alpha = /* value between 0 and 255 */;
}
}
You should take a look at DirectXTex which does a lot of this kind of row-by-row processing.
I have written an image resizer using Lanczos re-sampling. I've taken the implementation straight from the directions on wikipedia. The results look good visually, but for some reason it does not match the result from Matlab's resize with Lanczos very well (in pixel error).
Does anybody see any errors? This is not my area of expertise at all...
Here is my filter (I'm using Lanczos3 by default):
double lanczos_size_ = 3.0;
inline double sinc(double x) {
double pi = 3.1415926;
x = (x * pi);
if (x < 0.01 && x > -0.01)
return 1.0 + x*x*(-1.0/6.0 + x*x*1.0/120.0);
return sin(x)/x;
}
inline double LanczosFilter(double x) {
if (std::abs(x) < lanczos_size_) {
double pi = 3.1415926;
return sinc(x)*sinc(x/lanczos_size_);
} else {
return 0.0;
}
}
And my code to resize the image:
Image Resize(Image& image, int new_rows, int new_cols) {
int old_cols = image.size().cols;
int old_rows = image.size().rows;
double col_ratio =
static_cast<double>(old_cols)/static_cast<double>(new_cols);
double row_ratio =
static_cast<double>(old_rows)/static_cast<double>(new_rows);
// Apply filter first in width, then in height.
Image horiz_image(new_cols, old_rows);
for (int r = 0; r < old_rows; r++) {
for (int c = 0; c < new_cols; c++) {
// x is the new col in terms of the old col coordinates.
double x = static_cast<double>(c)*col_ratio;
// The old col corresponding to the closest new col.
int floor_x = static_cast<int>(x);
horiz_image[r][c] = 0.0;
double weight = 0.0;
// Add up terms across the filter.
for (int i = floor_x - lanczos_size_ + 1; i < floor_x + lanczos_size_; i++) {
if (i >= 0 && i < old_cols) {
double lanc_term = LanczosFilter(x - i);
horiz_image[r][c] += image[r][i]*lanc_term;
weight += lanc_term;
}
}
// Normalize the filter.
horiz_image[r][c] /= weight;
// Strap the pixel values to valid values.
horiz_image[r][c] = (horiz_image[r][c] > 1.0) ? 1.0 : horiz_image[r][c];
horiz_image[r][c] = (horiz_image[r][c] < 0.0) ? 0.0 : horiz_image[r][c];
}
}
// Now apply a vertical filter to the horiz image.
Image new_image(new_cols, new_rows);
for (int r = 0; r < new_rows; r++) {
double x = static_cast<double>(r)*row_ratio;
int floor_x = static_cast<int>(x);
for (int c = 0; c < new_cols; c++) {
new_image[r][c] = 0.0;
double weight = 0.0;
for (int i = floor_x - lanczos_size_ + 1; i < floor_x + lanczos_size_; i++) {
if (i >= 0 && i < old_rows) {
double lanc_term = LanczosFilter(x - i);
new_image[r][c] += horiz_image[i][c]*lanc_term;
weight += lanc_term;
}
}
new_image[r][c] /= weight;
new_image[r][c] = (new_image[r][c] > 1.0) ? 1.0 : new_image[r][c];
new_image[r][c] = (new_image[r][c] < 0.0) ? 0.0 : new_image[r][c];
}
}
return new_image;
}
Here is Lanczosh in one single loop. no errors.
Uses mentioned at top procedures.
void ResizeDD(
double* const pixelsSrc,
const int old_cols,
const int old_rows,
double* const pixelsTarget,
int const new_rows, int const new_cols)
{
double col_ratio =
static_cast<double>(old_cols) / static_cast<double>(new_cols);
double row_ratio =
static_cast<double>(old_rows) / static_cast<double>(new_rows);
// Now apply a filter to the image.
for (int r = 0; r < new_rows; ++r)
{
const double row_within = static_cast<double>(r)* row_ratio;
int floor_row = static_cast<int>(row_within);
for (int c = 0; c < new_cols; ++c)
{
// x is the new col in terms of the old col coordinates.
double col_within = static_cast<double>(c)* col_ratio;
// The old col corresponding to the closest new col.
int floor_col = static_cast<int>(col_within);
double& v_toSet = pixelsTarget[r * new_cols + c];
v_toSet = 0.0;
double weight = 0.0;
for (int i = floor_row - lanczos_size_ + 1; i <= floor_row + lanczos_size_; ++i)
{
for (int j = floor_col - lanczos_size_ + 1; j <= floor_col + lanczos_size_; ++j)
{
if (i >= 0 && i < old_rows && j >= 0 && j < old_cols)
{
const double lanc_term = LanczosFilter(row_within - i + col_within - j);
v_toSet += pixelsSrc[i * old_rows + j] * lanc_term;
weight += lanc_term;
}
}
}
v_toSet /= weight;
v_toSet = (v_toSet > 1.0) ? 1.0 : v_toSet;
v_toSet = (v_toSet < 0.0) ? 0.0 : v_toSet;
}
}
}
The line
for (int i = floor_x - lanczos_size_ + 1; i < floor_x + lanczos_size_; i++)
should be
for (int i = floor_x - lanczos_size_ + 1; i <= floor_x + lanczos_size_; i++)
Do not know but perhaps other mistakes linger too.
I think there is a mistake in your sinc function. Below the fraction bar you have to square pi and x. Additional you have to multiply the function with lanczos size
L(x) = **a***sin(pi*x)*sin(pi*x/a) * (pi**²**x**²**)^-1
Edit: My mistake, there is all right.
pls any one help me
i have create the edges in my project.i know how to check touch position is inside the shape
if (fix->TestPoint(locationWorld))
{
CCLOG(#"****touch inside shape***");
}
but i want create hexagon shape and i need to ball create inside hexagon shape and move inside hexagon.
i did ball move inside hexagon shape using below code:
b2BodyDef groundBodyDef;
groundBodyDef.position.Set(0, 0);
b2Body* groundBody = world->CreateBody(&groundBodyDef);
int countVal=[pos count];
// Define the ground box shape.
b2PolygonShape groundBox;
int range=[pos count]-2;
CCLOG(#"countVal=%d,range=%d",countVal,range);
for (int i=0; i<=range; i=i+2)
{
float x1,y1,x2,y2;
x1=[[pos objectAtIndex:i] floatValue];
y1=[[pos objectAtIndex:i+1] floatValue];
if (i==range)
{
x2=[[pos objectAtIndex:0] floatValue];
y2=[[pos objectAtIndex:1] floatValue];
}
else
{
x2=[[pos objectAtIndex:i+2] floatValue];
y2=[[pos objectAtIndex:i+3] floatValue];
}
CCLOG(#"x1=%f,y1=%f,x2=%f,y2=%f",x1,y1,x2,y2);
groundBox.SetAsEdge(b2Vec2(x1/PTM_RATIO,y1/PTM_RATIO),b2Vec2(x2/PTM_RATIO,y2/PTM_RATIO));
groundBody->CreateFixture(&groundBox, 0);
}
but i dont know how to find touch position is inside polygon shape.i use cocos2d with box2d
pls any one help me
Finally i got the answer:
i am checking if the point is inside polygon:
int pnpoly(int npol, float *xp, float *yp, float x, float y)
{
int i, j, c = 0;
for (i = 0, j = npol-1; i < npol; j = i++)
{
if ((((yp[i] <= y) && (y < yp[j])) ||
((yp[j] <= y) && (y < yp[i]))) &&
(x < (xp[j] - xp[i]) * (y - yp[i]) / (yp[j] - yp[i]) + xp[i]))
c = !c;
}
return c;
}