Segmentation fault when retrieving OGRE 3D 1.81 submesh data.
I tried to make use of the code from http://alumni.cs.ucr.edu/~sorianom/cs134_09win/
to get ogre mesh data for Bullet physics engine to use, but encountered an error message that said Segment Fault.
After reducing the code to find the reason I found it's "submesh->indexData->indexStart" that caused segment fault.
I am running on Ubuntu Linux 12.10 ( 32bit x86)(Due the budget limit, we can not afford to buy Windows), and use g++ as compiler.
Please help me, I am an elementary school teacher who are trying to make some CAI programs for students to learn Math, English...
I know cs134 sample code listed on the site is a little bit too old, I've upgrade all the meshes, dotsceneloader... but still cannot figure out what have to change.
Thank you!
The following is the reduced code that still makes the segment fault error message.
#include <Ogre.h>
#include <ExampleApplication.h>
#include <btBulletCollisionCommon.h>
class SampleApp : public ExampleApplication
{
public:
// Basic constructor
SampleApp()
{}
protected:
// Just override the mandatory create scene method
void createScene(void) {
mSceneMgr->setSkyBox(true, "Examples/CloudyNoonSkyBox");
Ogre::Light* myLight = mSceneMgr->createLight("Light0");
myLight->setType(Light::LT_POINT);
myLight->setPosition(0, 40, 0);
myLight->setDiffuseColour(1, 1, 1);
myLight->setSpecularColour(1, 1, 1);
Ogre::Entity* entity = mSceneMgr->createEntity("ogre", "ogrehead.mesh");
mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(entity);
Ogre::MeshPtr mesh = entity->getMesh();
Ogre::Mesh::SubMeshIterator j = mesh->getSubMeshIterator();
while (j.hasMoreElements()) {
Ogre::SubMesh* submesh = j.getNext();
std::cout << " submesh:" << submesh << "\n";
std::cout << " submesh->indexData:" << submesh->indexData << "\n";
//std::cout << " submesh->indexData->indexStart:" << submesh->indexData->indexStart << "\n";
int idxStart = submesh->indexData->indexStart;
int nIdx = submesh->indexData->indexCount;
}
}
};
// ----------------------------------------------------------------------------
// Main function, just boots the application object
// ----------------------------------------------------------------------------
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
#define WIN32_LEAN_AND_MEAN
#include "windows.h"
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT )
#else
int main(int argc, char **argv)
#endif
{
// Create application object
SampleApp app;
try
{
app.go();
}
catch( Exception& e )
{
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
MessageBox( NULL, e.getFullDescription().c_str(), "An exception has occured!", MB_OK | MB_ICONERROR | MB_TASKMODAL);
#else
std::cerr << "An exception has occured: " << e.getFullDescription();
#endif
}
return 0;
}
And the error message:
....
submesh:0xb752c080
submesh->indexData:0x8d042444
Segmentation fault (core dumped)
------------------
(program exited with code: 139)
The following is the gdb output:
(gdb) print submesh->indexData
$5 = (Ogre::IndexData *) 0x8d042444
(gdb) print submesh->indexData->indexStart
Cannot access memory at address 0x8d042458
(gdb)
ps: compiler setting: (You can compile the above code which is modified from CODE:BLOCK OGRE3D template , and bullet part isn't necessary in this reduced version)
g++ -o "%e" "%f" pkg-config --cflags --libs OGRE OIS bullet -I/usr/local/include/OGRE -I/usr/include/bullet
The original file is as following ( from http://tutorialsdl.googlecode.com/svn/trunk/Lab3/Lab3/OgreToBtMeshConverter.cpp) :
#include <Ogre.h>
#include <ExampleApplication.h>
#include <btBulletCollisionCommon.h>
class SampleApp : public ExampleApplication
{
public:
// Basic constructor
SampleApp()
{}
protected:
// Just override the mandatory create scene method
void createScene(void) {
mSceneMgr->setSkyBox(true, "Examples/CloudyNoonSkyBox");
Ogre::Light* myLight = mSceneMgr->createLight("Light0");
myLight->setType(Light::LT_POINT);
myLight->setPosition(0, 40, 0);
myLight->setDiffuseColour(1, 1, 1);
myLight->setSpecularColour(1, 1, 1);
Ogre::Entity* entity = mSceneMgr->createEntity("ogre", "ninja.mesh");
mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(entity);
//
// initialize bullets collision detection system
//
btVector3 worldAabbMin(-1000,-1000,-1000);
btVector3 worldAabbMax(1000,1000,1000);
btDefaultCollisionConfiguration* mColConfig;
btCollisionWorld* mColWorld;
btCollisionDispatcher* mDispatcher;
btAxisSweep3* mBroadphase;
mBroadphase = new btAxisSweep3(worldAabbMin, worldAabbMax); // broadphase
mColConfig = new btDefaultCollisionConfiguration();
mDispatcher = new btCollisionDispatcher(mColConfig); // narrowphase pair-wise checking
mColWorld = new btCollisionWorld(mDispatcher, mBroadphase, mColConfig);
//
// Registers every mesh in OGREs scene manager with the
// collision world. You should be adding your environment
// to the scene manager before this call. Your moveable
// character should be created after this call as to avoid
// having his mesh become part of the static level geometry.
//
// All meshes here are placed into group 2 and set to
// collide with group 1. You character should be in group
// 1, and set to collide with group 2. More about contact groups
// in the manual.
btCollisionWorld* colWorld=0;
registerEntityAsCollider(entity,colWorld);
}
void registerEntityAsCollider(Entity* entity, btCollisionWorld* colWorld)
{
// if you wish to do instancing you will have to share one
// btTriangleMesh amongst multiple btBvhTriangleMeshShape
// instances
btTriangleMesh* btMesh = new btTriangleMesh();
MeshPtr mesh = entity->getMesh();
Mesh::SubMeshIterator j = mesh->getSubMeshIterator();
while (j.hasMoreElements()) {
SubMesh* submesh = j.getNext();
int idxStart = submesh->indexData->indexStart;
int nIdx = submesh->indexData->indexCount;
HardwareIndexBuffer* idxBuffer
= submesh->indexData->indexBuffer.get();
HardwareVertexBufferSharedPtr virtBuffer;
VertexDeclaration* virtDecl;
if (submesh->useSharedVertices) {
virtDecl = mesh->sharedVertexData->vertexDeclaration;
assert(mesh->sharedVertexData->vertexBufferBinding->getBufferCount() > 0);
virtBuffer = mesh->sharedVertexData->vertexBufferBinding->getBuffer(0);
} else {
virtDecl = submesh->vertexData->vertexDeclaration;
assert(submesh->vertexData->vertexBufferBinding->getBufferCount() > 0);
virtBuffer = submesh->vertexData->vertexBufferBinding->getBuffer(0);
}
unsigned char* pVert = static_cast<unsigned char*>(virtBuffer->lock(HardwareBuffer::HBL_READ_ONLY));
// need to lock the buffer since vertex data resides on GPU
// and we need synchronization
unsigned short* sindices = NULL;
unsigned long* lindices = NULL;
if (idxBuffer->getType() == HardwareIndexBuffer::IT_16BIT) {
sindices = static_cast<unsigned short*>(idxBuffer->lock(HardwareBuffer::HBL_READ_ONLY));
} else if (idxBuffer->getType() == HardwareIndexBuffer::IT_32BIT) {
lindices = static_cast<unsigned long*>(idxBuffer->lock(HardwareBuffer::HBL_READ_ONLY));
} else {
assert(true == false);
}
const VertexElement* elm = virtDecl->findElementBySemantic(VES_POSITION, 0);
int offset = elm->getOffset();
assert(elm->getType() == VET_FLOAT3);
for (int k = idxStart; k < idxStart + nIdx; k += 3) {
unsigned int indices[3];
btVector3 vertices[3];
if (idxBuffer->getType() == HardwareIndexBuffer::IT_16BIT) {
for (int l = 0; l < 3; ++l) {
indices[l] = sindices[k + l];
}
} else {
for (int l = 0; l < 3; ++l) {
indices[l] = lindices[k + l];
}
}
for (int l = 0; l < 3; ++l) { // for each vertex
Real* posVert = (Real*)(pVert + indices[l] * virtBuffer->getVertexSize() + offset);
for (int m = 0; m < 3; ++m) { // for each vertex component
vertices[l][m] = posVert[m];
}
}
btMesh->addTriangle(vertices[0], vertices[1], vertices[2]);
}
idxBuffer->unlock();
virtBuffer->unlock();
}
btBvhTriangleMeshShape* btMeshShape = new btBvhTriangleMeshShape(btMesh, true, true);
btCollisionObject* btObj = new btCollisionObject();
btObj->setCollisionShape(btMeshShape);
Vector3 pos = entity->getParentSceneNode()->getPosition();
Quaternion orient = entity->getParentSceneNode()->getOrientation();
Vector3 scale = entity->getParentSceneNode()->getScale();
btMeshShape->setLocalScaling(btVector3(scale[0], scale[1], scale[2]));
btMeshShape->setMargin(0.0);
btTransform btTrans;
btTrans.setIdentity();
btTrans.setOrigin(btVector3(pos[0], pos[1], pos[2]));
btTrans.setRotation(btQuaternion(orient[1], orient[2], orient[3], orient[0]));
btObj->setWorldTransform(btTrans);
// the last 2 parameters are bit strings representing group membership
// and the groups which it is allowed to collide with
colWorld->addCollisionObject(btObj, 2, 1);
}
//
// This method will take every entity in your scene and register it as
// a mesh in the btCollisionWorld. NOTE: Be sure to call this function after
// you've added your static entities (environment) to the scene manager but
// before you add your characters.
//
void registerAllEntitiesAsColliders(SceneManager* sceneMgr, btCollisionWorld* colWorld)
{
SceneManager::MovableObjectIterator
i = sceneMgr->getMovableObjectIterator("Entity");
while (i.hasMoreElements()) {
Entity* entity = static_cast<Entity*>(i.getNext());
registerEntityAsCollider(entity, colWorld);
}
}
};
// ----------------------------------------------------------------------------
// Main function, just boots the application object
// ----------------------------------------------------------------------------
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
#define WIN32_LEAN_AND_MEAN
#include "windows.h"
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT )
#else
int main(int argc, char **argv)
#endif
{
// Create application object
SampleApp app;
try
{
app.go();
}
catch( Exception& e )
{
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
MessageBox( NULL, e.getFullDescription().c_str(), "An exception has occured!", MB_OK | MB_ICONERROR | MB_TASKMODAL);
#else
std::cerr << "An exception has occured: " << e.getFullDescription();
#endif
}
return 0;
}
Related
I am trying to write the simplest possible compute shader in DirectX12 so that I can have a starting point for a real project. However, it seems like no matter what I do I am unable to get my GPU to process "1+1" and see the output. As there is almost no documentation on compute shaders, I figured my only option now is to query StackOverflow.
I wrote the following code using the D3D12nBodyGravity project. First I copied as much of the code over as verbatim as possible, fixed "small" things, and then once it was all working I started trimming the code down to the basics. I am using Visual Studio 2019.
myClass.cpp:
#include "pch.h"
#include "myClass.h"
#include <d3dcompiler.h> // D3DReadFileToBlob
#include "Common\DirectXHelper.h" // NAME_D3D12_OBJECT
#include "Common\Device.h"
#include <iostream>
// InterlockedCompareExchange returns the object's value if the
// comparison fails. If it is already 0, then its value won't
// change and 0 will be returned.
#define InterlockedGetValue(object) InterlockedCompareExchange(object, 0, 0)
myClass::myClass()
: m_frameIndex(0)
, m_UavDescriptorSize(0)
, m_renderContextFenceValue(0)
, m_frameFenceValues{} {
std::cout << "Initializing myClass" << std::endl;
m_FenceValue = 0;
//std::cout << "Calling DXGIDeclareAdapterRemovalSupport()" << std::endl;
//DX::ThrowIfFailed(DXGIDeclareAdapterRemovalSupport());
// Identify the device
std::cout << "Identifying the device" << std::endl;
auto m_device = Device::Get().GetDevice();
std::cout << "Leading the rendering pipeline dependencies" << std::endl;
// Load the rendering pipeline dependencies.
{
std::cout << " Creating the root signatures" << std::endl;
// Create the root signatures.
{
CD3DX12_ROOT_PARAMETER rootParameter;
rootParameter.InitAsUnorderedAccessView(0);
Microsoft::WRL::ComPtr<ID3DBlob> signature;
Microsoft::WRL::ComPtr<ID3DBlob> error;
CD3DX12_ROOT_SIGNATURE_DESC computeRootSignatureDesc(1, &rootParameter, 0, nullptr);
DX::ThrowIfFailed(D3D12SerializeRootSignature(&computeRootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1, &signature, &error));
DX::ThrowIfFailed(m_device->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(), IID_PPV_ARGS(&m_computeRootSignature)));
}
// Describe and create the command queue.
std::cout << " Describing and creating the command queue" << std::endl;
D3D12_COMMAND_QUEUE_DESC queueDesc = {};
queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
DX::ThrowIfFailed(m_device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&m_commandQueue)));
NAME_D3D12_OBJECT(m_commandQueue);
std::cout << " Creating descriptor heaps" << std::endl;
// Create descriptor heaps.
{
// Describe and create a shader resource view (SRV) and unordered
// access view (UAV) descriptor heap.
D3D12_DESCRIPTOR_HEAP_DESC UavHeapDesc = {};
UavHeapDesc.NumDescriptors = DescriptorCount;
UavHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
UavHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
DX::ThrowIfFailed(m_device->CreateDescriptorHeap(&UavHeapDesc, IID_PPV_ARGS(&m_UavHeap)));
NAME_D3D12_OBJECT(m_UavHeap);
m_UavDescriptorSize = m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
}
std::cout << " Creating a command allocator for each frame" << std::endl;
// Create a command allocator for each frame.
for (UINT n = 0; n < FrameCount; n++) {
DX::ThrowIfFailed(m_device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&m_commandAllocators[n])));
}
} // Load the rendering pipeline dependencies.
std::cout << "Loading the sample assets" << std::endl;
// Load the sample assets.
{
std::cout << " Creating the pipeline states, including compiling and loading shaders" << std::endl;
// Create the pipeline states, which includes compiling and loading shaders.
{
Microsoft::WRL::ComPtr<ID3DBlob> computeShader;
#if defined(_DEBUG)
// Enable better shader debugging with the graphics debugging tools.
UINT compileFlags = D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION;
#else
UINT compileFlags = 0;
#endif
// Load and compile the compute shader.
DX::ThrowIfFailed(D3DReadFileToBlob(L"ComputeShader.cso", &computeShader));
auto convert_blob_to_byte = [](Microsoft::WRL::ComPtr<ID3DBlob> blob) {
auto* p = reinterpret_cast<unsigned char*>(blob->GetBufferPointer());
auto n = blob->GetBufferSize();
std::vector<unsigned char> buff;
buff.reserve(n);
std::copy(p, p + n, std::back_inserter(buff));
return buff;
};
std::vector<BYTE> m_computeShader = convert_blob_to_byte(computeShader);
// Describe and create the compute pipeline state object (PSO).
D3D12_COMPUTE_PIPELINE_STATE_DESC computePsoDesc = {};
computePsoDesc.pRootSignature = m_computeRootSignature.Get();
computePsoDesc.CS = CD3DX12_SHADER_BYTECODE(computeShader.Get());
DX::ThrowIfFailed(m_device->CreateComputePipelineState(&computePsoDesc, IID_PPV_ARGS(&m_computeState)));
NAME_D3D12_OBJECT(m_computeState);
}
std::cout << " Creating the command list" << std::endl;
// Create the command list.
DX::ThrowIfFailed(m_device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, m_commandAllocators[m_frameIndex].Get(), m_computeState.Get(), IID_PPV_ARGS(&m_commandList)));
NAME_D3D12_OBJECT(m_commandList);
std::cout << " Initializing the data in the buffers" << std::endl;
// Initialize the data in the buffers.
{
data.resize(2);
for (unsigned int i = 0; i < data.size(); i++) {
data[i] = 0.0f;
}
const UINT dataSize = data.size() * sizeof(data[0]);
D3D12_HEAP_PROPERTIES defaultHeapProperties = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT);
D3D12_HEAP_PROPERTIES uploadHeapProperties = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD);
D3D12_HEAP_PROPERTIES readbackHeapProperties = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_READBACK);
D3D12_RESOURCE_DESC bufferDesc = CD3DX12_RESOURCE_DESC::Buffer(dataSize, D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS);
D3D12_RESOURCE_DESC uploadBufferDesc = CD3DX12_RESOURCE_DESC::Buffer(dataSize);
readbackBufferDesc = CD3DX12_RESOURCE_DESC::Buffer(dataSize);
DX::ThrowIfFailed(m_device->CreateCommittedResource(
&defaultHeapProperties,
D3D12_HEAP_FLAG_NONE,
&bufferDesc,
D3D12_RESOURCE_STATE_COPY_DEST,
nullptr,
IID_PPV_ARGS(&m_dataBuffer)));
m_dataBuffer.Get()->SetName(L"m_dataBuffer");
DX::ThrowIfFailed(m_device->CreateCommittedResource(
&uploadHeapProperties,
D3D12_HEAP_FLAG_NONE,
&uploadBufferDesc,
D3D12_RESOURCE_STATE_GENERIC_READ,
nullptr,
IID_PPV_ARGS(&m_dataBufferUpload)));
m_dataBufferUpload.Get()->SetName(L"m_dataBufferUpload");
DX::ThrowIfFailed(m_device->CreateCommittedResource(
&readbackHeapProperties,
D3D12_HEAP_FLAG_NONE,
&readbackBufferDesc,
D3D12_RESOURCE_STATE_COPY_DEST,
nullptr,
IID_PPV_ARGS(&m_dataBufferReadback)));
m_dataBufferReadback.Get()->SetName(L"m_dataBufferReadback");
NAME_D3D12_OBJECT(m_dataBuffer);
dataSubResource = {};
dataSubResource.pData = &data[0];
dataSubResource.RowPitch = dataSize;
dataSubResource.SlicePitch = dataSubResource.RowPitch;
UpdateSubresources<1>(m_commandList.Get(), m_dataBuffer.Get(), m_dataBufferUpload.Get(), 0, 0, 1, &dataSubResource);
m_commandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_dataBuffer.Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_COMMON));
m_commandList->CopyResource(m_dataBufferReadback.Get(), m_dataBufferUpload.Get());
D3D12_UNORDERED_ACCESS_VIEW_DESC uavDesc = {};
uavDesc.Format = DXGI_FORMAT_UNKNOWN;
uavDesc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER;
uavDesc.Buffer.FirstElement = 0;
uavDesc.Buffer.NumElements = 1;
uavDesc.Buffer.StructureByteStride = sizeof(data[0]);
uavDesc.Buffer.CounterOffsetInBytes = 0;
uavDesc.Buffer.Flags = D3D12_BUFFER_UAV_FLAG_NONE;
CD3DX12_CPU_DESCRIPTOR_HANDLE uavHandle0(m_UavHeap->GetCPUDescriptorHandleForHeapStart(), Uav, m_UavDescriptorSize);
m_device->CreateUnorderedAccessView(m_dataBuffer.Get(), nullptr, &uavDesc, uavHandle0);
} // Initialize the data in the buffers.
std::cout << " Closing the command list and executing it to begind the initial GPU setup" << std::endl;
// Close the command list and execute it to begin the initial GPU setup.
DX::ThrowIfFailed(m_commandList->Close());
ID3D12CommandList* ppCommandLists[] = { m_commandList.Get() };
m_commandQueue->ExecuteCommandLists(_countof(ppCommandLists), ppCommandLists);
std::cout << " Creating synchronization objects and wait until assets have been uploaded to the GPU" << std::endl;
// Create synchronization objects and wait until assets have been uploaded to the GPU.
{
DX::ThrowIfFailed(m_device->CreateFence(m_renderContextFenceValue, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&m_renderContextFence)));
m_renderContextFenceValue++;
m_renderContextFenceEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
if (m_renderContextFenceEvent == nullptr) {
DX::ThrowIfFailed(HRESULT_FROM_WIN32(GetLastError()));
}
// Add a signal command to the queue.
DX::ThrowIfFailed(m_commandQueue->Signal(m_renderContextFence.Get(), m_renderContextFenceValue));
// Instruct the fence to set the event object when the signal command completes.
DX::ThrowIfFailed(m_renderContextFence->SetEventOnCompletion(m_renderContextFenceValue, m_renderContextFenceEvent));
m_renderContextFenceValue++;
// Wait until the signal command has been processed.
WaitForSingleObject(m_renderContextFenceEvent, INFINITE);
}
} // Load the sample assets.
std::cout << "Creating compute resources" << std::endl;
{
// Create compute resources.
D3D12_COMMAND_QUEUE_DESC queueDesc = { D3D12_COMMAND_LIST_TYPE_COMPUTE, 0, D3D12_COMMAND_QUEUE_FLAG_NONE };
DX::ThrowIfFailed(m_device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&m_computeCommandQueue)));
DX::ThrowIfFailed(m_device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_COMPUTE, IID_PPV_ARGS(&m_computeAllocator)));
DX::ThrowIfFailed(m_device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_COMPUTE, m_computeAllocator.Get(), nullptr, IID_PPV_ARGS(&m_computeCommandList)));
DX::ThrowIfFailed(m_device->CreateFence(0, D3D12_FENCE_FLAG_SHARED, IID_PPV_ARGS(&m_Fence)));
m_FenceEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
if (m_FenceEvent == nullptr) {
DX::ThrowIfFailed(HRESULT_FROM_WIN32(GetLastError()));
}
}
std::cout << "Calculating" << std::endl;
Calculate();
std::cout << "Finished" << std::endl;
}
void myClass::Calculate() {
m_computeCommandList.Get()->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_dataBuffer.Get(), D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_UNORDERED_ACCESS));
m_computeCommandList.Get()->SetPipelineState(m_computeState.Get());
m_computeCommandList.Get()->SetComputeRootSignature(m_computeRootSignature.Get());
ID3D12DescriptorHeap* ppHeaps[] = { m_UavHeap.Get() };
m_computeCommandList.Get()->SetDescriptorHeaps(_countof(ppHeaps), ppHeaps);
CD3DX12_GPU_DESCRIPTOR_HANDLE uavHandle(m_UavHeap->GetGPUDescriptorHandleForHeapStart(), Uav, m_UavDescriptorSize);
m_computeCommandList.Get()->SetComputeRootUnorderedAccessView(ComputeRootUAVTable, m_dataBuffer->GetGPUVirtualAddress());
m_computeCommandList.Get()->Dispatch(1, 1, 1);
m_computeCommandList.Get()->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_dataBuffer.Get(), D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_COMMON));
// Close and execute the command list.
DX::ThrowIfFailed(m_computeCommandList.Get()->Close());
ID3D12CommandList* commandLists[] = { m_computeCommandList.Get() };
m_computeCommandQueue->ExecuteCommandLists(1, commandLists);
// Wait for the compute shader to complete the calculation.
UINT64 FenceValue = InterlockedIncrement(&m_FenceValue);
DX::ThrowIfFailed(m_computeCommandQueue.Get()->Signal(m_Fence.Get(), FenceValue));
DX::ThrowIfFailed(m_Fence.Get()->SetEventOnCompletion(FenceValue, m_FenceEvent));
WaitForSingleObject(m_FenceEvent, INFINITE);
std::cout << "FenceValue = " << FenceValue << " " << m_FenceValue << " " << m_Fence.Get()->GetCompletedValue() << std::endl;
// Check the output!
float* dataptr = nullptr;
D3D12_RANGE range = { 0, readbackBufferDesc.Width };
DX::ThrowIfFailed(m_dataBufferReadback->Map(0, &range, (void**)&dataptr));
for (int i = 0; i < readbackBufferDesc.Width / sizeof(data[0]); i++)
printf("uav[%d] = %.2f\n", i, dataptr[i]);
m_dataBufferReadback->Unmap(0, nullptr);
for (unsigned int i = 0; i < data.size(); i++) {
std::cout << "data[" << i << "] = " << data[i] << std::endl;
}
}
myClass.h:
#pragma once
#include "Common\Device.h"
#include <iostream>
// We have to write all of this as its own class, otherwise we cannot
// use the "this" pointer when we create compute resources. We need to
// do that because this code tagets multithreading.
class myClass {
public:
myClass();
private:
// Two buffers full of data are used. The compute thread alternates
// writing to each of them. The render thread renders using the
// buffer that is not currently in use by the compute shader.
//struct Data {
// float c;
//};
//std::vector<Data> data;
std::vector<float> data;
// For the compute pipeline, the CBV is a struct containing some
// constants used in the compute shader.
struct ConstantBufferCS {
float a;
float b;
};
D3D12_SUBRESOURCE_DATA dataSubResource;
static const UINT FrameCount = 1;
//static const UINT ThreadCount = 1;
UINT m_heightInstances;
UINT m_widthInstances;
UINT m_frameIndex;
Microsoft::WRL::ComPtr<ID3D12RootSignature> m_rootSignature;
Microsoft::WRL::ComPtr<ID3D12RootSignature> m_computeRootSignature;
Microsoft::WRL::ComPtr<ID3D12CommandQueue> m_commandQueue;
Microsoft::WRL::ComPtr<ID3D12DescriptorHeap> m_UavHeap;
Microsoft::WRL::ComPtr<ID3D12CommandAllocator> m_commandAllocators[FrameCount];
Microsoft::WRL::ComPtr<ID3D12PipelineState> m_computeState;
Microsoft::WRL::ComPtr<ID3D12GraphicsCommandList> m_commandList;
Microsoft::WRL::ComPtr<ID3D12Resource> m_constantBufferCS;
UINT64 m_renderContextFenceValue;
HANDLE m_renderContextFenceEvent;
UINT64 m_frameFenceValues[FrameCount];
UINT m_UavDescriptorSize;
ConstantBufferCS constantBufferCS;
Microsoft::WRL::ComPtr<ID3D12Resource> constantBufferCSUpload;
Microsoft::WRL::ComPtr<ID3D12Fence> m_renderContextFence;
Microsoft::WRL::ComPtr<ID3D12Resource> m_dataBuffer;
Microsoft::WRL::ComPtr<ID3D12Resource> m_dataBufferUpload;
Microsoft::WRL::ComPtr<ID3D12Resource> m_dataBufferReadback;
// Compute objects.
Microsoft::WRL::ComPtr<ID3D12CommandAllocator> m_computeAllocator;
Microsoft::WRL::ComPtr<ID3D12CommandQueue> m_computeCommandQueue;
Microsoft::WRL::ComPtr<ID3D12GraphicsCommandList> m_computeCommandList;
Microsoft::WRL::ComPtr<ID3D12Fence> m_Fence;
volatile HANDLE m_FenceEvent;
D3D12_RESOURCE_DESC readbackBufferDesc;
// State
UINT64 volatile m_FenceValue;
/*
struct ThreadData {
myClass* pContext;
UINT threadIndex;
};
ThreadData m_threadData;
HANDLE m_threadHandles;
*/
void Calculate();
// Indices of shader resources in the descriptor heap.
enum DescriptorHeapIndex : UINT32 {
Uav = 0,
DescriptorCount = 1
};
enum ComputeRootParameters : UINT32 {
//ComputeRootCBV = 0,
ComputeRootUAVTable = 0,
ComputeRootParametersCount
};
};
Device.cpp:
#pragma once
#include "pch.h"
#include "Device.h"
#include "DirectXHelper.h"
#include <cassert> // for "assert"
#include <iostream>
static Device* gs_pSingelton = nullptr;
// Constructor
Device::Device(HINSTANCE hInst, bool useWarp)
: m_hInstance(hInst)
, m_useWarp(useWarp)
{
}
void Device::Initialize() {
#if defined(_DEBUG)
// Always enable the debug layer before doing anything DX12 related
// so all possible errors generated while creating DX12 objects
// are caught by the debug layer.
Microsoft::WRL::ComPtr<ID3D12Debug1> debugInterface;
DX::ThrowIfFailed(D3D12GetDebugInterface(IID_PPV_ARGS(&debugInterface)));
debugInterface->EnableDebugLayer();
// Enable these if you want full validation (will slow down rendering a lot).
//debugInterface->SetEnableGPUBasedValidation(TRUE);
//debugInterface->SetEnableSynchronizedCommandQueueValidation(TRUE);
#endif
auto dxgiAdapter = GetAdapter(false);
if (!dxgiAdapter) { // If no supporting DX12 adapters exist, fall back to WARP
dxgiAdapter = GetAdapter(true);
}
if (dxgiAdapter) {
m_device = CreateDevice(dxgiAdapter);
}
else {
throw std::exception("DXGI adapter enumeration failed.");
}
}
void Device::Create(HINSTANCE hInst) {
if (!gs_pSingelton) {
gs_pSingelton = new Device(hInst);
gs_pSingelton->Initialize();
}
}
Device& Device::Get() {
assert(gs_pSingelton);
return *gs_pSingelton;
}
void Device::Destroy() {
if (gs_pSingelton) {
delete gs_pSingelton;
gs_pSingelton = nullptr;
}
}
// Destructor
Device::~Device() {
}
Microsoft::WRL::ComPtr<ID3D12Device2> Device::CreateDevice(Microsoft::WRL::ComPtr<IDXGIAdapter4> adapter) {
Microsoft::WRL::ComPtr<ID3D12Device2> d3d12Device2;
DX::ThrowIfFailed(D3D12CreateDevice(adapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&d3d12Device2)));
// Enable debug messages in debug mode.
#if defined(_DEBUG)
Microsoft::WRL::ComPtr<ID3D12InfoQueue> pInfoQueue;
if (SUCCEEDED(d3d12Device2.As(&pInfoQueue))) {
pInfoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_CORRUPTION, TRUE);
pInfoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_ERROR, TRUE);
pInfoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_WARNING, TRUE);
// Suppress whole categories of messages
//D3D12_MESSAGE_CATEGORY Categories[] = {};
// Suppress messages based on their severity level
D3D12_MESSAGE_SEVERITY Severities[] = { D3D12_MESSAGE_SEVERITY_INFO };
// Suppress individual messages by their ID
D3D12_MESSAGE_ID DenyIds[] = {
D3D12_MESSAGE_ID_CLEARRENDERTARGETVIEW_MISMATCHINGCLEARVALUE, // I'm really not sure how to avoid this message.
D3D12_MESSAGE_ID_MAP_INVALID_NULLRANGE, // This warning occurs when using capture frame while graphics debugging.
D3D12_MESSAGE_ID_UNMAP_INVALID_NULLRANGE, // This warning occurs when using capture frame while graphics debugging.
};
D3D12_INFO_QUEUE_FILTER NewFilter = {};
//NewFilter.DenyList.NumCategories = _countof(Categories);
//NewFilter.DenyList.pCategoryList = Categories;
NewFilter.DenyList.NumSeverities = _countof(Severities);
NewFilter.DenyList.pSeverityList = Severities;
NewFilter.DenyList.NumIDs = _countof(DenyIds);
NewFilter.DenyList.pIDList = DenyIds;
DX::ThrowIfFailed(pInfoQueue->PushStorageFilter(&NewFilter));
}
#endif
return d3d12Device2;
}
Microsoft::WRL::ComPtr<IDXGIAdapter4> Device::GetAdapter(bool useWarp) {
UINT createFactoryFlags = 0;
#if defined(_DEBUG)
createFactoryFlags = DXGI_CREATE_FACTORY_DEBUG;
#endif
DX::ThrowIfFailed(CreateDXGIFactory2(createFactoryFlags, IID_PPV_ARGS(&m_factory)));
Microsoft::WRL::ComPtr<IDXGIAdapter1> dxgiAdapter1;
Microsoft::WRL::ComPtr<IDXGIAdapter4> dxgiAdapter4;
if (useWarp) {
DX::ThrowIfFailed(m_factory->EnumWarpAdapter(IID_PPV_ARGS(&dxgiAdapter1)));
DX::ThrowIfFailed(dxgiAdapter1.As(&dxgiAdapter4));
}
else {
SIZE_T maxDedicatedVideoMemory = 0;
for (UINT i = 0; m_factory->EnumAdapters1(i, &dxgiAdapter1) != DXGI_ERROR_NOT_FOUND; ++i) {
DXGI_ADAPTER_DESC1 dxgiAdapterDesc1;
dxgiAdapter1->GetDesc1(&dxgiAdapterDesc1);
// Check to see if the adapter can create a D3D12 device without actually
// creating it. The adapter with the largest dedicated video memory
// is favored.
if ((dxgiAdapterDesc1.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) == 0 &&
SUCCEEDED(D3D12CreateDevice(dxgiAdapter1.Get(),
D3D_FEATURE_LEVEL_11_0, __uuidof(ID3D12Device), nullptr)) &&
dxgiAdapterDesc1.DedicatedVideoMemory > maxDedicatedVideoMemory) {
maxDedicatedVideoMemory = dxgiAdapterDesc1.DedicatedVideoMemory;
DX::ThrowIfFailed(dxgiAdapter1.As(&dxgiAdapter4));
}
}
}
return dxgiAdapter4;
}
Device.h:
#pragma once
#include <dxgi1_6.h> // IDXGIAdapter4
// We require this file because we are unable to pass the device pointer to everywhere we need to.
class Device {
public:
/**
* Create the device singleton with the device instance handle.
*/
static void Create(HINSTANCE hInst);
/**
* Destroy the device instance.
*/
static void Destroy();
/**
* Get the device singleton.
*/
static Device& Get();
/**
* Get the Direct3D 12 device
*/
Microsoft::WRL::ComPtr<ID3D12Device2> GetDevice() const { return m_device; }
Microsoft::WRL::ComPtr<IDXGIFactory4> GetFactory() const { return m_factory; }
protected:
// Create a device instance
Device(HINSTANCE hInst, bool useWarp = false);
// Destroy the device instance.
virtual ~Device();
// Initialize the device instance.
void Initialize();
Microsoft::WRL::ComPtr<IDXGIAdapter4> GetAdapter(bool useWarp);
Microsoft::WRL::ComPtr<ID3D12Device2> CreateDevice(Microsoft::WRL::ComPtr<IDXGIAdapter4> adapter);
private:
Device(const Device& copy) = delete;
Device& operator=(const Device& other) = delete;
HINSTANCE m_hInstance;
Microsoft::WRL::ComPtr<ID3D12Device2> m_device;
Microsoft::WRL::ComPtr<IDXGIFactory4> m_factory;
bool m_useWarp;
};
ComputeShader.hlsl:
RWStructuredBuffer<float> output : register(u0); // UAV
[numthreads(1, 1, 1)]
void main( uint3 DTid : SV_DispatchThreadID ) {
output[DTid.x] = 1 + 1;
}
Please let me know if you are able to find what I do not understand. I can also try uploading my project to GitHub if it helps... SOS :(
there seemed to be a lot of people with the segmentation fault problem but I couldn't seem to find any that related to my program, if there is a thread I'm sorry, I looked through multiple though and couldn't find it.
pretty much everything so far:
#include <SDL.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <string>
#include <time.h>
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
const int maxLandMass = SCREEN_WIDTH * SCREEN_HEIGHT;
const int landPercentage = 30;
const int maxHeight = 200;
const int numAnts = 10;
int main(int argc, char **argv)
{
int currentLandMass = 0;
int ants[numAnts][3]={{0}}; //x,y,pDir (0123,NESW)
std::string rules[numAnts]={0};
std::string rule;
int states = 2;
std::cout << "Which rule would you like to use? ";
std::cin >> rule;
if(rule == "")
{
rule = "RL";
}
else if(rule == "RND" || rule == "rnd")
{
std::cout << "How many states? ";
std::cin >> states;
}
srand(time(NULL));
for(int i = 0;i < numAnts;i++)
{
ants[i][0] = rand() % SCREEN_WIDTH;
ants[i][1] = rand() % SCREEN_HEIGHT;
ants[i][2] = rand() % 4;
if(rule != "RND" && rule != "rnd")
{
rules[i] = rule;
}
else
{
std::string tempRule;
for(int s = 0; s < states; s++)
{
int r = rand() % 2;
if(r == 0){ tempRule += "L"; }
if(r == 1){ tempRule += "R"; }
}
rules[i] = tempRule;
}
std::cout << rules[i] << "\n";
}
SDL_Window* window = NULL;
SDL_Surface* surface = NULL;
if(SDL_Init(SDL_INIT_VIDEO) < 0)
{
printf("SDL could not initialize! SDL_Error: %s\n", SDL_GetError());
}
else
{
window = SDL_CreateWindow("SDL Tutorial", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
if( window == NULL )
{
printf("Window could not be created! SDL_Error: %s\n", SDL_GetError());
}
else
{
surface = SDL_GetWindowSurface(window);
SDL_FillRect(surface, NULL, SDL_MapRGB(surface->format, 0x00, 0x00, 0x00));
SDL_UpdateWindowSurface(window);
}
}
//Uint16 *pixels = (Uint16 *) surface->pixels;
/////////////////////////////
int grid[SCREEN_HEIGHT][SCREEN_WIDTH]={{0}};
int heights[SCREEN_HEIGHT][SCREEN_WIDTH]={{0}};
int prevState = 0;
for(int a = 0; a < numAnts; a++)
{
//TODO add stuff here
}
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
When it runs it should start with a console window to get some input from the user then switch to an SDL window and do its thing, but the console window tells me:
terminate called after throwing an instance of 'std::logic_error'
what():basic_string::_S_construct null not valid
I have a feeling its something to do with how I have initialised (or at least tried to) the arrays.
The part that I added last was the bit below the ////// line I made.
let me know if you will need more info, Ill get it as soon as I can, and I apologise for my programs current state, its messiness is driving me a bit mad too but (until I broke it) it worked :P
You are initializing your array of strings with zeros. That's an invalid initialization.
Interestingly, had you picked any other number, you'd get a clearer error message, telling you that you're doing an invalid conversion from int to const char* (which is a c-style string, and the closest valid input type std::string has a constructor for).
Unfortunately, the zero initialization is confusing your compiler to think you're actually assigning a pointer, which it may convert, but luckily it checks and sees that the pointer is NULL, and therefore bails out with the error message you saw: basic_string::_S_construct null not valid.
I took your code and removed all the SDL part, it compiled and reproduced the error.
I then replaced
std::string rules[numAnts]={0};
with
std::string rules[numAnts];
which uses the default constructor to create empty strings for all elements, and now it seems to work.
I'm trying to get control of the the Xterm with Xlib.
For that i'm making a Xterm with a strange title. After I list all window and check they names. But something is bugged the nammes of my Xterm does not appear when they are listed. Here is the code for list all window :
void CMD::getWindowTerminal()
{
Atom a = XInternAtom(m_display, "_NET_CLIENT_LIST", true);
Atom actualType;
int format;
unsigned long numItems, bytesAfter;
unsigned char *data = 0;
int status = XGetWindowProperty(m_display, m_root_win, a, 0L, (~0L), false,
AnyPropertyType, &actualType, &format, &numItems,
&bytesAfter, &data);
if (status >= Success && numItems)
{
long *array = (long*) data;
for (unsigned long k = 0; k < numItems; k++)
{
// get window Id:
Window w = (Window) array[k];
char* name = '\0';
status = XFetchName(m_display, w, &name);
if (status >= Success)
{
std::cout << w << " " << name << std::endl;
if (name == NULL)
{
m_window_terminal = w;
std::cout << "TERMINAL FOUND" << std::endl;
}
}
XFree(name);
}
XFree(data);
}
}
I cannot reproduce the error; your code finds my xterm windows. Are you querying the window of an xterm you only just spawned? If so, you might have a race condition in that you try to find the window before xterm had a chance of making it. In that case, a crummy solution would be to wait a bit and try again several times.
If that is not the case, I can only speculate (more) about causes (my speculations involve a misbehaving window manager or very old software), but perhaps I can suggest a solution: if the xterm doesn't show up in the root window's _NET_CLIENT_LIST, let's dig directly into the window tree and see if we can find it there. This bit of C code (porting to C++ should not be difficult, and anyway it's enough to try it out) traverses the window tree recursively with XQueryTree, so it queries all windows:
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/keysym.h>
Window window_from_name_search(Display *display, Window current, char const *needle) {
Window retval, root, parent, *children;
unsigned children_count;
char *name = NULL;
/* Check if this window has the name we seek */
if(XFetchName(display, current, &name) > 0) {
int r = strcmp(needle, name);
XFree(name);
if(r == 0) {
return current;
}
}
retval = 0;
/* If it does not: check all subwindows recursively. */
if(0 != XQueryTree(display, current, &root, &parent, &children, &children_count)) {
unsigned i;
for(i = 0; i < children_count; ++i) {
Window win = window_from_name_search(display, children[i], needle);
if(win != 0) {
retval = win;
break;
}
}
XFree(children);
}
return retval;
}
// frontend function: open display connection, start searching from the root window.
Window window_from_name(char const *name) {
Display *display = XOpenDisplay(NULL);
Window w = window_from_name_search(display, XDefaultRootWindow(display), name);
XCloseDisplay(display);
return w;
}
Since it handles all windows, your xterm window has to be among them. If it is not, refer back to the beginning (the bit about a possible race condition). And if that's not it, then something's very strange.
I have a 3rd party .dll (and relative .h and .lib) to control a device via USB.
I want to use the dll functions into a class (AOTF_controller) to implement my desired behaviour.
What I want to do is :
Connect to the device (connect() class function);
Initialize it (init() class function);
Set some parameters (setScanningFreq() class function)
Increase sequentially the frequency of my device (increaseFreq() class function)
Reset and close the USB connection.
I can obtain this behavior when I use the dll functions directly into the _tmain() therefore the device works correctly, but when I wrap the dll functions into a class and try to use the class something goes wrong.
I repeat the above process (list item 1-5) several times: sometimes it works fine, sometimes the program stop and the debugger gives me this error:
First-chance exception at 0x77533fb7 in AOTFcontrollerDebug.exe: 0xC0150014: The activation context activation stack for the running thread of execution is corrupt.
The error seems random, sometimes I can conclude 80 times the scan without any problem, sometimes it gives me error right at the first scan.
I tried to search for that error but I was not able to find anything useful.
Anyone can help? I guess could be related on how the dll functions are called in my class?
Here is the main function code:
// AOTFcontrollerDebug.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "AOTFcontrollerDebug.h"
#include "AOTF_Controller.h"
#include <iostream>
#include <string>
#include <sstream>
#include <AotfLibrary.h>
#define DEFAULT_STARTFREQUENCY 78
#define DEFAULT_ENDFREQUENCY 95.5
#define DEFAULT_NUMOFFRAMES 256
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// The one and only application object
CWinApp theApp;
using namespace std;
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
HMODULE hModule = ::GetModuleHandle(NULL);
if (hModule != NULL)
{
// initialize MFC and print and error on failure
if (!AfxWinInit(hModule, NULL, ::GetCommandLine(), 0))
{
// TODO: change error code to suit your needs
_tprintf(_T("Fatal Error: MFC initialization failed\n"));
nRetCode = 1;
}
else
{
// TODO: code your application's behavior here.
std::cout << "-----AOTF Controller Debugging-----"<<endl;
//input of scans to do
int repeatedScan;
std::cout << "Type how many repeated scan: "<<endl;
std::cin >> repeatedScan;
//instance
AOTF_Controller m_AOTF_Controller;
std::cout << "AOTF Controller instance done..."<<endl;
//loop over scans
for(int i =0;i<repeatedScan;i++)
{
m_AOTF_Controller.connect();
std::cout << "AOTF Controller connected..."<<endl;
std::cout << "Scan number : "<< (i + 1) <<endl;
m_AOTF_Controller.init();
//set the delta freq to increase at each step
m_AOTF_Controller.setScanningFreq(DEFAULT_STARTFREQUENCY, DEFAULT_ENDFREQUENCY, DEFAULT_NUMOFFRAMES);
//loop over wavelengths
int sleep_ms = 4;
for (int j =0; j <DEFAULT_NUMOFFRAMES; j++)
{
Sleep(sleep_ms) ;
m_AOTF_Controller.increaseFreq();
//std::cout << " "<< (j + 1) ;
}
// terminate scans
m_AOTF_Controller.reset();
m_AOTF_Controller.disconnect();
std::cout << endl <<"Scan number "<< (i + 1) << "terminated successfully" <<endl;
Sleep(sleep_ms*100) ;
}
}
}
else
{
// TODO: change error code to suit your needs
_tprintf(_T("Fatal Error: GetModuleHandle failed\n"));
nRetCode = 1;
}
return nRetCode;
}
and here the Aotf_Controller class code:
//Aotf_Controller.h
#pragma once
#include <AotfLibrary.h>
#include <string>
#include <sstream>
#include <iomanip>
#define CONVERSION_MHZ_TO_HZ 1000000
class AOTF_Controller
{
private:
enum Error {SUCCESSFUL , CONNECTION_ERROR, DISCONNECTION_ERROR, INIT_ERROR, RESET_ERROR , SET_ERROR }; // error enum values
HANDLE hAotfController;
int currentGain;
long currentFreq; // current frequency in Hz
long startFreq, endFreq, deltaFreq; // frequency values for the scanning in Hz
public:
AOTF_Controller(void);
~AOTF_Controller(void);
AOTF_Controller::Error connect();
AOTF_Controller::Error disconnect();
AOTF_Controller::Error init();
AOTF_Controller::Error setFreq(float freq); // for frequency value in MHZ (precision to the 3rd decimal i.e. KHz)
AOTF_Controller::Error setFreq(long freq); // for frequency value in Hz
AOTF_Controller::Error setGain(int gain);
AOTF_Controller::Error reset();
AOTF_Controller::Error setScanningFreq(float _startFreq, float _endFreq, int numOfFrames);
AOTF_Controller::Error increaseFreq();
};
//Aotf_Controller.cpp
#include "StdAfx.h"
#include "AOTF_Controller.h"
AOTF_Controller::AOTF_Controller(void)
{
currentGain = 0;
currentFreq = 0;
startFreq = 0;
endFreq = 0;
deltaFreq = 0;
hAotfController = NULL;
}
AOTF_Controller::~AOTF_Controller(void)
{
}
AOTF_Controller::Error AOTF_Controller::connect()
{
int iInstance = 0;
hAotfController = AotfOpen(iInstance);
if (!hAotfController)
{
return CONNECTION_ERROR;
}
else
{
return SUCCESSFUL;
}
}
AOTF_Controller::Error AOTF_Controller::disconnect()
{
if (!AotfClose (hAotfController))
{
return DISCONNECTION_ERROR;
}
else
{
hAotfController = NULL;
return SUCCESSFUL;
}
}
AOTF_Controller::Error AOTF_Controller::init()
{
std::string ampCom="dds a 0 16383\r"; //Command to set the amplitude parameter to the max
std::string modCom="mod dac * 16383\r";//Command to set the dac parameter to the max
int gain = 255; // set the gain to the max
if (!AotfWrite(hAotfController, ampCom.length(), (char *)ampCom.c_str()))
{
return Error::INIT_ERROR;
}
if (!AotfWrite(hAotfController, modCom.length(), (char *)modCom.c_str()))
{
return INIT_ERROR;
}
setGain(gain);
return SUCCESSFUL;
}
AOTF_Controller::Error AOTF_Controller::reset()
{
std::string resetCom = "dds reset\r";
if(!AotfWrite(hAotfController, resetCom.length() , (char *)resetCom.c_str()))
{
return RESET_ERROR;
}
return SUCCESSFUL;
}
AOTF_Controller::Error AOTF_Controller::setFreq(float freq)
{
long freqHz = (long)freq*CONVERSION_MHZ_TO_HZ;
setFreq(freqHz);
return SUCCESSFUL;
}
AOTF_Controller::Error AOTF_Controller::setFreq(long freq)
{
std::ostringstream oss; //stream to build the string
//building the string for the Frequency
oss << "dds f 0 !" << std::fixed << std::setprecision(0) << freq << "\r";
std::string freqCom = oss.str();
//send command to the AOTF
if(!AotfWrite(hAotfController, freqCom.length(), (char *) freqCom.c_str())) // set the frequency (80-120)
{
return SET_ERROR;
}
currentFreq = freq; // update monitoring variable in HZ
return Error::SUCCESSFUL;
}
AOTF_Controller::Error AOTF_Controller::setGain(int gain)
{
std::ostringstream oss; //stream to build the string
//building the string for the Gain
oss << "dds gain -p* * " << gain << "\r";
std::string gainCom = oss.str();
//send command to the AOTF
if(!AotfWrite(hAotfController, gainCom.length(), (char * )gainCom.c_str())) // set the gain (0-255)
{
return SET_ERROR;
}
currentGain = gain;
return SUCCESSFUL;
}
AOTF_Controller::Error AOTF_Controller::setScanningFreq(float _startFreq, float _endFreq, int numOfFrames)
{
float FreqRange = (_endFreq - _startFreq); //calculate range
//calculate DeltaFrequency (frequency increase after each captured frame)
deltaFreq = (long) ((FreqRange/(float)(numOfFrames-1))*(float)CONVERSION_MHZ_TO_HZ); //conversion from MHz to Hz
startFreq = (long) (_startFreq*CONVERSION_MHZ_TO_HZ);
endFreq = (long) (_endFreq*CONVERSION_MHZ_TO_HZ);
setFreq(_startFreq);
return SUCCESSFUL;
}
AOTF_Controller::Error AOTF_Controller::increaseFreq()
{
if (deltaFreq ==0)
{
return SET_ERROR;
}
long newFreq = currentFreq + deltaFreq;
std::ostringstream oss;
oss << "dds f 0 !" << std::fixed << std::setprecision(0) << newFreq << "\r";
std::string freqCom = oss.str();
//send command to the AOTF
if(!AotfWrite(hAotfController, freqCom.length(), (char *)freqCom.c_str())) // set the frequency (80-120)value
{
return SET_ERROR;
}
currentFreq = newFreq;
return SUCCESSFUL;
}
When I try to view 3D files (.3ds .dae etc ...), supported by Assimp, they are not displayed correctly. For example, "Jeep1.3ds" displayed me half the bodywork.
All nodes of information, meshes and normal were obtained correctly, and the number of vertices and faces are correct (I think).
Textures not meet the correct coordinates, I guess will be related to the above ...
In the picture you can "appreciate" my result and correct.
Thanks for any help or opinion.
Ogre code
Ogre::SceneNode *OgreAPP::makeMesh(Ogre::String meshFile,Ogre::String entityName,Ogre::String meshName)
{
Ogre::MeshPtr Mesh = Ogre::MeshManager::getSingleton().createManual(meshName,Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
Ogre::SubMesh *subMesh = Mesh->createSubMesh("subMesh");
Ogre::VertexDeclaration *vertexDeclaration;
Ogre::HardwareVertexBufferSharedPtr vertexBuffer;
Ogre::HardwareIndexBufferSharedPtr indexBuffer;
size_t offset=0;
// Get file name and extension from the Ogre Resource Manager
Ogre::FileInfoListPtr fileInfoListPtr(Ogre::ResourceGroupManager::getSingleton().findResourceFileInfo(Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,meshFile,false));
Ogre::FileInfoList *fileInfoList = fileInfoListPtr.getPointer();
Ogre::FileInfo &fileInfo = fileInfoList->front();
stringBuffer << fileInfo.archive->getName().c_str() << meshFile;
// ************** From Assimp code ***************************
ModelManager::loadModel(stringBuffer.str());
ModelManager::processData();
std::vector<float> *vData = ModelManager::getVertexData();
std::vector<uint16_t> *iData = ModelManager::getIndexData();
// ********************************************************************
Mesh->sharedVertexData = new Ogre::VertexData;
// Organizo la memoria de video
vertexDeclaration = Mesh->sharedVertexData->vertexDeclaration;
vertexDeclaration->addElement(0,offset,Ogre::VET_FLOAT3,Ogre::VES_POSITION);
offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3);
vertexDeclaration->addElement(0,offset,Ogre::VET_FLOAT3,Ogre::VES_NORMAL);
offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3);
vertexDeclaration->addElement(0,offset,Ogre::VET_FLOAT2,Ogre::VES_TEXTURE_COORDINATES);
offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT2);
// Make vertex buffer
vertexBuffer = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer(vertexDeclaration->getVertexSize(0),
vData->size()/8,
Ogre::HardwareBuffer::HBU_STATIC);
// Write the vertex buffer with the target data of vData->data() located in assimp code
vertexBuffer.getPointer()->writeData(0,vertexBuffer.getPointer()->getSizeInBytes(),vData->data());
// Make index buffer
indexBuffer = Ogre::HardwareBufferManager::getSingleton().createIndexBuffer(Ogre::HardwareIndexBuffer::IT_16BIT,
iData->size(),
Ogre::HardwareBuffer::HBU_STATIC);
indexBuffer.getPointer()->writeData(0,indexBuffer.getPointer()->getSizeInBytes(),iData->data());
Mesh->sharedVertexData->vertexBufferBinding->setBinding(0,vertexBuffer);
Mesh->sharedVertexData->vertexCount = vertexBuffer.getPointer()->getNumVertices();
Mesh->sharedVertexData->vertexStart = 0;
subMesh->useSharedVertices = true;
subMesh->indexData->indexBuffer = indexBuffer;
subMesh->indexData->indexCount = indexBuffer.getPointer()->getNumIndexes();
subMesh->indexData->indexStart = 0;
// I don't get real AABB from object, this is ok for probe
Mesh->_setBounds(Ogre::AxisAlignedBox(-100,-100,-100,100,100,100));
Mesh->load();
stringBuffer.str("");
stringBuffer << entityName << "_n";
oSceneManager->createEntity(entityName,meshName);
oSceneManager->getEntity(entityName)->setMaterialName("material/textura");
oSceneManager->getRootSceneNode()->createChildSceneNode(stringBuffer.str().c_str())->attachObject(oSceneManager->getEntity(entityName));
oSceneManager->getSceneNode(stringBuffer.str().c_str())->setPosition(0,0,0);
std::cout << "total de vertices: " << vData->size()/8 << "\n";
std::cout << "total de faces: " <<indexBuffer.getPointer()->getNumIndexes()/3 << "\n";
return oSceneManager->getSceneNode(stringBuffer.str().c_str());
}
Assimp .CPP
bool ModelManager::loadModel(std::string &file)
{
modelScene = importer.ReadFile(file,aiProcess_Triangulate |
aiProcess_GenNormals |
aiProcess_GenUVCoords);
if (!modelScene)
{
MessageBoxA(NULL,importer.GetErrorString(),"Error: La concha de la lora",MB_ICONERROR);
return false;
}
return true;
}
bool ModelManager::assimpGetMeshData(const aiMesh *mesh)
{
aiFace *face;
for (unsigned int v=0;v<mesh->mNumVertices;v++)
{
vertexBuff.push_back(mesh->mVertices[v].x);
vertexBuff.push_back(mesh->mVertices[v].y);
vertexBuff.push_back(mesh->mVertices[v].z);
vertexBuff.push_back(mesh->mNormals[v].x);
vertexBuff.push_back(mesh->mNormals[v].y);
vertexBuff.push_back(mesh->mNormals[v].z);
vertexBuff.push_back(mesh->mTextureCoords[0][v].x);
vertexBuff.push_back(mesh->mTextureCoords[0][v].y);
}
for (unsigned int f=0;f<mesh->mNumFaces;f++)
{
face = &mesh->mFaces[f];
indexBuff.push_back(face->mIndices[0]);
indexBuff.push_back(face->mIndices[1]);
indexBuff.push_back(face->mIndices[2]);
}
return true;
}
bool ModelManager::processData()
{
bool repeat=true;
nodeBuff.push_back(modelScene->mRootNode);
/* if (modelScene->mNumMeshes > 0)
{
for (unsigned int m=0;m<modelScene->mNumMeshes;m++)
this->assimpGetMeshData(modelScene->mMeshes[m]);
}*/
// I raise all nodes tree to the root level
while (repeat)
{
for (unsigned int a=0;a<nodeBuff.size();a++)
{
modelNode = nodeBuff.at(a);
if (modelNode->mNumChildren > 0)
for (unsigned int c=0;c<modelNode->mNumChildren;c++)
nodeBuff.push_back(modelNode->mChildren[c]);
else repeat=false;
}
}
// Get node information from the root level (all nodes)
for (unsigned int a=0;a<nodeBuff.size();a++)
{
modelNode = nodeBuff.at(a);
if (modelNode->mNumMeshes>0)
for (unsigned int b=0;b<modelNode->mNumMeshes;b++)
assimpGetMeshData(modelScene->mMeshes[modelNode->mMeshes]);
}
return true;
}
std::vector<float> *ModelManager::getVertexData()
{
return &vertexBuff;
}
std::vector<uint16_t> *ModelManager::getIndexData()
{
return &indexBuff;
}
Assimp .H
#include <assimp/Importer.hpp>
#include <assimp/scene.h>
#include <assimp/postprocess.h>
#include <assimp/matrix4x4.h>
#include <assimp/cimport.h>
#include <Windows.h>
#include <iostream>
#include <stdint.h>
#include <vector>
class ModelManager
{
public:
ModelManager();
bool loadModel(std::string &);
bool processData();
std::vector<float> *getVertexData();
std::vector<uint16_t> *getIndexData();
private:
bool assimpGetMeshData(const aiMesh *);
private:
Assimp::Importer importer;
const aiScene *modelScene;
const aiNode *modelNode;
const aiMesh *modelMesh;
const aiFace *modelFace;
std::vector<float> vertexBuff;
std::vector<uint16_t> indexBuff;
std::vector<const aiNode*> nodeBuff;
unsigned int numNodeBuff;
};
Ok ... errors, as they spend most of the time, in practice something small and basic but complex background.
"Simply" switch the coordinate system, when I import the file would have to be specified Assimp flags "aiProcess_MakeLeftHanded | aiProcess_FlipWindingOrder | aiProcess_FlipUVs" or "aiProcess_ConvertToLeftHanded".
Other than that I missed some transformation matrices (they had not considered), for that I use the flag "aiProcess_PreTransformVertices".
Apparently everything works fine ...
New code
bool ModelManager::loadModel(std::string &file)
{
modelScene = importer.ReadFile(file,aiProcess_MakeLeftHanded|aiProcess_FlipWindingOrder|aiProcess_FlipUVs|aiProcess_PreTransformVertices|
aiProcess_CalcTangentSpace|
aiProcess_GenSmoothNormals|
aiProcess_Triangulate|
aiProcess_FixInfacingNormals|
aiProcess_FindInvalidData |
aiProcess_ValidateDataStructure | 0
);
if (!modelScene)
{
MessageBoxA(NULL,importer.GetErrorString(),"Error: La concha de la lora...",MB_ICONERROR);
return false;
}
return true;
}