Pc-Trace

<< 2024年9月 >>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30






Pc-Trace
PC-Trace

< next Blenderの記事 prev >
01/20(日)
画像ファイルがあります 添付ファイルがあります
>>このカテゴリーの記事一覧

「Coffee Break」 Blender2.80を入れてみたが・・

そろそろ何か始めないと・・

FBで "清々しい" 気持ちになれると書かれていた「Blender2.8」を好奇心から install。

リンク:https://www.blender.org/



起動した画面に全力で拒否されている感が否めない。
何をどう操作すれば ??

"清々しい" 気持ちになれるのが良く理解できた!
仕事の合間で手軽に扱えるソフトでは無さそうだ。

※インストーラ版では旧バージョンがアンイストールされてしまう?ようなので、旧バージョンのデータを継続して使いたい場合、「zip」版の方が良いかもしれない。


「Inkscape」 プラグイン整備中のテスト

個人的なテスト:

Inkscapeの迷路プラグイン整備中。 Inkscape0.92.3 動いた。


InkscapeからBlenderに移して立体化
ちなみに上のパターンとは別物。(こちらは最初のテスト)


横長なのは円筒で端々がつながる迷路になっており、これは平面展開したもの。
テストなので・・。

Python・迷路ソース

#!/usr/bin/env python

# Draw a cylindrical maze suitable for plotting with the Eggbot
# The maze itself is generated using a depth first search (DFS)

# Written by Daniel C. Newman for the Eggbot Project
# Improvements and suggestions by W. Craig Trader
# 20 September 2010

# Update 26 April 2011 by Daniel C. Newman
#
# 1. Address Issue #40
# The extension now draws the maze by columns, going down
# one column of cells and then up the next column. By using
# this technique, the impact of slippage is largely limited
# the the West and East ends of the maze not meeting. Otherwise,
# the maze will still look quite well aligned both locally and
# globally. Only very gross slippage will impact the local
# appearance of the maze.
#
# Note that this new drawing technique is nearly as fast as
# the prior method. The prior method has been preserved and
# can be selected by setting self.hpp = True. ("hpp" intended
# to mean "high plotting precision".)
#
# 2. Changed the page dimensions to use a height of 800 rather
# than 1000 pixels.
#
# 3. When drawing the solution layer, draw the ending cell last.
# Previously, the starting and ending cells were first drawn,
# and then the solution path itself. That caused the pen to
# move to the beginning, the end, and then back to the beginning
# again to start the solution path. Alternatively, the solution
# path might have been drawn from the end to the start. However,
# just drawing the ending cell last was easier code-wise.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

import sys
import array
import random
import math
import inkex
import simplestyle

# Initialize the psuedo random number generator
random.seed()

PLOT_WIDTH = int( 3200 ) # Eggbot plot width in pixels
PLOT_HEIGHT = int( 800 ) # Eggbot plot height in pixels

TARGET_WIDTH = int( 3200 ) # Desired plot width in pixels
TARGET_HEIGHT = int( 600 ) # Desired plot height in pixels

# Add a SVG path element to the document
# We could do this just as easily as a polyline

def draw_SVG_path( pts, c, t, parent ):
if ( pts is None ) or len( pts ) == 0: # Nothing to draw
return
if isinstance( pts, list ):
assert len( pts ) % 3 == 0, "len(pts) must be a multiple of three"
d = "%s %d,%d" % ( pts[0], pts[1], pts[2] )
for i in range( 3, len( pts ), 3 ):
d += " %s %d,%d" % ( pts[i], pts[i+1], pts[i+2] )
elif isinstance( pts, str ):
d = pts
else:
return
style = { 'stroke':c, 'stroke-width':str( t ), 'fill':'none' }
line_attribs = { 'style':simplestyle.formatStyle( style ),'d':d }
inkex.etree.SubElement( parent, inkex.addNS( 'path','svg' ), line_attribs )

# Add a SVG rect element to the document

