Problems with create a new ImageGenerator - module

I'm new to the OpenNI and I'm trying to create a simple ImageGenerator that just display a pure color image, say white, I modified the “SampleModule” and in the UpdateData() method I assign the *pPixel value with 255. The UpdateData() method is as following
XnStatus SampleImage::UpdateData()
{
XnStatus nRetVal = XN_STATUS_OK;
XnUInt8* pPixel = m_pImageMap;
for (XnUInt y = 0; y < 300; ++y)
{
for (XnUInt x = 0; x < 400; ++x, ++pPixel)
{
*pPixel = (XnUInt8)255;
}
}
m_nFrameID++;
m_nTimestamp += 1000000 / SUPPORTED_FPS;
// mark that data is old
m_bDataAvailable = FALSE;
return (XN_STATUS_OK);
}
The code compile fine, and I could register it with nireg, but when I try to read the image pixel value from the data generated by the module I got some strange value (not 255 as I expected), I use the following code to read the pixel value.
const XnUInt8* pImageMap = mImageGenerator.GetImageMap();
for (XnUInt y = 0; y < 300; ++y)
{
for (XnUInt x = 0; x < 400; ++x, ++pImageMap)
{
cout << (int)*pImageMap << endl;
}
}
and also when I run the “NiViewer” the program still say it can't find the image node, but the “SampleModule” can be find as a depth.
Any advice would be appreciate.
Thanks a million,
Haolin Wei

Check if you did following things:
1. set color format, i.e, rgb (or YUV)
2. set correct value for each pixel in the updataData(), i.e. r=255,g=255,b=255

Related

Directx11 heightmap texture real-time modification problem

I'm making a terrain tool.
I made a 2D texture and am using it as a height map.
I want to change a specific part of the heightmap, but I'm having a problem.
I changed certain small parts, but the whole landscape of the texture is changed.
I would like to know the cause of this problem and how to solve it
thank you.
`HeightMap ShaderResourceView Create Code
void TerrainRenderer::BuildHeightmapSRV(ID3D11Device* device)
{
ReleaseCOM(mHeightMapSRV);
ReleaseCOM(m_hmapTex);
D3D11_TEXTURE2D_DESC texDesc;
texDesc.Width = m_terrainData.HeightmapWidth; //basic value 2049
texDesc.Height = m_terrainData.HeightmapHeight; //basic value 2049
texDesc.MipLevels = 1;
texDesc.ArraySize = 1;
texDesc.Format = DXGI_FORMAT_R16_FLOAT;
texDesc.SampleDesc.Count = 1;
texDesc.SampleDesc.Quality = 0;
texDesc.Usage = D3D11_USAGE_DYNAMIC;
texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
texDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
texDesc.MiscFlags = 0;
// HALF is defined in xnamath.h, for storing 16-bit float.
std::vector<HALF> hmap(mHeightmap.size());
//current mHeightmap is all zero.
std::transform(mHeightmap.begin(), mHeightmap.end(), hmap.begin(), XMConvertFloatToHalf);
D3D11_SUBRESOURCE_DATA data;
data.pSysMem = &hmap[0];
data.SysMemPitch = m_terrainData.HeightmapWidth * sizeof(HALF);
data.SysMemSlicePitch = 0;
HR(device->CreateTexture2D(&texDesc, &data, &m_hmapTex));
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
srvDesc.Format = texDesc.Format;
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
srvDesc.Texture2D.MostDetailedMip = 0;
srvDesc.Texture2D.MipLevels = -1;
HR(device->CreateShaderResourceView(m_hmapTex, &srvDesc, &mHeightMapSRV));
}
`HeightMap Texture modifying code
D3D11_MAPPED_SUBRESOURCE mappedData;
//m_hmapTex is ID3D11Texture2D*
HR(m_texMgr.m_context->Map(m_hmapTex, D3D11CalcSubresource(0, 0, 1), D3D11_MAP_WRITE_DISCARD, 0, &mappedData));
HALF* heightMapData = reinterpret_cast<HALF*>(mappedData.pData);
D3D11_TEXTURE2D_DESC heightmapDesc;
m_hmapTex->GetDesc(&heightmapDesc);
UINT width = heightmapDesc.Width;
for (int row = 0; row < width/4; ++row)
{
for (int col = 0; col < width/4; ++col)
{
idx = (row * width) + col;
heightMapData[idx] = static_cast<HALF>(XMConvertFloatToHalf(200));
}
}
m_texMgr.m_context->Unmap(m_hmapTex, D3D11CalcSubresource(0,0,1));
Please refer to the picture below
The lower right area renders the HeightMap texture.
I wanted to edit only 1/4 width and height, but that's all changed.
enter image description here
When the completed heightmap is applied, it works normally.
enter image description here
A texture does not always have the same width and height in memory as the definition suggests. Some textures strides (lines) are oversized. You have to use the Stride Size * Row to calculate the offset to write into.

