Skip navigation

Monthly Archives: August 2011

LightWave 3D OBJ Export v2.1 is completely screwed up

In this model I have, it does the most ODD things.

One thing it does (but this is valid, just I didn’t expect it) is it uses negative texcoord indices sometimes (so f 5/-1 126/-2 140/-3 52/-4). Negative indices just means to use the last vt, 2nd last vt, etc.

The thing it does apparently wrong is it DOES NOT include any newmtl statements, or a mtllib file, and it uses usemtl statements as if they are _IMAGE FILENAMES_ (really its supposed to be map_kd, or map_ka).

The quick fix is to add code:
– if usemtl is attempted but that mtl doesn’t exist, create it and see if there is an image with the same filename as the mtl. If there is, load it and use it for that mtl.
– check the vt index and if it is negative, use the -whatever vt coordinate from your current point in the file

These aren’t _that bad_, but they really should follow the file format correctly

Also, it exports non-convex polygons.

Advertisements

if( sh ) then: puts( “Yeah it was sh” ) ;

D3D9 Vertex buffer and index buffer sample code

//
// Nice MSDN article on vertex/index buffer draw scenarios
// http://msdn.microsoft.com/en-us/library/bb147325(VS.85).aspx
//

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#include <d3d9.h>      // core direct3d
#include <d3dx9.h>     // aux libs

#include <dxerr.h>    // detailed error messages

#pragma comment(lib, "d3d9.lib")
#pragma comment(lib, "d3dx9.lib")  // aux libs
#ifdef _DEBUG
#pragma comment(lib,"d3dx9d.lib")
#else
#pragma comment(lib,"d3dx9.lib")
#endif

#pragma comment(lib, "dxerr.lib")

// Macros.
#define SAFE_RELEASE(ptr) if(ptr) { ptr->Release(); ptr = NULL; }
#define CAST_AS_DWORD(x) *((DWORD*)&x)
#define PI 3.14159

#pragma region define the Vertex structure
struct Vertex
{
  float x,y,z ;
  DWORD color ;

  // Ctor starts you at origin in black
  // with alpha (opacity) set to 100%
  Vertex()
  {
    x=y=z = 0.0f;
    color = D3DCOLOR_XRGB( 0,0,0 ) ;
  }

  Vertex( float ix, float iy, float iz )
  {
    x=ix;y=iy;z=iz;
    color = D3DCOLOR_XRGB( 255,255,255 ) ;
  }

  // Ctor.
  Vertex( float ix, float iy, float iz,
    unsigned char ir, unsigned char ig, unsigned char ib )
  {
    x=ix;y=iy;z=iz;
    color = D3DCOLOR_XRGB( ir, ig, ib ) ;
  }

  // Ctor that lets you pick alpha
  Vertex( float ix, float iy, float iz,
    unsigned char ir, unsigned char ig, unsigned char ib, unsigned char ALPHA )
  {
    x=ix;y=iy;z=iz;
    color = D3DCOLOR_ARGB( ALPHA, ir, ig, ib ) ;
  }
} ;
#pragma endregion

struct Globals
{
  struct _Win
  {
    HINSTANCE hInstance;    // window app instance
    HWND hwnd;              // handle for the window
    HWND hConsole ;         // handle for the console window

    int width, height;
  } win ;

  IDirect3D9 * d3d ;
  IDirect3DDevice9 * gpu ; 

  // Vertex buffer contains the vertices
  IDirect3DVertexBuffer9 *vb ;
  IDirect3DIndexBuffer9 *ib ; // order to draw the vertices in
};

///////////////////////////
// GLOBALS
Globals g;

///////////////////////////
// FUNCTION PROTOTYPES
inline bool CHECK( HRESULT hr, char * msg, bool stop=true ) ;  // checks for errors on the HR passed.
bool initD3D() ;         // function to initialize the BEAST that is Direct3D9
void update() ;          // changes geometry of the scene
void drawAxes() ;        // draws the ever-important axes (for finding your way around your own scene!)
void draw() ;            // drawing function containing Direct3D drawing calls

LRESULT CALLBACK WndProc( HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam );
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLine, int iCmdShow );