def draw_SVG_rect( x, y, w, h, c, t, fill, parent ):
style = { 'stroke':c, 'stroke-width':str( t ), 'fill':fill }
rect_attribs = { 'style':simplestyle.formatStyle( style ),
'x':str( x ), 'y':str( y ),
'width':str( w ), 'height':str( h ) }
inkex.etree.SubElement( parent, inkex.addNS( 'rect', 'svg' ),
rect_attribs )

class Maze( inkex.Effect ):

# Each cell in the maze is represented using 9 bits:
#
# Visited -- When set, indicates that this cell has been visited during
# construction of the maze
#
# Border -- Four bits indicating which if any of this cell's walls are
# part of the maze's boundary (i.e., are unremovable walls)
#
# Walls -- Four bits indicating which if any of this cell's walls are
# still standing
#
# Visited Border Walls
# x x x x x x x x x
# W S E N W S E N

_VISITED = 0x0100
_NORTH = 0x0001
_EAST = 0x0002
_SOUTH = 0x0004
_WEST = 0x0008

def __init__( self ):

inkex.Effect.__init__( self )

self.OptionParser.add_option(
"--tab", action="store", type="string",
dest="tab", default="controls",
help="The active tab when Apply was pressed" )
self.OptionParser.add_option(
"--mazeSize", action="store", type="string", dest="mazeSize",
default="MEDIUM", help="Difficulty of maze to build" )
#self.OptionParser.add_option(
# "--hpp", action="store", type="inkbool", dest="hpp", default=False,
# help="Use a faster plotting technique that requires much better plotting precision" )
#self.hpp = self.options.hpp

self.hpp = False

self.w = int( 0 )
self.h = int( 0 )
self.solved = int( 0 )
self.start_x = int( 0 )
self.start_y = int( 0 )
self.finish_x = int( 0 )
self.finish_y = int( 0 )
self.solution_x = None
self.solution_y = None
self.cells = None

# Drawing information
self.scale = float( 25.0 )
self.last_point = None
self.path = ''

def effect( self ):

# These dimensions are chosen so as to maintain integral dimensions
# with a ratio of width to height of TARGET_WIDTH to TARGET_HEIGHT.
# Presently that's 3200 to 600 which leads to a ratio of 5 and 1/3.

if self.options.mazeSize == 'SMALL':
self.w = int( 32 )
self.h = int( 6 )
elif self.options.mazeSize == 'MEDIUM':
self.w = int( 64 )
self.h = int( 12 )
elif self.options.mazeSize == 'LARGE':
self.w = int( 96 )
self.h = int( 18 )
else:
self.w = int( 128 )
self.h = int( 24 )

# The large mazes tend to hit the recursion limit
limit = sys.getrecursionlimit()
if limit < ( 4 + self.w * self.h ):
sys.setrecursionlimit( 4 + self.w * self.h )

maze_size = self.w * self.h
self.finish_x = int( self.w - 1 )
self.finish_y = int( self.h - 1 )
self.solution_x = array.array( 'i', range( 0, maze_size ) )
self.solution_y = array.array( 'i', range( 0, maze_size ) )
self.cells = array.array( 'H', range( 0, maze_size ) )

# Remove any old maze
for node in self.document.xpath( '//svg:g[@inkscape:label="1 - Maze"]', namespaces=inkex.NSS ):
parent = node.getparent()
parent.remove( node )

# Remove any old solution
for node in self.document.xpath( '//svg:g[@inkscape:label="2 - Solution"]', namespaces=inkex.NSS ):
parent = node.getparent()
parent.remove( node )

# Remove any empty, default "Layer 1"
for node in self.document.xpath( '//svg:g[@id="layer1"]', namespaces=inkex.NSS ):
if not node.getchildren():
parent = node.getparent()
parent.remove( node )

# Start a new maze
self.solved = 0
self.start_x = random.randint( 0, self.w - 1 )
self.finish_x = random.randint( 0, self.w - 1 )