Best way to do object collision?

I'm trying to do wall collision for objects and I've followed a tutorial that offers one method of doing collision.
This is the tutorial: https://www.youtube.com/watch?v=yZU1QJJdxgs
Currently, if the object detects a wall, instead of moving it's full distance, it moves pixel by pixel until it's against the wall. This worked well until I started trying to rotate the object with image_rotate, because it caused objects to get stuck in walls by either sliding against them or if they rotated into them.
I fixed this by using draw_sprite_ext instead and changing the rotation of the sprite itself and not the mask, which worked for about 20 minutes until it started causing more problems.
///obj_player Step
//Initialise Variables
hor_speed = 0;
ver_speed = 0;
accelerationspeed = 0.2;
decelerationspeed = 0.2;
maxspeed = 3;
pointdirection = 0;
//Get player's input
key_right = keyboard_check(ord("D"))
key_left = -keyboard_check(ord("A"))
key_up = -keyboard_check(ord("W"))
key_down = keyboard_check(ord("S"))
pointdirection = point_direction(x,y,mouse_x,mouse_y) + 270
hor_movement = key_left + key_right;
ver_movement = key_up + key_down;
//horizontal acceleration
if !(abs(hor_speed) >= maxspeed) {
hor_speed += hor_movement * accelerationspeed;
}
//horizontal deceleration
if (hor_movement = 0) {
if !(hor_speed = 0) {
hor_speed -= (sign(hor_speed) * decelerationspeed)
}
}
//vertical acceleration
if !(abs(ver_speed) >= maxspeed) {
ver_speed += ver_movement * accelerationspeed;
}
//vertical deceleration
if (ver_movement = 0) {
if !(ver_speed = 0) {
ver_speed -= (sign(ver_speed) * decelerationspeed)
}
}
//horizontal collision
if (place_meeting(x+hor_speed,y,obj_wall)) {
while(!place_meeting(x+sign(hor_speed),y,obj_wall)) {
x += sign(hor_speed);
}
hor_speed = 0;
}
//vertical collision
if (place_meeting(x,y+ver_speed,obj_wall)) {
while(!place_meeting(x,y+sign(ver_speed),obj_wall)) {
y += sign(ver_speed);
}
ver_speed = 0;
}
//move the player
x += hor_speed;
y += ver_speed;
///obj_player Draw
//rotate to look at cursor
draw_sprite_ext(spr_player, 0, x,y,image_xscale,image_yscale, pointdirection, image_blend, image_alpha);
I think the best way to rotate objects is through image_rotate, and I'd like to do it without getting stuff stuck in walls. Can my current method of collision be adapted to do this, or should I attempt to do it in a different way?
Your code looks fine, but if you're going to be rotating objects then you would also need to consider having a "knock back mechanic." Reason being is the player could be sitting next to this wall and if you rotate the object over them so they cant move, its not a fun time being stuck.
So you 'could' have the object that's rotating do a check before rotating and if objects are in the way then either stop it or push them back so they cant be within range.

Optimizing code to generate static

