Näytetään tekstit, joissa on tunniste Blender. Näytä kaikki tekstit
Näytetään tekstit, joissa on tunniste Blender. Näytä kaikki tekstit

torstai 19. marraskuuta 2015

Ken Burns effect with Blender VSE

I made an exhibition video to Vantaa City Museum to their current exhibition about river Vantaa (Vantaanjoki). I was given texts, images of paintings, some photographs and an old map. Three videos was needed: the main video with texts and images, and two ambience videos - that were projected to ceiling - consisting just Ken Burns effects.

Video editing and Blender

I haven't made video editing recently, although I have even taught that several years ago. Back then I was using Adobe Premiere. Now I'm on Linux (Debian) so I had to search new tools for videoediting.

First I tried shortly OpenShot and Natron. Basically, Openshot was just too simple and Natron too complex, although Natron was very interesting. I made some test with OpenShot but I had problems with jerky motion in Ken Burns effects.

I ended up to using Blender.  I was familiar with the user interface of Blender but I wasn't sure about the usefulness of Blender's VSE (Video Sequence Editor).

 

VSE

I needed several Ken Burns effects so making those was my main concern. I found out that it is possible to add transform strip over existing strip. At transform strip there are position and scale values that can be animated. So, I had a Ken Burns effect.

But making those with adjusting sliders was quite impractical. It would have been so much easier to transform and scale strips by dragging them with the mouse.

But hey, it's Blender! Surely there must be some nice trick for this. And there was: vse transform tool. And BUM! Making Ken Burns effects was easy and fun.

 

Making Ken Burns effect with VSE

Shortly: add transform strip (T) to a image strip, drag and scale image strip in preview window where ever you like, add keyframes to position and scale properties of the strip, move to the end frame of the effect and do same there. Done!


I used Gimp for making transparencies and other image editing needs. Texts I made also with Gimp. I saved texts in Gimp's own xfc format and then exported as png images. Things go smoothly when one uses the final presentation resolution from the very beginning. It is important to know the final presentation resolution in a very early stage so that you don't have remake any of your image files.

 

Conslusion?

I learnt that VSE is a really capable tool for this kind of work. At least, If you know the user interface already. Otherwise there is some work to do with the basics of Blender.




PS. at 1.35 my son throws a stone to the river. He was getting bored while I was filming the ripples of the water...


lauantai 20. huhtikuuta 2013

3D verkossa ilman lisäosia (WebGL + X3DOM + Javascript)


Reaaliaikaisten 3D-materiaalien käyttö verkossa on tähän asti vaatinut erilaisten lisäosien asennusta. Tämä on ollut äärimmäisen kömpelöä sekä harvoin alustariippumatonta. Lisäksi erilaiset suljetut formaatit ovat asettaneet sisällöt vaaraan. Digitaalisen kulttuuriperinnön näkökulmasta tärkeää on, että työtä ei tehdä turhaan eikä aineistoja kadoteta sitä mukaa kun kaupallisten tuotteiden tuki lakkaa.

Uusimmat selaimet (Microsoftin selainta lukuunottamatta) eivät enää välttämättä tarvitse laajennuksia kolmiulotteisen sisällön näyttämiseen. WebGL:n avulla selain voi käyttää hyväkseen 3D-näytönohjaimen ominaisuuksia suoraan.

Tekniikka itsessään ei vielä tietenkään vielä riitä. Malli täytyy saada näkymään tässä formaatissa ja siihen pitää lisätä tietoja ja mahdollisesti interaktiivisuutta. X3D on standardoitu XML-formaatti 3D-materiaaleille ja X3DOM on javascript-kirjasto, jonka avulla X3D-tiedostoja voidaan kääntää WebGL:n ymmärtämään muotoon.


Petäjäveden vanhan kirkon virtuaalirekonstruktio X3DOM-versiona.

Tein yksinkertaisen demon, jossa käytin aikaisemmin tekemääni Petäjäveden vanhan kirkon mallia. Malli on tallennettu X3D-formaattiin Blenderissä eikä sitä ole käsin muokattu. Koska 3D-objektit ovat osa normaalia DOM-rakennetta, pääsee niihin käsiksi kuten verkkosivun elementteihinkin. Tämä tietysti edellyttää, että mallintaja on ollut johdonmukainen objektien nimeämisessä. Esimerkiksi kaikki ikkunat voidaan helposti piilottaa, jos ne on nimetty "ikkuna_2", "ikkuna_3" ja niin edelleen. Nyt tarvitsee vain etsiä kohteet, joiden alussa on sana "ikkuna" ja asettaa niiden renderointi pois päältä.

Kokeilun pohjalta X3DOM vaikuttaa erinomaiselta lähestymistavalta. Se yhdistää standardin formaatin viimeisimpään selainteknologiaan. Mallit ovat turvassa vaikka javascript ja WebGL tulevat katoamaan ennemmin tai myöhemmin.

