Can't Pass Array into UBO - c

I'm trying to initialize a setup in Vulkan where within the Shader there is a uniform array of textures and an corresponding arrays for the textures Width and Heights:
layout(binding=0) uniform UniformBufferObject {
mat4 model; //4x4 array of floats for uniform rotation and positioning
uint texW[32]; //Widths of ith texture
uint texH[32]; //Heights of ith texture
} ubo;
For some reason the shader only reads the mat4 and the first index of the texW. Everything else is initialized to 0.
Here's the Uniform Buffer Setup Code, for reference
void createUniformBuffers() {
/**Uniform Buffer for View Transformation*/
VkDeviceSize bufferSize = sizeof(uniformBufferObject);
uniformBuffers = malloc(swapChainSize * sizeof(VkBuffer));
uniformBuffersMemory = malloc(swapChainSize * sizeof (VkDeviceMemory));
for(uint i = 0; i < swapChainSize; i++)
createBuffer(bufferSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffers[i], &uniformBuffersMemory[i]);
}
void createDescriptorPool() {
VkDescriptorPoolSize poolSizes[4];
poolSizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
poolSizes[0].descriptorCount = swapChainSize;
poolSizes[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
poolSizes[1].descriptorCount = swapChainSize;
VkDescriptorPoolCreateInfo poolInfo;
poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
poolInfo.pNext = 0;
poolInfo.flags = 0;
poolInfo.poolSizeCount = 2;
poolInfo.pPoolSizes = poolSizes;
poolInfo.maxSets = swapChainSize;
if(vkCreateDescriptorPool(lDevice, &poolInfo, 0, & descriptorPool)) {
fprintf(stderr, "Failed to create Descriptor Pool\n");
exit(1);
}
}
void createDescriptorSets() {
VkDescriptorSetLayout layouts[swapChainSize];
for(uint i = 0; i < swapChainSize; i++) layouts[i] = descriptorSetLayout;
VkDescriptorSetAllocateInfo allocInfo;
allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
allocInfo.pNext = 0;
allocInfo.descriptorPool = descriptorPool;
allocInfo.descriptorSetCount = swapChainSize;
allocInfo.pSetLayouts = layouts;
descriptorSets = malloc(sizeof(VkDescriptorSet) * swapChainSize);
if(vkAllocateDescriptorSets(lDevice, &allocInfo, descriptorSets) ) {
fprintf(stderr,"Failed to allocate descriptor sets\n");
exit(1);
}
for(uint i = 0; i < swapChainSize; i++) {
VkDescriptorBufferInfo bufferInfo;
bufferInfo.buffer = uniformBuffers[i];
bufferInfo.offset = 0;
bufferInfo.range = VK_WHOLE_SIZE; //sizeof(uniformBufferObject);
VkWriteDescriptorSet descriptorWrites[2];
descriptorWrites[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptorWrites[0].pNext = 0;
descriptorWrites[0].dstSet = descriptorSets[i];
descriptorWrites[0].dstBinding = 0;
descriptorWrites[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
descriptorWrites[0].descriptorCount = 1;
descriptorWrites[0].pBufferInfo = &bufferInfo;
descriptorWrites[0].pImageInfo = 0;
descriptorWrites[0].pTexelBufferView = 0;
descriptorWrites[0].dstArrayElement = 0;
VkDescriptorImageInfo imageInfo;
imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
imageInfo.imageView = textureImageView[0];
imageInfo.sampler= textureSampler;
descriptorWrites[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptorWrites[1].pNext = 0;
descriptorWrites[1].dstBinding = 1;
descriptorWrites[1].dstSet = descriptorSets[i];
descriptorWrites[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
descriptorWrites[1].descriptorCount = 1;
descriptorWrites[1].pImageInfo = &imageInfo;
descriptorWrites[1].pBufferInfo = 0;
descriptorWrites[1].pTexelBufferView = 0;
descriptorWrites[1].dstArrayElement = 0;
vkUpdateDescriptorSets(lDevice, 2, descriptorWrites,0,0);
}
}
Here's the code where the uniformBuffer is updated,
void updateUniformBuffer(uint currentImage) {
//FTR, I know I probably shouldn't remap each update, optimizing this is on my todo-list
vkMapMemory(lDevice, uniformBuffersMemory[currentImage], 0, sizeof(uniformBufferObject), 0, (void*) &uData);
memcpy(uData, &uniformData, sizeof(uniformBufferObject));
memset(uData->model, 0, sizeof(uData->model));
//Rotating the View, GLSL acknowledges this data
uData->model[2][2] = uData->model[3][3] = 1;
uData->model[0][0] = cosf(angle);
uData->model[0][1] = -sinf(angle);
uData->model[1][1] = cosf(angle);
uData->model[1][0] = sinf(angle);
angle+= 0.05f;
uData->texW[0] = 1024; //<-------GLSL Vertex Shader will acknowledge this =)
uData->texH[0] = 1024; //<-------GLSL Vertex Shader will ignore this =(
uData->texH[0] = 1024; //<-------GLSL Vertex Shader will also ignore this >_<
vkUnmapMemory(lDevice,uniformBuffersMemory[currentImage]);}
Any pointers or advice would be greatly appreciated.

Related

Unexpected behaviour using function pointers

hope everyone one is doing well.
Just out here seeing the craziest programming behaviour I have ever seen, I was wondering if anyone can explain why is this happening?
I finally just finished rewriting how UART packets from an ESP32 is processed within the STM32H753ZI with an array that holds address of functions.
Depending on which packet arrives, for example "0x03" which is "enable line-in input" it will access that function within the function pointer array at the index of the packet, so in this case the "functionPointerArray[3]"
Whats happening is that when I comment out this piece of code:
void I2S_MuteHandler() {
/* SPI1 -> CR1 |= SPI_CR1_CSUSP;
SPI3 -> CR1 |= SPI_CR1_CSUSP;
while (((SPI1 -> CR1) & (SPI_CR1_CSTART)));
while (((SPI3 -> CR1) & (SPI_CR1_CSTART)));
DMA1_Stream0 -> CR &= ~DMA_SxCR_EN;
DMA1_Stream1 -> CR &= ~DMA_SxCR_EN;
DMA1_Stream3 -> CR &= ~DMA_SxCR_EN;
SPI1 -> CR1 &= ~SPI_CR1_SPE;
SPI3 -> CR1 &= ~SPI_CR1_SPE;*/
}
The output wave of which processed through a DSP code and sent out via "I2S3_TxBUFF" of code:
void I2S_HALFCOMPLETE_CALLBACK() {
int * I2S1_RxBUFF = getI2S1_RxBUFF();
int * I2S1_TxBUFF = getI2S1_TxBUFF();
int * I2S3_TxBUFF = getI2S3_TxBUFF();
double INSAMPLE_I2S_L[1024];
double INSAMPLE_I2S_R[1024];
double INSAMPLE_I2S_MONO[2048];
double OUTSAMPLE_I2S_L[1024];
double OUTSAMPLE_I2S_R[1024];
double OUTSAMPLE_I2S_MONO[2048];
for (int i = 0; i < 2048; i += 2) {
//EVEN
INSAMPLE_I2S_L[(i >> 1)] = (double)I2S1_RxBUFF[i] * (double)ADC_COMPENSATOR * 0.01 * centers.volume * centers.inputCompensator;
INSAMPLE_I2S_MONO[i] = (double)((I2S1_RxBUFF[i] + I2S1_RxBUFF[i+1]) >> 1) * (double)ADC_COMPENSATOR * 0.01 * subwoofers.volume;
//ODD
INSAMPLE_I2S_R[(i >> 1)] = (double)I2S1_RxBUFF[i+1] * (double)ADC_COMPENSATOR * 0.01 * centers.volume * centers.inputCompensator;
INSAMPLE_I2S_MONO[i+1] = INSAMPLE_I2S_MONO[i];
}
arm_biquad_cascade_df2T_f64(&subwoofers.audioStream_MONO, INSAMPLE_I2S_MONO, OUTSAMPLE_I2S_MONO, 2048);
arm_biquad_cascade_df2T_f64(&centers.audioStream_L, INSAMPLE_I2S_L, OUTSAMPLE_I2S_L, 1024);
arm_biquad_cascade_df2T_f64(&centers.audioStream_R, INSAMPLE_I2S_R, OUTSAMPLE_I2S_R, 1024);
for (int i = 0 ; i < 2048; i += 2){
//EVEN
I2S1_TxBUFF[i] = (int)OUTSAMPLE_I2S_L[i >> 1];
I2S3_TxBUFF[i] = (int)OUTSAMPLE_I2S_MONO[i];
//ODD
I2S1_TxBUFF[i+1] = (int)OUTSAMPLE_I2S_R[i >> 1];
I2S3_TxBUFF[i+1] = (int)OUTSAMPLE_I2S_MONO[i+1];
}
}
void I2S_TRANSFERCOMPLETE_CALLBACK() {
int * I2S1_RxBUFF = getI2S1_RxBUFF();
int * I2S1_TxBUFF = getI2S1_TxBUFF();
int * I2S3_TxBUFF = getI2S3_TxBUFF();
double INSAMPLE_I2S_L[1024];
double INSAMPLE_I2S_R[1024];
double INSAMPLE_I2S_MONO[2048];
double OUTSAMPLE_I2S_L[1024];
double OUTSAMPLE_I2S_R[1024];
double OUTSAMPLE_I2S_MONO[2048];
for (int i = 2048; i < 4096; i += 2) {
//EVEN
INSAMPLE_I2S_L[(i >> 1)-1024] = (double)I2S1_RxBUFF[i] * (double)ADC_COMPENSATOR * 0.01 * (double)centers.volume * centers.inputCompensator;
INSAMPLE_I2S_MONO[i-2048] = (double)((I2S1_RxBUFF[i] + I2S1_RxBUFF[i+1]) >> 1) * (double)ADC_COMPENSATOR * 0.01 * subwoofers.volume;
//ODD
INSAMPLE_I2S_R[(i >> 1)-1024] = (double)I2S1_RxBUFF[i+1] * (double)ADC_COMPENSATOR * 0.01 * (double)centers.volume * centers.inputCompensator;
INSAMPLE_I2S_MONO[(i+1)-2048] = INSAMPLE_I2S_MONO[i-2048];
}
arm_biquad_cascade_df2T_f64(&subwoofers.audioStream_MONO, INSAMPLE_I2S_MONO, OUTSAMPLE_I2S_MONO, 2048);
arm_biquad_cascade_df2T_f64(&centers.audioStream_L, INSAMPLE_I2S_L, OUTSAMPLE_I2S_L, 1024);
arm_biquad_cascade_df2T_f64(&centers.audioStream_R, INSAMPLE_I2S_R, OUTSAMPLE_I2S_R, 1024);
for (int i = 2048 ; i < 4096; i += 2){
//EVEN
I2S1_TxBUFF[i] = (int)OUTSAMPLE_I2S_L[(i >> 1)-1024];
I2S3_TxBUFF[i] = (int)OUTSAMPLE_I2S_MONO[i-2048];
//ODD
I2S1_TxBUFF[i+1] = (int)OUTSAMPLE_I2S_R[(i >> 1)-1024];
I2S3_TxBUFF[i+1] = (int)OUTSAMPLE_I2S_MONO[(i+1)-2048];
}
}
makes the input sine wave look like square waves and the biquad filters stop working
and when I uncomment the code thats causing the issue, the wave is working perfectly and the biquad filters work.
For a better in-depth look i'll include how I populate the array of function pointers and how it executes.
The function pointer array gets populated during the initialization stage of the MCU along side its peripherals CODE:
void load_functionHandlers() {
messageReceived[0] = I2S_MuteHandler; // I believe the issue stems here in this function
messageReceived[1] = I2S_UnmuteHandler;
// messageReceived[2] = SPDIF_MuteHandler;
// messageReceived[3] = SPDIF_UnmuteHandler;
messageReceived[3] = audioSelectorInlineHandler;
// messageReceived[5] = audioSelectorBluetoothHandler;
// messageReceived[6] = audioSelectorSPDIFHandler;
// messageReceived[7] = audioSelectorHDMIHandler;
// messageReceived[8] = audioSelectorInternalHandler;
// messageReceived[9] = audioSelectorExternalHandler;
// messageReceived[10] = setupIRHandler;
// messageReceived[11] = disableTouchHandler;
// messageReceived[12] = enableTouchHandler;
// messageReceived[13] = nightRiderLightsHandler;
// messageReceived[14] = rainbowLightsHandler;
messageReceived[15] = volumeIncreaseHandler;
messageReceived[16] = volumeDecreaseHandler;
//
messageReceived[17] = n_12dB_subBass_notch_EQHandler;
messageReceived[18] = n_9dB_subBass_notch_EQHandler;
messageReceived[19] = n_6dB_subBass_notch_EQHandler;
messageReceived[20] = n_3dB_subBass_notch_EQHandler;
messageReceived[21] = _0dB_subBass_notch_EQHandler;
messageReceived[22] = p_3dB_subBass_notch_EQHandler;
messageReceived[23] = p_6dB_subBass_notch_EQHandler;
messageReceived[24] = p_9dB_subBass_notch_EQHandler;
messageReceived[25] = p_12dB_subBass_notch_EQHandler;
messageReceived[26] = n_12dB_Bass_notch_EQHandler;
messageReceived[27] = n_9dB_Bass_notch_EQHandler;
messageReceived[28] = n_6dB_Bass_notch_EQHandler;
messageReceived[29] = n_3dB_Bass_notch_EQHandler;
messageReceived[30] = _0dB_Bass_notch_EQHandler;
messageReceived[31] = p_3dB_Bass_notch_EQHandler;
messageReceived[32] = p_6dB_Bass_notch_EQHandler;
messageReceived[33] = p_9dB_Bass_notch_EQHandler;
messageReceived[34] = p_12dB_Bass_notch_EQHandler;
messageReceived[35] = n_12dB_lower_midrange_notch_EQHandler;
messageReceived[36] = n_9dB_lower_midrange_notch_EQHandler;
messageReceived[37] = n_6dB_lower_midrange_notch_EQHandler;
messageReceived[38] = n_3dB_lower_midrange_notch_EQHandler;
messageReceived[39] = _0dB_lower_midrange_notch_EQHandler;
messageReceived[40] = p_3dB_lower_midrange_notch_EQHandler;
messageReceived[41] = p_6dB_lower_midrange_notch_EQHandler;
messageReceived[42] = p_9dB_lower_midrange_notch_EQHandler;
messageReceived[43] = p_12dB_lower_midrange_notch_EQHandler;
messageReceived[44] = n_12dB_midrange_notch_EQHandler;
messageReceived[45] = n_9dB_midrange_notch_EQHandler;
messageReceived[46] = n_6dB_midrange_notch_EQHandler;
messageReceived[47] = n_3dB_midrange_notch_EQHandler;
messageReceived[48] = _0dB_midrange_notch_EQHandler;
messageReceived[49] = p_3dB_midrange_notch_EQHandler;
messageReceived[50] = p_6dB_midrange_notch_EQHandler;
messageReceived[51] = p_9dB_midrange_notch_EQHandler;
messageReceived[52] = p_12dB_midrange_notch_EQHandler;
messageReceived[53] = n_12dB_higher_midrange_notch_EQHandler;
messageReceived[54] = n_9dB_higher_midrange_notch_EQHandler;
messageReceived[55] = n_6dB_higher_midrange_notch_EQHandler;
messageReceived[56] = n_3dB_higher_midrange_notch_EQHandler;
messageReceived[57] = _0dB_higher_midrange_notch_EQHandler;
messageReceived[58] = p_3dB_higher_midrange_notch_EQHandler;
messageReceived[59] = p_6dB_higher_midrange_notch_EQHandler;
messageReceived[60] = p_9dB_higher_midrange_notch_EQHandler;
messageReceived[61] = p_12dB_higher_midrange_notch_EQHandler;
messageReceived[62] = n_12dB_presence_notch_EQHandler;
messageReceived[63] = n_9dB_presence_notch_EQHandler;
messageReceived[64] = n_6dB_presence_notch_EQHandler;
messageReceived[65] = n_3dB_presence_notch_EQHandler;
messageReceived[66] = _0dB_presence_notch_EQHandler;
messageReceived[67] = p_3dB_presence_notch_EQHandler;
messageReceived[68] = p_6dB_presence_notch_EQHandler;
messageReceived[69] = p_9dB_presence_notch_EQHandler;
messageReceived[70] = p_12dB_presence_notch_EQHandler;
messageReceived[71] = n_12dB_brilliance_notch_EQHandler;
messageReceived[72] = n_9dB_brilliance_notch_EQHandler;
messageReceived[73] = n_6dB_brilliance_notch_EQHandler;
messageReceived[74] = n_3dB_brilliance_notch_EQHandler;
messageReceived[75] = _0dB_brilliance_notch_EQHandler;
messageReceived[76] = p_3dB_brilliance_notch_EQHandler;
messageReceived[77] = p_6dB_brilliance_notch_EQHandler;
messageReceived[78] = p_9dB_brilliance_notch_EQHandler;
messageReceived[79] = p_12dB_brilliance_notch_EQHandler;
messageReceived[80] = n_12dB_Bass_lowShelf_EQHandler;
messageReceived[81] = n_9dB_Bass_lowShelf_EQHandler;
messageReceived[82] = n_6dB_Bass_lowShelf_EQHandler;
messageReceived[83] = n_3dB_Bass_lowShelf_EQHandler;
messageReceived[84] = _0dB_Bass_lowShelf_EQHandler;
messageReceived[85] = p_3dB_Bass_lowShelf_EQHandler;
messageReceived[86] = p_6dB_Bass_lowShelf_EQHandler;
messageReceived[87] = p_9dB_Bass_lowShelf_EQHandler;
messageReceived[88] = p_12dB_Bass_lowShelf_EQHandler;
//messageReceived[89] = disableLightsHandler;
}
How the function pointer gets executed CODE:
static void (*messageReceived[255])(void); // Global Variable
void UART4_TRANSFERCOMPELTE_CALLBACK(uint8_t exitPacket) {
//functions pointers
if (exitPacket) {
if ((exitPacket >= 0) && (exitPacket <= 88)) {
(*messageReceived[exitPacket])();
}
} else {
uint8_t packet = getUART4_RxBUFF()[0];
if ((packet >= 0) && (packet <= 88)) {
(*messageReceived[packet])();
}
}
}
I can't never predict the behaviour of this. I try commenting out random function pointers where the function pointers get populated into the array and it works, and vice versa
I thought it was a memory address being overwritten somewhere, however I double checked the the two address of when the wave is square and when the wave is perfect. Its registers, address, anything you name it are identical. I am mind blown right now. If anyone can shine light on this would be amazing. It doesnt even enter the function thats in question at all
I know its an issue where populating the array is happening as when I do this test code to bypass the function pointer and comment out out the block of code it doesnt work still.
static void (*messageReceived[255])(void);
void UART4_TRANSFERCOMPELTE_CALLBACK(uint8_t exitPacket) {
//functions pointers
uint8_t * packet;
if (exitPacket) {
packet = malloc(sizeof(uint8_t));
packet[0] = exitPacket;
} else {
packet = getUART4_RxBUFF();
}
//(*messageReceived[packet[0]])(); // By passing function pointer array
audioSelectorInlineHandler();
}
UPDATE 1:
If I once again bypass the function pointer array and comment EVERYTHING in the function that populates the function pointer array. It works
CODE:
/*
* UART_PACKET_PROCESSOR.c
*
* Created on: May 13, 2021
* Author: Christopher
*/
#include <stdint.h>
#include <stdlib.h>
#include <constants.h>
#include <dspFactory.h>
#include <inputSourceFactory.h>
#include <opcode.h>
#include <packetProcessor.h>
#include <uartFactory.h>
static void (*messageReceived[255])(void);
void UART4_TRANSFERCOMPELTE_CALLBACK(uint8_t exitPacket) {
//functions pointers
uint8_t * packet = NULL;
if (exitPacket) {
//(*messageReceived[packet[exitPacket]])();
} else {
//(*messageReceived[getUART4_RxBUFF()[0]])();
}
audioSelectorInlineHandler();
}
void load_functionHandlers() {
// for (int i = 0; i < 255; i++) {
// messageReceived[i] = 0;
// }
//
// messageReceived[0] = &I2S_MuteHandler;
// messageReceived[1] = &I2S_UnmuteHandler;
//// messageReceived[2] = SPDIF_MuteHandler;
//// messageReceived[3] = SPDIF_UnmuteHandler;
//
// messageReceived[3] = &audioSelectorInlineHandler;
//// messageReceived[5] = audioSelectorBluetoothHandler;
//// messageReceived[6] = audioSelectorSPDIFHandler;
//// messageReceived[7] = audioSelectorHDMIHandler;
//
//// messageReceived[8] = audioSelectorInternalHandler;
//// messageReceived[9] = audioSelectorExternalHandler;
//
//// messageReceived[10] = setupIRHandler;
//// messageReceived[11] = disableTouchHandler;
//// messageReceived[12] = enableTouchHandler;
//
//// messageReceived[13] = nightRiderLightsHandler;
//// messageReceived[14] = rainbowLightsHandler;
//
// messageReceived[15] = &volumeIncreaseHandler;
// messageReceived[16] = &volumeDecreaseHandler;
////
// messageReceived[17] = &n_12dB_subBass_notch_EQHandler;
// messageReceived[18] = &n_9dB_subBass_notch_EQHandler;
// messageReceived[19] = &n_6dB_subBass_notch_EQHandler;
// messageReceived[20] = &n_3dB_subBass_notch_EQHandler;
// messageReceived[21] = &_0dB_subBass_notch_EQHandler;
// messageReceived[22] = &p_3dB_subBass_notch_EQHandler;
// messageReceived[23] = &p_6dB_subBass_notch_EQHandler;
// messageReceived[24] = &p_9dB_subBass_notch_EQHandler;
// messageReceived[25] = &p_12dB_subBass_notch_EQHandler;
//
// messageReceived[26] = &n_12dB_Bass_notch_EQHandler;
// messageReceived[27] = &n_9dB_Bass_notch_EQHandler;
// messageReceived[28] = &n_6dB_Bass_notch_EQHandler;
// messageReceived[29] = &n_3dB_Bass_notch_EQHandler;
// messageReceived[30] = &_0dB_Bass_notch_EQHandler;
// messageReceived[31] = &p_3dB_Bass_notch_EQHandler;
// messageReceived[32] = &p_6dB_Bass_notch_EQHandler;
// messageReceived[33] = &p_9dB_Bass_notch_EQHandler;
// messageReceived[34] = &p_12dB_Bass_notch_EQHandler;
//
// messageReceived[35] = &n_12dB_lower_midrange_notch_EQHandler;
// messageReceived[36] = &n_9dB_lower_midrange_notch_EQHandler;
// messageReceived[37] = &n_6dB_lower_midrange_notch_EQHandler;
// messageReceived[38] = &n_3dB_lower_midrange_notch_EQHandler;
// messageReceived[39] = &_0dB_lower_midrange_notch_EQHandler;
// messageReceived[40] = &p_3dB_lower_midrange_notch_EQHandler;
// messageReceived[41] = &p_6dB_lower_midrange_notch_EQHandler;
// messageReceived[42] = &p_9dB_lower_midrange_notch_EQHandler;
// messageReceived[43] = &p_12dB_lower_midrange_notch_EQHandler;
//
// messageReceived[44] = &n_12dB_midrange_notch_EQHandler;
// messageReceived[45] = &n_9dB_midrange_notch_EQHandler;
// messageReceived[46] = &n_6dB_midrange_notch_EQHandler;
// messageReceived[47] = &n_3dB_midrange_notch_EQHandler;
// messageReceived[48] = &_0dB_midrange_notch_EQHandler;
// messageReceived[49] = &p_3dB_midrange_notch_EQHandler;
// messageReceived[50] = &p_6dB_midrange_notch_EQHandler;
// messageReceived[51] = &p_9dB_midrange_notch_EQHandler;
// messageReceived[52] = &p_12dB_midrange_notch_EQHandler;
//
// messageReceived[53] = &n_12dB_higher_midrange_notch_EQHandler;
// messageReceived[54] = &n_9dB_higher_midrange_notch_EQHandler;
// messageReceived[55] = &n_6dB_higher_midrange_notch_EQHandler;
// messageReceived[56] = &n_3dB_higher_midrange_notch_EQHandler;
// messageReceived[57] = &_0dB_higher_midrange_notch_EQHandler;
// messageReceived[58] = &p_3dB_higher_midrange_notch_EQHandler;
// messageReceived[59] = &p_6dB_higher_midrange_notch_EQHandler;
// messageReceived[60] = &p_9dB_higher_midrange_notch_EQHandler;
// messageReceived[61] = &p_12dB_higher_midrange_notch_EQHandler;
//
// messageReceived[62] = &n_12dB_presence_notch_EQHandler;
// messageReceived[63] = &n_9dB_presence_notch_EQHandler;
// messageReceived[64] = &n_6dB_presence_notch_EQHandler;
// messageReceived[65] = &n_3dB_presence_notch_EQHandler;
// messageReceived[66] = &_0dB_presence_notch_EQHandler;
// messageReceived[67] = &p_3dB_presence_notch_EQHandler;
// messageReceived[68] = &p_6dB_presence_notch_EQHandler;
// messageReceived[69] = &p_9dB_presence_notch_EQHandler;
// messageReceived[70] = &p_12dB_presence_notch_EQHandler;
//
// messageReceived[71] = &n_12dB_brilliance_notch_EQHandler;
// messageReceived[72] = &n_9dB_brilliance_notch_EQHandler;
// messageReceived[73] = &n_6dB_brilliance_notch_EQHandler;
// messageReceived[74] = &n_3dB_brilliance_notch_EQHandler;
// messageReceived[75] = &_0dB_brilliance_notch_EQHandler;
// messageReceived[76] = &p_3dB_brilliance_notch_EQHandler;
// messageReceived[77] = &p_6dB_brilliance_notch_EQHandler;
// messageReceived[78] = &p_9dB_brilliance_notch_EQHandler;
// messageReceived[79] = &p_12dB_brilliance_notch_EQHandler;
//
// messageReceived[80] = &n_12dB_Bass_lowShelf_EQHandler;
// messageReceived[81] = &n_9dB_Bass_lowShelf_EQHandler;
// messageReceived[82] = &n_6dB_Bass_lowShelf_EQHandler;
// messageReceived[83] = &n_3dB_Bass_lowShelf_EQHandler;
// messageReceived[84] = &_0dB_Bass_lowShelf_EQHandler;
// messageReceived[85] = &p_3dB_Bass_lowShelf_EQHandler;
// messageReceived[86] = &p_6dB_Bass_lowShelf_EQHandler;
// messageReceived[87] = &p_9dB_Bass_lowShelf_EQHandler;
// messageReceived[88] = &p_12dB_Bass_lowShelf_EQHandler;
//messageReceived[89] = disableLightsHandler;
}
UPDATE 2:
If I tried another function to comment out and it still does the same behaviour.
CODE:
void load_functionHandlers() {
for (int i = 0; i < 255; i++) {
messageReceived[i] = 0;
}
messageReceived[0] = &I2S_MuteHandler;
messageReceived[1] = &I2S_UnmuteHandler; //Comment this shows same behavoir
// messageReceived[2] = SPDIF_MuteHandler;
// messageReceived[3] = SPDIF_UnmuteHandler;
messageReceived[3] = &audioSelectorInlineHandler;
// messageReceived[5] = audioSelectorBluetoothHandler;
// messageReceived[6] = audioSelectorSPDIFHandler;
// messageReceived[7] = audioSelectorHDMIHandler;
// messageReceived[8] = audioSelectorInternalHandler;
// messageReceived[9] = audioSelectorExternalHandler;
// messageReceived[10] = setupIRHandler;
// messageReceived[11] = disableTouchHandler;
// messageReceived[12] = enableTouchHandler;
// messageReceived[13] = nightRiderLightsHandler;
// messageReceived[14] = rainbowLightsHandler;
messageReceived[15] = &volumeIncreaseHandler; // no affect
messageReceived[16] = &volumeDecreaseHandler; // no affect
//
messageReceived[17] = &n_12dB_subBass_notch_EQHandler; ////////
messageReceived[18] = &n_9dB_subBass_notch_EQHandler;
messageReceived[19] = &n_6dB_subBass_notch_EQHandler;
messageReceived[20] = &n_3dB_subBass_notch_EQHandler;
messageReceived[21] = &_0dB_subBass_notch_EQHandler;
messageReceived[22] = &p_3dB_subBass_notch_EQHandler; any of these shows same behavior
messageReceived[23] = &p_6dB_subBass_notch_EQHandler;
messageReceived[24] = &p_9dB_subBass_notch_EQHandler;
messageReceived[25] = &p_12dB_subBass_notch_EQHandler;
messageReceived[26] = &n_12dB_Bass_notch_EQHandler;
messageReceived[27] = &n_9dB_Bass_notch_EQHandler;
messageReceived[28] = &n_6dB_Bass_notch_EQHandler;
messageReceived[29] = &n_3dB_Bass_notch_EQHandler;
messageReceived[30] = &_0dB_Bass_notch_EQHandler;
messageReceived[31] = &p_3dB_Bass_notch_EQHandler;
messageReceived[32] = &p_6dB_Bass_notch_EQHandler;
messageReceived[33] = &p_9dB_Bass_notch_EQHandler;
messageReceived[34] = &p_12dB_Bass_notch_EQHandler;
messageReceived[35] = &n_12dB_lower_midrange_notch_EQHandler;
messageReceived[36] = &n_9dB_lower_midrange_notch_EQHandler;
messageReceived[37] = &n_6dB_lower_midrange_notch_EQHandler;
messageReceived[38] = &n_3dB_lower_midrange_notch_EQHandler;
messageReceived[39] = &_0dB_lower_midrange_notch_EQHandler;
messageReceived[40] = &p_3dB_lower_midrange_notch_EQHandler;
messageReceived[41] = &p_6dB_lower_midrange_notch_EQHandler;
messageReceived[42] = &p_9dB_lower_midrange_notch_EQHandler;
messageReceived[43] = &p_12dB_lower_midrange_notch_EQHandler;
messageReceived[44] = &n_12dB_midrange_notch_EQHandler;
messageReceived[45] = &n_9dB_midrange_notch_EQHandler;
messageReceived[46] = &n_6dB_midrange_notch_EQHandler;
messageReceived[47] = &n_3dB_midrange_notch_EQHandler; any of these shows same behavior
messageReceived[48] = &_0dB_midrange_notch_EQHandler;
messageReceived[49] = &p_3dB_midrange_notch_EQHandler;
messageReceived[50] = &p_6dB_midrange_notch_EQHandler;
messageReceived[51] = &p_9dB_midrange_notch_EQHandler;
messageReceived[52] = &p_12dB_midrange_notch_EQHandler;
messageReceived[53] = &n_12dB_higher_midrange_notch_EQHandler;
messageReceived[54] = &n_9dB_higher_midrange_notch_EQHandler;
messageReceived[55] = &n_6dB_higher_midrange_notch_EQHandler;
messageReceived[56] = &n_3dB_higher_midrange_notch_EQHandler; any of these shows same behavior
messageReceived[57] = &_0dB_higher_midrange_notch_EQHandler;
messageReceived[58] = &p_3dB_higher_midrange_notch_EQHandler;
messageReceived[59] = &p_6dB_higher_midrange_notch_EQHandler;
messageReceived[60] = &p_9dB_higher_midrange_notch_EQHandler;
messageReceived[61] = &p_12dB_higher_midrange_notch_EQHandler;
messageReceived[62] = &n_12dB_presence_notch_EQHandler;
messageReceived[63] = &n_9dB_presence_notch_EQHandler;
messageReceived[64] = &n_6dB_presence_notch_EQHandler;
messageReceived[65] = &n_3dB_presence_notch_EQHandler; any of these shows same behavior
messageReceived[66] = &_0dB_presence_notch_EQHandler;
messageReceived[67] = &p_3dB_presence_notch_EQHandler;
messageReceived[68] = &p_6dB_presence_notch_EQHandler;
messageReceived[69] = &p_9dB_presence_notch_EQHandler;
messageReceived[70] = &p_12dB_presence_notch_EQHandler;
messageReceived[71] = &n_12dB_brilliance_notch_EQHandler;
messageReceived[72] = &n_9dB_brilliance_notch_EQHandler;
messageReceived[73] = &n_6dB_brilliance_notch_EQHandler;
messageReceived[74] = &n_3dB_brilliance_notch_EQHandler;
messageReceived[75] = &_0dB_brilliance_notch_EQHandler;
messageReceived[76] = &p_3dB_brilliance_notch_EQHandler; any of these shows same behavior
messageReceived[77] = &p_6dB_brilliance_notch_EQHandler;
messageReceived[78] = &p_9dB_brilliance_notch_EQHandler;
messageReceived[79] = &p_12dB_brilliance_notch_EQHandler;
messageReceived[80] = &n_12dB_Bass_lowShelf_EQHandler;
messageReceived[81] = &n_9dB_Bass_lowShelf_EQHandler;
messageReceived[82] = &n_6dB_Bass_lowShelf_EQHandler;
messageReceived[83] = &n_3dB_Bass_lowShelf_EQHandler;
messageReceived[84] = &_0dB_Bass_lowShelf_EQHandler; any of these shows same behavior
messageReceived[85] = &p_3dB_Bass_lowShelf_EQHandler;
messageReceived[86] = &p_6dB_Bass_lowShelf_EQHandler;
messageReceived[87] = &p_9dB_Bass_lowShelf_EQHandler;
messageReceived[88] = &p_12dB_Bass_lowShelf_EQHandler; ////////////
//messageReceived[89] = disableLightsHandler;
}
It is important to use C properly, otherwise, the one will be used by C. The code (in a question) suffers from numerous issues, I will emphasize just one: naming.
Thus, I had to assume few things since naming is not logical. Maybe I got it right.
#include <assert.h>
#include <stdint.h>
#include <stdlib.h>
typedef uint8_t function_id_type ;
/* valid function index is 0 ... (0xFF-1) */
#define MAX_FUNCTIONS 255
/* I assumed bellow has to be in the range above?
if not just change the value here
This first function is for some special purpose
*/
#define EXIT_PACKET_ID 0
#define VALID_FUNCTION_INDEX(IDX_) \
(IDX_ >= 0 && IDX_ < MAX_FUNCTIONS)
//
function_id_type getUART4_RxBUFF() {
// this is OK value as for testing/demo as we have
// not more that two elements in the function table
return (function_id_type)1;
// this will provoke assert exit downstream
// return (function_id_type)(MAX_FUNCTIONS + MAX_FUNCTIONS);
};
// type alias
// function table made of functions
// to process the messages received
typedef void (*function_table[MAX_FUNCTIONS])(void);
// demo workers
static void I2S_MuteHandler() {}
static void I2S_UnmuteHandler() {}
static void create_function_table ( function_table ft_ )
{
ft_[0] = I2S_MuteHandler;
ft_[1] = I2S_UnmuteHandler;
// leave the rest empty
}
// full table validity is obviously an expensive operation
#define PARTIALY_VALID_F_TABLE(FT) ( FT && FT[0] && FT[1] )
static void UART4_TRANSFERCOMPELTE_CALLBACK(
function_id_type exitPacket,
// due to the arg declaration
// will have to contain min MAX_FUNCTIONS
// and can not be null
void (*function_table[static MAX_FUNCTIONS])(void))
{
assert( PARTIALY_VALID_F_TABLE(function_table) );
if (exitPacket == EXIT_PACKET_ID) {
(*function_table[exitPacket])();
} else {
const function_id_type packet = getUART4_RxBUFF();
// in debug builds check before use
assert(VALID_FUNCTION_INDEX(packet)) ;
// index is valid but is there a function
// under that index
assert(function_table[packet]) ;
// all tests passed, use
(*function_table[packet])();
}
}
//
int main(void)
{
function_table my_ft_ = {0};
// this call fails on assert as ft is empty
// UART4_TRANSFERCOMPLETE_CALLBACK(EXIT_PACKET_ID, my_ft_) ;
create_function_table( my_ft_ ) ;
// OK
UART4_TRANSFERCOMPLETE_CALLBACK(EXIT_PACKET_ID, my_ft_) ;
// on this call make sure EXIT_PACKET_ID is not used
UART4_TRANSFERCOMPLETE_CALLBACK(EXIT_PACKET_ID + 1, my_ft_) ;
return EXIT_SUCCESS ;
}
There is nothing tricky or snazzy above and I hope the code is readable, with better naming, and easier to get right for the exact use-case. No Oscilloscope pictures were necessary :)
Also here is the link to the working Godbolt: https://godbolt.org/z/sa37a6o5a
Note there are no compiler arguments given. Please use them, in your work, after learning them and then if proven necessary.
HTH

Filling values in 1D array

Code Fragment
if (val==1)
paperR[LIMIT]={100,50,20,10,5,2,1};
else if (val==2)
paperR[LIMIT]={200,100,50,20,10,5,1};
PROBLEM ?
it's like doing
int ask;
LATER IN CODE
ask=1;
How to do it with array ?
You can't assign to an array, you can only provide a list of values if you're initializing the array at the point where it's being declared.
If you want to fill in an array, you can use memcpy from another array that contains the values you want to use. So you can declare:
const int arr100[] = {100,50,20,10,5,2,1};
const int arr200[] = {200,100,50,20,10,5,1};
int paperR[LIMIT];
if (val == 1) {
memcpy(paperR, arr100, sizeof arr100);
} else if (val == 2) {
memcpy(paperR, arr200, sizeof arr200);
}
You may do it by one element after other:
if (val==1)
{
paperR[0] = 100;
paperR[1] = 50;
paperR[2] = 20;
paperR[3] = 10;
paperR[4] = 5;
paperR[5] = 2;
paperR[6] = 1;
}
else if (val==2)
{
paperR[0] = 200;
paperR[1] = 100;
paperR[2] = 50;
paperR[3] = 20;
paperR[4] = 10;
paperR[5] = 5;
paperR[6] = 1;
}

code with double free or corruption

I've got a double free problem in my program. I know which pointer is double freed but I cant figure out when was it freed first.
here is the code of my function :
int spectrum_gen(char *shift_r, char *rec_poly, char *redun_poly,int spectrum_length)
{
char *seq = NULL,*l_shift = NULL,loop_shift[SIZE];
int current_weight,*spectrum = NULL,*spect_numb = NULL,length=1,spectrum_size=0;
int index,index2,temp,temp2,*temp3;
/* int *weights = NULL; */
int *encoded_w = NULL;
int min_length,min_weight = 1000;
int looping = 0;
int **spectrum_content = NULL;
int *seq_w;
int *weight_table = symbols_weight(Q);
int *weights = NULL;
spectrum= (int*) malloc(sizeof(int));
seq = (char*) malloc(sizeof(char));
l_shift = (char*) malloc(SIZE*sizeof(char*));
weights = (int*) malloc(sizeof(int));
encoded_w = (int*) malloc(sizeof(int));
spect_numb = (int*) malloc(sizeof(int));
spectrum_content = (int**) malloc(sizeof(int*));
spectrum_content[1] = (int*) malloc(sizeof(int));
seq_w = (int*) malloc(sizeof(int));
strcpy(seq,"1");
convert_to_real(seq,1);
while(length > 0)
{
/* show_word(seq,length);
show_word(shift_r,SIZE);
puts(""); */
if(length == 1)
{
set2zero(shift_r,SIZE);
current_weight = RTZ_weight(0,seq[0],shift_r,rec_poly,redun_poly,encoded_w,seq_w,weight_table);
*seq_w += seq_weight(seq,1,weight_table);
}
else
{
current_weight = RTZ_weight(weights[length-2],seq[length-1],shift_r,rec_poly,redun_poly,encoded_w,seq_w,weight_table);
*seq_w += seq_weight(seq,length,weight_table);
/* show_word(shift_r,SIZE);
show_word(loop_shift,SIZE); */
if(looping==1 && str_cmp(shift_r,loop_shift,SIZE))
{
puts("looping sequence!!");
free(spectrum);
spectrum = NULL;
free(encoded_w);
encoded_w = NULL;
free(spect_numb);
spect_numb = NULL;
free(spectrum_content);
spectrum_content = NULL;
free(weights);
weights = NULL;
return 1;
break;
}
if(*encoded_w==weights[length-2] && looping==0 && length>3)
{
str_cpy(loop_shift,shift_r,SIZE);
looping = 1;
}
if(*encoded_w != weights[length-2])
{
looping = 0;
}
}
weights = realloc(weights,length*sizeof(int));
weights[length-1] = *encoded_w;
l_shift = realloc(l_shift,length*sizeof(char));
l_shift[length-1] = shift_r[SIZE-1];
if((shift_r[0] != 0) && (*encoded_w < spectrum_length))
{
if((temp = index4(current_weight,spectrum,spectrum_size,1,0)) != (-1))
{
spect_numb[temp]++;
if((temp2 = index4(*seq_w,spectrum_content[temp],spectrum_content[temp][0],2,1)) != (-1))
{ spectrum_content[temp][temp2+1]++;
}
else
{
spectrum_content[temp][0] += 2;
spectrum_content[temp] = realloc(spectrum_content[temp],spectrum_content[temp][0]*sizeof(int));
spectrum_content[temp][spectrum_content[temp][0]-2] = *seq_w;
spectrum_content[temp][spectrum_content[temp][0]-1] = 1;
}
}
else
{
spectrum_size++;
spectrum = realloc(spectrum,spectrum_size*sizeof(int));
spect_numb = realloc(spect_numb,spectrum_size*sizeof(int));
/* spectrum content : creation of a new table to store the inputs with output of weight current_weight*/
spectrum_content = realloc(spectrum_content,spectrum_size*sizeof(int*));
spectrum_content[spectrum_size-1] = (int*) malloc(3*sizeof(int));
spectrum_content[spectrum_size-1][0] = 3;
spectrum_content[spectrum_size-1][1] = *seq_w;
spectrum_content[spectrum_size-1][2] = 1;
spectrum[spectrum_size-1] = current_weight;
spect_numb[spectrum_size-1] = 1;
}
}
if(seq_equal_zero(shift_r,SIZE) || (*encoded_w >= spectrum_length))
{
while((length>0) && (seq[length-1] == Q-1))
{
length--;
for(index=0;index<SIZE-1;index++)
shift_r[index] = shift_r[index+1];
shift_r[SIZE-1] = l_shift[length-1];
}
for(index=0;index<SIZE-1;index++)
shift_r[index] = shift_r[index+1];
shift_r[SIZE-1] = l_shift[length-2];
seq[length-1] += 1;
}
else
{
length++;
seq = realloc(seq,length*sizeof(char));
seq[length-1] = 0;
}
/* printf("%d\n%d\n",*encoded_w,current_weight);
getchar(); */
}
/* sort(spectrum,spect_numb,spectrum_content,spectrum_size);*/
puts("Debut du spectre de ce codeur :");
for(index=0;spectrum[index+1]<=spectrum_length;index++)
{
printf("( ");
for(index2=1;index2<spectrum_content[index][0]-2;index2+=2)
{
printf("%d*I^%d + ",spectrum_content[index][index2+1],spectrum_content[index][index2]);
}
printf("%d*I^%d",spectrum_content[index][spectrum_content[index][0]-1],spectrum_content[index][spectrum_content[index][0]-2]);
printf(" )*O^%d + ",spectrum[index]);
}
printf("( ");
for(index2=1;index2<spectrum_content[index][0]-2;index2+=2)
{
printf("%d*I^%d + ",spectrum_content[index][index2+1],spectrum_content[index][index2]);
}
printf("%d*I^%d",spectrum_content[index][spectrum_content[index][0]-1],spectrum_content[index][spectrum_content[index][0]-2]);
printf(")*O^%d",spectrum[index]);
puts("");
free(seq);
seq = NULL;
free(spectrum);
spectrum = NULL;
free(encoded_w);
encoded_w = NULL;
free(spect_numb);
spect_numb = NULL;
free(spectrum_content);
spectrum_content = NULL;
free(weights);
weights = NULL;
return 0;
}
that pointer is called seq.
It would be so cool if someone helps me with this :)
here are the two functions that handle that pointer
void convert_to_real(char *word,int end)
{
int index;
for(index=0;index<end;index++) word[index]-='0';
}
i dont think it may be a problem
the only other function that handles that pointer is :
int seq_weight(char *seq,int end,int *weight_table)
{
int index,weight = 0;
for(index=0;index<end;index++)
if(seq[index]>=0 && seq[index]<Q)
weight += weight_table[(int)seq[index]];
return weight;
}
and i dont think it would cause a problem neither. :(
It's great that you set the pointer value to null after you have free'd it. So make use of that fact, and check for null before you free it - that way you avoid the double delete. Then you don't have to hunt for the double deletion because you will be protected from it.

Save jpg data from database to a jpg file

I want to take the data in a field that contains a jpeg image and save it to an actual file that I can open with a paint editor. I know I could create an application to do this in c# but I'm wondering if there's a quick and easy way to just do it from a sql query?
It doesn't need to work on all records at once. I just need to be able to select a single record and save the image for that record to a file.
You can use MemoryStream object in C# as below
MemoryStream memstmSignature = new MemoryStream(InkToBytes(ds.Tables[1].Rows[0]["SIGNATURE"].ToString(), "image/gif", 0, 0));
Image imaSig = Image.FromStream(memstmSignature);
imaSig.RotateFlip(RotateFlipType.Rotate180FlipX);
imaSig.Save(Path.Combine(this.temporaryFilePath, this.signatureFileName));
memstmSignature.Close();
Helper functions below
private static byte[] InkToBytes(string inkStrokes, string encoderType, float x, float y)
{
ArrayList strokes = new ArrayList();
// max size for bit map
int maxX = 0;
int maxY = 0;
// intialize the strokes array with text string
int strokesCount;
if (inkStrokes.Length > 0)
{
if (inkStrokes.EndsWith(";"))
inkStrokes = inkStrokes.Remove((inkStrokes.Length - 1), 1);
char[] strokeSeperator = { ';' };
string[] strokeArray = inkStrokes.Split(strokeSeperator);
strokesCount = strokeArray.Length;
for (int i = 0; i < strokesCount; i++)
{
Stroke stroke = new Stroke(50);
stroke.Text = strokeArray[i];
strokes.Add(stroke);
Point[] points = stroke.ToPointArray();
int len = points.Length;
foreach (Point point in points)
{
maxX = (point.X > maxX ? point.X : maxX);
maxY = (point.Y > maxY ? point.Y : maxY);
}
}
}
// setup the gdi objects
Bitmap bitMap = new Bitmap(maxX + 20, maxY + 20); // leave some buffer room
Graphics graphics = Graphics.FromImage(bitMap);
Rectangle clientRect = new Rectangle(0, 0, bitMap.Width, bitMap.Height);
Pen pen = new Pen(Color.Black);
pen.Width = 2; // matches the client capture
// draw the bit map
if (x > 0 && y > 0)
graphics.DrawImage(bitMap, x, y);
else
graphics.DrawImage(bitMap, 0, 0);
graphics.FillRectangle(Brushes.White, clientRect);
graphics.DrawRectangle(pen, clientRect);
strokesCount = strokes.Count;
for (int j = 0; j < strokesCount; j++)
{
Stroke stroke = (Stroke)strokes[j];
if (stroke != null)
{
Point[] points = stroke.ToPointArray();
int len = points.Length;
if (len > 1)
{
Point prevPoint = points[0];
for (int i = 1; i < len; i++)
{
graphics.DrawLine(pen, prevPoint.X, prevPoint.Y, points[i].X, points[i].Y);
prevPoint = points[i];
}
}
}
}
// create the bytes from the bitmap to be returned
MemoryStream memStream = new MemoryStream(1000);
ImageCodecInfo imageCodedInfo = GetEncoderInfo(encoderType);
bitMap.Save(memStream, imageCodedInfo, null);
byte[] bytes = memStream.GetBuffer();
memStream.Close();
return bytes;
}
private static ImageCodecInfo GetEncoderInfo(String mimeType)
{
int j;
ImageCodecInfo[] encoders;
encoders = ImageCodecInfo.GetImageEncoders();
for (j = 0; j < encoders.Length; ++j)
{
if (encoders[j].MimeType == mimeType)
return encoders[j];
}
return null;
}
Hope this helps.
NOTE: I have not looked into to optimizing the above code

Box2d elastic rope joint

I'm writing a game, and I need to make up a rope. I maked it by b2RopeJoint, but there I have not found an opportunity to make it elastic.
Then I looked for b2DistanceJoint, everything is cool with the elasticity, but I can't find an ability to set a limit only to the maximum distance (without minimum one).
How can I do it?
Try this.
-(void) CreateElasticRope {
//=======Params
// Position and size
b2Vec2 lastPos = b2Vec2(4,4); //set position first body
float widthBody = 0.35;
float heightBody = 0.1;
// Body params
float density = 0.05;
float restitution = 0.5;
float friction = 0.5;
// Distance joint
float dampingRatio = 0.0;
float frequencyHz = 0;
// Rope joint
float kMaxWidth = 1.1;
// Bodies
int countBodyInChain = 15;
b2Body* prevBody;
//========Create bodies and joints
for (int k = 0; k < countBodyInChain; k++) {
b2BodyDef bodyDef;
if(k==0 ) bodyDef.type = b2_staticBody; //first body is static
else bodyDef.type = b2_dynamicBody;
bodyDef.position = lastPos;
lastPos += b2Vec2(2*widthBody, 0); //modify b2Vect for next body
bodyDef.fixedRotation = YES;
b2Body* body = world->CreateBody(&bodyDef);
b2PolygonShape distBodyBox;
distBodyBox.SetAsBox(widthBody, heightBody);
b2FixtureDef fixDef;
fixDef.density = density;
fixDef.restitution = restitution;
fixDef.friction = friction;
fixDef.shape = &distBodyBox;
body->CreateFixture(&fixDef);
body->SetHealth(9999999);
body->SetLinearDamping(0.0005f);
if(k>0) {
//Create distance joint
b2DistanceJointDef distJDef;
b2Vec2 anchor1 = prevBody->GetWorldCenter();
b2Vec2 anchor2 = body->GetWorldCenter();
distJDef.Initialize(prevBody, body, anchor1, anchor2);
distJDef.collideConnected = false;
distJDef.dampingRatio = dampingRatio;
distJDef.frequencyHz = frequencyHz;
world->CreateJoint(&distJDef);
//Create rope joint
b2RopeJointDef rDef;
rDef.maxLength = (body->GetPosition() - prevBody->GetPosition()).Length() * kMaxWidth;
rDef.localAnchorA = rDef.localAnchorB = b2Vec2_zero;
rDef.bodyA = prevBody;
rDef.bodyB = body;
world->CreateJoint(&rDef);
} //if k>0
prevBody = body;
} //for
}
There's a 2.2 style ropejoint implementation here: https://github.com/aaronfarr/box2Dweb
You can use both a rope joint and a distance joint together. Make the distance of the rope joint a bit longer than the distance joint.
From the Box2D testbed example, I modified the "Web" example as follows:
#ifndef ELASTICROPE_H
#define ELASTICROPE_H
#define NUM_JOINTS 7
#define NUM_LINKS 8
class ElasticRope : public Test
{
public:
ElasticRope()
{
b2Body* ground = NULL;
{
b2BodyDef bd;
ground = m_world->CreateBody(&bd);
b2EdgeShape shape;
shape.Set(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f));
ground->CreateFixture(&shape, 0.0f);
}
{
b2CircleShape shape;
shape.m_radius = 0.8f;
// create bodies
for (int b = 0; b < NUM_LINKS; b++) {
b2BodyDef bd;
bd.type = b2_dynamicBody;
bd.position.Set(5.0f, NUM_LINKS-b);
m_bodies[b] = m_world->CreateBody(&bd);
m_bodies[b]->CreateFixture(&shape, 5.0f);
}
for (int j = 0; j < NUM_JOINTS; j++) {
b2DistanceJointDef jd;
b2Vec2 p1, p2, d;
jd.frequencyHz = 5.0f;
jd.dampingRatio = 1.0f;
jd.bodyA = m_bodies[j];
jd.bodyB = m_bodies[j+1];
m_joints[j] = m_world->CreateJoint(&jd);
}
}
}
void Step(Settings* settings)
{
Test::Step(settings);
m_debugDraw.DrawString(5, m_textLine, "This demonstrates an elastic rope.");
m_textLine += DRAW_STRING_NEW_LINE;
}
void JointDestroyed(b2Joint* joint)
{
for (int32 i = 0; i < 8; ++i)
{
if (m_joints[i] == joint)
{
m_joints[i] = NULL;
break;
}
}
}
static Test* Create()
{
return new ElasticRope;
}
b2Body* m_bodies[NUM_LINKS];
b2Joint* m_joints[NUM_JOINTS];
};
#endif // ELASTICROPE_H
Its far from perfect, but may be a starting point.

Resources