/////////////////////////
// FUNCTION IMPLEMENTATIONS
inline bool CHECK( HRESULT hr, char * msg, bool stop )
{
  if( FAILED( hr ) )
  {
    printf( "%s. %s:  %s\n",
            msg, DXGetErrorStringA( hr ), DXGetErrorDescriptionA( hr ) ) ;

    // Pause so we can see the error and deal with it.
    if( stop )  system("pause") ;

    return false ;
  }

  else
    return true ;

}

/// Initializes Direct3D9.  Returns true on success.
bool initD3D()
{
  // start by nulling out both pointers:
  g.d3d = 0 ;
  g.gpu = 0 ;

  g.d3d = Direct3DCreate9( D3D_SDK_VERSION ) ;

  if( g.d3d == NULL )
  {
    // DEVICE CREATION FAILED!!!! OH NO!!!
    puts( "Oh.. PHOOEY!!!!!  Device creation FAILED!!! WHAT NOW???\n" ) ;
    return false ;
  }

  puts( "Direct3D9 creation success!" ) ;

  D3DPRESENT_PARAMETERS pps = { 0 } ;

  pps.Windowed = true ;
  pps.BackBufferCount = 1 ;
  pps.SwapEffect = D3DSWAPEFFECT_DISCARD ;
  pps.BackBufferFormat = D3DFMT_UNKNOWN ;
  pps.EnableAutoDepthStencil = true ;
  pps.AutoDepthStencilFormat = D3DFMT_D16 ;

  HRESULT hr = g.d3d->CreateDevice(

    D3DADAPTER_DEFAULT, // primary display adapter
    D3DDEVTYPE_HAL,     // use HARDWARE rendering (fast!)
    g.win.hwnd,
    D3DCREATE_HARDWARE_VERTEXPROCESSING,
    &pps,
    &g.gpu

  ) ;

  if( !CHECK( hr, "OH NOS!! I could not initialize Direct3D!  Bailing...\n" ) )
  {
    return false ;
  }

  puts( "Direct3D9 GPU device creation successful" ) ;

  hr = g.gpu->SetFVF( D3DFVF_XYZ | D3DFVF_DIFFUSE ) ;
  CHECK( hr, "SetFVF FAILED!" ) ;

  D3DVERTEXELEMENT9 pos ;

  pos.Usage = D3DDECLUSAGE_POSITION ;
  pos.UsageIndex = 0 ;
  pos.Stream = 0 ;
  pos.Type = D3DDECLTYPE_FLOAT3 ;
  pos.Offset = 0 ;

  pos.Method = D3DDECLMETHOD_DEFAULT ; 

  D3DVERTEXELEMENT9 col;

  col.Usage = D3DDECLUSAGE_COLOR ;
  col.UsageIndex = 0 ;
  col.Stream = 0 ;
  col.Type = D3DDECLTYPE_D3DCOLOR ;
  col.Offset = 3*sizeof( float ) ;
  col.Method = D3DDECLMETHOD_DEFAULT ;

  D3DVERTEXELEMENT9 vertexElements[] =
  {
    pos,
    col,

    D3DDECL_END()

  } ;

  IDirect3DVertexDeclaration9 * Vdecl ;

  hr = g.gpu->CreateVertexDeclaration( vertexElements, &Vdecl ) ;
  CHECK( hr, "CreateVertexDeclaration FAILED!" ) ;

  hr = g.gpu->SetVertexDeclaration( Vdecl ) ;
  CHECK( hr, "SetVertexDeclaration FAILED!" ) ;

  hr = g.gpu->SetRenderState( D3DRS_COLORVERTEX, TRUE ) ;
  CHECK( hr, "SetRenderState( COLORVERTEX ) FAILED!" ) ;

  hr = g.gpu->SetRenderState( D3DRS_LIGHTING, FALSE ) ;
  CHECK( hr, "Lighting off" ) ;

  hr = g.gpu->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE ) ;
  CHECK( hr, "cull mode off" ) ;






  int vbSize = 3*sizeof( Vertex );


  // CReate a vertex buffer
  // http://msdn.microsoft.com/en-us/library/bb174364(VS.85).aspx
  g.gpu->CreateVertexBuffer(
    vbSize,  // Length: Size of the vertex buffer, in bytes.
    0,       // Usage: 0 for when using hardware vertex processing (which we are!)
    0,       // FVF: I'm not using FVF, (I used a custom vertex declaration above)
    D3DPOOL_MANAGED, // D3DPOOL. Using a managed pool is good because it automatically
    // mirrors your data on the gpu and in system memory (so if the device is lost,
    // you don't have to re-create the vb)
    &g.vb,   // the vertex buffer
    NULL );  // always NULL

  Vertex* vbData ;
  // http://msdn.microsoft.com/en-us/library/bb205917(VS.85).aspx
  CHECK( g.vb->Lock(
    0, //Offset into the vertex data to lock, in bytes
    0,  // SECRET MSDN TIP:  "To lock the entire vertex buffer, specify 0 for both (OffsetToLock,SizeToLock) parameters"
    (void**)&vbData,
    0 // no special flags
  ), "Lock vb" ) ;
  {
    // write the data in. The vertex buffer is locked now,
    // and must be unlocked before we can draw it.
    vbData[ 0 ] = Vertex( -1, 0, 0, 255, 19, 0 ) ; // Red vertex @ ( -1, 0, 0 )
    vbData[ 1 ] = Vertex(  0, 1, 0, 0, 255, 0 ) ;  // Green vertex @ ( 0, 1, 0 )
    vbData[ 2 ] = Vertex(  1, 0, 0, 0, 0, 255 ) ;  // Blue vertex @ ( 1, 0, 0 )
  }
  CHECK( g.vb->Unlock(), "Unlock vb" ) ;




  // Create the index buffer
  CHECK( g.gpu->CreateIndexBuffer( 
    3*sizeof( short ), // size of index buffer, in bytes.  notice i have commited to use 16-bit indices here (I'm not
    // drawing more than 65536 vertices per draw call..)
    0, // Usage
    D3DFMT_INDEX16, // I'm using 16-bit indices
    D3DPOOL_MANAGED,
    &g.ib,
    NULL
  ), "Create index buffer" ) ;

  short* ibData ;
  CHECK( g.ib->Lock( 0, 0, (void**)&ibData, 0 ), "Lock ib" ) ;
  {
    ibData[0] = 0 ;
    ibData[1] = 1 ;
    ibData[2] = 2 ;
  }
  CHECK( g.ib->Unlock(), "Unlock ib" ) ;
  



  return true ;
}