# Initialize every cell with all four walls up

for i in range( 0, maze_size ):
self.cells[i] = Maze._NORTH | Maze._EAST | Maze._SOUTH | Maze._WEST

# Now set our borders -- borders being walls which cannot be removed.
# Since we are a maze on the surface of a cylinder we only have two
# edges and hence only two borders. We consider our two edges to run
# from WEST to EAST and to be at the NORTH and SOUTH.

z = ( self.h - 1 ) * self.w
for x in range( 0, self.w ):
self.cells[x] |= Maze._NORTH << 4
self.cells[x + z] |= Maze._SOUTH << 4

# Build the maze
self.handle_cell( 0, self.start_x, self.start_y )

# Now that the maze has been built, remove the appropriate walls
# associated with the start and finish points of the maze

# Note: we have to remove these after building the maze. If we
# remove them first, then the lack of a border at the start (or
# finish) cell will allow the handle_cell() routine to wander
# outside of the maze. I.e., handle_cell() doesn't do boundary
# checking on the cell cell coordinates it generates. Instead, it
# relies upon the presence of borders to prevent it wandering
# outside the confines of the maze.

self.remove_border( self.start_x, self.start_y, Maze._NORTH )
self.remove_wall( self.start_x, self.start_y, Maze._NORTH )

self.remove_border( self.finish_x, self.finish_y, Maze._SOUTH )
self.remove_wall( self.finish_x, self.finish_y, Maze._SOUTH )

# Now draw the maze

# The following scaling and translations scale the maze's
# (width, height) to (TARGET_WIDTH, TARGET_HEIGHT), and translates
# the maze so that it centered within a document of dimensions
# (width, height) = (PLOT_WIDTH, PLOT_HEIGHT)

# Note that each cell in the maze is drawn 2 x units wide by
# 2 y units high. A width and height of 2 was chosen for
# convenience and for allowing easy identification (as the integer 1)
# of the centerline along which to draw solution paths. It is the
# abstract units which are then mapped to the TARGET_WIDTH eggbot x
# pixels by TARGET_HEIGHT eggbot y pixels rectangle.

scale_x = float( TARGET_WIDTH ) / float( 2 * self.w )
scale_y = float( TARGET_HEIGHT ) / float( 2 * self.h )
translate_x = float( PLOT_WIDTH - TARGET_WIDTH ) / 2.0
translate_y = float( PLOT_HEIGHT - TARGET_HEIGHT ) / 2.0

# And the SVG transform is thus
t = 'translate(%f,%f)' % ( translate_x, translate_y ) + \
' scale(%f,%f)' % ( scale_x, scale_y )

# For scaling line thicknesses. We'll typically draw a line of
# thickness 1 but will need to make the SVG path have a thickness
# of 1 / scale so that after our transforms are applied, the
# resulting thickness is the 1 we wanted in the first place.

if scale_x > scale_y:
self.scale = scale_x
else:
self.scale = scale_y

self.last_point = None
self.path = ''

if not self.hpp:

# To draw the walls, we start at the left-most column of cells, draw down drawing
# the WEST and NORTH walls and then draw up drawing the EAST and SOUTH walls.
# By drawing in this back and forth fashion, we minimize the effect of slippage.

for x in range( 0, self.w, 2 ):
self.draw_vertical( x )

else:

# The drawing style of the "high plotting precision" / "faster plotting" mode
# is such that it minimizes the number of pen up / pen down operations
# but at the expense of requiring higher drawing precision. It's style
# of drawing works best when there is very minimal slippage of the egg

# Draw the horizontal walls

self.draw_horizontal_hpp( 0, Maze._NORTH )
for y in range( 0, self.h - 1 ):
self.draw_horizontal_hpp( y, Maze._SOUTH )
self.draw_horizontal_hpp( self.h - 1, Maze._SOUTH )

# Draw the vertical walls

