Author Topic: Graphics cache and animation  (Read 2631 times)

0 Members and 1 Guest are viewing this topic.

pkohut

  • Guest
Graphics cache and animation
« on: June 08, 2009, 08:38:31 AM »
The code below started as a test harnes to fix some graphics caching issues, and later
graphics updating withing an animation loop.  In another project I'm writing a simulator
to run inside AutoCAD and need the graphics to be updated in an animation loop.  Problem
was first the cache was all scrambled, and second the graphics were not updating untill the
application finished.  Think I've solved the problems with the code be, but was wondering if
the queueForGraphicsFlush(), flushGraphics() and acedUpdateDisplay are implemented correctly.
It seems to work but I'm not sure I've implemented it correctly (see near end of code).

Thanks,
Paul

Running the code:
Create a new project and replace the contents of "acrxEntryPoint.cpp" with the code below.
Compile and run, at the AutoCAD command line type RUNIT (might have to zoom extents
and RUNIT again).

Code: [Select]
// Animate the circle 1000 times
// Written by Paul Kohut, June 8, 2009
// paulkohut@hotmail.com

// Implements a fairly smooth aniniation loop within AutoCAD.

//-----------------------------------------------------------------------------
//----- acrxEntryPoint.h
//-----------------------------------------------------------------------------
#include "StdAfx.h"
#include "resource.h"
#define _USE_MATH_DEFINES 1
#include <math.h>


#define index(x, y, c) (y * c + x)

//-----------------------------------------------------------------------------
#define szRDS _RXST("nav")

#pragma comment(linker, "/export:_acrxGetApiVersion,PRIVATE")
//#pragma comment(linker, "/export:_acrxEntryPoint,PRIVATE")

//-----------------------------------------------------------------------------
//----- ObjectARX EntryPoint
class CBadGraphicsApp : public AcRxArxApp {

public:
CBadGraphicsApp () : AcRxArxApp () {}

virtual AcRx::AppRetCode On_kInitAppMsg (void *pkt) {
AcRx::AppRetCode retCode =AcRxArxApp::On_kInitAppMsg (pkt) ;
return (retCode) ;
}

virtual AcRx::AppRetCode On_kUnloadAppMsg (void *pkt) {
AcRx::AppRetCode retCode =AcRxArxApp::On_kUnloadAppMsg (pkt) ;
return (retCode) ;
}

virtual void RegisterServerComponents () {
}

static void EraseAllEntity(AcDbBlockTableRecordPointer & pBtr)
{
AcDbBlockTableRecordIterator * pIter;
pBtr->newIterator(pIter);
for(pIter->start(); !pIter->done(); pIter->step()) {
AcDbObjectId entId;
if(pIter->getEntityId(entId) == Acad::eOk) {
AcDbObject *pEnt;
if(actrTransactionManager->getObject(pEnt, entId, AcDb::kForWrite) == Acad::eOk)
{
pEnt->erase();
}
}
}
}

// draws a checker board, grid lines, and animates a circle.
static void DrawGraphics(void)
{
int nMapSizeX = 8;
int nMapSizeY = 8;

double dGridSizeX = 1.0, dGridSizeY = 1.0;

AcCmColor colorBlack;
AcCmColor colorGrid;
AcCmColor colorWhite;
AcCmColor colorRed;

colorBlack.setRGB(0, 0, 0);
colorGrid.setRGB(91, 91, 91);
colorWhite.setRGB(255, 255, 255);
colorRed.setRGB(255, 0, 0);

double x = 0.0, y = 0.0;

// Draw the checker board layout
AcDbDatabase * pDb = acdbHostApplicationServices()->workingDatabase();
AcDbBlockTableRecordPointer pRcd(ACDB_MODEL_SPACE, pDb, AcDb::kForWrite);
if(pRcd.openStatus() == Acad::eOk) {
EraseAllEntity(pRcd);
for(int j = 0; j < nMapSizeY; j++) {
x = 0.0;
for(int i = 0; i < nMapSizeX; i++) {
AcDbSolid * pSolid = new AcDbSolid(AcGePoint3d(x, y, 0.0),
AcGePoint3d(x + dGridSizeX, y, 0.0),
AcGePoint3d(x, y - dGridSizeY, 0.0),
AcGePoint3d(x + dGridSizeX, y - dGridSizeY, 0.0) );
pSolid->setColor((index(i, j, nMapSizeX) + j) % 2 ? colorBlack : colorWhite);
AcDbObjectId objId;
if(pRcd->appendAcDbEntity(objId, pSolid) == Acad::eOk)
{
actrTransactionManager->addNewlyCreatedDBRObject(pSolid);
pSolid->draw();
}
else
delete pSolid;

x += dGridSizeX;
}
y -= dGridSizeY;
}

// Draw vertical grid lines
x = 0.0;
y = 0.0;
double gridLineWidth = 0.05;
for(int i = 0; i <= nMapSizeX; i++) {
AcDbPolyline * pPline = new AcDbPolyline();
pPline->addVertexAt(pPline->numVerts(), AcGePoint2d(x, y), 0.0, gridLineWidth, gridLineWidth);
pPline->addVertexAt(pPline->numVerts(), AcGePoint2d(x, y - (dGridSizeY * nMapSizeY)), 0.0, gridLineWidth, gridLineWidth);
pPline->setColor(colorGrid);
AcDbObjectId objId;
if(pRcd->appendAcDbEntity(objId, pPline) == Acad::eOk)
{
actrTransactionManager->addNewlyCreatedDBRObject(pPline);
pPline->draw();
}
else
delete pPline;
x += dGridSizeX;
}

// Draw horizontal grid lines
x = 0.0;
y = 0.0;
for(int i = 0; i <= nMapSizeY; i++) {
AcDbPolyline * pPline = new AcDbPolyline();
pPline->addVertexAt(pPline->numVerts(), AcGePoint2d(x, y), 0.0, gridLineWidth, gridLineWidth);
pPline->addVertexAt(pPline->numVerts(), AcGePoint2d(x + (dGridSizeX * nMapSizeX), y), 0.0, gridLineWidth, gridLineWidth);
pPline->setColor(colorGrid);
if(pRcd->appendAcDbEntity(pPline) == Acad::eOk)
{
actrTransactionManager->addNewlyCreatedDBRObject(pPline);
pPline->draw();
}
else
delete pPline;
y -= dGridSizeY;
}

// Animate a circle going in a circle
static double stepp = M_PI_2 / 180.0;
static double x1 = nMapSizeX * dGridSizeX * 0.5;
static double y1 = -nMapSizeY * dGridSizeY * 0.5;
static double ang = 0.0;
AcDbCircle * pCircle = new AcDbCircle();
pCircle->setCenter(AcGePoint3d(cos(ang) * 2.0 + x1, sin(ang) * 2.0 + y1, 0.0));
pCircle->setRadius(0.25);
pCircle->setColor(colorRed);
if(pRcd->appendAcDbEntity(pCircle) == Acad::eOk)
{
actrTransactionManager->addNewlyCreatedDBRObject(pCircle);
}
else
delete pCircle;
ang += stepp;


}
}

// call when the user types RUNIT from the AutoCAD command line.
// Questions??? Is the queueing, flushing, and updating of the
// graphics done correctly? It works, but is this the right way?
static void navBadGraphicsRunIt(void)
{
AcTransaction * pTrans = actrTransactionManager->startTransaction();
actrTransactionManager->enableGraphicsFlush(kTrue);

for(int i = 0; i < 1000; i++) {
DrawGraphics();

actrTransactionManager->queueForGraphicsFlush();
actrTransactionManager->flushGraphics();
acedUpdateDisplay();
}

actrTransactionManager->endTransaction();
}
} ;

