Exemple #1
0
class RotationAxis(VisibleObject):
    default_shown = False
    ignore_light = True

    def __init__(self, body):
        VisibleObject.__init__(self, body.get_ascii_name() + '-axis')
        self.body = body

    def create_instance(self):
        self.vertexData = GeomVertexData('vertexData',
                                         GeomVertexFormat.getV3(),
                                         Geom.UHStatic)
        self.vertexWriter = GeomVertexWriter(self.vertexData, 'vertex')
        radius = 1.0
        top = LPoint3d(0, 0, radius * 1.25)
        north_pole = LPoint3d(0, 0, radius)
        south_pole = LPoint3d(0, 0, -radius)
        bottom = LPoint3d(0, 0, -radius * 1.25)
        self.vertexWriter.addData3f(*top)
        self.vertexWriter.addData3f(*north_pole)
        self.vertexWriter.addData3f(*south_pole)
        self.vertexWriter.addData3f(*bottom)
        self.lines = GeomLines(Geom.UHStatic)
        self.lines.addVertex(0)
        self.lines.addVertex(1)
        self.lines.addVertex(2)
        self.lines.addVertex(3)
        self.lines.closePrimitive()
        self.geom = Geom(self.vertexData)
        self.geom.addPrimitive(self.lines)
        self.node = GeomNode(self.body.get_ascii_name() + '-axis')
        self.node.addGeom(self.geom)
        self.instance = NodePath(self.node)
        self.instance.setRenderModeThickness(settings.axis_thickness)
        self.instance.setColor(self.parent.get_orbit_color())
        self.instance.setAntialias(AntialiasAttrib.MMultisample)
        self.instance.reparentTo(self.context.annotation)

    def check_settings(self):
        self.set_shown(settings.show_rotation_axis)

    def check_visibility(self, pixel_size):
        if self.parent.shown:
            distance_to_obs = self.parent.distance_to_obs
            if distance_to_obs > 0.0:
                size = self.parent.get_apparent_radius() / (distance_to_obs *
                                                            pixel_size)
            else:
                size = 0.0
            self.visible = size > settings.axis_fade
        else:
            self.visible = False

    def update_instance(self, camera_pos, orientation):
        if self.instance:
            self.place_instance(self.instance, self.parent)

    def get_scale(self):
        return self.body.get_scale()
Exemple #2
0
class Boundary(VisibleObject):
    ignore_light = True
    default_shown = True

    def __init__(self, name, points=[], color=None):
        VisibleObject.__init__(self, name)
        self.visible = True
        if color is None:
            color = bodyClasses.get_orbit_color('boundary')
        self.color = color
        self.points = points

    def check_settings(self):
        self.set_shown(settings.show_boundaries)

    def set_points_list(self, points):
        self.points = points

    def create_instance(self):
        self.vertexData = GeomVertexData('vertexData',
                                         GeomVertexFormat.getV3c4(),
                                         Geom.UHStatic)
        self.vertexWriter = GeomVertexWriter(self.vertexData, 'vertex')
        self.colorwriter = GeomVertexWriter(self.vertexData, 'color')
        for point in self.points:
            position = point.project(0,
                                     self.context.observer.camera_global_pos,
                                     self.context.observer.infinity)
            self.vertexWriter.addData3f(*position)
            self.colorwriter.addData4f(*self.color)
        self.lines = GeomLines(Geom.UHStatic)
        index = 0
        for i in range(len(self.points) - 1):
            self.lines.addVertex(index)
            self.lines.addVertex(index + 1)
            self.lines.closePrimitive()
            index += 1
        self.geom = Geom(self.vertexData)
        self.geom.addPrimitive(self.lines)
        self.node = GeomNode("boundary")
        self.node.addGeom(self.geom)
        self.instance = NodePath(self.node)
        self.instance.setRenderModeThickness(settings.boundary_thickness)
        self.instance.reparentTo(self.context.annotation)
        self.instance.setBin('background', settings.boundaries_depth)
        self.instance.set_depth_write(False)