# Since this is a maze on the surface of a cylinder, we don't need
# to draw the vertical walls at the outer edges (x = 0 & x = w - 1)

for x in range( 0, self.w ):
self.draw_vertical_hpp( x, Maze._EAST )

# Maze in layer "1 - Maze"
attribs = {
inkex.addNS( 'label', 'inkscape' ) : '1 - Maze',
inkex.addNS( 'groupmode', 'inkscape' ) : 'layer',
'transform' : t }
maze_layer = inkex.etree.SubElement( self.document.getroot(), 'g', attribs )
draw_SVG_path( self.path, "#000000", float( 1 / self.scale ), maze_layer )

# Now draw the solution in red in layer "2 - Solution"

attribs = {
inkex.addNS( 'label', 'inkscape' ) : '2 - Solution',
inkex.addNS( 'groupmode', 'inkscape' ) : 'layer',
'transform' : t }
maze_layer = inkex.etree.SubElement( self.document.getroot(), 'g', attribs )

# Mark the starting cell

draw_SVG_rect( 0.25 + 2 * self.start_x, 0.25 + 2 * self.start_y,
1.5, 1.5, "#ff0000", 0, "#ff0000", maze_layer )

# And now generate the solution path itself

# To minimize the number of plotted paths (and hence pen up / pen
# down operations), we generate as few SVG paths as possible.
# However, for aesthetic reasons we stop the path and start a new
# one when it runs off the edge of the document. We could keep on
# drawing as the eggbot will handle that just fine. However, it
# doesn't look as good in Inkscape. So, we end the path and start
# a new one which is wrapped to the other edge of the document.

pts = []
end_path = False
i = 0
while i < self.solved:

x1 = self.solution_x[i]
y1 = self.solution_y[i]

i += 1
x2 = self.solution_x[i]
y2 = self.solution_y[i]

if math.fabs( x1 - x2 ) > 1:

# We wrapped horizontally...
if x1 > x2:
x2 = x1 + 1
else:
x2 = x1 - 1
end_path = True

if i == 1:
pts.extend( [ 'M', 2 * x1 + 1, 2 * y1 + 1 ] )
pts.extend( [ 'L', 2 * x2 + 1, 2 * y2 + 1 ] )

if not end_path:
continue

x2 = self.solution_x[i]
y2 = self.solution_y[i]
pts.extend( [ 'M', 2 * x2 + 1, 2 * y2 + 1 ] )
end_path = False

# Put the solution path into the drawing
draw_SVG_path( pts, '#ff0000', float( 8 / self.scale ), maze_layer )

# Now mark the ending cell
draw_SVG_rect( 0.25 + 2*self.finish_x, 0.25 + 2 * self.finish_y,
1.5, 1.5, "#ff0000", 0, "#ff0000", maze_layer )

# Restore the recursion limit
sys.setrecursionlimit( limit )

# Set some document properties
node = self.document.getroot()
node.set( 'width', '3200' )
node.set( 'height', '800' )

# The following end up being ignored by Inkscape....
node = self.getNamedView()
node.set( 'showborder', 'false' )
node.set( inkex.addNS( 'cx', u'inkscape' ), '1600' )
node.set( inkex.addNS( 'cy', u'inkscape' ), '500' )
node.set( inkex.addNS( 'showpageshadow', u'inkscape' ), 'false' )

# Mark the cell at (x, y) as "visited"
def visit( self, x, y ):
self.cells[y * self.w + x] |= Maze._VISITED

# Return a non-zero value if the cell at (x, y) has been visited
def is_visited( self, x, y ):
if self.cells[y * self.w + x] & Maze._VISITED:
return -1
else:
return 0

# Return a non-zero value if the cell at (x, y) has a wall
# in the direction d
def is_wall( self, x, y, d ):
if self.cells[y * self.w + x] & d:
return -1
else:
return 0

# Remove the wall in the direction d from the cell at (x, y)
def remove_wall( self, x, y, d ):
self.cells[y * self.w + x] &= ~d

