Maya API - Move CV with Kinect - c++

I’m trying to create a 64-bit plug-in for Autodesk Maya 2013. The aim of this plug-in is to be able to model objects through the Kinect.
In context, with the plug-in you can select the CV of a created object. To specify you want to move the selected points, the position of selected CV is updated constantly.
Here is my problem, when I try to update the position of a selected CV of an object, the result is not displayed on the screen.
I have tried many ways without getting any result, as an example:
1) when I do the setPosition the point doesn’t update.
for ( ; !iter.isDone(); iter.next() ) {
iter.getDagPath( mdagPath, mComponent );
MItSurfaceCV sCvFn( mdagPath, mComponent, true, &stat );
if ( MS::kSuccess == stat ) {
for ( ; !sCvFn.isDone(); sCvFn.nextRow() ) {
for ( ; !sCvFn.isRowDone(); sCvFn.next() ) {
MPoint pto(pHand.posX, pHand.posY, pHand.posZ);
sCvFn.setPosition(pto, MSpace::kWorld);
}
}
}
sCvFn.updateSurface();
}
2) in this case, if you iterate over the array newCVS before doing the setCVs you can see the updated points.
But then, when doing setCVs and looking for the position in the CV array of the object (doing a getCVs) the position of the modified CV doesn’t change.
for ( ; !iter.isDone(); iter.next() ) {
stat = iter.getDagPath( mdagPath, mComponent );
if(stat == MS::kSuccess) {
MFnNurbsSurface surf(mdagPath);
MItSurfaceCV sCvFn( mdagPath, mComponent, true, &stat );
MPointArray currentCV;
surf.getCVs(currentCV, MSpace::kWorld);
MPointArray newCVS(currentCV.length(), MPoint::origin);
newCVS.setLength(currentCV.length());
for(unsigned i = 0; i < currentCV.length(); i++){
newCVS[i] = newCVS[i] + currentCV[i];
}
int index;
if ( MS::kSuccess == stat ) {
for ( ; !sCvFn.isDone(); sCvFn.nextRow() ) {
for ( ; !sCvFn.isRowDone(); sCvFn.next() ) {
sCvFn.getIndex(indexU, indexV);
int posArray = indexU * surf.numCVsInV() + indexV;
index = posArray;
MVector diff = MPoint(pHand.posX, pHand.posY, pHand.posZ) - currentCV[posArray];
newCVS[posArray] = newCVS[posArray] + diff;
}
}
surf.setCVs(newCVS, MSpace::kWorld);
surf.updateSurface();
}
}
3) When having CV selected in Maya, I tried to move this points with MEL commands. For this, I use the “MGlobal::executeCommand” function, but still nothing happens.
Finally, I changed executeCommand to executeCommandOnIdle. In this case, the object change correctly but the procedure crashes, perhaps, because this procedure is executed many times per second.
I would appreciate if anyone can help me with this problem or knows something about this.

Related

Vulkan's transfer queue family capabilities and video card support: Are the condition checks accurate?