void update()
{
}

////////////////////////
// DRAWING FUNCTIONS
void drawAxes()
{

  static float axisLen = 2.0f ;
  static Vertex axis[] = {

    // x-axis is red
    Vertex( -axisLen, 0, 0, 255, 0, 0 ),
    Vertex( +axisLen, 0, 0, 255, 0, 0 ),

    // y-axis green
    Vertex( 0, -axisLen, 0, 0, 255, 0 ),
    Vertex( 0, +axisLen, 0, 0, 255, 0 ),

    // z-axis blue
    Vertex( 0, 0, -axisLen, 0, 0, 255 ),
    Vertex( 0, 0, +axisLen, 0, 0, 255 )

  } ;

  HRESULT hr = g.gpu->DrawPrimitiveUP( D3DPT_LINELIST, 3, axis, sizeof( Vertex ) ) ;
  CHECK( hr, "DrawPrimitiveUP FAILED!" ) ;

  static float pointSize = 8.0f ;

  g.gpu->SetRenderState( D3DRS_POINTSIZE, CAST_AS_DWORD( pointSize ) ) ;

  // Draw points at end of axis.
  static Vertex points[] = {
    Vertex( axisLen, 0, 0, 255, 0, 0 ),
    Vertex( 0, axisLen, 0, 0, 255, 0 ),
    Vertex( 0, 0, axisLen, 0, 0, 255 ),
  } ;

  hr = g.gpu->DrawPrimitiveUP( D3DPT_POINTLIST, 3, points, sizeof( Vertex ) ) ;
  CHECK( hr, "DrawPrimitiveUP FAILED!" ) ;

}