# Return a non-zero value if the cell at (x, y) has a border wall
# in the direction d
def is_border( self, x, y, d ):
if self.cells[y * self.w + x] & ( d << 4 ):
return -1
else:
return 0

# Remove the border in the direction d from the cell at (x, y)
def remove_border( self, x, y, d ):
self.cells[y * self.w + x] &= ~( d << 4 )

# This is the DFS algorithm which builds the maze. We start at depth 0
# at the starting cell (self.start_x, self.start_y). We then walk to a
# randomly selected neighboring cell which has not yet been visited (i.e.,
# previously walked into). Each step of the walk is a recursive descent
# in depth. The solution to the maze comes about when we walk into the
# finish cell at (self.finish_x, self.finish_y).
#
# Each recursive descent finishes when the currently visited cell has no
# unvisited neighboring cells.
#
# Since we don't revisit previously visited cells, each cell is visited
# no more than once. As it turns out, each cell is visited, but that's a
# little harder to show. Net, net, each cell is visited exactly once.

def handle_cell( self, depth, x, y ):

# Mark the current cell as visited
self.visit( x, y )

# Save this cell's location in our solution trail / backtrace
if not self.solved:

self.solution_x[depth] = x
self.solution_y[depth] = y

if ( x == self.finish_x ) and ( y == self.finish_y ):
# Maze has been solved
self.solved = depth

# Shuffle the four compass directions: this is the primary source
# of "randomness" in the generated maze. We need to visit each
# neighboring cell which has not yet been visited. If we always
# did that in the same order, then our mazes would look very regular.
# So, we shuffle the list of directions we try in order to find an
# unvisited neighbor.

# HINT: TRY COMMENTING OUT THE shuffle() BELOW AND SEE FOR YOURSELF

directions = [Maze._NORTH, Maze._SOUTH, Maze._EAST, Maze._WEST]
random.shuffle( directions )

# Now from the cell at (x, y), look to each of the four
# directions for unvisited neighboring cells

for i in range( 0, 4 ):

# If there is a border in direction[i], then don't try
# looking for a neighboring cell in that direction. We
# Use this check and borders to prevent generating invalid
# cell coordinates.

if self.is_border( x, y, directions[i] ):
continue

# Determine the cell coordinates of a neighboring cell
# NOTE: we trust the use of maze borders to prevent us
# from generating invalid cell coordinates

if directions[i] == Maze._NORTH:
nx = x
ny = y - 1
opposite_direction = Maze._SOUTH

elif directions[i] == Maze._SOUTH:
nx = x
ny = y + 1
opposite_direction = Maze._NORTH

elif directions[i] == Maze._EAST:
nx = x + 1
ny = y
opposite_direction = Maze._WEST

else:
nx = x - 1
ny = y
opposite_direction = Maze._EAST

# Wrap in the horizontal dimension
if nx < 0:
nx += self.w
elif nx >= self.w:
nx -= self.w

# See if this neighboring cell has been visited
if self.is_visited( nx, ny ):
# Neighbor has been visited already
continue

# The neighboring cell has not been visited: remove the wall in
# the current cell leading to the neighbor. And, from the
# neighbor remove its wall leading to the current cell.

self.remove_wall( x, y, directions[i] )
self.remove_wall( nx, ny, opposite_direction )

# Now recur by "moving" to this unvisited neighboring cell

self.handle_cell( depth + 1, nx, ny )

def draw_line( self, x1, y1, x2, y2 ):

if self.last_point is not None:
if ( self.last_point[0] == x1 ) and ( self.last_point[1] == y1 ):
self.path += ' L %d,%d' % ( x2, y2 )
self.last_point = [ x2, y2 ]
elif ( self.last_point[0] == x2 ) and ( self.last_point[1] == y2 ):
self.path += ' L %d,%d L %d,%d' % ( x1, y1, x2, y2 )
# self.last_point unchanged
else:
self.path += ' M %d,%d L %d,%d' % ( x1, y1, x2, y2 )
self.last_point = [ x2, y2 ]
else:
self.path = 'M %d,%d L %d,%d' % ( x1, y1, x2, y2 )
self.last_point = [ x2, y2 ]