Exemple #3
0
class Orbit(VisibleObject):
    ignore_light = True
    default_shown = False
    selected_color = LColor(1.0, 0.0, 0.0, 1.0)

    def __init__(self, body):
        VisibleObject.__init__(self, body.get_ascii_name() + '-orbit')
        self.body = body
        self.nbOfPoints = 360
        self.orbit = self.find_orbit(self.body)
        self.color = None
        self.fade = 0.0
        if not self.orbit:
            print("No orbit for", self.get_name())
            self.visible = False
        self.check_settings()

    def check_settings(self):
        if self.body.body_class is None:
            print("No class for", self.body.get_name())
            return
        self.set_shown(settings.show_orbits
                       and bodyClasses.get_show_orbit(self.body.body_class))

    def find_orbit(self, body):
        if body != None:
            if not isinstance(body.orbit, FixedOrbit):
                return body.orbit
            else:
                return None, None
        else:
            return None, None

    def set_selected(self, selected):
        if selected:
            self.color = self.selected_color
        else:
            self.color = self.parent.get_orbit_color()
        if self.instance:
            self.instance.setColor(self.color * self.fade)

    def create_instance(self):
        if not self.orbit:
            return
        self.vertexData = GeomVertexData('vertexData',
                                         GeomVertexFormat.getV3(),
                                         Geom.UHStatic)
        self.vertexWriter = GeomVertexWriter(self.vertexData, 'vertex')
        delta = self.body.parent.get_local_position()
        for i in range(self.nbOfPoints):
            time = self.orbit.period / self.nbOfPoints * i
            pos = self.orbit.get_position_at(time)
            rot = self.orbit.get_rotation_at(time)
            pos = self.orbit.frame.get_local_position(rot.xform(pos)) - delta
            self.vertexWriter.addData3f(*pos)
        self.lines = GeomLines(Geom.UHStatic)
        for i in range(self.nbOfPoints - 1):
            self.lines.addVertex(i)
            self.lines.addVertex(i + 1)
            self.lines.closePrimitive()
        self.lines.addVertex(self.nbOfPoints - 1)
        self.lines.addVertex(0)
        self.lines.closePrimitive()
        self.geom = Geom(self.vertexData)
        self.geom.addPrimitive(self.lines)
        self.node = GeomNode(self.body.get_ascii_name() + '-orbit')
        self.node.addGeom(self.geom)
        self.instance = NodePath(self.node)
        self.instance.setRenderModeThickness(settings.orbit_thickness)
        self.instance.setCollideMask(GeomNode.getDefaultCollideMask())
        self.instance.node().setPythonTag('owner', self)
        self.instance.reparentTo(self.context.annotation_shader)
        if self.color is None:
            self.color = self.parent.get_orbit_color()
        self.instance.setColor(self.color * self.fade)
        self.instance.setAntialias(AntialiasAttrib.MMultisample)
        self.appearance = ModelAppearance(attribute_color=True)
        if settings.use_inv_scaling:
            vertex_control = LargeObjectVertexControl()
        else:
            vertex_control = None
        self.instance_ready = True
        self.shader = BasicShader(lighting_model=FlatLightingModel(),
                                  vertex_control=vertex_control)
        self.shader.apply(self, self.appearance)
        self.shader.update(self, self.appearance)

    def check_visibility(self, pixel_size):
        if self.parent.shown and self.orbit:
            distance_to_obs = self.parent.distance_to_obs
            if distance_to_obs > 0.0:
                size = self.orbit.get_apparent_radius() / (distance_to_obs *
                                                           pixel_size)
            else:
                size = 0.0
            self.visible = size > settings.orbit_fade
            self.fade = min(
                1.0,
                max(0.0, (size - settings.orbit_fade) / settings.orbit_fade))
            if self.color is not None and self.instance is not None:
                self.instance.setColor(self.color * self.fade)
        else:
            self.visible = False

    def update_instance(self, camera_pos, orientation):
        if self.instance:
            self.place_instance_params(self.instance,
                                       self.body.parent.scene_position,
                                       self.body.parent.scene_scale_factor,
                                       LQuaternion())
            self.shader.update(self, self.appearance)