I am following this Vulkan Youtube video tutorial by Joshua Shucker. I'm currently on his 14th video where he is working on creating a secondary queue family for the vertex buffer. This focuses on the staging process for vertex buffers. My code matches that of his in his video except that of a cout statement in which I added for testing. Here is the function and structure for the Queue Families:
struct QueueFamilyIndices {
int graphicsFamily = -1;
int transferFamily = -1;
bool isComplete() {
return (graphicsFamily >= 0 && transferFamily >= 0);
}
};
QueueFamilyIndices FindQueueFamilies( const VkPhysicalDevice* device, const VkSurfaceKHR* surface ) {
QueueFamilyIndices indices;
uint32_t queueFamilyCount = 0;
vkGetPhysicalDeviceQueueFamilyProperties( *device, &queueFamilyCount, nullptr );
std::vector<VkQueueFamilyProperties> queueFamilies( queueFamilyCount );
vkGetPhysicalDeviceQueueFamilyProperties( *device, &queueFamilyCount, queueFamilies.data() );
int i = 0;
for( const auto &queueFamily : queueFamilies ) {
VkBool32 presentSupport = false;
vkGetPhysicalDeviceSurfaceSupportKHR( *device, i, *surface, &presentSupport );
if( queueFamily.queueCount > 0 && (queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT) && presentSupport ) {
indices.graphicsFamily = i;
}
if( queueFamily.queueCount > 0 && (queueFamily.queueFlags & VK_QUEUE_TRANSFER_BIT) &&
!(queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT) && presentSupport ) {
indices.transferFamily = i;
}
if( indices.isComplete() ) {
break;
}
i++;
}
if( indices.graphicsFamily >= 0 && indices.transferFamily == -1 ) {
std::cout << "Graphics family found, transfer family missing: using graphics family" << std::endl;
indices.transferFamily = indices.graphicsFamily;
}
return indices;
}
Within this function vkGetPhysicalDeviceSurfaceSupportKHR(...) is being called twice since there are 2 queue families that have been found after vkGetPhysicalDeviceQueueFamilyProperties(...) has been called to populate the vector of VkQueueFamilyProperties structures.
Here is the specs for my NVidia GeForce gtx 750 Ti card based on Vulkan's specifications for its queue families: Vulkan:Report and in case the link changes over time here is the information directly:
Queue family 0
queueCount 16
flags GRAPHICS_BIT
COMPUTE_BIT
TRANSFER_BIT
SPARSE_BINDING_BIT
timestampValidBits 64
minImageTransferGranularity.width 1
minImageTransferGranularity.height 1
minImageTransferGranularity.depth 1
supportsPresent 1
Queue family 1
queueCount 1
flags TRANSFER_BIT
timestampValidBits 64
minImageTransferGranularity.width 1
minImageTransferGranularity.height 1
minImageTransferGranularity.depth 1
supportsPresent 0
Now according to these specs which coincide with the values in my vector of structs while I'm stepping through the debugger my structures are populated with
the values of:
queueFamilies[0].queueFlags = 15;
queueFamilies[0].queueCount = 16;
queueFamilies[0].timestampValidBits = 64;
queueFamilies[0].minImageTransferGranularity = { width = 1, height = 1, depth = 1 };
queueFamilies[1].queueFlags = 4;
queueFamilies[1].queueCount = 1;
queueFamilies[1].timestampValidBits = 64;
queueFamilies[1].minImageTransferGranularity = { width = 1, height = 1, depth = 1 };
So this appears to me that my card does support a separate queueFamily specifically the transferFamily.
Based on my assumption of this support and stepping through this function he has two if statements to check for valid conditions within the for loop for each of the indexed queueFamily objects. The if statements are returning exactly as they should be. My code compiles and builds without any errors or warnings, and it still does render then triangle when I'm not running it through the debugger and it does exit with a code of (0). So the code appears to be fine. However I'm not getting the results that I would at least be expecting.
I'm not sure if there is a bug in his code that he happened to missed, if I'm misinterpreting my video card's support of this Vulkan functionality, or if this could be either a Vulkan API bug or NVidia Driver bug.
However as I was stepping through this function to find out why the indices.transferFamily variable was not being set to i; I noticed that on the second iteration of the loop it has nothing to do with the presence of the transferFamilyQueue, its parameter values, or flags. What is causing this if statement to return false is the presentSupport variable as it is being set to 0 on the second call which does match the data sheet above. So the output is as expected.
My question then becomes: Is there an actual implementation problem with the condition checking in the second if statement?
This is where I'm stuck as I am a bit confused because we are checking to see if there is a transferQueueFamily available and if so use that to create and use a stagingBuffer to copy the contents from the CPU to the GPU for the vertex buffer(s). From what I can see it appears my card does have this transferFamily but does not have supportPresent for this family. However, when thinking about it; if you are using a transferFamily - transferQueue you wouldn't want to present it directly as you'll just be copying the data from a temporary vertexBuffer on the CPU to the vertexBuffer that will be used on the GPU. So I'm wondering if the final check in this if statement is correct or not. If my assumptions about how Vulkan is working here is incorrect please don't hesitate to correct me as this is my first attempt at getting a Vulkan rendering application working.
There's no Vulkan API or NVidia Driver bug. It's right there in your report sheet:
supportsPresent 0
E.g. AMD does seem to support presents on VK_QUEUE_TRANSFER_BIT queue families, but it is purely optional (31.4. Querying for WSI Support):
Not all physical devices will include WSI support. Within a physical device, not all queue families will support presentation.
There's no good reason to be checking presentSupport when searching for a transfer specific queue. This is likely a copy and paste error somewhere. Typically you don't care if anything other than the graphics queue has support for presentation.
You do want to use a transfer queue that does not have the graphics bit set, as such a queue is likely to correspond to dedicated transfer hardware that will not impact the performance of work being done on the graphics queue.
After reading a few good answers here and doing some more testing on my end I think I have found an appropriate solution to the application code design. This function is called about 4 or 5 times throughout the application by other functions. It is called when Vulkan is being initialized, it is called again when rating the devices' suitability for choosing the best possible device that is available, it is also being called when creating the logical device, and so forth.
All of these initial calls typically only need the queueFamily's count and or index values to make sure that a suitable graphics device with a queueFamily is available for graphics processing and rendering.
However when this function is being called to create an arbitrary buffer that will be used as a staging buffer for an existing dedicated transfer queue this time we actually need the family queue and all of its properties. So to fix this problem; when checking for the graphicsQueue I left this last condition check to see if presentSupport is available, as for when the for loop iterates to the next index to check for the dedicated transferQueue, I omitted this condition check for the presentSupport all together.
QueueFamilyIndices FindQueueFamilies( const VkPhysicalDevice* device, const VkSurfaceKHR* surface ) {
QueueFamilyIndices indices;
uint32_t queueFamilyCount = 0;
vkGetPhysicalDeviceQueueFamilyProperties( *device, &queueFamilyCount, nullptr );
std::vector<VkQueueFamilyProperties> queueFamilies( queueFamilyCount );
vkGetPhysicalDeviceQueueFamilyProperties( *device, &queueFamilyCount, queueFamilies.data() );
int i = 0;
for( const auto &queueFamily : queueFamilies ) {
VkBool32 presentSupport = false;
vkGetPhysicalDeviceSurfaceSupportKHR( *device, i, *surface, &presentSupport );
if( queueFamily.queueCount > 0 && (queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT) && presentSupport ) {
indices.graphicsFamily = i;
}
if( queueFamily.queueCount > 0 && (queueFamily.queueFlags & VK_QUEUE_TRANSFER_BIT) &&
!(queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT) /*&& presentSupport*/ ) {
indices.transferFamily = i;
}
if( indices.isComplete() ) {
break;
}
i++;
}
if( indices.graphicsFamily >= 0 && indices.transferFamily == -1 ) {
std::cout << "Graphics family found, transfer family missing: using graphics family" << std::endl;
indices.transferFamily = indices.graphicsFamily;
}
return indices;
}
Now not only is the indices.transferFamily being set to i on the 2nd iteration; the check for indices.isComplete() is also returning true and the last if statement for the roll back is now returning false. Everything seems to being rendering properly without issue. It appears that the staging buffers are being copied over to the GPU now instead of using the CPU for the vertex buffer objects.