def draw_wall( self, x, y, d, dir ):

if dir > 0:
if d == Maze._NORTH:
self.draw_line( 2*(x+1), 2*y, 2*x, 2*y )
elif d == Maze._WEST:
self.draw_line( 2*x, 2*y, 2*x, 2*(y+1) )
elif d == Maze._SOUTH:
self.draw_line( 2*(x+1), 2*(y+1), 2*x, 2*(y+1) )
else: # Mase._EAST
self.draw_line( 2*(x+1), 2*y, 2*(x+1), 2*(y+1) )
else:
if d == Maze._NORTH:
self.draw_line( 2*x, 2*y, 2*(x+1), 2*y )
elif d == Maze._WEST:
self.draw_line( 2*x, 2*(y+1), 2*x, 2*y )
elif d == Maze._SOUTH:
self.draw_line( 2*x, 2*(y+1), 2*(x+1), 2*(y+1) )
else: # Maze._EAST
self.draw_line( 2*(x+1), 2*(y+1), 2*(x+1), 2*y )

# Draw the vertical walls of the maze along the column of cells at
# horizonal positions

def draw_vertical( self, x ):

# Drawing moving downwards from north to south

if self.is_wall( x, 0, Maze._NORTH ):
self.draw_wall( x, 0, Maze._NORTH, +1 )

for y in range( 0, self.h ):
if self.is_wall( x, y, Maze._WEST ):
self.draw_wall( x, y, Maze._WEST, +1 )
if self.is_wall( x, y, Maze._SOUTH ):
self.draw_wall( x, y, Maze._SOUTH, +1 )

# Now, return drawing upwards moving from south to north

x += 1
if x >= self.w:
return

for y in range( self.h - 1, -1, -1 ):
if self.is_wall( x, y, Maze._SOUTH ):
self.draw_wall( x, y, Maze._SOUTH, -1 )
if self.is_wall( x, y, Maze._WEST ):
self.draw_wall( x, y, Maze._WEST, -1 )
if self.is_wall( x, 0, Maze._NORTH ):
self.draw_wall( x, 0, Maze._NORTH, -1 )

# Draw the horizontal walls of the maze along the row of
# cells at "height" y: "high plotting precision" version

def draw_horizontal_hpp(self, y, wall ):

# Cater to Python 2.4 and earlier
# dy = 0 if wall == Maze._NORTH else 1
if wall == Maze._NORTH:
dy = 0
else:
dy = 1

tracing = False
for x in range( 0, self.w ):

if self.is_wall( x, y, wall ):
if not tracing:
# Starting a new segment
segment = x
tracing = True
else:
if tracing:
# Reached the end of a segment
self.draw_line( 2 * segment, 2 * (y + dy),
2 * x, 2 * (y + dy) )
tracing = False

if tracing:
# Draw the last wall segment
self.draw_line( 2 * segment, 2 * (y + dy),
2 * self.w, 2 * (y + dy) )


# Draw the vertical walls of the maze along the column of cells at
# horizonal position x: "high plotting precision" version

def draw_vertical_hpp(self, x, wall ):

# Cater to Python 2.4 and earlier
# dx = 0 if wall == Maze._WEST else 1
if wall == Maze._WEST:
dx = 0
else:
dx = 1

# We alternate the direction in which we draw each vertical wall.
# First, from North to South and then from South to North. This
# reduces pen travel on the Eggbot

if x % 2 == 0: # North-South
y_start, y_finis, dy, offset = 0, self.h, 1, 0
else: # South-North
y_start, y_finis, dy, offset = self.h - 1, -1, -1, 2