Exemple #4
0
class Asterism(VisibleObject):
    def __init__(self, name):
        VisibleObject.__init__(self, name)
        self.visible = True
        self.color = bodyClasses.get_orbit_color('constellation')
        self.position = LPoint3d(0, 0, 0)
        self.segments = []
        self.position = None

    def check_settings(self):
        self.set_shown(settings.show_asterisms)

    def set_segments_list(self, segments):
        self.segments = segments
        ra_sin = 0
        ra_cos = 0
        decl = 0
        if len(self.segments) > 0 and len(self.segments[0]) > 0:
            for star in self.segments[0]:
                asc = star.orbit.get_right_asc()
                ra_sin += sin(asc)
                ra_cos += cos(asc)
                decl += star.orbit.get_declination()
            ra = atan2(ra_sin, ra_cos)
            decl /= len(self.segments[0])
            self.position = InfinitePosition(right_asc=ra,
                                             right_asc_unit=units.Rad,
                                             declination=decl,
                                             declination_unit=units.Rad)

    def create_instance(self):
        self.vertexData = GeomVertexData('vertexData',
                                         GeomVertexFormat.getV3c4(),
                                         Geom.UHStatic)
        self.vertexWriter = GeomVertexWriter(self.vertexData, 'vertex')
        self.colorwriter = GeomVertexWriter(self.vertexData, 'color')
        #TODO: Ugly hack to calculate star position from the sun...
        old_cam_pos = self.context.observer.camera_global_pos
        self.context.observer.camera_global_pos = LPoint3d()
        center = LPoint3d()
        for segment in self.segments:
            if len(segment) < 2: continue
            for star in segment:
                #TODO: Temporary workaround to have star pos
                star.update(0)
                star.update_obs(self.context.observer)
                position, distance, scale_factor = self.get_real_pos_rel(
                    star.rel_position, star.distance_to_obs,
                    star.vector_to_obs)
                self.vertexWriter.addData3f(*position)
                self.colorwriter.addData4f(*self.color)
        self.context.observer.camera_global_pos = old_cam_pos
        self.lines = GeomLines(Geom.UHStatic)
        index = 0
        for segment in self.segments:
            if len(segment) < 2: continue
            for i in range(len(segment) - 1):
                self.lines.addVertex(index)
                self.lines.addVertex(index + 1)
                self.lines.closePrimitive()
                index += 1
            index += 1
        self.geom = Geom(self.vertexData)
        self.geom.addPrimitive(self.lines)
        self.node = GeomNode("asterism")
        self.node.addGeom(self.geom)
        self.instance = NodePath(self.node)
        self.instance.setRenderModeThickness(settings.asterism_thickness)
        self.instance.reparentTo(self.context.annotation)
        self.instance.setBin('background', settings.asterisms_depth)
        self.instance.set_depth_write(False)
Exemple #5
0
class Grid(VisibleObject):
    ignore_light = True
    default_shown = False

    def __init__(self, name, orientation, color):
        VisibleObject.__init__(self, name)
        self.visible = True
        self.nbOfPoints = 360
        self.nbOfRings = 17
        self.nbOfSectors = 24
        self.points_to_remove = (self.nbOfPoints // (self.nbOfRings + 1)) // 2
        self.orientation = orientation
        self.color = color

    def create_instance(self):
        self.vertexData = GeomVertexData('vertexData',
                                         GeomVertexFormat.getV3c4(),
                                         Geom.UHStatic)
        self.vertexWriter = GeomVertexWriter(self.vertexData, 'vertex')
        self.colorwriter = GeomVertexWriter(self.vertexData, 'color')
        for r in range(1, self.nbOfRings + 1):
            for i in range(self.nbOfPoints):
                angle = 2 * pi / self.nbOfPoints * i
                x = cos(angle) * sin(pi * r / (self.nbOfRings + 1))
                y = sin(angle) * sin(pi * r / (self.nbOfRings + 1))
                z = sin(-pi / 2 + pi * r / (self.nbOfRings + 1))

                self.vertexWriter.addData3f(
                    (self.context.observer.infinity * x,
                     self.context.observer.infinity * y,
                     self.context.observer.infinity * z))
                if r == self.nbOfRings / 2 + 1:
                    self.colorwriter.addData4f(self.color.x * 1.5, 0, 0, 1)
                else:
                    self.colorwriter.addData4f(*self.color)
        for s in range(self.nbOfSectors):
            for i in range(self.points_to_remove,
                           self.nbOfPoints // 2 - self.points_to_remove + 1):
                angle = 2 * pi / self.nbOfPoints * i
                x = cos(2 * pi * s / self.nbOfSectors) * sin(angle)
                y = sin(2 * pi * s / self.nbOfSectors) * sin(angle)
                z = cos(angle)

                self.vertexWriter.addData3f(
                    (self.context.observer.infinity * x,
                     self.context.observer.infinity * y,
                     self.context.observer.infinity * z))
                if s == 0:
                    self.colorwriter.addData4f(self.color.x * 1.5, 0, 0, 1)
                else:
                    self.colorwriter.addData4f(*self.color)
        self.lines = GeomLines(Geom.UHStatic)
        index = 0
        for r in range(self.nbOfRings):
            for i in range(self.nbOfPoints - 1):
                self.lines.addVertex(index)
                self.lines.addVertex(index + 1)
                self.lines.closePrimitive()
                index += 1
            self.lines.addVertex(index)
            self.lines.addVertex(index - self.nbOfPoints + 1)
            self.lines.closePrimitive()
            index += 1
        for r in range(self.nbOfSectors):
            for i in range(self.nbOfPoints // 2 - self.points_to_remove * 2):
                self.lines.addVertex(index)
                self.lines.addVertex(index + 1)
                self.lines.closePrimitive()
                index += 1
            index += 1
        self.geom = Geom(self.vertexData)
        self.geom.addPrimitive(self.lines)
        self.node = GeomNode("grid")
        self.node.addGeom(self.geom)
        self.instance = NodePath(self.node)
        self.instance.setRenderModeThickness(settings.grid_thickness)
        #myMaterial = Material()
        #myMaterial.setEmission((1.0, 1.0, 1.0, 1))
        #self.instance.setMaterial(myMaterial)
        self.instance.reparentTo(self.context.annotation)
        self.instance.setQuat(LQuaternion(*self.orientation))

    def set_orientation(self, orientation):
        self.orientation = orientation
        if self.instance:
            self.instance.setQuat(LQuaternion(*self.orientation))
class Planetimpl():
    def __init__(self, world, size, distance, ratio, description, rotation, translation):
        self.worldOrigin = world
        self.size = size
        self.distance = distance
        self.renderRatio = ratio
        self.description = description
        self.rotation = rotation
        self.translation = translation

    def impl(self):
        # Load the Moon model
        self.planet = loader.loadModel("models/planet_sphere")
        self.chooseTexture("models/"+self.description+"_1k_tex.jpg")
        self.planet.reparentTo(self.worldOrigin)
        self.planet.setScale(self.size * self.renderRatio)
        self.planet.setPos(self.distance * self.renderRatio, 0.0, 0.0)
        self.planet.setTag('targetSize', str(self.size))
        self.planet.setTag('isPickable', '2')
        self.startstop = True
        return self.planet

    def chooseTexture(self, name):
        """
        Methode zum Setzen der Ursprungstextur
        """
        self.planet.setTexture(loader.loadTexture(name), 1)

    def line(self):
        # Create and populate the Moon orbit model using Vertices and Lines
        self.planetOrbitVertexData = GeomVertexData(self.description+'OrbitVertexData', GeomVertexFormat.getV3(), Geom.UHDynamic)
        self.planetOrbitVertexWriter = GeomVertexWriter(self.planetOrbitVertexData, 'vertex')
        self.planetOrbitNumberPoints = 360
        for i in range(self.planetOrbitNumberPoints):
            angleDegrees = i * 360 / self.planetOrbitNumberPoints
            angleRadians = angleDegrees * (pi / 180.0)
            x = -self.distance * sin(angleRadians)
            y =  self.distance * cos(angleRadians)
            self.planetOrbitVertexWriter.addData3f(x, y, 0.0)
        self.planetOrbitLines = GeomLines(Geom.UHStatic)
        for i in range(self.planetOrbitNumberPoints-1):
            self.planetOrbitLines.addVertex(i)
            self.planetOrbitLines.addVertex(i+1)
            self.planetOrbitLines.closePrimitive()
            self.planetOrbitLines.addVertex(self.planetOrbitNumberPoints-1)
            self.planetOrbitLines.addVertex(0)
        self.planetOrbitLines.closePrimitive()
        self.planetOrbitGeom = Geom(self.planetOrbitVertexData)
        self.planetOrbitGeom.addPrimitive(self.planetOrbitLines)
        self.planetOrbitNode = GeomNode(self.description+'OrbitNode')
        self.planetOrbitNode.addGeom(self.planetOrbitGeom)
        self.planetOrbitNnodePath = render.attachNewNode(self.planetOrbitNode)
        self.planetOrbitNnodePath.reparentTo(self.worldOrigin)
        return self.planetOrbitVertexWriter

    def setstartstop(self):
        self.startstop = not self.startstop
        return self.startstop

    def rotatePlanet(self, task):
        # Compute earth rotation
        frameTime = globalClock.getFrameTime()
        angleDegrees = frameTime *  self.rotation
        self.planet.setHpr(angleDegrees, 0, 0)
        # End task
        if self.startstop:
            return Task.cont
        else:
            return Task.done



    def translatePlanet(self, task):
        # Compute Moon position relative to Earth with circular orbit
        frameTime = globalClock.getFrameTime()
        angleDegrees = frameTime *  self.translation
        angleRadians = angleDegrees * (pi / 180.0)

        # Compute the Moon's position with respect to the Earth
        x = -self.distance * self.renderRatio * sin(angleRadians)
        y =  self.distance * self.renderRatio * cos(angleRadians)

        # Set the position on the model
        self.planet.setPos(x, y, 0.0)

        # Also rotate the orbit to follow the Moon and eliminate jitter effect
        self.planetOrbitVertexWriter.setRow(0)
        for i in range(self.planetOrbitNumberPoints):
            angleDegrees = angleDegrees + 360.0 / self.planetOrbitNumberPoints
            angleRadians = angleDegrees * (pi / 180.0)
            x = -self.distance * self.renderRatio * sin(angleRadians)
            y =  self.distance * self.renderRatio * cos(angleRadians)
            self.planetOrbitVertexWriter.setData3f(x, y, 0.0)

        # End task
        if self.startstop:
            return Task.cont
        else:
            return Task.done
Exemple #7
0
class Orbit(VisibleObject):
    ignore_light = True
    default_shown = False
    selected_color = LColor(1.0, 0.0, 0.0, 1.0)
    appearance = None
    shader = None

    def __init__(self, body):
        VisibleObject.__init__(self, body.get_ascii_name() + '-orbit')
        self.body = body
        self.owner = body
        self.nbOfPoints = 360
        self.orbit = self.find_orbit(self.body)
        self.color = None
        self.fade = 0.0
        if not self.orbit:
            print("No orbit for", self.get_name())
            self.visible = False

    def get_oid_color(self):
        if self.body is not None:
            return self.body.oid_color
        else:
            return LColor()

    @classmethod
    def create_shader(cls):
        cls.appearance = ModelAppearance(attribute_color=True)
        if settings.use_inv_scaling:
            vertex_control = LargeObjectVertexControl()
        else:
            vertex_control = None
        cls.shader = BasicShader(lighting_model=FlatLightingModel(), vertex_control=vertex_control)

    def check_settings(self):
        if self.body.body_class is None:
            print("No class for", self.body.get_name())
            return
        self.set_shown(settings.show_orbits and bodyClasses.get_show_orbit(self.body.body_class))

    def find_orbit(self, body):
        if body != None:
            if not isinstance(body.orbit, FixedOrbit):
                return body.orbit
            else:
                return None, None
        else:
            return None, None

    def set_selected(self, selected):
        if selected:
            self.color = self.selected_color
        else:
            self.color = self.parent.get_orbit_color()
        if self.instance:
            self.instance.setColor(srgb_to_linear(self.color * self.fade))

    def create_instance(self):
        self.vertexData = GeomVertexData('vertexData', GeomVertexFormat.getV3(), Geom.UHStatic)
        self.vertexWriter = GeomVertexWriter(self.vertexData, 'vertex')
        delta = self.body.parent.get_local_position()
        if self.orbit.is_periodic():
            epoch = self.context.time.time_full - self.orbit.period / 2
            step = self.orbit.period / (self.nbOfPoints - 1)
        else:
            #TODO: Properly calculate orbit start and end time
            epoch = self.orbit.get_time_of_perihelion() - self.orbit.period * 5.0
            step = self.orbit.period * 10.0 / (self.nbOfPoints - 1)
        for i in range(self.nbOfPoints):
            time = epoch + step * i
            pos = self.orbit.get_position_at(time) - delta
            self.vertexWriter.addData3f(*pos)
        self.lines = GeomLines(Geom.UHStatic)
        for i in range(self.nbOfPoints-1):
            self.lines.addVertex(i)
            self.lines.addVertex(i+1)
        if self.orbit.is_periodic() and self.orbit.is_closed():
            self.lines.addVertex(self.nbOfPoints-1)
            self.lines.addVertex(0)
        self.geom = Geom(self.vertexData)
        self.geom.addPrimitive(self.lines)
        self.node = GeomNode(self.body.get_ascii_name() + '-orbit')
        self.node.addGeom(self.geom)
        self.instance = NodePath(self.node)
        self.instance.setRenderModeThickness(settings.orbit_thickness)
        self.instance.setCollideMask(GeomNode.getDefaultCollideMask())
        self.instance.node().setPythonTag('owner', self)
        self.instance.reparentTo(self.context.annotation)
        if self.color is None:
            self.color = self.parent.get_orbit_color()
        self.instance.setColor(srgb_to_linear(self.color * self.fade))
        self.instance_ready = True
        if self.shader is None:
            self.create_shader()
        self.shader.apply(self, self.appearance)
        self.shader.update(self, self.appearance)

    def update_geom(self):
        geom = self.node.modify_geom(0)
        vdata = geom.modify_vertex_data()
        vwriter = GeomVertexRewriter(vdata, InternalName.get_vertex())
        #TODO: refactor with above code !!!
        delta = self.body.parent.get_local_position()
        if self.orbit.is_periodic():
            epoch = self.context.time.time_full - self.orbit.period
            step = self.orbit.period / (self.nbOfPoints - 1)
        else:
            #TODO: Properly calculate orbit start and end time
            epoch = self.orbit.get_time_of_perihelion() - self.orbit.period * 5.0
            step = self.orbit.period * 10.0 / (self.nbOfPoints - 1)
        for i in range(self.nbOfPoints):
            time = epoch + step * i
            pos = self.orbit.get_position_at(time) - delta
            vwriter.setData3f(*pos)

    def check_visibility(self, pixel_size):
        if self.parent.parent.visible and self.parent.shown and self.orbit:
            distance_to_obs = self.parent.distance_to_obs
            if distance_to_obs > 0.0:
                size = self.orbit.get_apparent_radius() / (distance_to_obs * pixel_size)
            else:
                size = 0.0
            self.visible = size > settings.orbit_fade
            self.fade = min(1.0, max(0.0, (size - settings.orbit_fade) / settings.orbit_fade))
            if self.color is not None and self.instance is not None:
                self.instance.setColor(srgb_to_linear(self.color * self.fade))
        else:
            self.visible = False

    def update_instance(self, camera_pos, camera_rot):
        if self.instance:
            self.place_instance_params(self.instance,
                                       self.body.parent.scene_position,
                                       self.body.parent.scene_scale_factor,
                                       LQuaternion())
            self.shader.update(self, self.appearance)

    def update_user_parameters(self):
        if self.instance is not None:
            self.update_geom()
Exemple #8
0
    def _build_grid(self):
        color = getattr(self.parameters, "color", (0, 0, 0, 0))

        node = NodePath(self.identifier)
        sx = self.grid.maxx - self.grid.minx + 1
        sy = self.grid.maxy - self.grid.miny + 1

        # 1. the squares
        squares = {}
        card = CardMaker('')
        cardgeom = NodePath(card.generate())
        for n in range(sx):
            for nn in range(sy):
                square = NodePath(self.identifier + '-square-%d-%d' %
                                  (n + 1, nn + 1))
                cardgeom.instanceTo(square)
                square.setPos(float(n) / sx, 0, -float(nn + 1) / sy)
                square.setScale(1.0 / sx, 1, 1.0 / sy)
                square.setColor(0, 0, 0, 1)
                square.reparentTo(node)
                squares[n, nn] = square

                #2: the lines
        gnode = GeomNode(self.identifier + "-lines")
        vformat = GeomVertexFormat.getV3cp()
        vdata = GeomVertexData(self.identifier + '-lines', vformat,
                               Geom.UHStatic)
        v_vertex = GeomVertexWriter(vdata, 'vertex')
        v_colors = GeomVertexWriter(vdata, 'color')

        for n in range(sx + 1):
            px = float(n) / sx
            v_vertex.addData3f(px, 0.0, 0.0)
            v_colors.addData4f(*color)
            v_vertex.addData3f(px, 0, -1)
            v_colors.addData4f(*color)
        for n in range(sy + 1):
            py = float(n) / sy
            v_vertex.addData3f(0.0, 0.0, -py)
            v_colors.addData4f(*color)
            v_vertex.addData3f(1.0, 0, -py)
            v_colors.addData4f(*color)

        geom = Geom(vdata)
        prim = GeomLines(Geom.UHStatic)
        for n in range(sx + 1):
            prim.addVertex(2 * n)
            prim.addVertex(2 * n + 1)
        for n in range(sy + 1):
            prim.addVertex(2 * (sx + n + 1))
            prim.addVertex(2 * (sx + n + 1) + 1)

        prim.closePrimitive()
        geom.addPrimitive(prim)

        gnode.addGeom(geom)
        node1 = NodePath(gnode)
        node1.reparentTo(node)

        self.node, self.squares, self.sx, self.sy = node, squares, sx, sy
        self.node.reparentTo(self.parentnode)