void draw()
{
  HRESULT hr ;

  hr = g.gpu->Clear( 0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
    D3DCOLOR_ARGB( 255, 25, 25, 25 ), 1.0f, 0 ) ;
  CHECK( hr, "Clear FAILED!" ) ;

  #pragma region set up the camera
  D3DXMATRIX projx ;

  D3DXMatrixPerspectiveFovRH( &projx, PI/4, (float)g.win.width/g.win.height, 1.0f, 1000.0f ) ;

  g.gpu->SetTransform( D3DTS_PROJECTION, &projx ) ;

  D3DXMATRIX viewx ;

  D3DXVECTOR3 eye( 4, 2, 4 ) ;
  D3DXVECTOR3 look( 0, 0, 0 ) ;
  D3DXVECTOR3 up( 0, 1, 0 ) ;
  D3DXMatrixLookAtRH( &viewx, &eye, &look, &up ) ;
  g.gpu->SetTransform( D3DTS_VIEW, &viewx ) ;
  #pragma endregion

  hr = g.gpu->BeginScene() ;
  CHECK( hr, "BeginScene FAILED!" ) ;

  #pragma region ACTUALLY __draw__

  drawAxes();

  // DRAW
  
  g.gpu->SetStreamSource( 0, g.vb, 0, sizeof( Vertex ) ) ; // SET THE VERTEX BUFFER
  //CHECK( g.gpu->DrawPrimitive( D3DPT_TRIANGLELIST, 0, 1 ), "Draw raw vb" ) ; // You can draw from the vertex buffer directly

  g.gpu->SetIndices( g.ib ) ;  // SET THE INDEX BUFFER

  // DrawIndexedPrimitive: http://msdn.microsoft.com/en-us/library/bb174369(VS.85).aspx
  CHECK( g.gpu->DrawIndexedPrimitive(
    D3DPT_TRIANGLELIST,
    0, // BaseVertexIndex: Offset from the start of the vertex buffer to the first vertex
    0, // MinIndex: Minimum vertex index for vertices used during this call. This is a zero based index relative to BaseVertexIndex.
    3, // NumVertices: Number of vertices used during this call. The first vertex is located at index: BaseVertexIndex + MinIndex.
    0, // StartIndex: Index of the first index to use when accesssing the vertex buffer. Beginning at StartIndex to index vertices from the vertex buffer.
    1  // PrimitiveCount: Number of primitives to render.
  ), "Draw indexed prim" ) ; // or you can draw using the index buffer as well

  #pragma endregion

  hr = g.gpu->EndScene() ;
  CHECK( hr, "EndScene FAILED!" ) ;

  // And finally, PRESENT what we drew to the backbuffer
  g.gpu->Present( 0, 0, 0, 0 ) ;

}

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLine, int iCmdShow )
{
  //////////////////
  // First we'll start by saving a copy of
  // the hInstance parameter inside our
  // "glob" of globals "g":
  g.win.hInstance = hInstance;
  // In case we need it later, we'll have it
  // with firsthand easy access.

  #pragma region part 0 - attach a console
  // Attach a console
  AllocConsole();
  AttachConsole( GetCurrentProcessId() ) ;
  freopen( "CON", "w", stdout ) ; // redirect stdout to console
  freopen( "CON", "w", stderr ) ; // redirect stderr to console

  // Move the console over to the top left
  g.win.hConsole = GetConsoleWindow();
  MoveWindow( g.win.hConsole, 0, 0, 400, 400, true ) ;

  printf( "* * Computer Program Begin * *\n" ) ;
  #pragma endregion

  #pragma region part 1 - create a window
  // The next few lines you should already
  // be used to:  create a WNDCLASSEX
  // that describes the properties of
  // the window we're going to soon create.
  // A.  Create the WNDCLASSEX
  WNDCLASSEX wcx = { 0 } ;
  wcx.cbSize = sizeof( WNDCLASSEX );
  wcx.hbrBackground = (HBRUSH)GetStockObject( BLACK_BRUSH );
  wcx.hCursor = LoadCursor( NULL, IDC_ARROW );
  wcx.hIcon = LoadIcon( NULL, IDI_APPLICATION );
  wcx.hInstance = hInstance;
  wcx.lpfnWndProc = WndProc;
  wcx.lpszClassName = TEXT("Philip");
  wcx.lpszMenuName = 0;
  wcx.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;

  // Register that class with the Windows O/S..
  RegisterClassEx( &wcx );

  int width = 800, height = 600;
  int leftEdge = 400, topEdge = 25 ;
  RECT rect;
  SetRect( &rect,
    leftEdge,  // left
    topEdge,   // top
    leftEdge + width, // right
    topEdge  + height ); // bottom

  // Save width and height off.
  g.win.width = rect.right - rect.left;
  g.win.height = rect.bottom - rect.top;

  // Adjust it.
  DWORD windowStyle = WS_OVERLAPPEDWINDOW ; // typical features of a normal window
  DWORD windowExStyle = 0 ; // I want the window to be topmost

  AdjustWindowRectEx( &rect, windowStyle, false, windowExStyle );

  g.win.hwnd = CreateWindowEx(
    windowExStyle,
    TEXT("Philip"),
    TEXT("DIRECT3D WINDOW"),
    windowStyle,
    rect.left, rect.top,  // adjusted x, y positions
    rect.right - rect.left, rect.bottom - rect.top,  // adjusted width and height
    NULL, NULL,
    hInstance, NULL);

  // check to see that the window
  // was created successfully!
  if( g.win.hwnd == NULL )
  {
    FatalAppExit( NULL, TEXT("CreateWindow() failed!") );
  }

  // and show.
  ShowWindow( g.win.hwnd, iCmdShow );

  // JUMP to the initD3D() method.
  if( !initD3D() )
  {
    FatalAppExit( 0, TEXT("SORRY!!!  DEVICE CREATION FAILED!!! YOU LOSE, WITHOUT EVEN PLAYING THE GAME!!!" ) ) ;
  }

  #pragma endregion

  #pragma region message loop
  MSG msg;

  while( 1 )
  {
    if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
    {
      if( msg.message == WM_QUIT )
      {
        break;
      }

      TranslateMessage( &msg );
      DispatchMessage( &msg );
    }
    else
    {
      update();
      draw();
    }
  }
  #pragma endregion

  //////////////
  // clean up
  SAFE_RELEASE( g.gpu ) ;
  SAFE_RELEASE( g.d3d ) ;

  // and a cheesy fade exit
  AnimateWindow( g.win.hwnd, 200, AW_HIDE | AW_BLEND );

  printf( "* * This Computer Program Has Ended * *\n" ) ;

  return msg.wParam;
}