tracing = False
for y in range( y_start, y_finis, dy ):
assert 0 <= y and y < self.h, "y (%d) is out of range" % y
if self.is_wall( x, y, wall ):
if not tracing:
# Starting a new segment
segment = y
tracing = True
else:
if tracing:
# Hit the end of a segment
self.draw_line( 2 * ( x + dx ), 2 * segment + offset,
2 * ( x + dx ), 2 * y + offset )
tracing = False

if tracing:
# complete the last wall segment
self.draw_line( 2 * ( x + dx ), 2 * segment + offset,
2 * ( x + dx ), 2 * y_finis + offset )

if __name__ == '__main__':
e = Maze()
e.affect()


添付ファイル 添付ファイル


「Inkscape」と「SketchUp8」の仲介ソフト「Blender」

Inkscapeに取り込んだ画像をSketchUpに渡すまでの動画。



※添付動画はデータ変換工程
添付ファイル 添付ファイル


「Blender2.79」 扉を別角度に配置する際の備忘録

動きを設定した扉を別角度にコピー配置した際、想像した振る舞いにならなかったので対処法の備忘録(あくまで個人的な手法)

振る舞いをテストするための扉サイズは適当。
手順は動画通りなので説明は省略。 「Ctrl」+「A」キーで再生

添付ファイル 添付ファイル


「Blender2.79」 Ic-SD inagaki architect様 三重塔(再掲)

コケていたメールが復活!

前に、ゲームエンジンのテスト用して使わせて頂いた制作途中の三重塔。
実は12月の暮れに、 Ic-SD inagaki architec様から完成データのリンクを頂いていた事がわかった。

その後テクスチャ付きの「SketchUp」データが無事読めるようになった事もあり、遅ればせながらノーマルの状態でレンダリングして再掲させて頂く事にした。

読み込み直後をレンダリング


背景黒のまま焦点距離18で全景


背景白で全景


焦点距離35でズーム


下手に照明や影を設定してない(できない!)せいか、アプリ内で見る拡大モデルはリアルで圧巻!

Ic-SD inagaki architec様、お礼が遅くなりましたが、
ありがとうございました。


「Blender2.79」 折戸 2

折戸失敗作を放置したままだったので整理。

「開始」ボタンか、「P」キーでプレイ開始。

「E]キーで折戸開閉。(ピンポン動作。 開き終わったら再び「E」キーで閉じる)
扉動作中の「E」キー操作は挙動が変化する。



動作はシンプルなアニメーション(60フレーム)を「E」キーで呼び出しているだけ。(扉同士の親子関係あり)

マテリアルの設定は平面の色つけ以外なし。
添付ファイル 添付ファイル


「Coffee Break」 Unityの「NavMesh」を思い出した。

すっかり忘れてしまったが、Unityの「NavMesh」に似ている?




「Blender」 スカイシェーダーを覗いてみる

前出のスカイシェーダーについて少し内容を覗いてみた。
ゲームデザイナー兼、開発者である Simon Wallner 氏により制作され、YouTube投稿者によって「Blender」に実装されたもの。

日没までの空の自然現象をシミュレートできる内容だが、それなりの期間をかけて築き上げた複雑な構成を理解し、"活用する" に至るまでには相応の時間も要する。 まぁ、半年満たない経験では語る(騙る?)以前の問題。

マウスの左ドラッグ(上下させる)で日没までをリアルにシミュレートできる。(左右で移動、他、W、A、S、Dでカメラ移動だが太陽を浴びる被写体が無いので意味も無い)

「Z」キーを押し続ける事で太陽が軌道に沿って上昇する。


※添付したBlenderファイルは、「Skyシェーダー」だけを抜粋したもの。
添付ファイル 添付ファイル


「Coffee Break」 YouTube動画をブックマーク!

こんな空がほしくなりブックマーク。



陸(グランド?)は距離に応じてスケーリングされているので難しそうだ。


「Blender2.79」 3分30秒の備忘録:Stainless

金属の質感(Stainlessのつもり)を忘れないための備忘録。