I am learning p5.js and wanted to generate a "static/noise texture" like so:
This is the code:
for (let y = 0; y < height; y++) {
for (let x = 0; x < width; x++) {
noiseVal = random(0,1);
stroke(255, noiseVal*255);
point(x,y);
}
}
This produces the desired outcome but it's obviously pretty slow since it has to iterate over every single pixel. What would be a more efficient way of doing this?
Your code is really not the best way to do with p5.js.
Take a look to the p5's pixels array.
When I run the following code, the function that use the pixels array run 100 times faster.
function setup() {
createCanvas(50, 50);
background(255);
let start, time;
start = performance.now();
noise_1();
time = performance.now() - start;
print("noise_1 : " + time);
start = performance.now();
noise_2();
time = performance.now() -start;
print("noise_2 : " + time);
}
// Your code
function noise_1() {
for (let y = 0; y < height; y++) {
for (let x = 0; x < width; x++) {
noiseVal = random(0,1);
stroke(noiseVal*255);
point(x,y);
}
}
}
// same with pixels array
function noise_2() {
loadPixels();
for (let i=0; i < pixels.length; i+=4){
noiseVal = random(0, 255);
pixels[i] = pixels[i+1] = pixels[i+2] = noiseVal;
}
updatePixels();
}
output :
noise_1 : 495.1
noise_2 : 5.92
To generate a single frame of static, you're going to have to iterate over each pixel. You could make your blocks larger than a single pixel, but that will only reduce the problem, not get rid of it completely.
Instead, you can probably get away with pre-computing a few images of static (let's say 10 or so). Save these as a file or to an off-screen buffer (the createGraphics() function is your friend), and then draw those images instead of drawing each pixel every frame.

Sprite Smooth movement and facing position according to movement

i'm trying to make this interaction with keyboard for movement using some sprites and i got stuck with two situations.
1) The character movement is not going acording to the animation itself (it only begin moving after one second or so while it's already being animated). What i really want it to do is, to move without a "initial acceleration feeling" that i get because of this problem
2) I can't think of a way to make the character face the position it should be facing when the key is released. I'll post the code here, but since it need images to work correctly and is not so small i made a skecth available at this link if you want to check it out: https://www.openprocessing.org/sketch/439572
PImage[] reverseRun = new PImage [16];
PImage[] zeroArray = new PImage [16];
void setup(){
size(800,600);
//Right Facing
for(int i = 0; i < zeroArray.length; i++){
zeroArray[i] = loadImage (i + ".png");
zeroArray[i].resize(155,155);
}
//Left Facing
for( int z = 0; z < reverseRun.length; z++){
reverseRun[z] = loadImage ( "mirror" + z + ".png");
reverseRun[z].resize(155,155);
}
}
void draw(){
frameRate(15);
background(255);
imageMode(CENTER);
if(x > width+10){
x = 0;
} else if (x < - 10){
x = width;}
if (i >= zeroArray.length){
i = 3;} //looping to generate constant motiion
if ( z >= reverseRun.length){
z = 3;} //looping to generate constant motiion
if (isRight) {
image(zeroArray[i], x, 300);
i++;
} //going through the images at the array
else if (isLeft) {
image(reverseRun[z],x,300);
z++;
} going through the images at the array
else if(!isRight){
image(zeroArray[i], x, 300);
i = 0; } //"stoped" sprite
}
}
//movement
float x = 300;
float y = 300;
float i = 0;
float z = 0;
float speed = 25;
boolean isLeft, isRight, isUp, isDown;
void keyPressed() {
setMove(keyCode, true);
if (isLeft ){
x -= speed;
}
if(isRight){
x += speed;
}
}
void keyReleased() {
setMove(keyCode, false);
}
boolean setMove(int k, boolean b) {
switch (k) {
case UP:
return isUp = b;
case DOWN:
return isDown = b;
case LEFT:
return isLeft = b;
case RIGHT:
return isRight = b;
default:
return b; }
}
The movement problem is caused by your operating system setting a delay between key presses. Try this out by going to a text editor and holding down a key. You'll notice that a character shows up immediately, followed by a delay, followed by the character repeating until you release the key.
That delay is also happening between calls to the keyPressed() function. And since you're moving the character (by modifying the x variable) inside the keyPressed() function, you're seeing a delay in the movement.
The solution to this problem is to check which key is pressed instead of relying solely on the keyPressed() function. You could use the keyCode variable inside the draw() function, or you could keep track of which key is pressed using a set of boolean variables.
Note that you're actually already doing that with the isLeft and isRight variables. But you're only checking them in the keyPressed() function, which defeats the purpose of them because of the problem I outlined above.
In other words, move this block from the keyPressed() function so it's inside the draw() function instead:
if (isLeft ){
x -= speed;
}
if(isRight){
x += speed;
}
As for knowing which way to face when the character is not moving, you could do that using another boolean value that keeps track of which direction you're facing.
Side note: you should really try to properly indent your code, as right now it's pretty hard to read.
Shameless self-promotion: I wrote a tutorial on user input in Processing available here.