////////////////////////
// WNDPROC
// Notice that WndProc is very very neglected.
// We hardly do anything with it!  That's because
// we do all of our processing in the draw()
// function.
LRESULT CALLBACK WndProc(   HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam )
{
  switch( message )
  {
  case WM_CREATE:
    Beep( 50, 10 );
    return 0;
    break;

  case WM_PAINT:
    {
      HDC hdc;
      PAINTSTRUCT ps;
      hdc = BeginPaint( hwnd, &ps );
      // don't draw here.  would be waaay too slow.
      // draw in the draw() function instead.
      EndPaint( hwnd, &ps );
    }
    return 0;
    break;

  case WM_KEYDOWN:
    switch( wparam )
    {
    case VK_ESCAPE:
      PostQuitMessage( 0 );
      break;
    default:
      break;
    }
    return 0;

  case WM_SIZE:
    {
      int width = LOWORD( lparam ) ;
      int height = HIWORD( lparam ) ;
      printf( "RESIZED TO width=%d height=%d\n", width, height ) ;
    }
    break;

  case WM_DESTROY:
    PostQuitMessage( 0 ) ;
    return 0;
    break;
  }

  return DefWindowProc( hwnd, message, wparam, lparam );
}

Its not hard

Using Rich Edit controls
How to format text in rich edit controls

#include <windows.h>
#include <CommCtrl.h>
#include <Richedit.h>
#include <stdio.h>

HWND main, re;
#pragma comment( lib, "comctl32.lib" )

LRESULT CALLBACK WndProc( HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam );
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLine, int iCmdShow );