Demo löytyy täältä:
http://opendimension.org/reconstructions/petajavesi/



tiistai 14. elokuuta 2012

Updating Blender script -> 2.63

Pyramidaze! in action.

Blender is evolving...


Blender is evolving fast which is a good thing. A bad thing is that also its Python API is changing thus breaking old scripts. But updating old scripts is a good way to learn the new API.

So, I updated my really old pyramidaze script. This simple script iterates through selected faces of the object and adds a pyramid top of them (see image above).

Blender now supports NGons which means that the API has changed also. There were two major changes in this case. The way polygons are accessed has changed due the NGons. Secondly, the API does not provide a polygon center any more, so center must be calculated in the script.

You can find a blend file including the script from here.
http://www.opendimension.org/blender_en/blends/pyramidaze_2.63.blend

tiistai 21. joulukuuta 2010

Using threads in Blender game engine




I just made an experiment of using threads in Blender's game engine. Even though using threads in Python does not necessarily make code any faster (see GIL), in this case using thread(s) has a really big difference.

AFAIK, rendering and execution of python scripts are running sequential in BGE. This is a bad thing if you have to make some heavy lifting in the script. Whole game engine have to wait until the job is done ruining your FPS. By using threads, the heavy lifting can be done parallel (or at least semiparallel) to main rendering loop.

The script can be found from Blenderartists.

maanantai 20. joulukuuta 2010

Towards Blender 2.55





I had a little break from Blender but now its time to go back and see what devs have been doing. I just converted my old pyramidaze script for 2.55. It is REALLY simple but it was my first python script back in 2006 :)

It just iterates through selected faces of the object and adds a pyramid top of them (see image above).

Here is 2.55 version:
#**********************************************************************************************
#pyramidaze.py
# - This script adds a "pyramid" over every selected face
#
# - Open this file in the Blender's text window
# - Select faces
# - set settings (see below)
# - run script (Alt + P)
# 
# there is nothing special in this script but it shows how to iterate 
# through all faces in selected object, how to get normal and how to 
create new mesh object.
#
# Feel free to use this script any way you like, I'm sure this is very useful ;)
#
#Ari Hayrinen 29.11.2006 
# updated for Blender 2.55 20.12.2010
#www.opendimension.org/blender_en
#
# TODO:
# - GUI 
# 
#*************************************************************************************************

import bpy
import mathutils

#************************************************************************************************
# settings
#************************************************************************************************
py_height = 1       # pyramid height if use_area is 0, negative value inverts pyramid
use_area = 1        # if 1, uses face area as pyramid height
area_multi = 1      # multiplier for face area, negative values inverts pyramid



#********************************************************************************
#main
#*********************************************************************************

objekti = bpy.context.active_object
scene = bpy.context.scene

# list for new faces
coords = []
faces = []

# counter so we know where to add new faces 
verts = 0  
vertices = objekti.data.vertices


# let's go through all faces in selected object
for face in objekti.data.faces:
#use only selected faces    

if face.select:


center = face.center

#number of vertices
vco = len(face.vertices) 

if use_area:
py_height = face.area * area_multi


#multiple normal with pyramid height and add result to the center of the face
center.x = center.x + face.normal[0] * py_height
center.y = center.y + face.normal[1] * py_height
center.z = center.z + face.normal[2] * py_height

#create vertices 
coords.append([center.x,center.y,center.z])
verts +=1

for i in range(vco):
coords.append(vertices[face.vertices[i]].co)
verts +=1


#create triangles
cco = vco + 1                        # number of created vertices
for j in range(vco):    
if j < (vco-1):
faces.append([verts-cco, verts-(cco-(j+1)), verts-(vco-j-1)])
else:
faces.append([verts-cco, verts-(cco-(j+1)), verts-(cco-1)])


# Create new mesh block and add faces to it
mesh = bpy.data.meshes.new('myMesh')

mesh.from_pydata(coords,"",faces)
mesh.update()

new_obj = bpy.data.objects.new("koe", mesh)
scene.objects.link(new_obj)

new_obj.location = objekti.location

perjantai 15. toukokuuta 2009

Blender and Physical Computing


During a Physical Computing class here at the University of Jyväskylä, I made a small experiment with Blender and Arduino. I build a very simple prototype called CHEEX (Cheap Exhibition Expander).

The idea is that instead of traditional exhibition posters or information kiosks, one could use any part of the exhibition room as a display by using data projector and servo-controlled mirror. By using sensors it is possible to react visitors and show them more information when they get near objects.

The Blender part


Blender has a virtual camera which is pointing to a target object. This target object is then animated and the camera naturally follows it. The rotations of the camera are then sent to Arduino, which controls two axis servo system which has a mirror attached to it.

Inside Blender I have a normal scene with camera, the target object and some other objects. Blender scene can be modelled according the exhibition room so that virtual camera and mirror points to same spot. Then it is possible to combine physical space with virtual space.