How can I stop wxProgressDialog re-sizing?

I am using a wxProgressDialog on Windows. Whenever I change the text in the dialog the dialog box re-sizes to best accommodate the text, this leads to the dialog frequently re-sizing which looks terrible.
I tried SetMinSize and SetSizeHints but these seemed to have no effect. SetSize also seems not to work.
(For info, the dialog is show progress of file transfer. As each file is transferred its full path is displayed. These vary greatly leading the continual re-sizing.)
My code is based on this code from the samples:
static const int max = 100;
wxProgressDialog dialog("Progress dialog example",
// "Reserve" enough space for the multiline
// messages below, we'll change it anyhow
// immediately in the loop below
wxString(' ', 100) + "\n\n\n\n",
max, // range
this, // parent
wxPD_CAN_ABORT |
wxPD_CAN_SKIP |
wxPD_APP_MODAL |
//wxPD_AUTO_HIDE | // -- try this as well
wxPD_ELAPSED_TIME |
wxPD_ESTIMATED_TIME |
wxPD_REMAINING_TIME |
wxPD_SMOOTH // - makes indeterminate mode bar on WinXP very small
);
bool cont = true;
for ( int i = 0; i <= max; i++ )
{
wxString msg;
// test both modes of wxProgressDialog behaviour: start in
// indeterminate mode but switch to the determinate one later
const bool determinate = i > max/2;
if ( i == max )
{
msg = "That's all, folks!\n"
"\n"
"Nothing to see here any more.";
}
else if ( !determinate )
{
msg = "Testing indeterminate mode\n"
"\n"
"This mode allows you to show to the user\n"
"that something is going on even if you don't know\n"
"when exactly will you finish.";
}
else if ( determinate )
{
msg = "Now in standard determinate mode\n"
"\n"
"This is the standard usage mode in which you\n"
"update the dialog after performing each new step of work.\n"
"It requires knowing the total number of steps in advance.";
}
// will be set to true if "Skip" button was pressed
bool skip = false;
if ( determinate )
{
cont = dialog.Update(i, msg, &skip);
}
else
{
cont = dialog.Pulse(msg, &skip);
}
// each skip will move progress about quarter forward
if ( skip )
{
i += max/4;
if ( i >= 100 )
i = 99;
}
if ( !cont )
{
if ( wxMessageBox(wxT("Do you really want to cancel?"),
wxT("Progress dialog question"), // caption
wxYES_NO | wxICON_QUESTION) == wxYES )
break;
cont = true;
dialog.Resume();
}
wxMilliSleep(200);
}
if ( !cont )
{
wxLogStatus(wxT("Progress dialog aborted!"));
}
else
{
wxLogStatus(wxT("Countdown from %d finished"), max);
}
}
Select a size for the file path display. If the path is shorter, add blanks, if longer replace with ellipses ( ... )
wxControl::Ellipsize is useful for this ( http://docs.wxwidgets.org/3.1/classwx_control.html#a0bb834cae2a8986aceddb89f84ef4ed1 )
If you want a fixed size, you need to use wxGenericProgressDialog, there doesn't seem to be any way of preventing the native dialog, used by default under the systems that support it (Vista and later), of adapting its size to its contents.

How to get resolution of camera

How to get the resolution of camera? Can somebody give me some suggestion.
Only i can do is the following,but it takes too much time to get the resolution.
The code's sequence look like this:
a.Open the camerra
b.Change the camera's resolution, and check the reuslt
void GetResolution( const int& countOfCamera, resolution_t (&resoulationTemp)[MAX_RESOLUTION] ){
VideoCapture *pVideoCaptures[MAX_CAMERA] = {NULL};
bool ret1 = false;
bool ret2 = false;
for ( int j=0; j<countOfCamera; ++j ) {
pVideoCaptures[j] = new VideoCapture(j);
/*==========================================================================
*If we don't do this, we will not open the Camera correctly
===========================================================================*/
pVideoCaptures[j]->set( CV_CAP_PROP_FRAME_WIDTH, defaultResolution.width );
pVideoCaptures[j]->set ( CV_CAP_PROP_FRAME_HEIGHT, defaultResolution.height );
}
for ( int i=0; i<MAX_RESOLUTION; ++i ) {
for ( int j=0; j<countOfCamera; ++j ) {
ret1 = pVideoCaptures[j]->set( CV_CAP_PROP_FRAME_WIDTH, resolutions[i].width );
ret2 = pVideoCaptures[j]->set ( CV_CAP_PROP_FRAME_HEIGHT, resolutions[i].height );
if ( !(ret1 && ret2) ) { //The resolution is not OK
break; //Check the next resolution
} else if ( j == ( countOfCamera -1 ) ) { //The resolution is OK for all camera,then store it.
resoulationTemp[i].width = resolutions[i].width;
resoulationTemp[i].height = resolutions[i].height;
} else {
//Do nothing
}
}
}
for ( int j=0; j<countOfCamera; ++j ) //Release the memory
{
pVideoCaptures[j]->release();
delete pVideoCaptures[j];
pVideoCaptures[j] = NULL;
}
}
Unfortunately there is no convenient way to get supported resolutions list for the particular camera by the opencv API (as it supports so many platforms and so many video capturing backends). Even your code will suffer from this, read the sources of videoio.hpp. But most of the digital video devices supports standard resolutions, you can simply select from them. Another way to get actual list of supported formats is to use 3rd party libraries, for the instance Qt solves this task by the couple of calls.

Don't understand these C++ box2d Errors

I've trying to get this C++ method to work in my iOS game.
-(b2Vec2) RayCheckWithInput:p1 andX:p2
{
b2RayCastInput input;
input.p1 = p1;
input.p2 = p2;
input.maxFraction = 1;
//check every fixture of every body to find closest
float closestFraction = 1; //start with end of line as p2
b2Vec2 intersectionNormal(0,0);
for (b2Body* b = self.world.world->GetBodyList(); b; b = b->GetNext()) {
for (b2Fixture* f = b->GetFixtureList(); f; f = f->GetNext()) {
b2RayCastOutput output;
if ( ! f->RayCast( &output, input ) )
continue;
if ( output.fraction < closestFraction ) {
closestFraction = output.fraction;
intersectionNormal = output.normal;
}
}
}
b2Vec2 intersectionPoint = p1 + closestFraction * (p2 - p1);
return intersectionPoint;
}
I know a fair bit about obj-c, but not C++. Here's a screen shot of the errors for that method it's showing.
Any help appreciated (in Chrome you can do right click and open image in new tab to see it better)
You need to be more explicit with the variables passed into the Objective-C function. You are passing without a type so it is not able to infer that it is actually a C++ type rather than an Objective-C type.
Try something like:
-(b2Vec2) RayCheckWithInput: (CPPTye*)p1 andX: (CPPTye*)p2
Edit: a quick check of the box2d docs says you need something like this:
-(b2Vec2) RayCheckWithInput: (b2Vec2)p1 andX: (b2Vec2)p2
Edit 2: Also worth noting that the Raycast function takes a third parameter childIndex as described in the docs.

Why would GLU crash at this spot?

I have found that my application crashes with a null reference exception right here in sweep.c in GLU source code:
static void ConnectLeftVertex( GLUtesselator *tess, GLUvertex *vEvent )
/*
* Purpose: connect a "left" vertex (one where both edges go right)
* to the processed portion of the mesh. Let R be the active region
* containing vEvent, and let U and L be the upper and lower edge
* chains of R. There are two possibilities:
*
* - the normal case: split R into two regions, by connecting vEvent to
* the rightmost vertex of U or L lying to the left of the sweep line
*
* - the degenerate case: if vEvent is close enough to U or L, we
* merge vEvent into that edge chain. The subcases are:
* - merging with the rightmost vertex of U or L
* - merging with the active edge of U or L
* - merging with an already-processed portion of U or L
*/
{
ActiveRegion *regUp, *regLo, *reg;
GLUhalfEdge *eUp, *eLo, *eNew;
ActiveRegion tmp;
/* assert( vEvent->anEdge->Onext->Onext == vEvent->anEdge ); */
/* Get a pointer to the active region containing vEvent */
tmp.eUp = vEvent->anEdge->Sym;
/* __GL_DICTLISTKEY */ /* __gl_dictListSearch */
regUp = (ActiveRegion *)dictKey( dictSearch( tess->dict, &tmp ));
regLo = RegionBelow( regUp );
eUp = regUp->eUp;
eLo = regLo->eUp; //CRASHES RIGHT HERE SINCE RegLo is = 0x000000 FOR SOME REASON
/* Try merging with U or L first */
if( EdgeSign( eUp->Dst, vEvent, eUp->Org ) == 0 ) {
ConnectLeftDegenerate( tess, regUp, vEvent );
return;
}
/* Connect vEvent to rightmost processed vertex of either chain.
* e->Dst is the vertex that we will connect to vEvent.
*/
reg = VertLeq( eLo->Dst, eUp->Dst ) ? regUp : regLo;
if( regUp->inside || reg->fixUpperEdge) {
if( reg == regUp ) {
eNew = __gl_meshConnect( vEvent->anEdge->Sym, eUp->Lnext );
if (eNew == NULL) longjmp(tess->env,1);
} else {
GLUhalfEdge *tempHalfEdge= __gl_meshConnect( eLo->Dnext, vEvent->anEdge);
if (tempHalfEdge == NULL) longjmp(tess->env,1);
eNew = tempHalfEdge->Sym;
}
if( reg->fixUpperEdge ) {
if ( !FixUpperEdge( reg, eNew ) ) longjmp(tess->env,1);
} else {
ComputeWinding( tess, AddRegionBelow( tess, regUp, eNew ));
}
SweepEvent( tess, vEvent );
} else {
/* The new vertex is in a region which does not belong to the polygon.
* We don''t need to connect this vertex to the rest of the mesh.
*/
AddRightEdges( tess, regUp, vEvent->anEdge, vEvent->anEdge, NULL, TRUE );
}
}
It seems as though eRegLo is a NULL pointer sometimes which causes my application to crash. How could I modify the source to prevent it from crashing my application?
Thanks
You will have to look into the source for RegionBelow and see if and when it can return a NULL pointer. Between your call to RegionBelow and your de-reference of regLo, perform a regLo == NULL check. You can do this with an assert or by throwing an exception (in C++). Most likely, if RegionBelow can return NULL on error, there will be some other method that you can use to determine what the error was and how to handle it. You will have to consult the source code or documentation for RegionBelow to find that information.