void setColor( HWND richEditCtrl, COLORREF textColor, COLORREF bgColor )
{
  CHARFORMAT2 cf ;

  cf.cbSize = sizeof( CHARFORMAT2 ) ;
  cf.dwMask = CFM_COLOR | CFM_BACKCOLOR | CFM_EFFECTS2 ; // I'm setting only the style information
  
  cf.crTextColor = textColor ;
  cf.crBackColor = bgColor ;
  cf.dwEffects = CFE_BOLD ;
  
  SendMessage( richEditCtrl, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf ) ;
}

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPInst, char* line, int show)
{
	InitCommonControls() ;
  LoadLibrary(TEXT("Msftedit.dll"));
  

  WNDCLASSEX wc = { 0 };
  wc.cbSize = sizeof( WNDCLASSEX ) ;
  wc.hbrBackground = (HBRUSH)GetStockObject( WHITE_BRUSH );
  wc.hCursor = LoadCursor( NULL, IDC_ARROW );
  wc.hIcon = LoadIcon( NULL, IDI_APPLICATION );
  wc.hInstance = hInstance;
  wc.lpfnWndProc = WndProc ;
  wc.lpszClassName = TEXT("rt");
  wc.style = CS_HREDRAW | CS_VREDRAW;

  if( !RegisterClassEx(&wc) )
    FatalAppExitA( 0, "Couldn't register window class!" ) ;
	
  main=CreateWindowEx( 0, L"rt",L"title",WS_OVERLAPPEDWINDOW,64,64,640,480,0,0,hInstance,0);
  if( !main ) 
    FatalAppExitA( 0, "Couldn't create main!" ) ;
	
  // http://msdn.microsoft.com/en-us/library/bb774367(VS.85).aspx
  re=CreateWindowEx(0, MSFTEDIT_CLASS, TEXT("Hi!  Click anywhere on the bar above.\n"),
        WS_VISIBLE | WS_CHILD | WS_VSCROLL |
        ES_MULTILINE | ES_LEFT | ES_NOHIDESEL | ES_AUTOVSCROLL | ES_READONLY,
        0, 0, 640, 480, 
        main, NULL, hInstance, NULL);
  if( !re )
    FatalAppExitA( 0, "Couldn't create your rich text box!" ) ;

  CHARFORMAT2 cf ;
  cf.cbSize = sizeof( CHARFORMAT2 ) ;
  cf.dwMask = CFM_COLOR | CFM_BACKCOLOR | CFM_EFFECTS2 ; // I'm setting only the style information
  cf.crTextColor = RGB( 255, 0, 0 ) ;
  cf.crBackColor = RGB( 255,255,255 ) ;
  cf.dwEffects = CFE_BOLD ;
  SendMessage( re, EM_SETCHARFORMAT, SCF_ALL, (LPARAM)&cf ) ;
	
  ShowWindow(main,show);
  ShowWindow(re,show);

	MSG Msg={0};
	while (GetMessageA(&Msg,0,0,0))
	{
		TranslateMessage(&Msg);
		DispatchMessageA(&Msg);
	}
	return 0;
}