Technicalities


Technically system is very simple. I used very simple protocol between Blender and Arduino. By sending sequences of three bytes, I could quite easily send rotations to Arduino. First Blender sends "255" and then angle for root servo and then angle for head servo. Arduino is reading serial port and when it receives 255, it knows that following two bytes are the angles for the servos.

System also has one ultrasonic sensor and value from that sensor is send back to Blender every time Blender sends the angle values for servos. This way everything stays in sync and there is no problems with serial port buffer overflows.

System has still one major problem. Servos are connected directly to Arduino and they are using too much power. This makes the readings from the ultrasonic sensor unreliable when servos are moving (at least I *think* that is causing this). I sort of resolved the problem by taking an average of several values but that can be considered a hack. I'll order a motorshield for Arduino and test if using it will resolve the problem.

perjantai 17. huhtikuuta 2009

Bouncing virtual ball with Arduino (and Blender)

UPDATED 20.4.2009






I'm quite new on this Arduino stuff and I may have misunderstood something. But anyway, here are some observations of using Arduino and Blender's game engine.

It's easy!

It is really easy to get values from Arduino to Blender. Here is a simple setup for reading photo-resistor's values from Blender:
from Blender.Mathutils import Vector import serial 
port = '/dev/ttyUSB0' 
pin = 0 
try: 
    GameLogic.SerialPort 
except: 
    GameLogic.SerialPort = serial.Serial(port,9600) 

# read data 
valo = GameLogic.SerialPort.readline() 
val = float(valo)/200 

# BLENDER stuff 

objs = GameLogic.getCurrentScene().getObjectList() 
cube = objs["OBbox"] 
cube.setPosition([1.0,1.0,val])


Here I'm reading photoresistor values and then tell Blender's game-engine to change "box" object's position according that value. The arduino code looks like this:

/* Arduino reading photo resistor to serial * * */ 
int analogPin=0; 
int analogVal=0; 
void setup() { Serial.begin(9600); } 
void loop() { 
    // get the value from photoresistor 
    analogVal = analogRead(analogPin); 
    Serial.println(analogVal); 
    //delay(100);
}


Not so fast!



There is a one catch when reading data from Arduino to Blender. And that's the fact that python scripts are executed on every frame and that mean that you'll read data from serial port approx. 60 times per second.

However, Arduino is sending data much faster. As a result, you'll see a horrible delay in Blender. That's because the data arduino sent is buffered and you are actually reading from buffer. So you'll get "historical" values from serial port, not the current values. And for interactive application that is not wanted.

There are couple of ways to fix this:

The simplest way is to program Arduino to send data more rarely. You could use delay function if there is nothing else that Arduino should do (delay halts everything in Arduino).

Request/response model


Better and more predictable way is to tell Arduino when we want to get a value. So when we want a value, we send a signal to arduino to send data and then we read the value. This way we'll always get the current values no matter of how high or low our frame rates are.

(I *think* that it would be also possible to run a separate python thread for Arduino input and just read values from that thread)


port = '/dev/Arduino' 
pin = 0 
 
try: 
    GameLogic.SerialPort 
except: 
    try: 
        GameLogic.SerialPort = serial.Serial(port,9600,timeout=1)  
        print 'Port ' + port + 'found!' 
         
        #ok, we have a port. Let's test if we can write to it 
        try: 
            GameLogic.SerialPort.write('x') 
            GameLogic.serialRead = False 
            GameLogic.serialOk = True 
              
        except: 
            GameLogic.serialOk = False 
            print 'could not write to port ' + port + '!' 
         
         
    except: 
        GameLogic.serialOk = False 
        print 'no port ' + port + ' found!' 
     
 
 
# do stuff if serial port is OK 
if GameLogic.serialOk: 
    if GameLogic.serialRead: 
        valo = GameLogic.SerialPort.readline() 
        val = float(valo)/100 
        GameLogic.serialRead = False     
    else: 
        GameLogic.SerialPort.write('a') 
        GameLogic.serialRead = True     
     
 
    # BLENDER stuff 
    if GameLogic.serialRead == False: 
        objs = GameLogic.getCurrentScene().getObjectList() 
        cube = objs["OBbox"] 
        cube.setPosition([1.0,1.0,val])


When Blender is ready to receive a value from Arduino, it send character "a" to the Arduino. Arduino sent one value and that is read next round. Arduino code is very simple:
int analogPin=0;
int analogVal=0;

void setup() {
  Serial.begin(9600);
}

void loop() {
  if ( Serial.available()) {
    char ch = Serial.read();
    if ('a'==ch) {
      analogVal = analogRead(analogPin);
      Serial.println(analogVal);
    }
  }
}

Here is a very simple demo using photoresistor to control a box's position. A top of box there is a ball so you can bounce the ball with adjusting the amount of light.





That's it!