//-----------------------------------------------------------------------------
IMPLEMENT_ARX_ENTRYPOINT(CBadGraphicsApp)

ACED_ARXCOMMAND_ENTRY_AUTO(CBadGraphicsApp, navBadGraphics, RunIt, RunIt, ACRX_CMD_TRANSPARENT, NULL)


Spike Wilbury

  • Guest
Re: Graphics cache and animation
« Reply #1 on: June 08, 2009, 11:09:17 AM »
Hi Paul,

Those are the steps, to force the update.

Do you need this:
actrTransactionManager->enableGraphicsFlush(kTrue); ? 

and why not placing:
DrawGraphics();

After?

Maybe :)





pkohut

  • Guest
Re: Graphics cache and animation
« Reply #2 on: June 08, 2009, 11:18:39 AM »
Hi Paul,

Those are the steps, to force the update.

Do you need this:
actrTransactionManager->enableGraphicsFlush(kTrue); ? 

and why not placing:
DrawGraphics();

After?

Maybe :)



Probably don't need the enableGraphicsFlush(kTrue) will take it out in a bit and test,
otherwise it's leftover code from experimentation.

How do you mean DrawGraphics() after?  You mean putting it after the function
navBadGraphicsRunIt?  The way it is now eliminates the need to forward reference
of DrawGraphics.

Thanks

Spike Wilbury

  • Guest
Re: Graphics cache and animation
« Reply #3 on: June 08, 2009, 11:31:50 AM »
Probably don't need the enableGraphicsFlush(kTrue) will take it out in a bit and test,
otherwise it's leftover code from experimentation.

How do you mean DrawGraphics() after?  You mean putting it after the function
navBadGraphicsRunIt?  The way it is now eliminates the need to forward reference
of DrawGraphics.

Thanks

I have used this on one function and before calling acedDragGen(); that's why.

and was referring to this... it does the same as the way you have it now - but don't know to much about it :).

Code: [Select]
actrTransactionManager->queueForGraphicsFlush();
actrTransactionManager->flushGraphics();
acedUpdateDisplay();
DrawGraphics();



pkohut

  • Guest
Re: Graphics cache and animation
« Reply #4 on: June 08, 2009, 11:59:36 AM »
Code: [Select]
actrTransactionManager->queueForGraphicsFlush();
actrTransactionManager->flushGraphics();
acedUpdateDisplay();
DrawGraphics();

Ah, I see what your talking about.  No, the DrawGraphics function needs to
be called first, then queue up then changes and force a redraw.  Otherwise
the displayed graphical elements are one step out of sync.