Aplly new Material and light to a complex loaded object.

Software: Away3D 4.x

rgbox, Newbie
Posted: 03 October 2011 06:06 AM   Total Posts: 12

I’m loading a complex model made in Cinema 4d as .OBJ
Probably the geometry is not correct, but it can be rendered in 3D max.

After loading, I’m going to apply new material and a light to the loaded object.

Problems:
1. New Material is applied only to a fragment of the model. Not sure how to apply it to all.
2. When I add light (uncommenting the line

subMesh.material.lights=[_light3] 

), I get “RangeError: Error #3669:”

Can anybody help? Please!

package
{
 import away3d
.cameras.Camera3D;
 
import away3d.cameras.lenses.PerspectiveLens;
 
import away3d.containers.View3D;
 
import away3d.events.LoaderEvent;
 
import away3d.loaders.Loader3D;
 
import away3d.loaders.parsers.Max3DSParser;
 
import away3d.loaders.parsers.OBJParser;

 
import away3d.lights.DirectionalLight;
 
import away3d.lights.LightBase;
 
import away3d.lights.PointLight;

 
import away3d.materials.ColorMaterial
 import away3d
.materials.SegmentMaterial
 import away3d
.materials.methods.OutlineMethod

 import away3d
.entities.Mesh;

 
import flash.display.StageAlign;
 
import flash.display.StageScaleMode;

 
import flash.display.Sprite;
 
import flash.events.Event;
 
import flash.geom.Vector3D;
 
import flash.net.URLRequest;
 
[SWF(width="800"height="450"frameRate="60"backgroundColor="#ffffff")]



 
public class LoaderObject extends Sprite
 {
  
private var _view View3D;
  private var 
_container Loader3D;

  private var 
_light3 LightBase;


  public function 
LoaderObject()
  
{

   _view 
= new View3D();
   
_view.antiAlias 2;
   
_view.backgroundColor 0xffff00;
   var 
camera:Camera3D _view.camera;
   
camera.lens = new PerspectiveLens();
   
camera.800;

   
_light3 = new DirectionalLight(-1000000, -1000000, -1000000);
   
_light3.specular 0;
   
_light3.diffuse 0.3;
   
_light3.color 0xffffff;

   
_view.scene.addChild(_light3);

   
addChild(_view);

   
Loader3D.enableParser(OBJParser);

   
_container = new Loader3D();
   
_container.scale(10);
   
_container.addEventListener(LoaderEvent.RESOURCE_COMPLETEonResourceComplete);
   
_container.addEventListener(LoaderEvent.LOAD_ERRORonResourceLoadingError);

   
_container.load(new URLRequest('mymodels/wto.obj'));

   
_view.scene.addChild(_container);
   
_view.camera.lookAt(_container.position);
   
_view.camera.lens.far Vector3D.distance(_container.position_view.camera.position)+100000;
   
_view.camera.lens.near 10;

   
stage.scaleMode StageScaleMode.NO_SCALE;
   
stage.align StageAlign.TOP_LEFT;
   
stage.addEventListener(Event.RESIZEonStageResize);

  
}

  
private function onStageResize(event Event) : void
  {
   _view
.width stage.stageWidth;
   
_view.height stage.stageHeight;
  
}

  
private function onResourceComplete(away3d.events.LoaderEvent) : void
  {
   _view
.width stage.stageWidth;
   
_view.height stage.stageHeight;
   
this.addEventListener(Event.ENTER_FRAMEhandleEnterFrame);
   
setSub(_container)
  
}

  
private function setSub(Msh{
   
var mtr = new ColorMaterial(0x0000ff1)
   
mtr.ambientColor 0x0000ff

   
var nc Msh.numChildren
   
if (nc>0{
    
for (var i=0i<nci++) {
     
var subMesh Mesh(Msh.getChildAt(i));
     
subMesh.material mtr;
//           subMesh.material.lights=[_light3]
           
setSub(subMesh)
    
}
   }

  }

  
private function onResourceLoadingError(e:LoaderEvent) : void
  {
    trace
("oops, model load failed");
  
}

  
private function onResourceMapsLoadingError(e:LoaderEvent) : void
  {
    trace
("A map failed to load in this model: ["+e.url+"]");
  
}

  
private function handleEnterFrame(Event) : void
  {
   _container
.rotationY += .5;
   
_view.render();
  
}
 }

 

   

Avatar
theMightyAtom, Sr. Member
Posted: 03 October 2011 08:11 AM   Total Posts: 669   [ # 1 ]

Try this:

package
{
 import away3d
.cameras.Camera3D;
 
import away3d.cameras.lenses.PerspectiveLens;
 
import away3d.containers.View3D;
 
import away3d.events.LoaderEvent;
 
import away3d.loaders.Loader3D;
 
import away3d.loaders.parsers.Max3DSParser;
 
import away3d.loaders.parsers.OBJParser;

 
import away3d.lights.DirectionalLight;
 
import away3d.lights.LightBase;
 
import away3d.lights.PointLight;

 
import away3d.materials.ColorMaterial
 import away3d
.materials.SegmentMaterial
 import away3d
.materials.methods.OutlineMethod

 import away3d
.entities.Mesh;

 
import flash.display.StageAlign;
 
import flash.display.StageScaleMode;

 
import flash.display.Sprite;
 
import flash.events.Event;
 
import flash.geom.Vector3D;
 
import flash.net.URLRequest;
 
[SWF(width="800"height="450"frameRate="60"backgroundColor="#ffffff")]



 
public class LoaderObject extends Sprite
 {
  
private var _view View3D;
  private var 
_container Loader3D;
  private var 
_camera:Camera3D;

  private var 
_light3 LightBase;


  public function 
LoaderObject()
  
{

   _view 
= new View3D();
   
_view.antiAlias 2;
   
_view.backgroundColor 0xffff00;
   
_camera _view.camera;
   
_camera.lens = new PerspectiveLens();
   
_camera.800;

   
_light3 = new DirectionalLight(0,0,-1);
   
_light3.specular 0.1;
   
_light3.diffuse 1;
   
_light3.color 0xffffff;
   
_view.scene.addChild(_light3);
   
_light3.= -200;
   
_light3.800;

   
addChild(_view);

   
Loader3D.enableParser(OBJParser);

   
_container = new Loader3D();
   
_container.scale(10);
  
   
_container.addEventListener(LoaderEvent.RESOURCE_COMPLETEonResourceComplete);
   
_container.addEventListener(LoaderEvent.LOAD_ERRORonResourceLoadingError);

   
_container.load(new URLRequest('mymodels/wto.obj'));

   
_view.scene.addChild(_container);
   
_view.camera.lookAt(_container.position);
   
_view.camera.lens.far Vector3D.distance(_container.position_view.camera.position)+100000;
   
_view.camera.lens.near 10;

   
stage.scaleMode StageScaleMode.NO_SCALE;
   
stage.align StageAlign.TOP_LEFT;
   
stage.addEventListener(Event.RESIZEonStageResize);

  
}

  
private function onStageResize(event Event) : void
  {
   _view
.width stage.stageWidth;
   
_view.height stage.stageHeight;
  
}

  
private function onResourceComplete(away3d.events.LoaderEvent) : void
  {
   _view
.width stage.stageWidth;
   
_view.height stage.stageHeight;
   
this.addEventListener(Event.ENTER_FRAMEhandleEnterFrame);
   
setSub(_container)
  
}

  
private function setSub(Msh{
   
var mtr = new ColorMaterial(0x0000ff1)
   
mtr.ambientColor 0x0000ff
   mtr
.lights [_light3];

   var 
nc Msh.numChildren
   
if (nc>0{
    
for (var i=0i<nci++) {
     
var subMesh Mesh(Msh.getChildAt(i));
     
subMesh.material mtr;
//           subMesh.material.lights=[_light3]
           
setSub(subMesh)
    
}
   }

  }

  
private function onResourceLoadingError(e:LoaderEvent) : void
  {
    trace
("oops, model load failed");
  
}

  
private function onResourceMapsLoadingError(e:LoaderEvent) : void
  {
    trace
("A map failed to load in this model: ["+e.url+"]");
  
}

  
private function handleEnterFrame(Event) : void
  {
   _container
.rotationY += .5;
   
_view.render();
  
}
 }

Directional lights are always tricky, because if they don’t hit the target, it looks like they don’t work. My advice, use PositionLight, at least for testing.

The things I’ve altered are as follows:
1. The lights direction ((-1000000, -1000000, -1000000) !!!!!)
Away is expecting a normalised vector, values -1 to 1
2. The lights position. I suspect the light was inside you model (0,0,0), as you haven’t given it any position.
3. I’ve applied the light to the material.
4. Changed light’s diffuse and specular levels, just to make the lighting effect easier to see.

If that doesn’t work, there may be something wrong with you .obj file.

Good Luck!

 

   

rgbox, Newbie
Posted: 03 October 2011 09:59 AM   Total Posts: 12   [ # 2 ]

Thank you, theMightyAtom!

Unfortunately your varaint works the same - only if light is not attached to the material. If light is attached to the material - the error appears.

Still I’m not sure how to give new material to all loaded object parts.

I’ve uploaded project files to:
http://www.rgbox.com/TEMP/test_upload.zip - 1.14 Mbytes - contains model, material, FLA, HTML and SWF compiled without lights

For some other simple models this code works fine, with and without lights. Current model works without lights only.

 

   

Avatar
theMightyAtom, Sr. Member
Posted: 03 October 2011 11:27 AM   Total Posts: 669   [ # 3 ]

Everything points towards a parsing error of the model, i.e. the variant of .obj exported by Cinema 4D differs from the .obj format expected by Away3D.
I had some issues with 3D Studio, until I changed to another .obj exporter.
When you export from Cinema 4D, what options do you have?
Make sure you don’t export materials, if you are applying them in away3D.
(that could be a cause of your current problem). And make sure you are exporting to triangles, although you wouldn’t even be getting this far if you didn’t smile

I have a deadline myself this afternoon, but I will try and check your source later,

Cheers!

 

   

rgbox, Newbie
Posted: 03 October 2011 11:33 AM   Total Posts: 12   [ # 4 ]

In fact, the model exported from Cinema 4D does not work at all. I import it to 3d max and export back to OBJ.

 

   

Avatar
theMightyAtom, Sr. Member
Posted: 03 October 2011 11:34 AM   Total Posts: 669   [ # 5 ]

Couldn’t resist taking a peak!
Should it look like the screenshot attached?

Compiled and ran without problems, and it does use the material library correctly. Incidentally the model seems to be from 3D studio…

Make sure you are using the latest build of Away3D and the latest Flash player!

Cheers

 

   

rgbox, Newbie
Posted: 03 October 2011 11:39 AM   Total Posts: 12   [ # 6 ]

Did you turn the lights on? - uncommented the line:
//  mtr.lights = [_light3];

Yes, this model was reexported from 3d max

 

   

rgbox, Newbie
Posted: 03 October 2011 11:41 AM   Total Posts: 12   [ # 7 ]

Yes that is the correct model.
I wonder why new material is not applied (it should be all blue)

 

   

Avatar
theMightyAtom, Sr. Member
Posted: 03 October 2011 11:57 AM   Total Posts: 669   [ # 8 ]

A quick scan in 3D studio and I can see the problem. The model is corrupt.
Some faces are facing one way, some the other. you could repair it, but it would take hours as there’s no “automatic repair” button :(

I tried other models with your code and they work fine. Although this is a complex shape, it is a single mesh and would normally be quite simple to use in Away3D.

Sorry I can’t be more helpful, but if 3D Studio can’t render it correctly, there’s not much hope for Away3D to render it either.

You could try exporting from Cinema4D in a different format (Collada maybe?) as it can be that the obj exporter is causing the issue.

Good Luck!


(notice missing triangles and inverted faces (dark ones))

 

   

rgbox, Newbie
Posted: 03 October 2011 12:01 PM   Total Posts: 12   [ # 9 ]

theMightyAtom,
Thank you very much!
Your help is very important to me!

I’ll look for other options to export models

 

   

Avatar
80prozent, Sr. Member
Posted: 03 October 2011 12:10 PM   Total Posts: 430   [ # 10 ]

hi

if you use cinema 4d r10 or earlier, you can try exporting via riptide-pro-obj-plugin (its free for this versions. its available for later versions too, but not for free).

hope that helps

 

 Signature 

sorry…i hope my actionscript is better than my english…

   

rgbox, Newbie
Posted: 12 October 2011 06:00 AM   Total Posts: 12   [ # 11 ]

One problem I found and solved was normals.
Setting autoDeriveVertexNormals=true makes this model work with lights.

Another problem not solved:
I do not know how to apply new material if loaded file contains a number of objects. I made a recursion setSub(Msh), but it does not work for all objects - some parts do not obtain new material. Can you suggest a solution?

private function onResourceComplete(away3d.events.LoaderEvent) : void {
    _view
.width stage.stageWidth;
    
_view.height stage.stageHeight;
    
this.addEventListener(Event.ENTER_FRAMEhandleEnterFrame);
    
setSub(_container)
  
}

  
private function setSub(Msh{
    
var mtr = new ColorMaterial(0x0000ff1)
    
mtr.ambientColor 0x0000ff
    mtr
.lights [_light3];
    var 
nc Msh.numChildren
    
if (nc>0{
      
for (var i=0i<nci++) {
        
var subMesh Mesh(Msh.getChildAt(i));
        
subMesh.material mtr;
  for (var 
sg=0sg<subMesh.geometry.subGeometries.lengthsg++) {
         subMesh
.geometry.subGeometries[sg].autoDeriveVertexNormals true;
      
}
        setSub
(subMesh)
      
}
    }
  } 

 

   

Avatar
theMightyAtom, Sr. Member
Posted: 12 October 2011 06:12 AM   Total Posts: 669   [ # 12 ]

Firstly, realise that _container is not a Mesh.
That makes your code read funny, although it would still work.
So what you are calling a subMesh, is actually just a Mesh, inside your loader.
Apart from that, I can’t see the problem. Applying a material to a Mesh, should apply the material to all it’s submeshes.

I suspect again that it is the model, rather than the code that is causing the trouble.

 

   

rgbox, Newbie
Posted: 12 October 2011 03:16 PM   Total Posts: 12   [ # 13 ]

subMesh starts on _container (that is a Loader3D) children. That is correct. The problem is that some of details cannot be found as _container children, at least their material does not change.

 

   
   

X

Away3D Forum

Member Login

Username

Password

Remember_me



X