I need to render a .obj imported from AutoDesk 3DS max to get an output in jpg or png file. How do I do it? I am using Expression blend 4 and WPF Visual Studio.
Asked
Active
Viewed 658 times
1 Answers
2
Use SharpGL, a C# library which makes it super easy to use OpenGL in your C# applications. It does include support for directly loading .obj files.
Double Edit: I've replaced my code samples with an implementation using them. I have ran the following code, and it does work, it loads up a .obj and renders it on screen with no problems
XAML ..Make sure you add
xmlns:sharpGL="clr-namespace:SharpGL.WPF;assembly=SharpGL.WPF"
to the window properties
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="30" />
<RowDefinition />
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Orientation="Horizontal">
<Button Content="Add Item" Click="Add_Click" />
<Button Content="Take Screen Shot" Click="ScreenShot_Click" />
</StackPanel>
<sharpGL:OpenGLControl Grid.Row="1" Name="myOpenGLControl"
OpenGLDraw="OpenGLControl_OpenGLDraw" OpenGLInitialized="OpenGLControl_OpenGLInitialized"
RenderContextType="FBO" />
</Grid>
Code behind
Note: I haven't actually implemented the saving of the graphics, but at this point you can render on screen a preview of the model.
public partial class MainWindow : Window
{
float rotation_angle = 0f;
float rotation_x = 0f;
float rotation_y = 0f;
float rotation_z = 0f;
private List<Polygon> _polygons = new List<Polygon>();
public MainWindow()
{
InitializeComponent();
myOpenGLControl.OpenGL.Enable(OpenGL.GL_TEXTURE_2D);
}
private void OpenGLControl_OpenGLDraw(object sender, SharpGL.SceneGraph.OpenGLEventArgs args)
{
OpenGL gl = args.OpenGL;
// Clear The Screen And The Depth Buffer
gl.Clear(OpenGL.GL_COLOR_BUFFER_BIT | OpenGL.GL_DEPTH_BUFFER_BIT);
// Move Left And Into The Screen
gl.LoadIdentity();
gl.Translate(0.0f, -1.0f, -10.0f);
gl.Rotate(rotation_angle, rotation_x, rotation_y, rotation_z);
foreach (Polygon polygon in _polygons)
{
polygon.PushObjectSpace(gl);
polygon.Render(gl, SharpGL.SceneGraph.Core.RenderMode.Render);
polygon.PopObjectSpace(gl);
}
rotation_angle += 3;
rotation_x = 0;
rotation_y = 20;
rotation_z = -5;
}
private void OpenGLControl_OpenGLInitialized(object sender, SharpGL.SceneGraph.OpenGLEventArgs args)
{
OpenGL gl = args.OpenGL;
gl.Enable(OpenGL.GL_DEPTH_TEST);
float[] global_ambient = new float[] { 0.5f, 0.5f, 0.5f, 1.0f };
float[] light0pos = new float[] { 0.0f, 5.0f, 10.0f, 1.0f };
float[] light0ambient = new float[] { 0.2f, 0.2f, 0.2f, 1.0f };
float[] light0diffuse = new float[] { 0.3f, 0.3f, 0.3f, 1.0f };
float[] light0specular = new float[] { 0.8f, 0.8f, 0.8f, 1.0f };
float[] lmodel_ambient = new float[] { 0.2f, 0.2f, 0.2f, 1.0f };
gl.LightModel(OpenGL.GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
gl.LightModel(OpenGL.GL_LIGHT_MODEL_AMBIENT, global_ambient);
gl.Light(OpenGL.GL_LIGHT0, OpenGL.GL_POSITION, light0pos);
gl.Light(OpenGL.GL_LIGHT0, OpenGL.GL_AMBIENT, light0ambient);
gl.Light(OpenGL.GL_LIGHT0, OpenGL.GL_DIFFUSE, light0diffuse);
gl.Light(OpenGL.GL_LIGHT0, OpenGL.GL_SPECULAR, light0specular);
gl.Enable(OpenGL.GL_LIGHTING);
gl.Enable(OpenGL.GL_LIGHT0);
gl.ShadeModel(OpenGL.GL_SMOOTH);
}
private void Add_Click(object sender, RoutedEventArgs e)
{
List<Polygon> polygons = LoadScene("ducky.obj");
polygons.ScaleMaxExtentTo(10);
_polygons.AddRange(polygons);
}
private void ScreenShot_Click(object sender, RoutedEventArgs e)
{
//Here you can use either of the below methods to get the raw pixel data
//which needs to be manually formatted for the file type of your choice.
//myOpenGLControl.OpenGL.ReadBuffer();
//myOpenGLControl.OpenGL.ReadPixels();
}
private List<Polygon> LoadScene(string filePath)
{
List<Polygon> polygons = new List<Polygon>();
Scene scene = SerializationEngine.Instance.LoadScene(filePath);
if (scene != null)
{
polygons.AddRange(scene.SceneContainer.Traverse<Polygon>());
}
return polygons;
}
}
public static class ExtensionMethods
{
/// <summary>Scales the polygons to not excede the maximum size in OpenGL Units.</summary>
public static void ScaleMaxExtentTo(this List<Polygon> polygons, float maxSize)
{
foreach (var polygon in polygons) { polygon.ScaleMaxExtentTo(maxSize); }
}
/// <summary>Scales the polygon to not excede the maximum size in OpenGL Units.</summary>
public static void ScaleMaxExtentTo(this Polygon polygon, float maxSize)
{
float[] extent = new float[3];
polygon.BoundingVolume.GetBoundDimensions(out extent[0], out extent[1], out extent[2]);
float maxExtent = extent.Max();
float scaleFactor = maxExtent > maxSize ? maxSize / maxExtent : 1;
polygon.Transformation.ScaleX = scaleFactor;
polygon.Transformation.ScaleY = scaleFactor;
polygon.Transformation.ScaleZ = scaleFactor;
}
}

BenVlodgi
- 2,135
- 1
- 13
- 26
-
Found some discussion on the topic here regarding this: http://stackoverflow.com/questions/421600/3ds-max-object-to-opengl – ouflak Mar 06 '14 at 15:09
-
I am not sure how this works. i couldn't get it to work. I am a rookie and just started with WPF so please help – user2575033 Mar 06 '14 at 17:56
-
@user2575033 What exactly could you not get to work... could you explain what you tried to do? – BenVlodgi Mar 06 '14 at 18:03
-
Thank you so much i appeeciate your help. I am just using viewport in Expression blend 4 and adding texture to .obj and .mtl file from 3DS max. so Open GL is not in for me. i just need to render the content displayed in design view of blend 4 in .png or .jpeg format – user2575033 Mar 06 '14 at 19:54
-
@user2575033 Okay, so you just need to take a screenshot of the viewport? If not... you could use OpenGL, you will just have to send over the viewports angles/coordinates, and you can render it in OpenGL... but if it is just a screenshot you need, that would be much simpler. – BenVlodgi Mar 06 '14 at 20:06
-
yes i need only screenshot of viewport but only way to do it that i know of is printscreen which is not what i want to do. – user2575033 Mar 07 '14 at 03:31