LRESULT CALLBACK WndProc( HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam )
{
  switch( message )
  {
  case WM_CREATE:
    // upon creation, let the speaker beep at 50Hz, for 10ms.
    Beep( 50, 10 );
    return 0;
    break;

  case WM_PAINT:
    {
      // we would place our Windows painting code here.
      HDC hdc;
      PAINTSTRUCT ps;
      hdc = BeginPaint( hwnd, &ps );

      // draw a circle and a 2 squares
      Ellipse( hdc, 20, 20, 160, 160 );
      Rectangle( hdc, 50, 50, 90, 90 );
      Rectangle( hdc, 100, 50, 140, 90 );

      EndPaint( hwnd, &ps );
    }
    return 0;
    break;

  case WM_SIZE:
    {
      int w = LOWORD( lparam ) ;
      int h = HIWORD( lparam ) ;
      MoveWindow( re, 0, 0, w, h, true ) ;
    }
    break;

  case WM_CHAR:
    switch( wparam )
    {
      case VK_ESCAPE: 
        PostQuitMessage( 0 ) ;
        break ;
    }
    break ;

  case WM_NCHITTEST:
  case WM_LBUTTONDOWN:
    {
      int x = LOWORD( lparam ) ;
      int y = HIWORD( lparam ) ;
      TCHAR buf[280];
      wsprintf( buf, L"Mouse is @ (%d, %d)\n", x, y ) ;

      // Move the caret to the end
      CHARRANGE crg = { LONG_MAX, LONG_MAX } ;
      SendMessage( re, EM_EXSETSEL, 0, (LPARAM)&crg ) ;

      // select random text color
      setColor( re, RGB( rand()%256, rand()%256, rand()%256 ), RGB( rand()%256, rand()%256, rand()%256 ) ) ;
      
      SendMessage( re, EM_REPLACESEL, TRUE, (LPARAM)buf ) ;
       

    }
    break ;

  case WM_RBUTTONDOWN:
    {
      // clear it with SETTEXTEX
      SETTEXTEX st ;
      st.codepage = CP_ACP ; // ansi codepage
      st.flags = ST_KEEPUNDO ;

      SendMessage( re, EM_SETTEXTEX, (WPARAM)&st, (LPARAM)"Cleared" ) ; // OVERWRITES all text
    }
    break ;

  case WM_DESTROY:
    PostQuitMessage( 0 ) ;
    return 0;
    break;

  }

  return DefWindowProc( hwnd, message, wparam, lparam );
}

D3D11: ERROR: ID3D11DeviceContext::Draw: A Vertex Shader is always required when drawing, but none is currently bound. [ EXECUTION ERROR #341: DEVICE_DRAW_VERTEX_SHADER_NOT_SET ]
D3D11: ERROR: ID3D11DeviceContext::Draw: Rasterization Unit is enabled (PixelShader is not NULL or Depth/Stencil test is enabled and RasterizedStream is not D3D11_SO_NO_RASTERIZED_STREAM) but position is not provided by the last shader before the Rasterization Unit. [ EXECUTION ERROR #362: DEVICE_DRAW_POSITION_NOT_PRESENT ]

These errors occur if you forget to have an output with the output semantic :COLOR on your pixel shader in d3d11.

Its a bit weird, but IDXGIKeyedMutex::AcquireSync has a parameter called Key. The docs state:

Key [in]
Type: UINT64

A value that indicates which device to give access to. This method will succeed when the device that currently owns the surface calls the IDXGIKeyedMutex::ReleaseSync method using the same value. This value can be any UINT64 value.

Observations:

  • – The first AcquireSync call __Must__ be made on 0, otherwise the app hangs forever
  • – If you Acquire on 0, and you release on 1, then the next person to pick up __must__ pick up on 1

Useful if ordering. Say A picks up the mutex on 0. Then, there are 2 objects B and C that must go in the order B, C. So:

– A PICKS UP 0, RELEASES on 1
– B picks up 1, releases 2
– C picks up 2, releases 0

Now they are going in a cycle, A,B,C,A,B,C…

C cannot go before B (because it will block until B releases on 2).

If you’re not ordering, you can just always use 0 for the key.

I didn’t know this, but an HINSTANCE is apparently a pointer to an IMAGE_DOS_HEADER struct.

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
  IMAGE_DOS_HEADER* header = (IMAGE_DOS_HEADER*)(hInstance) ;
  // ...
}

See this

Its weird to choke in dtor, but I had this situation where I was _inserting into a vector_, and getting a weird bug.

Naturally I start to think “must be a compiler bug..”

And you know when you get that thought, there’s something to be learned. So keep searching.

It turned out I was doing pushes of the form

vector<AABB> vec ;
vec.push_back( AABB( min, max ) ) ;

So the AABB was being

1. CONSTRUCTED with the AABB(min,max) ctor call
2. Copy constructed into the vector
3. destructed (item that was originally AABB(min,max) ctor created must be destroyed after copy into the vector)

So it was crashing on the dtor bit.

Turned out I had a non-initialized object ptr in AABB, and in ~AABB it was attempted to destroy that non-init ptr. Forgot to include init to 0 in AABB(min,max) ctor.