操作記録した動画は編集なしのそのまま。 
レンダリング完了までの全作業時間は3分30秒未満(毎回気分によるムラがある!)


「レンダー」ボタンか「F12」でレンダリング。

わずかに角処理を施す事でよりリアル感が増すため他にならってやってみた。
添付ファイル 添付ファイル


「Coffee Break」 SU8の巨大データが読めた!

SketchUp8のデータでお借りしている、Ic-SD inagaki architect様の50Mを超える広大な「六条院」モデル。

インポートに多少の時間は要するが(自分のPCで数分はかかる)、その間コーヒータイム。
一度読み込んだデータを「Blender」の標準データで再保存すると次回から10秒程度に短縮できる。

一度画面に取り込んだデータは負担なく軽快に動く。


木階や御簾などの一部に施してある「テクスチャ」もそのまま再現されているのが確認できた。


【レンダリング前の設定】
■ノーマルの状態では背景が黒になるので空色に変更。
■モデルが広大で、カメラがノーマルのままでは全景を収める事ができず、「クリッピング(被写界深度)」を500に変更(赤枠部分)。


※インポート時、取り込み後に不要となる"カメラ"や"シーン"は最初でオプションから外した。
焦点距離の「25」は、より自然に見えると書かれているマニュアルの推薦値。

これで「Unity」より楽に作業できそうな気がする。


「Blender」 PBR Material プラグイン

フリーのマテリアルプラグイン。 これはよさそう。

https://3d-wolf.com/products/materials.html





「Blender2.79」 時計のマテリアル設定(後編)

前出の動画による説明(グダグダだが、面倒なので編集、修正ナシで)


■文字盤(緑)の面を選択する際は編集モードの面選択で「C」キーを押して円形選択に切り替え、センターホイルで円サイズを調整して選択する。
取りこぼした面は「Shift」キーを押しながら面を追加で選択する

■フレームのリング(ピンク)選択は編集モードの面選択で、「Shift」+「Alt」キーを押しながらエッジをクリックし、リング状に選択していく(選択するポイントは動画参照)


インターネットの速度が遅い方のために「mp4」を zip ファイルで添付。
添付ファイル 添付ファイル


「Blender2.79」 時計のマテリアル設定(前編)

"プロ"の方は笑いのネタにしかならないのでご遠慮を!

記事の最後にBlenderの「練習用データ(全マテリアル未設定)」と「完成データ」を添付。
完成データは「レンダリングボタン」か、「F12」でレンダリング開始。

設定作業自体は短時間で終わるので、練習用データで是非トライしてほしい。


金属などの反射素材は、空や樹木などの映り込む環境が無いと効果を出すことが困難だが、ワールドのチェック柄とアンビエントで代用。

【設定に関する全項目(赤枠部分)】

ステンレスフレームや、長針、短針、軸、ロゴ、文字などの設定


文字盤の色と反射の設定


時計のフレームにアクセントでつけたリング色と反射の設定


アルミバントの取り付け金具の設定


カメラ焦点距離の設定(25はマニュアルによる推薦値だが、好きに)


ワールドの設定


ワールドのテクスチャ設定


ランプの設定



全設定の様子は後編で動画制作予定。
添付ファイル 添付ファイル


「Blender2.79」 整理するとたったの10分程度で済む作業内容だった!

前の記事で「ヘトヘト」+「クタクタ」などの泣き言を撤回!
これは英語のマニュアルが読めない自分の責任。

結局のところ整理すると10分もあれば済んでしまう内容だった。

モデリング中のマテリアル未設定の状態(既出)


適当に着色し、レンダリング終了までわずか10分。(気分で多少前後する)


先週の自分が今のレンダリング結果を見るとまだ先の事に思えたかもしれない。

すべてマニュアル書かれている内容だが、忘れないよう動画備忘録を作成する予定。(もちろん間違い勘違いを恐れずBlenderのデータごとここにアップ!)


< next prev >