Welcome Guest. Please Login or Register. Mar 31st, 2018, 10:45pm
ATTENTION MEMBERS: Conforums will be closing it doors and discontinuing its service on April 15, 2018. We apologize Conforums does not have any export functions to migrate data. Ad-Free has been deactivated. Outstanding Ad-Free credits will be reimbursed to respective payment methods.
Thank you Conforums members.
Cross-platform BBC BASIC (Windows, Linux x86, Mac OS-X, Android, iOS, Raspberry Pi)
Wavefront OBJ to FVF converter
« Thread started on: Sep 15th, 2017, 8:26pm »
I was fascinated by the 3D Face Reconstruction work by the University of Nottingham and wanted to experiment with manipulating the generated 3D models in BBC BASIC. These models are downloadable as Wavefront OBJ format files, whereas of course BBC BASIC expects a Flexible Vertex Format (FVF) file; so I wrote a converter (listed below)! You can see the rather spooky result at the Facebook page.
Here's another automatic conversion from Wavefront OBJ format. The original file is downloadable as trumpet.obj; it has 11,908 nodes and 11,362 polygonal faces of order up to 36.
Another use for the converter would be to take advantage of the 3D editing capabilities of a tool such as MeshLab which can export OBJ files.
Richard.
Code:
REM Wavefront OBJ to FVF converter, Richard Russell, 15-Sep-2017 HIMEM = PAGE + 20000000 ObjFile$ = "trumpet.obj" ObjFile% = OPENIN(ObjFile$) IF ObjFile%=0 ERROR 100, "Can't open file " + ObjFile$ IF RIGHT$(ObjFile$,4)=".obj" OR RIGHT$(ObjFile$,4)=".OBJ" THEN FVFfile$ = LEFT$(ObjFile$,LEN(ObjFile$)-4) + ".fvf" ELSE FVFfile$ = ObjFile$ + ".obj" ENDIF FVFfile% = OPENOUT(FVFfile$) IF FVFfile%=0 ERROR 100, "Can't create file " + FVFfile$ PTR#FVFfile% = 8 DIM c(100000,2), v(100000,2), t(100000,1), n(100000,2), p(2) nv% = 0 : REM Number of vertices nt% = 0 : REM Number of texture coordinates nn% = 0 : REM Number of normals nf% = 0 : REM Number of triangular faces vf% = &012 : REM Initial vertex format xsum = 0 ysum = 0 zsum = 0 WHILE NOT EOF#ObjFile% a$ = GET$#ObjFile% CASE LEFT$(a$,2) OF WHEN "v ": v(nv%,0) = FNn(a$) : v(nv%,1) = FNn(a$) : v(nv%,2) = FNn(a$) c(nv%,0) = FNn(a$) : c(nv%,1) = FNn(a$) : c(nv%,2) = FNn(a$) IF c(nv%,1) <> 0 OR c(nv%,2) <> 0 vf% OR= &040 : REM Include diffuse colour nv% += 1 WHEN "vt": t(nt%,0) = FNn(a$) : t(nt%,1) = FNn(a$) IF t(nv%,0) <> 0 OR t(nv%,1) <> 0 vf% OR= &100 : REM Include texture coords nt% += 1 WHEN "vn": n(nn%,0) = FNn(a$) : n(nn%,1) = FNn(a$) : n(nn%,2) = FNn(a$) nn% += 1 WHEN "f ": t1% = 0 : t2% = 0 : t3% = 0 : n1% = 0 : n2% = 0 : n3% = 0 v1% = FNn(a$) : IF ASCa$=&2F t1% = FNn(a$) : IF ASCa$=&2F n1% = FNn(a$) v2% = FNn(a$) : IF ASCa$=&2F t2% = FNn(a$) : IF ASCa$=&2F n2% = FNn(a$) IF v1% > 0 v1% -= 1 ELSE v1% += nv% IF v2% > 0 v2% -= 1 ELSE v2% += nv% IF t1% > 0 t1% -= 1 ELSE t1% += nt% IF t2% > 0 t2% -= 1 ELSE t2% += nt% IF n1% > 0 n1% -= 1 ELSE n1% += nn% IF n2% > 0 n2% -= 1 ELSE n2% += nn% REPEAT v3% = FNn(a$) : IF ASCa$=&2F t3% = FNn(a$) : IF ASCa$=&2F n3% = FNn(a$) IF v3% = 0 EXIT REPEAT IF v3% > 0 v3% -= 1 ELSE v3% += nv% IF t3% > 0 t3% -= 1 ELSE t3% += nt% IF n3% > 0 n3% -= 1 ELSE n3% += nn% REM Vertex coordinates: x1 = v(v1%,0) : y1 = v(v1%,1) : z1 = v(v1%,2) x2 = v(v2%,0) : y2 = v(v2%,1) : z2 = v(v2%,2) x3 = v(v3%,0) : y3 = v(v3%,1) : z3 = v(v3%,2) REM Vertex colour: R1 = c(v1%,0) : G1 = c(v1%,1) : B1 = c(v1%,2) R2 = c(v2%,0) : G2 = c(v2%,1) : B2 = c(v2%,2) R3 = c(v3%,0) : G3 = c(v3%,1) : B3 = c(v3%,2) REM Texture coordinates: u1 = t(t1%,0) : v1 = t(t1%,1) u2 = t(t2%,0) : v2 = t(t2%,1) u3 = t(t3%,0) : v3 = t(t3%,1) REM Normals: IF n1% IF n2% IF n3% THEN p1 = 0 : q1 = 0 : r1 = 0 p2 = 0 : q2 = 0 : r2 = 0 p3 = 0 : q3 = 0 : r3 = 0 ON ERROR LOCAL IF FALSE THEN p(0) = n(n1%,0) : p(1) = n(n1%,1) : p(2) = n(n1%,2) p() /= MOD(p()) : p1 = p(0) : q1 = p(1) : r1 = p(2) p(0) = n(n2%,0) : p(1) = n(n2%,1) : p(2) = n(n2%,2) p() /= MOD(p()) : p2 = p(0) : q2 = p(1) : r2 = p(2) p(0) = n(n3%,0) : p(1) = n(n3%,1) : p(2) = n(n3%,2) p() /= MOD(p()) : p3 = p(0) : q3 = p(1) : r3 = p(2) ENDIF : RESTORE ERROR ELSE a = x3 - x2 b = y3 - y2 c = z3 - z2 d = x1 - x3 e = y1 - y3 f = z1 - z3 p(0) = b*f-c*e p(1) = c*d-a*f p(2) = a*e-b*d IF MOD(p()) <> 0 p() /= MOD(p()) p1 = p(0) : q1 = p(1) : r1 = p(2) p2 = p(0) : q2 = p(1) : r2 = p(2) p3 = p(0) : q3 = p(1) : r3 = p(2) ENDIF PROC4(FVFfile%,FN4(x1)) : PROC4(FVFfile%,FN4(y1)) : PROC4(FVFfile%,FN4(z1)) PROC4(FVFfile%,FN4(p1)) : PROC4(FVFfile%,FN4(q1)) : PROC4(FVFfile%,FN4(r1)) IF vf% AND &040 THEN BPUT#FVFfile%,B1*&FF BPUT#FVFfile%,G1*&FF BPUT#FVFfile%,R1*&FF BPUT#FVFfile%,&FF ENDIF IF vf% AND &100 PROC4(FVFfile%,FN4(u1)) : PROC4(FVFfile%,FN4(v1)) PROC4(FVFfile%,FN4(x2)) : PROC4(FVFfile%,FN4(y2)) : PROC4(FVFfile%,FN4(z2)) PROC4(FVFfile%,FN4(p2)) : PROC4(FVFfile%,FN4(q2)) : PROC4(FVFfile%,FN4(r2)) IF vf% AND &040 THEN BPUT#FVFfile%,B2*&FF BPUT#FVFfile%,G2*&FF BPUT#FVFfile%,R2*&FF BPUT#FVFfile%,&FF ENDIF IF vf% AND &100 PROC4(FVFfile%,FN4(u2)) : PROC4(FVFfile%,FN4(v2)) PROC4(FVFfile%,FN4(x3)) : PROC4(FVFfile%,FN4(y3)) : PROC4(FVFfile%,FN4(z3)) PROC4(FVFfile%,FN4(p3)) : PROC4(FVFfile%,FN4(q3)) : PROC4(FVFfile%,FN4(r3)) IF vf% AND &040 THEN BPUT#FVFfile%,B3*&FF BPUT#FVFfile%,G3*&FF BPUT#FVFfile%,R3*&FF BPUT#FVFfile%,&FF ENDIF IF vf% AND &100 PROC4(FVFfile%,FN4(u3)) : PROC4(FVFfile%,FN4(v3)) xsum += x1 + x2 + x3 ysum += y1 + y2 + y3 zsum += z1 + z2 + z3 nf% += 1 v2% = v3% : t2% = t3% : n2% = n3% UNTIL FALSE ENDCASE ENDWHILE CLOSE #ObjFile% PRINT "Total number of vertices = "; nv% PRINT "Total number of texture coordinates = "; nt% PRINT "Total number of normals = "; nn% PRINT "Total number of faces = "; nf% PRINT "Mean X = "; xsum / nf% / 3 PRINT "Mean Y = "; ysum / nf% / 3 PRINT "Mean Z = "; zsum / nf% / 3 vs% = 24 : REM Vertex size (bytes) IF vf% AND &040 vs% += 4 IF vf% AND &100 vs% += 8 PTR#FVFfile% = 0 PROC4(FVFfile%, nf%*3) PROC4(FVFfile%, vf% OR vs% << 16) CLOSE #FVFfile% PRINT "Output file '"; FVFfile$; "' created" END DEF FNn(RETURN a$) IF ASCa$=&2F a$ = MID$(a$,2) : = VAL(a$) WHILE ASCa$>&20 : a$ = MID$(a$,2) : ENDWHILE WHILE ASCa$=&20 : a$ = MID$(a$,2) : ENDWHILE = VAL(a$) DEF PROC4(F%,N%) BPUT#F%,N% : BPUT#F%,N%>>8 : BPUT#F%,N%>>16 : BPUT#F%,N%>>24 ENDPROC DEF FN4(a#)LOCALP%:P%=^a#:IFa#=FALSE THEN=FALSE =P%!4ANDNOT&7FFFFFFFOR(P%!4-&38000000<<3OR!P%>>29AND7)+(!P%>>28AND1)
What do you mean by a B3D file? That extension normally refers to a Blitz 3D file (used by Blitz BASIC) which has nothing to do with BBC BASIC. I accidentally used the same extension in the early days for 3D files used by BBC BASIC, but that caused great confusion: the formats have nothing in common.
So now I always use the extension FVF (flexible vertex format) for the 3D files accepted by FN_load3D in D3DLIB(A), OGLLIB and GLESLIB, i.e. the file format described here. You should already be aware of that, because you know that BB4W and BBCSDL are highly compatible in their 3D functionality, which is why Rubik.bbc for example runs equally well in either version without modification.
To avoid perpetuating the confusion please use the extension FVF rather than B3D for BBC BASIC's 3D files. My OBJ to FVF converter creates the right kind of file for use with BB4W and BBCSDL, of course! I'm not stupid, well not totally stupid, well....
I am quite surprised. Both me and DDRM have been using this code from your lessons
As you should know, BB4W is supplied with the files BASE.B3D and PYRAMID.B3D (in the EXAMPLES\GRAPHICS folder) so everybody ends up with those files on their disk and I can't make them 'disappear'! Even if I were to change their names in the BB4W distribution, the new files would be stored in addition to the old ones rather than replacing them.
So my judgement was that little would be achieved, other than perhaps even more confusion, by retrospectively changing the extension of the files supplied with BB4W. However you should find that I have consistently used the FVF extension in the context of BBCSDL, so for example the equivalent files supplied with that product are base.fvf and pyramid.fvf. They are the same files, just renamed.
I thought I had made it perfectly clear that the 3D libraries for BBCSDL - ogllib.bbc and gleslib.bbc - are designed to be as compatible as possible with D3DLIBA. That was after all the whole point: to make writing cross-platform programs as painless an exercise as possible (the main residual incompatibility being that the BBCSDL libraries will only accept textures in BMP format). As I said in my previous message, Rubik.bbc runs on both BB4W and BBCSDL without any modification.
Therefore I don't really understand how you came to the conclusion that the (BB4W) B3D and FVF file formats are different. What is certainly the case is that the original Blitz3D variety of B3D file is still in common use and you can find many examples online. There was even a post made to a Blitz forum pointing out (incorrectly) that BB4W uses the same file format. The potential for confusion was far too great for it to be allowed to continue.
I cannot comment on the decision of the admin of the 'other' BB4W forum to continue to use the B3D extension. Perhaps he feels that the FVF extension is associated with BBCSDL, which neither he nor his forum supports.
Re: Wavefront OBJ to FVF converter
« Reply #5 on: Sep 16th, 2017, 1:22pm »
Richard, it isn't the files that are at issue. The HELP section in BBC4W, when accessing direct 3D uses the B3D format. I am sure it was just overlooked by DDRM as it wasn't the focus of the goal to make the tools.
I can focus on the FVF extension if there is an issue concerning the other extension. Like with languages, I doubt that a file format can cause issues, aside from giving attention to the other Basic platform.
BBC Basic is far easier than the other language you mentioned.
Also I must say, your work on that converter is a fantastic creation. I have been looking for an OBJ converter for basic for years. (since around 2009
And it really is no big issue, as I see that the code you supplied for FVF and B3D examples are identical:
Code:
DEF PROCcreate3d F% = OPENOUT"TRIANGLE.B3D" PROC4(3):REM 3 vertices PROC4(&100042):REM vertex size &10 and format &42 REM LL x LL y LL z LL colour PROC4(FN_f4(-1.0)):PROC4(FN_f4(-1.0)):PROC4(FN_f4(1.0)):PROC4(&FF0000FF) REM LR x LR y LR z LR colour PROC4(FN_f4(1.0)):PROC4(FN_f4(-1.0)):PROC4(FN_f4(1.0)):PROC4(&FF00FF00) REM PEAK X PEAK Y PEAK Z Peak colour PROC4(FN_f4(0.0)):PROC4(FN_f4(1.0)):PROC4(FN_f4(0.0)):PROC4(&FFFF0000) CLOSE #F% ENDPROC : DEF PROC4(A%):BPUT#F%,A%:BPUT#F%,A%>>8:BPUT#F%,A%>>16:BPUT#F%,A%>>24:ENDPROC
Code:
F% = OPENOUT"TRIANGLE.FVF" PROC4(3):REM 3 vertices PROC4(&100042):REM vertex size &10 and format &42 PROC4(FN_f4(-1.0)):PROC4(FN_f4(-1.0)):PROC4(FN_f4(1.0)):PROC4(&FF0000FF) PROC4(FN_f4(1.0)):PROC4(FN_f4(-1.0)):PROC4(FN_f4(1.0)):PROC4(&FF00FF00) PROC4(FN_f4(0.0)):PROC4(FN_f4(1.0)):PROC4(FN_f4(0.0)):PROC4(&FFFF0000) CLOSE #F% DEF PROC4(A%):BPUT#F%,A%:BPUT#F%,A%>>8:BPUT#F%,A%>>16:BPUT#F%,A%>>24:ENDPROC
Richard, it isn't the files that are at issue. The HELP section in BBC4W, when accessing direct 3D uses the B3D format.
There is no such thing as "B3D format" (or, if you prefer to look at it this way, it's the format of Blitz 3D object files which isn't used by BBC BASIC). Admittedly the code example in the Help file creates a file with the .B3D extension but it's not the extension that defines the file's contents - it's how you create the file! The extension could be anything at all and it would still work.
I don't see what I could have done differently, other than not making the (stupid) mistake of misusing the B3D extension in the first place. Obviously I hugely regret that mistake, as I do the many other stupid decisions that I made when originally creating BB4W. It's one reason why it would have been far better if BBC BASIC for Windows had never existed.
But I did make those mistakes and it's something I have to live with every day (or perhaps not live with, and that's an option I consider every day too). All I can do now is to attempt to put things right as far as possible by no longer using the misleading B3D extension, but you seem to think that is yet another mistake. Argggh!!!!
I can't claim that excuse. Before adopting the B3D extension I should have looked it up on a site like filext.com (quite different then from what it is now) when I would have discovered its existing use(s).
Re: Wavefront OBJ to FVF converter
« Reply #9 on: Sep 17th, 2017, 09:06am »
Has anybody else tried the Nottingham University 3D Face Reconstruction tool? It's very easy to use: Find a full-face straight-on selfie (preferably without glasses), with good contrast between your face and the background, and upload it here.
When it has finished processing, download the generated .OBJ file and convert it to a .FVF using the code I listed previously in this thread.
Plug the FVF file into the program below if you want to use the same animation as I did for Donald Trump, or adapt it to your preference.
Upload a video capture to YouTube (etc.), so we can see the result, if you dare!Richard.
Code:
REM. Turning Face by Richard Russell, 16-Sep-2017 HIMEM = PAGE + 5000000 IF INKEY$(-256)="W" INSTALL @lib$+"D3DLIBA" ELSE INSTALL @lib$+"ogllib" ON CLOSE PROCcleanup : QUIT ON ERROR PROCcleanup : IF ERR=17 CHAIN @lib$+"../examples/tools/touchide" ELSE MODE 3 : PRINT REPORT$ : END ON MOVE IF @msg% <> 5 RETURN ELSE PROCcleanup : CLEAR VDU 20,26,12 DIM pVB%(0), nv%(0), vf%(0), vl%(0), l%(0), m%(0), t%(0), y(0), p(0), r(0) DIM X(0), Y(0), Z(0), eye(2), at(2) REM. Initialise OpenGL: IF INKEY$(-256)="W" pDev% = FN_initd3d(@hwnd%, 1, 0) ELSE pDev% = FN_initgl(@hwnd%, 1, 0) IF pDev% = 0 ERROR 100, "Couldn't initialise 3D subsystem" REM. Load 3D object: pVB%(0) = FN_load3d(pDev%, @dir$ + "trump.fvf", nv%(0), vf%(0), vl%(0)) IF pVB%(0) = 0 ERROR 101, "Couldn't load FVF file" REM. Render the turning face: at() = 100, 100, 40 REPEAT turn = SIN(TIME/100) eye() = at(0)+400*SIN(turn), 0, at(2)+400*COS(turn) PROC_render(pDev%, &7F7F90, 0, l%(), 1, m%(), t%(), pVB%(), nv%(), vf%(), vl%(), \ \ y(), p(), r(), X(), Y(), Z(), eye(), at(), PI/6, @vdu%!208/@vdu%!212, 1, 1000, PI) UNTIL INKEY(1)=0 END DEF PROCcleanup pVB%(0) += 0 : IF pVB%(0) PROC_release(pVB%(0)) *REFRESH ON ENDPROC