Vulkan depth image binding error

Hi I am trying to bind depth memory buffer but I get an error saying as below. I have no idea why this error is popping up.
The depth format is VK_FORMAT_D16_UNORM and the usage is VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT. I have read online that the TILING shouldnt be linear but then I get a different error. Thanks!!!
The code for creating and binding the image is as below.
VkImageCreateInfo imageInfo = {};
// If the depth format is undefined, use fallback as 16-byte value
if (Depth.format == VK_FORMAT_UNDEFINED) {
Depth.format = VK_FORMAT_D16_UNORM;
}
const VkFormat depthFormat = Depth.format;
VkFormatProperties props;
vkGetPhysicalDeviceFormatProperties(*deviceObj->gpu, depthFormat, &props);
if (props.linearTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) {
imageInfo.tiling = VK_IMAGE_TILING_LINEAR;
}
else if (props.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) {
imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
}
else {
std::cout << "Unsupported Depth Format, try other Depth formats.\n";
exit(-1);
}
imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
imageInfo.pNext = NULL;
imageInfo.imageType = VK_IMAGE_TYPE_2D;
imageInfo.format = depthFormat;
imageInfo.extent.width = width;
imageInfo.extent.height = height;
imageInfo.extent.depth = 1;
imageInfo.mipLevels = 1;
imageInfo.arrayLayers = 1;
imageInfo.samples = NUM_SAMPLES;
imageInfo.queueFamilyIndexCount = 0;
imageInfo.pQueueFamilyIndices = NULL;
imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
imageInfo.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
imageInfo.flags = 0;
// User create image info and create the image objects
result = vkCreateImage(deviceObj->device, &imageInfo, NULL, &Depth.image);
assert(result == VK_SUCCESS);
// Get the image memory requirements
VkMemoryRequirements memRqrmnt;
vkGetImageMemoryRequirements(deviceObj->device, Depth.image, &memRqrmnt);
VkMemoryAllocateInfo memAlloc = {};
memAlloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
memAlloc.pNext = NULL;
memAlloc.allocationSize = 0;
memAlloc.memoryTypeIndex = 0;
memAlloc.allocationSize = memRqrmnt.size;
// Determine the type of memory required with the help of memory properties
pass = deviceObj->memoryTypeFromProperties(memRqrmnt.memoryTypeBits, 0, /* No requirements */ &memAlloc.memoryTypeIndex);
assert(pass);
// Allocate the memory for image objects
result = vkAllocateMemory(deviceObj->device, &memAlloc, NULL, &Depth.mem);
assert(result == VK_SUCCESS);
// Bind the allocated memeory
result = vkBindImageMemory(deviceObj->device, Depth.image, Depth.mem, 0);
assert(result == VK_SUCCESS);
Yes, linear tiling may not be supported for depth usage Images.
Consult the specification and Valid Usage section of VkImageCreateInfo. The capability is queried by vkGetPhysicalDeviceFormatProperties and vkGetPhysicalDeviceImageFormatProperties commands. Though depth formats are "opaque", so there is not much reason to use linear tiling.
This you seem to be doing in your code.
But the error informs you that you are trying to use a memory type that is not allowed for the given Image. Use vkGetImageMemoryRequirements command to query which memory types are allowed.
Possibly you have some error there (you are using 0x1 which is obviously not part of 0x84 per the message). You may want to reuse the example code in the Device Memory chapter of the specification. Provide your memoryTypeFromProperties implementation for more specific answer.
I accidentally set the typeIndex to 1 instead of i and it works now. In my defense I have been vulkan coding the whole day and my eyes are bleeding :). Thanks for the help.
bool VulkanDevice::memoryTypeFromProperties(uint32_t typeBits, VkFlags
requirementsMask, uint32_t *typeIndex)
{
// Search memtypes to find first index with those properties
for (uint32_t i = 0; i < 32; i++) {
if ((typeBits & 1) == 1) {
// Type is available, does it match user properties?
if ((memoryProperties.memoryTypes[i].propertyFlags & requirementsMask) == requirementsMask) {
*typeIndex = i;// was set to 1 :(
return true;
}
}
typeBits >>= 1;
}
// No memory types matched, return failure
return false;
}