This question came up in an internal discussion, and I thought I'd share the code provided by our Engineering team with you (with a few minor additions from my side, of course).
The idea is to render a 3D scene off-screen (i.e. save to file the rendered image not visible in the editor). In the below code, we do zoom to the extents of the 3D model that gets created, just to show it's there, but the rendering activity itself is not performed by the 3D view that is used to generate the graphics for AutoCAD's editor window.
A 3D model does need to be loaded in the editor for this to work, so I decided to add a simple sphere to the modelspace and set its material to one that renders nicely (Sitework.Paving - Surfacing.Riverstone.Mortared). The code doesn't import the material programmatically, so you'll want to make sure it's there in the drawing to get the full effect of the rendering (by dragging the material into the drawing view from the materials tool palette, for instance), or to change the code to point to one that exists in the active drawing.
Here's the C# code:
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.GraphicsSystem;
using Autodesk.AutoCAD.Interop;
using System.Drawing;
namespace OffscreenRendering
{
public class Commands
{
[CommandMethod("OSR")]
static public void OffscreenRender()
{
CreateSphere();
RenderToFile("c:\\sphere.png");
}
static public void CreateSphere()
{
Document doc =
Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
Transaction tr =
doc.TransactionManager.StartTransaction();
using (tr)
{
BlockTable bt =
(BlockTable)tr.GetObject(
db.BlockTableId,
OpenMode.ForRead
);
BlockTableRecord btr =
(BlockTableRecord)tr.GetObject(
bt[BlockTableRecord.ModelSpace],
OpenMode.ForWrite
);
Solid3d sol = new Solid3d();
sol.CreateSphere(10.0);
const string matname =
"Sitework.Paving - Surfacing.Riverstone.Mortared";
DBDictionary matdict =
(DBDictionary)tr.GetObject(
db.MaterialDictionaryId,
OpenMode.ForRead
);
if (matdict.Contains(matname))
{
sol.Material = matname;
}
else
{
ed.WriteMessage(
"\nMaterial (" + matname + ") not found" +
" - sphere will be rendered without it.",
matname
);
}
btr.AppendEntity(sol);
tr.AddNewlyCreatedDBObject(sol, true);
tr.Commit();
}
AcadApplication acadApp =
(AcadApplication)Application.AcadApplication;
acadApp.ZoomExtents();
}
static public void RenderToFile(string filename)
{
Document doc =
Application.DocumentManager.MdiActiveDocument;
Editor ed = doc.Editor;
int vpn =
System.Convert.ToInt32(
Application.GetSystemVariable("CVPORT")
);
View gsv =
doc.GraphicsManager.GetGsView(vpn, true);
using (View view = gsv.Clone(true, true))
{
Device dev =
doc.GraphicsManager.CreateAutoCADOffScreenDevice();
using (dev)
{
dev.OnSize(doc.GraphicsManager.DisplaySize);
dev.DeviceRenderType = RendererType.FullRender;
dev.Add(view);
using (Bitmap bitmap = view.RenderToImage())
{
bitmap.Save(filename);
ed.WriteMessage(
"\nRendered image saved to: " +
filename
);
}
}
}
}
}
}
And here's the resized contents of the file created at c:\sphere.png by the OSR command: