Recent

Author Topic: Rendering 3D Scene with loaded 3D object  (Read 10632 times)

lainz

  • Hero Member
  • *****
  • Posts: 4470
    • https://lainz.github.io/
Rendering 3D Scene with loaded 3D object
« on: May 20, 2016, 07:09:00 pm »
Hi, i'm trying to load and render a 3d model created with Blender.

First I rotate the object to see the same as I see in blender (each 3D program follow their own axis usage, is not the same in Blender and in Unity...). Just a few rotations and it's done.

But I need to zoom it a bit, in Blender the cube is 1m x 1m x 1m, and I've added some pyramids and an extra cube to see where it points, then is 3m wide. But when I render it it is too far from camera. I tryed using scene.Zoom just by 1.5 like in the bgra 3d demo but changing that the object is not anymore in view. Is neccesary to scale it to properly view it or I can keep the size and adjust the camera or something else?

Also I have the .mtl file containing the materials, these how can be loaded? BTW this file in particular does not have a particular material, is the blender default. But maybe I add pictures and other material stuff later. The 3D Builder application that comes with Windows 10 tell me to figure where is the .mtl file when I load the obj...

Edit: This is another question, is possible to render to OpenGL 3D and apply a filter to the rendered bitmap? for example in Unity there are filters to apply to the DirectX output (blur, bloom, noise, etc..)
« Last Edit: May 20, 2016, 07:10:39 pm by lainz »

circular

  • Hero Member
  • *****
  • Posts: 4221
    • Personal webpage
Re: Rendering 3D Scene with loaded 3D object
« Reply #1 on: May 21, 2016, 02:50:24 pm »
Hi Lainz!

There are three ways you can make the object look bigger.

By defining a smaller distance between the viewer and the object.
Code: Pascal  [Select][+][-]
  1.   scene.Camera.ViewPoint := Point3D(0,0,-10);
(by default the Z view position is -100)

By making the object bigger by calling its Scale function.

By changing the zoom (note that it is multiplying the current value, not setting it directly). Note that once you set the zoom like that, you don't have the autozoom anymore. It means that if the surface is resized (for example becomes 800x600 instead of 640x480, then the zoom is not ajusted).
Code: Pascal  [Select][+][-]
  1.   scene.Zoom := scene.Zoom*10;


To load the materials, before loading the object, call LoadMaterialsFromFile(...) function.

Note that if you have textures, the function FetchTexture must be overriden. It is up to you to decide how to store the images. To make it simple, you can simple keep an array of the textures as TBGLBitmap. And when the scene is destroyed, free all the textures. The scene object works with IBGRAScanner, so it does not know about the memory allocation or what type of bitmap it is.

Also, you could for example load the images from a stream, a zip file, etc. It does not need to be a file. Maybe it could be made easier to use. Just tell me your thoughts about it.

Note that in the example attached in your message, it uses TBGRAVirtualScreen, so it does not use OpenGL. To use OpenGL, you need a TBGLVirtualScreen and to call the RenderGL function.

About applying filters, it is not possible for now. I suppose it would be possible to do that using a framebuffer. I have not studied this question.
Conscience is the debugger of the mind

lainz

  • Hero Member
  • *****
  • Posts: 4470
    • https://lainz.github.io/
Re: Rendering 3D Scene with loaded 3D object
« Reply #2 on: May 21, 2016, 10:42:02 pm »
Quote
By defining a smaller distance between the viewer and the object.

This is working fine for me.

Code: Pascal  [Select][+][-]
  1. To load the materials, before loading the object, call LoadMaterialsFromFile(...) function.
  2.  
  3. Note that if you have textures, the function FetchTexture must be overriden. It is up to you to decide how to store the images. To make it simple, you can simple keep an array of the textures as TBGLBitmap. And when the scene is destroyed, free all the textures. The scene object works with IBGRAScanner, so it does not know about the memory allocation or what type of bitmap it is.
  4.  
  5. Also, you could for example load the images from a stream, a zip file, etc. It does not need to be a file. Maybe it could be made easier to use. Just tell me your thoughts about it.

I need to try, then I can tell you.

Code: Pascal  [Select][+][-]
  1. Note that in the example attached in your message, it uses TBGRAVirtualScreen, so it does not use OpenGL. To use OpenGL, you need a TBGLVirtualScreen and to call the RenderGL function.
  2.  
  3. About applying filters, it is not possible for now. I suppose it would be possible to do that using a framebuffer. I have not studied this question.
  4.  

Yes, I will keep using TBGRAVirtualScreen because of filters and because my GPU does not support antialiasing, but software render does.

lainz

  • Hero Member
  • *****
  • Posts: 4470
    • https://lainz.github.io/
Re: Rendering 3D Scene with loaded 3D object
« Reply #3 on: May 21, 2016, 11:25:56 pm »
Testing

LoadMaterialsFromFile('object.mtl');

with this mtl file:

Code: Pascal  [Select][+][-]
  1. # Blender MTL File: 'None'
  2. # Material Count: 1
  3.  
  4. newmtl Material
  5. Ns 96.078431
  6. Ka 1.000000 1.000000 1.000000
  7. Kd 0.800000 0.000000 0.000000
  8. Ks 0.500000 0.500000 0.500000
  9. Ke 0.000000 0.000000 0.000000
  10. Ni 1.000000
  11. d 1.000000
  12. illum 2
  13.  

the object becomes invisible. Is supossed to have a red color of diffuse and white specular and I don't know the others.

circular

  • Hero Member
  • *****
  • Posts: 4221
    • Personal webpage
Re: Rendering 3D Scene with loaded 3D object
« Reply #4 on: May 23, 2016, 01:37:37 am »
the object becomes invisible. Is supossed to have a red color of diffuse and white specular and I don't know the others.
Indeed that's surprising. The "d" line specifies the opacity. Here it is 1.0 so that is opaque. So it is not supposed to be transparent indeed.
Conscience is the debugger of the mind

lainz

  • Hero Member
  • *****
  • Posts: 4470
    • https://lainz.github.io/
Re: Rendering 3D Scene with loaded 3D object
« Reply #5 on: May 23, 2016, 12:15:35 pm »
You're right, is not transparent, I've changed VirtualScreen color to gray and the 3d object appears but is not red, is white.

circular

  • Hero Member
  • *****
  • Posts: 4221
    • Personal webpage
Re: Rendering 3D Scene with loaded 3D object
« Reply #6 on: May 23, 2016, 08:19:55 pm »
It may be that the specular light is saturating.

What if you set it to zero?
Code: Pascal  [Select][+][-]
  1. Ks 0 0 0
Conscience is the debugger of the mind

lainz

  • Hero Member
  • *****
  • Posts: 4470
    • https://lainz.github.io/
Re: Rendering 3D Scene with loaded 3D object
« Reply #7 on: May 24, 2016, 05:22:29 pm »
It may be that the specular light is saturating.

What if you set it to zero?
Code: Pascal  [Select][+][-]
  1. Ks 0 0 0

Is the same. Maybe because I have no lights? In LazPaint if you don't add a light in the imported 3d model is gray. In my case totally white.

When importing an 255 0 0 colored object in lazpaint the color is converted to 255 170 170, why? In Blender is red and in 3D Builder the same. Maybe something with the ambiant light?

the mtl

Code: Pascal  [Select][+][-]
  1. # Blender MTL File: 'None'
  2. # Material Count: 1
  3.  
  4. newmtl Material
  5. Ns 194.117647
  6. Ka 1.000000 1.000000 1.000000
  7. Kd 1.000000 0.000000 0.000000
  8. Ks 1.000000 1.000000 1.000000
  9. Ke 0.000000 0.000000 0.000000
  10. Ni 1.000000
  11. d 1.000000
  12. illum 2

the obj

Code: Pascal  [Select][+][-]
  1. # Blender v2.77 (sub 0) OBJ File: ''
  2. # www.blender.org
  3. mtllib object.mtl
  4. o Cube
  5. v 1.000000 -1.000000 -1.000000
  6. v 1.000000 -1.000000 1.000000
  7. v -1.000000 -1.000000 1.000000
  8. v -1.000000 -1.000000 -1.000000
  9. v 1.000000 1.000000 -0.999999
  10. v 0.999999 1.000000 1.000001
  11. v -1.000000 1.000000 1.000000
  12. v -1.000000 1.000000 -1.000000
  13. vn 0.000000 -1.000000 0.000000
  14. vn 0.000000 1.000000 0.000000
  15. vn 1.000000 0.000000 0.000000
  16. vn -0.000000 -0.000000 1.000000
  17. vn -1.000000 -0.000000 -0.000000
  18. vn 0.000000 0.000000 -1.000000
  19. usemtl Material
  20. s off
  21. f 1//1 2//1 3//1 4//1
  22. f 5//2 8//2 7//2 6//2
  23. f 1//3 5//3 6//3 2//3
  24. f 2//4 6//4 7//4 3//4
  25. f 3//5 7//5 8//5 4//5
  26. f 5//6 1//6 4//6 8//6
  27.  

circular

  • Hero Member
  • *****
  • Posts: 4221
    • Personal webpage
Re: Rendering 3D Scene with loaded 3D object
« Reply #8 on: May 25, 2016, 09:04:11 pm »
It may be because of saturation of lightness.

What if you remove all light sources and only set AmbiantLightness to 1?
Conscience is the debugger of the mind

lainz

  • Hero Member
  • *****
  • Posts: 4470
    • https://lainz.github.io/
Re: Rendering 3D Scene with loaded 3D object
« Reply #9 on: May 25, 2016, 11:03:31 pm »
Is the same, I have no lights and it is still white.

I'll try with bitmaps next or assigning the materials with code instead of file.

Edit: with bitmaps works fine, just I have a problem, when freeing the bitmap I get a SIGSEV error, if I don't free the bitmap I get mem leaks, whats the way you use to free the bitmap?

I'm using the obj that comes with lazpaint this time 'greek_vase', but material color is not loaded again, now I get gray instead of white, maybe this time is for the missing light sources, like in lazpaint gets gray instead of colored.

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtCtrls,
  9.   BGRAVirtualScreen, BGRABitmap, BGRABitmapTypes, BGRAScene3D, BGRAOpenGL3D, BCTypes;
  10.  
  11. type
  12.  
  13.   { T3DGraphic }
  14.  
  15.   T3DGraphic = class(TBGLScene3D)
  16.   private
  17.     bitmap: TBGRABitmap;
  18.   protected
  19.     function FetchTexture({%H-}AName: string; out texSize: TPointF): IBGRAScanner; override;
  20.   public
  21.     constructor Create;
  22.     destructor Destroy; override;
  23.   end;
  24.  
  25.   { TForm1 }
  26.  
  27.   TForm1 = class(TForm)
  28.     BGRAVirtualScreen1: TBGRAVirtualScreen;
  29.     Timer1: TTimer;
  30.     procedure BGRAVirtualScreen1Click(Sender: TObject);
  31.     procedure BGRAVirtualScreen1Redraw(Sender: TObject; Bitmap: TBGRABitmap);
  32.     procedure FormCreate(Sender: TObject);
  33.     procedure FormDestroy(Sender: TObject);
  34.     procedure Timer1Timer(Sender: TObject);
  35.   private
  36.     { private declarations }
  37.   public
  38.     { public declarations }
  39.     scene: T3DGraphic;
  40.     bitmap: TBGRABitmap;
  41.   end;
  42.  
  43. var
  44.   Form1: TForm1;
  45.  
  46. implementation
  47.  
  48. {$R *.lfm}
  49.  
  50. { T3DGraphic }
  51.  
  52. function T3DGraphic.FetchTexture(AName: string; out texSize: TPointF
  53.   ): IBGRAScanner;
  54. begin
  55.   bitmap := TBGRABitmap.Create(AName);
  56.   result := bitmap;
  57.   texSize := PointF(256,256);
  58. end;
  59.  
  60. constructor T3DGraphic.Create;
  61. begin
  62.   inherited Create;
  63.   LoadMaterialsFromFile('greek_vase.mtl');
  64.   LoadObjectFromFile('greek_vase.obj', True);
  65. end;
  66.  
  67. destructor T3DGraphic.Destroy;
  68. begin
  69.   FreeAndNil(bitmap);
  70.   inherited Destroy;
  71. end;
  72.  
  73. { TForm1 }
  74.  
  75. procedure TForm1.BGRAVirtualScreen1Redraw(Sender: TObject; Bitmap: TBGRABitmap);
  76. begin
  77.   scene.RenderingOptions.AntialiasingMode := am3dResample;
  78.   scene.RenderingOptions.AntialiasingResampleLevel := 2;
  79.   scene.RenderingOptions.MinZ := 1;
  80.   scene.Surface := Bitmap;
  81.   scene.Render;
  82.   scene.Surface := nil;
  83. end;
  84.  
  85. procedure TForm1.BGRAVirtualScreen1Click(Sender: TObject);
  86. begin
  87.  
  88. end;
  89.  
  90. procedure TForm1.FormCreate(Sender: TObject);
  91. begin
  92.   scene := T3DGraphic.Create;
  93.   if scene.Object3DCount > 0 then
  94.   begin
  95.     // Perfectly aligned with Blender 'Front view'
  96.     scene.Object3D[0].MainPart.RotateZDeg(180, False);
  97.     scene.Object3D[0].MainPart.RotateYDeg(180, False);
  98.   end;
  99.   //scene.Camera.ViewPoint := Point3D(-2,-2,-2);
  100. end;
  101.  
  102. procedure TForm1.FormDestroy(Sender: TObject);
  103. begin
  104.   Timer1.Enabled:=False;
  105.   scene.Free;
  106. end;
  107.  
  108. procedure TForm1.Timer1Timer(Sender: TObject);
  109. begin
  110.   scene.Object3D[0].MainPart.RotateYDeg(-1, False);
  111.   BGRAVirtualScreen1.DiscardBitmap;
  112. end;
  113.  
  114. end.  
« Last Edit: May 25, 2016, 11:45:03 pm by lainz »

circular

  • Hero Member
  • *****
  • Posts: 4221
    • Personal webpage
Re: Rendering 3D Scene with loaded 3D object
« Reply #10 on: May 26, 2016, 11:21:22 pm »
Hi!

I think I found the explanation. There is an ambiant color, a diffuse color and a specular color. In this case, the ambiant color is white, so it appears white with the ambiant light.

So to make it red you need to set ambiant values to be the same as the diffuse values:
Code: [Select]
Ka 1.000000 0.000000 0.000000
Conscience is the debugger of the mind

lainz

  • Hero Member
  • *****
  • Posts: 4470
    • https://lainz.github.io/
Re: Rendering 3D Scene with loaded 3D object
« Reply #11 on: May 27, 2016, 01:07:49 am »
Hi!

I think I found the explanation. There is an ambiant color, a diffuse color and a specular color. In this case, the ambiant color is white, so it appears white with the ambiant light.

So to make it red you need to set ambiant values to be the same as the diffuse values:
Code: [Select]
Ka 1.000000 0.000000 0.000000

Yes, that is working!

About loading a texture bitmap via FetchTexture, maybe you can specify if it must free the bitmap automatically (something like FreeTexture or something) that would be nice, like a third argument.

circular

  • Hero Member
  • *****
  • Posts: 4221
    • Personal webpage
Re: Rendering 3D Scene with loaded 3D object
« Reply #12 on: May 27, 2016, 02:25:26 pm »
About the error with freeing bitmaps, there was an error and I fixed it. Maybe you don't have the latest version of BGRABitmap.

Otherwise, can you turn on debug information and then when it crashes tell me what line of code it crashes?
Conscience is the debugger of the mind

circular

  • Hero Member
  • *****
  • Posts: 4221
    • Personal webpage
Re: Rendering 3D Scene with loaded 3D object
« Reply #13 on: May 27, 2016, 03:30:23 pm »
Hi!

To make it simpler, I have added a FetchDirectory property. Here is how to use it:
Code: Pascal  [Select][+][-]
  1.   scene.FetchDirectory := '.';
  2.   scene.FetchObject('greek_vase.obj');  

That will load the materials, the object and the textures. And you don't need to free it yourself.

So the scene class would be
Code: Pascal  [Select][+][-]
  1.   { T3DGraphic }
  2.  
  3.   T3DGraphic = class(TBGRAScene3D)
  4.   public
  5.     constructor Create;
  6.   end;    
  7.  
  8. { T3DGraphic }
  9.  
  10. constructor T3DGraphic.Create;
  11. begin
  12.   inherited Create;
  13.   FetchDirectory := '.';
  14.   FetchObject('greek_vase.obj');
  15. end;
  16.  
Conscience is the debugger of the mind

lainz

  • Hero Member
  • *****
  • Posts: 4470
    • https://lainz.github.io/
Re: Rendering 3D Scene with loaded 3D object
« Reply #14 on: May 27, 2016, 04:21:37 pm »
Alright thanks! Working fine.

Now I can continue with the contest project  :)

The last thing, you can convert it to OpenGL instead of using VirtualScreen? Because I get some errors like 'opengl context has not been created yet' and it just stop the debug cursor at FetchObject, that's possible?
« Last Edit: May 27, 2016, 05:12:01 pm by lainz »

 

TinyPortal © 2005-2018